diff options
author | Jeremy <Golrag@users.noreply.github.com> | 2024-03-27 18:55:44 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-27 18:55:44 +0100 |
commit | 1f855ef56336c6a7fd74898e9c9beba77828c69b (patch) | |
tree | ecf633a2a1c04ca4832f51777e4f9f4c3a1ea4cc /src | |
parent | 5c4b1ace41b417539ed0abfec7475c23765e81c9 (diff) |
Core/GameObjects: Implement destructible_hitpoint table to store health info about destructible buildings (#29836)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 32 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObjectData.h | 9 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 36 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.h | 4 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 1 | ||||
-rw-r--r-- | src/server/scripts/Battlefield/BattlefieldTB.cpp | 3 |
7 files changed, 69 insertions, 18 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 32b0bc706ad..a901f637072 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1067,10 +1067,10 @@ bool GameObject::Create(uint32 entry, Map* map, Position const& pos, QuaternionD break; case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING: { - // TODO: Get the values somehow, no longer in gameobject_template - m_goValue.Building.Health = 20000/*goinfo->destructibleBuilding.intactNumHits + goinfo->destructibleBuilding.damagedNumHits*/; - m_goValue.Building.MaxHealth = m_goValue.Building.Health; + m_goValue.Building.DestructibleHitpoint = sObjectMgr->GetDestructibleHitpoint(GetGOInfo()->destructibleBuilding.HealthRec); + m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint ? m_goValue.Building.DestructibleHitpoint->GetMaxHealth() : 0; SetGoAnimProgress(255); + // yes, even after the updatefield rewrite this garbage hack is still in client QuaternionData reinterpretId; memcpy(&reinterpretId.x, &m_goInfo->destructibleBuilding.DestructibleModelRec, sizeof(float)); @@ -3623,7 +3623,7 @@ QuaternionData GameObject::GetWorldRotation() const void GameObject::ModifyHealth(int32 change, WorldObject* attackerOrHealer /*= nullptr*/, uint32 spellId /*= 0*/) { - if (!m_goValue.Building.MaxHealth || !change) + if (!m_goValue.Building.DestructibleHitpoint || !change) return; // prevent double destructions of the same object @@ -3632,13 +3632,13 @@ void GameObject::ModifyHealth(int32 change, WorldObject* attackerOrHealer /*= nu if (int32(m_goValue.Building.Health) + change <= 0) m_goValue.Building.Health = 0; - else if (int32(m_goValue.Building.Health) + change >= int32(m_goValue.Building.MaxHealth)) - m_goValue.Building.Health = m_goValue.Building.MaxHealth; + else if (int32(m_goValue.Building.Health) + change >= int32(m_goValue.Building.DestructibleHitpoint->GetMaxHealth())) + m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint->GetMaxHealth(); else m_goValue.Building.Health += change; // Set the health bar, value = 255 * healthPct; - SetGoAnimProgress(m_goValue.Building.Health * 255 / m_goValue.Building.MaxHealth); + SetGoAnimProgress(m_goValue.Building.Health * 255 / m_goValue.Building.DestructibleHitpoint->GetMaxHealth()); // dealing damage, send packet if (Player* player = attackerOrHealer ? attackerOrHealer->GetCharmerOrOwnerPlayerOrPlayerItself() : nullptr) @@ -3659,9 +3659,9 @@ void GameObject::ModifyHealth(int32 change, WorldObject* attackerOrHealer /*= nu if (!m_goValue.Building.Health) newState = GO_DESTRUCTIBLE_DESTROYED; - else if (m_goValue.Building.Health <= 10000/*GetGOInfo()->destructibleBuilding.damagedNumHits*/) // TODO: Get health somewhere + else if (m_goValue.Building.Health <= m_goValue.Building.DestructibleHitpoint->DamagedNumHits) newState = GO_DESTRUCTIBLE_DAMAGED; - else if (m_goValue.Building.Health == m_goValue.Building.MaxHealth) + else if (m_goValue.Building.Health == m_goValue.Building.DestructibleHitpoint->GetMaxHealth()) newState = GO_DESTRUCTIBLE_INTACT; if (newState == GetDestructibleState()) @@ -3680,9 +3680,9 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, WorldOb case GO_DESTRUCTIBLE_INTACT: RemoveFlag(GO_FLAG_DAMAGED | GO_FLAG_DESTROYED); SetDisplayId(m_goInfo->displayId); - if (setHealth) + if (setHealth && m_goValue.Building.DestructibleHitpoint) { - m_goValue.Building.Health = m_goValue.Building.MaxHealth; + m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint->GetMaxHealth(); SetGoAnimProgress(255); } EnableCollision(true); @@ -3702,10 +3702,10 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, WorldOb modelId = modelData->State1Wmo; SetDisplayId(modelId); - if (setHealth) + if (setHealth && m_goValue.Building.DestructibleHitpoint) { - m_goValue.Building.Health = 10000/*m_goInfo->destructibleBuilding.damagedNumHits*/; - uint32 maxHealth = m_goValue.Building.MaxHealth; + m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint->DamagedNumHits; + uint32 maxHealth = m_goValue.Building.DestructibleHitpoint->GetMaxHealth(); // in this case current health is 0 anyway so just prevent crashing here if (!maxHealth) maxHealth = 1; @@ -3753,9 +3753,9 @@ void GameObject::SetDestructibleState(GameObjectDestructibleState state, WorldOb SetDisplayId(modelId); // restores to full health - if (setHealth) + if (setHealth && m_goValue.Building.DestructibleHitpoint) { - m_goValue.Building.Health = m_goValue.Building.MaxHealth; + m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint->GetMaxHealth(); SetGoAnimProgress(255); } EnableCollision(true); diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 81db669c0b0..0f8941dc870 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -136,7 +136,7 @@ union GameObjectValue struct { uint32 Health; - uint32 MaxHealth; + ::DestructibleHitpoint const* DestructibleHitpoint; } Building; //42 GAMEOBJECT_TYPE_CAPTURE_POINT struct diff --git a/src/server/game/Entities/GameObject/GameObjectData.h b/src/server/game/Entities/GameObject/GameObjectData.h index d9d6a904c6d..ebf67292ced 100644 --- a/src/server/game/Entities/GameObject/GameObjectData.h +++ b/src/server/game/Entities/GameObject/GameObjectData.h @@ -27,6 +27,15 @@ #include <set> #include <string> +struct DestructibleHitpoint +{ + uint32 Id; + uint32 IntactNumHits; + uint32 DamagedNumHits; + + uint32 GetMaxHealth() const { return IntactNumHits + DamagedNumHits; } +}; + // from `gameobject_template` struct GameObjectTemplate { diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index ab693e0143b..0a60ee9719e 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7480,6 +7480,33 @@ void ObjectMgr::LoadGameObjectLocales() TC_LOG_INFO("server.loading", ">> Loaded {} gameobject_template_locale strings in {} ms", uint32(_gameObjectLocaleStore.size()), GetMSTimeDiffToNow(oldMSTime)); } +void ObjectMgr::LoadDestructibleHitpoints() +{ + uint32 oldMSTime = getMSTime(); + + _destructibleHitpointStore.clear(); // need for reload case + + // 0 1 2 + QueryResult result = WorldDatabase.Query("SELECT Id, IntactNumHits, DamagedNumHits FROM destructible_hitpoint"); + if (!result) + return; + + do + { + Field* fields = result->Fetch(); + + uint32 id = fields[0].GetUInt32(); + + DestructibleHitpoint& data = _destructibleHitpointStore[id]; + data.Id = id; + data.IntactNumHits = fields[1].GetUInt32(); + data.DamagedNumHits = fields[2].GetUInt32(); + + } while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded {} destructible_hitpoint records in {} ms", _destructibleHitpointStore.size(), GetMSTimeDiffToNow(oldMSTime)); +} + inline void CheckGOLockId(GameObjectTemplate const* goInfo, uint32 dataN, uint32 N) { if (sLockStore.LookupEntry(dataN)) @@ -7741,6 +7768,10 @@ void ObjectMgr::LoadGameObjectTemplate() got.barberChair.SitAnimKit = 0; } break; + case GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING: + if (got.destructibleBuilding.HealthRec && !GetDestructibleHitpoint(got.destructibleBuilding.HealthRec)) + TC_LOG_ERROR("sql.sql", "GameObject (Entry: {}) Has non existing Destructible Hitpoint Record {}.", entry, got.destructibleBuilding.HealthRec); + break; case GAMEOBJECT_TYPE_GARRISON_BUILDING: if (uint32 transportMap = got.garrisonBuilding.SpawnMap) _transportMaps.insert(transportMap); @@ -10452,6 +10483,11 @@ TerrainSwapInfo const* ObjectMgr::GetTerrainSwapInfo(uint32 terrainSwapId) const return Trinity::Containers::MapGetValuePtr(_terrainSwapInfoById, terrainSwapId); } +DestructibleHitpoint const* ObjectMgr::GetDestructibleHitpoint(uint32 entry) const +{ + return Trinity::Containers::MapGetValuePtr(_destructibleHitpointStore, entry); +} + GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry) const { return Trinity::Containers::MapGetValuePtr(_gameObjectTemplateStore, entry); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 2ffc9f94989..e26de428769 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -503,6 +503,7 @@ typedef std::unordered_map<uint32, EquipmentInfoContainerInternal> EquipmentInfo typedef std::unordered_map<uint32, CreatureModelInfo> CreatureModelContainer; typedef std::unordered_map<std::pair<uint32, Difficulty>, std::vector<uint32>> CreatureQuestItemMap; typedef std::unordered_map<uint32, std::vector<int32>> CreatureQuestCurrenciesMap; +typedef std::unordered_map<uint32, DestructibleHitpoint> DestructibleHitpointContainer; typedef std::unordered_map<uint32, GameObjectTemplate> GameObjectTemplateContainer; typedef std::unordered_map<uint32, GameObjectTemplateAddon> GameObjectTemplateAddonContainer; typedef std::unordered_map<ObjectGuid::LowType, GameObjectOverride> GameObjectOverrideContainer; @@ -1119,10 +1120,12 @@ class TC_GAME_API ObjectMgr typedef std::map<uint32, uint32> CharacterConversionMap; + DestructibleHitpoint const* GetDestructibleHitpoint(uint32 entry) const; GameObjectTemplate const* GetGameObjectTemplate(uint32 entry) const; GameObjectTemplateContainer const& GetGameObjectTemplates() const { return _gameObjectTemplateStore; } uint32 LoadReferenceVendor(int32 vendor, int32 item_id, std::set<uint32>* skip_vendors); + void LoadDestructibleHitpoints(); void LoadGameObjectTemplate(); void LoadGameObjectTemplateAddons(); void LoadGameObjectOverrides(); @@ -1901,6 +1904,7 @@ class TC_GAME_API ObjectMgr CreatureLocaleContainer _creatureLocaleStore; GameObjectDataContainer _gameObjectDataStore; GameObjectLocaleContainer _gameObjectLocaleStore; + DestructibleHitpointContainer _destructibleHitpointStore; GameObjectTemplateContainer _gameObjectTemplateStore; GameObjectTemplateAddonContainer _gameObjectTemplateAddonStore; GameObjectOverrideContainer _gameObjectOverrideStore; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 68bc5b4c77b..15eef323705 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1920,6 +1920,7 @@ void World::SetInitialWorldSettings() sObjectMgr->LoadPageTexts(); TC_LOG_INFO("server.loading", "Loading Game Object Templates..."); // must be after LoadPageTexts + sObjectMgr->LoadDestructibleHitpoints(); sObjectMgr->LoadGameObjectTemplate(); TC_LOG_INFO("server.loading", "Loading Game Object template addons..."); diff --git a/src/server/scripts/Battlefield/BattlefieldTB.cpp b/src/server/scripts/Battlefield/BattlefieldTB.cpp index 05222f50052..fc08cee710d 100644 --- a/src/server/scripts/Battlefield/BattlefieldTB.cpp +++ b/src/server/scripts/Battlefield/BattlefieldTB.cpp @@ -461,7 +461,8 @@ void BattlefieldTB::UpdateNPCsAndGameObjects() if (GameObject* go = GetGameObject(guid)) { go->SetDestructibleState(GO_DESTRUCTIBLE_INTACT); - go->ModifyHealth(go->GetGOValue()->Building.MaxHealth); + if (go->GetGOValue()->Building.DestructibleHitpoint) + go->ModifyHealth(go->GetGOValue()->Building.DestructibleHitpoint->GetMaxHealth()); } } } |