aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2021_07_01_13_world_2018_02_24_06_world.sql6
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp34
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h1
-rw-r--r--src/server/game/Entities/GameObject/GameObjectData.h15
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp6
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp57
-rw-r--r--src/server/game/Globals/ObjectMgr.h4
-rw-r--r--src/server/game/World/World.cpp5
-rw-r--r--src/server/scripts/Commands/cs_gobject.cpp17
10 files changed, 116 insertions, 31 deletions
diff --git a/sql/updates/world/master/2021_07_01_13_world_2018_02_24_06_world.sql b/sql/updates/world/master/2021_07_01_13_world_2018_02_24_06_world.sql
new file mode 100644
index 00000000000..b330e6ec8ed
--- /dev/null
+++ b/sql/updates/world/master/2021_07_01_13_world_2018_02_24_06_world.sql
@@ -0,0 +1,6 @@
+CREATE TABLE IF NOT EXISTS `gameobject_overrides` (
+ `spawnId` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `faction` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `flags` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`spawnId`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index f231ef6a683..821dc454323 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -318,11 +318,14 @@ bool GameObject::Create(uint32 entry, Map* map, Position const& pos, QuaternionD
SetObjectScale(goInfo->size);
- if (m_goTemplateAddon)
+ if (GameObjectOverride const* goOverride = GetGameObjectOverride())
{
- SetFaction(m_goTemplateAddon->faction);
- SetFlags(GameObjectFlags(m_goTemplateAddon->flags));
+ SetFaction(goOverride->Faction);
+ SetFlags(GameObjectFlags(goOverride->Flags));
+ }
+ if (m_goTemplateAddon)
+ {
if (m_goTemplateAddon->WorldEffectID)
{
m_updateFlag.GameObject = true;
@@ -871,14 +874,14 @@ void GameObject::Update(uint32 diff)
SetGoState(GO_STATE_READY);
//any return here in case battleground traps
- if (GameObjectTemplateAddon const* addon = GetTemplateAddon())
- if (addon->flags & GO_FLAG_NODESPAWN)
+ if (GameObjectOverride const* goOverride = GetGameObjectOverride())
+ if (goOverride->Flags & GO_FLAG_NODESPAWN)
return;
}
loot.clear();
- //! If this is summoned by a spell with ie. SPELL_EFFECT_SUMMON_OBJECT_WILD, with or without owner, we check respawn criteria based on spell
+ //! If this is summoned by a spell with ie. SPELL_EFFECT_SUMMON_OBJECT_WILD, with or without owner, we check respawn criteria based on speSendObjectDeSpawnAnim(GetGUID());ll
//! The GetOwnerGUID() check is mostly for compatibility with hacky scripts - 99% of the time summoning should be done trough spells.
if (GetSpellId() || !GetOwnerGUID().IsEmpty())
{
@@ -894,8 +897,8 @@ void GameObject::Update(uint32 diff)
{
SendGameObjectDespawn();
//reset flags
- if (GameObjectTemplateAddon const* addon = GetTemplateAddon())
- SetFlags(GameObjectFlags(addon->flags));
+ if (GameObjectOverride const* goOverride = GetGameObjectOverride())
+ SetFlags(GameObjectFlags(goOverride->Flags));
}
if (!m_respawnDelayTime)
@@ -938,6 +941,17 @@ void GameObject::Update(uint32 diff)
}
}
+GameObjectOverride const* GameObject::GetGameObjectOverride() const
+{
+ if (m_spawnId)
+ {
+ if (GameObjectOverride const* goOverride = sObjectMgr->GetGameObjectOverride(m_spawnId))
+ return goOverride;
+ }
+
+ return m_goTemplateAddon;
+}
+
void GameObject::Refresh()
{
// Do not refresh despawned GO from spellcast (GO's from spellcast are destroyed after despawn)
@@ -982,8 +996,8 @@ void GameObject::Delete()
SetGoState(GO_STATE_READY);
- if (GameObjectTemplateAddon const* addon = GetTemplateAddon())
- SetFlags(GameObjectFlags(addon->flags));
+ if (GameObjectOverride const* goOverride = GetGameObjectOverride())
+ SetFlags(GameObjectFlags(goOverride->Flags));
uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0;
if (poolid)
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 42979d3f8ab..bb1efe37da0 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -106,6 +106,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void Update(uint32 p_time) override;
GameObjectTemplate const* GetGOInfo() const { return m_goInfo; }
GameObjectTemplateAddon const* GetTemplateAddon() const { return m_goTemplateAddon; }
+ GameObjectOverride const* GetGameObjectOverride() const;
GameObjectData const* GetGameObjectData() const { return m_goData; }
GameObjectValue const* GetGOValue() const { return &m_goValue; }
diff --git a/src/server/game/Entities/GameObject/GameObjectData.h b/src/server/game/Entities/GameObject/GameObjectData.h
index b2d66eaac51..89ee6f97307 100644
--- a/src/server/game/Entities/GameObject/GameObjectData.h
+++ b/src/server/game/Entities/GameObject/GameObjectData.h
@@ -1040,13 +1040,18 @@ struct GameObjectTemplate
WorldPacket BuildQueryData(LocaleConstant loc) const;
};
+// From `gameobject_template_addon`, `gameobject_overrides`
+struct GameObjectOverride
+{
+ uint32 Faction;
+ uint32 Flags;
+};
+
// From `gameobject_template_addon`
-struct GameObjectTemplateAddon
+struct GameObjectTemplateAddon : public GameObjectOverride
{
- uint32 faction;
- uint32 flags;
- uint32 mingold;
- uint32 maxgold;
+ uint32 Mingold;
+ uint32 Maxgold;
uint32 WorldEffectID;
uint32 AIAnimKitID;
};
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index db38ba84fae..37c3b88710f 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -8802,7 +8802,7 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type, bool aeLooting/* = fa
if (go->GetLootMode() > 0)
if (GameObjectTemplateAddon const* addon = go->GetTemplateAddon())
- loot->generateMoneyLoot(addon->mingold, addon->maxgold);
+ loot->generateMoneyLoot(addon->Mingold, addon->Maxgold);
if (loot_type == LOOT_FISHING)
go->getFishLoot(loot, this);
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index f2667e84a37..1d40a5dfbad 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -86,10 +86,10 @@ bool Transport::Create(ObjectGuid::LowType guidlow, uint32 entry, uint32 mapid,
_triggeredArrivalEvent = false;
_triggeredDepartureEvent = false;
- if (m_goTemplateAddon)
+ if (GameObjectOverride const* goOverride = GetGameObjectOverride())
{
- SetFaction(m_goTemplateAddon->faction);
- SetFlags(GameObjectFlags(m_goTemplateAddon->flags));
+ SetFaction(goOverride->Faction);
+ SetFlags(GameObjectFlags(goOverride->Flags));
}
m_goValue.Transport.PathProgress = 0;
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 42ac714018d..84117d199ca 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -7432,18 +7432,18 @@ void ObjectMgr::LoadGameObjectTemplateAddons()
}
GameObjectTemplateAddon& gameObjectAddon = _gameObjectTemplateAddonStore[entry];
- gameObjectAddon.faction = uint32(fields[1].GetUInt16());
- gameObjectAddon.flags = fields[2].GetUInt32();
- gameObjectAddon.mingold = fields[3].GetUInt32();
- gameObjectAddon.maxgold = fields[4].GetUInt32();
+ gameObjectAddon.Faction = uint32(fields[1].GetUInt16());
+ gameObjectAddon.Flags = fields[2].GetUInt32();
+ gameObjectAddon.Mingold = fields[3].GetUInt32();
+ gameObjectAddon.Maxgold = fields[4].GetUInt32();
gameObjectAddon.WorldEffectID = fields[5].GetUInt32();
gameObjectAddon.AIAnimKitID = fields[6].GetUInt32();
// checks
- if (gameObjectAddon.faction && !sFactionTemplateStore.LookupEntry(gameObjectAddon.faction))
- TC_LOG_ERROR("sql.sql", "GameObject (Entry: %u) has invalid faction (%u) defined in `gameobject_template_addon`.", entry, gameObjectAddon.faction);
+ if (gameObjectAddon.Faction && !sFactionTemplateStore.LookupEntry(gameObjectAddon.Faction))
+ TC_LOG_ERROR("sql.sql", "GameObject (Entry: %u) has invalid faction (%u) defined in `gameobject_template_addon`.", entry, gameObjectAddon.Faction);
- if (gameObjectAddon.maxgold > 0)
+ if (gameObjectAddon.Maxgold > 0)
{
switch (got->type)
{
@@ -7475,6 +7475,44 @@ void ObjectMgr::LoadGameObjectTemplateAddons()
TC_LOG_INFO("server.loading", ">> Loaded %u game object template addons in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
+void ObjectMgr::LoadGameObjectOverrides()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // 0 1 2
+ QueryResult result = WorldDatabase.Query("SELECT spawnId, faction, flags FROM gameobject_overrides");
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 gameobject faction and flags overrides. DB table `gameobject_overrides` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+
+ ObjectGuid::LowType spawnId = fields[0].GetUInt64();
+ GameObjectData const* goData = GetGameObjectData(spawnId);
+ if (!goData)
+ {
+ TC_LOG_ERROR("sql.sql", "GameObject (SpawnId: " UI64FMTD ") does not exist but has a record in `gameobject_overrides`", spawnId);
+ continue;
+ }
+
+ GameObjectOverride& gameObjectOverride = _gameObjectOverrideStore[spawnId];
+ gameObjectOverride.Faction = fields[1].GetUInt32();
+ gameObjectOverride.Flags = fields[2].GetUInt32();
+
+ if (gameObjectOverride.Faction && !sFactionTemplateStore.LookupEntry(gameObjectOverride.Faction))
+ TC_LOG_ERROR("sql.sql", "GameObject (SpawnId: " UI64FMTD ") has invalid faction (%u) defined in `gameobject_overrides`.", spawnId, gameObjectOverride.Faction);
+
+ ++count;
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u gameobject faction and flags overrides in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
void ObjectMgr::LoadExplorationBaseXP()
{
uint32 oldMSTime = getMSTime();
@@ -9934,6 +9972,11 @@ GameObjectTemplateAddon const* ObjectMgr::GetGameObjectTemplateAddon(uint32 entr
return nullptr;
}
+GameObjectOverride const* ObjectMgr::GetGameObjectOverride(ObjectGuid::LowType spawnId) const
+{
+ return Trinity::Containers::MapGetValuePtr(_gameObjectOverrideStore, spawnId);
+}
+
CreatureTemplate const* ObjectMgr::GetCreatureTemplate(uint32 entry) const
{
return Trinity::Containers::MapGetValuePtr(_creatureTemplateStore, entry);
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 85ac73d7cf3..4f609eb3f95 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -505,6 +505,7 @@ typedef std::unordered_map<uint32, CreatureModelInfo> CreatureModelContainer;
typedef std::unordered_map<uint32, std::vector<uint32>> CreatureQuestItemMap;
typedef std::unordered_map<uint32, GameObjectTemplate> GameObjectTemplateContainer;
typedef std::unordered_map<uint32, GameObjectTemplateAddon> GameObjectTemplateAddonContainer;
+typedef std::unordered_map<ObjectGuid::LowType, GameObjectOverride> GameObjectOverrideContainer;
typedef std::unordered_map<ObjectGuid::LowType, GameObjectData> GameObjectDataContainer;
typedef std::unordered_map<ObjectGuid::LowType, GameObjectAddon> GameObjectAddonContainer;
typedef std::unordered_map<uint32, std::vector<uint32>> GameObjectQuestItemMap;
@@ -1034,6 +1035,7 @@ class TC_GAME_API ObjectMgr
void LoadGameObjectTemplate();
void LoadGameObjectTemplateAddons();
+ void LoadGameObjectOverrides();
CreatureTemplate const* GetCreatureTemplate(uint32 entry) const;
CreatureTemplateContainer const& GetCreatureTemplates() const { return _creatureTemplateStore; }
@@ -1045,6 +1047,7 @@ class TC_GAME_API ObjectMgr
CreatureAddon const* GetCreatureAddon(ObjectGuid::LowType lowguid) const;
GameObjectAddon const* GetGameObjectAddon(ObjectGuid::LowType lowguid) const;
GameObjectTemplateAddon const* GetGameObjectTemplateAddon(uint32 entry) const;
+ GameObjectOverride const* GetGameObjectOverride(ObjectGuid::LowType spawnId) const;
CreatureAddon const* GetCreatureTemplateAddon(uint32 entry) const;
ItemTemplate const* GetItemTemplate(uint32 entry) const;
ItemTemplateContainer const& GetItemTemplateStore() const { return _itemTemplateStore; }
@@ -1800,6 +1803,7 @@ class TC_GAME_API ObjectMgr
GameObjectLocaleContainer _gameObjectLocaleStore;
GameObjectTemplateContainer _gameObjectTemplateStore;
GameObjectTemplateAddonContainer _gameObjectTemplateAddonStore;
+ GameObjectOverrideContainer _gameObjectOverrideStore;
SpawnGroupDataContainer _spawnGroupDataStore;
SpawnGroupLinkContainer _spawnGroupMapStore;
InstanceSpawnGroupContainer _instanceSpawnGroupStore;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 06f45667e25..4cc192a5e4b 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1929,7 +1929,10 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadSpawnGroups();
TC_LOG_INFO("server.loading", "Loading GameObject Addon Data...");
- sObjectMgr->LoadGameObjectAddons(); // must be after LoadGameObjectTemplate() and LoadGameObjects()
+ sObjectMgr->LoadGameObjectAddons(); // must be after LoadGameObjects()
+
+ TC_LOG_INFO("server.loading", "Loading GameObject faction and flags overrides...");
+ sObjectMgr->LoadGameObjectOverrides(); // must be after LoadGameObjects()
TC_LOG_INFO("server.loading", "Loading GameObject Quest Items...");
sObjectMgr->LoadGameObjectQuestItems();
diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp
index 9b5bc70b866..0b0d7792874 100644
--- a/src/server/scripts/Commands/cs_gobject.cpp
+++ b/src/server/scripts/Commands/cs_gobject.cpp
@@ -605,14 +605,15 @@ public:
if (!param1)
return false;
+ ObjectGuid::LowType spawnId = 0;
if (strcmp(param1, "guid") == 0)
{
char* tail = strtok(nullptr, "");
char* cValue = handler->extractKeyFromLink(tail, "Hgameobject");
if (!cValue)
return false;
- ObjectGuid::LowType guidLow = atoull(cValue);
- GameObjectData const* data = sObjectMgr->GetGameObjectData(guidLow);
+ spawnId = atoull(cValue);
+ GameObjectData const* data = sObjectMgr->GetGameObjectData(spawnId);
if (!data)
return false;
entry = data->id;
@@ -672,8 +673,16 @@ public:
handler->PSendSysMessage(LANG_GOINFO_NAME, name.c_str());
handler->PSendSysMessage(LANG_GOINFO_SIZE, gameObjectInfo->size);
- if (GameObjectTemplateAddon const* addon = sObjectMgr->GetGameObjectTemplateAddon(entry))
- handler->PSendSysMessage(LANG_GOINFO_ADDON, addon->faction, addon->flags);
+ GameObjectOverride const* goOverride = nullptr;
+ if (spawnId)
+ if (GameObjectOverride const* ovr = sObjectMgr->GetGameObjectOverride(spawnId))
+ goOverride = ovr;
+
+ if (!goOverride)
+ goOverride = sObjectMgr->GetGameObjectTemplateAddon(entry);
+
+ if (goOverride)
+ handler->PSendSysMessage(LANG_GOINFO_ADDON, goOverride->Faction, goOverride->Flags);
handler->PSendSysMessage(LANG_OBJECTINFO_AIINFO, gameObjectInfo->AIName.c_str(), sObjectMgr->GetScriptName(gameObjectInfo->ScriptId).c_str());