From 4d8a2a20e18d673f066b018d2925893265e31047 Mon Sep 17 00:00:00 2001 From: sindoring Date: Thu, 16 Apr 2026 17:51:58 +0400 Subject: [PATCH] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=D1=8B=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=D0=B0=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B5=D0=B4=D0=B0=D1=82=D0=B5=D0=BB=D1=8C:=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=B3=D0=BB=D0=B0=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2?= =?UTF-8?q?=20=D0=B3=D0=B8=D0=BB=D1=8C=D0=B4=D0=B8=D1=8E=20=D0=B8=20=D0=B3?= =?UTF-8?q?=D1=80=D1=83=D0=BF=D0=BF=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mod-playerbots/src/Bot/PlayerbotAI.cpp | 5 +- src/server/game/Cache/CharacterCache.cpp | 48 ++++++++++++++++--- src/server/game/Cache/CharacterCache.h | 6 ++- src/server/game/Guilds/Guild.cpp | 2 +- src/server/game/Handlers/CharacterHandler.cpp | 3 +- src/server/scripts/Commands/cs_cache.cpp | 6 ++- 6 files changed, 56 insertions(+), 14 deletions(-) diff --git a/modules/mod-playerbots/src/Bot/PlayerbotAI.cpp b/modules/mod-playerbots/src/Bot/PlayerbotAI.cpp index b6afb1c..6c5675e 100644 --- a/modules/mod-playerbots/src/Bot/PlayerbotAI.cpp +++ b/modules/mod-playerbots/src/Bot/PlayerbotAI.cpp @@ -4772,7 +4772,10 @@ uint32 PlayerbotAI::AutoScaleActivity(uint32 mod) return static_cast(mod * (1 - lagProgress)); } -bool PlayerbotAI::IsOpposing(Player* player) { return IsOpposing(player->getRace(), bot->getRace()); } +bool PlayerbotAI::IsOpposing(Player* player) +{ + return player && bot && player->GetTeamId() != bot->GetTeamId(); +} bool PlayerbotAI::IsOpposing(uint8 race1, uint8 race2) { diff --git a/src/server/game/Cache/CharacterCache.cpp b/src/server/game/Cache/CharacterCache.cpp index f940173..c671a49 100644 --- a/src/server/game/Cache/CharacterCache.cpp +++ b/src/server/game/Cache/CharacterCache.cpp @@ -28,6 +28,16 @@ namespace { std::unordered_map _characterCacheStore; std::unordered_map _characterCacheByNameStore; + + TeamId GetEffectiveCharacterTeam(uint8 race, uint32 playerFlags, uint8 gameMode) + { + TeamId teamId = Player::TeamIdForRace(race); + + if (Player::ResolveGameModeFromStorage(playerFlags, gameMode) == PLAYER_GAMEMODE_TRAITOR) + return teamId == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE; + + return teamId; + } } CharacterCache* CharacterCache::instance() @@ -62,7 +72,11 @@ void CharacterCache::LoadCharacterCacheStorage() _characterCacheStore.clear(); uint32 oldMSTime = getMSTime(); - QueryResult result = CharacterDatabase.Query("SELECT guid, name, account, race, gender, class, level FROM characters"); + QueryResult result = CharacterDatabase.Query(R"( + SELECT c.guid, c.name, c.account, c.race, c.gender, c.class, c.level, c.playerFlags, COALESCE(mgc.game_mode, 0) + FROM characters c + LEFT JOIN mod_gamemodes_characters mgc ON mgc.guid = c.guid + )"); if (!result) { LOG_INFO("server.loading", "No character name data loaded, empty query!"); @@ -73,7 +87,8 @@ void CharacterCache::LoadCharacterCacheStorage() { Field* fields = result->Fetch(); AddCharacterCacheEntry(ObjectGuid::Create(fields[0].Get()) /*guid*/, fields[2].Get() /*account*/, fields[1].Get() /*name*/, - fields[4].Get() /*gender*/, fields[3].Get() /*race*/, fields[5].Get() /*class*/, fields[6].Get() /*level*/); + fields[4].Get() /*gender*/, fields[3].Get() /*race*/, fields[5].Get() /*class*/, fields[6].Get() /*level*/, + fields[7].Get() /*playerFlags*/, fields[8].Get() /*gameMode*/); } while (result->NextRow()); QueryResult mailCountResult = CharacterDatabase.Query("SELECT receiver, COUNT(receiver) FROM mail GROUP BY receiver"); @@ -92,7 +107,12 @@ void CharacterCache::LoadCharacterCacheStorage() void CharacterCache::RefreshCacheEntry(uint32 lowGuid) { - QueryResult result = CharacterDatabase.Query("SELECT guid, name, account, race, gender, class, level FROM characters WHERE guid = {}", lowGuid); + QueryResult result = CharacterDatabase.Query(R"( + SELECT c.guid, c.name, c.account, c.race, c.gender, c.class, c.level, c.playerFlags, COALESCE(mgc.game_mode, 0) + FROM characters c + LEFT JOIN mod_gamemodes_characters mgc ON mgc.guid = c.guid + WHERE c.guid = {} + )", lowGuid); if (!result) { return; @@ -102,7 +122,9 @@ void CharacterCache::RefreshCacheEntry(uint32 lowGuid) { Field* fields = result->Fetch(); DeleteCharacterCacheEntry(ObjectGuid::Create(lowGuid), fields[1].Get()); - AddCharacterCacheEntry(ObjectGuid::Create(fields[0].Get()) /*guid*/, fields[2].Get() /*account*/, fields[1].Get() /*name*/, fields[4].Get() /*gender*/, fields[3].Get() /*race*/, fields[5].Get() /*class*/, fields[6].Get() /*level*/); + AddCharacterCacheEntry(ObjectGuid::Create(fields[0].Get()) /*guid*/, fields[2].Get() /*account*/, fields[1].Get() /*name*/, + fields[4].Get() /*gender*/, fields[3].Get() /*race*/, fields[5].Get() /*class*/, fields[6].Get() /*level*/, + fields[7].Get() /*playerFlags*/, fields[8].Get() /*gameMode*/); } while (result->NextRow()); QueryResult mailCountResult = CharacterDatabase.Query("SELECT receiver, COUNT(receiver) FROM mail WHERE receiver = {} GROUP BY receiver", lowGuid); @@ -119,16 +141,18 @@ void CharacterCache::RefreshCacheEntry(uint32 lowGuid) /* Modifying functions */ -void CharacterCache::AddCharacterCacheEntry(ObjectGuid const& guid, uint32 accountId, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level) +void CharacterCache::AddCharacterCacheEntry(ObjectGuid const& guid, uint32 accountId, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level, uint32 playerFlags, uint8 gameMode) { CharacterCacheEntry& data = _characterCacheStore[guid]; data.Guid = guid; data.Name = name; data.AccountId = accountId; + data.PlayerFlags = playerFlags; data.Race = race; data.Sex = gender; data.Class = playerClass; data.Level = level; + data.GameMode = gameMode; data.GuildId = 0; // Will be set in guild loading or guild setting for (uint8 i = 0; i < MAX_ARENA_SLOT; ++i) { @@ -145,7 +169,7 @@ void CharacterCache::DeleteCharacterCacheEntry(ObjectGuid const& guid, std::stri _characterCacheByNameStore.erase(name); } -void CharacterCache::UpdateCharacterData(ObjectGuid const& guid, std::string const& name, Optional gender /*= {}*/, Optional race /*= {}*/) +void CharacterCache::UpdateCharacterData(ObjectGuid const& guid, std::string const& name, Optional gender /*= {}*/, Optional race /*= {}*/, Optional playerFlags /*= {}*/, Optional gameMode /*= {}*/) { auto itr = _characterCacheStore.find(guid); if (itr == _characterCacheStore.end()) @@ -164,6 +188,16 @@ void CharacterCache::UpdateCharacterData(ObjectGuid const& guid, std::string con itr->second.Race = *race; } + if (playerFlags) + { + itr->second.PlayerFlags = *playerFlags; + } + + if (gameMode) + { + itr->second.GameMode = *gameMode; + } + //WorldPackets::Misc::InvalidatePlayer packet(guid); //sWorld->SendGlobalMessage(packet.Write()); @@ -311,7 +345,7 @@ uint32 CharacterCache::GetCharacterTeamByGuid(ObjectGuid guid) const return 0; } - return Player::TeamIdForRace(itr->second.Race); + return GetEffectiveCharacterTeam(itr->second.Race, itr->second.PlayerFlags, itr->second.GameMode); } uint32 CharacterCache::GetCharacterAccountIdByGuid(ObjectGuid guid) const diff --git a/src/server/game/Cache/CharacterCache.h b/src/server/game/Cache/CharacterCache.h index c0f8572..3bce935 100644 --- a/src/server/game/Cache/CharacterCache.h +++ b/src/server/game/Cache/CharacterCache.h @@ -29,10 +29,12 @@ struct CharacterCacheEntry ObjectGuid Guid; std::string Name; uint32 AccountId; + uint32 PlayerFlags = 0; uint8 Class; uint8 Race; uint8 Sex; uint8 Level; + uint8 GameMode = 0; uint8 MailCount; ObjectGuid::LowType GuildId; std::array ArenaTeamId; @@ -49,10 +51,10 @@ class AC_GAME_API CharacterCache void LoadCharacterCacheStorage(); void RefreshCacheEntry(uint32 lowGuid); - void AddCharacterCacheEntry(ObjectGuid const& guid, uint32 accountId, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level); + void AddCharacterCacheEntry(ObjectGuid const& guid, uint32 accountId, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level, uint32 playerFlags = 0, uint8 gameMode = 0); void DeleteCharacterCacheEntry(ObjectGuid const& guid, std::string const& name); - void UpdateCharacterData(ObjectGuid const& guid, std::string const& name, Optional gender = {}, Optional race = {}); + void UpdateCharacterData(ObjectGuid const& guid, std::string const& name, Optional gender = {}, Optional race = {}, Optional playerFlags = {}, Optional gameMode = {}); void UpdateCharacterLevel(ObjectGuid const& guid, uint8 level); void UpdateCharacterAccountId(ObjectGuid const& guid, uint32 accountId); void UpdateCharacterGuildId(ObjectGuid const& guid, ObjectGuid::LowType guildId); diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 21daccd..d6b4bc3 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1483,7 +1483,7 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name) return; } - if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && pInvitee->GetTeamId(true) != player->GetTeamId(true)) + if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && pInvitee->GetTeamId() != player->GetTeamId()) { SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_NOT_ALLIED, name); return; diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 0d9b128..df75c96 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -582,7 +582,8 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData) { LOG_INFO("entities.player.character", "Account: {} (IP: {}) Create Character: {} {}", GetAccountId(), GetRemoteAddress(), newChar->GetName(), newChar->GetGUID().ToString()); sScriptMgr->OnPlayerCreate(newChar.get()); - sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->getGender(), newChar->getRace(), newChar->getClass(), newChar->GetLevel()); + sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->getGender(), newChar->getRace(), newChar->getClass(), newChar->GetLevel(), + newChar->GetUInt32Value(PLAYER_FLAGS), static_cast(newChar->GetGameMode())); SendCharCreate(CHAR_CREATE_SUCCESS); } else diff --git a/src/server/scripts/Commands/cs_cache.cpp b/src/server/scripts/Commands/cs_cache.cpp index 2e05f54..768750d 100644 --- a/src/server/scripts/Commands/cs_cache.cpp +++ b/src/server/scripts/Commands/cs_cache.cpp @@ -111,12 +111,14 @@ public: { if (sCharacterCache->HasCharacterCacheEntry(cPlayer->GetGUID())) { - sCharacterCache->UpdateCharacterData(cPlayer->GetGUID(), cPlayer->GetName(), cPlayer->getGender(), cPlayer->getRace()); + sCharacterCache->UpdateCharacterData(cPlayer->GetGUID(), cPlayer->GetName(), cPlayer->getGender(), cPlayer->getRace(), + cPlayer->GetUInt32Value(PLAYER_FLAGS), static_cast(cPlayer->GetGameMode())); } else { sCharacterCache->AddCharacterCacheEntry(cPlayer->GetGUID(), cPlayer->GetSession()->GetAccountId(), cPlayer->GetName(), - cPlayer->getGender(), cPlayer->getRace(), cPlayer->getClass(), cPlayer->GetLevel()); + cPlayer->getGender(), cPlayer->getRace(), cPlayer->getClass(), cPlayer->GetLevel(), + cPlayer->GetUInt32Value(PLAYER_FLAGS), static_cast(cPlayer->GetGameMode())); } sCharacterCache->UpdateCharacterAccountId(cPlayer->GetGUID(), cPlayer->GetSession()->GetAccountId());