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.
570 lines
14 KiB
570 lines
14 KiB
/*** |
|
* |
|
* Copyright (c) 1996-2002, 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 CTF FLAG CODE |
|
****************************************************** |
|
*****************************************************/ |
|
|
|
#include "extdll.h" |
|
#include "util.h" |
|
#include "cbase.h" |
|
#include "player.h" |
|
#include "weapons.h" |
|
#include "gamerules.h" |
|
#include "items.h" |
|
#include "threewave_gamerules.h" |
|
#include "flags.h" |
|
|
|
unsigned short g_usCarried; |
|
unsigned short g_usFlagSpawn; |
|
enum Flag_Anims |
|
{ |
|
ON_GROUND = 0, |
|
NOT_CARRIED, |
|
CARRIED, |
|
WAVE_IDLE, |
|
FLAG_POSITION |
|
}; |
|
|
|
void CItemFlag::Spawn() |
|
{ |
|
Precache(); |
|
SET_MODEL( ENT( pev ), "models/flag.mdl" ); |
|
|
|
pev->movetype = MOVETYPE_TOSS; |
|
pev->solid = SOLID_TRIGGER; |
|
UTIL_SetOrigin( pev, pev->origin ); |
|
UTIL_SetSize( pev, Vector( -16, -16, 0 ), Vector( 16, 16, 16 ) ); |
|
|
|
SetThink( &CItemFlag::FlagThink ); |
|
SetTouch( &CItemFlag::FlagTouch ); |
|
|
|
pev->nextthink = gpGlobals->time + 0.3; |
|
|
|
//Set the Skin based on the team. |
|
pev->skin = pev->team; |
|
|
|
Dropped = FALSE; |
|
m_flDroppedTime = 0.0; |
|
|
|
pev->sequence = NOT_CARRIED; |
|
pev->framerate = 1.0; |
|
|
|
// if( !DROP_TO_FLOOR( ENT( pev ) ) ) |
|
// ResetFlag( pev->team ); |
|
} |
|
|
|
void CItemFlag::FlagTouch( CBaseEntity *pToucher ) |
|
{ |
|
if( !pToucher ) |
|
return; |
|
|
|
if( !pToucher->IsPlayer() ) |
|
return; |
|
|
|
if( FBitSet( pev->effects, EF_NODRAW ) ) |
|
return; |
|
|
|
if( pToucher->pev->health <= 0 ) |
|
return; |
|
|
|
if( pToucher->pev->team == 0 ) |
|
return; |
|
|
|
CBasePlayer *pPlayer = (CBasePlayer *)pToucher; |
|
|
|
//Same team as the flag |
|
if( pev->team == pToucher->pev->team ) |
|
{ |
|
//Flag is dropped, let's return it |
|
if( Dropped ) |
|
{ |
|
Dropped = FALSE; |
|
|
|
pPlayer->AddPoints( TEAM_CAPTURE_RECOVERY_BONUS, TRUE ); |
|
|
|
if( pPlayer->pev->team == RED ) |
|
{ |
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Returned_Red_Flag\"\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
|
|
if( ( (CThreeWave*)g_pGameRules )->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->pFlagReturner = pPlayer; |
|
pTeamMate->m_flFlagReturnTime = gpGlobals->time + TEAM_CAPTURE_RETURN_FLAG_ASSIST_TIMEOUT; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
if( pPlayer->pev->team == BLUE ) |
|
{ |
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Returned_Blue_Flag\"\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
|
|
if( ( (CThreeWave*)g_pGameRules )->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->pFlagReturner = pPlayer; |
|
pTeamMate->m_flFlagReturnTime = gpGlobals->time + TEAM_CAPTURE_RETURN_FLAG_ASSIST_TIMEOUT; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
//Back at home! |
|
ResetFlag( pev->team ); |
|
|
|
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL ); |
|
if( pev->team == RED ) |
|
WRITE_BYTE( RED_FLAG_RETURNED_PLAYER ); |
|
else if( pev->team == BLUE ) |
|
WRITE_BYTE( BLUE_FLAG_RETURNED_PLAYER ); |
|
WRITE_STRING( STRING( pToucher->pev->netname ) ); |
|
MESSAGE_END(); |
|
|
|
// Remove this one |
|
UTIL_Remove( this ); |
|
return; |
|
} |
|
// Not Dropped, means it's the one in our base |
|
else |
|
{ |
|
// We have the enemy flag! |
|
// Capture it! |
|
if( pPlayer->m_bHasFlag ) |
|
{ |
|
if( pev->team == RED ) |
|
Capture( pPlayer, BLUE ); |
|
else if( pev->team == BLUE ) |
|
Capture( pPlayer, RED ); |
|
|
|
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 ); |
|
return; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
if( Dropped ) |
|
{ |
|
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL ); |
|
if( pev->team == RED ) |
|
WRITE_BYTE( RED_FLAG_STOLEN ); |
|
else if( pev->team == BLUE ) |
|
WRITE_BYTE( BLUE_FLAG_STOLEN ); |
|
WRITE_STRING( STRING( pToucher->pev->netname ) ); |
|
MESSAGE_END(); |
|
|
|
pPlayer->m_bHasFlag = TRUE; |
|
|
|
CBaseEntity *pEnt = NULL; |
|
|
|
if( pev->team == RED ) |
|
{ |
|
pEnt = CBaseEntity::Create( "carried_flag_team1", pPlayer->pev->origin, pPlayer->pev->angles, pPlayer->edict() ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Picked_Up_Red_Flag\"\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
} |
|
else if( pev->team == BLUE ) |
|
{ |
|
pEnt = CBaseEntity::Create( "carried_flag_team2", pPlayer->pev->origin, pPlayer->pev->angles, pPlayer->edict() ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Picked_Up_Blue_Flag\"\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
} |
|
|
|
CCarriedFlag *pCarriedFlag = (CCarriedFlag *)pEnt; |
|
pCarriedFlag->Owner = pPlayer; |
|
|
|
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, 0, 0 ); |
|
|
|
UTIL_Remove( this ); |
|
} |
|
else |
|
{ |
|
pev->effects |= EF_NODRAW; |
|
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL ); |
|
if( pev->team == RED ) |
|
WRITE_BYTE( RED_FLAG_STOLEN ); |
|
else if( pev->team == BLUE ) |
|
WRITE_BYTE( BLUE_FLAG_STOLEN ); |
|
WRITE_STRING( STRING( pToucher->pev->netname ) ); |
|
MESSAGE_END(); |
|
|
|
pPlayer->m_bHasFlag = TRUE; |
|
pPlayer->m_flCarrierPickupTime = gpGlobals->time + TEAM_CAPTURE_CARRIER_FLAG_SINCE_TIMEOUT; |
|
|
|
CBaseEntity *pEnt = NULL; |
|
|
|
if( pev->team == RED ) |
|
{ |
|
pEnt = CBaseEntity::Create( "carried_flag_team1", pev->origin, pev->angles, pPlayer->edict() ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Stole_Red_Flag\"\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
} |
|
else if( pev->team == BLUE ) |
|
{ |
|
pEnt = CBaseEntity::Create( "carried_flag_team2", pev->origin, pev->angles, pPlayer->edict() ); |
|
|
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Stole_Blue_Flag\"\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
} |
|
|
|
CCarriedFlag *pCarriedFlag = (CCarriedFlag *)pEnt; |
|
pCarriedFlag->Owner = pPlayer; |
|
|
|
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, 0, 0 ); |
|
} |
|
|
|
( (CThreeWave*)g_pGameRules )->m_flFlagStatusTime = gpGlobals->time + 0.1; |
|
} |
|
} |
|
|
|
void CItemFlag::Capture( CBasePlayer *pPlayer, int iTeam ) |
|
{ |
|
CBaseEntity *pFlag1 = NULL; |
|
|
|
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL ); |
|
if( iTeam == RED ) |
|
WRITE_BYTE( RED_FLAG_CAPTURED ); |
|
else if ( iTeam == BLUE ) |
|
WRITE_BYTE( BLUE_FLAG_CAPTURED ); |
|
WRITE_STRING( STRING( pPlayer->pev->netname ) ); |
|
MESSAGE_END(); |
|
|
|
if( pPlayer->pFlagCarrierKiller ) |
|
{ |
|
if( pPlayer->m_flFlagCarrierKillTime > gpGlobals->time ) |
|
{ |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pPlayer->pFlagCarrierKiller->pev->netname ) ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " gets an assist for fragging the flag carrier!\n" ); |
|
|
|
pPlayer->pFlagCarrierKiller->AddPoints( TEAM_CAPTURE_FRAG_CARRIER_ASSIST_BONUS, TRUE ); |
|
pPlayer->pFlagCarrierKiller = NULL; |
|
pPlayer->m_flFlagCarrierKillTime = 0.0; |
|
} |
|
} |
|
|
|
if( pPlayer->pFlagReturner ) |
|
{ |
|
if( pPlayer->m_flFlagReturnTime > gpGlobals->time ) |
|
{ |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, STRING( pPlayer->pFlagReturner->pev->netname ) ); |
|
UTIL_ClientPrintAll( HUD_PRINTNOTIFY, " gets an assist for returning his flag!\n"); |
|
|
|
pPlayer->pFlagReturner->AddPoints( TEAM_CAPTURE_RETURN_FLAG_ASSIST_BONUS, TRUE ); |
|
pPlayer->pFlagReturner = NULL; |
|
pPlayer->m_flFlagReturnTime = 0.0; |
|
} |
|
} |
|
|
|
if( iTeam != pPlayer->pev->team ) |
|
{ |
|
if( iTeam == RED ) |
|
{ |
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Captured_Red_Flag\"\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
} |
|
else |
|
{ |
|
UTIL_LogPrintf( "\"%s<%i><%s><%s>\" triggered \"Captured_Blue_Flag\"\n", |
|
STRING( pPlayer->pev->netname ), |
|
GETPLAYERUSERID( pPlayer->edict() ), |
|
GETPLAYERAUTHID( pPlayer->edict() ), |
|
GetTeamName( pPlayer->pev->team ) ); |
|
} |
|
} |
|
|
|
if( iTeam == RED ) |
|
{ |
|
( (CThreeWave *)g_pGameRules )->iBlueTeamScore++; |
|
|
|
while( ( pFlag1 = UTIL_FindEntityByClassname( pFlag1, "carried_flag_team1" ) ) != NULL ) |
|
{ |
|
if( pFlag1 ) |
|
UTIL_Remove( pFlag1 ); |
|
} |
|
} |
|
else if( iTeam == BLUE ) |
|
{ |
|
( (CThreeWave*)g_pGameRules )->iRedTeamScore++; |
|
|
|
while( ( pFlag1 = UTIL_FindEntityByClassname( pFlag1, "carried_flag_team2" ) ) != NULL ) |
|
{ |
|
if ( pFlag1 ) |
|
UTIL_Remove( pFlag1 ); |
|
} |
|
} |
|
|
|
pPlayer->m_bHasFlag = FALSE; |
|
pPlayer->AddPoints( TEAM_CAPTURE_CAPTURE_BONUS, TRUE ); |
|
|
|
for( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
CBaseEntity *pTeamMate = UTIL_PlayerByIndex( i ); |
|
|
|
if( pTeamMate ) |
|
{ |
|
if( pTeamMate->pev->team == pPlayer->pev->team ) |
|
pTeamMate->AddPoints( TEAM_CAPTURE_TEAM_BONUS, TRUE ); |
|
} |
|
} |
|
|
|
ResetFlag( iTeam ); |
|
} |
|
|
|
void CItemFlag::Materialize() |
|
{ |
|
if ( pev->effects & EF_NODRAW ) |
|
{ |
|
pev->effects &= ~EF_NODRAW; |
|
pev->effects |= EF_MUZZLEFLASH; |
|
} |
|
|
|
PLAYBACK_EVENT_FULL( FEV_GLOBAL | FEV_RELIABLE, |
|
edict(), g_usFlagSpawn, 0, (float*)&g_vecZero, (float*)&g_vecZero, |
|
0.0, 0.0, pev->team, 0, 0, 0 ); |
|
|
|
Dropped = FALSE; |
|
|
|
SetTouch( &CItemFlag::FlagTouch ); |
|
SetThink( &CItemFlag::FlagThink ); |
|
} |
|
|
|
void CItemFlag::ResetFlag( int iTeam ) |
|
{ |
|
CBaseEntity *pFlag1 = NULL; |
|
|
|
if( iTeam == BLUE ) |
|
{ |
|
while( ( pFlag1 = UTIL_FindEntityByClassname( pFlag1, "item_flag_team2" ) ) != NULL ) |
|
{ |
|
CItemFlag *pFlag2 = (CItemFlag*)pFlag1; |
|
|
|
if( pFlag2->Dropped ) |
|
continue; |
|
|
|
if( pFlag2->pev->effects & EF_NODRAW ) |
|
pFlag2->Materialize(); |
|
} |
|
} |
|
else if( iTeam == RED ) |
|
{ |
|
while( ( pFlag1 = UTIL_FindEntityByClassname( pFlag1, "item_flag_team1" ) ) != NULL ) |
|
{ |
|
CItemFlag *pFlag2 = (CItemFlag*)pFlag1; |
|
|
|
if( pFlag2->Dropped ) |
|
continue; |
|
|
|
if( pFlag2->pev->effects & EF_NODRAW ) |
|
pFlag2->Materialize(); |
|
} |
|
} |
|
|
|
( (CThreeWave*)g_pGameRules )->m_flFlagStatusTime = gpGlobals->time + 0.1; |
|
} |
|
|
|
void CItemFlag::FlagThink() |
|
{ |
|
if( Dropped ) |
|
{ |
|
if( m_flDroppedTime <= gpGlobals->time ) |
|
{ |
|
ResetFlag( pev->team ); |
|
MESSAGE_BEGIN( MSG_ALL, gmsgCTFMsgs, NULL ); |
|
if( pev->team == RED ) |
|
WRITE_BYTE( RED_FLAG_RETURNED ); |
|
else if( pev->team == BLUE ) |
|
WRITE_BYTE( BLUE_FLAG_RETURNED ); |
|
WRITE_STRING( "" ); |
|
MESSAGE_END(); |
|
|
|
UTIL_Remove( this ); |
|
return; |
|
} |
|
} |
|
|
|
//Using 0.2 just in case we might lag the server. |
|
pev->nextthink = gpGlobals->time + 0.2; |
|
} |
|
|
|
void CItemFlag::Precache() |
|
{ |
|
PRECACHE_MODEL( "models/flag.mdl" ); |
|
PRECACHE_SOUND( "ctf/flagcap.wav" ); |
|
PRECACHE_SOUND( "ctf/flagtk.wav" ); |
|
PRECACHE_SOUND( "ctf/flagret.wav" ); |
|
} |
|
|
|
class CItemFlagTeam1 : public CItemFlag |
|
{ |
|
void Spawn() |
|
{ |
|
pev->classname = MAKE_STRING( "item_flag_team1" ); |
|
pev->team = RED; |
|
CItemFlag::Spawn(); |
|
} |
|
}; |
|
|
|
class CItemFlagTeam2 : public CItemFlag |
|
{ |
|
void Spawn() |
|
{ |
|
pev->classname = MAKE_STRING( "item_flag_team2" ); |
|
pev->team = BLUE; |
|
CItemFlag::Spawn(); |
|
} |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( item_flag_team1, CItemFlagTeam1 ) |
|
LINK_ENTITY_TO_CLASS( ctf_redflag, CItemFlagTeam1 ) |
|
LINK_ENTITY_TO_CLASS( item_flag_team2, CItemFlagTeam2 ) |
|
LINK_ENTITY_TO_CLASS( ctf_blueflag, CItemFlagTeam2 ) |
|
|
|
void CCarriedFlag::Spawn() |
|
{ |
|
Precache(); |
|
|
|
SET_MODEL( ENT( pev ), "models/flag.mdl" ); |
|
UTIL_SetOrigin( pev, pev->origin ); |
|
|
|
pev->movetype = MOVETYPE_NONE; |
|
pev->solid = SOLID_NOT; |
|
pev->effects |= EF_NODRAW; |
|
pev->sequence = WAVE_IDLE; |
|
pev->framerate = 1.0; |
|
|
|
/* |
|
if( pev->team == RED ) |
|
pev->skin = 1; |
|
else if( pev->team == BLUE ) |
|
pev->skin = 2;*/ |
|
pev->skin = pev->team; |
|
|
|
m_iOwnerOldVel = 0; |
|
|
|
SetThink( &CCarriedFlag::FlagThink ); |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
} |
|
|
|
void CCarriedFlag::Precache() |
|
{ |
|
PRECACHE_MODEL( "models/flag.mdl" ); |
|
} |
|
|
|
void CCarriedFlag::FlagThink() |
|
{ |
|
// Make it visible |
|
pev->effects &= ~EF_NODRAW; |
|
|
|
// And let if follow |
|
pev->aiment = ENT( Owner->pev ); |
|
pev->movetype = MOVETYPE_FOLLOW; |
|
|
|
// If owner is death or lost flag, remove |
|
if( !Owner->IsAlive() || !Owner->m_bHasFlag ) |
|
UTIL_Remove( this ); |
|
else |
|
{ |
|
// If owners speed is low, go in idle mode |
|
if( Owner->pev->velocity.Length() <= 75 && pev->sequence != WAVE_IDLE ) |
|
{ |
|
pev->sequence = WAVE_IDLE; |
|
} |
|
// Else let the flag go wild |
|
else if( Owner->pev->velocity.Length() >= 75 && pev->sequence != CARRIED ) |
|
{ |
|
pev->sequence = CARRIED; |
|
} |
|
|
|
pev->frame += pev->framerate; |
|
|
|
if( pev->frame < 0.0 || pev->frame >= 256.0 ) |
|
{ |
|
pev->frame -= (int)( pev->frame / 256.0 ) * 256.0; |
|
} |
|
pev->nextthink = gpGlobals->time + 0.1; |
|
} |
|
} |
|
|
|
class CCarriedFlagTeam1 : public CCarriedFlag |
|
{ |
|
void Spawn() |
|
{ |
|
pev->team = RED; |
|
CCarriedFlag::Spawn(); |
|
} |
|
}; |
|
|
|
class CCarriedFlagTeam2 : public CCarriedFlag |
|
{ |
|
void Spawn() |
|
{ |
|
pev->team = BLUE; |
|
CCarriedFlag::Spawn(); |
|
} |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( carried_flag_team1, CCarriedFlagTeam1 ) |
|
LINK_ENTITY_TO_CLASS( carried_flag_team2, CCarriedFlagTeam2 )
|
|
|