Esempio n. 1
0
/*
* ChaseStep
*/
void G_ChaseStep( edict_t *ent, int step )
{
	int i, j;
	int start;
	edict_t *newtarget = NULL;

	if( !ent->r.client->resp.chase.active )
		return;

	i = start = ent->r.client->resp.chase.target;

	if( step == 0 )
	{
		if( G_Chase_IsValidTarget( ent, game.edicts + i, ent->r.client->resp.chase.teamonly ) )
			newtarget = game.edicts + i;
		else
			step = 1;
	}

	if( !newtarget )
	{
		for( j = 0; j < gs.maxclients; j++ )
		{
			i += step;
			if( i < 1 )
				i = gs.maxclients;
			else if( i > gs.maxclients )
				i = 1;
			if( i == start )
				break;
			if( G_Chase_IsValidTarget( ent, game.edicts + i, ent->r.client->resp.chase.teamonly ) )
			{	
				newtarget = game.edicts + i;
				break;
			}
		}
	}

	if( newtarget )
	{
		G_ChasePlayer( ent, va( "%i", PLAYERNUM( newtarget ) ), ent->r.client->resp.chase.teamonly, ent->r.client->resp.chase.followmode );
	}
}
Esempio n. 2
0
/*
* ChaseStep
*/
void G_ChaseStep( edict_t *ent, int step )
{
	int i, j, team;
	bool player_found;
	int actual;
	int start;
	edict_t *newtarget = NULL;

	assert( step == -1 || step == 0 || step == 1 );

	if( !ent->r.client->resp.chase.active )
		return;

	start = ent->r.client->resp.chase.target;
	i = -1;
	player_found = false; // needed to prevent an infinite loop if there are no players
	// find the team of the previously chased player and his index in the sorted teamlist
	for( team = TEAM_PLAYERS; team < GS_MAX_TEAMS; team++ )
	{
		for( j = 0; j < teamlist[team].numplayers; j++ )
		{
			player_found = true;
			if( teamlist[team].playerIndices[j] == start )
			{
				i = j;
				break;
			}
		}
		if( j != teamlist[team].numplayers )
			break;
	}

	if( step == 0 )
	{
		// keep chasing the current player if possible
		if( i >= 0 && G_Chase_IsValidTarget( ent, game.edicts + start, ent->r.client->resp.chase.teamonly ) )
			newtarget = game.edicts + start;
		else
			step = 1;
	}

	if( !newtarget && player_found )
	{
		// reset the team if the previously chased player was not found
		if( team == GS_MAX_TEAMS )
			team = TEAM_PLAYERS;
		for( j = 0; j < gs.maxclients; j++ )
		{
			// at this point step is -1 or 1
			i += step;
			// change to the previous team if we skipped before the start of this one
			// the loop assures empty teams before this team are skipped as well
			while( i < 0 )
			{
				team--;
				if( team < TEAM_PLAYERS )
					team = GS_MAX_TEAMS - 1;
				i = teamlist[team].numplayers - 1;
			}
			// similarly, change to the next team if we skipped past the end of this one
			while( i >= teamlist[team].numplayers )
			{
				team++;
				if( team == GS_MAX_TEAMS )
					team = TEAM_PLAYERS;
				i = 0;
			}
			actual = teamlist[team].playerIndices[i];
			if( actual == start )
				break; // back at the original player, no need to waste time
			if( G_Chase_IsValidTarget( ent, game.edicts + actual, ent->r.client->resp.chase.teamonly ) )
			{
				newtarget = game.edicts + actual;
				break;
			}
			// make another step if this player is not valid
		}
	}

	if( newtarget )
		G_ChasePlayer( ent, va( "%i", PLAYERNUM( newtarget ) ), ent->r.client->resp.chase.teamonly, ent->r.client->resp.chase.followmode );
}
Esempio n. 3
0
/*
* G_ChasePlayer
*/
void G_ChasePlayer( edict_t *ent, const char *name, bool teamonly, int followmode )
{
	int i;
	edict_t *e;
	gclient_t *client;
	int targetNum = -1;
	int oldTarget;
	bool can_follow = true;
	char colorlessname[MAX_NAME_BYTES];

	client = ent->r.client;

	oldTarget = client->resp.chase.target;

	if( teamonly && !client->teamstate.is_coach )
		can_follow = false;

	if( !can_follow && followmode )
	{
		G_PrintMsg( ent, "Chasecam follow mode unavailable\n" );
		followmode = false;
	}

	if( ent->r.client->resp.chase.followmode && !followmode )
		G_PrintMsg( ent, "Disabling chasecam follow mode\n" );

	// always disable chasing as a start
	memset( &client->resp.chase, 0, sizeof( chasecam_t ) );

	// locate the requested target
	if( name && name[0] )
	{
		// find it by player names
		for( e = game.edicts + 1; PLAYERNUM( e ) < gs.maxclients; e++ )
		{
			if( !G_Chase_IsValidTarget( ent, e, teamonly ) )
				continue;

			Q_strncpyz( colorlessname, COM_RemoveColorTokens( e->r.client->netname ), sizeof(colorlessname) );

			if( !Q_stricmp( COM_RemoveColorTokens( name ), colorlessname ) )
			{
				targetNum = PLAYERNUM( e );
				break;
			}
		}

		// didn't find it by name, try by numbers
		if( targetNum == -1 )
		{
			i = atoi( name );
			if( i >= 0 && i < gs.maxclients )
			{
				e = game.edicts + 1 + i;
				if( G_Chase_IsValidTarget( ent, e, teamonly ) )
					targetNum = PLAYERNUM( e );
			}
		}

		if( targetNum == -1 )
			G_PrintMsg( ent, "Requested chasecam target is not available\n" );
	}

	// try to reuse old target if we didn't find a valid one
	if( targetNum == -1 && oldTarget > 0 && oldTarget < gs.maxclients )
	{
		e = game.edicts + 1 + oldTarget;
		if( G_Chase_IsValidTarget( ent, e, teamonly ) )
			targetNum = PLAYERNUM( e );
	}

	// if we still don't have a target, just pick the first valid one
	if( targetNum == -1 )
	{
		for( e = game.edicts + 1; PLAYERNUM( e ) < gs.maxclients; e++ )
		{
			if( !G_Chase_IsValidTarget( ent, e, teamonly ) )
				continue;

			targetNum = PLAYERNUM( e );
			break;
		}
	}

	// make the client a ghost
	G_GhostClient( ent );
	if( targetNum != -1 )
	{
		// we found a target, set up the chasecam
		client->resp.chase.target = targetNum + 1;
		client->resp.chase.teamonly = teamonly;
		client->resp.chase.followmode = followmode;
		G_Chase_SetChaseActive( ent, true );
	}
	else
	{
		// stay as observer
		if( !teamonly )
			ent->movetype = MOVETYPE_NOCLIP;
		client->level.showscores = false;
		G_Chase_SetChaseActive( ent, false );
		G_CenterPrintMsg( ent, "No one to chase" );
	}
}
Esempio n. 4
0
/*
* G_EndFrame_UpdateChaseCam
*/
static void G_EndFrame_UpdateChaseCam( edict_t *ent )
{
	edict_t *targ;
	int followpov;

	// not in chasecam
	if( !ent->r.client->resp.chase.active )
		return;

	if( ( followpov = G_Chase_FindFollowPOV( ent ) ) != -1 )
		ent->r.client->resp.chase.target = followpov;

	// is our chase target gone?
	targ = &game.edicts[ent->r.client->resp.chase.target];

	if( !G_Chase_IsValidTarget( ent, targ, ent->r.client->resp.chase.teamonly ) )
	{
		if( game.realtime < ent->r.client->resp.chase.timeout ) // wait for timeout
			return;

		ent->r.client->resp.chase.timeout = game.realtime + 1500; // update timeout

		G_ChasePlayer( ent, NULL, ent->r.client->resp.chase.teamonly, ent->r.client->resp.chase.followmode );
		targ = &game.edicts[ent->r.client->resp.chase.target];
		if( !G_Chase_IsValidTarget( ent, targ, ent->r.client->resp.chase.teamonly ) )
			return;
	}

	ent->r.client->resp.chase.timeout = game.realtime + 1500; // update timeout

	if( targ == ent )
		return;

	// free our psev buffer when in chasecam
	G_ClearPlayerStateEvents( ent->r.client );

	// copy target playerState to me
	ent->r.client->ps = targ->r.client->ps;

	// fix some stats we don't want copied from the target
	ent->r.client->ps.stats[STAT_REALTEAM] = ent->s.team;
	ent->r.client->ps.stats[STAT_LAYOUTS] &= ~STAT_LAYOUT_SCOREBOARD;
	ent->r.client->ps.stats[STAT_LAYOUTS] &= ~STAT_LAYOUT_CHALLENGER;
	ent->r.client->ps.stats[STAT_LAYOUTS] &= ~STAT_LAYOUT_READY;
	ent->r.client->ps.stats[STAT_LAYOUTS] &= ~STAT_LAYOUT_SPECTEAMONLY;
	ent->r.client->ps.stats[STAT_LAYOUTS] &= ~STAT_LAYOUT_INSTANTRESPAWN;

	if( ent->r.client->resp.chase.teamonly )
	{
		ent->r.client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_SPECTEAMONLY;
		if( !ent->r.client->teamstate.is_coach )
			ent->r.client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_SPECDEAD; // show deadcam effect
	}

	if( ent->r.client->level.showscores || GS_MatchState() >= MATCH_STATE_POSTMATCH )
		ent->r.client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_SCOREBOARD; // show the scoreboard

	if( GS_HasChallengers() && ent->r.client->queueTimeStamp )
		ent->r.client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_CHALLENGER;

	if( GS_MatchState() <= MATCH_STATE_WARMUP && level.ready[PLAYERNUM( ent )] )
		ent->r.client->ps.stats[STAT_LAYOUTS] |= STAT_LAYOUT_READY;

	// chasecam uses PM_CHASECAM
	ent->r.client->ps.pmove.pm_type = PM_CHASECAM;
	ent->r.client->ps.pmove.pm_flags |= PMF_NO_PREDICTION;

	VectorCopy( targ->s.origin, ent->s.origin );
	VectorCopy( targ->s.angles, ent->s.angles );
	GClip_LinkEntity( ent );
}