bool CNNM2ECC::addNewGroup(string svname, svutil::word & putid, string parentid) { WORDLIST subglist; //获取所有子孙 id if(parentid.find(".")==std::string::npos) { OBJECT objse= Cache_GetSVSE(parentid); if( objse==INVALID_VALUE ) return false; SVSE *se= reinterpret_cast<SVSE *>(objse); if(se==NULL) return false; subglist= se->GetSubGroups(); } else { OBJECT objgroup= Cache_GetGroup( parentid ); if(objgroup==INVALID_VALUE) return false; Group* pNnmGroup = reinterpret_cast<Group *>(objgroup); if(pNnmGroup==NULL) return false; subglist= pNnmGroup->GetSubGroups(); } //遍历子孙 for(WORDLIST::iterator it1=subglist.begin();it1!=subglist.end();it1++) { OBJECT objgroup2= Cache_GetGroup( (*it1).getword() ); if(objgroup2==INVALID_VALUE) continue; Group *pGroup = reinterpret_cast<Group *>(objgroup2); if(pGroup!=NULL) { std::string groupname = svname.c_str(); if(groupname.compare((pGroup->GetProperty())["sv_name"])==0) { putid = pGroup->GetID(); return true; } } } //如果没有发现需要的子孙,则新建 OBJECT newobj= CreateGroup(); if(newobj==INVALID_VALUE) return false; Group* pg= reinterpret_cast<Group *>(newobj); if(pg==NULL) return false; (pg->GetProperty())["sv_name"]= svname.c_str(); putid = AddNewGroup(newobj,parentid); bool ret= SubmitGroup(newobj); CloseGroup( newobj ); return ret; }
//////////////////////////////////////////////////////////////// ///This function handles CMSG_GROUP_ACCEPT: //////////////////////////////////////////////////////////////// void WorldSession::HandleGroupAcceptOpcode(WorldPacket & recv_data) { CHECK_INWORLD_RETURN; // we are in group already if(_player->GetGroup() != NULL) return; Player* player = objmgr.GetPlayer(_player->GetInviter()); if(!player) return; player->SetInviter(0); _player->SetInviter(0); Group* grp = player->GetGroup(); if(grp != NULL) { grp->AddMember(_player->m_playerInfo); _player->iInstanceType = grp->m_difficulty; _player->SendDungeonDifficulty(); //sInstanceSavingManager.ResetSavedInstancesForPlayer(_player); return; } // If we're this far, it means we have no existing group, and have to make one. grp = new Group(true); grp->m_difficulty = static_cast<uint8>(player->iInstanceType); grp->AddMember(player->m_playerInfo); // add the inviter first, therefore he is the leader grp->AddMember(_player->m_playerInfo); // add us. _player->iInstanceType = grp->m_difficulty; _player->SendDungeonDifficulty(); Instance* instance = sInstanceMgr.GetInstanceByIds(player->GetMapId(), player->GetInstanceID()); if(instance != NULL && instance->m_creatorGuid == player->GetLowGUID()) { grp->m_instanceIds[instance->m_mapId][instance->m_difficulty] = instance->m_instanceId; instance->m_creatorGroup = grp->GetID(); instance->m_creatorGuid = 0; instance->SaveToDB(); } //sInstanceSavingManager.ResetSavedInstancesForPlayer(_player); // Currentgroup and all that shit are set by addmember. }
bool ChatHandler::HandleResetInstanceCommand(const char* args, WorldSession* m_session) { uint32 instanceId; int argc = 1; char* playername = NULL; char* guidString = (char*)args; // Parse arguments char* space = (char*)strchr(args, ' '); if (space) { *space = '\0'; playername = space + 1; argc = 2; } instanceId = atoi(guidString); if (!instanceId) { RedSystemMessage(m_session, "You must specify an instance id."); return true; } Player* plr; if (argc == 1) plr = getSelectedChar(m_session, true); else plr = objmgr.GetPlayer((const char*)playername, false);; if (!plr) { RedSystemMessage(m_session, "Player not found"); return true; } Instance* instance = sInstanceMgr.GetInstanceByIds(NUM_MAPS, instanceId); if (instance == NULL) { RedSystemMessage(m_session, "There's no instance with id %u.", instanceId); return true; } if (IS_PERSISTENT_INSTANCE(instance)) { if (m_session->CanUseCommand('z')) { bool foundSomething = false; plr->getPlayerInfo()->savedInstanceIdsLock.Acquire(); for (uint32 difficulty = 0; difficulty < NUM_INSTANCE_MODES; difficulty++) { PlayerInstanceMap::iterator itr = plr->getPlayerInfo()->savedInstanceIds[difficulty].find(instance->m_mapId); if (itr == plr->getPlayerInfo()->savedInstanceIds[difficulty].end() || (*itr).second != instance->m_instanceId) continue; plr->SetPersistentInstanceId(instance->m_mapId, difficulty, 0); SystemMessage(m_session, "Instance with id %u (%s) is persistent and will only be revoked from player.", instanceId, GetDifficultyString(static_cast<uint8>(difficulty))); foundSomething = true; } plr->getPlayerInfo()->savedInstanceIdsLock.Release(); if (!foundSomething) RedSystemMessage(m_session, "Player is not assigned to persistent instance with id %u.", instanceId); return true; } else { RedSystemMessage(m_session, "Instance with id %u is persistent and can only be removed from player by admins.", instanceId); return true; } } if (instance->m_mapMgr && instance->m_mapMgr->HasPlayers()) { RedSystemMessage(m_session, "Failed to reset non-persistent instance with id %u, due to player still inside.", instanceId); return true; } if (instance->m_creatorGroup) { Group* group = plr->GetGroup(); if (group == NULL || instance->m_creatorGroup != group->GetID()) { RedSystemMessage(m_session, "Player %s is not a member of the group assigned to the non-persistent instance with id %u.", plr->GetName(), instanceId); return true; } } else if (instance->m_creatorGuid == 0 || instance->m_creatorGuid != plr->GetLowGUID()) { RedSystemMessage(m_session, "Player %s is not assigned to instance with id %u.", plr->GetName(), instanceId); return true; } // tell player the instance was reset WorldPacket data(SMSG_INSTANCE_RESET, 4); data << instance->m_mapId; plr->GetSession()->SendPacket(&data); // shut down instance sInstanceMgr.DeleteBattlegroundInstance(instance->m_mapId, instance->m_instanceId); // RedSystemMessage(m_session, "Resetting single non-persistent instances is not available yet."); sGMLog.writefromsession(m_session, "used reset instance command on %s, instance %u,", plr->GetName(), instanceId); return true; }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player* plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo* inf = WorldMapInfoStorage.LookupEntry(mapid); Group* pGroup; InstanceMap* instancemap; Instance* in; if(inf == NULL || mapid >= NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if(inf->type == INSTANCE_BATTLEGROUND) return INSTANCE_ABORT_NOT_FOUND; pGroup = plr->GetGroup(); // players without groups cannot enter raids and heroic instances if(pGroup == NULL && inf->type == INSTANCE_RAID && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; if(pGroup == NULL && (inf->type == INSTANCE_NONRAID && plr->iInstanceType == MODE_HEROIC) && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // players without raid groups cannot enter raid instances if(pGroup != NULL && pGroup->GetGroupType() != GROUP_TYPE_RAID && inf->type == INSTANCE_RAID && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // We deny transfer if we requested a heroic instance of a map that has no heroic mode // We are trying to enter into a non-multi instance with a heroic group, downscaling if(inf->type == INSTANCE_NONRAID && plr->GetDungeonDifficulty() == MODE_HEROIC) { plr->SetDungeonDifficulty(MODE_NORMAL); plr->SendDungeonDifficulty(); Group* grp = plr->GetGroup(); if(grp != NULL) grp->SetDungeonDifficulty(MODE_NORMAL); } // if it's not a normal / 10men normal then check if we even have this mode if(inf->type == INSTANCE_RAID && plr->GetRaidDifficulty() != MODE_NORMAL_10MEN) { uint32 newtype = 0; if(!inf->HasDifficulty(plr->GetRaidDifficulty())) { // no it doesn't so we will downscale it /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This part is totally speculative, if you know how this is done actually then do change it // switch(plr->GetRaidDifficulty()) { case MODE_NORMAL_25MEN: case MODE_HEROIC_10MEN: { newtype = MODE_NORMAL_10MEN; break; } case MODE_HEROIC_25MEN: { newtype = MODE_NORMAL_25MEN; break; } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // check if we have this mode if(!inf->HasDifficulty(newtype)) { //appearantly we don't so we set to 10men normal, which is the default for old raids too //regardless of their playerlimit newtype = MODE_NORMAL_10MEN; } // Setting the new mode on us and our group if(plr->GetRaidDifficulty() != newtype) { plr->SetRaidDifficulty(newtype); plr->SendRaidDifficulty(); Group* grp = plr->GetGroup(); if(grp != NULL) grp->SetRaidDifficulty(newtype); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // If we are here, it means: // 1.) We're a simple non-raid and non-heroic dungeon // 2.) We're a multi-dungeon set to heroic and we are in a group // 3.) We're a raid, and we are in a raid group // 4.) We're a raid, we are in a raid group, and we have the right mode set // // So, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // Otherwise, we will try to create them a new one. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// m_mapLock.Acquire(); instancemap = m_instances[mapid]; // If there are no instances of this map yet, we need to create the map if(instancemap == NULL) { if(instanceid != 0) { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } else { InstanceMap::iterator itr; // this is the case when we enter an already existing instance ( with summons for example ) if(instanceid != 0) { itr = instancemap->find(instanceid); if(itr != instancemap->end()) { in = itr->second; if(!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... m_mapLock.Release(); sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if(pGroup) in->m_creatorGroup = pGroup->GetID(); m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } } else // this is the case when we enter the normal way (e.g. we enter thru the portal ) { in = NULL; if(pGroup != NULL) // we are in a group { uint32 grpdiff; // We want to use the raid difficulty for raids, and dungeon difficulty for dungeons if(inf->type == INSTANCE_RAID) grpdiff = pGroup->m_raiddifficulty; else grpdiff = pGroup->m_difficulty; if((inf->type == INSTANCE_MULTIMODE && grpdiff == MODE_HEROIC) || inf->type == INSTANCE_RAID) { // This is the case when we don't have this map on this difficulty saved yet for the player entering if(plr->GetPersistentInstanceId(mapid, grpdiff) == 0) { // The group has this instance saved already so we will use it if(pGroup->m_instanceIds[mapid][ grpdiff ] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][ grpdiff ]); } else if(sWorld.instance_TakeGroupLeaderID) { PlayerInfo* pLeaderInfo = pGroup->GetLeader(); if(pLeaderInfo) { pLeaderInfo->savedInstanceIdsLock.Acquire(); PlayerInstanceMap::iterator itrLeader = pLeaderInfo->savedInstanceIds[ grpdiff ].find(mapid); if(itrLeader != pLeaderInfo->savedInstanceIds[ grpdiff ].end()) { in = sInstanceMgr.GetInstanceByIds(mapid, (*itrLeader).second); } pLeaderInfo->savedInstanceIdsLock.Release(); } } } // If we have it saved to the player then use that if(in == NULL && plr->GetPersistentInstanceId(mapid, grpdiff) != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, plr->GetPersistentInstanceId(mapid, grpdiff)); } } else { if(pGroup->m_instanceIds[mapid][ grpdiff ] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][ grpdiff ]); } } } if(in == NULL) { // We are not in a group, so we will look for an instance that we own and has the right difficulty uint32 diff; if(inf->type == INSTANCE_RAID) diff = plr->GetRaidDifficulty(); else diff = plr->GetDungeonDifficulty(); for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(in->m_difficulty == diff && PlayerOwnsInstance(in, plr)) break; in = NULL; } } // We've found an instance! if(in != NULL) { m_mapLock.Release(); // check the player count and in combat status. if(in->m_mapMgr) { if(in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; if(in->m_mapMgr->GetPlayerCount() >= inf->playerlimit) return INSTANCE_ABORT_FULL; } if(!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if(pGroup) in->m_creatorGroup = pGroup->GetID(); plr->SetInstanceID(in->m_instanceId); // found our instance, allow him in. return INSTANCE_OK; } } } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; switch(inf->type) { case INSTANCE_NONRAID: case INSTANCE_MULTIMODE: in->m_difficulty = plr->GetDungeonDifficulty(); break; case INSTANCE_RAID: in->m_difficulty = plr->GetRaidDifficulty(); break; } in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapInfo = inf; in->m_mapMgr = NULL; // always start off without a map manager, it is created in GetInstance() in->m_isBattleground = false; in->m_persistent = IS_PERSISTENT_INSTANCE(in) && objmgr.m_InstanceBossInfoMap[mapid] == NULL; in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; if(sWorld.instance_SlidingExpiration) { if(inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_HEROIC) in->m_expiration = UNIXTIME + TIME_DAY; else in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } else { if(inf->type == INSTANCE_MULTIMODE && in->m_difficulty >= MODE_HEROIC) { in->m_expiration = UNIXTIME - (UNIXTIME % TIME_DAY) + ((UNIXTIME % TIME_DAY) > (sWorld.instance_DailyHeroicInstanceResetHour * TIME_HOUR) ? 82800 : -3600) + ((sWorld.instance_DailyHeroicInstanceResetHour - sWorld.GMTTimeZone) * TIME_HOUR); } else if(IS_PERSISTENT_INSTANCE(in)) { if(m_nextInstanceReset[in->m_mapId] == 0) { m_nextInstanceReset[in->m_mapId] = UNIXTIME - (UNIXTIME % TIME_DAY) - ((sWorld.GMTTimeZone + 1) * TIME_HOUR) + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); CharacterDatabase.Execute("DELETE FROM server_settings WHERE setting_id LIKE 'next_instance_reset_%u';", in->m_mapId); CharacterDatabase.Execute("INSERT INTO server_settings VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } if(m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME) { do { time_t tmp = m_nextInstanceReset[in->m_mapId]; if(tmp + (TIME_MINUTE * 15) < UNIXTIME) m_nextInstanceReset[in->m_mapId] = tmp + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); } while(m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME); CharacterDatabase.Execute("DELETE FROM server_settings WHERE setting_id LIKE 'next_instance_reset_%u';", in->m_mapId); CharacterDatabase.Execute("INSERT INTO server_settings VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } in->m_expiration = m_nextInstanceReset[in->m_mapId]; } else { in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } } plr->SetInstanceID(in->m_instanceId); Log.Debug("InstanceMgr", "Creating instance for player %u and group %u on map %u. (%u)", in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // save our new instance to the database. in->SaveToDB(); // apply it in the instance map instancemap->insert(InstanceMap::value_type(in->m_instanceId, in)); // Try to add instance ID to player plr->SetPersistentInstanceId(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
void CBattlegroundManager::HandleArenaJoin(WorldSession * m_session, uint32 BattlegroundType, uint8 as_group, uint8 rated_match) { uint32 pguid = m_session->GetPlayer()->GetLowGUID(); uint32 lgroup = GetLevelGrouping(m_session->GetPlayer()->getLevel()); if(as_group && m_session->GetPlayer()->GetGroup() == NULL) return; Group * pGroup = m_session->GetPlayer()->GetGroup(); if(as_group) { if(pGroup->GetSubGroupCount() != 1) { m_session->SystemMessage("Sorry, raid groups joining battlegrounds are currently unsupported."); return; } if(pGroup->GetLeader() != m_session->GetPlayer()->m_playerInfo) { m_session->SystemMessage("You must be the party leader to add a group to an arena."); return; } GroupMembersSet::iterator itx; if(!rated_match) { /* add all players normally.. bleh ;P */ pGroup->Lock(); for(itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if((*itx)->m_loggedInPlayer && !(*itx)->m_loggedInPlayer->m_bgIsQueued && !(*itx)->m_loggedInPlayer->m_bg) HandleArenaJoin((*itx)->m_loggedInPlayer->GetSession(), BattlegroundType, 0, 0); } pGroup->Unlock(); return; } else { /* make sure all players are 70 */ uint32 maxplayers; uint32 arenateamtype; switch(BattlegroundType) { case BATTLEGROUND_ARENA_2V2: arenateamtype=0; maxplayers=2; break; case BATTLEGROUND_ARENA_3V3: arenateamtype=1; maxplayers=3; break; case BATTLEGROUND_ARENA_5V5: arenateamtype=2; maxplayers=5; break; default: arenateamtype=0; maxplayers=2; break; } uint32 team_id = 0; pGroup->Lock(); for(itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if( maxplayers == 0 ) { m_session->SystemMessage("You have too many players in your party to join this type of arena."); pGroup->Unlock(); return; } if((*itx)->lastLevel < 70) { m_session->SystemMessage("Sorry, some of your party members are not level 70."); pGroup->Unlock(); return; } if((*itx)->m_loggedInPlayer) { ArenaTeam * t = (*itx)->m_loggedInPlayer->m_arenaTeams[arenateamtype]; if( t != NULL ) { if ( team_id == 0 ) team_id = t->m_id; if ( team_id != t->m_id ) { m_session->SystemMessage("Sorry, not all your party members are in same arena team."); pGroup->Unlock(); return; } } else { m_session->SystemMessage("Sorry, not all your party members are in same arena team."); pGroup->Unlock(); return; } if( (*itx)->m_loggedInPlayer->m_bgIsQueued ) BattlegroundManager.RemovePlayerFromQueues((*itx)->m_loggedInPlayer); /* if((*itx)->m_loggedInPlayer->m_bg || (*itx)->m_loggedInPlayer->m_bg || (*itx)->m_loggedInPlayer->m_bgIsQueued) { m_session->SystemMessage("One or more of your party members are already queued or inside a battleground."); pGroup->Unlock(); return; } */ --maxplayers; } } if( maxplayers > 0 ) { m_session->SystemMessage("Sorry, you have too few valid arena members in your group."); pGroup->Unlock(); return; } WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << uint32(6); // all arenas for(itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if((*itx)->m_loggedInPlayer) { SendBattlefieldStatus((*itx)->m_loggedInPlayer, 1, BattlegroundType, 0 , 0, 0,1); (*itx)->m_loggedInPlayer->m_bgIsQueued = true; (*itx)->m_loggedInPlayer->m_bgQueueInstanceId = 0; (*itx)->m_loggedInPlayer->m_bgQueueType = BattlegroundType; (*itx)->m_loggedInPlayer->GetSession()->SendPacket(&data); (*itx)->m_loggedInPlayer->m_bgEntryPointX=(*itx)->m_loggedInPlayer->GetPositionX(); (*itx)->m_loggedInPlayer->m_bgEntryPointY=(*itx)->m_loggedInPlayer->GetPositionY(); (*itx)->m_loggedInPlayer->m_bgEntryPointZ=(*itx)->m_loggedInPlayer->GetPositionZ(); (*itx)->m_loggedInPlayer->m_bgEntryPointMap=(*itx)->m_loggedInPlayer->GetMapId(); } } pGroup->Unlock(); m_queueLock.Acquire(); m_queuedGroups[BattlegroundType].push_back(pGroup->GetID()); m_queueLock.Release(); Log.Success("BattlegroundMgr", "Group %u is now in battleground queue for arena type %u", pGroup->GetID(), BattlegroundType); /* send the battleground status packet */ return; } } /* Queue him! */ m_queueLock.Acquire(); m_queuedPlayers[BattlegroundType][lgroup].push_back(pguid); Log.Success("BattlegroundMgr", "Player %u is now in battleground queue for {Arena %u}", m_session->GetPlayer()->GetLowGUID(), BattlegroundType ); /* send the battleground status packet */ SendBattlefieldStatus(m_session->GetPlayer(), 1, BattlegroundType, 0 , 0, 0,0); m_session->GetPlayer()->m_bgIsQueued = true; m_session->GetPlayer()->m_bgQueueInstanceId = 0; m_session->GetPlayer()->m_bgQueueType = BattlegroundType; /* Set battleground entry point */ m_session->GetPlayer()->m_bgEntryPointX = m_session->GetPlayer()->GetPositionX(); m_session->GetPlayer()->m_bgEntryPointY = m_session->GetPlayer()->GetPositionY(); m_session->GetPlayer()->m_bgEntryPointZ = m_session->GetPlayer()->GetPositionZ(); m_session->GetPlayer()->m_bgEntryPointMap = m_session->GetPlayer()->GetMapId(); m_session->GetPlayer()->m_bgEntryPointInstance = m_session->GetPlayer()->GetInstanceID(); m_queueLock.Release(); }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player* plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = LimitedMapInfoStorage.LookupEntry(mapid); MapEntry* map = dbcMap.LookupEntry(mapid); InstanceMap * instancemap; Instance * in = NULL; //is the map vaild? if(inf == NULL || mapid >= NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; // shouldn't happen if(inf->type == INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; if(map->israid()) // check that heroic mode is available if the player has requested it. { if(plr->iRaidType > 1 && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } else if(plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; //do we need addition raid/heroic checks? Group * pGroup = plr->GetGroup() ; if( !plr->triggerpass_cheat ) { // players without groups cannot enter raid instances (no soloing them:P) if( pGroup == NULL && (map->israid() || inf->type == INSTANCE_MULTIMODE)) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; //and has the required level if( plr->getLevel() < 80) { if(!map->israid()) { //otherwise we still need to be lvl 70/80 for heroic. if( plr->iInstanceType && plr->getLevel() < uint32(inf->HasFlag(WMI_INSTANCE_XPACK_02) ? 80 : 70)) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } else //otherwise we still need to be lvl 70/80 for heroic. if( plr->iRaidType > 1 && plr->getLevel() < uint32(inf->HasFlag(WMI_INSTANCE_XPACK_02) ? 80 : 70)) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; //and we might need a key too. bool reqkey = (inf->heroic_key[0] || inf->heroic_key[1])? true : false; bool haskey = (plr->GetItemInterface()->GetItemCount(inf->heroic_key[0], false) || plr->GetItemInterface()->GetItemCount(inf->heroic_key[1], false))? true : false; if(reqkey && !haskey) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } } // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // next we check if there is a saved instance belonging to him. // otherwise, we can create them a new one. m_mapLock.Acquire(); //find all instances for our map instancemap = m_instances[mapid]; if(instancemap) { InstanceMap::iterator itr; // do we have a specific instance id we should enter (saved or active). // don't bother looking for saved instances, if we had one we found it in areatrigger.cpp if(instanceid != 0) { itr = instancemap->find(instanceid); if(itr != instancemap->end()) { in = itr->second; //we have an instance,but can we enter it? uint8 owns = PlayerOwnsInstance( in, plr ); if( owns >= OWNER_CHECK_OK ) { // If the map is active and has players if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat) { //check if combat is in progress if( in->m_mapMgr->IsCombatInProgress()) { m_mapLock.Release(); return INSTANCE_ABORT_ENCOUNTER; } // check if we are full if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit ) { m_mapLock.Release(); return INSTANCE_ABORT_FULL; } } uint32 plrdiff = map->israid() ? plr->iRaidType : plr->iInstanceType; if(in->m_difficulty == plrdiff) { //wakeup call for saved instances if(!in->m_mapMgr) in->m_mapMgr = _CreateInstance(in); if(owns == OWNER_CHECK_SAVED_OK && !in->m_mapMgr->HasPlayers()) { if(plr->GetGroup()) in->m_creatorGroup = plr->GetGroupID(); } m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_TOO_MANY; } } else DEBUG_LOG("InstanceMgr","Check failed %s, return code %u",plr->GetName(), owns); } m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } else { // search all active instances and see if we have one here. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; //we have an instance,but do we own it? uint8 owns = PlayerOwnsInstance(in, plr); if( owns >= OWNER_CHECK_OK ) { // check the player count and in combat status. if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat) { if( in->m_mapMgr->IsCombatInProgress()) { m_mapLock.Release(); return INSTANCE_ABORT_ENCOUNTER; } // check if we are full if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit ) { m_mapLock.Release(); return INSTANCE_ABORT_FULL; } } uint32 plrdiff = map->israid() ? plr->iRaidType : plr->iInstanceType; if(in->m_difficulty == plrdiff) { //wakeup call for saved instances if(!in->m_mapMgr) in->m_mapMgr = _CreateInstance(in); if(owns == OWNER_CHECK_SAVED_OK && !in->m_mapMgr->HasPlayers()) { if(plr->GetGroup()) in->m_creatorGroup = plr->GetGroupID(); } // found our instance, allow him in. m_mapLock.Release(); return INSTANCE_OK; } } else DEBUG_LOG("InstanceMgr","Check failed %s, return code %u",plr->GetName(), owns); } } } else { if(instanceid != 0) { // wtf, how can we have an instance_id for a mapid which doesn't even exist? m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } // this mapid hasn't been added yet, so we gotta create the hashmap now. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } // if we're here, it means we need to create a new instance. bool raid = map->israid(); in = new Instance; in->m_creation = UNIXTIME; in->m_expiration = (raid ? UNIXTIME + inf->cooldown : 0); // expire time 0 is 10 minutes after last player leaves in->m_creatorGuid = plr->GetLowGUID(); in->m_creatorGroup = (pGroup ? pGroup->GetID() : 0); in->m_difficulty = (raid ? plr->iRaidType : plr->iInstanceType); in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapMgr = NULLMAPMGR; // always start off without a map manager, it is created in _CreateInstance(in) //crash fix; GM's without group will start up raid instances as if they where nonraids //this to avoid exipring check, this is mainly for developers purpose; GM's should NOT invite any players here! if( plr->triggerpass_cheat && !plr->GetGroup() && raid) { const char * message = "Started this instance for development purposes only, do not invite players!!"; sEventMgr.AddEvent( plr, &Player::_Warn, message, EVENT_UNIT_SENDMESSAGE, 5000, 1, 0); } in->m_mapInfo = inf; in->m_dbcMap = map; in->m_isBattleground = false; plr->SetInstanceID(in->m_instanceId); DEBUG_LOG("InstanceMgr", "Prepared new %s %u for player %u and group %u on map %u with difficulty %u. (%u)", raid ? "Raid" : "Instance" ,in->m_instanceId, in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_difficulty, in->m_instanceId); // apply it in the instance map instancemap->insert( InstanceMap::value_type( in->m_instanceId, in ) ); // create the actual instance (if we don't GetInstance() won't be able to access it). in->m_mapMgr = _CreateInstance(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
void CBattlegroundManager::EventQueueUpdate() { deque<Player*> tempPlayerVec[2]; uint32 i,j,k; Player * plr; CBattleground * bg; list<uint32>::iterator it3, it4; //vector<Player*>::iterator it6; map<uint32, CBattleground*>::iterator iitr; Arena * arena; int32 team; m_queueLock.Acquire(); m_instanceLock.Acquire(); for(i = 0; i < BATTLEGROUND_NUM_TYPES; ++i) { for(j = 0; j < MAX_LEVEL_GROUP; ++j) { if(!m_queuedPlayers[i][j].size()) continue; tempPlayerVec[0].clear(); tempPlayerVec[1].clear(); for(it3 = m_queuedPlayers[i][j].begin(); it3 != m_queuedPlayers[i][j].end();) { it4 = it3++; plr = objmgr.GetPlayer(*it4); if(!plr || GetLevelGrouping(plr->getLevel()) != j) { m_queuedPlayers[i][j].erase(it4); continue; } // queued to a specific instance id? if(plr->m_bgQueueInstanceId != 0) { iitr = m_instances[i].find(plr->m_bgQueueInstanceId); if(iitr == m_instances[i].end()) { // queue no longer valid plr->GetSession()->SystemMessage("Your queue on battleground instance id %u is no longer valid. Reason: Instance Deleted.", plr->m_bgQueueInstanceId); plr->m_bgIsQueued = false; plr->m_bgQueueType = 0; plr->m_bgQueueInstanceId = 0; m_queuedPlayers[i][j].erase(it4); } // can we join? bg = iitr->second; if(bg->CanPlayerJoin(plr)) { bg->AddPlayer(plr, plr->GetTeam()); m_queuedPlayers[i][j].erase(it4); } } else { if(IS_ARENA(i)) tempPlayerVec[0].push_back(plr); else tempPlayerVec[plr->GetTeam()].push_back(plr); } } // try to join existing instances for(iitr = m_instances[i].begin(); iitr != m_instances[i].end(); ++iitr) { if( iitr->second->HasEnded() || iitr->second->GetLevelGroup() != j) continue; if(IS_ARENA(i)) { arena = ((Arena*)iitr->second); if(arena->Rated()) continue; team = arena->GetFreeTeam(); while(team >= 0 && tempPlayerVec[0].size()) { plr = *tempPlayerVec[0].begin(); tempPlayerVec[0].pop_front(); plr->m_bgTeam=team; arena->AddPlayer(plr, team); ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); team = arena->GetFreeTeam(); } } else { bg = iitr->second; for(k = 0; k < 2; ++k) { while(tempPlayerVec[k].size() && bg->HasFreeSlots(k)) { plr = *tempPlayerVec[k].begin(); tempPlayerVec[k].pop_front(); bg->AddPlayer(plr, plr->GetTeam()); ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); } } } } if(IS_ARENA(i)) { // enough players to start a round? if(tempPlayerVec[0].size() < BGMinimumPlayers[i]) continue; if(CanCreateInstance(i,j)) { arena = ((Arena*)CreateInstance(i, j)); team = arena->GetFreeTeam(); while(!arena->IsFull() && tempPlayerVec[0].size() && team >= 0) { plr = *tempPlayerVec[0].begin(); tempPlayerVec[0].pop_front(); plr->m_bgTeam=team; arena->AddPlayer(plr, team); team = arena->GetFreeTeam(); // remove from the main queue (painful!) ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); } } } else { #ifdef ONLY_ONE_PERSON_REQUIRED_TO_JOIN_DEBUG if(tempPlayerVec[0].size() >= 1 || tempPlayerVec[1].size() >= 1) #else if(tempPlayerVec[0].size() >= BGMinimumPlayers[i] && tempPlayerVec[1].size() >= BGMinimumPlayers[i]) #endif { if(CanCreateInstance(i,j)) { bg = CreateInstance(i,j); if( bg == NULL ) { // creation failed for(k = 0; k < 2; ++k) { while(tempPlayerVec[k].size()) { plr = *tempPlayerVec[k].begin(); tempPlayerVec[k].pop_front(); ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); } } } else { // push as many as possible in for(k = 0; k < 2; ++k) { while(tempPlayerVec[k].size() && bg->HasFreeSlots(k)) { plr = *tempPlayerVec[k].begin(); tempPlayerVec[k].pop_front(); plr->m_bgTeam=k; bg->AddPlayer(plr, k); ErasePlayerFromList(plr->GetLowGUID(), &m_queuedPlayers[i][j]); } } } } } } } } /* Handle paired arena team joining */ list<uint32>::iterator itz; list<uint32>::iterator itp; for(i = BATTLEGROUND_ARENA_2V2; i < BATTLEGROUND_ARENA_5V5+1; ++i) { // We need at least this many :( if(m_queuedGroups[i].size() < 2) continue; list<uint32> removegroups; for(itz = m_queuedGroups[i].begin(); itz != m_queuedGroups[i].end(); itz++) { Group * pGroup = objmgr.GetGroupById(*itz); if(!pGroup || !pGroup->m_isqueued || !pGroup->GetLeader() || pGroup->GetLeader()->arenaTeam[i - 4] == NULL) continue; uint32 maxRange = pGroup->GetLeader()->arenaTeam[i - 4]->m_queueSearchRange; pGroup->GetLeader()->arenaTeam[i - 4]->m_queueSearchRange += 100; vector<uint32> inRangeGroups; uint32 rating = pGroup->GetLeader()->arenaTeam[i - 4]->m_stat_rating; for(itp = m_queuedGroups[i].begin(); itp != m_queuedGroups[i].end();) { Group * tGrp = objmgr.GetGroupById(*itp); if(!tGrp || !tGrp->m_isqueued || !tGrp->GetLeader() || tGrp->GetLeader()->arenaTeam[i - 4] == NULL) { itp = m_queuedGroups[i].erase(itp); continue; } ++itp; if( pGroup == tGrp ) continue; uint32 tRating = tGrp->GetLeader()->arenaTeam[i - 4]->m_stat_rating; int32 diff = (int32)tRating - (int32)rating; if(diff < 0) diff = -diff; if(diff > (int32)maxRange) continue; //Log.Notice("Debug", "EventQueueUpdate added 1 in range arena"); inRangeGroups.push_back(tGrp->GetID()); } // K, we have a giant list of groups that we could group with, hopefully! // or not, we can't go on :( if(!inRangeGroups.size()) continue; // But if we're here, we can :D uint32 r = 0; if( inRangeGroups.size() > 1 ) r = RandomUInt((uint32)inRangeGroups.size() - 1); Group * pairGroup = objmgr.GetGroupById(inRangeGroups[r]); if(!pairGroup) continue; // Now, let's create this rated Arena Match :) //Log.Notice("Debug", "EventQueueUpdate creating arena"); Arena * arena = (Arena*)CreateInstance(i, LEVEL_GROUP_70); ArenaTeam *pTeamPair[2]; if(arena) { //Log.Notice("Debug", "EventQueueUpdate arena created"); removegroups.push_back(pGroup->GetID()); removegroups.push_back(pairGroup->GetID()); pGroup->m_isqueued = false; pairGroup->m_isqueued = false; arena->rated_match = true; if( pGroup->GetLeader()->arenaTeam[i - 4] != NULL ) { arena->m_ratedTeams[0] = pGroup->GetLeader()->arenaTeam[i - 4]->m_id; pTeamPair[0] = pGroup->GetLeader()->arenaTeam[i - 4]; } else pTeamPair[0] = NULL; if( pairGroup->GetLeader()->arenaTeam[i - 4] != NULL ) { arena->m_ratedTeams[1] = pairGroup->GetLeader()->arenaTeam[i - 4]->m_id; pTeamPair[1] = pairGroup->GetLeader()->arenaTeam[i - 4]; } else pTeamPair[1] = NULL; pGroup->GetLeader()->arenaTeam[i - 4]->m_queueSearchRange = 100; pairGroup->GetLeader()->arenaTeam[i - 4]->m_queueSearchRange = 100; GroupMembersSet::iterator gitr; pGroup->Lock(); for(gitr = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); gitr != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); gitr++) { PlayerInfo * pi = (*gitr); if(!pi->m_loggedInPlayer) continue; //Log.Notice("Debug", "EventQueueUpdate player lewp"); pi->m_loggedInPlayer->m_bgTeam = 0; if(arena->HasFreeSlots(0)) { arena->AddPlayer(pi->m_loggedInPlayer, 0); arena->m_RatedPlayers[0].insert(pi); if( pTeamPair[0] != NULL ) { ArenaTeamMember * atm = pTeamPair[0]->GetMember(pi); if(atm) { atm->Played_ThisSeason++; atm->Played_ThisWeek++; } //Log.Notice("Debug", "EventQueueUpdate added player %s", pi->m_loggedInPlayer->GetName()); } } } pGroup->Unlock(); pairGroup->Lock(); for(gitr = pairGroup->GetSubGroup(0)->GetGroupMembersBegin(); gitr != pairGroup->GetSubGroup(0)->GetGroupMembersEnd(); gitr++) { PlayerInfo * pi = (*gitr); if(!pi->m_loggedInPlayer || pi->arenaTeam[i-4] == NULL) continue; pi->m_loggedInPlayer->m_bgTeam = 1; if(arena->HasFreeSlots(1)) { arena->AddPlayer(pi->m_loggedInPlayer, 1); arena->m_RatedPlayers[1].insert(pi); if( pTeamPair[1] != NULL ) { ArenaTeamMember * atm = pTeamPair[1]->GetMember(pi); if(atm) { atm->Played_ThisSeason++; atm->Played_ThisWeek++; } } } } pairGroup->Unlock(); } } for(itz = removegroups.begin(); itz != removegroups.end(); itz++) { m_queuedGroups[i].remove(*itz); } } m_queueLock.Release(); m_instanceLock.Release(); }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player * plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = WorldMapInfoStorage.LookupEntry(mapid); Group * pGroup; InstanceMap * instancemap; Instance * in; if(inf == NULL || mapid>=NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if(inf->type==INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; // players without groups cannot enter raid instances (no soloing them:P) if(plr->GetGroup() == NULL && (inf->type == INSTANCE_RAID || inf->type == INSTANCE_MULTIMODE) && !plr->triggerpass_cheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // check that heroic mode is available if the player has requested it. if(plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // otherwise, we can create them a new one. m_mapLock.Acquire(); instancemap = m_instances[mapid]; // set up our pointers (cleaner code is always good) pGroup = plr->GetGroup(); if(instancemap == NULL) { if(instanceid != 0) { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } // gotta create the hashmap. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } else { InstanceMap::iterator itr; if(instanceid != 0) { itr = instancemap->find(instanceid); if(itr != instancemap->end()) { m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } } else { // search the instance and see if we have one here. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(PlayerOwnsInstance(in, plr)) { m_mapLock.Release(); // check the player count and in combat status. if(in->m_mapMgr) { if(in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; if(in->m_mapMgr->GetPlayerCount() >= inf->playerlimit) return INSTANCE_ABORT_FULL; } // found our instance, allow him in. return INSTANCE_OK; } } } } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; in->m_expiration =UNIXTIME + inf->cooldown; // expire time 0 is 10 minutes after last player leaves in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; in->m_difficulty = plr->iInstanceType; in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapMgr = NULL; // always start off without a map manager, it is created in GetInstance() in->m_mapInfo = inf; in->m_isBattleground=false; plr->SetInstanceID(in->m_instanceId); Log.Debug("InstanceMgr", "Creating instance for player %u and group %u on map %u. (%u)", in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // save our new instance to the database. in->SaveToDB(); // apply it in the instance map instancemap->insert( InstanceMap::value_type( in->m_instanceId, in ) ); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
bool ChatHandler::HandleResetInstanceCommand(const char* args, WorldSession *m_session) { uint32 instanceId = (args ? atoi(args) : 0); if(instanceId == 0) return false; Player * plr = getSelectedChar(m_session, true); if(!plr) return true; Instance *instance = sInstanceMgr.GetInstanceByIds(NUM_MAPS, instanceId); if(instance == NULL) { RedSystemMessage(m_session, "There's no instance with id %u.", instanceId); return true; } if(IS_PERSISTENT_INSTANCE(instance)) { if(m_session->CanUseCommand('z')) { bool foundSomething = false; plr->m_playerInfo->savedInstanceIdsLock.Acquire(); for(int difficulty=0; difficulty<NUM_INSTANCE_MODES; difficulty++) { PlayerInstanceMap::iterator itr = plr->m_playerInfo->savedInstanceIds[difficulty].find(instance->m_mapId); if(itr == plr->m_playerInfo->savedInstanceIds[difficulty].end() || (*itr).second != instance->m_instanceId) continue; plr->SetPersistentInstanceId(instance->m_mapId, difficulty, 0); SystemMessage(m_session, "Instance with id %u (%s) is persistent and will only be revoked from player.", instanceId, GetDifficultyString(difficulty)); foundSomething = true; } plr->m_playerInfo->savedInstanceIdsLock.Release(); if(!foundSomething) RedSystemMessage(m_session, "Player is not assigned to persistent instance with id %u.", instanceId); return true; } else { RedSystemMessage(m_session, "Instance with id %u is persistent and can only be removed from player by admins.", instanceId); return true; } } if(instance->m_mapMgr && instance->m_mapMgr->HasPlayers()) { RedSystemMessage(m_session, "Failed to reset non-persistent instance with id %u, due to player still inside.", instanceId); return true; } if(instance->m_creatorGroup) { Group *group = plr->GetGroup(); if(group == NULL || instance->m_creatorGroup != group->GetID()) { RedSystemMessage(m_session, "Player %s is not a member of the group assigned to the non-persistent instance with id %u.", plr->GetName(), instanceId); return true; } } else if(instance->m_creatorGuid == 0 || instance->m_creatorGuid != plr->GetLowGUID()) { RedSystemMessage(m_session, "Player %s is not assigned to instance with id %u.", plr->GetName(), instanceId); return true; } //TODO: Reset that instance...^^ RedSystemMessage(m_session, "Resetting single non-persistent instances is not available yet."); sGMLog.writefromsession(m_session, "used reset instance command on %s, instance %u,", plr->GetName(), instanceId); return true; }
uint32 InstanceMgr::PreTeleport(uint32 mapid, PlayerPointer plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = WorldMapInfoStorage.LookupEntry(mapid); Group * pGroup = plr->GetGroup() ; InstanceMap * instancemap; Instance * in; if(inf == NULL || mapid>=NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if(inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if(inf->type==INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; if( !plr->triggerpass_cheat ) { // players without groups cannot enter raid instances (no soloing them:P) if( pGroup == NULL && (inf->type == INSTANCE_RAID || inf->type == INSTANCE_MULTIMODE)) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // check that heroic mode is available if the player has requested it. if(plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; } // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // otherwise, we can create them a new one. m_mapLock.Acquire(); instancemap = m_instances[mapid]; if(instancemap) { InstanceMap::iterator itr; if(instanceid != 0) { //try to find our instance in ones active now. itr = instancemap->find(instanceid); if(itr != instancemap->end()) { Instance *inn = itr->second; if( PlayerOwnsInstance( inn, plr ) >= OWNER_CHECK_OK ) { m_mapLock.Release(); return INSTANCE_OK; } } //There are no active maps, re-check if this concerns a saved instance. Instance * saved_in = sInstanceMgr.GetSavedInstance( mapid, plr->GetLowGUID() ); if( saved_in && saved_in->m_instanceId == instanceid ) { if ( PlayerOwnsInstance( saved_in, plr ) >= OWNER_CHECK_OK ) { m_mapLock.Release(); return INSTANCE_OK; } } m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } else { // search all active instances and see if we have one here. for(itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if(PlayerOwnsInstance(in, plr) >= OWNER_CHECK_OK ) { m_mapLock.Release(); // check the player count and in combat status. if(in->m_mapMgr && in->m_mapMgr->HasPlayers() && !plr->triggerpass_cheat) { if( in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; // check if we are full if( in->m_mapMgr->GetPlayerCount() >= inf->playerlimit ) return INSTANCE_ABORT_FULL; } // found our instance, allow him in. return INSTANCE_OK; } else DEBUG_LOG("InstanceMgr","Check failed %s",plr->GetName()); } } } else { if(instanceid != 0) { return INSTANCE_ABORT_NOT_FOUND; } // gotta create the hashmap. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; in->m_expiration = (inf->type == INSTANCE_NONRAID) ? 0 : UNIXTIME + inf->cooldown; // expire time 0 is 10 minutes after last player leaves in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; in->m_difficulty = plr->iInstanceType; in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapMgr = NULLMAPMGR; // always start off without a map manager, it is created in GetInstance() //crash fix; GM's without group will start up raid instances as if they where nonraids //this to avoid exipring check, this is mainly for developers purpose; GM's should NOT invite any players here! if( plr->triggerpass_cheat && !plr->GetGroup() && inf->type == INSTANCE_RAID) { inf->type = INSTANCE_NONRAID; sGMLog.writefromsession(plr->GetSession(), "Started a raid instance %d [%s] as non_raid instance.", mapid, inf->name); DEBUG_LOG("InstanceMgr","Started a raid instance %d [%s] as non_raid instance.", mapid, inf->name); } in->m_mapInfo = inf; in->m_isBattleground=false; plr->SetInstanceID(in->m_instanceId); if( plr->GetGroup() && !plr->GetSession()->HasGMPermissions())//GM should not set the instanceID pGroup->SetGroupInstanceID(in->m_instanceId); DEBUG_LOG("InstanceMgr", "Prepared new instance %u for player %u and group %u on map %u. (%u)",in->m_instanceId, in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // apply it in the instance map instancemap->insert( InstanceMap::value_type( in->m_instanceId, in ) ); // create the actual instance (if we don't GetInstance() won't be able to access it). in->m_mapMgr = _CreateInstance(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }
//////////////////////////////////////////////////////////////// ///This function handles CMSG_GROUP_ACCEPT and deny: //////////////////////////////////////////////////////////////// void WorldSession::HandleGroupAcceptOpcode( WorldPacket & recv_data ) { if(!_player->IsInWorld()) { return; } uint8 packet_type; recv_data >> packet_type; if( packet_type == 0 ) //0x80 for group accept and 0 is for decline { HandleGroupDeclineOpcode( recv_data ); return; } Player *player = objmgr.GetPlayer(_player->GetInviter()); if ( !player ) { return; } //check if this invite is still valid if( player->GetInviter() != _player->GetLowGUID() || _player->GetInviter() != player->GetLowGUID() ) { _player->BroadcastMessage( "Group invite from player %s expired", player->GetName() ); player->BroadcastMessage( "Group invite from player %s expired", _player->GetName() ); return; } player->SetInviter(0); _player->SetInviter(0); Group *grp = player->GetGroup(); if(grp) { grp->AddMember(_player->m_playerInfo); _player->dungeon_difficulty = grp->dungeon_difficulty; _player->raid_difficulty = grp->raid_difficulty; _player->SendDungeonDifficulty(); _player->SendRaidDifficulty(); //sInstanceSavingManager.ResetSavedInstancesForPlayer(_player); return; } // If we're this far, it means we have no existing group, and have to make one. grp = new Group(true); grp->dungeon_difficulty = player->dungeon_difficulty; grp->raid_difficulty = player->raid_difficulty; grp->AddMember(player->m_playerInfo); // add the inviter first, therefore he is the leader grp->AddMember(_player->m_playerInfo); // add us. _player->dungeon_difficulty = grp->dungeon_difficulty; _player->raid_difficulty = grp->raid_difficulty; _player->SendDungeonDifficulty(); _player->SendRaidDifficulty(); Instance *instance = sInstanceMgr.GetInstanceByIds(player->GetMapId(), player->GetInstanceID()); if(instance != NULL && instance->m_creatorGuid == player->GetLowGUID()) { grp->AddSavedInstance(instance->m_mapId,instance->instance_difficulty,instance->m_instanceId); instance->m_creatorGroup = grp->GetID(); instance->m_creatorGuid = 0; instance->SaveToDB(); } //sInstanceSavingManager.ResetSavedInstancesForPlayer(_player); // Currentgroup and all that shit are set by addmember. }
void CBattlegroundManager::RemovePlayerFromQueues(Player* plr) { m_queueLock.Acquire(); ARCEMU_ASSERT(plr->m_bgQueueType < BATTLEGROUND_NUM_TYPES); sEventMgr.RemoveEvents(plr, EVENT_BATTLEGROUND_QUEUE_UPDATE); uint32 lgroup = GetLevelGrouping(plr->getLevel()); list<uint32>::iterator itr; itr = m_queuedPlayers[plr->m_bgQueueType][lgroup].begin(); while (itr != m_queuedPlayers[plr->m_bgQueueType][lgroup].end()) { if ((*itr) == plr->GetLowGUID()) { Log.Debug("BattlegroundManager", "Removing player %u from queue instance %u type %u", plr->GetLowGUID(), plr->m_bgQueueInstanceId, plr->m_bgQueueType); m_queuedPlayers[plr->m_bgQueueType][lgroup].erase(itr); break; } ++itr; } plr->m_bgIsQueued = false; plr->m_bgTeam = plr->GetTeam(); plr->m_pendingBattleground = NULL; SendBattlefieldStatus(plr, BGSTATUS_NOFLAGS, 0, 0, 0, 0, 0); m_queueLock.Release(); Group* group; group = plr->GetGroup(); if (group) //if da n****s in a group, boot dis bitch ass' group outa da q { Log.Debug("BattlegroundManager", "Player %u removed whilst in a group. Removing players group %u from queue", plr->GetLowGUID(), group->GetID()); RemoveGroupFromQueues(group); } }
void CBattlegroundManager::HandleArenaJoin(WorldSession* m_session, uint32 BattlegroundType, uint8 as_group, uint8 rated_match) { uint32 pguid = m_session->GetPlayer()->GetLowGUID(); uint32 lgroup = GetLevelGrouping(m_session->GetPlayer()->getLevel()); if (as_group && m_session->GetPlayer()->GetGroup() == NULL) return; Group* pGroup = m_session->GetPlayer()->GetGroup(); if (as_group) { if (pGroup->GetSubGroupCount() != 1) { m_session->SystemMessage(m_session->LocalizedWorldSrv(55)); return; } if (pGroup->GetLeader() != m_session->GetPlayer()->getPlayerInfo()) { m_session->SystemMessage(m_session->LocalizedWorldSrv(56)); return; } GroupMembersSet::iterator itx; if (!rated_match) { /* add all players normally.. bleh ;P */ pGroup->Lock(); for (itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if ((*itx)->m_loggedInPlayer && !(*itx)->m_loggedInPlayer->m_bgIsQueued && !(*itx)->m_loggedInPlayer->m_bg) HandleArenaJoin((*itx)->m_loggedInPlayer->GetSession(), BattlegroundType, 0, 0); } pGroup->Unlock(); return; } else { /* make sure all players are 70 */ uint32 maxplayers; uint32 type = BattlegroundType - BATTLEGROUND_ARENA_2V2; switch (BattlegroundType) { case BATTLEGROUND_ARENA_3V3: maxplayers = 3; break; case BATTLEGROUND_ARENA_5V5: maxplayers = 5; break; case BATTLEGROUND_ARENA_2V2: default: maxplayers = 2; break; } if (pGroup->GetLeader()->m_loggedInPlayer && pGroup->GetLeader()->m_loggedInPlayer->m_arenaTeams[type] == NULL) { m_session->SendNotInArenaTeamPacket(uint8(maxplayers)); return; } pGroup->Lock(); for (itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if (maxplayers == 0) { m_session->SystemMessage(m_session->LocalizedWorldSrv(58)); pGroup->Unlock(); return; } if ((*itx)->lastLevel < PLAYER_ARENA_MIN_LEVEL) { m_session->SystemMessage(m_session->LocalizedWorldSrv(59)); pGroup->Unlock(); return; } if ((*itx)->m_loggedInPlayer) { if ((*itx)->m_loggedInPlayer->m_bg || (*itx)->m_loggedInPlayer->m_bgIsQueued) { m_session->SystemMessage(m_session->LocalizedWorldSrv(60)); pGroup->Unlock(); return; }; if ((*itx)->m_loggedInPlayer->m_arenaTeams[type] != pGroup->GetLeader()->m_loggedInPlayer->m_arenaTeams[type]) { m_session->SystemMessage(m_session->LocalizedWorldSrv(61)); pGroup->Unlock(); return; } --maxplayers; } } WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << uint32(6); // all arenas for (itx = pGroup->GetSubGroup(0)->GetGroupMembersBegin(); itx != pGroup->GetSubGroup(0)->GetGroupMembersEnd(); ++itx) { if ((*itx)->m_loggedInPlayer) { SendBattlefieldStatus((*itx)->m_loggedInPlayer, BGSTATUS_INQUEUE, BattlegroundType, 0, 0, 0, 1); (*itx)->m_loggedInPlayer->m_bgIsQueued = true; (*itx)->m_loggedInPlayer->m_bgQueueInstanceId = 0; (*itx)->m_loggedInPlayer->m_bgQueueType = BattlegroundType; (*itx)->m_loggedInPlayer->GetSession()->SendPacket(&data); (*itx)->m_loggedInPlayer->m_bgEntryPointX = (*itx)->m_loggedInPlayer->GetPositionX(); (*itx)->m_loggedInPlayer->m_bgEntryPointY = (*itx)->m_loggedInPlayer->GetPositionY(); (*itx)->m_loggedInPlayer->m_bgEntryPointZ = (*itx)->m_loggedInPlayer->GetPositionZ(); (*itx)->m_loggedInPlayer->m_bgEntryPointMap = (*itx)->m_loggedInPlayer->GetMapId(); } } pGroup->Unlock(); m_queueLock.Acquire(); m_queuedGroups[BattlegroundType].push_back(pGroup->GetID()); m_queueLock.Release(); Log.Notice("BattlegroundMgr", "Group %u is now in battleground queue for arena type %u", pGroup->GetID(), BattlegroundType); /* send the battleground status packet */ return; } } /* Queue him! */ m_queueLock.Acquire(); m_queuedPlayers[BattlegroundType][lgroup].push_back(pguid); Log.Notice("BattlegroundMgr", "Player %u is now in battleground queue for {Arena %u}", m_session->GetPlayer()->GetLowGUID(), BattlegroundType); /* send the battleground status packet */ SendBattlefieldStatus(m_session->GetPlayer(), BGSTATUS_INQUEUE, BattlegroundType, 0, 0, 0, 0); m_session->GetPlayer()->m_bgIsQueued = true; m_session->GetPlayer()->m_bgQueueInstanceId = 0; m_session->GetPlayer()->m_bgQueueType = BattlegroundType; /* Set battleground entry point */ m_session->GetPlayer()->m_bgEntryPointX = m_session->GetPlayer()->GetPositionX(); m_session->GetPlayer()->m_bgEntryPointY = m_session->GetPlayer()->GetPositionY(); m_session->GetPlayer()->m_bgEntryPointZ = m_session->GetPlayer()->GetPositionZ(); m_session->GetPlayer()->m_bgEntryPointMap = m_session->GetPlayer()->GetMapId(); m_session->GetPlayer()->m_bgEntryPointInstance = m_session->GetPlayer()->GetInstanceID(); m_queueLock.Release(); }
//Yeahlight: Searches for the group that will be rewarded with exp and first loot rights returnGroup HateList::GetRewardingGroup() { groupDamage groupsToConsider[255] = {0}; int16 groupCounter = 0; int16 groupID = 0; int16 leadingGroupID = 0; sint32 highestGroupDamage = 0; sint32 entityDamage = 0; Mob* entity = NULL; returnGroup groupToReward; Group* group = NULL; bool groupFound = false; for(int i = 0; i < 255; i++) { groupsToConsider[i].groupID = -1; groupsToConsider[i].groupDamageTotal = -1; } groupToReward.damage = 0; groupToReward.group = NULL; LinkedListIterator<tHateEntry*> iterator(list); iterator.Reset(); while(iterator.MoreElements()) { entityDamage = 0; if(iterator.GetData()) entityDamage = iterator.GetData()->damage; if(entityDamage > 0) { entity = iterator.GetData()->ent; //Yeahlight: Entity exists in the zone if(entity) { //Yeahlight: Entity is a client if(entity->IsClient()) { //Yeahlight: PC is grouped if(entity->CastToClient()->IsGrouped()) { group = entity_list.GetGroupByClient(entity->CastToClient()); //Yeahlight: Group exists if(group) { groupID = group->GetID(); //Yeahlight: We do not have a group list started yet, so start it off with this group if(groupCounter == 0) { groupsToConsider[0].groupID = groupID; groupsToConsider[0].groupDamageTotal = iterator.GetData()->damage; groupsToConsider[0].group = group; groupCounter++; } //Yeahlight: A group list has been created already else { //Yeahlight: Iterate through the group list for(int i = 0; i < groupCounter; i++) { //Yeahlight: Found the group for which this PC resides if(groupID == groupsToConsider[i].groupID) { //Yeahlight: Add the client's damage to the group's total groupsToConsider[i].groupDamageTotal += iterator.GetData()->damage; //Yeahlight: Flag the PC as found groupFound = true; //Yeahlight: "Break out" of the loop i = groupCounter; } } //Yeahlight: This grouped PC did not find their group in the list, so we need to add their group if(!groupFound) { groupsToConsider[groupCounter].groupID = groupID; groupsToConsider[groupCounter].groupDamageTotal = iterator.GetData()->damage; groupsToConsider[groupCounter].group = group; groupCounter++; } } } //Yeahlight: Group does not exist else { } } //Yeahlight: PC is not grouped else { } } //Yeahlight: Entity is the pet of a client else if(entity->IsNPC() && entity->GetOwner() && entity->GetOwner()->IsClient()) { //Yeahlight: Owner of the pet is grouped if(entity->GetOwner()->CastToClient()->IsGrouped()) { group = entity_list.GetGroupByClient(entity->GetOwner()->CastToClient()); //Yeahlight: Group exists if(group) { groupID = group->GetID(); //Yeahlight: We do not have a group list started yet, so start it off with this group if(groupCounter == 0) { groupsToConsider[0].groupID = groupID; groupsToConsider[0].groupDamageTotal = iterator.GetData()->damage; groupsToConsider[0].group = group; groupCounter++; } //Yeahlight: A group list has been created already else { //Yeahlight: Iterate through the group list for(int i = 0; i < groupCounter; i++) { //Yeahlight: Found the group for which this pet resides if(groupID == groupsToConsider[i].groupID) { //Yeahlight: Add the pet's damage to the group's total groupsToConsider[i].groupDamageTotal += iterator.GetData()->damage; //Yeahlight: Flag the pet as found groupFound = true; //Yeahlight: "Break out" of the loop i = groupCounter; } } //Yeahlight: This grouped pet did not find their group in the list, so we need to add their group if(!groupFound) { groupsToConsider[groupCounter].groupID = groupID; groupsToConsider[groupCounter].groupDamageTotal = iterator.GetData()->damage; groupsToConsider[groupCounter].group = group; groupCounter++; } } } //Yeahlight: Group does not exist else { } } //Yeahlight: Pet's owner is not grouped else { } } } //Yeahlight: Entity does not exist in the zone else { } } iterator.Advance(); //Yeahlight: Zone freeze debug if(ZONE_FREEZE_DEBUG && rand()%ZONE_FREEZE_DEBUG == 1) EQC_FREEZE_DEBUG(__LINE__, __FILE__); } //Yeahlight: Iterate through the group list and record for the highest damaging group for(int i = 0; i < groupCounter; i++) { //Yeahlight: Found a group with more total damage than our current leader if(groupsToConsider[i].groupDamageTotal > highestGroupDamage) { highestGroupDamage = groupsToConsider[i].groupDamageTotal; groupToReward.damage = groupsToConsider[i].groupDamageTotal; groupToReward.group = groupsToConsider[i].group; } } return groupToReward; }
void InstanceMgr::ResetSavedInstances(Player * plr) { WorldPacket *pData; Instance * in; InstanceMap::iterator itr; InstanceMap * instancemap; uint32 i; if (!plr->IsInWorld() || plr->GetMapMgr()->GetMapInfo()->type != INSTANCE_NULL) return; m_mapLock.Acquire(); Group *group = plr->GetGroup(); for (i = 0; i < NUM_MAPS; ++i) { if (m_instances[i] != NULL) { instancemap = m_instances[i]; for (itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if (IS_RESETABLE_INSTANCE(in) && ((group && group->GetID() == in->m_creatorGroup) || plr->GetLowGUID() == in->m_creatorGuid)) { if (in->m_mapMgr && in->m_mapMgr->HasPlayers()) { pData = new WorldPacket(SMSG_INSTANCE_RESET_FAILED, 8); *pData << uint32(INSTANCE_RESET_ERROR_PLAYERS_INSIDE); *pData << uint32(in->m_mapId); plr->GetSession()->SendPacket(pData); delete pData; continue; } if (group) { group->m_instanceIds[in->m_mapId][in->m_difficulty] = 0; } // <mapid> has been reset. pData = new WorldPacket(SMSG_INSTANCE_RESET, 4); *pData << uint32(in->m_mapId); plr->GetSession()->SendPacket(pData); delete pData; // destroy the instance _DeleteInstance(in, true); } } } } m_mapLock.Release(); /* plr->m_playerInfo->savedInstanceIdsLock.Acquire(); for(int difficulty=0; difficulty<NUM_INSTANCE_MODES; difficulty++) { PlayerInstanceMap::iterator itr,itr2=plr->m_playerInfo->savedInstanceIds[difficulty].begin(); for(; itr2 != plr->m_playerInfo->savedInstanceIds[difficulty].end();) { itr = itr2; itr2++; in = sInstanceMgr.GetInstanceByIds((*itr).first, (*itr).second); if( !in ) continue; if(((group && group->GetID() == in->m_creatorGroup) || plr->GetLowGUID() == in->m_creatorGuid)) { if(in->m_mapMgr && in->m_mapMgr->HasPlayers()) { pData = new WorldPacket(SMSG_RESET_INSTANCE_FAILED, 8); *pData << uint32(INSTANCE_RESET_ERROR_PLAYERS_INSIDE); *pData << uint32(in->m_mapId); plr->GetSession()->SendPacket(pData); delete pData; continue; } if(group) { group->m_instanceIds[in->m_mapId][in->m_difficulty] = 0; } // <mapid> has been reset. pData = new WorldPacket(SMSG_RESET_INSTANCE, 4); *pData << uint32(in->m_mapId); plr->GetSession()->SendPacket(pData); delete pData; //remove instance from player plr->SetPersistentInstanceId(in->m_mapId, difficulty, 0); // destroy the instance _DeleteInstance(in, true); } } } plr->m_playerInfo->savedInstanceIdsLock.Release();*/ }
uint32 InstanceMgr::PreTeleport(uint32 mapid, Player * plr, uint32 instanceid) { // preteleport is where all the magic happens :P instance creation, etc. MapInfo * inf = WorldMapInfoStorage.LookupEntry(mapid); Group * pGroup; InstanceMap * instancemap; Instance * in; if (inf == NULL || mapid >= NUM_MAPS) return INSTANCE_ABORT_NOT_FOUND; // main continent check. if (inf->type == INSTANCE_NULL) { // this will be useful when clustering comes into play. // we can check if the destination world server is online or not and then cancel them before they load. return (m_singleMaps[mapid] != NULL) ? INSTANCE_OK : INSTANCE_ABORT_NOT_FOUND; } // shouldn't happen if (inf->type == INSTANCE_PVP) return INSTANCE_ABORT_NOT_FOUND; pGroup = plr->GetGroup(); // players without groups cannot enter raids and heroic instances if (pGroup == NULL && (inf->type == INSTANCE_RAID || (inf->type == INSTANCE_MULTIMODE && plr->iInstanceType >= MODE_HEROIC)) && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // players without raid groups cannot enter raid instances if (pGroup != NULL && pGroup->GetGroupType() != GROUP_TYPE_RAID && inf->type == INSTANCE_RAID && !plr->TriggerpassCheat) return INSTANCE_ABORT_NOT_IN_RAID_GROUP; // check that heroic mode is available if the player has requested it. if (plr->iInstanceType && inf->type != INSTANCE_MULTIMODE) return INSTANCE_ABORT_HEROIC_MODE_NOT_AVAILABLE; // if we are here, it means: // 1) we're a non-raid instance // 2) we're a raid instance, and the person is in a group. // so, first we have to check if they have an instance on this map already, if so, allow them to teleport to that. // otherwise, we can create them a new one. m_mapLock.Acquire(); instancemap = m_instances[mapid]; if (instancemap == NULL) { if (instanceid != 0) { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } // gotta create the hashmap. m_instances[mapid] = new InstanceMap; instancemap = m_instances[mapid]; } else { InstanceMap::iterator itr; if (instanceid != 0) { itr = instancemap->find(instanceid); if (itr != instancemap->end()) { in = itr->second; if (!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... m_mapLock.Release(); sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if (pGroup) in->m_creatorGroup = pGroup->GetID(); m_mapLock.Release(); return INSTANCE_OK; } else { m_mapLock.Release(); return INSTANCE_ABORT_NOT_FOUND; } } else { in = NULL; if (pGroup != NULL) { if ((inf->type == INSTANCE_MULTIMODE && pGroup->m_difficulty >= MODE_HEROIC) || inf->type == INSTANCE_RAID) { if (plr->GetPersistentInstanceId(mapid, pGroup->m_difficulty) == 0) { if (pGroup->m_instanceIds[mapid][pGroup->m_difficulty] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][pGroup->m_difficulty]); } else if (sWorld.instance_TakeGroupLeaderID) { PlayerInfo *pLeaderInfo = pGroup->GetLeader(); if (pLeaderInfo) { pLeaderInfo->savedInstanceIdsLock.Acquire(); PlayerInstanceMap::iterator itrLeader = pLeaderInfo->savedInstanceIds[pGroup->m_difficulty].find(mapid); if (itrLeader != pLeaderInfo->savedInstanceIds[pGroup->m_difficulty].end()) { in = sInstanceMgr.GetInstanceByIds(mapid, (*itrLeader).second); } pLeaderInfo->savedInstanceIdsLock.Release(); } } } if (in == NULL && plr->GetPersistentInstanceId(mapid, pGroup->m_difficulty) != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, plr->GetPersistentInstanceId(mapid, pGroup->m_difficulty)); } } else { if (pGroup->m_instanceIds[mapid][pGroup->m_difficulty] != 0) { in = sInstanceMgr.GetInstanceByIds(mapid, pGroup->m_instanceIds[mapid][pGroup->m_difficulty]); } } } if (in == NULL) { // search the instance and see if we have one here. for (itr = instancemap->begin(); itr != instancemap->end();) { in = itr->second; ++itr; if (in->m_difficulty == plr->iInstanceType && PlayerOwnsInstance(in, plr)) break; in = NULL; } } if (in != NULL) { m_mapLock.Release(); // check the player count and in combat status. if (in->m_mapMgr) { if (in->m_mapMgr->IsCombatInProgress()) return INSTANCE_ABORT_ENCOUNTER; if (in->m_mapMgr->GetPlayerCount() >= inf->playerlimit) return INSTANCE_ABORT_FULL; } if (!CHECK_INSTANCE_GROUP(in, pGroup)) { // Another group is already playing in this instance of the dungeon... sChatHandler.SystemMessageToPlr(plr, "Another group is already inside this instance of the dungeon."); return INSTANCE_ABORT_NOT_IN_RAID_GROUP; } // Try to add instance ID to player plr->SetPersistentInstanceId(in); // Set current group if (pGroup) in->m_creatorGroup = pGroup->GetID(); plr->SetInstanceID(in->m_instanceId); // found our instance, allow him in. return INSTANCE_OK; } } } // if we're here, it means we need to create a new instance. in = new Instance; in->m_creation = UNIXTIME; in->m_difficulty = pGroup ? pGroup->m_difficulty : plr->iInstanceType; in->m_instanceId = GenerateInstanceID(); in->m_mapId = mapid; in->m_mapInfo = inf; in->m_mapMgr = NULL; // always start off without a map manager, it is created in GetInstance() in->m_isBattleground = false; in->m_persistent = IS_PERSISTENT_INSTANCE(in) && objmgr.m_InstanceBossInfoMap[mapid] == NULL; in->m_creatorGuid = pGroup ? 0 : plr->GetLowGUID(); // creator guid is 0 if its owned by a group. in->m_creatorGroup = pGroup ? pGroup->GetID() : 0; if (sWorld.instance_SlidingExpiration) { if (inf->type == INSTANCE_MULTIMODE && in->m_difficulty >= MODE_HEROIC) in->m_expiration = UNIXTIME + TIME_DAY; else in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } else { if (inf->type == INSTANCE_MULTIMODE && in->m_difficulty >= MODE_HEROIC) { in->m_expiration = UNIXTIME - (UNIXTIME % TIME_DAY) + ((UNIXTIME % TIME_DAY) > (sWorld.instance_DailyHeroicInstanceResetHour * TIME_HOUR) ? 82800 : -3600) + ((sWorld.instance_DailyHeroicInstanceResetHour - sWorld.GMTTimeZone) * TIME_HOUR); } else if (IS_PERSISTENT_INSTANCE(in)) { if (m_nextInstanceReset[in->m_mapId] == 0) { m_nextInstanceReset[in->m_mapId] = UNIXTIME - (UNIXTIME % TIME_DAY) - ((sWorld.GMTTimeZone + 1) * TIME_HOUR) + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); CharacterDatabase.Execute("REPLACE INTO `server_settings` (`setting_id`, `setting_value`) VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } if (m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME) { do { time_t tmp = m_nextInstanceReset[in->m_mapId]; if (tmp + (TIME_MINUTE * 15) < UNIXTIME) m_nextInstanceReset[in->m_mapId] = tmp + (in->m_mapInfo->cooldown == 0 ? TIME_DAY : in->m_mapInfo->cooldown); } while (m_nextInstanceReset[in->m_mapId] + (TIME_MINUTE * 15) < UNIXTIME); CharacterDatabase.Execute("REPLACE INTO `server_settings` (`setting_id`, `setting_value`) VALUES ('next_instance_reset_%u', '%u')", in->m_mapId, m_nextInstanceReset[in->m_mapId]); } in->m_expiration = m_nextInstanceReset[in->m_mapId]; } else { in->m_expiration = (inf->type == INSTANCE_NONRAID || (inf->type == INSTANCE_MULTIMODE && in->m_difficulty == MODE_NORMAL)) ? 0 : UNIXTIME + inf->cooldown; } } plr->SetInstanceID(in->m_instanceId); Log.Debug("InstanceMgr", "Creating instance for player %u and group %u on map %u. (%u)", in->m_creatorGuid, in->m_creatorGroup, in->m_mapId, in->m_instanceId); // save our new instance to the database. in->SaveToDB(); // apply it in the instance map instancemap->insert(InstanceMap::value_type(in->m_instanceId, in)); // Try to add instance ID to player plr->SetPersistentInstanceId(in); // instance created ok, i guess? return the ok for him to transport. m_mapLock.Release(); return INSTANCE_OK; }