Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
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.
 
 
 
 
 
 

1509 lines
38 KiB

//++ BulliT - with ideas from http://www.planethalflife.com/whenitsdone/
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "aggamerules.h"
#include "agglobal.h"
#include "agctf.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
extern int gmsgCTFSound;
extern int gmsgCTFFlag;
extern int gmsgCountdown;
enum CTFSound
{
YouHaveFlag = 0,
TeamHaveFlag,
EnemyHaveFlag,
BlueFlagReturned,
RedFlagReturned,
BlueScores,
RedScores,
BlueFlagStolen,
RedFlagStolen,
//not used...
BlueLeads,
RedLeads,
TeamsTied,
SuddenDeath,
Stolen,
Capture,
};
FILE_GLOBAL int s_iTeam1Captures;
FILE_GLOBAL int s_iTeam2Captures;
DLL_GLOBAL bool g_bTeam1FlagStolen;
DLL_GLOBAL bool g_bTeam2FlagStolen;
DLL_GLOBAL bool g_bTeam1FlagLost;
DLL_GLOBAL bool g_bTeam2FlagLost;
FILE_GLOBAL int s_iPlayerFlag1;
FILE_GLOBAL int s_iPlayerFlag2;
extern int gmsgTeamScore;
AgCTF::AgCTF()
{
m_iTeam1Captures = 0;
m_iTeam2Captures = 0;
s_iTeam1Captures = s_iTeam2Captures = 0;
g_bTeam1FlagStolen = g_bTeam2FlagStolen = false;
g_bTeam1FlagLost = g_bTeam2FlagLost = false;
s_iPlayerFlag1 = 0;
s_iPlayerFlag2 = 0;
m_iPlayerFlag1 = 0;
m_iPlayerFlag2= 0;
m_fNextCountdown = 0.0;
m_fMatchStart = 0.0;
if (ag_ctf_roundbased.value)
m_Status = Waiting;
else
m_Status = Playing;
}
AgCTF::~AgCTF()
{
}
void AgCTF::PlayerInitHud(CBasePlayer* pPlayer)
{
ASSERT(NULL != pPlayer);
if (!pPlayer)
return;
ASSERT(NULL != pPlayer->pev);
if (!pPlayer->pev)
return;
MESSAGE_BEGIN( MSG_ONE, gmsgTeamScore, NULL, pPlayer->pev );
WRITE_STRING( CTF_TEAM1_NAME);
WRITE_SHORT( m_iTeam1Captures );
WRITE_SHORT( 0 );
MESSAGE_END();
MESSAGE_BEGIN( MSG_ONE, gmsgTeamScore, NULL, pPlayer->pev );
WRITE_STRING( CTF_TEAM2_NAME);
WRITE_SHORT( m_iTeam2Captures );
WRITE_SHORT( 0 );
MESSAGE_END();
}
bool AgCTF::CaptureLimit()
{
if (ag_ctf_capture_limit.value > 1
&& ( s_iTeam1Captures == ag_ctf_capture_limit.value
||s_iTeam2Captures == ag_ctf_capture_limit.value))
return true;
return false;
}
void AgCTF::SendCaptures(CBasePlayer* pPlayer)
{
ASSERT(NULL != pPlayer);
if (!pPlayer)
return;
ASSERT(NULL != pPlayer->pev);
if (!pPlayer->pev)
return;
MESSAGE_BEGIN( MSG_ONE, gmsgTeamScore, NULL, pPlayer->pev );
WRITE_STRING( CTF_TEAM1_NAME);
WRITE_SHORT( s_iTeam1Captures );
WRITE_SHORT( 0 );
MESSAGE_END();
MESSAGE_BEGIN( MSG_ONE, gmsgTeamScore, NULL, pPlayer->pev );
WRITE_STRING( CTF_TEAM2_NAME);
WRITE_SHORT( s_iTeam2Captures );
WRITE_SHORT( 0 );
MESSAGE_END();
}
void AgCTF::ResetScore(bool bResetCaptures)
{
m_iTeam1Captures = -1;
m_iTeam2Captures = -1;
s_iTeam1Captures = s_iTeam2Captures = 0;
m_Status = Playing;
if (bResetCaptures)
ResetCaptures();
}
void AgCTF::ResetCaptures()
{
g_bTeam1FlagStolen = g_bTeam2FlagStolen = false;
//Reset flag carrier.
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBasePlayer* pPlayerLoop = AgPlayerByIndex(i);
if (pPlayerLoop)
{
pPlayerLoop->m_bFlagTeam1 = false;
pPlayerLoop->m_bFlagTeam2 = false;
}
}
//Remove carried flag
CBaseEntity* pEntity = NULL;
pEntity = NULL;
while ((pEntity = UTIL_FindEntityByClassname( pEntity, "carried_flag_team1" )) != NULL)
UTIL_Remove(pEntity);
pEntity = NULL;
while ((pEntity = UTIL_FindEntityByClassname( pEntity, "carried_flag_team2" )) != NULL)
UTIL_Remove(pEntity);
//Remove dropped flag
pEntity = NULL;
while ((pEntity = UTIL_FindEntityByClassname( pEntity, "item_flag_team1" )) != NULL)
{
if (((AgCTFFlag*)pEntity)->m_bDropped)
UTIL_Remove(pEntity);
}
pEntity = NULL;
while ((pEntity = UTIL_FindEntityByClassname( pEntity, "item_flag_team2" )) != NULL)
{
if (((AgCTFFlag*)pEntity)->m_bDropped)
UTIL_Remove(pEntity);
}
//Reset base flag
AgCTFFlag::ResetFlag(CTF_TEAM1_NAME);
AgCTFFlag::ResetFlag(CTF_TEAM2_NAME);
}
void AgCTF::Think()
{
if (!g_pGameRules)
return;
if (m_iTeam1Captures != s_iTeam1Captures
||m_iTeam2Captures != s_iTeam2Captures)
{
m_iTeam1Captures = s_iTeam1Captures;
//Send new team score to all clients.
MESSAGE_BEGIN( MSG_ALL, gmsgTeamScore );
WRITE_STRING( CTF_TEAM1_NAME);
WRITE_SHORT( s_iTeam1Captures );
WRITE_SHORT( 0 );
MESSAGE_END();
m_iTeam2Captures = s_iTeam2Captures;
//Send new team score to all clients.
MESSAGE_BEGIN( MSG_ALL, gmsgTeamScore );
WRITE_STRING( CTF_TEAM2_NAME);
WRITE_SHORT( s_iTeam2Captures );
WRITE_SHORT( 0 );
MESSAGE_END();
}
if (m_iPlayerFlag1 != s_iPlayerFlag1
||m_iPlayerFlag2 != s_iPlayerFlag2)
{
m_iPlayerFlag1 = s_iPlayerFlag1;
m_iPlayerFlag2 = s_iPlayerFlag2;
//Send new flag status to all clients.
MESSAGE_BEGIN( MSG_ALL, gmsgCTFFlag );
WRITE_BYTE( m_iPlayerFlag1 );
WRITE_BYTE( m_iPlayerFlag2 );
MESSAGE_END();
}
m_FileItemCache.Init();
RoundBasedThink();
}
void AgCTF::RoundBasedThink()
{
//We only update status once every second.
if (m_fNextCountdown > gpGlobals->time)
return;
m_fNextCountdown = gpGlobals->time + 1.0;
//Handle the status
if (Waiting == m_Status)
{
g_bPaused = true;
m_Status = Countdown;
m_fMatchStart = gpGlobals->time + 8.0;
m_fNextCountdown = gpGlobals->time + 3.0;
//Write waiting message
MESSAGE_BEGIN( MSG_ALL, gmsgCountdown);
WRITE_BYTE( 50 );
WRITE_BYTE( 1 );
WRITE_STRING( m_sWinner.c_str() );
WRITE_STRING( "" );
MESSAGE_END();
}
else if (Countdown == m_Status)
{
if (m_fMatchStart < gpGlobals->time)
{
//Clear out the map
AgResetMap();
//Reset CTF items
ResetCaptures();
m_Status = Spawning;
m_sWinner = "";
//Time to start playing.
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBasePlayer* pPlayerLoop = AgPlayerByIndex(i);
if (pPlayerLoop && pPlayerLoop->m_bReady)
{
if (!pPlayerLoop->IsSpectator())
pPlayerLoop->RespawnMatch();
}
}
m_Status = Playing;
//Stop countdown
MESSAGE_BEGIN( MSG_ALL, gmsgCountdown);
WRITE_BYTE( -1 );
WRITE_BYTE( 0 );
WRITE_STRING( "" );
WRITE_STRING( "" );
MESSAGE_END();
g_bPaused = false;
}
else
{
//Write countdown message.
MESSAGE_BEGIN( MSG_ALL, gmsgCountdown);
WRITE_BYTE( (int)(m_fMatchStart - gpGlobals->time) );
WRITE_BYTE( 1 );
WRITE_STRING( "" );
WRITE_STRING( "" );
MESSAGE_END();
}
}
}
void AgCTF::RoundOver(const char* pszWinner)
{
m_sWinner = pszWinner;
m_Status = Waiting;
}
void AgCTF::ClientConnected(CBasePlayer* pPlayer)
{
ASSERT(NULL != pPlayer);
if (!pPlayer)
return;
ASSERT(NULL != pPlayer->pev);
if (!pPlayer->pev)
return;
}
void AgCTF::ClientDisconnected(CBasePlayer* pPlayer)
{
ASSERT(NULL != pPlayer);
if (!pPlayer)
return;
ASSERT(NULL != pPlayer->pev);
if (!pPlayer->pev)
return;
PlayerDropFlag(pPlayer);
}
void AgCTF::PlayerKilled(CBasePlayer* pPlayer,entvars_t *pKiller)
{
ASSERT(NULL != pPlayer);
if (!pPlayer)
return;
ASSERT(NULL != pPlayer->pev);
if (!pPlayer->pev)
return;
CBaseEntity* pKillerBE = CBaseEntity::Instance(pKiller);
if (pKillerBE && CLASS_PLAYER == pKillerBE->Classify())
{
CBasePlayer* pKillerPlayer = ((CBasePlayer*)pKillerBE);
AddPointsForKill(pKillerPlayer,pPlayer);
}
bool bReturnDirectly = (0 == strcmp(STRING(pKiller->classname),"trigger_hurt"));
if (bReturnDirectly)
{
if (pPlayer->m_bFlagTeam1)
{
CBaseEntity* pEntity = NULL;
pEntity = NULL;
while ((pEntity = UTIL_FindEntityByClassname( pEntity, "carried_flag_team1" )) != NULL)
UTIL_Remove(pEntity);
pPlayer->m_bFlagTeam1 = false;
AgCTFFlag::ResetFlag(CTF_TEAM1_NAME);
char szText[201];
sprintf(szText, "%s flag returned!", CTF_TEAM1_NAME);
AgConsole(szText);
UTIL_ClientPrintAll( HUD_PRINTCENTER, szText );
MESSAGE_BEGIN( MSG_ALL, gmsgCTFSound );
WRITE_BYTE( BlueFlagReturned );
MESSAGE_END();
}
else if (pPlayer->m_bFlagTeam2)
{
CBaseEntity* pEntity = NULL;
pEntity = NULL;
while ((pEntity = UTIL_FindEntityByClassname( pEntity, "carried_flag_team2" )) != NULL)
UTIL_Remove(pEntity);
pPlayer->m_bFlagTeam2 = false;
AgCTFFlag::ResetFlag(CTF_TEAM2_NAME);
char szText[201];
sprintf(szText, "%s flag returned!", CTF_TEAM2_NAME);
AgConsole(szText);
UTIL_ClientPrintAll( HUD_PRINTCENTER, szText );
MESSAGE_BEGIN( MSG_ALL, gmsgCTFSound );
WRITE_BYTE( RedFlagReturned );
MESSAGE_END();
}
}
else
PlayerDropFlag(pPlayer);
}
void AgCTF::AddPointsForKill(CBasePlayer *pAttacker, CBasePlayer *pKilled)
{
if ( pAttacker != pKilled && g_pGameRules->PlayerRelationship( pAttacker, pKilled ) == GR_TEAMMATE )
return; //Killed his team m8.
if( ( FStrEq(CTF_TEAM1_NAME, pKilled->m_szTeamName) && pKilled->m_bFlagTeam2 )
|| ( FStrEq(CTF_TEAM2_NAME, pKilled->m_szTeamName) && pKilled->m_bFlagTeam1 ) )
{
//He killed the flag carrier.
pAttacker->AddPoints(ag_ctf_carrierkillpoints.value, TRUE);
}
//Check if he is 192 units within his own flag (defending)
edict_t* pFind = NULL;
if (FStrEq(CTF_TEAM1_NAME, pAttacker->m_szTeamName))
pFind = FIND_ENTITY_BY_CLASSNAME(NULL,"item_flag_team1");
else if (FStrEq(CTF_TEAM2_NAME, pAttacker->m_szTeamName))
pFind = FIND_ENTITY_BY_CLASSNAME( NULL, "item_flag_team2" );
if (pFind)
{
Vector vtFlag = pFind->v.origin;
Vector vtPlayer = pKilled->pev->origin;
float fDistance = (vtFlag - vtPlayer).Length();
if (fDistance < 192)
//Add points for defending.
pAttacker->AddPoints(ag_ctf_defendpoints.value, TRUE);
}
}
void AgCTF::PlayerDropFlag(CBasePlayer* pPlayer, bool bPlayerDrop)
{
ASSERT(NULL != pPlayer);
if (!pPlayer)
return;
ASSERT(NULL != pPlayer->pev);
if (!pPlayer->pev)
return;
//When carrying a flag, drop it!
if (pPlayer->m_bFlagTeam1 || pPlayer->m_bFlagTeam2)
{
char szText [201];
CBaseEntity *pEnt = NULL;
if (bPlayerDrop)
UTIL_MakeVectors ( pPlayer->pev->angles );
if (pPlayer->m_bFlagTeam1)
{
pEnt = CBaseEntity::Create( "item_flag_team1", bPlayerDrop? (pPlayer->pev->origin + gpGlobals->v_forward * 10) : pPlayer->pev->origin, pPlayer->pev->angles, pPlayer->edict() );
sprintf(szText, "%s lost the %s flag!", STRING(pPlayer->pev->netname), CTF_TEAM1_NAME);
AgConsole(szText);
UTIL_ClientPrintAll( HUD_PRINTCENTER, szText );
g_bTeam1FlagLost = true;
}
else if (pPlayer->m_bFlagTeam2)
{
pEnt = CBaseEntity::Create( "item_flag_team2", bPlayerDrop? (pPlayer->pev->origin + gpGlobals->v_forward * 10) : pPlayer->pev->origin, pPlayer->pev->angles, pPlayer->edict() );
sprintf(szText, "%s lost the %s flag!", STRING(pPlayer->pev->netname), CTF_TEAM2_NAME);
AgConsole(szText);
UTIL_ClientPrintAll( HUD_PRINTCENTER, szText );
g_bTeam2FlagLost = true;
}
if (bPlayerDrop)
{
pEnt->pev->velocity = gpGlobals->v_forward * 300 + gpGlobals->v_forward * 100;
pEnt->pev->angles.z = 0;
}
else
pEnt->pev->velocity = pPlayer->pev->velocity * 1.2;
pEnt->pev->angles.x = 0;
AgCTFFlag *pFlag = (AgCTFFlag *)pEnt;
if (bPlayerDrop)
pFlag->m_fNextTouch = gpGlobals->time + 0.5; //Gotta give the flag a bit of time to fly away from player before it can be picked up again.
pFlag->m_bDropped = true;
pFlag->m_fNextReset = gpGlobals->time + ag_ctf_flag_resettime.value;
pPlayer->m_bFlagTeam1 = false;
pPlayer->m_bFlagTeam2 = false;
}
}
extern int gmsgItemPickup;
enum Flag_Animations
{
ON_GROUND = 0,
NOT_CARRIED,
CARRIED,
WAVE_IDLE,
FLAG_POSITION
};
void AgCTFFlag::Spawn ( void )
{
m_fNextTouch = 0;
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( &AgCTFFlag::Think );
SetTouch( &AgCTFFlag::FlagTouch );
pev->nextthink = gpGlobals->time + 0.1;
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
pev->skin = 1;
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
pev->skin = 2;
m_bDropped = false;
pev->sequence = NOT_CARRIED;
pev->framerate = 1.0;
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
{
pev->rendercolor.x = 0;
pev->rendercolor.y = 0;
pev->rendercolor.z = 128;
}
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
{
pev->rendercolor.x = 128;
pev->rendercolor.y = 0;
pev->rendercolor.z = 0;
}
pev->renderamt = 50;
pev->renderfx = kRenderFxGlowShell;
}
void AgCTFFlag::Precache( void )
{
PRECACHE_MODEL ("models/flag.mdl");
}
void AgCTFFlag::Capture(CBasePlayer *pPlayer, const char *m_szTeamName)
{
char szText[201];
sprintf(szText, "%s captured the %s flag!", STRING(pPlayer->pev->netname), m_szTeamName);
AgConsole(szText);
UTIL_ClientPrintAll( HUD_PRINTCENTER, szText );
//Give the player the points
pPlayer->AddPoints(ag_ctf_capturepoints.value, TRUE);
pPlayer->AddPointsToTeam(ag_ctf_teamcapturepoints.value, TRUE);
//And give the team a capture
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
{
MESSAGE_BEGIN( MSG_ALL, gmsgCTFSound );
WRITE_BYTE( RedScores );
MESSAGE_END();
s_iTeam2Captures++;
UTIL_LogPrintf("Team \"%s\" triggered \"Capture\" (%s \"%d\") (%s \"%d\")\n",CTF_TEAM2_NAME,CTF_TEAM1_NAME,s_iTeam1Captures,CTF_TEAM2_NAME,s_iTeam2Captures);
if (ag_ctf_roundbased.value)
g_pGameRules->m_CTF.RoundOver(CTF_TEAM2_NAME);
}
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
{
MESSAGE_BEGIN( MSG_ALL, gmsgCTFSound );
WRITE_BYTE( BlueScores );
MESSAGE_END();
s_iTeam1Captures++;
UTIL_LogPrintf("Team \"%s\" triggered \"Capture\" (%s \"%d\") (%s \"%d\")\n",CTF_TEAM1_NAME,CTF_TEAM1_NAME,s_iTeam1Captures,CTF_TEAM2_NAME,s_iTeam2Captures);
if (ag_ctf_roundbased.value)
g_pGameRules->m_CTF.RoundOver(CTF_TEAM1_NAME);
}
ResetFlag( m_szTeamName );
}
void AgCTFFlag::ResetFlag()
{
AgCTFFlag::ResetFlag(m_szTeamName);
char szText[201];
sprintf(szText, "%s flag returned!", m_szTeamName);
AgConsole(szText);
UTIL_ClientPrintAll( HUD_PRINTCENTER, szText );
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
{
MESSAGE_BEGIN( MSG_ALL, gmsgCTFSound );
WRITE_BYTE( BlueFlagReturned );
MESSAGE_END();
}
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
{
MESSAGE_BEGIN( MSG_ALL, gmsgCTFSound );
WRITE_BYTE( RedFlagReturned );
MESSAGE_END();
}
if (m_bDropped)
UTIL_Remove( this );
}
void AgCTFFlag::ResetFlag(const char *szTeamName)
{
edict_t *pFind;
if (FStrEq(CTF_TEAM1_NAME, szTeamName))
{
pFind = FIND_ENTITY_BY_CLASSNAME( NULL, "item_flag_team1" );
g_bTeam1FlagStolen = false;
g_bTeam1FlagLost = false;
}
else if (FStrEq(CTF_TEAM2_NAME, szTeamName))
{
pFind = FIND_ENTITY_BY_CLASSNAME( NULL, "item_flag_team2" );
g_bTeam2FlagStolen = false;
g_bTeam2FlagLost = false;
}
else
return;
while ( !FNullEnt( pFind ) )
{
CBaseEntity *pEnt = CBaseEntity::Instance( pFind );
AgCTFFlag *pFlag = (AgCTFFlag *)pEnt;
pFlag->Materialize( );
if (FStrEq(CTF_TEAM1_NAME, szTeamName))
pFind = FIND_ENTITY_BY_CLASSNAME( pFind, "item_flag_team1" );
else if (FStrEq(CTF_TEAM2_NAME, szTeamName))
pFind = FIND_ENTITY_BY_CLASSNAME( pFind, "item_flag_team2" );
}
}
void AgCTFFlag::FlagTouch( CBaseEntity *pOther )
{
if (m_fNextTouch > gpGlobals->time)
return;
// if it's not a player, ignore
if ( !pOther->IsPlayer() )
return;
if ( !pOther->IsAlive() )
return;
CBasePlayer *pPlayer = (CBasePlayer *)pOther;
if (MyTouch( pPlayer ))
{
SUB_UseTargets( pOther, USE_TOGGLE, 0 );
SetTouch( NULL );
SetThink( NULL );
//if it's a dropped flag, remove. Else make it invisible
if (m_bDropped)
UTIL_Remove( this );
else
pev->effects |= EF_NODRAW;
}
}
void AgCTFFlag::Materialize( void )
{
if ( pev->effects & EF_NODRAW )
{
// changing from invisible state to visible.
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "items/suitchargeok1.wav", 1, ATTN_NORM, 0, 150 );
pev->effects &= ~EF_NODRAW;
pev->effects |= EF_MUZZLEFLASH;
}
SetTouch( &AgCTFFlag::FlagTouch );
SetThink( &AgCTFFlag::Think );
}
BOOL AgCTFFlag::MyTouch( CBasePlayer *pPlayer )
{
char szText[201];
// Can only carry one flag and can not pickup own flag
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
{
//if client has other teams flag and it isn't a dropped flag, then there is a capture!
if ( pPlayer->m_bFlagTeam2 && !m_bDropped)
{
pPlayer->m_bFlagTeam2 = false;
UTIL_SendDirectorMessage( pPlayer->edict(), this->edict(), 10 | DRC_FLAG_DRAMATIC);
Capture(pPlayer, CTF_TEAM2_NAME);
return FALSE;
}
else if ( pPlayer->m_bFlagTeam1 )
{
return FALSE;
}
else if (FStrEq(pPlayer->m_szTeamName, CTF_TEAM1_NAME))
{
//if dropped, return flag
if (m_bDropped)
{
ResetFlag(CTF_TEAM1_NAME);
sprintf(szText, "%s returned the %s flag!", STRING(pPlayer->pev->netname), m_szTeamName);
AgConsole(szText);
UTIL_ClientPrintAll( HUD_PRINTCENTER, szText );
UTIL_Remove( this );
pPlayer->AddPoints(ag_ctf_returnpoints.value, TRUE);
MESSAGE_BEGIN( MSG_ALL, gmsgCTFSound );
WRITE_BYTE( BlueFlagReturned );
MESSAGE_END();
}
//but don't pick it up!
return FALSE;
}
}
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
{
//if client has other teams flag and it isn't a dropped flag, then there is a capture!
if ( pPlayer->m_bFlagTeam1 && !m_bDropped)
{
pPlayer->m_bFlagTeam1 = false;
UTIL_SendDirectorMessage( pPlayer->edict(), this->edict(), 10 | DRC_FLAG_DRAMATIC);
Capture(pPlayer, CTF_TEAM1_NAME);
return FALSE;
}
else if ( pPlayer->m_bFlagTeam2 )
{
return FALSE;
}
else if (FStrEq(pPlayer->m_szTeamName, CTF_TEAM2_NAME))
{
//if dropped, return flag
if (m_bDropped)
{
ResetFlag(CTF_TEAM2_NAME);
sprintf(szText, "%s returned the %s flag!", STRING(pPlayer->pev->netname), m_szTeamName);
AgConsole(szText);
UTIL_ClientPrintAll( HUD_PRINTCENTER, szText );
UTIL_Remove( this );
MESSAGE_BEGIN( MSG_ALL, gmsgCTFSound );
WRITE_BYTE( RedFlagReturned );
MESSAGE_END();
pPlayer->AddPoints(ag_ctf_returnpoints.value, TRUE);
}
//but don't pick it up!
return FALSE;
}
}
if ( ( pPlayer->pev->weapons & (1<<WEAPON_SUIT) ) )
{
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
{
pPlayer->m_bFlagTeam1 = true;
// player is now carrying the flag of team1, so give him the flag
CBaseEntity *pEnt = CBaseEntity::Create( "carried_flag_team1", pev->origin, pev->angles, pPlayer->edict() );
AgCTFPlayerFlag *pCarriedFlag = (AgCTFPlayerFlag *)pEnt;
pCarriedFlag->m_pOwner = pPlayer;
s_iPlayerFlag1 = pPlayer->entindex();
/*
//Glow blue
pCarriedFlag->pev->renderfx = kRenderFxGlowShell;
pCarriedFlag->pev->rendercolor = Vector( 0, 0, 255 ); // RGB
pCarriedFlag->pev->renderamt = 100; // Shell size
*/
}
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
{
pPlayer->m_bFlagTeam2 = true;
// player is now carrying the flag of team2, so give him the flag
CBaseEntity *pEnt = CBaseEntity::Create( "carried_flag_team2", pev->origin, pev->angles, pPlayer->edict() );
AgCTFPlayerFlag *pCarriedFlag = (AgCTFPlayerFlag *)pEnt;
pCarriedFlag->m_pOwner = pPlayer;
s_iPlayerFlag2 = pPlayer->entindex();
/*
//Glow red
pCarriedFlag->pev->renderfx = kRenderFxGlowShell;
pCarriedFlag->pev->rendercolor = Vector( 255, 0, 0 ); // RGB
pCarriedFlag->pev->renderamt = 100; // Shell size
*/
}
MESSAGE_BEGIN( MSG_ONE, gmsgItemPickup, NULL, pPlayer->pev );
WRITE_STRING( STRING(pev->classname) );
MESSAGE_END();
//Let all players hear and read that the flag is gone
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
{
if (!g_bTeam1FlagLost)
pPlayer->AddPoints(ag_ctf_stealpoints.value, TRUE);
sprintf(szText, "%s got the %s flag!\n", STRING(pPlayer->pev->netname), CTF_TEAM1_NAME);
}
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
{
if (!g_bTeam2FlagLost)
pPlayer->AddPoints(ag_ctf_stealpoints.value, TRUE);
sprintf(szText, "%s got the %s flag!\n", STRING(pPlayer->pev->netname), CTF_TEAM2_NAME);
}
AgConsole(szText);
UTIL_ClientPrintAll( HUD_PRINTCENTER, szText );
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
CBasePlayer* pPlayerLoop = AgPlayerByIndex(i);
if (pPlayerLoop)
{
if (pPlayer != pPlayerLoop)
{
if (pPlayerLoop->IsSpectator() || pPlayerLoop->IsProxy())
{
if (!m_bDropped)
{
if (FStrEq(m_szTeamName, CTF_TEAM1_NAME))
{
MESSAGE_BEGIN( MSG_ONE, gmsgCTFSound, NULL, pPlayerLoop->pev );
WRITE_BYTE(BlueFlagStolen);
MESSAGE_END();
}
else
{
MESSAGE_BEGIN( MSG_ONE, gmsgCTFSound, NULL, pPlayerLoop->pev );
WRITE_BYTE(RedFlagStolen);
MESSAGE_END();
}
}
}
else if (FStrEq(pPlayerLoop->m_szTeamName, m_szTeamName))
{
MESSAGE_BEGIN( MSG_ONE, gmsgCTFSound, NULL, pPlayerLoop->pev );
WRITE_BYTE(EnemyHaveFlag);
MESSAGE_END();
}
else
{
MESSAGE_BEGIN( MSG_ONE, gmsgCTFSound, NULL, pPlayerLoop->pev );
WRITE_BYTE(TeamHaveFlag);
MESSAGE_END();
}
}
else
{
MESSAGE_BEGIN( MSG_ONE, gmsgCTFSound, NULL, pPlayerLoop->pev );
WRITE_BYTE(YouHaveFlag);
MESSAGE_END();
}
}
}
int iPowerUp = 0;
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
{
g_bTeam1FlagStolen = true;
g_bTeam1FlagLost = false;
//Glow red
pPlayer->pev->renderfx = kRenderFxGlowShell;
pPlayer->pev->rendercolor = Vector( 128, 0, 0 ); // RGB
pPlayer->pev->renderamt = 50; // Shell size
iPowerUp = 2;
}
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
{
g_bTeam2FlagStolen = true;
g_bTeam2FlagLost = false;
//Glow blue
pPlayer->pev->renderfx = kRenderFxGlowShell;
pPlayer->pev->rendercolor = Vector( 0, 0, 128 ); // RGB
pPlayer->pev->renderamt = 50; // Shell size
iPowerUp = 2;
}
UTIL_SendDirectorMessage( pPlayer->edict(), this->edict(), 8 | DRC_FLAG_DRAMATIC);
return TRUE;
}
return FALSE;
}
void AgCTFFlag::Think( void )
{
if (m_bDropped && m_fNextReset <= gpGlobals->time)
{
//Let all players know that the flag has been returned
char szText[201];
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
{
sprintf(szText, "The %s flag has returned.\n", CTF_TEAM1_NAME);
ResetFlag(CTF_TEAM1_NAME);
MESSAGE_BEGIN( MSG_ALL, gmsgCTFSound );
WRITE_BYTE( BlueFlagReturned );
MESSAGE_END();
}
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
{
sprintf(szText, "The %s flag has returned.\n", CTF_TEAM2_NAME);
ResetFlag(CTF_TEAM2_NAME);
MESSAGE_BEGIN( MSG_ALL, gmsgCTFSound );
WRITE_BYTE( RedFlagReturned );
MESSAGE_END();
}
AgConsole(szText);
UTIL_ClientPrintAll( HUD_PRINTCENTER, szText );
UTIL_Remove( this );
return;
}
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 AgCTFFlagTeam1 : public AgCTFFlag
{
void Spawn( void )
{
pev->classname = MAKE_STRING("item_flag_team1"); //CCTF map compatibility hack
strcpy( m_szTeamName, CTF_TEAM1_NAME );
AgCTFFlag::Spawn( );
}
};
#ifndef AG_NO_CLIENT_DLL
LINK_ENTITY_TO_CLASS( item_flag_team1, AgCTFFlagTeam1 );
LINK_ENTITY_TO_CLASS( ctf_blueflag, AgCTFFlagTeam1 ); //CCTF map compatibility hack
#endif
class AgCTFFlagTeam2 : public AgCTFFlag
{
void Spawn( void )
{
pev->classname = MAKE_STRING("item_flag_team2"); //CCTF map compatibility hack
strcpy( m_szTeamName, CTF_TEAM2_NAME );
AgCTFFlag::Spawn( );
}
};
#ifndef AG_NO_CLIENT_DLL
LINK_ENTITY_TO_CLASS( item_flag_team2, AgCTFFlagTeam2 );
LINK_ENTITY_TO_CLASS( ctf_redflag, AgCTFFlagTeam2 ); //CCTF map compatibility hack
#endif
class AgCTFFlagTeamOP4 : public AgCTFFlag
{
int m_iTeam;
void KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "goal_no"))
{
m_iTeam = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "ctf_flag")) //HLE map compatibility hack
{
if (1 == atoi(pkvd->szValue))
m_iTeam = 2;
else if (2 == atoi(pkvd->szValue))
m_iTeam = 1;
pkvd->fHandled = TRUE;
}
else
AgCTFFlag::KeyValue( pkvd );
}
void Spawn( void )
{
if (1 == m_iTeam)
{
pev->classname = MAKE_STRING("item_flag_team1");
strcpy( m_szTeamName, CTF_TEAM1_NAME );
}
else if (2 == m_iTeam)
{
pev->classname = MAKE_STRING("item_flag_team2");
strcpy( m_szTeamName, CTF_TEAM2_NAME );
}
AgCTFFlag::Spawn( );
}
};
#ifndef AG_NO_CLIENT_DLL
LINK_ENTITY_TO_CLASS( item_ctfflag, AgCTFFlagTeamOP4 ); //OP4CTF map compatibility hack.
LINK_ENTITY_TO_CLASS( info_flag_ctf, AgCTFFlagTeamOP4 ); //HLE map compatibility hack
#endif
//=========================================================
// Carried Flag
//
// This is a complete new entity because it doesn't behave
// as a flag. It just sits on the back of the player and
// removes itself at the right time. (When player is gone
// or death or lost the flag.)
//=========================================================
void AgCTFPlayerFlag ::Spawn( )
{
Precache( );
SET_MODEL(ENT(pev), "models/flag.mdl");
UTIL_SetOrigin( pev, pev->origin );
pev->movetype = MOVETYPE_NONE;
pev->solid = SOLID_NOT;
//HACKHACKHACK: Overcome the attachment with no owner yet model "hop" by making it invisible
pev->effects |= EF_NODRAW;
pev->sequence = WAVE_IDLE;
pev->framerate = 1.0;
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
pev->skin = 1;
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
pev->skin = 2;
SetThink( &AgCTFPlayerFlag::Think );
pev->nextthink = gpGlobals->time + 0.1;
}
void AgCTFPlayerFlag::UpdateOnRemove( void )
{
if (FStrEq(CTF_TEAM1_NAME, m_szTeamName))
s_iPlayerFlag1 = 0;
else if (FStrEq(CTF_TEAM2_NAME, m_szTeamName))
s_iPlayerFlag2 = 0;
}
void AgCTFPlayerFlag::Precache( )
{
PRECACHE_MODEL ("models/flag.mdl");
}
void AgCTFPlayerFlag::Think( )
{
//Make it visible
pev->effects &= ~EF_NODRAW;
//And let if follow
pev->aiment = ENT(m_pOwner->pev);
pev->movetype = MOVETYPE_FOLLOW;
//Remove if owner is death
if (!m_pOwner->IsAlive())
UTIL_Remove( this );
//If owner lost flag, remove
if ( !m_pOwner->m_bFlagTeam1 && !m_pOwner->m_bFlagTeam2)
{
UTIL_Remove( this );
}
else
{
//If owners speed is low, go in idle mode
if (m_pOwner->pev->velocity.Length() <= 75 && pev->sequence != WAVE_IDLE)
{
pev->sequence = WAVE_IDLE;
}
//Else let the flag go wild
else if (m_pOwner->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 AgCTFPlayerFlagTeam1 : public AgCTFPlayerFlag
{
void Spawn( void )
{
strcpy( m_szTeamName, CTF_TEAM1_NAME );
AgCTFPlayerFlag::Spawn( );
}
};
#ifndef AG_NO_CLIENT_DLL
LINK_ENTITY_TO_CLASS( carried_flag_team1, AgCTFPlayerFlagTeam1 );
#endif
class AgCTFPlayerFlagTeam2 : public AgCTFPlayerFlag
{
void Spawn( void )
{
strcpy( m_szTeamName, CTF_TEAM2_NAME );
AgCTFPlayerFlag::Spawn( );
}
};
#ifndef AG_NO_CLIENT_DLL
LINK_ENTITY_TO_CLASS( carried_flag_team2, AgCTFPlayerFlagTeam2 );
#endif
class AgCTFDetect : public CBaseEntity
{
void Spawn( void )
{
UTIL_SetOrigin( pev, pev->origin );
pev->solid = SOLID_NOT;
pev->effects = EF_NODRAW;
AgString sGametype = CVAR_GET_STRING("sv_ag_gametype");
if (sGametype != "ctf")
CVAR_SET_STRING("sv_ag_gamemode","ctf");
}
void KeyValue( KeyValueData* pkvd)
{
pkvd->fHandled = FALSE;
}
};
#ifndef AG_NO_CLIENT_DLL
LINK_ENTITY_TO_CLASS( info_hmctfdetect, AgCTFDetect );
LINK_ENTITY_TO_CLASS( info_ctfdetect, AgCTFDetect ); //OP4 CTF detect
LINK_ENTITY_TO_CLASS( game_mode_ctf, AgCTFDetect ); //HLE CTF detect
#endif
/*
============
EntSelectCTFSpawnPoint
Returns the CTF entity to spawn at
USES AND SETS GLOBAL g_pLastSpawn
============
*/
extern CBaseEntity *g_pLastSpawn;
BOOL IsSpawnPointValid( CBaseEntity *pPlayer, CBaseEntity *pSpot);
inline int FNullEnt( CBaseEntity *ent ) { return (ent == NULL) || FNullEnt( ent->edict() ); }
edict_t *EntSelectCTFSpawnPoint( CBaseEntity *pPlayer )
{
CBaseEntity *pSpot;
edict_t *player;
player = pPlayer->edict();
CBasePlayer *cbPlayer = (CBasePlayer *)pPlayer; //we need a CBasePlayer
pSpot = g_pLastSpawn;
// Randomize the start spot
for ( int i = RANDOM_LONG(1,5); i > 0; i-- )
{
if (FStrEq(cbPlayer->m_szTeamName, CTF_TEAM1_NAME))
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_team1" );
else if (FStrEq(cbPlayer->m_szTeamName, CTF_TEAM2_NAME))
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_team2" );
else
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
}
if ( FNullEnt( pSpot ) ) // skip over the null point
{
if (FStrEq(cbPlayer->m_szTeamName, CTF_TEAM1_NAME))
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_team1" );
else if (FStrEq(cbPlayer->m_szTeamName, CTF_TEAM2_NAME))
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_team2" );
else
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
}
CBaseEntity *pFirstSpot = pSpot;
do
{
if ( pSpot )
{
// check if pSpot is valid
if ( IsSpawnPointValid( pPlayer, pSpot ) )
{
if ( pSpot->pev->origin == Vector( 0, 0, 0 ) )
{
if (FStrEq(cbPlayer->m_szTeamName, CTF_TEAM1_NAME))
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_team1" );
else if (FStrEq(cbPlayer->m_szTeamName, CTF_TEAM2_NAME))
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_team2" );
else
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
continue;
}
// valid pSpot, so it can be returned
goto ReturnSpot;
}
}
// increment pSpot
if (FStrEq(cbPlayer->m_szTeamName, CTF_TEAM1_NAME))
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_team1" );
else if (FStrEq(cbPlayer->m_szTeamName, CTF_TEAM2_NAME))
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_team2" );
else
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
} while ( pSpot != pFirstSpot ); // loop if we're not back to the start
// we haven't found a place to spawn yet, so kill any guy at the first spawn point and spawn there
if ( !FNullEnt( pSpot ) )
{
CBaseEntity *ent = NULL;
while ( (ent = UTIL_FindEntityInSphere( ent, pSpot->pev->origin, 128 )) != NULL )
{
// if ent is a client, kill em (unless they are ourselves)
if ( ent->IsPlayer() && !(ent->edict() == player) )
ent->TakeDamage( VARS(INDEXENT(0)), VARS(INDEXENT(0)), 300, DMG_GENERIC );
}
goto ReturnSpot;
}
ReturnSpot:
if ( FNullEnt( pSpot ) )
{
ALERT(at_error, "PutClientInServer: no info_player_team1,info_player_team2 on level");
ClientPrint(pPlayer->pev,HUD_PRINTCENTER, "This is not a valid CTF map!" );
pSpot = UTIL_FindEntityByClassname( pSpot, "info_player_deathmatch" );
if (FNullEnt( pSpot ))
return INDEXENT(0);
}
g_pLastSpawn = pSpot;
return pSpot->edict();
}
class AgCTFSpawn : public CPointEntity
{
int m_iTeam;
public:
void KeyValue( KeyValueData *pkvd );
BOOL IsTriggered( CBaseEntity *pEntity );
void Spawn( void );
private:
};
void AgCTFSpawn::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "master"))
{
pev->netname = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
//OP4 map compatibility
else if (FStrEq(pkvd->szKeyName, "team_no"))
{
m_iTeam = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CPointEntity::KeyValue( pkvd );
}
BOOL AgCTFSpawn::IsTriggered( CBaseEntity *pEntity )
{
BOOL master = UTIL_IsMasterTriggered( pev->netname, pEntity );
return master;
}
void AgCTFSpawn :: Spawn( void )
{
//CCTF map compatibility
if (FStrEq(STRING(pev->classname), "ctf_bluespawn"))
pev->classname = MAKE_STRING("info_player_team1");
else if (FStrEq(STRING(pev->classname), "ctf_redspawn"))
pev->classname = MAKE_STRING("info_player_team2");
//HLE map compatibility
else if (FStrEq(STRING(pev->classname), "info_player_ctf_blue"))
pev->classname = MAKE_STRING("info_player_team1");
else if (FStrEq(STRING(pev->classname), "info_player_ctf_red"))
pev->classname = MAKE_STRING("info_player_team2");
//OP4 map compatibility
else if (1 == m_iTeam)
pev->classname = MAKE_STRING("info_player_team1");
else if (2 == m_iTeam)
pev->classname = MAKE_STRING("info_player_team2");
pev->solid = SOLID_NOT;
}
#ifndef AG_NO_CLIENT_DLL
LINK_ENTITY_TO_CLASS(info_player_team1,AgCTFSpawn);
LINK_ENTITY_TO_CLASS(ctf_bluespawn,AgCTFSpawn); //CCTF map compatibility
LINK_ENTITY_TO_CLASS(info_player_team2,AgCTFSpawn);
LINK_ENTITY_TO_CLASS(ctf_redspawn,AgCTFSpawn); //CCTF map compatibility
LINK_ENTITY_TO_CLASS(info_ctfspawn,AgCTFSpawn); //OP4 CTF map compatibility
LINK_ENTITY_TO_CLASS(info_player_ctf_blue,AgCTFSpawn); //HLE CTF map compatibility
LINK_ENTITY_TO_CLASS(info_player_ctf_red,AgCTFSpawn); //HLE CTF map compatibility
#endif
#include "vector.h"
class AgCTFFileItemCache;
AgCTFFileItem::AgCTFFileItem()
{
m_vOrigin = Vector(0,0,0);
m_vAngles = Vector(0,0,0);
m_szName[0] = '\0';
}
AgCTFFileItem::~AgCTFFileItem()
{
}
void AgCTFFileItem::Show()
{
CLaserSpot* pSpot = CLaserSpot::CreateSpot();
UTIL_SetOrigin( pSpot->pev, m_vOrigin );
pSpot->LiveForTime(5.0);
}
AgCTFFileItemCache::AgCTFFileItemCache()
{
m_bInitDone = false;
Load();
}
AgCTFFileItemCache::~AgCTFFileItemCache()
{
//Delete all.
for (AgCTFFileItemList::iterator itrFileItems = m_lstFileItems.begin() ;itrFileItems != m_lstFileItems.end(); ++itrFileItems)
delete *itrFileItems;
m_lstFileItems.clear();
}
void AgCTFFileItemCache::Add(const AgString& sFileItem,CBasePlayer* pPlayer)
{
ASSERT(NULL != pPlayer);
if (!pPlayer)
return;
ASSERT(NULL != pPlayer->pev);
if (!pPlayer->pev)
return;
if (0 == sFileItem.size())
return;
AgCTFFileItem* pFileItem = new AgCTFFileItem;
strcpy(pFileItem->m_szName,sFileItem.c_str());
pFileItem->m_vOrigin = pPlayer->pev->origin;
pFileItem->m_vAngles = pPlayer->pev->angles;
m_lstFileItems.push_back(pFileItem);
pFileItem->Show();
Save(pPlayer);
AgConsole(UTIL_VarArgs("Added item %s.",(const char*)sFileItem.c_str()),pPlayer);
}
void AgCTFFileItemCache::Del(CBasePlayer* pPlayer)
{
ASSERT(NULL != pPlayer);
if (!pPlayer)
return;
ASSERT(NULL != pPlayer->pev);
if (!pPlayer->pev)
return;
if (0 == m_lstFileItems.size())
return;
AgCTFFileItem* pFileItem = m_lstFileItems.back();
AgConsole(UTIL_VarArgs("Deleted last item - %s.",pFileItem->m_szName,pPlayer));
m_lstFileItems.pop_back();
Save(pPlayer);
}
void AgCTFFileItemCache::List(CBasePlayer* pPlayer)
{
ASSERT(NULL != pPlayer);
if (!pPlayer)
return;
ASSERT(NULL != pPlayer->pev);
if (!pPlayer->pev)
return;
for (AgCTFFileItemList::iterator itrFileItems = m_lstFileItems.begin() ;itrFileItems != m_lstFileItems.end(); ++itrFileItems)
{
AgConsole(UTIL_VarArgs("%s",(const char*)(*itrFileItems)->m_szName),pPlayer);
(*itrFileItems)->Show();
}
}
void AgCTFFileItemCache::Load(CBasePlayer* pPlayer)
{
for (AgCTFFileItemList::iterator itrFileItems = m_lstFileItems.begin() ;itrFileItems != m_lstFileItems.end(); ++itrFileItems)
delete *itrFileItems;
m_lstFileItems.clear();
char szFile[MAX_PATH];
char szData[20000];
sprintf(szFile, "%s/ctf/%s.ctf", AgGetDirectory(),STRING(gpGlobals->mapname));
FILE* pFile = fopen(szFile,"r");
if (!pFile)
{
// file error
return;
}
int iRead = fread(szData,sizeof(char),sizeof(szData)-2,pFile);
fclose(pFile);
if (0 >= iRead)
return;
szData[iRead] = '\0';
char* pszCTFString = strtok( szData, "\n");
while (pszCTFString != NULL)
{
AgCTFFileItem* pFileItem = new AgCTFFileItem;
sscanf(pszCTFString,"%s %f %f %f %f %f %f\n",pFileItem->m_szName,&pFileItem->m_vOrigin.x,&pFileItem->m_vOrigin.y,&pFileItem->m_vOrigin.z,&pFileItem->m_vAngles.x,&pFileItem->m_vAngles.y,&pFileItem->m_vAngles.z);
m_lstFileItems.push_back(pFileItem);
pszCTFString = strtok( NULL, "\n");
}
}
void AgCTFFileItemCache::Save(CBasePlayer* pPlayer)
{
if (0 == m_lstFileItems.size())
return;
char szFile[MAX_PATH];
sprintf(szFile, "%s/ctf/%s.ctf", AgGetDirectory(),STRING(gpGlobals->mapname));
FILE* pFile = fopen(szFile,"wb");
if (!pFile)
{
// file error
AgConsole(UTIL_VarArgs("Couldn't create/save FileItem file %s.",szFile),pPlayer);
return;
}
//Loop and write the file.
for (AgCTFFileItemList::iterator itrFileItems = m_lstFileItems.begin() ;itrFileItems != m_lstFileItems.end(); ++itrFileItems)
{
//Append.
AgCTFFileItem* pFileItem = *itrFileItems;
fprintf(pFile,"%s %f %f %f %f %f %f\n",pFileItem->m_szName,pFileItem->m_vOrigin.x,pFileItem->m_vOrigin.y,pFileItem->m_vOrigin.z,pFileItem->m_vAngles.x,pFileItem->m_vAngles.y,pFileItem->m_vAngles.z);
}
fflush(pFile);
fclose(pFile);
}
void AgCTFFileItemCache::Init()
{
if (m_bInitDone)
return;
m_bInitDone = true;
for (AgCTFFileItemList::iterator itrFileItems = m_lstFileItems.begin() ;itrFileItems != m_lstFileItems.end(); ++itrFileItems)
{
AgCTFFileItem* pFileItem = *itrFileItems;
if (g_pGameRules->IsAllowedToSpawn(pFileItem->m_szName))
CBaseEntity::Create(pFileItem->m_szName, pFileItem->m_vOrigin, pFileItem->m_vAngles, INDEXENT(0));
}
}
//-- Martin Webrant