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.
928 lines
22 KiB
928 lines
22 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. |
|
* |
|
****/ |
|
|
|
// ------------------------------------------- |
|
// |
|
// maprules.cpp |
|
// |
|
// This module contains entities for implementing/changing game |
|
// rules dynamically within each map (.BSP) |
|
// |
|
// ------------------------------------------- |
|
|
|
#include "extdll.h" |
|
#include "eiface.h" |
|
#include "util.h" |
|
#include "gamerules.h" |
|
//#include "maprules.h" //empty file |
|
#include "cbase.h" |
|
#include "player.h" |
|
|
|
class CRuleEntity : public CBaseEntity |
|
{ |
|
public: |
|
void Spawn( void ); |
|
void KeyValue( KeyValueData *pkvd ); |
|
virtual int Save( CSave &save ); |
|
virtual int Restore( CRestore &restore ); |
|
static TYPEDESCRIPTION m_SaveData[]; |
|
|
|
void SetMaster( int iszMaster ) { m_iszMaster = iszMaster; } |
|
|
|
protected: |
|
BOOL CanFireForActivator( CBaseEntity *pActivator ); |
|
|
|
private: |
|
string_t m_iszMaster; |
|
}; |
|
|
|
TYPEDESCRIPTION CRuleEntity::m_SaveData[] = |
|
{ |
|
DEFINE_FIELD( CRuleEntity, m_iszMaster, FIELD_STRING), |
|
}; |
|
|
|
IMPLEMENT_SAVERESTORE( CRuleEntity, CBaseEntity ) |
|
|
|
void CRuleEntity::Spawn( void ) |
|
{ |
|
pev->solid = SOLID_NOT; |
|
pev->movetype = MOVETYPE_NONE; |
|
pev->effects = EF_NODRAW; |
|
} |
|
|
|
void CRuleEntity::KeyValue( KeyValueData *pkvd ) |
|
{ |
|
if( FStrEq(pkvd->szKeyName, "master" ) ) |
|
{ |
|
SetMaster( ALLOC_STRING( pkvd->szValue ) ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else |
|
CBaseEntity::KeyValue( pkvd ); |
|
} |
|
|
|
BOOL CRuleEntity::CanFireForActivator( CBaseEntity *pActivator ) |
|
{ |
|
if (!pActivator) |
|
{ |
|
return TRUE; |
|
} |
|
else if ( m_iszMaster ) |
|
{ |
|
if( UTIL_IsMasterTriggered( m_iszMaster, pActivator ) ) |
|
return TRUE; |
|
else |
|
return FALSE; |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
// |
|
// CRulePointEntity -- base class for all rule "point" entities (not brushes) |
|
// |
|
class CRulePointEntity : public CRuleEntity |
|
{ |
|
public: |
|
void Spawn( void ); |
|
}; |
|
|
|
void CRulePointEntity::Spawn( void ) |
|
{ |
|
CRuleEntity::Spawn(); |
|
pev->frame = 0; |
|
pev->model = 0; |
|
} |
|
|
|
// |
|
// CRuleBrushEntity -- base class for all rule "brush" entities (not brushes) |
|
// Default behavior is to set up like a trigger, invisible, but keep the model for volume testing |
|
// |
|
class CRuleBrushEntity : public CRuleEntity |
|
{ |
|
public: |
|
void Spawn( void ); |
|
|
|
private: |
|
}; |
|
|
|
void CRuleBrushEntity::Spawn( void ) |
|
{ |
|
SET_MODEL( edict(), STRING(pev->model) ); |
|
CRuleEntity::Spawn(); |
|
} |
|
|
|
// CGameScore / game_score -- award points to player / team |
|
// Points +/- total |
|
// Flag: Allow negative scores SF_SCORE_NEGATIVE |
|
// Flag: Award points to team in teamplay SF_SCORE_TEAM |
|
|
|
#define SF_SCORE_NEGATIVE 0x0001 |
|
#define SF_SCORE_TEAM 0x0002 |
|
|
|
class CGameScore : public CRulePointEntity |
|
{ |
|
public: |
|
void Spawn( void ); |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
void KeyValue( KeyValueData *pkvd ); |
|
|
|
inline int Points( void ) { return (int)pev->frags; } |
|
inline BOOL AllowNegativeScore( void ) { return pev->spawnflags & SF_SCORE_NEGATIVE; } |
|
inline BOOL AwardToTeam( void ) { return pev->spawnflags & SF_SCORE_TEAM; } |
|
|
|
inline void SetPoints( int points ) { pev->frags = points; } |
|
|
|
private: |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_score, CGameScore ) |
|
|
|
void CGameScore::Spawn( void ) |
|
{ |
|
CRulePointEntity::Spawn(); |
|
} |
|
|
|
void CGameScore::KeyValue( KeyValueData *pkvd ) |
|
{ |
|
if( FStrEq( pkvd->szKeyName, "points" ) ) |
|
{ |
|
SetPoints( atoi( pkvd->szValue ) ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else |
|
CRulePointEntity::KeyValue( pkvd ); |
|
} |
|
|
|
void CGameScore::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
if( !CanFireForActivator( pActivator ) ) |
|
return; |
|
|
|
// Only players can use this |
|
if( pActivator->IsPlayer() ) |
|
{ |
|
if( AwardToTeam() ) |
|
{ |
|
pActivator->AddPointsToTeam( Points(), AllowNegativeScore() ); |
|
} |
|
else |
|
{ |
|
pActivator->AddPoints( Points(), AllowNegativeScore() ); |
|
} |
|
} |
|
} |
|
|
|
// CGameEnd / game_end -- Ends the game in MP |
|
|
|
class CGameEnd : public CRulePointEntity |
|
{ |
|
public: |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
private: |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_end, CGameEnd ) |
|
|
|
void CGameEnd::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
if( !CanFireForActivator( pActivator ) ) |
|
return; |
|
|
|
g_pGameRules->EndMultiplayerGame(); |
|
} |
|
|
|
// |
|
// CGameText / game_text -- NON-Localized HUD Message (use env_message to display a titles.txt message) |
|
// Flag: All players SF_ENVTEXT_ALLPLAYERS |
|
// |
|
|
|
#define SF_ENVTEXT_ALLPLAYERS 0x0001 |
|
#define SF_ENVTEXT_ONLY_ONCE 0x0002 |
|
|
|
|
|
class CGameText : public CRulePointEntity |
|
{ |
|
public: |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
void KeyValue( KeyValueData *pkvd ); |
|
|
|
virtual int Save( CSave &save ); |
|
virtual int Restore( CRestore &restore ); |
|
static TYPEDESCRIPTION m_SaveData[]; |
|
|
|
inline BOOL MessageToAll( void ) { return (pev->spawnflags & SF_ENVTEXT_ALLPLAYERS); } |
|
inline void MessageSet( const char *pMessage ) { pev->message = ALLOC_STRING(pMessage); } |
|
inline const char *MessageGet( void ) { return STRING(pev->message); } |
|
|
|
void EXPORT TriggerThink( void ); |
|
|
|
private: |
|
|
|
hudtextparms_t m_textParms; |
|
CBaseEntity *m_pActivator; |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_text, CGameText ) |
|
|
|
// Save parms as a block. Will break save/restore if the structure changes, but this entity didn't ship with Half-Life, so |
|
// it can't impact saved Half-Life games. |
|
TYPEDESCRIPTION CGameText::m_SaveData[] = |
|
{ |
|
DEFINE_ARRAY( CGameText, m_textParms, FIELD_CHARACTER, sizeof(hudtextparms_t) ), |
|
DEFINE_FIELD( CGameText, m_pActivator, FIELD_CLASSPTR ), |
|
}; |
|
|
|
IMPLEMENT_SAVERESTORE( CGameText, CRulePointEntity ) |
|
|
|
void CGameText::KeyValue( KeyValueData *pkvd ) |
|
{ |
|
if( FStrEq( pkvd->szKeyName, "channel" ) ) |
|
{ |
|
m_textParms.channel = atoi( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "x" ) ) |
|
{ |
|
m_textParms.x = atof( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq(pkvd->szKeyName, "y" ) ) |
|
{ |
|
m_textParms.y = atof( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "effect" ) ) |
|
{ |
|
m_textParms.effect = atoi( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "color" ) ) |
|
{ |
|
int color[4]; |
|
UTIL_StringToIntArray( color, 4, pkvd->szValue ); |
|
m_textParms.r1 = color[0]; |
|
m_textParms.g1 = color[1]; |
|
m_textParms.b1 = color[2]; |
|
m_textParms.a1 = color[3]; |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "color2" ) ) |
|
{ |
|
int color[4]; |
|
UTIL_StringToIntArray( color, 4, pkvd->szValue ); |
|
m_textParms.r2 = color[0]; |
|
m_textParms.g2 = color[1]; |
|
m_textParms.b2 = color[2]; |
|
m_textParms.a2 = color[3]; |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "fadein" ) ) |
|
{ |
|
m_textParms.fadeinTime = atof( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "fadeout" ) ) |
|
{ |
|
m_textParms.fadeoutTime = atof( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "holdtime" ) ) |
|
{ |
|
m_textParms.holdTime = atof( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq(pkvd->szKeyName, "fxtime" ) ) |
|
{ |
|
m_textParms.fxTime = atof( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else |
|
CRulePointEntity::KeyValue( pkvd ); |
|
} |
|
|
|
void CGameText::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
if( !CanFireForActivator( pActivator ) ) |
|
return; |
|
|
|
if( MessageToAll() ) |
|
{ |
|
UTIL_HudMessageAll( m_textParms, MessageGet() ); |
|
} |
|
else |
|
{ |
|
if ( pActivator && pActivator->IsNetClient() ) |
|
{ |
|
UTIL_HudMessage( pActivator, m_textParms, MessageGet() ); |
|
} |
|
} |
|
|
|
if ( pev->target ) |
|
{ |
|
m_pActivator = pActivator; |
|
SetThink(&CGameText:: TriggerThink ); |
|
SetNextThink( m_textParms.fadeinTime + m_textParms.holdTime + m_textParms.fadeoutTime ); |
|
// ALERT(at_console, "GameText sets NextThink = %f\n", m_textParms.fadeinTime + m_textParms.holdTime + m_textParms.fadeoutTime); |
|
} |
|
else if ( pev->spawnflags & SF_ENVTEXT_ONLY_ONCE ) |
|
{ |
|
SetThink(&CGameText:: SUB_Remove ); |
|
SetNextThink( 0.1 ); |
|
} |
|
} |
|
|
|
//LRC |
|
void CGameText::TriggerThink( void ) |
|
{ |
|
// ALERT(at_console, "GameText uses targets\n"); |
|
SUB_UseTargets( m_pActivator, USE_TOGGLE, 0 ); |
|
|
|
if ( pev->spawnflags & SF_ENVTEXT_ONLY_ONCE ) |
|
{ |
|
SetThink(&CGameText:: SUB_Remove ); |
|
SetNextThink( 0.1 ); |
|
} |
|
} |
|
|
|
// |
|
// CGameTeamMaster / game_team_master -- "Masters" like multisource, but based on the team of the activator |
|
// Only allows mastered entity to fire if the team matches my team |
|
// |
|
// team index (pulled from server team list "mp_teamlist" |
|
// Flag: Remove on Fire |
|
// Flag: Any team until set? -- Any team can use this until the team is set (otherwise no teams can use it) |
|
// |
|
|
|
#define SF_TEAMMASTER_FIREONCE 0x0001 |
|
#define SF_TEAMMASTER_ANYTEAM 0x0002 |
|
|
|
class CGameTeamMaster : public CRulePointEntity |
|
{ |
|
public: |
|
void KeyValue( KeyValueData *pkvd ); |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
// int ObjectCaps( void ) { return CRulePointEntity:: ObjectCaps() | FCAP_MASTER; } |
|
|
|
BOOL IsTriggered( CBaseEntity *pActivator ); |
|
const char *TeamID( void ); |
|
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_TEAMMASTER_FIREONCE) ? TRUE : FALSE; } |
|
inline BOOL AnyTeam( void ) { return (pev->spawnflags & SF_TEAMMASTER_ANYTEAM) ? TRUE : FALSE; } |
|
|
|
private: |
|
BOOL TeamMatch( CBaseEntity *pActivator ); |
|
|
|
int m_teamIndex; |
|
USE_TYPE triggerType; |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_team_master, CGameTeamMaster ) |
|
|
|
void CGameTeamMaster::KeyValue( KeyValueData *pkvd ) |
|
{ |
|
if( FStrEq( pkvd->szKeyName, "teamindex" ) ) |
|
{ |
|
m_teamIndex = atoi( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "triggerstate" ) ) |
|
{ |
|
int type = atoi( pkvd->szValue ); |
|
switch( type ) |
|
{ |
|
case 0: |
|
triggerType = USE_OFF; |
|
break; |
|
case 2: |
|
triggerType = USE_TOGGLE; |
|
break; |
|
default: |
|
triggerType = USE_ON; |
|
break; |
|
} |
|
pkvd->fHandled = TRUE; |
|
} |
|
else |
|
CRulePointEntity::KeyValue( pkvd ); |
|
} |
|
|
|
void CGameTeamMaster::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
if( !CanFireForActivator( pActivator ) ) |
|
return; |
|
|
|
if( useType == USE_SET ) |
|
{ |
|
if( value < 0 ) |
|
{ |
|
m_teamIndex = -1; |
|
} |
|
else |
|
{ |
|
m_teamIndex = g_pGameRules->GetTeamIndex( pActivator->TeamID() ); |
|
} |
|
return; |
|
} |
|
|
|
if( TeamMatch( pActivator ) ) |
|
{ |
|
SUB_UseTargets( pActivator, triggerType, value ); |
|
if( RemoveOnFire() ) |
|
UTIL_Remove( this ); |
|
} |
|
} |
|
|
|
BOOL CGameTeamMaster::IsTriggered( CBaseEntity *pActivator ) |
|
{ |
|
return TeamMatch( pActivator ); |
|
} |
|
|
|
const char *CGameTeamMaster::TeamID( void ) |
|
{ |
|
if( m_teamIndex < 0 ) // Currently set to "no team" |
|
return ""; |
|
|
|
return g_pGameRules->GetIndexedTeamName( m_teamIndex ); // UNDONE: Fill this in with the team from the "teamlist" |
|
} |
|
|
|
BOOL CGameTeamMaster::TeamMatch( CBaseEntity *pActivator ) |
|
{ |
|
if( m_teamIndex < 0 && AnyTeam() ) |
|
return TRUE; |
|
|
|
if( !pActivator ) |
|
return FALSE; |
|
|
|
return UTIL_TeamsMatch( pActivator->TeamID(), TeamID() ); |
|
} |
|
|
|
// |
|
// CGameTeamSet / game_team_set -- Changes the team of the entity it targets to the activator's team |
|
// Flag: Fire once |
|
// Flag: Clear team -- Sets the team to "NONE" instead of activator |
|
|
|
#define SF_TEAMSET_FIREONCE 0x0001 |
|
#define SF_TEAMSET_CLEARTEAM 0x0002 |
|
|
|
class CGameTeamSet : public CRulePointEntity |
|
{ |
|
public: |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_TEAMSET_FIREONCE) ? TRUE : FALSE; } |
|
inline BOOL ShouldClearTeam( void ) { return (pev->spawnflags & SF_TEAMSET_CLEARTEAM) ? TRUE : FALSE; } |
|
|
|
private: |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_team_set, CGameTeamSet ) |
|
|
|
void CGameTeamSet::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
if( !CanFireForActivator( pActivator ) ) |
|
return; |
|
|
|
if( ShouldClearTeam() ) |
|
{ |
|
SUB_UseTargets( pActivator, USE_SET, -1 ); |
|
} |
|
else |
|
{ |
|
SUB_UseTargets( pActivator, USE_SET, 0 ); |
|
} |
|
|
|
if( RemoveOnFire() ) |
|
{ |
|
UTIL_Remove( this ); |
|
} |
|
} |
|
|
|
// |
|
// CGamePlayerZone / game_player_zone -- players in the zone fire my target when I'm fired |
|
// |
|
// Needs master? |
|
class CGamePlayerZone : public CRuleBrushEntity |
|
{ |
|
public: |
|
void KeyValue( KeyValueData *pkvd ); |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
|
|
virtual int Save( CSave &save ); |
|
virtual int Restore( CRestore &restore ); |
|
static TYPEDESCRIPTION m_SaveData[]; |
|
|
|
private: |
|
string_t m_iszInTarget; |
|
string_t m_iszOutTarget; |
|
string_t m_iszInCount; |
|
string_t m_iszOutCount; |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_zone_player, CGamePlayerZone ) |
|
TYPEDESCRIPTION CGamePlayerZone::m_SaveData[] = |
|
{ |
|
DEFINE_FIELD( CGamePlayerZone, m_iszInTarget, FIELD_STRING ), |
|
DEFINE_FIELD( CGamePlayerZone, m_iszOutTarget, FIELD_STRING ), |
|
DEFINE_FIELD( CGamePlayerZone, m_iszInCount, FIELD_STRING ), |
|
DEFINE_FIELD( CGamePlayerZone, m_iszOutCount, FIELD_STRING ), |
|
}; |
|
|
|
IMPLEMENT_SAVERESTORE( CGamePlayerZone, CRuleBrushEntity ) |
|
|
|
void CGamePlayerZone::KeyValue( KeyValueData *pkvd ) |
|
{ |
|
if( FStrEq(pkvd->szKeyName, "intarget" ) ) |
|
{ |
|
m_iszInTarget = ALLOC_STRING( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "outtarget" ) ) |
|
{ |
|
m_iszOutTarget = ALLOC_STRING( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "incount" ) ) |
|
{ |
|
m_iszInCount = ALLOC_STRING( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else if( FStrEq( pkvd->szKeyName, "outcount" ) ) |
|
{ |
|
m_iszOutCount = ALLOC_STRING( pkvd->szValue ); |
|
pkvd->fHandled = TRUE; |
|
} |
|
else |
|
CRuleBrushEntity::KeyValue( pkvd ); |
|
} |
|
|
|
void CGamePlayerZone::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
int playersInCount = 0; |
|
int playersOutCount = 0; |
|
|
|
if( !CanFireForActivator( pActivator ) ) |
|
return; |
|
|
|
CBaseEntity *pPlayer = NULL; |
|
|
|
for( int i = 1; i <= gpGlobals->maxClients; i++ ) |
|
{ |
|
pPlayer = UTIL_PlayerByIndex( i ); |
|
if ( pPlayer ) |
|
{ |
|
TraceResult trace; |
|
int hullNumber; |
|
BOOL inside = FALSE; |
|
|
|
if (pev->origin == g_vecZero) //LRC - to support movewith |
|
{ |
|
hullNumber = human_hull; |
|
if( pPlayer->pev->flags & FL_DUCKING ) |
|
{ |
|
hullNumber = head_hull; |
|
} |
|
|
|
UTIL_TraceModel( pPlayer->pev->origin, pPlayer->pev->origin, hullNumber, edict(), &trace ); |
|
inside = trace.fStartSolid; |
|
} |
|
else |
|
{ |
|
//LIMITATION: this doesn't allow for non-cuboid game_zone_player entities. |
|
// (is that a problem?) |
|
inside = this->Intersects(pPlayer); |
|
} |
|
|
|
if ( inside ) |
|
{ |
|
playersInCount++; |
|
if( m_iszInTarget ) |
|
{ |
|
FireTargets( STRING( m_iszInTarget ), pPlayer, pActivator, useType, value ); |
|
} |
|
} |
|
else |
|
{ |
|
playersOutCount++; |
|
if( m_iszOutTarget ) |
|
{ |
|
FireTargets( STRING( m_iszOutTarget ), pPlayer, pActivator, useType, value ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
if( m_iszInCount ) |
|
{ |
|
FireTargets( STRING( m_iszInCount ), pActivator, this, USE_SET, playersInCount ); |
|
} |
|
|
|
if( m_iszOutCount ) |
|
{ |
|
FireTargets( STRING( m_iszOutCount ), pActivator, this, USE_SET, playersOutCount ); |
|
} |
|
} |
|
|
|
// |
|
// CGamePlayerHurt / game_player_hurt -- Damages the player who fires it |
|
// Flag: Fire once |
|
|
|
#define SF_PKILL_FIREONCE 0x0001 |
|
|
|
class CGamePlayerHurt : public CRulePointEntity |
|
{ |
|
public: |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_PKILL_FIREONCE) ? TRUE : FALSE; } |
|
|
|
private: |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_player_hurt, CGamePlayerHurt ) |
|
|
|
void CGamePlayerHurt::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
if( !CanFireForActivator( pActivator ) ) |
|
return; |
|
|
|
if( pActivator->IsPlayer() ) |
|
{ |
|
if( pev->dmg < 0 ) |
|
pActivator->TakeHealth( -pev->dmg, DMG_GENERIC ); |
|
else |
|
pActivator->TakeDamage( pev, pev, pev->dmg, DMG_GENERIC ); |
|
} |
|
|
|
SUB_UseTargets( pActivator, useType, value ); |
|
|
|
if( RemoveOnFire() ) |
|
{ |
|
UTIL_Remove( this ); |
|
} |
|
} |
|
|
|
// |
|
// CGameCounter / game_counter -- Counts events and fires target |
|
// Flag: Fire once |
|
// Flag: Reset on Fire |
|
|
|
#define SF_GAMECOUNT_FIREONCE 0x0001 |
|
#define SF_GAMECOUNT_RESET 0x0002 |
|
|
|
class CGameCounter : public CRulePointEntity |
|
{ |
|
public: |
|
void Spawn( void ); |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_GAMECOUNT_FIREONCE) ? TRUE : FALSE; } |
|
inline BOOL ResetOnFire( void ) { return (pev->spawnflags & SF_GAMECOUNT_RESET) ? TRUE : FALSE; } |
|
|
|
inline void CountUp( void ) { pev->frags++; } |
|
inline void CountDown( void ) { pev->frags--; } |
|
inline void ResetCount( void ) { pev->frags = pev->dmg; } |
|
inline int CountValue( void ) { return (int)pev->frags; } |
|
inline int LimitValue( void ) { return (int)pev->health; } |
|
|
|
inline BOOL HitLimit( void ) { return CountValue() == LimitValue(); } |
|
|
|
private: |
|
|
|
inline void SetCountValue( int value ) { pev->frags = value; } |
|
inline void SetInitialValue( int value ) { pev->dmg = value; } |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_counter, CGameCounter ) |
|
|
|
void CGameCounter::Spawn( void ) |
|
{ |
|
// Save off the initial count |
|
SetInitialValue( CountValue() ); |
|
CRulePointEntity::Spawn(); |
|
} |
|
|
|
void CGameCounter::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
if( !CanFireForActivator( pActivator ) ) |
|
return; |
|
|
|
switch( useType ) |
|
{ |
|
case USE_ON: |
|
case USE_TOGGLE: |
|
CountUp(); |
|
break; |
|
case USE_OFF: |
|
CountDown(); |
|
break; |
|
case USE_SET: |
|
SetCountValue( (int)value ); |
|
break; |
|
case USE_KILL: |
|
case USE_SAME: |
|
case USE_NOT: |
|
break; |
|
default: |
|
break; |
|
} |
|
|
|
if( HitLimit() ) |
|
{ |
|
SUB_UseTargets( pActivator, USE_TOGGLE, 0 ); |
|
if( RemoveOnFire() ) |
|
{ |
|
UTIL_Remove( this ); |
|
} |
|
|
|
if( ResetOnFire() ) |
|
{ |
|
ResetCount(); |
|
} |
|
} |
|
} |
|
|
|
// |
|
// CGameCounterSet / game_counter_set -- Sets the counter's value |
|
// Flag: Fire once |
|
|
|
#define SF_GAMECOUNTSET_FIREONCE 0x0001 |
|
|
|
class CGameCounterSet : public CRulePointEntity |
|
{ |
|
public: |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_GAMECOUNTSET_FIREONCE) ? TRUE : FALSE; } |
|
|
|
private: |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_counter_set, CGameCounterSet ) |
|
|
|
void CGameCounterSet::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
if( !CanFireForActivator( pActivator ) ) |
|
return; |
|
|
|
SUB_UseTargets( pActivator, USE_SET, pev->frags ); |
|
|
|
if( RemoveOnFire() ) |
|
{ |
|
UTIL_Remove( this ); |
|
} |
|
} |
|
|
|
// |
|
// CGamePlayerEquip / game_playerequip -- Sets the default player equipment |
|
// Flag: USE Only |
|
|
|
#define SF_PLAYEREQUIP_USEONLY 0x0001 |
|
#define MAX_EQUIP 32 |
|
|
|
class CGamePlayerEquip : public CRulePointEntity |
|
{ |
|
public: |
|
void KeyValue( KeyValueData *pkvd ); |
|
void Touch( CBaseEntity *pOther ); |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
|
|
inline BOOL UseOnly( void ) { return (pev->spawnflags & SF_PLAYEREQUIP_USEONLY) ? TRUE : FALSE; } |
|
|
|
private: |
|
void EquipPlayer( CBaseEntity *pPlayer ); |
|
|
|
string_t m_weaponNames[MAX_EQUIP]; |
|
int m_weaponCount[MAX_EQUIP]; |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_player_equip, CGamePlayerEquip ) |
|
|
|
void CGamePlayerEquip::KeyValue( KeyValueData *pkvd ) |
|
{ |
|
CRulePointEntity::KeyValue( pkvd ); |
|
|
|
if( !pkvd->fHandled ) |
|
{ |
|
for( int i = 0; i < MAX_EQUIP; i++ ) |
|
{ |
|
if( !m_weaponNames[i] ) |
|
{ |
|
char tmp[128]; |
|
|
|
UTIL_StripToken( pkvd->szKeyName, tmp ); |
|
|
|
m_weaponNames[i] = ALLOC_STRING( tmp ); |
|
m_weaponCount[i] = atoi( pkvd->szValue ); |
|
m_weaponCount[i] = Q_max( 1, m_weaponCount[i] ); |
|
pkvd->fHandled = TRUE; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CGamePlayerEquip::Touch( CBaseEntity *pOther ) |
|
{ |
|
if( !CanFireForActivator( pOther ) ) |
|
return; |
|
|
|
if( UseOnly() ) |
|
return; |
|
|
|
EquipPlayer( pOther ); |
|
} |
|
|
|
void CGamePlayerEquip::EquipPlayer( CBaseEntity *pEntity ) |
|
{ |
|
CBasePlayer *pPlayer = NULL; |
|
|
|
if( pEntity->IsPlayer() ) |
|
{ |
|
pPlayer = (CBasePlayer *)pEntity; |
|
} |
|
|
|
if( !pPlayer ) |
|
return; |
|
|
|
for( int i = 0; i < MAX_EQUIP; i++ ) |
|
{ |
|
if( !m_weaponNames[i] ) |
|
break; |
|
for( int j = 0; j < m_weaponCount[i]; j++ ) |
|
{ |
|
pPlayer->GiveNamedItem( STRING( m_weaponNames[i] ) ); |
|
} |
|
} |
|
} |
|
|
|
void CGamePlayerEquip::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
EquipPlayer( pActivator ); |
|
} |
|
|
|
// |
|
// CGamePlayerTeam / game_player_team -- Changes the team of the player who fired it |
|
// Flag: Fire once |
|
// Flag: Kill Player |
|
// Flag: Gib Player |
|
|
|
#define SF_PTEAM_FIREONCE 0x0001 |
|
#define SF_PTEAM_KILL 0x0002 |
|
#define SF_PTEAM_GIB 0x0004 |
|
|
|
class CGamePlayerTeam : public CRulePointEntity |
|
{ |
|
public: |
|
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
|
|
private: |
|
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_PTEAM_FIREONCE) ? TRUE : FALSE; } |
|
inline BOOL ShouldKillPlayer( void ) { return (pev->spawnflags & SF_PTEAM_KILL) ? TRUE : FALSE; } |
|
inline BOOL ShouldGibPlayer( void ) { return (pev->spawnflags & SF_PTEAM_GIB) ? TRUE : FALSE; } |
|
|
|
const char *TargetTeamName( const char *pszTargetName ); |
|
}; |
|
|
|
LINK_ENTITY_TO_CLASS( game_player_team, CGamePlayerTeam ) |
|
|
|
const char *CGamePlayerTeam::TargetTeamName( const char *pszTargetName ) |
|
{ |
|
CBaseEntity *pTeamEntity = NULL; |
|
|
|
while( ( pTeamEntity = UTIL_FindEntityByTargetname( pTeamEntity, pszTargetName ) ) != NULL ) |
|
{ |
|
if( FClassnameIs( pTeamEntity->pev, "game_team_master" ) ) |
|
return pTeamEntity->TeamID(); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
void CGamePlayerTeam::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) |
|
{ |
|
if( !CanFireForActivator( pActivator ) ) |
|
return; |
|
|
|
if( pActivator->IsPlayer() ) |
|
{ |
|
const char *pszTargetTeam = TargetTeamName( STRING(pev->target) ); |
|
if ( pszTargetTeam ) |
|
{ |
|
CBasePlayer *pPlayer = (CBasePlayer *)pActivator; |
|
g_pGameRules->ChangePlayerTeam( pPlayer, pszTargetTeam, ShouldKillPlayer(), ShouldGibPlayer() ); |
|
} |
|
} |
|
|
|
if( RemoveOnFire() ) |
|
{ |
|
UTIL_Remove( this ); |
|
} |
|
}
|
|
|