mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-24 10:56:38 +01:00
Core/GameObject: implemented gameobject_overrides table to change faction and flags values on a per-spawn basis
Updates #20957
Closes #20958
(cherry picked from commit 34967e9c32)
This commit is contained in:
@@ -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;
|
||||
@@ -318,11 +318,14 @@ bool GameObject::Create(uint32 entry, Map* map, Position const& pos, QuaternionD
|
||||
|
||||
SetObjectScale(goInfo->size);
|
||||
|
||||
if (GameObjectOverride const* goOverride = GetGameObjectOverride())
|
||||
{
|
||||
SetFaction(goOverride->Faction);
|
||||
SetFlags(GameObjectFlags(goOverride->Flags));
|
||||
}
|
||||
|
||||
if (m_goTemplateAddon)
|
||||
{
|
||||
SetFaction(m_goTemplateAddon->faction);
|
||||
SetFlags(GameObjectFlags(m_goTemplateAddon->flags));
|
||||
|
||||
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)
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -1040,13 +1040,18 @@ struct GameObjectTemplate
|
||||
WorldPacket BuildQueryData(LocaleConstant loc) const;
|
||||
};
|
||||
|
||||
// From `gameobject_template_addon`
|
||||
struct GameObjectTemplateAddon
|
||||
// From `gameobject_template_addon`, `gameobject_overrides`
|
||||
struct GameObjectOverride
|
||||
{
|
||||
uint32 faction;
|
||||
uint32 flags;
|
||||
uint32 mingold;
|
||||
uint32 maxgold;
|
||||
uint32 Faction;
|
||||
uint32 Flags;
|
||||
};
|
||||
|
||||
// From `gameobject_template_addon`
|
||||
struct GameObjectTemplateAddon : public GameObjectOverride
|
||||
{
|
||||
uint32 Mingold;
|
||||
uint32 Maxgold;
|
||||
uint32 WorldEffectID;
|
||||
uint32 AIAnimKitID;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user