From b5ce4a66df0c76583c662056e46619c8fe98f297 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Fri, 26 Apr 2024 22:32:17 +0200 Subject: Core/Creature: implement overriding creature static flags based on spawnId and difficultyId (#29940) --- src/server/game/Entities/Creature/Creature.cpp | 20 ++++++- src/server/game/Entities/Creature/Creature.h | 2 + src/server/game/Entities/Creature/CreatureData.h | 22 ++++++++ src/server/game/Globals/ObjectMgr.cpp | 66 ++++++++++++++++++++++++ src/server/game/Globals/ObjectMgr.h | 5 ++ src/server/game/World/World.cpp | 3 ++ 6 files changed, 117 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index c07672dd08c..b519961d569 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -561,7 +561,8 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i) m_spells[i] = GetCreatureTemplate()->spells[i]; - ApplyAllStaticFlags(m_creatureDifficulty->StaticFlags); + CreatureStaticFlagsHolder staticFlags = GenerateStaticFlags(m_creatureDifficulty, GetSpawnId(), GetMap()->GetDifficultyID()); + ApplyAllStaticFlags(staticFlags); _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_NO_XP, creatureInfo->type == CREATURE_TYPE_CRITTER || IsPet() @@ -701,6 +702,23 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, return true; } +CreatureStaticFlagsHolder Creature::GenerateStaticFlags(CreatureDifficulty const* creatureDifficulty, ObjectGuid::LowType spawnId, Difficulty difficultyId) const +{ + CreatureStaticFlagsOverride const* staticFlagsOverride = sObjectMgr->GetCreatureStaticFlagsOverride(spawnId, difficultyId); + if (!staticFlagsOverride) + return creatureDifficulty->StaticFlags; + + return CreatureStaticFlagsHolder( + staticFlagsOverride->StaticFlags1.value_or(creatureDifficulty->StaticFlags.GetFlags()), + staticFlagsOverride->StaticFlags2.value_or(creatureDifficulty->StaticFlags.GetFlags2()), + staticFlagsOverride->StaticFlags3.value_or(creatureDifficulty->StaticFlags.GetFlags3()), + staticFlagsOverride->StaticFlags4.value_or(creatureDifficulty->StaticFlags.GetFlags4()), + staticFlagsOverride->StaticFlags5.value_or(creatureDifficulty->StaticFlags.GetFlags5()), + staticFlagsOverride->StaticFlags6.value_or(creatureDifficulty->StaticFlags.GetFlags6()), + staticFlagsOverride->StaticFlags7.value_or(creatureDifficulty->StaticFlags.GetFlags7()), + staticFlagsOverride->StaticFlags8.value_or(creatureDifficulty->StaticFlags.GetFlags8())); +} + void Creature::ApplyAllStaticFlags(CreatureStaticFlagsHolder const& flags) { _staticFlags = flags; diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index a11b6b00ec9..3a29b188192 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -557,6 +557,8 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma time_t _lastDamagedTime; // Part of Evade mechanics CreatureTextRepeatGroup m_textRepeat; + // Draws data from m_creatureDifficulty and spawn/difficulty based override data and returns a CreatureStaticFlagsHolder value which contains the data of both + CreatureStaticFlagsHolder GenerateStaticFlags(CreatureDifficulty const* creatureDifficulty, ObjectGuid::LowType spawnId, Difficulty difficultyId) const; void ApplyAllStaticFlags(CreatureStaticFlagsHolder const& flags); // Regenerate health diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index dea0e4be37b..be4a65dd417 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -317,6 +317,15 @@ public: void ApplyFlag(CreatureStaticFlags7 flag, bool apply) { if (apply) _flags7 |= flag; else _flags7 &= ~flag; } void ApplyFlag(CreatureStaticFlags8 flag, bool apply) { if (apply) _flags8 |= flag; else _flags8 &= ~flag; } + EnumFlag GetFlags() const { return _flags; } + EnumFlag GetFlags2() const { return _flags2; } + EnumFlag GetFlags3() const { return _flags3; } + EnumFlag GetFlags4() const { return _flags4; } + EnumFlag GetFlags5() const { return _flags5; } + EnumFlag GetFlags6() const { return _flags6; } + EnumFlag GetFlags7() const { return _flags7; } + EnumFlag GetFlags8() const { return _flags8; } + private: EnumFlag _flags; EnumFlag _flags2; @@ -646,6 +655,19 @@ struct CreatureAddon VisibilityDistanceType visibilityDistanceType; }; +// `creature_static_flags_override` table +struct CreatureStaticFlagsOverride +{ + Optional StaticFlags1; + Optional StaticFlags2; + Optional StaticFlags3; + Optional StaticFlags4; + Optional StaticFlags5; + Optional StaticFlags6; + Optional StaticFlags7; + Optional StaticFlags8; +}; + // Vendors struct VendorItem { diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 7c933cdd774..10cb845f24d 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -10727,6 +10727,11 @@ JumpChargeParams const* ObjectMgr::GetJumpChargeParams(int32 id) const return Trinity::Containers::MapGetValuePtr(_jumpChargeParams, id); } +CreatureStaticFlagsOverride const* ObjectMgr::GetCreatureStaticFlagsOverride(ObjectGuid::LowType spawnId, Difficulty difficultyId) const +{ + return Trinity::Containers::MapGetValuePtr(_creatureStaticFlagsOverrideStore, std::make_pair(spawnId, difficultyId)); +} + void ObjectMgr::LoadGameObjectQuestItems() { uint32 oldMSTime = getMSTime(); @@ -10860,6 +10865,67 @@ void ObjectMgr::LoadCreatureQuestCurrencies() TC_LOG_INFO("server.loading", ">> Loaded {} creature quest currencies in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); } +void ObjectMgr::LoadCreatureStaticFlagsOverride() +{ + // reload case + _creatureStaticFlagsOverrideStore.clear(); + + uint32 oldMSTime = getMSTime(); + + // 0 1 2 3 4 5 6 7 8 9 + QueryResult result = WorldDatabase.Query("SELECT SpawnId, DifficultyId, StaticFlags1, StaticFlags2, StaticFlags3, StaticFlags4, StaticFlags5, StaticFlags6, StaticFlags7, StaticFlags8 FROM creature_static_flags_override"); + + if (!result) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 creature static flag overrides. DB table `creature_static_flags_override` is empty."); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + + ObjectGuid::LowType spawnId = fields[0].GetUInt64(); + Difficulty difficultyId = static_cast(fields[1].GetUInt8()); + + CreatureData const* creatureData = GetCreatureData(spawnId); + if (!creatureData) + { + TC_LOG_ERROR("sql.sql", "Table `creature_static_flags_override` has data for nonexistent creature (SpawnId: {}), skipped", spawnId); + continue; + } + + if (std::find(creatureData->spawnDifficulties.begin(), creatureData->spawnDifficulties.end(), difficultyId) == creatureData->spawnDifficulties.end()) + { + TC_LOG_ERROR("sql.sql", "Table `creature_static_flags_override` has data for a creature that is not available for the specified DifficultyId (SpawnId: {}, DifficultyId: {}), skipped", spawnId, difficultyId); + continue; + } + + CreatureStaticFlagsOverride& staticFlagsOverride = _creatureStaticFlagsOverrideStore[std::make_pair(spawnId, difficultyId)]; + if (!fields[2].IsNull()) + staticFlagsOverride.StaticFlags1 = static_cast(fields[2].GetUInt32()); + if (!fields[3].IsNull()) + staticFlagsOverride.StaticFlags2 = static_cast(fields[3].GetUInt32()); + if (!fields[4].IsNull()) + staticFlagsOverride.StaticFlags3 = static_cast(fields[4].GetUInt32()); + if (!fields[5].IsNull()) + staticFlagsOverride.StaticFlags4 = static_cast(fields[5].GetUInt32()); + if (!fields[6].IsNull()) + staticFlagsOverride.StaticFlags5 = static_cast(fields[6].GetUInt32()); + if (!fields[7].IsNull()) + staticFlagsOverride.StaticFlags6 = static_cast(fields[7].GetUInt32()); + if (!fields[8].IsNull()) + staticFlagsOverride.StaticFlags7 = static_cast(fields[8].GetUInt32()); + if (!fields[9].IsNull()) + staticFlagsOverride.StaticFlags8 = static_cast(fields[9].GetUInt32()); + + ++count; + } while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded {} creature static flag overrides in {} ms", count, GetMSTimeDiffToNow(oldMSTime)); +} + void ObjectMgr::InitializeQueriesData(QueryDataGroup mask) { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index e26de428769..d373047127c 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -503,6 +503,7 @@ typedef std::unordered_map EquipmentInfo typedef std::unordered_map CreatureModelContainer; typedef std::unordered_map, std::vector> CreatureQuestItemMap; typedef std::unordered_map> CreatureQuestCurrenciesMap; +typedef std::unordered_map, CreatureStaticFlagsOverride> CreatureStaticFlagsOverrideMap; typedef std::unordered_map DestructibleHitpointContainer; typedef std::unordered_map GameObjectTemplateContainer; typedef std::unordered_map GameObjectTemplateAddonContainer; @@ -1322,6 +1323,7 @@ class TC_GAME_API ObjectMgr void LoadGameObjectQuestItems(); void LoadCreatureQuestItems(); void LoadCreatureQuestCurrencies(); + void LoadCreatureStaticFlagsOverride(); void LoadTempSummons(); void LoadCreatures(); void LoadLinkedRespawn(); @@ -1757,6 +1759,8 @@ class TC_GAME_API ObjectMgr JumpChargeParams const* GetJumpChargeParams(int32 id) const; + CreatureStaticFlagsOverride const* GetCreatureStaticFlagsOverride(ObjectGuid::LowType spawnId, Difficulty difficultyId) const; + private: // first free id for selected id type uint32 _auctionId; @@ -1899,6 +1903,7 @@ class TC_GAME_API ObjectMgr GameObjectQuestItemMap _gameObjectQuestItemStore; CreatureQuestItemMap _creatureQuestItemStore; CreatureQuestCurrenciesMap _creatureQuestCurrenciesStore; + CreatureStaticFlagsOverrideMap _creatureStaticFlagsOverrideStore; EquipmentInfoContainer _equipmentInfoStore; LinkedRespawnContainer _linkedRespawnStore; CreatureLocaleContainer _creatureLocaleStore; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 9ed9c7c85d6..1c2255e30eb 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -2370,6 +2370,9 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading Creature Text Locales..."); sCreatureTextMgr->LoadCreatureTextLocales(); + TC_LOG_INFO("server.loading", "Loading creature StaticFlags overrides..."); + sObjectMgr->LoadCreatureStaticFlagsOverride(); // must be after LoadCreatures + TC_LOG_INFO("server.loading", "Initializing Scripts..."); sScriptMgr->Initialize(); sScriptMgr->OnConfigLoad(false); // must be done after the ScriptMgr has been properly initialized -- cgit v1.2.3