void MapPersistentStateManager::LoadGameobjectRespawnTimes() { // remove outdated data CharacterDatabase.DirectExecute("DELETE FROM gameobject_respawn WHERE respawntime <= UNIX_TIMESTAMP(NOW())"); uint32 count = 0; QueryResult *result = CharacterDatabase.Query("SELECT guid, respawntime, map, instance, resettime FROM gameobject_respawn LEFT JOIN instance ON instance = id"); if(!result) { barGoLink bar(1); bar.step(); sLog.outString(); sLog.outString(">> Loaded 0 gameobject respawn time."); return; } barGoLink bar((int)result->GetRowCount()); do { Field *fields = result->Fetch(); bar.step(); uint32 loguid = fields[0].GetUInt32(); uint64 respawn_time = fields[1].GetUInt64(); uint32 mapId = fields[2].GetUInt32(); uint32 instanceId = fields[3].GetUInt32(); time_t resetTime = (time_t)fields[4].GetUInt64(); GameObjectData const* data = sObjectMgr.GetGOData(loguid); if (!data) continue; if (mapId != data->mapid) continue; MapEntry const* mapEntry = sMapStore.LookupEntry(mapId); if (!mapEntry || (mapEntry->Instanceable() != (instanceId != 0))) continue; MapPersistentState* state = AddPersistentState(mapEntry, instanceId, resetTime, mapEntry->IsDungeon(), true); if (!state) continue; state->SetGORespawnTime(loguid, time_t(respawn_time)); ++count; } while (result->NextRow()); delete result; sLog.outString(">> Loaded %u gameobject respawn times", count); sLog.outString(); }
void PoolGroup<T>::DespawnObject(MapPersistentState& mapState, uint32 guid) { for (size_t i = 0; i < EqualChanced.size(); ++i) { // if spawned if (mapState.GetSpawnedPoolData().IsSpawnedObject<T>(EqualChanced[i].guid)) { // any or specially requested if (!guid || EqualChanced[i].guid == guid) { Despawn1Object(mapState, EqualChanced[i].guid); mapState.GetSpawnedPoolData().RemoveSpawn<T>(EqualChanced[i].guid, poolId); } } } for (size_t i = 0; i < ExplicitlyChanced.size(); ++i) { // spawned if (mapState.GetSpawnedPoolData().IsSpawnedObject<T>(ExplicitlyChanced[i].guid)) { // any or specially requested if (!guid || ExplicitlyChanced[i].guid == guid) { Despawn1Object(mapState, ExplicitlyChanced[i].guid); mapState.GetSpawnedPoolData().RemoveSpawn<T>(ExplicitlyChanced[i].guid, poolId); } } } }
/* - adding instance into manager - called from DungeonMap::Add, _LoadBoundInstances, LoadGroups */ MapPersistentState* MapPersistentStateManager::AddPersistentState(MapEntry const* mapEntry, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load /*=false*/, bool initPools /*= true*/, uint32 completedEncountersMask /*= 0*/) { if (MapPersistentState *old_save = GetPersistentState(mapEntry->MapID, instanceId)) return old_save; if (mapEntry->IsDungeon()) { if (!resetTime || resetTime < time(NULL)) { // initialize reset time // for normal instances if no creatures are killed the instance will reset in two hours if (mapEntry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL) resetTime = m_Scheduler.GetResetTimeFor(mapEntry->MapID, difficulty); else { resetTime = time(NULL) + 2 * HOUR; // normally this will be removed soon after in DungeonMap::Add, prevent error m_Scheduler.ScheduleReset(true, resetTime, DungeonResetEvent(RESET_EVENT_NORMAL_DUNGEON, mapEntry->MapID, difficulty, instanceId)); } } } DEBUG_LOG("MapPersistentStateManager::AddPersistentState: mapid = %d, instanceid = %d, reset time = '" UI64FMTD "', canRset = %u", mapEntry->MapID, instanceId, uint64(resetTime), canReset ? 1 : 0); MapPersistentState* state = NULL; if (mapEntry->IsDungeon() && instanceId) { DungeonPersistentState* dungeonState = new DungeonPersistentState(mapEntry->MapID, instanceId, difficulty, resetTime, canReset, completedEncountersMask); if (!load) dungeonState->SaveToDB(); state = dungeonState; } else if (mapEntry->IsBattleGroundOrArena()) state = new BattleGroundPersistentState(mapEntry->MapID, instanceId, difficulty); else if (!instanceId) state = new WorldPersistentState(mapEntry->MapID); else { sLog.outError("MapPersistentStateManager::AddPersistentState cannot create persistent state for mapid = %d, instanceid = %d, reset time = %ld, canReset = %u", mapEntry->MapID, instanceId, resetTime, canReset ? 1 : 0); return state; } if (state && instanceId) m_instanceSaveByInstanceId[instanceId] = state; else if (state && !instanceId) m_instanceSaveByMapId[mapEntry->MapID] = state; if (state && initPools) state->InitPools(); if (state) sWorldStateMgr.CreateInstanceState(mapEntry->MapID, instanceId); return state; }
void MapPersistentStateManager::InitWorldMaps() { MapPersistentState* state = nullptr; // need any from created for shared pool state for (uint32 mapid = 0; mapid < sMapStore.GetNumRows(); ++mapid) if (MapEntry const* entry = sMapStore.LookupEntry(mapid)) if (!entry->Instanceable()) state = AddPersistentState(entry, 0, REGULAR_DIFFICULTY, 0, false, true, false); if (state) state->InitPools(); }
/* - adding instance into manager - called from DungeonMap::Add, _LoadBoundInstances, LoadGroups */ MapPersistentState* MapPersistentStateManager::AddPersistentState(MapEntry const* mapEntry, uint32 instanceId, time_t resetTime, bool canReset, bool load /*=false*/, bool initPools /*= true*/) { if (MapPersistentState *old_save = GetPersistentState(mapEntry->MapID, instanceId)) return old_save; if (mapEntry->IsDungeon()) { if (!resetTime) { // initialize reset time // for normal instances if no creatures are killed the instance will reset in two hours if(mapEntry->map_type == MAP_RAID) resetTime = m_Scheduler.GetResetTimeFor(mapEntry->MapID); else { resetTime = time(NULL) + 2 * HOUR; // normally this will be removed soon after in DungeonMap::Add, prevent error m_Scheduler.ScheduleReset(true, resetTime, DungeonResetEvent(RESET_EVENT_NORMAL_DUNGEON, mapEntry->MapID, instanceId)); } } } DEBUG_LOG("MapPersistentStateManager::AddPersistentState: mapid = %d, instanceid = %d, reset time = %u, canRset = %u", mapEntry->MapID, instanceId, resetTime, canReset ? 1 : 0); MapPersistentState *state; if (mapEntry->IsDungeon()) { DungeonPersistentState* dungeonState = new DungeonPersistentState(mapEntry->MapID, instanceId, resetTime, canReset); if (!load) dungeonState->SaveToDB(); state = dungeonState; } else if (mapEntry->IsBattleGround()) state = new BattleGroundPersistentState(mapEntry->MapID, instanceId); else state = new WorldPersistentState(mapEntry->MapID); if (instanceId) m_instanceSaveByInstanceId[instanceId] = state; else m_instanceSaveByMapId[mapEntry->MapID] = state; if (initPools) state->InitPools(); return state; }
void PoolGroup<GameObject>::ReSpawn1Object(MapPersistentState& mapState, PoolObject* obj) { if (GameObjectData const* data = sObjectMgr.GetGOData(obj->guid)) { // for non-instanceable maps pool spawn can be at different map from provided mapState if (MapPersistentState* dataMapState = mapState.GetMapId() == data->mapid ? &mapState : sMapPersistentStateMgr.GetPersistentState(data->mapid, 0)) if (Map* dataMap = dataMapState->GetMap()) if (GameObject* pGameobject = dataMap->GetGameObject(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, obj->guid))) pGameobject->GetMap()->Add(pGameobject); } }
void PoolGroup<Creature>::ReSpawn1Object(MapPersistentState& mapState, PoolObject* obj) { if (CreatureData const* data = sObjectMgr.GetCreatureData(obj->guid)) { // for non-instanceable maps pool spawn can be at different map from provided mapState if (MapPersistentState* dataMapState = mapState.GetMapId() == data->mapid ? &mapState : sMapPersistentStateMgr.GetPersistentState(data->mapid, 0)) if (Map* dataMap = dataMapState->GetMap()) if (Creature* pCreature = dataMap->GetCreature(data->GetObjectGuid(obj->guid))) pCreature->GetMap()->Add(pCreature); } }
void PoolGroup<GameObject>::Despawn1Object(MapPersistentState& mapState, uint32 guid) { if (GameObjectData const* data = sObjectMgr.GetGOData(guid)) { // for non-instanceable maps pool spawn can be at different map from provided mapState if (MapPersistentState* dataMapState = mapState.GetMapId() == data->mapid ? &mapState : sMapPersistentStateMgr.GetPersistentState(data->mapid, 0)) { dataMapState->RemoveGameobjectFromGrid(guid, data); if (Map* dataMap = dataMapState->GetMap()) if (GameObject* pGameobject = dataMap->GetGameObject(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, guid))) pGameobject->AddObjectToRemoveList(); } } }
void PoolGroup<Creature>::Despawn1Object(MapPersistentState& mapState, uint32 guid) { if (CreatureData const* data = sObjectMgr.GetCreatureData(guid)) { // for non-instanceable maps pool spawn can be at different map from provided mapState if (MapPersistentState* dataMapState = mapState.GetMapId() == data->mapid ? &mapState : sMapPersistentStateMgr.GetPersistentState(data->mapid, 0)) { dataMapState->RemoveCreatureFromGrid(guid, data); if (Map* dataMap = dataMapState->GetMap()) if (Creature* pCreature = dataMap->GetCreature(data->GetObjectGuid(guid))) pCreature->AddObjectToRemoveList(); } } }
void PoolGroup<T>::SpawnObject(MapPersistentState& mapState, uint32 limit, uint32 triggerFrom, bool instantly) { SpawnedPoolData& spawns = mapState.GetSpawnedPoolData(); uint32 lastDespawned = 0; int count = limit - spawns.GetSpawnedObjects(poolId); // If triggered from some object respawn this object is still marked as spawned // and also counted into m_SpawnedPoolAmount so we need increase count to be // spawned by 1 if (triggerFrom) { if (spawns.IsSpawnedObject<T>(triggerFrom)) ++count; else triggerFrom = 0; } // This will try to spawn the rest of pool, not guaranteed for (int i = 0; i < count; ++i) { PoolObject* obj = RollOne(spawns, triggerFrom); if (!obj) continue; if (obj->guid == lastDespawned) continue; if (obj->guid == triggerFrom) { MANGOS_ASSERT(spawns.IsSpawnedObject<T>(obj->guid)); MANGOS_ASSERT(spawns.GetSpawnedObjects(poolId) > 0); ReSpawn1Object(mapState, obj); triggerFrom = 0; continue; } spawns.AddSpawn<T>(obj->guid, poolId); Spawn1Object(mapState, obj, instantly); if (triggerFrom) { // One spawn one despawn no count increase DespawnObject(mapState, triggerFrom); lastDespawned = triggerFrom; triggerFrom = 0; } } }
void PoolGroup<GameObject>::Spawn1Object(MapPersistentState& mapState, PoolObject* obj, bool instantly) { if (GameObjectData const* data = sObjectMgr.GetGOData(obj->guid)) { MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); // for non-instanceable maps pool spawn can be at different map from provided mapState if (MapPersistentState* dataMapState = mapState.GetMapId() == data->mapid ? &mapState : sMapPersistentStateMgr.GetPersistentState(data->mapid, 0)) { dataMapState->AddGameobjectToGrid(obj->guid, data); Map* dataMap = dataMapState->GetMap(); // We use spawn coords to spawn if (dataMap && dataMap->IsLoaded(data->posX, data->posY)) { GameObject* pGameobject = new GameObject; //DEBUG_LOG("Spawning gameobject %u", obj->guid); if (!pGameobject->LoadFromDB(obj->guid, dataMap)) { delete pGameobject; return; } else { 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_BOOL_SAVE_RESPAWN_TIME_IMMEDIATELY)) pGameobject->SaveRespawnTime(); } dataMap->Add(pGameobject); } } } // for not loaded grid just update respawn time (avoid work for instances until implemented support) else if(!instantly) { // for spawned by default object only if (data->spawntimesecs >= 0) dataMapState->SaveGORespawnTime(obj->guid, time(NULL) + data->spawntimesecs); } } } }
void PoolGroup<Creature>::Spawn1Object(MapPersistentState& mapState, PoolObject* obj, bool instantly) { if (CreatureData const* data = sObjectMgr.GetCreatureData(obj->guid)) { MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); // for non-instanceable maps pool spawn can be at different map from provided mapState if (MapPersistentState* dataMapState = mapState.GetMapId() == data->mapid ? &mapState : sMapPersistentStateMgr.GetPersistentState(data->mapid, 0)) { dataMapState->AddCreatureToGrid(obj->guid, data); Map* dataMap = dataMapState->GetMap(); // We use spawn coords to spawn if (dataMap && dataMap->IsLoaded(data->posX, data->posY)) { Creature* pCreature = new Creature; //DEBUG_LOG("Spawning creature %u",obj->guid); if (!pCreature->LoadFromDB(obj->guid, dataMap)) { delete pCreature; return; } 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_BOOL_SAVE_RESPAWN_TIME_IMMEDIATELY) || pCreature->IsWorldBoss()) pCreature->SaveRespawnTime(); } dataMap->Add(pCreature); } } // for not loaded grid just update respawn time (avoid work for instances until implemented support) else if(!instantly) { dataMapState->SaveCreatureRespawnTime(obj->guid, time(NULL) + data->spawntimesecs); } } } }
void PoolManager::InitSpawnPool(MapPersistentState& mapState, uint16 pool_id) { // spawn pool for expected map or for not initialized shared pools state for non-instanceable maps if (mPoolTemplate[pool_id].CanBeSpawnedAtMap(mapState.GetMapEntry())) SpawnPool(mapState, pool_id, true); }
void MapPersistentStateManager::LoadCreatureRespawnTimes() { // remove outdated data CharacterDatabase.DirectExecute("DELETE FROM creature_respawn WHERE respawntime <= UNIX_TIMESTAMP(NOW())"); uint32 count = 0; // 0 1 2 3 4 5 6 QueryResult* result = CharacterDatabase.Query("SELECT guid, respawntime, map, instance, difficulty, resettime, encountersMask FROM creature_respawn LEFT JOIN instance ON instance = id"); if (!result) { BarGoLink bar(1); bar.step(); sLog.outString(">> Loaded 0 creature respawn time."); sLog.outString(); return; } BarGoLink bar(result->GetRowCount()); do { Field* fields = result->Fetch(); bar.step(); uint32 loguid = fields[0].GetUInt32(); uint64 respawn_time = fields[1].GetUInt64(); uint32 mapId = fields[2].GetUInt32(); uint32 instanceId = fields[3].GetUInt32(); uint8 difficulty = fields[4].GetUInt8(); time_t resetTime = (time_t)fields[5].GetUInt64(); uint32 completedEncounters = fields[6].GetUInt32(); CreatureData const* data = sObjectMgr.GetCreatureData(loguid); if (!data) continue; MapEntry const* mapEntry = sMapStore.LookupEntry(data->mapid); if (!mapEntry) continue; if (instanceId) // In instance - mapId must be data->mapid and mapEntry must be Instanceable { if (mapId != data->mapid || !mapEntry->Instanceable()) continue; } else // Not in instance, mapEntry must not be Instanceable { if (mapEntry->Instanceable()) continue; } if (difficulty >= (!mapEntry->Instanceable() ? REGULAR_DIFFICULTY + 1 : MAX_DIFFICULTY)) continue; MapPersistentState* state = AddPersistentState(mapEntry, instanceId, Difficulty(difficulty), resetTime, mapEntry->IsDungeon(), true, true, completedEncounters); if (!state) continue; state->SetCreatureRespawnTime(loguid, time_t(respawn_time)); ++count; } while (result->NextRow()); delete result; sLog.outString(">> Loaded %u creature respawn times", count); sLog.outString(); }