GetLocalPlayer

From Valve Developer Community
Jump to navigation Jump to search

UTIL_GetLocalPlayer is a function that's used extensively in the Source SDK 2013 code base. Unfortunately, it always returns null in Multiplayer and therefore doesn't work. When fixing this code up, you can use multiple other functions to replace UTIL_GetLocalPlayer depending on the situation.

UTIL_GetListenServerHost

UTIL_GetListenServerHost already exists in the codebase, so you won't need to insert any additional code. Obviously, the function returns the listenserver-host, which is the client that also hosts the "server" on his machine. When on a dedicated server, NULL will be returned.

UTIL_GetNearestPlayer

UTIL_GetNearestPlayer can be incredibly useful when fixing up code for multiplayer, however you'll need to add it into your code first as it was not written by Valve. To do this, open up util.cpp and paste the following function underneath the GetLocalPlayer() function at around line 660.

//
// Returns nearest player. 
// Control with boolean if line of sight is needed.
//
CBasePlayer *UTIL_GetNearestPlayer(CBaseEntity *pLooker, bool bNeedsLOS)
{
	float flFinalDistance = 999999.0f;
	CBasePlayer *pFinalPlayer = NULL;

	for (int i = 1; i < gpGlobals->maxClients; i++)
	{
		CBasePlayer *pPlayer = UTIL_PlayerByIndex(i);

		if (!pPlayer){
			continue;
		}

		float flDistance = (pPlayer->GetAbsOrigin() - pLooker->GetAbsOrigin()).LengthSqr();

		if (flDistance < flFinalDistance)
		{
			if (bNeedsLOS)
			{
				//Check if the player is visible to the entity (only brushes obstruct vision)
				if (!pLooker->FVisible(pPlayer, MASK_SOLID_BRUSHONLY))
				{
					continue;
				}				
			}
			
			pFinalPlayer = pPlayer;
			flFinalDistance = flDistance;
		}
	}

	return pFinalPlayer;
}

Now add this line in util.h at line 231:

CBasePlayer *UTIL_GetNearestPlayer(CBaseEntity *pLooker, bool needsLOS = false);

By default, you will only need to pass the entity pointer through the parameters and the nearest player will be returned. If you only want the nearest visible player returned, you also need to pass a (true) boolean.

Fix up UTIL_GetLocalPlayer

This is not a proper solution, UTIL_GetLocalPlayer will never work properly in multiplayer because of its very concept. However, you can still fix it up to return a player, even when in multiplayer mode.

In util.cpp, search for the UTIL_GetLocalPlayer() function. Delete it and replace it with:

//
// Return the listenserver-host.
// If that's not possible, try to return literally ANY player
// 
CBasePlayer *UTIL_GetLocalPlayer( void )
{
	//try to return the listenserver-host
	CBasePlayer *pHost = UTIL_GetListenServerHost();
	if (pHost){
		return pHost;
	}

	//try to return literally any other client on the server
	for (int i = 1; i < gpGlobals->maxClients; i++)
	{
		CBasePlayer *pPlayer = UTIL_PlayerByIndex(i);

		if (pPlayer){
			return pPlayer;
		}	
	}

	return NULL;
}