/*
* G_RunGametype
*/
void G_RunGametype( void )
{
	G_Teams_ExecuteChallengersQueue();
	G_Teams_UpdateMembersList();
	G_Match_CheckStateAbort();

	G_UpdateScoreBoardMessages();

	//check gametype specific rules
	if( game.asEngine != NULL )
		GT_asCallThinkRules();
	else
		G_Gametype_GENERIC_ThinkRules();

	if( G_EachNewSecond() )
	{
		G_CheckNumBots();
		G_TickOutPowerUps();
	}

	if( G_EachNewMinute() )
		G_CheckEvenTeam();

	G_Match_ScoreAnnouncement();
	G_Match_ReadyAnnouncement();

	if( GS_TeamBasedGametype() )
		G_Teams_UpdateTeamInfoMessages();

	G_asGarbageCollect( false );
}
Beispiel #2
0
/*
* G_Teams_AdvanceChallengersQueue
*/
void G_Teams_AdvanceChallengersQueue( void )
{
	int i, team, loserscount, winnerscount, playerscount = 0;
	int maxscore = 999999;
	edict_t *won, *e;
	int START_TEAM = TEAM_PLAYERS, END_TEAM = TEAM_PLAYERS+1;

	if( !GS_HasChallengers() )
		return;

	G_Teams_UpdateMembersList();

	if( GS_TeamBasedGametype() )
	{
		START_TEAM = TEAM_ALPHA;
		END_TEAM = GS_MAX_TEAMS;
	}

	// assign new timestamps to all the players inside teams
	for( team = START_TEAM; team < END_TEAM; team++ )
	{
		playerscount += teamlist[team].numplayers;
	}

	if( !playerscount )
		return;

	loserscount = 0;
	if( playerscount > 1 )
	{
		loserscount = (int)( playerscount / 2 );
	}
	winnerscount = playerscount - loserscount;

	// put everyone who just played out of the challengers queue
	for( team = START_TEAM; team < END_TEAM; team++ )
	{
		for( i = 0; i < teamlist[team].numplayers; i++ )
		{
			e = game.edicts + teamlist[team].playerIndices[i];
			e->r.client->queueTimeStamp = 0;
		}
	}

	// put (back) the best scoring players in first positions of challengers queue
	for( i = 0; i < winnerscount; i++ )
	{
		won = G_Teams_BestScoreBelow( maxscore );
		if( won )
		{
			maxscore = won->r.client->level.stats.score;
			won->r.client->queueTimeStamp = 1 + ( winnerscount-i ); // never have 2 players with the same timestamp
		}
	}
}
Beispiel #3
0
/*
* G_Teams_JoinTeam - checks that client can join the given team and then joins it
*/
bool G_Teams_JoinTeam( edict_t *ent, int team )
{
	int error;

	G_Teams_UpdateMembersList(); // make sure we have up-to-date data

	if( !ent->r.client )
		return false;

	if( ( error = G_GameTypes_DenyJoinTeam( ent, team ) ) )
	{
		if( error == ER_TEAM_INVALID )
		{
			G_PrintMsg( ent, "Can't join %s in %s\n", GS_TeamName( team ),
				gs.gametypeName );
		}
		else if( error == ER_TEAM_CHALLENGERS )
		{
			G_Teams_JoinChallengersQueue( ent );
		}
		else if( error == ER_TEAM_FULL )
		{
			G_PrintMsg( ent, "Team %s is FULL\n", GS_TeamName( team ) );
			G_Teams_JoinChallengersQueue( ent );
		}
		else if( error == ER_TEAM_LOCKED )
		{
			G_PrintMsg( ent, "Team %s is LOCKED\n", GS_TeamName( team ) );
			G_Teams_JoinChallengersQueue( ent );
		}
		else if( error == ER_TEAM_MATCHSTATE )
		{
			G_PrintMsg( ent, "Can't join %s at this moment\n", GS_TeamName( team ) );
		}
		else if( error == ER_TEAM_UNEVEN )
		{
			G_PrintMsg( ent, "Can't join %s because of uneven teams\n", GS_TeamName( team ) ); // FIXME: need more suitable message :P
			G_Teams_JoinChallengersQueue( ent );
		}
		return false;
	}

	//ok, can join, proceed
	G_Teams_SetTeam( ent, team );
	return true;
}
Beispiel #4
0
/*
* G_Teams_JoinAnyTeam - find us a team since we are too lazy to do ourselves
*/
bool G_Teams_JoinAnyTeam( edict_t *ent, bool silent )
{
	int best_numplayers = gs.maxclients + 1, best_score = 999999;
	int i, team = -1;
	bool wasinqueue = ( ent->r.client->queueTimeStamp != 0 );

	G_Teams_UpdateMembersList(); // make sure we have up-to-date data

	//depending on the gametype, of course
	if( !GS_TeamBasedGametype() )
	{
		if( ent->s.team == TEAM_PLAYERS )
		{
			if( !silent )
			{
				G_PrintMsg( ent, "You are already in %s team\n", GS_TeamName( TEAM_PLAYERS ) );
			}
			return false;
		}
		if( G_Teams_JoinTeam( ent, TEAM_PLAYERS ) )
		{
			if( !silent )
			{
				G_PrintMsg( NULL, "%s%s joined the %s team.\n",
					ent->r.client->netname, S_COLOR_WHITE, GS_TeamName( ent->s.team ) );
			}
		}
		return true;

	}
	else
	{       //team based

		//find the available team with smaller player count or worse score
		for( i = TEAM_ALPHA; i < GS_MAX_TEAMS; i++ )
		{
			if( G_GameTypes_DenyJoinTeam( ent, i ) )
			{
				continue;
			}

			if( team == -1 || teamlist[i].numplayers < best_numplayers
					|| ( teamlist[i].numplayers == best_numplayers && teamlist[i].stats.score < best_score ) )
			{
				best_numplayers = teamlist[i].numplayers;
				best_score = teamlist[i].stats.score;
				team = i;
			}
		}

		if( team == ent->s.team )
		{                   // he is at the right team
			if( !silent )
			{
				G_PrintMsg( ent, "%sCouldn't find a better team than team %s.\n",
					S_COLOR_WHITE, GS_TeamName( ent->s.team ) );
			}
			return false;
		}

		if( team != -1 )
		{
			if( G_Teams_JoinTeam( ent, team ) )
			{
				if( !silent )
				{
					G_PrintMsg( NULL, "%s%s joined the %s team.\n",
						ent->r.client->netname, S_COLOR_WHITE, GS_TeamName( ent->s.team ) );
				}
				return true;
			}
		}
		if( GS_MatchState() <= MATCH_STATE_PLAYTIME && !silent )
			G_Teams_JoinChallengersQueue( ent );
	}

	// don't print message if we joined the queue
	if( !silent && ( !GS_HasChallengers() || wasinqueue || !ent->r.client->queueTimeStamp ) )
		G_PrintMsg( ent, "You can't join the game now\n" );

	return false;
}
Beispiel #5
0
/*
* G_ClientRespawn
*/
void G_ClientRespawn( edict_t *self, bool ghost )
{
	int i;
	edict_t *spawnpoint;
	vec3_t hull_mins, hull_maxs;
	vec3_t spawn_origin, spawn_angles;
	gclient_t *client;
	int old_team;

	G_DeathAwards( self );

	G_SpawnQueue_RemoveClient( self );

	self->r.svflags &= ~SVF_NOCLIENT;

	//if invalid be spectator
	if( self->r.client->team < 0 || self->r.client->team >= GS_MAX_TEAMS )
		self->r.client->team = TEAM_SPECTATOR;

	// force ghost always to true when in spectator team
	if( self->r.client->team == TEAM_SPECTATOR )
		ghost = true;

	old_team = self->s.team;
	if( self->r.client->teamstate.is_coach )
		ghost = true;

	GClip_UnlinkEntity( self );

	client = self->r.client;

	memset( &client->resp, 0, sizeof( client->resp ) );
	memset( &client->ps, 0, sizeof( client->ps ) );
	client->resp.timeStamp = level.time;
	client->ps.playerNum = PLAYERNUM( self );

	// clear entity values
	memset( &self->snap, 0, sizeof( self->snap ) );
	memset( &self->s, 0, sizeof( self->s ) );
	memset( &self->olds, 0, sizeof( self->olds ) );
	memset( &self->invpak, 0, sizeof( self->invpak ) );

	self->s.number = self->olds.number = ENTNUM( self );

	// relink client struct
	self->r.client = &game.clients[PLAYERNUM( self )];

	// update team
	self->s.team = client->team;

	self->deadflag = DEAD_NO;
	self->s.type = ET_PLAYER;
	self->groundentity = NULL;
	self->takedamage = DAMAGE_AIM;
	self->think = player_think;
	self->pain = player_pain;
	self->die = player_die;
	self->viewheight = playerbox_stand_viewheight;
	self->r.inuse = true;
	self->mass = PLAYER_MASS;
	self->air_finished = level.time + ( 12 * 1000 );
	self->r.clipmask = MASK_PLAYERSOLID;
	self->waterlevel = 0;
	self->watertype = 0;
	self->flags &= ~FL_NO_KNOCKBACK;
	self->r.svflags &= ~SVF_CORPSE;
	self->enemy = NULL;
	self->r.owner = NULL;
	self->max_health = 100;
	self->health = self->max_health;

	if( AI_GetType( self->ai ) == AI_ISBOT )
	{
		self->think = NULL;
		self->classname = "bot";
	}
	else if( self->r.svflags & SVF_FAKECLIENT )
		self->classname = "fakeclient";
	else
		self->classname = "player";

	VectorCopy( playerbox_stand_mins, self->r.mins );
	VectorCopy( playerbox_stand_maxs, self->r.maxs );
	VectorClear( self->velocity );
	VectorClear( self->avelocity );

	VectorCopy( self->r.mins, hull_mins );
	VectorCopy( self->r.maxs, hull_maxs );
	trap_CM_RoundUpToHullSize( hull_mins, hull_maxs, NULL );
	if( self->r.maxs[2] > hull_maxs[2] )
		self->viewheight -= (self->r.maxs[2] - hull_maxs[2]);

	client->ps.POVnum = ENTNUM( self );

	// set movement info
	client->ps.pmove.stats[PM_STAT_MAXSPEED] = (short)DEFAULT_PLAYERSPEED;
	client->ps.pmove.stats[PM_STAT_JUMPSPEED] = (short)DEFAULT_JUMPSPEED;
	client->ps.pmove.stats[PM_STAT_DASHSPEED] = (short)DEFAULT_DASHSPEED;

	if( ghost )
	{
		self->r.solid = SOLID_NOT;
		self->movetype = MOVETYPE_NOCLIP;
		if( self->s.team == TEAM_SPECTATOR )
			self->r.svflags |= SVF_NOCLIENT;
	}
	else
	{
		self->r.client->resp.takeStun = true;
		self->r.solid = SOLID_YES;
		self->movetype = MOVETYPE_PLAYER;
		client->ps.pmove.stats[PM_STAT_FEATURES] = static_cast<unsigned short>(PMFEAT_DEFAULT);
		if( !g_allow_bunny->integer )
			client->ps.pmove.stats[PM_STAT_FEATURES] &= ~( PMFEAT_AIRCONTROL|PMFEAT_FWDBUNNY );
	}

	ClientUserinfoChanged( self, client->userinfo );

	if( old_team != self->s.team )
		G_Teams_UpdateMembersList();

	SelectSpawnPoint( self, &spawnpoint, spawn_origin, spawn_angles );
	VectorCopy( spawn_origin, client->ps.pmove.origin );
	VectorCopy( spawn_origin, self->s.origin );
	VectorCopy( self->s.origin, self->s.old_origin );

	// set angles
	self->s.angles[PITCH] = 0;
	self->s.angles[YAW] = anglemod( spawn_angles[YAW] );
	self->s.angles[ROLL] = 0;
	VectorCopy( self->s.angles, client->ps.viewangles );

	// set the delta angle
	for( i = 0; i < 3; i++ )
		client->ps.pmove.delta_angles[i] = ANGLE2SHORT( client->ps.viewangles[i] ) - client->ucmd.angles[i];

	// don't put spectators in the game
	if( !ghost )
	{
		if( KillBox( self ) )
		{
		}
	}

	self->s.attenuation = ATTN_NORM;

	self->s.teleported = true;

	// hold in place briefly
	client->ps.pmove.pm_flags = PMF_TIME_TELEPORT;
	client->ps.pmove.pm_time = 14;
	client->ps.pmove.stats[PM_STAT_NOUSERCONTROL] = CLIENT_RESPAWN_FREEZE_DELAY;
	client->ps.pmove.stats[PM_STAT_NOAUTOATTACK] = 1000;

	// set race stats to invisible
	client->ps.stats[STAT_TIME_SELF] = STAT_NOTSET;
	client->ps.stats[STAT_TIME_BEST] = STAT_NOTSET;
	client->ps.stats[STAT_TIME_RECORD] = STAT_NOTSET;
	client->ps.stats[STAT_TIME_ALPHA] = STAT_NOTSET;
	client->ps.stats[STAT_TIME_BETA] = STAT_NOTSET;

	BOT_Respawn( self );

	self->r.client->level.respawnCount++;

	G_UseTargets( spawnpoint, self );

	GClip_LinkEntity( self );

	// let the gametypes perform their changes
	if( game.asEngine != NULL )
		GT_asCallPlayerRespawn( self, old_team, self->s.team );
	else
		G_Gametype_GENERIC_ClientRespawn( self, old_team, self->s.team );
}