///// returns a new or existing Instance ///// in case of battlegrounds it will only return an existing map, those maps are created by bg-system Map* MapManager::CreateInstance(uint32 id, Player * player) { Map* map = NULL; Map * pNewMap = NULL; uint32 NewInstanceId = 0; // instanceId of the resulting map const MapEntry* entry = sMapStore.LookupEntry(id); if(entry->IsBattleGroundOrArena()) { // find existing bg map for player NewInstanceId = player->GetBattleGroundId(); ASSERT(NewInstanceId); if (map = FindMap(id, NewInstanceId)) ASSERT(map); } else if (InstanceSave* pSave = player->GetBoundInstanceSaveForSelfOrGroup(id)) { // solo/perm/group NewInstanceId = pSave->GetGUID(); map = FindMap(id, NewInstanceId); // it is possible that the save exists but the map doesn't if (!map) { pNewMap = CreateInstanceMap(id, NewInstanceId, pSave->GetDifficulty(), pSave); NewInstanceId = pNewMap->GetInstanceId(); } } else { // if no instanceId via group members or instance saves is found // the instance will be created for the first time NewInstanceId = sObjectMgr.GenerateLowGuid(HIGHGUID_INSTANCE); Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(entry->IsRaid()) : player->GetDifficulty(entry->IsRaid()); pNewMap = CreateInstanceMap(id, NewInstanceId, diff); NewInstanceId = pNewMap->GetInstanceId(); } //add a new map object into the registry if(pNewMap) { i_maps[MapID(id, NewInstanceId)] = pNewMap; map = pNewMap; } return map; }
void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj, bool instantly) { if (GameObjectData const* data = sObjectMgr.GetGOData(obj->guid)) { sObjectMgr.AddGameobjectToGrid(obj->guid, data); // Spawn if necessary (loaded grids only) // this base map checked as non-instanced and then only existing Map* map = const_cast<Map*>(sMapMgr.FindMap(data->mapid)); if(!map) return; // 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)) { GameObject* pGameobject = new GameObject; //DEBUG_LOG("Spawning gameobject %u", obj->guid); if (!pGameobject->LoadFromDB(obj->guid, map)) { 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_IMMEDIATLY)) pGameobject->SaveRespawnTime(); } 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); } } }
void PoolGroup<Creature>::Spawn1Object(PoolObject* obj, bool instantly) { if (CreatureData const* data = sObjectMgr.GetCreatureData(obj->guid)) { sObjectMgr.AddCreatureToGrid(obj->guid, data); // Spawn if necessary (loaded grids only) Map* map = const_cast<Map*>(sMapMgr.FindMap(data->mapid)); if(!map) return; // We use spawn coords to spawn (avoid work for instances until implemented support) if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY)) { Creature* pCreature = new Creature; //DEBUG_LOG("Spawning creature %u",obj->guid); if (!pCreature->LoadFromDB(obj->guid, map)) { 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_IMMEDIATLY) || pCreature->IsWorldBoss()) pCreature->SaveRespawnTime(); } 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); } } }
// Summon group of player static bool HandleGroupSummonCommand(ChatHandler* handler, char const* args) { Player* target; if (!handler->extractPlayerTarget((char*)args, &target)) return false; // check online security if (handler->HasLowerSecurity(target, 0)) return false; Group* group = target->GetGroup(); std::string nameLink = handler->GetNameLink(target); if (!group) { handler->PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); handler->SetSentErrorMessage(true); return false; } Player* gmPlayer = handler->GetSession()->GetPlayer(); Group* gmGroup = gmPlayer->GetGroup(); Map* gmMap = gmPlayer->GetMap(); bool toInstance = gmMap->Instanceable(); // we are in instance, and can summon only player in our group with us as lead if (toInstance && ( !gmGroup || group->GetLeaderGUID() != gmPlayer->GetGUID() || gmGroup->GetLeaderGUID() != gmPlayer->GetGUID())) // the last check is a bit excessive, but let it be, just in case { handler->SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); handler->SetSentErrorMessage(true); return false; } for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->GetSource(); if (!player || player == gmPlayer || !player->GetSession()) continue; // check online security if (handler->HasLowerSecurity(player, 0)) return false; std::string plNameLink = handler->GetNameLink(player); if (player->IsBeingTeleported()) { handler->PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); handler->SetSentErrorMessage(true); return false; } if (toInstance) { Map* playerMap = player->GetMap(); if (playerMap->Instanceable() && playerMap->GetInstanceId() != gmMap->GetInstanceId()) { // cannot summon from instance to instance handler->PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, plNameLink.c_str()); handler->SetSentErrorMessage(true); return false; } } handler->PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), ""); if (handler->needReportToTarget(player)) ChatHandler(player->GetSession()).PSendSysMessage(LANG_SUMMONED_BY, handler->GetNameLink().c_str()); // stop flight if need if (player->IsInFlight()) { player->GetMotionMaster()->MovementExpired(); player->CleanupAfterTaxiFlight(); } // save only in non-flight case else player->SaveRecallPosition(); // before GM float x, y, z; gmPlayer->GetClosePoint(x, y, z, player->GetObjectSize()); player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation()); } return true; }
//Summon Player bool ChatHandler::HandleSummonCommand(const char* args) { Player* target; uint64 target_guid; std::string target_name; if (!extractPlayerTarget((char*)args, &target, &target_guid, &target_name)) return false; Player* _player = m_session->GetPlayer(); if (target == _player || target_guid == _player->GetGUID()) { PSendSysMessage(LANG_CANT_TELEPORT_SELF); SetSentErrorMessage(true); return false; } if (target) { std::string nameLink = playerLink(target_name); // check online security if (HasLowerSecurity(target, 0)) return false; if (target->IsBeingTeleported()) { PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str()); SetSentErrorMessage(true); return false; } Map* map = m_session->GetPlayer()->GetMap(); if (map->IsBattlegroundOrArena()) { // only allow if gm mode is on if (!_player->isGameMaster()) { PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM, nameLink.c_str()); SetSentErrorMessage(true); return false; } // if both players are in different bgs else if (target->GetBattlegroundId() && m_session->GetPlayer()->GetBattlegroundId() != target->GetBattlegroundId()) target->LeaveBattleground(false); // Note: should be changed so target gets no Deserter debuff // all's well, set bg id // when porting out from the bg, it will be reset to 0 target->SetBattlegroundId(m_session->GetPlayer()->GetBattlegroundId(), m_session->GetPlayer()->GetBattlegroundTypeId()); // remember current position as entry point for return at bg end teleportation if (!target->GetMap()->IsBattlegroundOrArena()) target->SetBattlegroundEntryPoint(); } else if (map->IsDungeon()) { Map* cMap = target->GetMap(); if (cMap->Instanceable() && cMap->GetInstanceId() != map->GetInstanceId()) target->UnbindInstance(map->GetInstanceId(), target->GetDungeonDifficulty(), true); // we are in instance, and can summon only player in our group with us as lead if (!m_session->GetPlayer()->GetGroup() || !target->GetGroup() || (target->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID())) // the last check is a bit excessive, but let it be, just in case { PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, nameLink.c_str()); SetSentErrorMessage(true); return false; } } PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), ""); if (needReportToTarget(target)) ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(_player->GetName()).c_str()); // stop flight if need if (target->isInFlight()) { target->GetMotionMaster()->MovementExpired(); target->CleanupAfterTaxiFlight(); } // save only in non-flight case else target->SaveRecallPosition(); // before GM float x, y, z; m_session->GetPlayer()->GetClosePoint(x, y, z, target->GetObjectSize()); target->TeleportTo(m_session->GetPlayer()->GetMapId(), x, y, z, target->GetOrientation()); target->SetPhaseMask(m_session->GetPlayer()->GetPhaseMask(), true); } else { // check offline security if (HasLowerSecurity(NULL, target_guid)) return false; std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), GetSkyFireString(LANG_OFFLINE)); // in point where GM stay Player::SavePositionInDB(m_session->GetPlayer()->GetMapId(), m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetOrientation(), m_session->GetPlayer()->GetZoneId(), target_guid); } return true; }
void WorldSession::HandleMoveWorldportAckOpcode() { // get start teleport coordinates (will used later in fail case) WorldLocation old_loc; GetPlayer()->GetPosition(old_loc); // get the teleport destination WorldLocation &loc = GetPlayer()->GetTeleportDest(); // possible errors in the coordinate validity check if (!MapManager::IsValidMapCoord(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation)) { // stop teleportation else we would try this again and again in LogoutPlayer... GetPlayer()->SetSemaphoreTeleport(false); // player don't gets saved - so his coords will stay at the point where // he was last saved LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapEntry const* mEntry = sMapStore.LookupEntry(loc.mapid); Map *map = NULL; // prevent crash at attempt landing to not existed battleground instance if(mEntry->IsBattleGroundOrArena()) { if (GetPlayer()->GetBattleGroundId()) map = sMapMgr.FindMap(loc.mapid, GetPlayer()->GetBattleGroundId()); if (!map) { GetPlayer()->SetSemaphoreTeleport(false); // Teleport to previous place, if cannot be ported back TP to homebind place if (!GetPlayer()->TeleportTo(old_loc)) GetPlayer()->TeleportToHomebind(); return; } } InstanceTemplate const* mInstance = ObjectMgr::GetInstanceTemplate(loc.mapid); // reset instance validity, except if going to an instance inside an instance if (GetPlayer()->m_InstanceValid == false && !mInstance) GetPlayer()->m_InstanceValid = true; GetPlayer()->SetSemaphoreTeleport(false); // relocate the player to the teleport destination if (!map) map = sMapMgr.CreateMap(loc.mapid, GetPlayer()); GetPlayer()->SetMapId(loc.mapid); GetPlayer()->SetMap(map); GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); // since the MapId is set before the GetInstance call, the InstanceId must be set to 0 // to let GetInstance() determine the proper InstanceId based on the player's binds GetPlayer()->SetInstanceId(map->GetInstanceId()); // check this before Map::Add(player), because that will create the instance save! bool reset_notify = (GetPlayer()->GetBoundInstance(GetPlayer()->GetMapId(), GetPlayer()->GetDifficulty()) == NULL); GetPlayer()->SendInitialPacketsBeforeAddToMap(); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if (!GetPlayer()->GetMap()->Add(GetPlayer())) { // Teleport to previous place, if cannot be ported back TP to homebind place if (!GetPlayer()->TeleportTo(old_loc)) GetPlayer()->TeleportToHomebind(); return; } //this will set player's team ... so IT MUST BE CALLED BEFORE SendInitialPacketsAfterAddToMap() // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if (_player->InBattleGround()) { // cleanup seting if outdated if (!mEntry->IsBattleGroundOrArena()) { // Do next only if found in battleground _player->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG. // reset destination bg team _player->SetBGTeam(TEAM_NONE); } // join to bg case else if (BattleGround *bg = _player->GetBattleGround()) { if (_player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) bg->AddPlayer(_player); } } GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) { if (!_player->InBattleGround()) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Reset(*GetPlayer()); return; } // battleground state prepare, stop flight GetPlayer()->GetUnitStateMgr().InitDefaults(true); GetPlayer()->CleanupAfterTaxiFlight(); } // resurrect character at enter into instance where his corpse exist after add to map Corpse *corpse = GetPlayer()->GetCorpse(); if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) { if (mEntry->IsDungeon()) { GetPlayer()->ResurrectPlayer(0.5f,false); GetPlayer()->SpawnCorpseBones(); } } if (mEntry->IsRaid() && mInstance) { if (reset_notify) { uint32 timeleft = sInstanceSaveManager.GetResetTimefor (GetPlayer()->GetMapId()) - time(NULL); GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), timeleft); // greeting at the entrance of the resort raid instance } } // mount allow check if (!mEntry->IsMountAllowed()) _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); // honorless target if (GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); // resummon pet if (GetPlayer()->m_temporaryUnsummonedPetNumber) { Pet* NewPet = new Pet; if (!NewPet->LoadPetFromDB(GetPlayer(), 0, GetPlayer()->m_temporaryUnsummonedPetNumber, true)) delete NewPet; GetPlayer()->m_temporaryUnsummonedPetNumber = 0; } }
void GameEvent::GameEventSpawn(int16 event_id) { if(max_event_id + event_id >= mGameEventCreatureGuids.size()) { sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventCreatureGuids element %u (size: %u)",max_event_id + event_id,mGameEventCreatureGuids.size()); return; } for (GuidList::iterator itr = mGameEventCreatureGuids[max_event_id + event_id].begin();itr != mGameEventCreatureGuids[max_event_id + event_id].end();++itr) { // Add to correct cell CreatureData const* data = objmgr.GetCreatureData(*itr); if (data) { objmgr.AddCreatureToGrid(*itr, data); // Spawn if necessary (loaded grids only) Map* map = const_cast<Map*>(MapManager::Instance().GetBaseMap(data->mapid)); // We use spawn coords to spawn if(!map->Instanceable() && !map->IsRemovalGrid(data->spawn_posX,data->spawn_posY)) { Creature* pCreature = new Creature((WorldObject*)NULL); //sLog.outDebug("Spawning creature %u",*itr); if (!pCreature->LoadFromDB(*itr, map->GetInstanceId())) { delete pCreature; } else { map->Add(pCreature); } } } } if(max_event_id + event_id >= mGameEventGameobjectGuids.size()) { sLog.outError("GameEvent::GameEventSpawn attempt access to out of range mGameEventGameobjectGuids element %u (size: %u)",max_event_id + event_id,mGameEventGameobjectGuids.size()); return; } for (GuidList::iterator itr = mGameEventGameobjectGuids[max_event_id + event_id].begin();itr != mGameEventGameobjectGuids[max_event_id + event_id].end();++itr) { // Add to correct cell GameObjectData const* data = objmgr.GetGOData(*itr); if (data) { objmgr.AddGameobjectToGrid(*itr, data); // Spawn if necessary (loaded grids only) // this base map checked as non-instanced and then only existed Map* map = const_cast<Map*>(MapManager::Instance().GetBaseMap(data->mapid)); // We use current coords to unspawn, not spawn coords since creature can have changed grid if(!map->Instanceable() && !map->IsRemovalGrid(data->posX, data->posY)) { GameObject* pGameobject = new GameObject((WorldObject*)NULL); //sLog.outDebug("Spawning gameobject %u", *itr); if (!pGameobject->LoadFromDB(*itr, map->GetInstanceId())) { delete pGameobject; } else { if(pGameobject->isSpawnedByDefault()) map->Add(pGameobject); } } } } }
void ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, const uint32 &y, const uint32 &t_diff) const { // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle info.UpdateTimeTracker(t_diff); if( info.getTimeTracker().Passed() ) { if( grid.ActiveObjectsInGrid() == 0 && !ObjectAccessor::Instance().PlayersNearGrid(x, y, m.GetId(), m.GetInstanceId()) ) { ObjectGridStoper stoper(grid); stoper.StopN(); grid.SetGridState(GRID_STATE_IDLE); } else { m.ResetGridExpiry(grid, 0.1f); } } }
//Summon group of player bool ChatHandler::HandleGroupSummonCommand(const char* args) { Player* target; if (!extractPlayerTarget((char*)args, &target)) return false; // check online security if (HasLowerSecurity(target, 0)) return false; Group *grp = target->GetGroup(); std::string nameLink = GetNameLink(target); if (!grp) { PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); SetSentErrorMessage(true); return false; } Map* gmMap = m_session->GetPlayer()->GetMap(); bool to_instance = gmMap->Instanceable(); // we are in instance, and can summon only player in our group with us as lead if (to_instance && ( !m_session->GetPlayer()->GetGroup() || (grp->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) || (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()))) // the last check is a bit excessive, but let it be, just in case { SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); SetSentErrorMessage(true); return false; } for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *pl = itr->getSource(); if (!pl || pl == m_session->GetPlayer() || !pl->GetSession()) continue; // check online security if (HasLowerSecurity(pl, 0)) return false; std::string plNameLink = GetNameLink(pl); if (pl->IsBeingTeleported() == true) { PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); SetSentErrorMessage(true); return false; } if (to_instance) { Map* plMap = pl->GetMap(); if (plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId()) { // cannot summon from instance to instance PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, plNameLink.c_str()); SetSentErrorMessage(true); return false; } } PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), ""); if (needReportToTarget(pl)) ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetNameLink().c_str()); // stop flight if need if (pl->isInFlight()) { pl->GetMotionMaster()->MovementExpired(); pl->CleanupAfterTaxiFlight(); } // save only in non-flight case else pl->SaveRecallPosition(); if (pl->IsMounted()) { pl->Unmount(); pl->RemoveAurasByType(SPELL_AURA_MOUNTED); } // before GM float x, y, z; m_session->GetPlayer()->GetClosePoint(x, y, z, pl->GetObjectSize()); pl->TeleportTo(m_session->GetPlayer()->GetMapId(), x, y, z, pl->GetOrientation()); } return true; }