|
/*** * * Copyright (c) 1999, 2000 Valve LLC. All rights reserved. * * This product contains software technology licensed from Id * Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. * All Rights Reserved. * * Use, distribution, and modification of this source code and/or resulting * object code is restricted to non-commercial enhancements to products from * Valve LLC. All other use, distribution, or modification is prohibited * without written permission from Valve LLC. * ****/ // // teamplay_gamerules.cpp // #include "extdll.h" #include "util.h" #include "cbase.h" #include "player.h" #include "weapons.h" #include "gamerules.h" #include "afctf_gamerules.h" #include "game.h"
static char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH]; static int team_scores[MAX_TEAMS]; static int num_teams = 0;
extern DLL_GLOBAL BOOL g_fGameOver;
CHalfLifeAFCTF :: CHalfLifeAFCTF() { m_DisableDeathMessages = FALSE; m_DisableDeathPenalty = FALSE;
memset( team_names, 0, sizeof(team_names) ); memset( team_scores, 0, sizeof(team_scores) ); num_teams = 0;
// Copy over the team from the server config m_szTeamList[0] = 0;
// Cache this because the team code doesn't want to deal with changing this in the middle of a game strncpy( m_szTeamList, teamlist.string, TEAMPLAY_TEAMLISTLENGTH );
edict_t *pWorld = INDEXENT(0); if ( pWorld && pWorld->v.team ) { if ( teamoverride.value ) { const char *pTeamList = STRING(pWorld->v.team); if ( pTeamList && strlen(pTeamList) ) { strncpy( m_szTeamList, pTeamList, TEAMPLAY_TEAMLISTLENGTH ); } } } // Has the server set teams if ( strlen( m_szTeamList ) ) m_teamLimit = TRUE; else m_teamLimit = FALSE;
RecountTeams(); }
extern cvar_t timeleft, fragsleft;
void CHalfLifeAFCTF :: Think ( void ) { ///// Check game rules ///// static int last_frags; static int last_time;
int frags_remaining = 0; int time_remaining = 0;
if ( g_fGameOver ) // someone else quit the game already { CHalfLifeAFCTF::Think(); return; }
float flTimeLimit = CVAR_GET_FLOAT("mp_timelimit") * 60; time_remaining = (int)(flTimeLimit ? ( flTimeLimit - gpGlobals->time ) : 0);
if ( flTimeLimit != 0 && gpGlobals->time >= flTimeLimit ) { GoToIntermission(); return; }
float flFragLimit = fraglimit.value; if ( flFragLimit ) { int bestfrags = 9999; int remain;
// check if any team is over the frag limit for ( int i = 0; i < num_teams; i++ ) { if ( team_scores[i] >= flFragLimit ) { GoToIntermission(); return; }
remain = flFragLimit - team_scores[i]; if ( remain < bestfrags ) { bestfrags = remain; } } frags_remaining = bestfrags; }
// Updates when frags change if ( frags_remaining != last_frags ) { g_engfuncs.pfnCvar_DirectSet( &fragsleft, UTIL_VarArgs( "%i", frags_remaining ) ); }
// Updates once per second if ( timeleft.value != last_time ) { g_engfuncs.pfnCvar_DirectSet( &timeleft, UTIL_VarArgs( "%i", time_remaining ) ); }
last_frags = frags_remaining; last_time = time_remaining; }
//========================================================= // ClientCommand // the user has typed a command which is unrecognized by everything else; // this check to see if the gamerules knows anything about the command //========================================================= BOOL CHalfLifeAFCTF :: ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) { char szMenu [512]; char text [1024];
if ( FStrEq( pcmd, "menuselect" ) ) { if ( CMD_ARGC() < 2 ) return TRUE;
int slot = atoi( CMD_ARGV(1) );
// select the item from the current menu switch(pPlayer->m_nMenu) case Menu_ChangeTeam: { if (slot == 1) { //If already on this team, do nothing if (FStrEq(pPlayer->m_szTeamName, AFCTF_TEAM1_NAME)) { return TRUE; } //Join the team sprintf( text, "%s joined the Blue team\n",STRING(pPlayer->pev->netname)); UTIL_SayText( text, pPlayer ); //When observer, make it respawnable, let it join a team and then respawn if ( pPlayer->m_afPhysicsFlags & PFLAG_OBSERVER) { pPlayer->pev->deadflag = DEAD_RESPAWNABLE; ChangePlayerTeam( pPlayer, AFCTF_TEAM1_NAME, FALSE, FALSE ); // recound stuff RecountTeams(); pPlayer->Spawn(); } //Else just switch teams else { ChangePlayerTeam( pPlayer, AFCTF_TEAM1_NAME, TRUE, TRUE ); // recound stuff RecountTeams(); } } else if (slot == 2) { //If already on this team, do nothing if (FStrEq(pPlayer->m_szTeamName, AFCTF_TEAM2_NAME)) { return TRUE; } //Join the team sprintf( text, "%s joined the Red team\n",STRING(pPlayer->pev->netname)); UTIL_SayText( text, pPlayer ); //When observer, make it respawnable, let it join a team and then respawn if ( pPlayer->m_afPhysicsFlags & PFLAG_OBSERVER) { pPlayer->pev->deadflag = DEAD_RESPAWNABLE; ChangePlayerTeam( pPlayer, AFCTF_TEAM2_NAME, FALSE, FALSE ); // recound stuff RecountTeams(); pPlayer->Spawn(); } //Else just switch teams else { ChangePlayerTeam( pPlayer, AFCTF_TEAM2_NAME, TRUE, TRUE ); // recound stuff RecountTeams(); } } else if (slot == 3) { //If already on the smallest team, do nothing if (FStrEq(pPlayer->m_szTeamName,TeamWithFewestPlayers())) { return TRUE; } sprintf( text, "%s joined the %s team\n",STRING(pPlayer->pev->netname), TeamWithFewestPlayers()); UTIL_SayText( text, pPlayer ); //When observer, make it respawnable, let it join a team and then respawn if ( pPlayer->m_afPhysicsFlags & PFLAG_OBSERVER) { pPlayer->pev->deadflag = DEAD_RESPAWNABLE; ChangePlayerTeam( pPlayer, TeamWithFewestPlayers(), FALSE, FALSE ); // recound stuff RecountTeams(); pPlayer->Spawn(); } //Else just switch teams else { ChangePlayerTeam( pPlayer, TeamWithFewestPlayers(), TRUE, TRUE ); // recound stuff RecountTeams(); } } }
return TRUE; } else if ( FStrEq( pcmd, "changeteam" ) ) { //Make sure he's not dead if (!pPlayer->IsAlive()) return TRUE;
pPlayer->m_nMenu = Menu_ChangeTeam; strcpy (szMenu, "Select a team\n\n"); strcat (szMenu, "1. Army Team\n"); strcat (szMenu, "2. Security Team\n\n"); strcat (szMenu, "3. Autoteam"); ShowMenu (pPlayer, 0x7, 0, 0, szMenu);
return TRUE; } return FALSE; }
extern int gmsgGameMode; extern int gmsgSayText; extern int gmsgTeamInfo;
void CHalfLifeAFCTF :: UpdateGameMode( CBasePlayer *pPlayer ) { MESSAGE_BEGIN( MSG_ONE, gmsgGameMode, NULL, pPlayer->edict() ); WRITE_BYTE( 1 ); // game mode teamplay MESSAGE_END(); }
const char *CHalfLifeAFCTF::SetDefaultPlayerTeam( CBasePlayer *pPlayer ) { // copy out the team name from the model char *mdls = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model" ); strncpy( pPlayer->m_szTeamName, mdls, TEAM_NAME_LENGTH );
RecountTeams();
// update the current player of the team he is joining if ( pPlayer->m_szTeamName[0] == '\0' || !IsValidTeam( pPlayer->m_szTeamName ) || defaultteam.value ) { const char *pTeamName = NULL; if ( defaultteam.value ) { pTeamName = team_names[0]; } else { pTeamName = TeamWithFewestPlayers(); } strncpy( pPlayer->m_szTeamName, pTeamName, TEAM_NAME_LENGTH ); }
return pPlayer->m_szTeamName; }
//========================================================= // InitHUD //========================================================= void CHalfLifeAFCTF::InitHUD( CBasePlayer *pPlayer ) { //SetDefaultPlayerTeam( pPlayer ); CHalfLifeMultiplay::InitHUD( pPlayer );
RecountTeams();
char *mdls = g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model" ); // update the current player of the team he is joining char text[1024]; if ( !strcmp( mdls, pPlayer->m_szTeamName ) ) { sprintf( text, "* you are on team \'%s\'\n", pPlayer->m_szTeamName ); } else { sprintf( text, "* assigned to team %s\n", pPlayer->m_szTeamName ); }
ChangePlayerTeam( pPlayer, pPlayer->m_szTeamName, FALSE, FALSE ); UTIL_SayText( text, pPlayer ); int clientIndex = pPlayer->entindex(); RecountTeams(); // update this player with all the other players team info // loop through all active players and send their team info to the new client for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBaseEntity *plr = UTIL_PlayerByIndex( i ); if ( plr && IsValidTeam( plr->TeamID() ) ) { MESSAGE_BEGIN( MSG_ONE, gmsgTeamInfo, NULL, pPlayer->edict() ); WRITE_BYTE( plr->entindex() ); WRITE_STRING( plr->TeamID() ); MESSAGE_END(); } } if ( pPlayer->m_afPhysicsFlags & PFLAG_OBSERVER) { char szMenu [512] pPlayer->m_nMenu = Menu_ChangeTeam; strcpy (szMenu, "Select a team\n\n"); strcat (szMenu, "1. Blue Team\n"); strcat (szMenu, "2. Red Team\n\n"); strcat (szMenu, "3. Autoteam"); ShowMenu (pPlayer, 0x7, 0, 0, szMenu); } }
void CHalfLifeAFCTF::ChangePlayerTeam( CBasePlayer *pPlayer, const char *pTeamName, BOOL bKill, BOOL bGib ) { int damageFlags = DMG_GENERIC; int clientIndex = pPlayer->entindex();
if ( !bGib ) { damageFlags |= DMG_NEVERGIB; } else { damageFlags |= DMG_ALWAYSGIB; }
if ( bKill ) { // kill the player, remove a death, and let them start on the new team m_DisableDeathMessages = TRUE; m_DisableDeathPenalty = TRUE;
entvars_t *pevWorld = VARS( INDEXENT(0) ); pPlayer->TakeDamage( pevWorld, pevWorld, 900, damageFlags );
m_DisableDeathMessages = FALSE; m_DisableDeathPenalty = FALSE; }
// copy out the team name from the model strncpy( pPlayer->m_szTeamName, pTeamName, TEAM_NAME_LENGTH );
g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", pPlayer->m_szTeamName ); g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "team", pPlayer->m_szTeamName );
// notify everyone's HUD of the team change MESSAGE_BEGIN( MSG_ALL, gmsgTeamInfo ); WRITE_BYTE( clientIndex ); WRITE_STRING( pPlayer->m_szTeamName ); MESSAGE_END(); }
//========================================================= // ClientUserInfoChanged //========================================================= void CHalfLifeAFCTF::ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer ) { char text[1024];
// prevent skin/color/model changes char *mdls = g_engfuncs.pfnInfoKeyValue( infobuffer, "model" );
if ( !stricmp( mdls, pPlayer->m_szTeamName ) ) return;
if ( defaultteam.value ) { int clientIndex = pPlayer->entindex();
g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", pPlayer->m_szTeamName ); g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "team", pPlayer->m_szTeamName ); sprintf( text, "* Not allowed to change teams in this game!\n" ); UTIL_SayText( text, pPlayer ); return; }
if ( defaultteam.value || !IsValidTeam( mdls ) ) { int clientIndex = pPlayer->entindex();
g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", pPlayer->m_szTeamName ); sprintf( text, "* Can't change team to \'%s\'\n", mdls ); UTIL_SayText( text, pPlayer ); sprintf( text, "* Server limits teams to \'%s\'\n", m_szTeamList ); UTIL_SayText( text, pPlayer ); return; } // notify everyone of the team change sprintf( text, "* %s has changed to team \'%s\'\n", STRING(pPlayer->pev->netname), mdls ); UTIL_SayTextAll( text, pPlayer );
UTIL_LogPrintf( "\"%s<%i>\" changed to team %s\n", STRING( pPlayer->pev->netname ), GETPLAYERUSERID( pPlayer->edict() ), mdls );
ChangePlayerTeam( pPlayer, mdls, TRUE, TRUE ); // recound stuff RecountTeams(); }
extern int gmsgDeathMsg;
//========================================================= // Deathnotice. //========================================================= void CHalfLifeAFCTF::DeathNotice( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pevInflictor ) { if ( m_DisableDeathMessages ) return; if ( pVictim && pKiller && pKiller->flags & FL_CLIENT ) { CBasePlayer *pk = (CBasePlayer*) CBaseEntity::Instance( pKiller );
if ( pk ) { if ( (pk != pVictim) && (PlayerRelationship( pVictim, pk ) == GR_TEAMMATE) ) { MESSAGE_BEGIN( MSG_ALL, gmsgDeathMsg ); WRITE_BYTE( ENTINDEX(ENT(pKiller)) ); // the killer WRITE_BYTE( ENTINDEX(pVictim->edict()) ); // the victim WRITE_STRING( "teammate" ); // flag this as a teammate kill MESSAGE_END(); return; } } }
CHalfLifeAFCTF::DeathNotice( pVictim, pKiller, pevInflictor ); }
//========================================================= //========================================================= void CHalfLifeAFCTF :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor ) { if ( !m_DisableDeathPenalty ) { CHalfLifeMultiplay::PlayerKilled( pVictim, pKiller, pInflictor ); RecountTeams(); } }
//========================================================= // IsTeamplay //========================================================= BOOL CHalfLifeAFCTF::IsTeamplay( void ) { return TRUE; }
BOOL CHalfLifeAFCTF::FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker ) { if ( pAttacker && PlayerRelationship( pPlayer, pAttacker ) == GR_TEAMMATE ) { // my teammate hit me. if ( (CVAR_GET_FLOAT("mp_friendlyfire") == 0) && (pAttacker != pPlayer) ) { // friendly fire is off, and this hit came from someone other than myself, then don't get hurt return FALSE; } }
return CHalfLifeMultiplay::FPlayerCanTakeDamage( pPlayer, pAttacker ); }
//========================================================= //========================================================= int CHalfLifeAFCTF::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ) { // half life multiplay has a simple concept of Player Relationships. // you are either on another player's team, or you are not. if ( !pPlayer || !pTarget || !pTarget->IsPlayer() ) return GR_NOTTEAMMATE;
if ( (*GetTeamID(pPlayer) != '\0') && (*GetTeamID(pTarget) != '\0') && !stricmp( GetTeamID(pPlayer), GetTeamID(pTarget) ) ) { return GR_TEAMMATE; }
return GR_NOTTEAMMATE; }
//========================================================= //========================================================= BOOL CHalfLifeAFCTF::ShouldAutoAim( CBasePlayer *pPlayer, edict_t *target ) { // always autoaim, unless target is a teammate CBaseEntity *pTgt = CBaseEntity::Instance( target ); if ( pTgt && pTgt->IsPlayer() ) { if ( PlayerRelationship( pPlayer, pTgt ) == GR_TEAMMATE ) return FALSE; // don't autoaim at teammates }
return CHalfLifeMultiplay::ShouldAutoAim( pPlayer, target ); }
//========================================================= //========================================================= int CHalfLifeAFCTF::IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ) { if ( !pKilled ) return 0;
if ( !pAttacker ) return 1;
if ( pAttacker != pKilled && PlayerRelationship( pAttacker, pKilled ) == GR_TEAMMATE ) return -1;
return 1; }
//========================================================= //========================================================= const char *CHalfLifeAFCTF::GetTeamID( CBaseEntity *pEntity ) { if ( pEntity == NULL || pEntity->pev == NULL ) return "";
// return their team name return pEntity->TeamID(); }
int CHalfLifeAFCTF::GetTeamIndex( const char *pTeamName ) { if ( pTeamName && *pTeamName != 0 ) { // try to find existing team for ( int tm = 0; tm < num_teams; tm++ ) { if ( !stricmp( team_names[tm], pTeamName ) ) return tm; } } return -1; // No match }
const char *CHalfLifeAFCTF::GetIndexedTeamName( int teamIndex ) { if ( teamIndex < 0 || teamIndex >= num_teams ) return "";
return team_names[ teamIndex ]; }
BOOL CHalfLifeAFCTF::IsValidTeam( const char *pTeamName ) { if ( !m_teamLimit ) // Any team is valid if the teamlist isn't set return TRUE;
return ( GetTeamIndex( pTeamName ) != -1 ) ? TRUE : FALSE; }
const char *CHalfLifeAFCTF::TeamWithFewestPlayers( void ) { int i; int minPlayers = MAX_TEAMS; int teamCount[ MAX_TEAMS ]; char *pTeamName = NULL;
memset( teamCount, 0, MAX_TEAMS * sizeof(int) ); // loop through all clients, count number of players on each team for ( i = 1; i <= gpGlobals->maxClients; i++ ) { CBaseEntity *plr = UTIL_PlayerByIndex( i );
if ( plr ) { int team = GetTeamIndex( plr->TeamID() ); if ( team >= 0 ) teamCount[team] ++; } }
// Find team with least players for ( i = 0; i < num_teams; i++ ) { if ( teamCount[i] < minPlayers ) { minPlayers = teamCount[i]; pTeamName = team_names[i]; } }
return pTeamName; }
//========================================================= //========================================================= void CHalfLifeAFCTF::RecountTeams( void ) { char *pName; char teamlist[TEAMPLAY_TEAMLISTLENGTH];
// loop through all teams, recounting everything num_teams = 0;
// Copy all of the teams from the teamlist // make a copy because strtok is destructive strcpy( teamlist, m_szTeamList ); pName = teamlist; pName = strtok( pName, ";" ); while ( pName != NULL && *pName ) { if ( GetTeamIndex( pName ) < 0 ) { strcpy( team_names[num_teams], pName ); num_teams++; } pName = strtok( NULL, ";" ); }
if ( num_teams < 2 ) { num_teams = 0; m_teamLimit = FALSE; }
// Sanity check memset( team_scores, 0, sizeof(team_scores) );
// loop through all clients for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBaseEntity *plr = UTIL_PlayerByIndex( i );
if ( plr ) { const char *pTeamName = plr->TeamID(); // try add to existing team int tm = GetTeamIndex( pTeamName ); if ( tm < 0 ) // no team match found { if ( !m_teamLimit ) { // add to new team tm = num_teams; num_teams++; team_scores[tm] = 0; strncpy( team_names[tm], pTeamName, MAX_TEAMNAME_LENGTH ); } }
if ( tm >= 0 ) { team_scores[tm] += plr->pev->frags; } } } }
//========================================================= // Menustuff //=========================================================
extern int gmsgShowMenu; // the message # for ShowMenu
void CHalfLifeAFCTF::ShowMenu (CBasePlayer *pPlayer, int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, char *pszText) { MESSAGE_BEGIN( MSG_ONE, gmsgShowMenu, NULL, pPlayer ->pev); WRITE_SHORT( bitsValidSlots); WRITE_CHAR( nDisplayTime ); WRITE_BYTE( fNeedMore ); WRITE_STRING (pszText); MESSAGE_END(); }
Helft mir bitte!
--
*arg* Immer diese S***** Kopilier Fehler, ich könnte dieses S***** in den ***** ******!!!! Immer diese Ver******* fehler!! *arg*
|