From 9a8a74c2ad440686fbb6f6bfd048716fbb6a76e8 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 11 Feb 2011 23:17:39 +0300 Subject: [PATCH] [11138] Make sure GameEvent/Pool systems work with static instance object guids * Pool System for correct full power work in instance need implement MapPersistentState local pool system state for instanceable maps. Unit this not implemented pool system must avoid creating/despawn/touch instance map objects. Currently this work because instance map object use dynamic generated guids and "invisible" for Pool System, with explcitly forbiden for it spawn directly new objects. Code changes add explicit checks for preserve this way work for time when instance object will use static guids. When local pool state storing in persistent state this protection checks will possible drop. Non-instanced working cases converted in local map object search calls. * GameEvent Systems currently have code that work correctly only with objects at non-instanced maps by same reasons as Pool System. But in different Pool System case game event activate/deactivate expected applied to _all_ object copies in all existed instanceable map copies. Code modified for work in expected way. Direct spawn disabled for instanceable maps until swith to static guids. Despawn code will make affect only for non-instanceavble maps unit swithc to static guids as-is. This is preserve current code working result. * Convert last case usage global creature search in aura code to map local case. Player case also possible not need now after including caster damage/heal mods part to aura base damage/heal. In any cases player case preserved in old way work. NOTE: this last places dependent from global creature/gameobject guid search so look like this make possible start direct work to switch instances use static guids instead dynamic generated --- src/game/Creature.cpp | 53 ++++++++++++++++++++++ src/game/Creature.h | 5 +++ src/game/GameEventMgr.cpp | 93 ++++++++++++++++++--------------------- src/game/GameObject.cpp | 55 ++++++++++++++++++++++- src/game/GameObject.h | 6 +++ src/game/PoolManager.cpp | 74 ++++++++++++++++++++++++++----- src/game/SpellAuras.cpp | 8 ++-- src/shared/revision_nr.h | 2 +- 8 files changed, 231 insertions(+), 65 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 238f2c3c3..0f167bfc3 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -2407,3 +2407,56 @@ void Creature::FillGuidsListFromThreatList( std::vector& guids, uint for (ThreatList::const_iterator itr = threats.begin(); maxamount && itr != threats.end(); ++itr, --maxamount) guids.push_back((*itr)->getUnitGuid()); } + +struct AddCaretureToRemoveListInMapsWorker +{ + AddCaretureToRemoveListInMapsWorker(ObjectGuid guid) : i_guid(guid) {} + + void operator() (Map* map) + { + if (Creature* pCreature = map->GetCreature(i_guid)) + pCreature->AddObjectToRemoveList(); + } + + ObjectGuid i_guid; +}; + +void Creature::AddToRemoveListInMaps(uint32 db_guid, CreatureData const* data) +{ + AddCaretureToRemoveListInMapsWorker worker(ObjectGuid(HIGHGUID_UNIT, data->id, db_guid)); + sMapMgr.DoForAllMapsWithMapId(data->mapid, worker); +} + +struct SpawnCreatureInMapsWorker +{ + SpawnCreatureInMapsWorker(uint32 guid, CreatureData const* data) + : i_guid(guid), i_data(data) {} + + void operator() (Map* map) + { + // We use spawn coords to spawn + if (map->IsLoaded(i_data->posX, i_data->posY)) + { + Creature* pCreature = new Creature; + //DEBUG_LOG("Spawning creature %u",*itr); + if (!pCreature->LoadFromDB(i_guid, map)) + { + delete pCreature; + } + else + { + map->Add(pCreature); + } + } + } + + uint32 i_guid; + CreatureData const* i_data; +}; + +void Creature::SpawnInMaps(uint32 db_guid, CreatureData const* data) +{ + SpawnCreatureInMapsWorker worker(db_guid, data); + sMapMgr.DoForAllMapsWithMapId(data->mapid, worker); +} + diff --git a/src/game/Creature.h b/src/game/Creature.h index 9233a091c..df31120d0 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -610,6 +610,11 @@ class MANGOS_DLL_SPEC Creature : public Unit float GetRespawnRadius() const { return m_respawnradius; } void SetRespawnRadius(float dist) { m_respawnradius = dist; } + // Functions spawn/remove creature with DB guid in all loaded map copies (if point grid loaded in map) + // FIXME: it will work for for instanceable maps only after switch to use static guids) + static void AddToRemoveListInMaps(uint32 db_guid, CreatureData const* data); + static void SpawnInMaps(uint32 db_guid, CreatureData const* data); + void StartGroupLoot(Group* group, uint32 timer); void SendZoneUnderAttackMessage(Player* attacker); diff --git a/src/game/GameEventMgr.cpp b/src/game/GameEventMgr.cpp index 4c97869cf..3225dc074 100644 --- a/src/game/GameEventMgr.cpp +++ b/src/game/GameEventMgr.cpp @@ -710,24 +710,12 @@ void GameEventMgr::GameEventSpawn(int16 event_id) sObjectMgr.AddCreatureToGrid(*itr, data); - // Spawn if necessary (loaded grids only) - if (Map* map = const_cast(sMapMgr.FindMap(data->mapid))) - { - // We use spawn coords to spawn - if (!map->Instanceable() && map->IsLoaded(data->posX,data->posY)) - { - Creature* pCreature = new Creature; - //DEBUG_LOG("Spawning creature %u",*itr); - if (!pCreature->LoadFromDB(*itr, map)) - { - delete pCreature; - } - else - { - map->Add(pCreature); - } - } - } + // FIXME: gameevent system can't work correctly in instanceable maps while object sin instances use dynamic guids + // Current code prevent wrong way work until switch to use static guids for instance objects + MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); + + if (mapEntry && !mapEntry->Instanceable()) + Creature::SpawnInMaps(*itr, data); } } @@ -757,26 +745,12 @@ void GameEventMgr::GameEventSpawn(int16 event_id) sObjectMgr.AddGameobjectToGrid(*itr, data); - // Spawn if necessary (loaded grids only) - // this base map checked as non-instanced and then only existing - if (Map* map = const_cast(sMapMgr.FindMap(data->mapid))) - { - // We use current coords to unspawn, not spawn coords since creature can have changed grid - if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY)) - { - GameObject* pGameobject = new GameObject; - //DEBUG_LOG("Spawning gameobject %u", *itr); - if (!pGameobject->LoadFromDB(*itr, map)) - { - delete pGameobject; - } - else - { - if(pGameobject->isSpawnedByDefault()) - map->Add(pGameobject); - } - } - } + // FIXME: gameevent system can't work correctly in instanceable maps while object sin instances use dynamic guids + // Current code prevent wrong way work until switch to use static guids for instance objects + MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); + + if (mapEntry && !mapEntry->Instanceable()) + GameObject::SpawnInMaps(*itr, data); } } @@ -819,10 +793,11 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) } } + // Remove spawn data sObjectMgr.RemoveCreatureFromGrid(*itr, data); - if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, *itr))) - pCreature->AddObjectToRemoveList(); + // Remove spawned cases + Creature::AddToRemoveListInMaps(*itr, data); } } @@ -848,10 +823,11 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) } } + // Remove spawn data sObjectMgr.RemoveGameobjectFromGrid(*itr, data); - if( GameObject* pGameobject = ObjectAccessor::GetGameObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, *itr)) ) - pGameobject->AddObjectToRemoveList(); + // Remove spawned cases + GameObject::AddToRemoveListInMaps(*itr, data); } } @@ -894,6 +870,29 @@ GameEventCreatureData const* GameEventMgr::GetCreatureUpdateDataForActiveEvent(u return NULL; } +struct GameEventUpdateCreatureDataInMapsWorker +{ + GameEventUpdateCreatureDataInMapsWorker(ObjectGuid guid, CreatureData const* data, GameEventCreatureData* event_data, bool activate) + : i_guid(guid), i_data(data), i_event_data(event_data), i_activate(activate) {} + + void operator() (Map* map) + { + if (Creature* pCreature = map->GetCreature(i_guid)) + { + pCreature->UpdateEntry(i_data->id, TEAM_NONE, i_data, i_activate ? i_event_data : NULL); + + // spells not casted for event remove case (sent NULL into update), do it + if (!i_activate) + pCreature->ApplyGameEventSpells(i_event_data, false); + } + } + + ObjectGuid i_guid; + CreatureData const* i_data; + GameEventCreatureData* i_event_data; + bool i_activate; +}; + void GameEventMgr::UpdateCreatureData(int16 event_id, bool activate) { for(GameEventCreatureDataList::iterator itr = mGameEventCreatureData[event_id].begin();itr != mGameEventCreatureData[event_id].end();++itr) @@ -904,14 +903,8 @@ void GameEventMgr::UpdateCreatureData(int16 event_id, bool activate) continue; // Update if spawned - if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, itr->first))) - { - pCreature->UpdateEntry(data->id, TEAM_NONE, data, activate ? &itr->second : NULL); - - // spells not casted for event remove case (sent NULL into update), do it - if (!activate) - pCreature->ApplyGameEventSpells(&itr->second, false); - } + GameEventUpdateCreatureDataInMapsWorker worker(ObjectGuid(HIGHGUID_UNIT, data->id, itr->first), data, &itr->second, activate); + sMapMgr.DoForAllMapsWithMapId(data->mapid, worker); } } diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 2b0d13ef2..52c6294ae 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -1701,4 +1701,57 @@ bool GameObject::IsInSkillupList(Player* player) const void GameObject::AddToSkillupList(Player* player) { m_SkillupSet.insert(player->GetObjectGuid()); -} \ No newline at end of file +} + +struct AddGameObjectToRemoveListInMapsWorker +{ + AddGameObjectToRemoveListInMapsWorker(ObjectGuid guid) : i_guid(guid) {} + + void operator() (Map* map) + { + if (GameObject* pGameobject = map->GetGameObject(i_guid)) + pGameobject->AddObjectToRemoveList(); + } + + ObjectGuid i_guid; +}; + +void GameObject::AddToRemoveListInMaps(uint32 db_guid, GameObjectData const* data) +{ + AddGameObjectToRemoveListInMapsWorker worker(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, db_guid)); + sMapMgr.DoForAllMapsWithMapId(data->mapid, worker); +} + +struct SpawnGameObjectInMapsWorker +{ + SpawnGameObjectInMapsWorker(uint32 guid, GameObjectData const* data) + : i_guid(guid), i_data(data) {} + + void operator() (Map* map) + { + // Spawn if necessary (loaded grids only) + if (map->IsLoaded(i_data->posX, i_data->posY)) + { + GameObject* pGameobject = new GameObject; + //DEBUG_LOG("Spawning gameobject %u", *itr); + if (!pGameobject->LoadFromDB(i_guid, map)) + { + delete pGameobject; + } + else + { + if (pGameobject->isSpawnedByDefault()) + map->Add(pGameobject); + } + } + } + + uint32 i_guid; + GameObjectData const* i_data; +}; + +void GameObject::SpawnInMaps(uint32 db_guid, GameObjectData const* data) +{ + SpawnGameObjectInMapsWorker worker(db_guid, data); + sMapMgr.DoForAllMapsWithMapId(data->mapid, worker); +} diff --git a/src/game/GameObject.h b/src/game/GameObject.h index a5a0dba0d..eda4a2b57 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -656,6 +656,12 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject uint32 GetRespawnDelay() const { return m_respawnDelayTime; } void Refresh(); void Delete(); + + // Functions spawn/remove gameobject with DB guid in all loaded map copies (if point grid loaded in map) + // FIXME: it will work for for instanceable maps only after switch to use static guids) + static void AddToRemoveListInMaps(uint32 db_guid, GameObjectData const* data); + static void SpawnInMaps(uint32 db_guid, GameObjectData const* data); + void getFishLoot(Loot *loot, Player* loot_owner); GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); } void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } diff --git a/src/game/PoolManager.cpp b/src/game/PoolManager.cpp index 9b57d0c91..803b82354 100644 --- a/src/game/PoolManager.cpp +++ b/src/game/PoolManager.cpp @@ -265,8 +265,20 @@ void PoolGroup::Despawn1Object(uint32 guid) { sObjectMgr.RemoveCreatureFromGrid(guid, data); - if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, guid))) - pCreature->AddObjectToRemoveList(); + // FIXME: pool system must have local state for each instanced map copy + // Current code preserve existed single state for all instanced map copies way + // specially because pool system not spawn object in instanceable maps + MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); + + // temporary limit pool system full power work to continents + if (mapEntry && !mapEntry->Instanceable()) + { + if (Map* map = const_cast(sMapMgr.FindMap(data->mapid))) + { + if (Creature* pCreature = map->GetCreature(ObjectGuid(HIGHGUID_UNIT, data->id, guid))) + pCreature->AddObjectToRemoveList(); + } + } } } @@ -278,8 +290,20 @@ void PoolGroup::Despawn1Object(uint32 guid) { sObjectMgr.RemoveGameobjectFromGrid(guid, data); - if (GameObject* pGameobject = ObjectAccessor::GetGameObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, guid))) - pGameobject->AddObjectToRemoveList(); + // FIXME: pool system must have local state for each instanced map copy + // Current code preserve existed single state for all instanced map copies way + // specially because pool system not spawn object in instanceable maps + MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); + + // temporary limit pool system full power work to continents + if (mapEntry && !mapEntry->Instanceable()) + { + if (Map* map = const_cast(sMapMgr.FindMap(data->mapid))) + { + if (GameObject* pGameobject = map->GetGameObject(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, guid))) + pGameobject->AddObjectToRemoveList(); + } + } } } @@ -370,7 +394,8 @@ void PoolGroup::Spawn1Object(PoolObject* obj, bool instantly) MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); - // temporary limit pool system full power work to continents + // FIXME: pool system must have local state for each instanced map copy + // Current code preserve existed single state for all instanced map copies way if (mapEntry && !mapEntry->Instanceable()) { // Spawn if necessary (loaded grids only) @@ -417,7 +442,8 @@ void PoolGroup::Spawn1Object(PoolObject* obj, bool instantly) MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); - // temporary limit pool system full power work to continents + // FIXME: pool system must have local state for each instanced map copy + // Current code preserve existed single state for all instanced map copies way if (mapEntry && !mapEntry->Instanceable()) { // Spawn if necessary (loaded grids only) @@ -471,8 +497,22 @@ template <> void PoolGroup::ReSpawn1Object(PoolObject* obj) { if (CreatureData const* data = sObjectMgr.GetCreatureData(obj->guid)) - if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, obj->guid))) - pCreature->GetMap()->Add(pCreature); + { + // FIXME: pool system must have local state for each instanced map copy + // Current code preserve existed single state for all instanced map copies way + // specially because pool system not spawn object in instanceable maps + MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); + + // temporary limit pool system full power work to continents + if (mapEntry && !mapEntry->Instanceable()) + { + if (Map* map = const_cast(sMapMgr.FindMap(data->mapid))) + { + if (Creature* pCreature = map->GetCreature(ObjectGuid(HIGHGUID_UNIT, data->id, obj->guid))) + pCreature->GetMap()->Add(pCreature); + } + } + } } // Method that does the respawn job on the specified gameobject @@ -480,8 +520,22 @@ template <> void PoolGroup::ReSpawn1Object(PoolObject* obj) { if (GameObjectData const* data = sObjectMgr.GetGOData(obj->guid)) - if (GameObject* pGameobject = ObjectAccessor::GetGameObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, obj->guid))) - pGameobject->GetMap()->Add(pGameobject); + { + // FIXME: pool system must have local state for each instanced map copy + // Current code preserve existed single state for all instanced map copies way + // specially because pool system not spawn object in instanceable maps + MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); + + // temporary limit pool system full power work to continents + if (mapEntry && !mapEntry->Instanceable()) + { + if (Map* map = const_cast(sMapMgr.FindMap(data->mapid))) + { + if (GameObject* pGameobject = map->GetGameObject(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, obj->guid))) + pGameobject->GetMap()->Add(pGameobject); + } + } + } } // Nothing to do for a child Pool diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index bcedb0158..224cc2e7b 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -8607,10 +8607,12 @@ Unit* SpellAuraHolder::GetCaster() const if(GetCasterGuid() == m_target->GetObjectGuid()) return m_target; - //return ObjectAccessor::GetUnit(*m_target,m_caster_guid); //must return caster even if it's in another grid/map - Unit *unit = ObjectAccessor::GetUnitInWorld(*m_target, m_casterGuid); - return unit && unit->IsInWorld() ? unit : NULL; + if (m_casterGuid.IsPlayer()) + if (Player* caster = sObjectMgr.GetPlayer(m_casterGuid)) + return caster->IsInWorld() ? caster : NULL; + + return m_target->IsInWorld() ? m_target->GetMap()->GetCreature(m_casterGuid) : NULL; } bool SpellAuraHolder::IsWeaponBuffCoexistableWith(SpellAuraHolder* ref) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e86841716..a7b5b960e 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11137" + #define REVISION_NR "11138" #endif // __REVISION_NR_H__