From bcd1a701ac0305806bc6021317b6274ef581ba77 Mon Sep 17 00:00:00 2001 From: acidmanifesto Date: Mon, 25 Oct 2021 08:25:13 -0400 Subject: [PATCH] fix(Core): ScriptName not readable in creature and gameobject table fix (#8715) --- .../game/Entities/Creature/Creature.cpp | 5 ++- .../game/Entities/Creature/CreatureData.h | 1 + .../game/Entities/GameObject/GameObject.cpp | 8 +++++ .../game/Entities/GameObject/GameObject.h | 3 +- src/server/game/Globals/ObjectMgr.cpp | 35 ++++++++++++++----- src/server/game/Globals/ObjectMgr.h | 2 +- src/server/game/Handlers/MiscHandler.cpp | 6 ++-- 7 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 50c2c5c89..32fe2e869 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1031,7 +1031,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u //! Need to be called after LoadCreaturesAddon - MOVEMENTFLAG_HOVER is set there m_positionZ += GetHoverHeight(); - LastUsedScriptID = GetCreatureTemplate()->ScriptID; + LastUsedScriptID = GetScriptId(); if (IsSpiritHealer() || IsSpiritGuide() || (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_GHOST_VISIBILITY)) { @@ -2769,6 +2769,9 @@ std::string Creature::GetScriptName() const uint32 Creature::GetScriptId() const { + if (CreatureData const* creatureData = GetCreatureData()) + return creatureData->ScriptId; + return sObjectMgr->GetCreatureTemplate(GetEntry())->ScriptID; } diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index b54979049..e031b311b 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -285,6 +285,7 @@ struct CreatureData uint32 npcflag{0}; uint32 unit_flags{0}; // enum UnitFlags mask values uint32 dynamicflags{0}; + uint32 ScriptId; bool dbData{true}; bool overwrittenZ{false}; }; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 7961912ef..bec4b5df5 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -2090,6 +2090,14 @@ void GameObject::EventInform(uint32 eventId) m_zoneScript->ProcessEvent(this, eventId); } +uint32 GameObject::GetScriptId() const +{ + if (GameObjectData const* gameObjectData = GetGOData()) + return gameObjectData->ScriptId; + + return GetGOInfo()->ScriptId; +} + // overwrite WorldObject function for proper name localization std::string const& GameObject::GetNameForLocaleIdx(LocaleConstant loc_idx) const { diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 01c31959f..2cc5a80eb 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -711,6 +711,7 @@ struct GameObjectData float orientation{0.0f}; G3D::Quat rotation; int32 spawntimesecs{0}; + uint32 ScriptId; uint32 animprogress{0}; GOState go_state{GO_STATE_ACTIVE}; uint8 spawnMask{0}; @@ -933,7 +934,7 @@ public: void EventInform(uint32 eventId); - [[nodiscard]] virtual uint32 GetScriptId() const { return GetGOInfo()->ScriptId; } + [[nodiscard]] virtual uint32 GetScriptId() const; [[nodiscard]] GameObjectAI* AI() const { return m_AI; } [[nodiscard]] std::string GetAIName() const; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index dbab73586..a9f873ca6 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1835,7 +1835,9 @@ void ObjectMgr::LoadCreatures() // 0 1 2 3 4 5 6 7 8 9 10 QueryResult result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, wander_distance, " // 11 12 13 14 15 16 17 18 19 20 21 - "currentwaypoint, curhealth, curmana, MovementType, spawnMask, phaseMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags " + "currentwaypoint, curhealth, curmana, MovementType, spawnMask, phaseMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags, " + // 22 + "creature.ScriptName " "FROM creature " "LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid " "LEFT OUTER JOIN pool_creature ON creature.guid = pool_creature.guid"); @@ -1893,6 +1895,10 @@ void ObjectMgr::LoadCreatures() data.npcflag = fields[19].GetUInt32(); data.unit_flags = fields[20].GetUInt32(); data.dynamicflags = fields[21].GetUInt32(); + data.ScriptId = GetScriptId(fields[22].GetString()); + + if (!data.ScriptId) + data.ScriptId = cInfo->ScriptID; MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid); if (!mapEntry) @@ -2136,7 +2142,9 @@ void ObjectMgr::LoadGameobjects() // 0 1 2 3 4 5 6 QueryResult result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation, " // 7 8 9 10 11 12 13 14 15 16 17 - "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, eventEntry, pool_entry " + "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, eventEntry, pool_entry, " + // 18 + "ScriptName " "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid " "LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid"); @@ -2202,6 +2210,9 @@ void ObjectMgr::LoadGameobjects() data.rotation.z = fields[9].GetFloat(); data.rotation.w = fields[10].GetFloat(); data.spawntimesecs = fields[11].GetInt32(); + data.ScriptId = GetScriptId(fields[19].GetString()); + if (!data.ScriptId) + data.ScriptId = gInfo->ScriptId; MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid); if (!mapEntry) @@ -8710,14 +8721,21 @@ void ObjectMgr::LoadScriptNames() { uint32 oldMSTime = getMSTime(); - _scriptNamesStore.push_back(""); + // We insert an empty placeholder here so we can use the + // script id 0 as dummy for "no script found". + _scriptNamesStore.emplace_back(""); + QueryResult result = WorldDatabase.Query( "SELECT DISTINCT(ScriptName) FROM achievement_criteria_data WHERE ScriptName <> '' AND type = 11 " "UNION " "SELECT DISTINCT(ScriptName) FROM battleground_template WHERE ScriptName <> '' " "UNION " + "SELECT DISTINCT(ScriptName) FROM creature WHERE ScriptName <> '' " + "UNION " "SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' " "UNION " + "SELECT DISTINCT(ScriptName) FROM gameobject WHERE ScriptName <> '' " + "UNION " "SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' " "UNION " "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' " @@ -8743,16 +8761,15 @@ void ObjectMgr::LoadScriptNames() return; } - uint32 count = 1; + _scriptNamesStore.reserve(result->GetRowCount() + 1); do { _scriptNamesStore.push_back((*result)[0].GetString()); - ++count; } while (result->NextRow()); std::sort(_scriptNamesStore.begin(), _scriptNamesStore.end()); - LOG_INFO("server.loading", ">> Loaded %d Script Names in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + LOG_INFO("server.loading", ">> Loaded " SZFMTD " ScriptNames in %u ms", _scriptNamesStore.size(), GetMSTimeDiffToNow(oldMSTime)); LOG_INFO("server.loading", " "); } @@ -8762,15 +8779,15 @@ std::string const& ObjectMgr::GetScriptName(uint32 id) const return (id < _scriptNamesStore.size()) ? _scriptNamesStore[id] : empty; } -uint32 ObjectMgr::GetScriptId(const char* name) +uint32 ObjectMgr::GetScriptId(std::string const& name) { // use binary search to find the script name in the sorted vector // assume "" is the first element - if (!name) + if (name.empty()) return 0; ScriptNameContainer::const_iterator itr = std::lower_bound(_scriptNamesStore.begin(), _scriptNamesStore.end(), name); - if (itr == _scriptNamesStore.end() || *itr != name) + if (itr == _scriptNamesStore.end() || (*itr != name)) return 0; return uint32(itr - _scriptNamesStore.begin()); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 4fb01e6d0..aef51af8a 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1317,7 +1317,7 @@ public: void LoadScriptNames(); ScriptNameContainer& GetScriptNames() { return _scriptNamesStore; } [[nodiscard]] std::string const& GetScriptName(uint32 id) const; - uint32 GetScriptId(const char* name); + uint32 GetScriptId(std::string const& name); [[nodiscard]] SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const { diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index c46f3f8c6..62c9eb705 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -150,13 +150,13 @@ void WorldSession::HandleGossipSelectOptionOpcode(WorldPacket& recv_data) if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - if ((unit && unit->GetCreatureTemplate()->ScriptID != unit->LastUsedScriptID) || (go && go->GetGOInfo()->ScriptId != go->LastUsedScriptID)) + if ((unit && unit->GetScriptId() != unit->LastUsedScriptID) || (go && go->GetScriptId() != go->LastUsedScriptID)) { LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - Script reloaded while in use, ignoring and set new scipt id"); if (unit) - unit->LastUsedScriptID = unit->GetCreatureTemplate()->ScriptID; + unit->LastUsedScriptID = unit->GetScriptId(); if (go) - go->LastUsedScriptID = go->GetGOInfo()->ScriptId; + go->LastUsedScriptID = go->GetScriptId(); _player->PlayerTalkClass->SendCloseGossip(); return; }