Example #1
0
void InstanceMgr::BuildSavedInstancesForPlayer(Player * plr)
{
    WorldPacket data(4);
    Instance * in;
    InstanceMap::iterator itr;
    InstanceMap * instancemap;
    uint32 i;

    if (!plr->IsInWorld() || plr->GetMapMgr()->GetMapInfo()->type != INSTANCE_NULL)
    {
        m_mapLock.Acquire();
        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 (PlayerOwnsInstance(in, plr) && !IS_PERSISTENT_INSTANCE(in))
                    {
                        m_mapLock.Release();

                        data.SetOpcode(SMSG_UPDATE_LAST_INSTANCE);
                        data << uint32(in->m_mapId);
                        plr->GetSession()->SendPacket(&data);

                        data.Initialize(SMSG_UPDATE_INSTANCE_OWNERSHIP);
                        data << uint32(0x01);
                        plr->GetSession()->SendPacket(&data);

                        return;
                    }
                }
            }
        }
        m_mapLock.Release();
    }

    data.SetOpcode(SMSG_UPDATE_INSTANCE_OWNERSHIP);
    data << uint32(0x00);
    plr->GetSession()->SendPacket(&data);
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
void MapCell::LoadObjects(CellSpawns * sp)
{
    //we still have mobs loaded on cell. There is no point of loading them again
    if (_loaded == true)
        return;

    _loaded = true;
    Instance * pInstance = _mapmgr->pInstance;
    InstanceBossInfoMap *bossInfoMap = objmgr.m_InstanceBossInfoMap[_mapmgr->GetMapId()];

    if (sp->CreatureSpawns.size())//got creatures
    {
        for (CreatureSpawnList::iterator i = sp->CreatureSpawns.begin(); i != sp->CreatureSpawns.end(); i++)
        {
            uint32 respawnTimeOverride = 0;
            if (pInstance)
            {
                if (bossInfoMap != NULL && IS_PERSISTENT_INSTANCE(pInstance))
                {
                    bool skip = false;
                    for (std::set<uint32>::iterator killedNpc = pInstance->m_killedNpcs.begin(); killedNpc != pInstance->m_killedNpcs.end(); ++killedNpc)
                    {
                        // Do not spawn the killed boss.
                        if ((*killedNpc) == (*i)->entry)
                        {
                            skip = true;
                            break;
                        }
                        // Do not spawn the killed boss' trash.
                        InstanceBossInfoMap::const_iterator bossInfo = bossInfoMap->find((*killedNpc));
                        if (bossInfo != bossInfoMap->end() && bossInfo->second->trash.find((*i)->id) != bossInfo->second->trash.end())
                        {
                            skip = true;
                            break;
                        }
                    }
                    if (skip)
                        continue;

                    for (InstanceBossInfoMap::iterator bossInfo = bossInfoMap->begin(); bossInfo != bossInfoMap->end(); ++bossInfo)
                    {
                        if (pInstance->m_killedNpcs.find(bossInfo->second->creatureid) == pInstance->m_killedNpcs.end() && bossInfo->second->trash.find((*i)->id) != bossInfo->second->trash.end())
                        {
                            respawnTimeOverride = bossInfo->second->trashRespawnOverride;
                        }
                    }
                }
                else
                {
                    // No boss information available ... fallback ...
                    if (pInstance->m_killedNpcs.find((*i)->id) != pInstance->m_killedNpcs.end())
                        continue;
                }
            }

            Creature * c = _mapmgr->CreateCreature((*i)->entry);

            c->SetMapId(_mapmgr->GetMapId());
            c->SetInstanceID(_mapmgr->GetInstanceID());
            c->m_loadedFromDB = true;
            if (respawnTimeOverride > 0)
                c->m_respawnTimeOverride = respawnTimeOverride;

            if (c->Load(*i, _mapmgr->iInstanceMode, _mapmgr->GetMapInfo()) && c->CanAddToWorld())
            {
                c->PushToWorld(_mapmgr);
            }
            else
                delete c;//missing proto or smth of that kind
        }
    }

    if (sp->GOSpawns.size())//got GOs
    {
        for (GOSpawnList::iterator i = sp->GOSpawns.begin(); i != sp->GOSpawns.end(); i++)
        {
            GameObject * go = _mapmgr->CreateGameObject((*i)->entry);
            go->SetInstanceID(_mapmgr->GetInstanceID());
            if (go->Load(*i))
            {
                //uint32 state = go->GetUInt32Value(GAMEOBJECT_STATE);

                // FIXME - burlex
                /*
                if(pInstance && pInstance->FindObject((*i)->stateNpcLink))
                {
                go->SetUInt32Value(GAMEOBJECT_STATE, (state ? 0 : 1));
                }*/

                go->m_loadedFromDB = true;
                go->PushToWorld(_mapmgr);
            }
            else
                delete go;//missing proto or smth of that kind
        }
    }
}
Example #5
0
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;
}
Example #6
0
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;
}