mirror of
https://github.com/mangosfour/server.git
synced 2025-12-12 10:37:03 +00:00
[9392] Update creature/gameobject pool at despawn instead spawn prepare.
This let solve problem with not despawned creature/gameobject at pool update in case when related grid not loaded. Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
parent
941b2edb10
commit
b2718378ef
6 changed files with 93 additions and 41 deletions
|
|
@ -374,11 +374,7 @@ void Creature::Update(uint32 diff)
|
||||||
//Call AI respawn virtual function
|
//Call AI respawn virtual function
|
||||||
i_AI->JustRespawned();
|
i_AI->JustRespawned();
|
||||||
|
|
||||||
uint16 poolid = GetDBTableGUIDLow() ? sPoolMgr.IsPartOfAPool<Creature>(GetDBTableGUIDLow()) : 0;
|
GetMap()->Add(this);
|
||||||
if (poolid)
|
|
||||||
sPoolMgr.UpdatePool<Creature>(poolid, GetDBTableGUIDLow());
|
|
||||||
else
|
|
||||||
GetMap()->Add(this);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -389,8 +385,16 @@ void Creature::Update(uint32 diff)
|
||||||
|
|
||||||
if( m_deathTimer <= diff )
|
if( m_deathTimer <= diff )
|
||||||
{
|
{
|
||||||
RemoveCorpse();
|
// since pool system can fail to roll unspawned object, this one can remain spawned, so must set respawn nevertheless
|
||||||
DEBUG_LOG("Removing corpse... %u ", GetEntry());
|
uint16 poolid = GetDBTableGUIDLow() ? sPoolMgr.IsPartOfAPool<Creature>(GetDBTableGUIDLow()) : 0;
|
||||||
|
if (poolid)
|
||||||
|
sPoolMgr.UpdatePool<Creature>(poolid, GetDBTableGUIDLow());
|
||||||
|
|
||||||
|
if (IsInWorld()) // can be despawned by update pool
|
||||||
|
{
|
||||||
|
RemoveCorpse();
|
||||||
|
DEBUG_LOG("Removing corpse... %u ", GetEntry());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -419,8 +423,19 @@ void Creature::Update(uint32 diff)
|
||||||
{
|
{
|
||||||
if( m_deathTimer <= diff )
|
if( m_deathTimer <= diff )
|
||||||
{
|
{
|
||||||
RemoveCorpse();
|
// since pool system can fail to roll unspawned object, this one can remain spawned, so must set respawn nevertheless
|
||||||
DEBUG_LOG("Removing alive corpse... %u ", GetEntry());
|
uint16 poolid = GetDBTableGUIDLow() ? sPoolMgr.IsPartOfAPool<Creature>(GetDBTableGUIDLow()) : 0;
|
||||||
|
|
||||||
|
if (poolid)
|
||||||
|
sPoolMgr.UpdatePool<Creature>(poolid, GetDBTableGUIDLow());
|
||||||
|
|
||||||
|
if (IsInWorld()) // can be despawned by update pool
|
||||||
|
{
|
||||||
|
RemoveCorpse();
|
||||||
|
DEBUG_LOG("Removing alive corpse... %u ", GetEntry());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -574,7 +574,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin();itr != mGameEventPoolIds[internal_event_id].end();++itr)
|
for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin();itr != mGameEventPoolIds[internal_event_id].end();++itr)
|
||||||
sPoolMgr.SpawnPool(*itr);
|
sPoolMgr.SpawnPool(*itr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameEventMgr::GameEventUnspawn(int16 event_id)
|
void GameEventMgr::GameEventUnspawn(int16 event_id)
|
||||||
|
|
|
||||||
|
|
@ -256,11 +256,7 @@ void GameObject::Update(uint32 /*p_time*/)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// respawn timer
|
// respawn timer
|
||||||
uint16 poolid = GetDBTableGUIDLow() ? sPoolMgr.IsPartOfAPool<GameObject>(GetDBTableGUIDLow()) : 0;
|
GetMap()->Add(this);
|
||||||
if (poolid)
|
|
||||||
sPoolMgr.UpdatePool<GameObject>(poolid, GetDBTableGUIDLow());
|
|
||||||
else
|
|
||||||
GetMap()->Add(this);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -445,13 +441,20 @@ void GameObject::Update(uint32 /*p_time*/)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// since pool system can fail to roll unspawned object, this one can remain spawned, so must set respawn nevertheless
|
||||||
m_respawnTime = time(NULL) + m_respawnDelayTime;
|
m_respawnTime = time(NULL) + m_respawnDelayTime;
|
||||||
|
|
||||||
// if option not set then object will be saved at grid unload
|
// if option not set then object will be saved at grid unload
|
||||||
if(sWorld.getConfig(CONFIG_BOOL_SAVE_RESPAWN_TIME_IMMEDIATLY))
|
if(sWorld.getConfig(CONFIG_BOOL_SAVE_RESPAWN_TIME_IMMEDIATLY))
|
||||||
SaveRespawnTime();
|
SaveRespawnTime();
|
||||||
|
|
||||||
UpdateObjectVisibility();
|
// if part of pool, let pool system schedule new spawn instead of just scheduling respawn
|
||||||
|
if(uint16 poolid = GetDBTableGUIDLow() ? sPoolMgr.IsPartOfAPool<GameObject>(GetDBTableGUIDLow()) : 0)
|
||||||
|
sPoolMgr.UpdatePool<GameObject>(poolid, GetDBTableGUIDLow());
|
||||||
|
|
||||||
|
// can be not in world at pool despawn
|
||||||
|
if (IsInWorld())
|
||||||
|
UpdateObjectVisibility();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include "ProgressBar.h"
|
#include "ProgressBar.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "MapManager.h"
|
#include "MapManager.h"
|
||||||
|
#include "World.h"
|
||||||
#include "Policies/SingletonImp.h"
|
#include "Policies/SingletonImp.h"
|
||||||
|
|
||||||
INSTANTIATE_SINGLETON_1(PoolManager);
|
INSTANTIATE_SINGLETON_1(PoolManager);
|
||||||
|
|
@ -253,7 +254,7 @@ void PoolGroup<Pool>::RemoveOneRelation(uint16 child_pool_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void PoolGroup<T>::SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom)
|
void PoolGroup<T>::SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom, bool instantly)
|
||||||
{
|
{
|
||||||
uint32 lastDespawned = 0;
|
uint32 lastDespawned = 0;
|
||||||
int count = limit - spawns.GetSpawnedObjects(poolId);
|
int count = limit - spawns.GetSpawnedObjects(poolId);
|
||||||
|
|
@ -283,7 +284,7 @@ void PoolGroup<T>::SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 tri
|
||||||
}
|
}
|
||||||
|
|
||||||
spawns.AddSpawn<T>(obj->guid,poolId);
|
spawns.AddSpawn<T>(obj->guid,poolId);
|
||||||
Spawn1Object(obj);
|
Spawn1Object(obj, instantly);
|
||||||
|
|
||||||
if (triggerFrom)
|
if (triggerFrom)
|
||||||
{
|
{
|
||||||
|
|
@ -297,7 +298,7 @@ void PoolGroup<T>::SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 tri
|
||||||
|
|
||||||
// Method that is actualy doing the spawn job on 1 creature
|
// Method that is actualy doing the spawn job on 1 creature
|
||||||
template <>
|
template <>
|
||||||
void PoolGroup<Creature>::Spawn1Object(PoolObject* obj)
|
void PoolGroup<Creature>::Spawn1Object(PoolObject* obj, bool instantly)
|
||||||
{
|
{
|
||||||
if (CreatureData const* data = sObjectMgr.GetCreatureData(obj->guid))
|
if (CreatureData const* data = sObjectMgr.GetCreatureData(obj->guid))
|
||||||
{
|
{
|
||||||
|
|
@ -305,7 +306,7 @@ void PoolGroup<Creature>::Spawn1Object(PoolObject* obj)
|
||||||
|
|
||||||
// Spawn if necessary (loaded grids only)
|
// Spawn if necessary (loaded grids only)
|
||||||
Map* map = const_cast<Map*>(sMapMgr.CreateBaseMap(data->mapid));
|
Map* map = const_cast<Map*>(sMapMgr.CreateBaseMap(data->mapid));
|
||||||
// We use spawn coords to spawn
|
// We use spawn coords to spawn (avoid work for instances until implemented support)
|
||||||
if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
|
if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
|
||||||
{
|
{
|
||||||
Creature* pCreature = new Creature;
|
Creature* pCreature = new Creature;
|
||||||
|
|
@ -316,14 +317,28 @@ void PoolGroup<Creature>::Spawn1Object(PoolObject* obj)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
// if new spawn replaces a just despawned creature, not instantly spawn but set respawn timer
|
||||||
|
if(!instantly)
|
||||||
|
{
|
||||||
|
pCreature->SetRespawnTime( pCreature->GetRespawnDelay() );
|
||||||
|
if (sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY) || pCreature->isWorldBoss())
|
||||||
|
pCreature->SaveRespawnTime();
|
||||||
|
}
|
||||||
map->Add(pCreature);
|
map->Add(pCreature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// for not loaded grid just update respawn time (avoid work for instances until implemented support)
|
||||||
|
else if(!map->Instanceable() && !instantly)
|
||||||
|
{
|
||||||
|
sObjectMgr.SaveCreatureRespawnTime(obj->guid,map->GetInstanceId(),time(NULL) + data->spawntimesecs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same for 1 gameobject
|
// Same for 1 gameobject
|
||||||
template <>
|
template <>
|
||||||
void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj)
|
void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj, bool instantly)
|
||||||
{
|
{
|
||||||
if (GameObjectData const* data = sObjectMgr.GetGOData(obj->guid))
|
if (GameObjectData const* data = sObjectMgr.GetGOData(obj->guid))
|
||||||
{
|
{
|
||||||
|
|
@ -332,6 +347,7 @@ void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj)
|
||||||
// this base map checked as non-instanced and then only existed
|
// this base map checked as non-instanced and then only existed
|
||||||
Map* map = const_cast<Map*>(sMapMgr.CreateBaseMap(data->mapid));
|
Map* map = const_cast<Map*>(sMapMgr.CreateBaseMap(data->mapid));
|
||||||
// We use current coords to unspawn, not spawn coords since creature can have changed grid
|
// We use current coords to unspawn, not spawn coords since creature can have changed grid
|
||||||
|
// (avoid work for instances until implemented support)
|
||||||
if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
|
if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
|
||||||
{
|
{
|
||||||
GameObject* pGameobject = new GameObject;
|
GameObject* pGameobject = new GameObject;
|
||||||
|
|
@ -344,17 +360,33 @@ void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (pGameobject->isSpawnedByDefault())
|
if (pGameobject->isSpawnedByDefault())
|
||||||
|
{
|
||||||
|
// if new spawn replaces a just despawned object, not instantly spawn but set respawn timer
|
||||||
|
if(!instantly)
|
||||||
|
{
|
||||||
|
pGameobject->SetRespawnTime( pGameobject->GetRespawnDelay() );
|
||||||
|
if (sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY))
|
||||||
|
pGameobject->SaveRespawnTime();
|
||||||
|
}
|
||||||
map->Add(pGameobject);
|
map->Add(pGameobject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// for not loaded grid just update respawn time (avoid work for instances until implemented support)
|
||||||
|
else if(!map->Instanceable() && !instantly)
|
||||||
|
{
|
||||||
|
// for spawned by default object only
|
||||||
|
if (data->spawntimesecs >= 0)
|
||||||
|
sObjectMgr.SaveGORespawnTime(obj->guid,map->GetInstanceId(),time(NULL) + data->spawntimesecs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same for 1 pool
|
// Same for 1 pool
|
||||||
template <>
|
template <>
|
||||||
void PoolGroup<Pool>::Spawn1Object(PoolObject* obj)
|
void PoolGroup<Pool>::Spawn1Object(PoolObject* obj, bool instantly)
|
||||||
{
|
{
|
||||||
sPoolMgr.SpawnPool(obj->guid);
|
sPoolMgr.SpawnPool(obj->guid, instantly);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method that does the respawn job on the specified creature
|
// Method that does the respawn job on the specified creature
|
||||||
|
|
@ -676,7 +708,7 @@ void PoolManager::Initialize()
|
||||||
sLog.outErrorDb("Pool Id (%u) has all creatures or gameobjects with explicit chance sum <>100 and no equal chance defined. The pool system cannot pick one to spawn.", pool_entry);
|
sLog.outErrorDb("Pool Id (%u) has all creatures or gameobjects with explicit chance sum <>100 and no equal chance defined. The pool system cannot pick one to spawn.", pool_entry);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SpawnPool(pool_entry);
|
SpawnPool(pool_entry, true);
|
||||||
count++;
|
count++;
|
||||||
} while (result->NextRow());
|
} while (result->NextRow());
|
||||||
delete result;
|
delete result;
|
||||||
|
|
@ -688,35 +720,37 @@ void PoolManager::Initialize()
|
||||||
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
|
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
|
||||||
// If it's same, the creature is respawned only (added back to map)
|
// If it's same, the creature is respawned only (added back to map)
|
||||||
template<>
|
template<>
|
||||||
void PoolManager::SpawnPool<Creature>(uint16 pool_id, uint32 db_guid)
|
void PoolManager::SpawnPoolGroup<Creature>(uint16 pool_id, uint32 db_guid, bool instantly)
|
||||||
{
|
{
|
||||||
if (!mPoolCreatureGroups[pool_id].isEmpty())
|
if (!mPoolCreatureGroups[pool_id].isEmpty())
|
||||||
mPoolCreatureGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid);
|
mPoolCreatureGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid, instantly);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
|
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
|
||||||
// If it's same, the gameobject is respawned only (added back to map)
|
// If it's same, the gameobject is respawned only (added back to map)
|
||||||
template<>
|
template<>
|
||||||
void PoolManager::SpawnPool<GameObject>(uint16 pool_id, uint32 db_guid)
|
void PoolManager::SpawnPoolGroup<GameObject>(uint16 pool_id, uint32 db_guid, bool instantly)
|
||||||
{
|
{
|
||||||
if (!mPoolGameobjectGroups[pool_id].isEmpty())
|
if (!mPoolGameobjectGroups[pool_id].isEmpty())
|
||||||
mPoolGameobjectGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid);
|
mPoolGameobjectGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid, instantly);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
|
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
|
||||||
// If it's same, the pool is respawned only
|
// If it's same, the pool is respawned only
|
||||||
template<>
|
template<>
|
||||||
void PoolManager::SpawnPool<Pool>(uint16 pool_id, uint32 sub_pool_id)
|
void PoolManager::SpawnPoolGroup<Pool>(uint16 pool_id, uint32 sub_pool_id, bool instantly)
|
||||||
{
|
{
|
||||||
if (!mPoolPoolGroups[pool_id].isEmpty())
|
if (!mPoolPoolGroups[pool_id].isEmpty())
|
||||||
mPoolPoolGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, sub_pool_id);
|
mPoolPoolGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, sub_pool_id, instantly);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoolManager::SpawnPool( uint16 pool_id )
|
/*!
|
||||||
|
\param instantly defines if (leaf-)objects are spawned instantly or with fresh respawn timer */
|
||||||
|
void PoolManager::SpawnPool(uint16 pool_id, bool instantly)
|
||||||
{
|
{
|
||||||
SpawnPool<Pool>(pool_id, 0);
|
SpawnPoolGroup<Pool>(pool_id, 0, instantly);
|
||||||
SpawnPool<GameObject>(pool_id, 0);
|
SpawnPoolGroup<GameObject>(pool_id, 0, instantly);
|
||||||
SpawnPool<Creature>(pool_id, 0);
|
SpawnPoolGroup<Creature>(pool_id, 0, instantly);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call to despawn a pool, all gameobjects/creatures in this pool are removed
|
// Call to despawn a pool, all gameobjects/creatures in this pool are removed
|
||||||
|
|
@ -748,9 +782,9 @@ template<typename T>
|
||||||
void PoolManager::UpdatePool(uint16 pool_id, uint32 db_guid_or_pool_id)
|
void PoolManager::UpdatePool(uint16 pool_id, uint32 db_guid_or_pool_id)
|
||||||
{
|
{
|
||||||
if (uint16 motherpoolid = IsPartOfAPool<Pool>(pool_id))
|
if (uint16 motherpoolid = IsPartOfAPool<Pool>(pool_id))
|
||||||
SpawnPool<Pool>(motherpoolid, pool_id);
|
SpawnPoolGroup<Pool>(motherpoolid, pool_id, false);
|
||||||
else
|
else
|
||||||
SpawnPool<T>(pool_id, db_guid_or_pool_id);
|
SpawnPoolGroup<T>(pool_id, db_guid_or_pool_id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
template void PoolManager::UpdatePool<Pool>(uint16 pool_id, uint32 db_guid_or_pool_id);
|
template void PoolManager::UpdatePool<Pool>(uint16 pool_id, uint32 db_guid_or_pool_id);
|
||||||
|
|
|
||||||
|
|
@ -76,9 +76,9 @@ class PoolGroup
|
||||||
PoolObject* RollOne(SpawnedPoolData& spawns, uint32 triggerFrom);
|
PoolObject* RollOne(SpawnedPoolData& spawns, uint32 triggerFrom);
|
||||||
void DespawnObject(SpawnedPoolData& spawns, uint32 guid=0);
|
void DespawnObject(SpawnedPoolData& spawns, uint32 guid=0);
|
||||||
void Despawn1Object(uint32 guid);
|
void Despawn1Object(uint32 guid);
|
||||||
void SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom);
|
void SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom, bool instantly);
|
||||||
|
|
||||||
void Spawn1Object(PoolObject* obj);
|
void Spawn1Object(PoolObject* obj, bool instantly);
|
||||||
void ReSpawn1Object(PoolObject* obj);
|
void ReSpawn1Object(PoolObject* obj);
|
||||||
void RemoveOneRelation(uint16 child_pool_id);
|
void RemoveOneRelation(uint16 child_pool_id);
|
||||||
private:
|
private:
|
||||||
|
|
@ -104,7 +104,7 @@ class PoolManager
|
||||||
|
|
||||||
bool CheckPool(uint16 pool_id) const;
|
bool CheckPool(uint16 pool_id) const;
|
||||||
|
|
||||||
void SpawnPool(uint16 pool_id);
|
void SpawnPool(uint16 pool_id, bool instantly);
|
||||||
void DespawnPool(uint16 pool_id);
|
void DespawnPool(uint16 pool_id);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -112,7 +112,7 @@ class PoolManager
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void SpawnPool(uint16 pool_id, uint32 db_guid_or_pool_id);
|
void SpawnPoolGroup(uint16 pool_id, uint32 db_guid_or_pool_id, bool instantly);
|
||||||
|
|
||||||
uint16 max_pool_id;
|
uint16 max_pool_id;
|
||||||
typedef std::vector<PoolTemplateData> PoolTemplateDataMap;
|
typedef std::vector<PoolTemplateData> PoolTemplateDataMap;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "9391"
|
#define REVISION_NR "9392"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue