예제 #1
0
Map::Map(int width, int height)
{
	_width = width;
	_height = height;
	_grid = new Grid*[_width];
	for (int i = 0; i < _width; i++)
	{
		_grid[i] = new Grid[_height];
		for (int j = 0; j < _height; j++)
			_grid[i][j].setGridCoord(GridCoord(i, j));
	}
	// (width, height)
}
예제 #2
0
void WorldSession::HandleMoveWorldportAckOpcode()
{
    // ignore unexpected far teleports
    if (!GetPlayer()->IsBeingTeleportedFar())
        return;

    GetPlayer()->SetSemaphoreTeleportFar(0);

    // get the teleport destination
    WorldLocation const& loc = GetPlayer()->GetTeleportDest();

    // possible errors in the coordinate validity check
    if (!MapManager::IsValidMapCoord(loc))
    {
        KickPlayer();
        return;
    }

    // get the destination map entry, not the current one, this will fix homebind and reset greeting
    MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId());
    InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(loc.GetMapId());

    Map* oldMap = GetPlayer()->GetMap();
    if (GetPlayer()->IsInWorld())
    {
        sLog->outError("Player (Name %s) is still in world when teleported from map %u to new map %u", GetPlayer()->GetName().c_str(), oldMap->GetId(), loc.GetMapId());
        oldMap->RemovePlayerFromMap(GetPlayer(), false);
    }

    // reset instance validity, except if going to an instance inside an instance
    if (GetPlayer()->m_InstanceValid == false && !mInstance)
    {
        GetPlayer()->m_InstanceValid = true;
        // pussywizard: m_InstanceValid can be false only by leaving a group in an instance => so remove temp binds that could not be removed because player was still on the map!
        if (!sInstanceSaveMgr->PlayerIsPermBoundToInstance(GetPlayer()->GetGUIDLow(), oldMap->GetId(), oldMap->GetDifficulty()))
            sInstanceSaveMgr->PlayerUnbindInstance(GetPlayer()->GetGUIDLow(), oldMap->GetId(), oldMap->GetDifficulty(), true);
    }

    // relocate the player to the teleport destination
    Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), GetPlayer());
    // the CanEnter checks are done in TeleporTo but conditions may change
    // while the player is in transit, for example the map may get full
    if (!newMap || !newMap->CanEnter(GetPlayer()))
    {
        sLog->outError("Map %d could not be created for player %d, porting player to homebind", loc.GetMapId(), GetPlayer()->GetGUIDLow());
        GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
        return;
    }

    GetPlayer()->Relocate(loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation());

    GetPlayer()->ResetMap();
    GetPlayer()->SetMap(newMap);

    GetPlayer()->SendInitialPacketsBeforeAddToMap();
    if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer()))
    {
        sLog->outError("WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!", GetPlayer()->GetName().c_str(), GetPlayer()->GetGUIDLow(), loc.GetMapId());
        GetPlayer()->ResetMap();
        GetPlayer()->SetMap(oldMap);
        GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation());
        return;
    }

    oldMap->AfterPlayerUnlinkFromMap();

    // pussywizard: transport teleport couldn't teleport us to the same map (some other teleport pending, reqs not met, etc.), but we still have transport set until player moves! clear it if map differs (crashfix)
    if (Transport* t = _player->GetTransport())
        if (!t->IsInMap(_player))
        {
            t->RemovePassenger(_player);
            _player->m_transport = NULL;
            _player->m_movementInfo.transport.Reset();
            _player->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
        }

    if (!_player->getHostileRefManager().isEmpty())
        _player->getHostileRefManager().deleteReferences(); // pussywizard: multithreading crashfix

    CellCoord pair(Trinity::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()));
    Cell cell(pair);
    if (!GridCoord(cell.GridX(), cell.GridY()).IsCoordValid())
    {
        KickPlayer();
        return;
    }
    newMap->LoadGrid(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY());

    // pussywizard: player supposed to enter bg map
    if (_player->InBattleground())
    {
        // but landed on another map, cleanup data
        if (!mEntry->IsBattlegroundOrArena())
            _player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE, PLAYER_MAX_BATTLEGROUND_QUEUES, false, false, TEAM_NEUTRAL);
        // everything ok
        else if (Battleground* bg = _player->GetBattleground())
        {
            if (_player->IsInvitedForBattlegroundInstance()) // GMs are not invited, so they are not added to participants
                bg->AddPlayer(_player);
        }
    }

    // pussywizard: arena spectator stuff
    {
        if (newMap->IsBattleArena() && ((BattlegroundMap*)newMap)->GetBG() && _player->HasPendingSpectatorForBG(((BattlegroundMap*)newMap)->GetInstanceId()))
        {
            _player->ClearReceivedSpectatorResetFor();
            _player->SetIsSpectator(true);
            ArenaSpectator::SendCommand(_player, "%sENABLE", SPECTATOR_ADDON_PREFIX);
            ((BattlegroundMap*)newMap)->GetBG()->AddSpectator(_player);
            ArenaSpectator::HandleResetCommand(_player);
        }
        else
            _player->SetIsSpectator(false);

        GetPlayer()->SetPendingSpectatorForBG(0);
        timeWhoCommandAllowed = time(NULL) + sWorld->GetNextWhoListUpdateDelaySecs() + 1; // after exiting arena Subscribe will scan for a player and cached data says he is still in arena, so disallow until next update

        if (uint32 inviteInstanceId = _player->GetPendingSpectatorInviteInstanceId())
        {
            if (Battleground* tbg = sBattlegroundMgr->GetBattleground(inviteInstanceId))
                tbg->RemoveToBeTeleported(_player->GetGUID());
            _player->SetPendingSpectatorInviteInstanceId(0);
        }
    }

    // xinef: do this again, player can be teleported inside bg->AddPlayer(_player)!!!!
    CellCoord pair2(Trinity::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()));
    Cell cell2(pair2);
    if (!GridCoord(cell2.GridX(), cell2.GridY()).IsCoordValid())
    {
        KickPlayer();
        return;
    }
    newMap->LoadGrid(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY());

    GetPlayer()->SendInitialPacketsAfterAddToMap();

    // resurrect character at enter into instance where his corpse exist after add to map
    Corpse* corpse = GetPlayer()->GetCorpse();
    if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId())
    {
        if (mEntry->IsDungeon())
        {
            GetPlayer()->ResurrectPlayer(0.5f, false);
            GetPlayer()->SpawnCorpseBones();
        }
    }

    bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena();
    if (mInstance)
    {
        Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid());
        if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID, diff))
            if (mapDiff->resetTime)
                if (time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->MapID, diff))
                {
                    uint32 timeleft = uint32(timeReset - time(NULL));
                    GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft, true);
                }
        allowMount = mInstance->AllowMount;
    }

    // mount allow check
    if (!allowMount)
        _player->RemoveAurasByType(SPELL_AURA_MOUNTED);

    // update zone immediately, otherwise leave channel will cause crash in mtmap
    uint32 newzone, newarea;
    GetPlayer()->GetZoneAndAreaId(newzone, newarea, true);
    GetPlayer()->UpdateZone(newzone, newarea);

    // honorless target
    if (GetPlayer()->pvpInfo.IsHostile)
        GetPlayer()->CastSpell(GetPlayer(), 2479, true);

    // in friendly area
    else if (GetPlayer()->IsPvP() && !GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
        GetPlayer()->UpdatePvP(false, false);

    // resummon pet
    GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();

    //lets process all delayed operations on successful teleport
    GetPlayer()->ProcessDelayedOperations();
}
예제 #3
0
void gridSnap::Snap(Object* pobj, IPoint2 *p, TimeValue t)
{	

	ViewExp *vpt = theman->GetVpt();

	if ( ! vpt || ! vpt->IsAlive() )
	{
		// why are we here
		DbgAssert(!_T("Invalid viewport!"));
		return;
	}

	DbgAssert(vpt != NULL);

	//local copy of the cursor position
	Point2 fp = Point2((float)p->x, (float)p->y);

	BOOL got_one= FALSE;
	//Get point on the consttruction plane 
	Point3 local_cp = vpt->GetPointOnCP(*p);
	Point3 world_snapped;

	Matrix3 tmconst;
	vpt->GetConstructionTM( tmconst );

	// aszabo|nov.01.05|#596889, #613720, #703875 
	// In order to allow snapping to the grid sub-divisions computed based on viewport 
	// the zoom facto, the grid spacing is taken from the viewport.  
	// When the grid is invisible and the zoom factor changes, the viewport returns 
	// the grid spacing computed last time the grid was displayed.
	// When max starts up with hidden grids (via maxstart.max), the viewport's grid 
	// spacing will be zero and in that case we take the grid spacing value specified 
	// in the Grid setting UI.
	float gridSpacing = vpt->GetGridSize();
	if (!(gridSpacing > 0.0f || gridSpacing < 0.0f)) {
		gridSpacing = GetCOREInterface()->GetGridSpacing();
	}


	//Compute all the hit point candidates
	if(	GetActive(INT_SUB))
	{
		float gridZ = 0.f;
#ifdef GAME_VER
		float gridSpacing = GetCOREInterface()->GetGridSpacing();

		SnapInfo si;
		GetCOREInterface()->InitSnapInfo(&si);
		if(si.snapType == SNAP_25D)
			gridZ = GridCoord(local_cp.z,gridSpacing);

		Point3 intsnapped = Point3(GridCoord(local_cp.x,gridSpacing),GridCoord(local_cp.y,gridSpacing),gridZ);
		world_snapped = tmconst * intsnapped;//now in world space
		got_one = TRUE;

		hitmesh = new HitMesh(5);
		hitmesh->setVert(0,tmconst * Point3(intsnapped.x,intsnapped.y - gridSpacing,gridZ));
		hitmesh->setVert(1,tmconst * Point3(intsnapped.x,intsnapped.y + gridSpacing,gridZ));
		hitmesh->setVert(2,tmconst * Point3(intsnapped.x-gridSpacing,intsnapped.y,gridZ));
		hitmesh->setVert(3,tmconst * Point3(intsnapped.x + gridSpacing,intsnapped.y,gridZ));

		//now register a hit with the osnap manager
		//possibly screen for proximity to the foreground
		theman->RecordHit(new OsnapHit(world_snapped, this, INT_SUB, hitmesh));

#else //!GAME_VER
		// aszabo|sep.15.04|#596889|The gridSpacing spacing shouldn't be zero, but if it is, it can lead to infinite loops
		DbgAssert(gridSpacing > 0.0f || gridSpacing < 0.0f);
		if (gridSpacing > 0.0f || gridSpacing < 0.0f)
		{
			// Record all hits that fall in the snap preview area.
			// Grids are infinite, so we can't loop  through their "vertexes".
			// Instead go through only those that are potential snap points, by starting
			// at the closest grid point to the mouse and extending in all directions
			// using "grid size" steps.
			Point3 intsnapped = Point3(GridCoord(local_cp.x,gridSpacing),GridCoord(local_cp.y,gridSpacing),gridZ);
			Point3 curIntsnapped(intsnapped);
			world_snapped = tmconst * intsnapped;

			// set the window transform to identity to guarantee a world-screen transformation.
			if (theman->GetVpt() && theman->GetVpt()->getGW()) {
				theman->GetVpt()->getGW()->setTransform(Matrix3(TRUE));
			}
			// Find all snap points on the right side (positive x) of the intsnapped, including the intsnapped
			while (CheckPotentialHit(&world_snapped,0, fp)) 
			{
				got_one = TRUE;
				RecordNewIntSubHit(world_snapped, tmconst, curIntsnapped, gridSpacing);

				//ktong|Jan.27.2006|#748560|Limit the number of snap points to search only visibly distinct points.
				// If the grid point is too far away to tell it from the next gridpoint, stop searching.
				// No point in enumerating snap points a user can't visibly tell apart.
				// Check after the first snap point (the closest) is registered to at least have one.
				if (TooDistant(theman, world_snapped, gridSpacing)) {
					break;
				}

				// Go down the vertical grid line
				curIntsnapped.y -= gridSpacing;
				FindVerticalIntSubHit(tmconst, curIntsnapped, fp, (-gridSpacing));

				// Go up the vertical grid line
				curIntsnapped.y = intsnapped.y + gridSpacing;
				FindVerticalIntSubHit(tmconst, curIntsnapped, fp, gridSpacing);

				// Go to the right of the original vertival grid line
				curIntsnapped.y = intsnapped.y;
				curIntsnapped.x += gridSpacing;
				world_snapped = tmconst * curIntsnapped;
			} 
			// Find all snap points on the left side (negative x) of the intsnapped
			curIntsnapped.y = intsnapped.y;
			curIntsnapped.x = intsnapped.x - gridSpacing;
			world_snapped = tmconst * curIntsnapped;
			//ktong|Jan.27.2006|#748560|Limit the number of snap points to search only visibly distinct points.
			while (CheckPotentialHit(&world_snapped,0, fp) && !TooDistant(theman, world_snapped, gridSpacing) ) 
			{
				got_one = TRUE;
				RecordNewIntSubHit(world_snapped, tmconst, curIntsnapped, gridSpacing);

				// Go down the vertical grid line
				curIntsnapped.y -= gridSpacing;
				FindVerticalIntSubHit(tmconst, curIntsnapped, fp, (-gridSpacing));

				// Go up the vertical grid line
				curIntsnapped.y = intsnapped.y + gridSpacing;
				FindVerticalIntSubHit(tmconst, curIntsnapped, fp, gridSpacing);

				// Go to the right of the original vertival grid line
				curIntsnapped.y = intsnapped.y;
				curIntsnapped.x -= gridSpacing;
				world_snapped = tmconst * curIntsnapped;
			} 
		}
#endif //GAME_VER
	}


	if(	GetActive(EDGE_SUB) && !got_one)
	{
		BOOL snapx = FALSE;
		float xSnap = GridCoord(local_cp.x,gridSpacing);
		float ySnap = GridCoord(local_cp.y,gridSpacing);
		float xDist = (float)fabs(xSnap - local_cp.x);
		float yDist = (float)fabs(ySnap - local_cp.y);
		Point3 esnapped;

		// Which one is closer?
		if(xDist < yDist)
		{
			snapx = TRUE;
			esnapped = Point3(xSnap,local_cp.y,0.0f);
		}
		else
		{
			esnapped = Point3(local_cp.x,ySnap,0.0f);
		}
		world_snapped = tmconst * esnapped;//now in world space

		if (CheckPotentialHit(&world_snapped,0, fp))
		{
			if(clipgrid(world_snapped, *vpt))
			{
				got_one = TRUE;
				HitMesh* hitmesh = new HitMesh(3);
				if(snapx)
				{
					hitmesh->setVert(0,tmconst * Point3(esnapped.x,esnapped.y - gridSpacing,0.0f));
					hitmesh->setVert(1,tmconst * Point3(esnapped.x,esnapped.y + gridSpacing,0.0f));
				}
				else
				{
					hitmesh->setVert(0,tmconst * Point3(esnapped.x - gridSpacing, esnapped.y,0.0f));
					hitmesh->setVert(1,tmconst * Point3(esnapped.x + gridSpacing, esnapped.y,0.0f));
				}
				theman->RecordHit(new OsnapHit(world_snapped, this, EDGE_SUB, hitmesh));
			}
		}
	}
}