You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1435 lines
37 KiB
1435 lines
37 KiB
/*** |
|
* |
|
* Copyright (c) 2001, 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. |
|
* |
|
****/ |
|
/* |
|
|
|
===== threewave_gamerules.cpp ======================================================== |
|
|
|
This contains all the gamerules for the ThreeWave CTF Gamemode. |
|
It also contains the Flag entity information. |
|
|
|
*/ |
|
|
|
#define NUM_TEAMS 2 |
|
|
|
const char *sTeamNames[] = |
|
{ |
|
"SPECTATOR", |
|
"RED", |
|
"BLUE" |
|
}; |
|
|
|
#include "extdll.h" |
|
#include "util.h" |
|
#include "cbase.h" |
|
#include "player.h" |
|
#include "weapons.h" |
|
#include "gamerules.h" |
|
#include "skill.h" |
|
#include "game.h" |
|
#include "items.h" |
|
#include "threewave_gamerules.h" |
|
#include "flags.h" |
|
#include "runes.h" |
|
#include "grapple.h" |
|
|
|
static char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH]; |
|
static int team_scores[MAX_TEAMS]; |
|
static int num_teams = 0; |
|
|
|
bool g_bSpawnedRunes; |
|
extern void SpawnRunes( void ); |
|
|
|
extern unsigned short g_usCarried; |
|
extern edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer, bool bCheckDM ); |
|
extern edict_t *RuneSelectSpawnPoint( void ); |
|
|
|
#ifndef NO_VOICEGAMEMGR |
|
class CThreeWaveGameMgrHelper : public IVoiceGameMgrHelper |
|
{ |
|
public: |
|
virtual bool CanPlayerHearPlayer( CBasePlayer *pPlayer1, CBasePlayer *pPlayer2 ) |
|
{ |
|
return stricmp( pPlayer1->TeamID(), pPlayer2->TeamID() ) == 0; |
|
} |
|
}; |
|
static CThreeWaveGameMgrHelper g_GameMgrHelper; |
|
#endif |
|
|
|
extern DLL_GLOBAL BOOL g_fGameOver; |
|
|
|
const char *GetTeamName( int team ) |
|
{ |
|
if( team < 0 || team > NUM_TEAMS ) |
|
team = 0; |
|
|
|
return sTeamNames[team]; |
|
} |
|
|
|
CThreeWave::CThreeWave() |
|
{ |
|
#ifndef NO_VOICEGAMEMGR |
|
// CHalfLifeMultiplay already initialized it - just override its helper callback. |
|
m_VoiceGameMgr.SetHelper( &g_GameMgrHelper ); |
|
#endif |
|
m_DisableDeathMessages = FALSE; |
|
m_DisableDeathPenalty = FALSE; |
|
|
|
memset( team_names, 0, sizeof(team_names) ); |
|
memset( team_scores, 0, sizeof(team_scores) ); |
|
num_teams = 0; |
|
|
|
iBlueTeamScore = iRedTeamScore = 0; |
|
g_bSpawnedRunes = FALSE; |
|
|
|
// 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(); |
|
} |
|
|
|
BOOL CThreeWave::ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128] ) |
|
{ |
|
return CHalfLifeMultiplay::ClientConnected( pEntity, pszName, pszAddress, szRejectReason ); |
|
} |
|
|
|
extern cvar_t timeleft, fragsleft; |
|
|
|
void CThreeWave::Think( void ) |
|
{ |
|
#ifndef NO_VOICEGAMEMGR |
|
m_VoiceGameMgr.Update( gpGlobals->frametime ); |
|
#endif |
|
///// 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 |
|
{ |
|
CHalfLifeMultiplay::Think(); |
|
return; |
|
} |
|
|
|
// Update HUD timer and effective time. |
|
m_Timer.Think(); |
|
|
|
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; |
|
} |
|
|
|
if( !g_bSpawnedRunes ) |
|
SpawnRunes(); |
|
|
|
if( m_flFlagStatusTime && m_flFlagStatusTime <= gpGlobals->time ) |
|
GetFlagStatus( NULL ); |
|
|
|
// 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; |
|
} |
|
|
|
void CThreeWave::JoinTeam( CBasePlayer *pPlayer, int iTeam ) |
|
{ |
|
bool bIsNotSpawn = false; |
|
|
|
if( pPlayer->pev->team == iTeam ) |
|
return; |
|
|
|
if( pPlayer->m_flNextTeamChange > gpGlobals->time ) |
|
return; |
|
|
|
pPlayer->m_flNextTeamChange = gpGlobals->time + 5; |
|
|
|
if( pPlayer->pev->team == 0 ) |
|
bIsNotSpawn = true; |
|
|
|
ChangePlayerTeam( pPlayer, iTeam ); |
|
RecountTeams(); |
|
|
|
if( bIsNotSpawn ) |
|
pPlayer->Spawn(); |
|
} |
|
|
|
int CThreeWave::TeamWithFewestPlayers() |
|
{ |
|
CBaseEntity *pPlayer = NULL; |
|
CBasePlayer *player = NULL; |
|
|
|
int iNumRed, iNumBlue; |
|
|
|
int iTeam = 0; |
|
|
|
// Initialize the player counts.. |
|
iNumRed = iNumBlue = 0; |
|
|
|
for( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer *pPlayer = (CBasePlayer *)UTIL_PlayerByIndex( i ); |
|
|
|
if( pPlayer && pPlayer->pev->flags != FL_DORMANT ) |
|
{ |
|
if( pPlayer->pev->team == RED ) |
|
iNumRed += 1; |
|
else if( pPlayer->pev->team == BLUE ) |
|
iNumBlue += 1; |
|
} |
|
} |
|
|
|
if( ( iNumRed == iNumBlue ) || ( iNumRed == 0 && iNumBlue == 0 ) ) |
|
iTeam = RANDOM_LONG( RED, BLUE ); |
|
else if( iNumRed > iNumBlue ) |
|
iTeam = BLUE; |
|
else if( iNumRed < iNumBlue ) |
|
iTeam = RED; |
|
|
|
return iTeam; |
|
|
|
} |
|
|
|
extern void DropRune( CBasePlayer *pPlayer ); |
|
//========================================================= |
|
// 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 CThreeWave::ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) |
|
{ |
|
#ifndef NO_VOICEGAMEMGR |
|
if( m_VoiceGameMgr.ClientCommand( pPlayer, pcmd ) ) |
|
return TRUE; |
|
#endif |
|
if( FStrEq( pcmd, "menuselect" ) ) |
|
{ |
|
int iTeam = 0; |
|
|
|
if( CMD_ARGC() < 2 ) |
|
return TRUE; |
|
|
|
int slot = atoi( CMD_ARGV( 1 ) ); |
|
|
|
// select the item from the current menu |
|
switch( pPlayer->m_iMenu ) |
|
{ |
|
case Team_Menu: |
|
case Team_Menu_IG: |
|
switch ( slot ) |
|
{ |
|
case 1: |
|
iTeam = RED; |
|
break; |
|
case 2: |
|
iTeam = BLUE; |
|
break; |
|
case 5: |
|
iTeam = TeamWithFewestPlayers(); |
|
break; |
|
default: |
|
return TRUE; |
|
} |
|
break; |
|
default: |
|
return TRUE; |
|
} |
|
JoinTeam( pPlayer, iTeam ); |
|
return TRUE; |
|
} |
|
else if( FStrEq( pcmd, "droprune" ) ) |
|
{ |
|
DropRune( pPlayer ); |
|
return TRUE; |
|
} |
|
else if( FStrEq( pcmd, "changeteam" ) ) |
|
{ |
|
if( pPlayer->pev->team != 0 ) |
|
{ |
|
pPlayer->ShowMenu( 1 + 2 + 16 + 512, -1, FALSE, "#Team_Menu_Join_IG" ); |
|
pPlayer->m_iMenu = Team_Menu_IG; |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
extern int gmsgGameMode; |
|
extern int gmsgSayText; |
|
extern int gmsgTeamInfo; |
|
|
|
void CThreeWave::UpdateGameMode( CBasePlayer *pPlayer ) |
|
{ |
|
MESSAGE_BEGIN( MSG_ONE, gmsgGameMode, NULL, pPlayer->edict() ); |
|
WRITE_BYTE( 1 ); // game mode teamplay |
|
MESSAGE_END(); |
|
} |
|
|
|
edict_t *CThreeWave::GetPlayerSpawnSpot( CBasePlayer *pPlayer ) |
|
{ |
|
BOOL bCheckDM; |
|
edict_t *pentSpawnSpot; |
|
|
|
if( FBitSet( pPlayer->m_afPhysicsFlags, PFLAG_OBSERVER ) || pPlayer->pev->team == 0 ) |
|
bCheckDM = FALSE; |
|
else |
|
{ |
|
if( RANDOM_LONG( 1, 7 ) < 3 ) |
|
bCheckDM = TRUE; |
|
else |
|
bCheckDM = FALSE; |
|
} |
|
pentSpawnSpot = EntSelectSpawnPoint( pPlayer, bCheckDM ); |
|
|
|
if( IsMultiplayer() && pentSpawnSpot->v.target ) |
|
{ |
|
FireTargets( STRING( pentSpawnSpot->v.target ), pPlayer, pPlayer, USE_TOGGLE, 0 ); |
|
} |
|
|
|
pPlayer->pev->origin = VARS( pentSpawnSpot )->origin + Vector( 0, 0, 1 ); |
|
pPlayer->pev->v_angle = g_vecZero; |
|
pPlayer->pev->velocity = g_vecZero; |
|
pPlayer->pev->angles = VARS( pentSpawnSpot )->angles; |
|
pPlayer->pev->punchangle = g_vecZero; |
|
pPlayer->pev->fixangle = TRUE; |
|
|
|
return pentSpawnSpot; |
|
} |
|
|
|
void CThreeWave::PlayerTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker ) |
|
{ |
|
if( !pAttacker->IsPlayer() ) |
|
return; |
|
|
|
if( pPlayer->pev->team == pAttacker->pev->team ) |
|
return; |
|
|
|
if( pPlayer->m_bHasFlag ) |
|
{ |
|
pPlayer->pCarrierHurter = (CBasePlayer *)pAttacker; |
|
pPlayer->m_flCarrierHurtTime = gpGlobals->time + TEAM_CAPTURE_CARRIER_DANGER_PROTECT_TIMEOUT; |
|
} |
|
|
|
} |
|
|
|
void CThreeWave::PlayerSpawn( CBasePlayer *pPlayer ) |
|
{ |
|
BOOL addDefault; |
|
CBaseEntity *pWeaponEntity = NULL; |
|
|
|
if( pPlayer->pev->team == 0 ) |
|
{ |
|
pPlayer->pev->takedamage = DAMAGE_NO; |
|
pPlayer->pev->solid = SOLID_NOT; |
|
pPlayer->pev->movetype = MOVETYPE_NOCLIP; |
|
pPlayer->pev->effects |= EF_NODRAW; |
|
pPlayer->pev->flags |= FL_NOTARGET; |
|
pPlayer->m_afPhysicsFlags |= PFLAG_OBSERVER; |
|
pPlayer->m_iHideHUD |= HIDEHUD_WEAPONS | HIDEHUD_FLASHLIGHT | HIDEHUD_HEALTH; |
|
pPlayer->m_flFlagStatusTime = gpGlobals->time + 0.1; |
|
} |
|
else |
|
{ |
|
pPlayer->pev->weapons |= ( 1 << WEAPON_SUIT ); |
|
addDefault = TRUE; |
|
|
|
while( ( pWeaponEntity = UTIL_FindEntityByClassname( pWeaponEntity, "game_player_equip" ) ) ) |
|
{ |
|
pWeaponEntity->Touch( pPlayer ); |
|
addDefault = FALSE; |
|
} |
|
|
|
if( addDefault ) |
|
{ |
|
pPlayer->m_bHasFlag = FALSE; |
|
pPlayer->m_iHideHUD &= ~HIDEHUD_WEAPONS; |
|
pPlayer->m_iHideHUD &= ~HIDEHUD_FLASHLIGHT; |
|
pPlayer->m_iHideHUD &= ~HIDEHUD_HEALTH; |
|
pPlayer->m_afPhysicsFlags &= ~PFLAG_OBSERVER; |
|
|
|
// Start with init ammoload |
|
pPlayer->m_iAmmoShells = 25; |
|
|
|
// Start with shotgun and axe |
|
pPlayer->GiveNamedItem( "weapon_quakegun" ); |
|
|
|
if( arcade.value ) |
|
{ |
|
pPlayer->m_iQuakeItems |= ( IT_AXE | IT_SHOTGUN | IT_SUPER_SHOTGUN | IT_NAILGUN | IT_SUPER_NAILGUN | IT_GRENADE_LAUNCHER | IT_ROCKET_LAUNCHER | IT_LIGHTNING ); |
|
pPlayer->m_iAmmoRockets = 100; |
|
pPlayer->m_iAmmoCells = 100; |
|
pPlayer->m_iAmmoShells = 100; |
|
pPlayer->m_iAmmoNails = 200; |
|
pPlayer->pev->health = 200; |
|
pPlayer->pev->armortype = 0.8; |
|
pPlayer->pev->armorvalue = 200; |
|
pPlayer->m_iQuakeItems &= ~( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3 ); |
|
pPlayer->m_iQuakeItems |= IT_ARMOR3; |
|
} |
|
else |
|
pPlayer->m_iQuakeItems |= ( IT_SHOTGUN | IT_AXE ); |
|
|
|
if( allowhook.value ) |
|
pPlayer->m_iQuakeItems |= IT_EXTRA_WEAPON; |
|
|
|
pPlayer->m_iQuakeWeapon = pPlayer->W_BestWeapon(); |
|
pPlayer->W_SetCurrentAmmo(); |
|
|
|
pPlayer->m_flFlagStatusTime = gpGlobals->time + 0.1; |
|
} |
|
} |
|
|
|
/* MESSAGE_BEGIN( MSG_ONE, gmsgRuneStatus, NULL, pPlayer->pev); |
|
WRITE_BYTE( pPlayer->m_iRuneStatus ); |
|
MESSAGE_END();*/ |
|
} |
|
|
|
void CBasePlayer::ShowMenu( int bitsValidSlots, int nDisplayTime, BOOL fNeedMore, const char *pszText ) |
|
{ |
|
MESSAGE_BEGIN( MSG_ONE, gmsgShowMenu, NULL, pev ); |
|
WRITE_SHORT( bitsValidSlots); |
|
WRITE_CHAR( nDisplayTime ); |
|
WRITE_BYTE( fNeedMore ); |
|
WRITE_STRING( pszText ); |
|
MESSAGE_END(); |
|
} |
|
|
|
//========================================================= |
|
// InitHUD |
|
//========================================================= |
|
void CThreeWave::InitHUD( CBasePlayer *pPlayer ) |
|
{ |
|
CHalfLifeMultiplay::InitHUD( pPlayer ); |
|
|
|
int clientIndex = pPlayer->entindex(); |
|
// 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 ) |
|
{ |
|
MESSAGE_BEGIN( MSG_ONE, gmsgTeamInfo, NULL, pPlayer->edict() ); |
|
WRITE_BYTE( plr->entindex() ); |
|
WRITE_STRING( plr->TeamID() ); |
|
MESSAGE_END(); |
|
|
|
if( ( (CBasePlayer *)plr )->m_bHasFlag ) |
|
{ |
|
MESSAGE_BEGIN( MSG_ONE, gmsgFlagCarrier, NULL, pPlayer->edict() ); |
|
WRITE_BYTE( plr->entindex() ); |
|
WRITE_BYTE( 1 ); |
|
MESSAGE_END(); |
|
} |
|
} |
|
} |
|
|
|
// Remove Rune icon if we have one. |
|
MESSAGE_BEGIN( MSG_ONE, gmsgRuneStatus, NULL, pPlayer->pev ); |
|
WRITE_BYTE( 0 ); |
|
MESSAGE_END(); |
|
|
|
if( pPlayer->pev->team == 0 ) |
|
{ |
|
pPlayer->ShowMenu( 1 + 2 + 16, -1, FALSE, "#Team_Menu_Join" ); |
|
pPlayer->m_iMenu = Team_Menu; |
|
} |
|
} |
|
|
|
void CThreeWave::ChangePlayerTeam( CBasePlayer *pPlayer, int iTeam ) |
|
{ |
|
int clientIndex = pPlayer->entindex(); |
|
int damageFlags = DMG_GENERIC; |
|
|
|
if( pPlayer->pev->team != 0 ) |
|
{ |
|
damageFlags |= DMG_ALWAYSGIB; |
|
|
|
// 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; |
|
} |
|
|
|
int oldTeam = pPlayer->pev->team; |
|
pPlayer->pev->team = iTeam; |
|
|
|
strcpy( pPlayer->m_szTeamName, sTeamNames[pPlayer->pev->team] ); |
|
|
|
ClientUserInfoChanged( pPlayer, NULL ); |
|
|
|
// notify everyone's HUD of the team change |
|
MESSAGE_BEGIN( MSG_ALL, gmsgTeamInfo ); |
|
WRITE_BYTE( clientIndex ); |
|
WRITE_STRING( pPlayer->m_szTeamName ); |
|
MESSAGE_END(); |
|
|
|
MESSAGE_BEGIN( MSG_ALL, gmsgScoreInfo ); |
|
WRITE_BYTE( ENTINDEX(pPlayer->edict()) ); |
|
WRITE_SHORT( pPlayer->pev->frags ); |
|
WRITE_SHORT( pPlayer->m_iDeaths ); |
|
WRITE_SHORT( pPlayer->pev->team ); |
|
MESSAGE_END(); |
|
|
|
// log the change |
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" joined team \"%s\"\n", |
|
STRING(pPlayer->pev->netname), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( oldTeam ), |
|
pPlayer->m_szTeamName ); |
|
} |
|
|
|
//========================================================= |
|
// ClientUserInfoChanged |
|
//========================================================= |
|
void CThreeWave::ClientUserInfoChanged( CBasePlayer *pPlayer, char *infobuffer ) |
|
{ |
|
int clientIndex = pPlayer->entindex(); |
|
const char *pszModel = ""; |
|
int iTopColor = 0; |
|
|
|
if( pPlayer->pev->team == RED ) |
|
{ |
|
pszModel = "red"; |
|
iTopColor = 255; |
|
} |
|
else if( pPlayer->pev->team == BLUE ) |
|
{ |
|
pszModel = "blue"; |
|
iTopColor = 153; |
|
} |
|
g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "topcolor", UTIL_VarArgs( "%d", iTopColor ) ); |
|
g_engfuncs.pfnSetClientKeyValue( clientIndex, g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model", pszModel ); |
|
} |
|
|
|
extern int gmsgDeathMsg; |
|
|
|
//========================================================= |
|
// Deathnotice. |
|
//========================================================= |
|
void CThreeWave::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; |
|
} |
|
} |
|
} |
|
|
|
CHalfLifeMultiplay::DeathNotice( pVictim, pKiller, pevInflictor ); |
|
} |
|
|
|
//========================================================= |
|
//========================================================= |
|
void CThreeWave::ClientDisconnected( edict_t *pClient ) |
|
{ |
|
if( pClient ) |
|
{ |
|
CBasePlayer *pPlayer = (CBasePlayer *)CBaseEntity::Instance( pClient ); |
|
|
|
if( pPlayer ) |
|
{ |
|
//We have the flag, spawn it |
|
if( pPlayer->m_bHasFlag ) |
|
{ |
|
CBaseEntity *pEnt = NULL; |
|
|
|
//We have the BLUE flag, Spawn it |
|
if( pPlayer->pev->team == RED ) |
|
{ |
|
pEnt = CBaseEntity::Create( "item_flag_team2", pPlayer->pev->origin, pPlayer->pev->angles, pPlayer->edict() ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Dropped_Blue_Flag\"\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
} |
|
//We have the RED flag, Spawn it |
|
else if( pPlayer->pev->team == BLUE ) |
|
{ |
|
pEnt = CBaseEntity::Create( "item_flag_team1", pPlayer->pev->origin, pPlayer->pev->angles, pPlayer->edict() ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Dropped_Red_Flag\"\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
} |
|
|
|
pEnt->pev->velocity = pPlayer->pev->velocity * 1.2; |
|
pEnt->pev->angles.x = 0; |
|
|
|
CItemFlag *pFlag = (CItemFlag *)pEnt; |
|
pFlag->Dropped = TRUE; |
|
pFlag->m_flDroppedTime = gpGlobals->time + TEAM_CAPTURE_FLAG_RETURN_TIME; |
|
|
|
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE, |
|
pPlayer->edict(), g_usCarried, 0, (float*)&g_vecZero, (float*)&g_vecZero, |
|
0.0, 0.0, pPlayer->entindex(), pPlayer->pev->team, 1, 0 ); |
|
|
|
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL ); |
|
if( pPlayer->pev->team == RED ) |
|
WRITE_BYTE( BLUE_FLAG_LOST ); |
|
else if( pPlayer->pev->team == BLUE ) |
|
WRITE_BYTE( RED_FLAG_LOST ); |
|
WRITE_STRING( STRING( pPlayer->pev->netname ) ); |
|
MESSAGE_END(); |
|
|
|
m_flFlagStatusTime = gpGlobals->time + 0.1; |
|
|
|
pPlayer->m_bHasFlag = FALSE; |
|
} |
|
|
|
// drop any runes the player has |
|
if( pPlayer->m_iRuneStatus ) |
|
{ |
|
CItemRune *pRune = (CItemRune*)CBaseEntity::Create( g_RuneEntityName[pPlayer->m_iRuneStatus], pPlayer->pev->origin, pPlayer->pev->angles, pPlayer->edict() ); |
|
if( pRune ) |
|
{ |
|
pRune->pev->velocity = pPlayer->pev->velocity * 1.5; |
|
pRune->pev->angles.x = 0; |
|
pRune->dropped = true; |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Dropped_%s\"\n", |
|
STRING(pPlayer->pev->netname), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
pPlayer->m_szTeamName, |
|
g_RuneName[pPlayer->m_iRuneStatus] ); |
|
} |
|
|
|
pPlayer->m_iRuneStatus = 0; |
|
} |
|
|
|
FireTargets( "game_playerleave", pPlayer, pPlayer, USE_TOGGLE, 0 ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" disconnected\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
|
|
pPlayer->RemoveAllItems( TRUE );// destroy all of the players weapons and items |
|
} |
|
} |
|
} |
|
|
|
void CThreeWave::PlayerThink( CBasePlayer *pPlayer ) |
|
{ |
|
if( g_fGameOver ) |
|
{ |
|
// check for button presses |
|
if( pPlayer->m_afButtonPressed & ( IN_DUCK | IN_ATTACK | IN_ATTACK2 | IN_USE | IN_JUMP ) ) |
|
m_iEndIntermissionButtonHit = TRUE; |
|
|
|
// clear attack/use commands from player |
|
pPlayer->m_afButtonPressed = 0; |
|
pPlayer->pev->button = 0; |
|
pPlayer->m_afButtonReleased = 0; |
|
} |
|
|
|
if( pPlayer->pFlagCarrierKiller ) |
|
{ |
|
if( pPlayer->m_flFlagCarrierKillTime <= gpGlobals->time ) |
|
pPlayer->pFlagCarrierKiller = NULL; |
|
} |
|
|
|
if( pPlayer->pFlagReturner ) |
|
{ |
|
if( pPlayer->m_flFlagReturnTime <= gpGlobals->time ) |
|
pPlayer->pFlagReturner = NULL; |
|
} |
|
|
|
if( pPlayer->pCarrierHurter ) |
|
{ |
|
if( pPlayer->m_flCarrierHurtTime <= gpGlobals->time ) |
|
pPlayer->pCarrierHurter = NULL; |
|
} |
|
|
|
if( pPlayer->m_iRuneStatus == ITEM_RUNE4_FLAG ) |
|
{ |
|
if( pPlayer->m_flRegenTime <= gpGlobals->time ) |
|
{ |
|
if( pPlayer->pev->health < 150 ) |
|
{ |
|
pPlayer->pev->health += 5; |
|
|
|
if( pPlayer->pev->health > 150) |
|
pPlayer->pev->health = 150; |
|
|
|
pPlayer->m_flRegenTime = gpGlobals->time + 1; |
|
EMIT_SOUND( ENT( pPlayer->pev), CHAN_ITEM, "rune/rune4.wav", 1, ATTN_NORM ); |
|
} |
|
if( pPlayer->pev->armorvalue < 150 && pPlayer->pev->armorvalue ) |
|
{ |
|
pPlayer->pev->armorvalue += 5; |
|
|
|
if( pPlayer->pev->armorvalue > 150) |
|
pPlayer->pev->armorvalue = 150; |
|
|
|
pPlayer->m_flRegenTime = gpGlobals->time + 1; |
|
|
|
EMIT_SOUND( ENT( pPlayer->pev ), CHAN_ITEM, "rune/rune4.wav", 1, ATTN_NORM ); |
|
} |
|
} |
|
} |
|
|
|
if( pPlayer->m_bOn_Hook ) |
|
pPlayer->Service_Grapple(); |
|
|
|
if( pPlayer->m_flFlagStatusTime && pPlayer->m_flFlagStatusTime <= gpGlobals->time ) |
|
GetFlagStatus( pPlayer ); |
|
} |
|
|
|
//========================================================= |
|
//========================================================= |
|
void CThreeWave::PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor ) |
|
{ |
|
CBasePlayer *pk = NULL; |
|
|
|
if( pKiller ) |
|
{ |
|
CBaseEntity *pTemp = CBaseEntity::Instance( pKiller ); |
|
|
|
if( pTemp->IsPlayer() ) |
|
pk = (CBasePlayer*)pTemp; |
|
} |
|
|
|
//Only award a bonus if the Flag carrier had the flag for more than 2 secs |
|
//Prevents from people waiting for the flag carrier to grab the flag and then killing him |
|
//Instead of actually defending the flag. |
|
if( pVictim->m_bHasFlag ) |
|
{ |
|
if( pk ) |
|
{ |
|
if( pVictim->pev->team != pk->pev->team ) |
|
{ |
|
if( pVictim->m_flCarrierPickupTime <= gpGlobals->time ) |
|
pk->AddPoints( TEAM_CAPTURE_FRAG_CARRIER_BONUS, TRUE ); |
|
|
|
if( pk->pev->team == RED ) |
|
{ |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pk->pev->netname ) ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " fragged " ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "BLUE" ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "'s flag carrier!\n" ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Killed_Enemy_Flag_Carrier\"\n", |
|
STRING( pk->pev->netname ), |
|
GETPLAYERUSERID( pk->edict() ), |
|
GETPLAYERAUTHID( pk->edict() ), |
|
GetTeamName( pk->pev->team ) ); |
|
|
|
if( iBlueFlagStatus == BLUE_FLAG_STOLEN ) |
|
{ |
|
for( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer *pTeamMate = (CBasePlayer *)UTIL_PlayerByIndex( i ); |
|
|
|
if( pTeamMate ) |
|
{ |
|
if( pTeamMate->m_bHasFlag ) |
|
{ |
|
pTeamMate->pFlagCarrierKiller = pk; |
|
pTeamMate->m_flFlagCarrierKillTime = gpGlobals->time + TEAM_CAPTURE_FRAG_CARRIER_ASSIST_TIMEOUT; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
if( pk->pev->team == BLUE ) |
|
{ |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pk->pev->netname ) ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " fragged " ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "RED" ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "'s flag carrier!\n" ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Killed_Enemy_Flag_Carrier\"\n", |
|
STRING( pk->pev->netname ), |
|
GETPLAYERUSERID( pk->edict() ), |
|
GETPLAYERAUTHID( pk->edict() ), |
|
GetTeamName( pk->pev->team ) ); |
|
|
|
if( iRedFlagStatus == RED_FLAG_STOLEN ) |
|
{ |
|
for( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer *pTeamMate = (CBasePlayer *)UTIL_PlayerByIndex( i ); |
|
|
|
if( pTeamMate ) |
|
{ |
|
if( pTeamMate->m_bHasFlag ) |
|
{ |
|
pTeamMate->pFlagCarrierKiller = pk; |
|
pTeamMate->m_flFlagCarrierKillTime = gpGlobals->time + TEAM_CAPTURE_FRAG_CARRIER_ASSIST_TIMEOUT; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
CBaseEntity *pEnt = NULL; |
|
|
|
// We have the BLUE flag, Spawn it |
|
if( pVictim->pev->team == RED ) |
|
{ |
|
pEnt = CBaseEntity::Create( "item_flag_team2", pVictim->pev->origin, pVictim->pev->angles, pVictim->edict() ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Dropped_Blue_Flag\"\n", |
|
STRING( pVictim->pev->netname ), |
|
GETPLAYERUSERID( pVictim->edict() ), |
|
GETPLAYERAUTHID( pVictim->edict() ), |
|
GetTeamName( pVictim->pev->team ) ); |
|
} |
|
else if( pVictim->pev->team == BLUE ) |
|
{ |
|
pEnt = CBaseEntity::Create( "item_flag_team1", pVictim->pev->origin, pVictim->pev->angles, pVictim->edict() ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Dropped_Red_Flag\"\n", |
|
STRING( pVictim->pev->netname ), |
|
GETPLAYERUSERID( pVictim->edict() ), |
|
GETPLAYERAUTHID( pVictim->edict() ), |
|
GetTeamName( pVictim->pev->team ) ); |
|
} |
|
|
|
pEnt->pev->velocity = pVictim->pev->velocity * 1.2; |
|
pEnt->pev->angles.x = 0; |
|
|
|
CItemFlag *pFlag = (CItemFlag *)pEnt; |
|
pFlag->Dropped = TRUE; |
|
|
|
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE, |
|
pVictim->edict(), g_usCarried, 0, (float *)&g_vecZero, (float *)&g_vecZero, |
|
0.0, 0.0, pVictim->entindex(), pVictim->pev->team, 1, 0 ); |
|
|
|
pFlag->m_flDroppedTime = gpGlobals->time + TEAM_CAPTURE_FLAG_RETURN_TIME; |
|
|
|
MESSAGE_BEGIN ( MSG_ALL, gmsgCTFMsgs, NULL ); |
|
if( pVictim->pev->team == RED ) |
|
WRITE_BYTE( BLUE_FLAG_LOST ); |
|
else if( pVictim->pev->team == BLUE ) |
|
WRITE_BYTE( RED_FLAG_LOST ); |
|
WRITE_STRING( STRING( pVictim->pev->netname ) ); |
|
MESSAGE_END(); |
|
|
|
pVictim->m_bHasFlag = FALSE; |
|
|
|
m_flFlagStatusTime = gpGlobals->time + 0.1; |
|
} |
|
else |
|
{ |
|
if( pk ) |
|
{ |
|
if( pk->pev->team == RED ) |
|
{ |
|
if( iBlueFlagStatus == BLUE_FLAG_STOLEN ) |
|
{ |
|
for( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer *pTeamMate = (CBasePlayer *)UTIL_PlayerByIndex( i ); |
|
|
|
if ( pTeamMate && pTeamMate != pk ) |
|
{ |
|
if ( pTeamMate->pev->team == pk->pev->team ) |
|
{ |
|
if ( pTeamMate->m_bHasFlag ) |
|
{ |
|
if ( pTeamMate->pCarrierHurter ) |
|
{ |
|
if ( pTeamMate->pCarrierHurter == pVictim ) |
|
{ |
|
if ( pTeamMate->m_flCarrierHurtTime > gpGlobals->time ) |
|
{ |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pk->pev->netname ) ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " defends "); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "RED" ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "'s flag carrier against an agressive enemy\n"); |
|
|
|
pk->AddPoints( TEAM_CAPTURE_CARRIER_DANGER_PROTECT_BONUS, TRUE ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
if( pk->pev->team == BLUE ) |
|
{ |
|
if( iRedFlagStatus == RED_FLAG_STOLEN ) |
|
{ |
|
for( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer *pTeamMate = (CBasePlayer *)UTIL_PlayerByIndex( i ); |
|
|
|
if( pTeamMate && pTeamMate != pk ) |
|
{ |
|
if( pTeamMate->pev->team == pk->pev->team ) |
|
{ |
|
if( pTeamMate->m_bHasFlag ) |
|
{ |
|
if( pTeamMate->pCarrierHurter ) |
|
{ |
|
if( pTeamMate->pCarrierHurter == pVictim ) |
|
{ |
|
if( pTeamMate->m_flCarrierHurtTime > gpGlobals->time ) |
|
{ |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pk->pev->netname ) ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " defends "); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "BLUE" ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "'s flag carrier against an agressive enemy\n"); |
|
|
|
pk->AddPoints( TEAM_CAPTURE_CARRIER_DANGER_PROTECT_BONUS, TRUE ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
// Find if this guy is near our flag or our flag carrier |
|
CBaseEntity *ent = NULL; |
|
float Dist; |
|
|
|
if( pk ) |
|
{ |
|
if( pk->pev->team == RED ) |
|
{ |
|
while( ( ent = UTIL_FindEntityByClassname( ent, "item_flag_team1" ) ) != NULL ) |
|
{ |
|
//Do not defend a invisible flag |
|
if( ent->pev->effects & EF_NODRAW ) |
|
break; |
|
|
|
Dist = ( pk->pev->origin - ent->pev->origin ).Length(); |
|
|
|
if( Dist <= TEAM_CAPTURE_TARGET_PROTECT_RADIUS ) |
|
{ |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING ( pk->pev->netname ) ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " defends the "); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "RED"); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " flag\n"); |
|
|
|
pk->AddPoints( TEAM_CAPTURE_FLAG_DEFENSE_BONUS, TRUE ); |
|
break; |
|
} |
|
} |
|
|
|
if( iBlueFlagStatus == BLUE_FLAG_STOLEN ) |
|
{ |
|
for( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer *pTeamMate = (CBasePlayer *)UTIL_PlayerByIndex( i ); |
|
|
|
if( pTeamMate && pTeamMate != pk ) |
|
{ |
|
if( pTeamMate->pev->team == pk->pev->team ) |
|
{ |
|
if( pTeamMate->m_bHasFlag ) |
|
{ |
|
Dist = ( pk->pev->origin - pTeamMate->pev->origin ).Length(); |
|
|
|
if( Dist <= TEAM_CAPTURE_TARGET_PROTECT_RADIUS ) |
|
{ |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pk->pev->netname ) ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " defends " ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "RED" ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "'s flag carrier\n" ); |
|
|
|
pk->AddPoints( TEAM_CAPTURE_CARRIER_PROTECT_BONUS, TRUE ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
} |
|
else if( pk->pev->team == BLUE ) |
|
{ |
|
while( ( ent = UTIL_FindEntityByClassname( ent, "item_flag_team2") ) != NULL ) |
|
{ |
|
// Do not defend a invisible flag |
|
if( ent->pev->effects & EF_NODRAW ) |
|
break; |
|
|
|
Dist = ( pk->pev->origin - ent->pev->origin ).Length(); |
|
|
|
if( Dist <= TEAM_CAPTURE_TARGET_PROTECT_RADIUS ) |
|
{ |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pk->pev->netname ) ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " defends the " ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "RED" ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " flag\n" ); |
|
|
|
pk->AddPoints( TEAM_CAPTURE_FLAG_DEFENSE_BONUS, TRUE ); |
|
break; |
|
} |
|
} |
|
|
|
if( iRedFlagStatus == RED_FLAG_STOLEN ) |
|
{ |
|
for( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer *pTeamMate = (CBasePlayer *)UTIL_PlayerByIndex( i ); |
|
|
|
if( pTeamMate && pTeamMate != pk ) |
|
{ |
|
if( pTeamMate->pev->team == pk->pev->team ) |
|
{ |
|
if( pTeamMate->m_bHasFlag ) |
|
{ |
|
Dist = ( pk->pev->origin - pTeamMate->pev->origin ).Length(); |
|
|
|
if( Dist <= TEAM_CAPTURE_TARGET_PROTECT_RADIUS ) |
|
{ |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pk->pev->netname ) ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " defends "); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "RED"); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "'s flag carrier\n" ); |
|
|
|
pk->AddPoints( TEAM_CAPTURE_CARRIER_PROTECT_BONUS, TRUE ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
if( pVictim->m_iRuneStatus ) |
|
{ |
|
CItemRune *pRune = (CItemRune*)CBaseEntity::Create( g_RuneEntityName[pVictim->m_iRuneStatus], pVictim->pev->origin, pVictim->pev->angles, NULL ); |
|
if( pRune ) |
|
{ |
|
pRune->pev->velocity = pVictim->pev->velocity * 1.5; |
|
pRune->pev->angles.x = 0; |
|
pRune->dropped = true; |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Dropped_%s\"\n", |
|
STRING(pVictim->pev->netname), |
|
GETPLAYERUSERID( pVictim->edict() ), |
|
GETPLAYERAUTHID( pVictim->edict() ), |
|
pVictim->m_szTeamName, |
|
g_RuneName[pVictim->m_iRuneStatus] ); |
|
} |
|
|
|
pVictim->m_iRuneStatus = 0; |
|
} |
|
|
|
if( pVictim->m_ppHook ) |
|
pVictim->m_ppHook->Reset_Grapple(); |
|
|
|
MESSAGE_BEGIN( MSG_ONE, gmsgRuneStatus, NULL, pVictim->pev ); |
|
WRITE_BYTE( pVictim->m_iRuneStatus ); |
|
MESSAGE_END(); |
|
|
|
if( !m_DisableDeathPenalty ) |
|
{ |
|
CHalfLifeMultiplay::PlayerKilled( pVictim, pKiller, pInflictor ); |
|
RecountTeams(); |
|
} |
|
} |
|
|
|
//========================================================= |
|
// IsTeamplay |
|
//========================================================= |
|
BOOL CThreeWave::IsTeamplay() |
|
{ |
|
return TRUE; |
|
} |
|
|
|
BOOL CThreeWave::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 CThreeWave::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; |
|
|
|
//As simple as this |
|
if( pPlayer->pev->team == pTarget->pev->team ) |
|
{ |
|
return GR_TEAMMATE; |
|
} |
|
|
|
return GR_NOTTEAMMATE; |
|
} |
|
|
|
//========================================================= |
|
//========================================================= |
|
BOOL CThreeWave::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 CThreeWave::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 *CThreeWave::GetTeamID( CBaseEntity *pEntity ) |
|
{ |
|
if( pEntity == NULL || pEntity->pev == NULL ) |
|
return ""; |
|
|
|
// return their team name |
|
return pEntity->TeamID(); |
|
} |
|
|
|
int CThreeWave::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 *CThreeWave::GetIndexedTeamName( int teamIndex ) |
|
{ |
|
if( teamIndex < 0 || teamIndex >= num_teams ) |
|
return ""; |
|
|
|
return team_names[teamIndex]; |
|
} |
|
|
|
BOOL CThreeWave::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; |
|
} |
|
|
|
void CThreeWave::GetFlagStatus( CBasePlayer *pPlayer ) |
|
{ |
|
CBaseEntity *pFlag = NULL; |
|
int iFoundCount = 0; |
|
int iDropped = 0; |
|
|
|
while( ( pFlag = UTIL_FindEntityByClassname( pFlag, "carried_flag_team1" ) ) != NULL ) |
|
{ |
|
if( pFlag && !FBitSet( pFlag->pev->flags, FL_KILLME ) ) |
|
iFoundCount++; |
|
} |
|
|
|
if( iFoundCount >= 1 ) |
|
iRedFlagStatus = RED_FLAG_STOLEN; |
|
|
|
if( !iFoundCount ) |
|
{ |
|
while( ( pFlag = UTIL_FindEntityByClassname( pFlag, "item_flag_team1" ) ) != NULL ) |
|
{ |
|
if( pFlag ) |
|
{ |
|
if( ( (CItemFlag*)pFlag )->Dropped ) |
|
iDropped++; |
|
|
|
iFoundCount++; |
|
} |
|
} |
|
|
|
if( iFoundCount > 1 && iDropped == 1 ) |
|
iRedFlagStatus = RED_FLAG_DROPPED; |
|
else if( iFoundCount >= 1 && iDropped == 0 ) |
|
iRedFlagStatus = RED_FLAG_ATBASE; |
|
} |
|
|
|
iDropped = iFoundCount = 0; |
|
|
|
while( ( pFlag = UTIL_FindEntityByClassname( pFlag, "carried_flag_team2" ) ) != NULL ) |
|
{ |
|
if( pFlag && !FBitSet( pFlag->pev->flags, FL_KILLME ) ) |
|
iFoundCount++; |
|
} |
|
|
|
if( iFoundCount >= 1 ) |
|
iBlueFlagStatus = BLUE_FLAG_STOLEN; |
|
|
|
if( !iFoundCount ) |
|
{ |
|
while( ( pFlag = UTIL_FindEntityByClassname( pFlag, "item_flag_team2" ) ) != NULL ) |
|
{ |
|
if( pFlag ) |
|
{ |
|
if( ( (CItemFlag* )pFlag )->Dropped ) |
|
iDropped++; |
|
|
|
iFoundCount++; |
|
} |
|
} |
|
|
|
if( iFoundCount > 1 && iDropped == 1 ) |
|
iBlueFlagStatus = BLUE_FLAG_DROPPED; |
|
else if( iFoundCount >= 1 && iDropped == 0 ) |
|
iBlueFlagStatus = BLUE_FLAG_ATBASE; |
|
} |
|
|
|
if( pPlayer ) |
|
{ |
|
if( pPlayer->pev->team == 0 ) |
|
{ |
|
MESSAGE_BEGIN( MSG_ONE, gmsgFlagStatus, NULL, pPlayer->edict() ); |
|
WRITE_BYTE( 0 ); |
|
WRITE_BYTE( iRedFlagStatus ); |
|
WRITE_BYTE( iBlueFlagStatus ); |
|
WRITE_BYTE( iRedTeamScore ); |
|
WRITE_BYTE( iBlueTeamScore ); |
|
MESSAGE_END(); |
|
} |
|
else |
|
{ |
|
MESSAGE_BEGIN( MSG_ONE, gmsgFlagStatus, NULL, pPlayer->edict() ); |
|
WRITE_BYTE( 1 ); |
|
WRITE_BYTE( iRedFlagStatus ); |
|
WRITE_BYTE( iBlueFlagStatus ); |
|
WRITE_BYTE( iRedTeamScore ); |
|
WRITE_BYTE( iBlueTeamScore ); |
|
MESSAGE_END(); |
|
} |
|
|
|
pPlayer->m_flFlagStatusTime = 0.0; |
|
} |
|
else |
|
{ |
|
MESSAGE_BEGIN( MSG_ALL, gmsgFlagStatus, NULL ); |
|
WRITE_BYTE( 1 ); |
|
WRITE_BYTE( iRedFlagStatus ); |
|
WRITE_BYTE( iBlueFlagStatus ); |
|
WRITE_BYTE( iRedTeamScore ); |
|
WRITE_BYTE( iBlueTeamScore ); |
|
MESSAGE_END(); |
|
|
|
m_flFlagStatusTime = 0.0; |
|
} |
|
|
|
for( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBasePlayer *plr = (CBasePlayer *)UTIL_PlayerByIndex( i ); |
|
|
|
if( plr ) |
|
{ |
|
MESSAGE_BEGIN( MSG_ALL, gmsgFlagCarrier, NULL ); |
|
WRITE_BYTE( plr->entindex() ); |
|
WRITE_BYTE( plr->m_bHasFlag ); |
|
MESSAGE_END(); |
|
} |
|
} |
|
} |
|
|
|
|
|
//========================================================= |
|
//========================================================= |
|
void CThreeWave::RecountTeams() |
|
{ |
|
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; |
|
} |
|
} |
|
} |
|
}
|
|
|