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__