aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp32
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h2
-rw-r--r--src/server/game/Entities/GameObject/GameObjectData.h9
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp36
-rw-r--r--src/server/game/Globals/ObjectMgr.h4
-rw-r--r--src/server/game/World/World.cpp1
6 files changed, 67 insertions, 17 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...");