Beispiel #1
0
/*
==============
JoinedTeam
==============
A player just joined a team, so do things.
*/
void JoinedTeam (edict_t *ent, qboolean reconnected, qboolean notify)
{
	PMenu_Close (ent);

	if (notify)
	{
		if (g_gamemode->value != GAMEMODE_1V1)
			gi.bprintf (PRINT_HIGH, "%s %sjoined team '%s'\n", ent->client->pers.netname, reconnected ? "re" : "", teaminfo[ent->client->pers.team].name);
		else
			gi.bprintf (PRINT_HIGH, "%s %sjoined the game.\n", ent->client->pers.netname, reconnected ? "re" : "");
	}

	ent->client->resp.ready = false;

	//joining a team with no captain by default assigns.
	//FIXME: should this still assign even if the team has existing players?
	if (!teaminfo[ent->client->pers.team].captain)
		TDM_SetCaptain (ent->client->pers.team, ent);

	//nasty hack for setting team names for 1v1 mode
	TDM_UpdateTeamNames ();

	//if we were invited mid-game, reallocate and insert into teamplayers
	// wision: do not add if a player reconnected and used his joincode
	// skuller: force add if player was picked/invited to the different team
	if (tdm_match_status != MM_WARMUP && !reconnected && (!ent->client->resp.teamplayerinfo || ent->client->resp.teamplayerinfo->team != ent->client->pers.team))
		TDM_AddPlayerToMatchinfo (ent);

	//wision: set skin for new player
	gi.configstring (CS_PLAYERSKINS + (ent - g_edicts) - 1, va("%s\\%s", ent->client->pers.netname, teaminfo[ent->client->pers.team].skin));

	//set everyone elses teamskin for this player based on what team he is on
	TDM_SetAllTeamSkins (ent);

	//set this players teamskins based on his team
	TDM_SetTeamSkins (ent, NULL);

	if (g_gamemode->value != GAMEMODE_1V1)
		gi.configstring (CS_TDM_SPECTATOR_STRINGS + (ent - g_edicts) - 1, va ("%s (%s)", ent->client->pers.netname, teaminfo[ent->client->pers.team].name));
	else
		gi.configstring (CS_TDM_SPECTATOR_STRINGS + (ent - g_edicts) - 1, ent->client->pers.netname);

	TDM_TeamsChanged ();
	respawn (ent);

	// switch from spec to player statusbar, if weapon hud is enabled, that'll happen in respawn()
	if (!UF(ent, WEAPON_HUD)) {
		TDM_UpdateHud(ent, true);
	}
}
Beispiel #2
0
/*
==============
ToggleChaseCam
==============
Player hit Spectator menu option or used
chase command.
*/
void ToggleChaseCam (edict_t *ent)
{
    if (ent->client->pers.team)
    {
        TDM_LeftTeam (ent, true);
        TDM_TeamsChanged ();
        if (tdm_match_status == MM_TIMEOUT && teaminfo[TEAM_A].players == 0 && teaminfo[TEAM_B].players == 0)
            TDM_ResumeGame ();
        respawn (ent);
    }

    if (ent->client->chase_target)
        DisableChaseCam (ent);
    else
        GetChaseTarget(ent);

    PMenu_Close (ent);
}
Beispiel #3
0
/*
==============
TDM_SetupClient
==============
Setup the client after an initial connection. Called on first spawn
only, not every map. Returns true if a join code was used to respawn
a full player, so that PutClientInServer knows about it.
*/
qboolean TDM_SetupClient (edict_t *ent)
{
	ent->client->pers.team = TEAM_SPEC;
	TDM_TeamsChanged ();

	//handled in userinfo updates now
	//TDM_DownloadPlayerConfig (ent);

	if (!TDM_ProcessJoinCode (ent, 0))
	{
		if (tdm_match_status == MM_TIMEOUT)
		{
			gi.cprintf (ent, PRINT_CHAT, "\nMatch is currently paused and will auto resume in %s.\n", TDM_SecsToString(FRAMES_TO_SECS(level.timeout_end_framenum - level.realframenum)));
		}
		else
		{
			TDM_ShowTeamMenu (ent);
			gi.cprintf (ent, PRINT_CHAT, "\nWelcome to OpenTDM!\nType 'commands' in the console for a brief command guide.\n\n");
		}
	}
	else
	{
		if (tdm_match_status == MM_TIMEOUT)
		{
			if (TDM_Is1V1())
			{
				//only resume if we have 2 players - it's possible both players dropped, and that is a situation
				//we need to be able to handle.
				if (teaminfo[TEAM_A].players == 1 && teaminfo[TEAM_B].players == 1)
					TDM_ResumeGame ();
				return true;
			}
		}
	}

	return false;
}
Beispiel #4
0
/*
==============
TDM_Disconnected
==============
A player disconnected, do things.
*/
void TDM_Disconnected (edict_t *ent)
{
	qboolean	removeTimeout;

	removeTimeout = false;

	//have to check this right up here since we nuke the teamplayer just below!
	if (tdm_match_status == MM_TIMEOUT && level.tdm_timeout_caller && level.tdm_timeout_caller->client == ent)
		removeTimeout = true;

	//we remove this up here so TDM_LeftTeam doesn't try to resume if we become implicit timeout caller
	TDM_RemoveStatsLink (ent);

	if (ent->client->pers.team)
	{
		if (tdm_match_status >= MM_PLAYING && tdm_match_status != MM_SCOREBOARD)
		{
			//do joincode stuff if a team player disconnects - save all their client info
			ent->client->resp.teamplayerinfo->saved_client = gi.TagMalloc (sizeof(gclient_t), TAG_GAME);
			*ent->client->resp.teamplayerinfo->saved_client = *ent->client;

			ent->client->resp.teamplayerinfo->saved_entity = gi.TagMalloc (sizeof(edict_t), TAG_GAME);
			*ent->client->resp.teamplayerinfo->saved_entity = *ent;

			if (TDM_Is1V1() && g_1v1_timeout->value > 0)
			{
				edict_t		*ghost;

				//may have already been set by a player or previous client disconnect
				if (tdm_match_status != MM_TIMEOUT)
				{	
					edict_t		*opponent;

					//timeout is called implicitly in 1v1 games or the other player would auto win
					level.timeout_end_framenum = level.realframenum + SECS_TO_FRAMES(g_1v1_timeout->value);
					level.last_tdm_match_status = tdm_match_status;
					tdm_match_status = MM_TIMEOUT;

					level.tdm_timeout_caller = ent->client->resp.teamplayerinfo;
					gi.bprintf (PRINT_CHAT, "%s disconnected and has %s to reconnect.\n", level.tdm_timeout_caller->name, TDM_SecsToString (g_1v1_timeout->value));

					//show the opponent their options
					opponent = TDM_FindPlayerForTeam (TEAM_A);
					if (opponent)
						gi.cprintf (opponent, PRINT_HIGH, "Your opponent has disconnected. You can allow them %s to reconnect, or you can force a forfeit by typing 'win' in the console.\n", TDM_SecsToString (g_1v1_timeout->value));

					opponent = TDM_FindPlayerForTeam (TEAM_B);
					if (opponent)
						gi.cprintf (opponent, PRINT_HIGH, "Your opponent has disconnected. You can allow them %s to reconnect, or you can force a forfeit by typing 'win' in the console.\n", TDM_SecsToString (g_1v1_timeout->value));
				}

				//show a "ghost" player where the player was
				ghost = G_Spawn ();
				VectorCopy (ent->s.origin, ghost->s.origin);
				VectorCopy (ent->s.origin, ghost->old_origin);
				VectorCopy (ent->s.angles, ghost->s.angles);
				ghost->s.effects = EF_SPHERETRANS;
				ghost->s.modelindex = 255;
				ghost->s.modelindex2 = 255;
				ghost->s.skinnum = ent - g_edicts - 1;
				ghost->s.frame = ent->s.frame;
				ghost->count = ent->s.number;
				ghost->classname = "ghost";
				ghost->target_ent = ent;
				ghost->enttype = ENT_GHOST;
				gi.linkentity (ghost);
			}
		}

		if (removeTimeout)
			TDM_ResumeGame ();

		TDM_LeftTeam (ent, false);
	}

	TDM_TeamsChanged ();

	if (tdm_match_status == MM_WARMUP && teaminfo[TEAM_SPEC].players == 0 && teaminfo[TEAM_A].players == 0 && teaminfo[TEAM_B].players == 0)
	{
		if (vote.active)
			TDM_RemoveVote ();

		//reset the map if it's been running for over 7 days to workaround time precision bugs in the engine, fixes 0000208
		if (time (NULL) - level.spawntime > (86400 * 7))
		{
			char	command[256];
			Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", level.mapname);
			gi.AddCommandString (command);
		}
	}
	else
		TDM_CheckVote ();

	//zero for connecting clients on server browsers
	ent->client->ps.stats[STAT_FRAGS] = 0;
}