summaryrefslogtreecommitdiff
path: root/game/server/dod/dod_bombtarget.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/dod/dod_bombtarget.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/server/dod/dod_bombtarget.cpp')
-rw-r--r--game/server/dod/dod_bombtarget.cpp767
1 files changed, 767 insertions, 0 deletions
diff --git a/game/server/dod/dod_bombtarget.cpp b/game/server/dod/dod_bombtarget.cpp
new file mode 100644
index 0000000..6956717
--- /dev/null
+++ b/game/server/dod/dod_bombtarget.cpp
@@ -0,0 +1,767 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "dod_player.h"
+#include "dod_gamerules.h"
+#include "dod_shareddefs.h"
+#include "dod_bombtarget.h"
+#include "basecombatweapon.h"
+#include "weapon_dodbasebomb.h"
+#include "dod_team.h"
+#include "dod_shareddefs.h"
+#include "dod_objective_resource.h"
+
+BEGIN_DATADESC(CDODBombTarget)
+
+ DEFINE_KEYFIELD( m_iszCapPointName, FIELD_STRING, "target_control_point" ),
+
+ DEFINE_KEYFIELD( m_iBombingTeam, FIELD_INTEGER, "bombing_team" ),
+
+ DEFINE_KEYFIELD( m_iTimerAddSeconds, FIELD_INTEGER, "add_timer_seconds" ),
+
+ DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
+ DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
+
+ DEFINE_OUTPUT( m_OnBecomeActive, "OnBombTargetActivated" ),
+ DEFINE_OUTPUT( m_OnBecomeInactive, "OnBombTargetDeactivated" ),
+ DEFINE_OUTPUT( m_OnBombPlanted, "OnBombPlanted" ),
+ DEFINE_OUTPUT( m_OnBombExploded, "OnBombExploded" ),
+ DEFINE_OUTPUT( m_OnBombDisarmed, "OnBombDefused" ),
+
+ DEFINE_KEYFIELD( m_bStartDisabled, FIELD_INTEGER, "StartDisabled" ),
+
+ DEFINE_USEFUNC( State_Use ),
+ DEFINE_THINKFUNC( State_Think ),
+
+END_DATADESC();
+
+IMPLEMENT_SERVERCLASS_ST(CDODBombTarget, DT_DODBombTarget)
+ SendPropInt( SENDINFO(m_iState), 3 ),
+ SendPropInt( SENDINFO(m_iBombingTeam), 3 ),
+
+ SendPropModelIndex( SENDINFO(m_iTargetModel) ),
+ SendPropModelIndex( SENDINFO(m_iUnavailableModel) ),
+END_SEND_TABLE()
+
+LINK_ENTITY_TO_CLASS( dod_bomb_target, CDODBombTarget );
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::Spawn( void )
+{
+ m_pControlPoint = NULL;
+
+ Precache();
+
+ SetTouch( NULL );
+ SetUse( &CDODBombTarget::State_Use );
+ SetThink( &CDODBombTarget::State_Think );
+ SetNextThink( gpGlobals->curtime + 0.1 );
+
+ m_pCurStateInfo = NULL;
+ if ( m_bStartDisabled )
+ State_Transition( BOMB_TARGET_INACTIVE );
+ else
+ State_Transition( BOMB_TARGET_ACTIVE );
+
+ BaseClass::Spawn();
+
+ // incase we have any animating bomb models
+ SetPlaybackRate( 1.0 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::Precache( void )
+{
+ BaseClass::Precache();
+
+ PrecacheModel( DOD_BOMB_TARGET_MODEL_ARMED );
+ m_iTargetModel = PrecacheModel( DOD_BOMB_TARGET_MODEL_TARGET );
+ m_iUnavailableModel = PrecacheModel( DOD_BOMB_TARGET_MODEL_UNAVAILABLE );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: change use flags based on state
+//-----------------------------------------------------------------------------
+int CDODBombTarget::ObjectCaps()
+{
+ int caps = BaseClass::ObjectCaps();
+
+ if ( State_Get() != BOMB_TARGET_INACTIVE )
+ {
+ caps |= (FCAP_CONTINUOUS_USE | FCAP_USE_IN_RADIUS);
+ }
+
+ return caps;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: timer length accessor
+//-----------------------------------------------------------------------------
+float CDODBombTarget::GetBombTimerLength( void )
+{
+ return DOD_BOMB_TIMER_LENGTH;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Transition( BombTargetState newState )
+{
+ State_Leave();
+ State_Enter( newState );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Enter( BombTargetState newState )
+{
+ m_pCurStateInfo = State_LookupInfo( newState );
+
+ if ( 0 )
+ {
+ if ( m_pCurStateInfo )
+ Msg( "DODRoundState: entering '%s'\n", m_pCurStateInfo->m_pStateName );
+ else
+ Msg( "DODRoundState: entering #%d\n", newState );
+ }
+
+ // Initialize the new state.
+ if ( m_pCurStateInfo && m_pCurStateInfo->pfnEnterState )
+ (this->*m_pCurStateInfo->pfnEnterState)();
+
+ m_iState = (int)newState;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Leave()
+{
+ if ( m_pCurStateInfo && m_pCurStateInfo->pfnLeaveState )
+ {
+ (this->*m_pCurStateInfo->pfnLeaveState)();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Think()
+{
+ if ( m_pCurStateInfo && m_pCurStateInfo->pfnThink )
+ {
+ (this->*m_pCurStateInfo->pfnThink)();
+ }
+
+ SetNextThink( gpGlobals->curtime + 0.1 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ if ( m_pCurStateInfo && m_pCurStateInfo->pfnUse )
+ {
+ (this->*m_pCurStateInfo->pfnUse)( pActivator, pCaller, useType, value );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CDODBombTargetStateInfo* CDODBombTarget::State_LookupInfo( BombTargetState state )
+{
+ static CDODBombTargetStateInfo bombTargetStateInfos[] =
+ {
+ { BOMB_TARGET_INACTIVE, "BOMB_TARGET_INACTIVE", &CDODBombTarget::State_Enter_INACTIVE, NULL, NULL, NULL },
+ { BOMB_TARGET_ACTIVE, "BOMB_TARGET_ACTIVE", &CDODBombTarget::State_Enter_ACTIVE, NULL, NULL, &CDODBombTarget::State_Use_ACTIVE },
+ { BOMB_TARGET_ARMED, "BOMB_TARGET_ARMED", &CDODBombTarget::State_Enter_ARMED, &CDODBombTarget::State_Leave_Armed, &CDODBombTarget::State_Think_ARMED, &CDODBombTarget::State_Use_ARMED }
+ };
+
+ for ( int i=0; i < ARRAYSIZE( bombTargetStateInfos ); i++ )
+ {
+ if ( bombTargetStateInfos[i].m_iState == state )
+ return &bombTargetStateInfos[i];
+ }
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Enter_INACTIVE( void )
+{
+ // go invisible
+ AddEffects( EF_NODRAW );
+
+ m_OnBecomeInactive.FireOutput( this, this );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Enter_ACTIVE( void )
+{
+ RemoveEffects( EF_NODRAW );
+
+ // set transparent model
+ SetModel( DOD_BOMB_TARGET_MODEL_TARGET );
+
+ m_OnBecomeActive.FireOutput( this, this );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Enter_ARMED( void )
+{
+ RemoveEffects( EF_NODRAW );
+
+ // set solid model
+ SetModel( DOD_BOMB_TARGET_MODEL_ARMED );
+
+ // start count down
+ m_flExplodeTime = gpGlobals->curtime + GetBombTimerLength();
+
+ m_OnBombPlanted.FireOutput( this, this );
+
+ // tell CP our time until detonation
+ CControlPoint *pCP = GetControlPoint();
+ if ( pCP )
+ {
+ pCP->BombPlanted( GetBombTimerLength(), m_pPlantingPlayer );
+ }
+
+ EmitSound( "Weapon_C4.Fuse" );
+
+ static int iWickSeq = LookupSequence( "w_tnt_wick" );
+ ResetSequence( iWickSeq );
+}
+
+void CDODBombTarget::State_Leave_Armed( void )
+{
+ StopSound( "Weapon_C4.Fuse" );
+}
+
+void CDODBombTarget::ResetDefuse( int index )
+{
+ DefusingPlayer *pRec = &m_DefusingPlayers[index];
+
+ Assert( pRec );
+
+ if ( pRec && pRec->m_pPlayer )
+ {
+ pRec->m_pPlayer->SetDefusing( NULL );
+
+ //cancel the progress bar
+ pRec->m_pPlayer->SetProgressBarTime( 0 );
+ }
+
+ m_DefusingPlayers.Remove( index );
+
+ // if noone else is defusing, set objective resource to not be defusing
+ if ( m_DefusingPlayers.Count() <= 0 )
+ {
+ CControlPoint *pCP = GetControlPoint();
+ if ( pCP )
+ {
+ g_pObjectiveResource->SetBombBeingDefused( pCP->GetPointIndex(), false );
+ }
+ }
+}
+
+#include "IEffects.h"
+void TE_Sparks( IRecipientFilter& filter, float delay,
+ const Vector *pos, int nMagnitude, int nTrailLength, const Vector *pDir );
+
+extern short g_sModelIndexFireball;
+
+void CDODBombTarget::Explode( void )
+{
+ // output the explosion
+ EmitSound( "Weapon_C4.Explode" );
+
+ Vector origin = GetAbsOrigin();
+
+ CPASFilter filter( origin );
+
+ te->Explosion( filter, -1.0, // don't apply cl_interp delay
+ &origin,
+ g_sModelIndexFireball,
+ 20, //scale
+ 25,
+ TE_EXPLFLAG_NONE,
+ 0,
+ 0 );
+
+ float flDamage = 200;
+ float flDmgRadius = flDamage * 2.5;
+ // do a separate radius damage that ignores the world for added damage!
+ CTakeDamageInfo dmgInfo( this, m_pPlantingPlayer, vec3_origin, origin, flDamage, DMG_BLAST | DMG_BOMB );
+ DODGameRules()->RadiusDamage( dmgInfo, origin, flDmgRadius, CLASS_NONE, NULL, true );
+
+ // stun players in a radius
+ const float flStunDamage = 100;
+
+ CTakeDamageInfo stunInfo( this, this, vec3_origin, GetAbsOrigin(), flStunDamage, DMG_STUN );
+ DODGameRules()->RadiusStun( stunInfo, GetAbsOrigin(), flDmgRadius );
+
+ State_Transition( BOMB_TARGET_INACTIVE );
+
+ m_OnBombExploded.FireOutput( this, this );
+
+ // tell CP bomb is no longer active
+ CControlPoint *pCP = GetControlPoint();
+ if ( pCP )
+ {
+ CDODPlayer *pPlayer = m_pPlantingPlayer;
+
+ if ( !pPlayer || !pPlayer->IsConnected() )
+ {
+ // pick a random player from the bombing team
+
+ // hax - if we are debug and team is 0, use allies
+ if ( m_iBombingTeam == TEAM_UNASSIGNED )
+ m_iBombingTeam = TEAM_ALLIES;
+
+ CDODTeam *pTeam = GetGlobalDODTeam( m_iBombingTeam );
+
+ pPlayer = NULL;
+
+ if ( pTeam->GetNumPlayers() > 0 )
+ {
+ pPlayer = ToDODPlayer( pTeam->GetPlayer( 0 ) );
+
+ if ( !pPlayer || !pPlayer->IsConnected() )
+ {
+ // bad situation, abandon here
+ pPlayer = NULL;
+ }
+ }
+ }
+
+ pCP->BombExploded( pPlayer, m_iBombingTeam );
+
+ g_pObjectiveResource->SetBombBeingDefused( pCP->GetPointIndex(), false );
+ }
+
+ // If we add time to the round timer, tell Gamerules
+ // Don't do this if this bomb ended the game
+ if ( m_iTimerAddSeconds > 0 )
+ {
+ if ( m_pPlantingPlayer && FStrEq( STRING(gpGlobals->mapname), "dod_jagd" ) )
+ {
+ // if the timer is 0:00 or less, achievement time
+ if ( DODGameRules()->GetTimerSeconds() <= 0 )
+ {
+ m_pPlantingPlayer->AwardAchievement( ACHIEVEMENT_DOD_JAGD_OVERTIME_CAP );
+ }
+ }
+
+ if ( DODGameRules()->State_Get() == STATE_RND_RUNNING )
+ {
+ DODGameRules()->AddTimerSeconds( m_iTimerAddSeconds );
+ }
+ }
+}
+
+void CDODBombTarget::BombDefused( CDODPlayer *pDefuser )
+{
+ // tell CP bomb is no longer active
+ CControlPoint *pCP = GetControlPoint();
+ if ( pCP )
+ {
+ pCP->BombDisarmed( pDefuser );
+ }
+
+ if ( pDefuser )
+ {
+ pDefuser->StatEvent_BombDefused();
+ }
+
+ State_Transition( BOMB_TARGET_ACTIVE );
+
+ m_OnBombDisarmed.FireOutput( this, this );
+}
+
+bool CDODBombTarget::CanPlayerStartDefuse( CDODPlayer *pPlayer )
+{
+ if ( !pPlayer || !pPlayer->IsAlive() || !pPlayer->IsConnected() )
+ {
+ // if the defuser is not alive or has disconnected, reset
+ return false;
+ }
+
+ if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
+ {
+ // they are not on the ground, remove them
+ pPlayer->HintMessage( HINT_BOMB_DEFUSE_ONGROUND );
+
+ return false;
+ }
+
+ Vector vecDist = ( pPlayer->GetAbsOrigin() - GetAbsOrigin() );
+ float flDist = vecDist.Length();
+
+ if ( flDist > DOD_BOMB_DEFUSE_MAXDIST ) // PLAYER_USE_RADIUS is not actually used by the playerUse code!!
+ {
+ // they are too far away to continue ( or start ) defusing
+ return false;
+ }
+
+ return true;
+}
+
+bool CDODBombTarget::CanPlayerContinueDefusing( CDODPlayer *pPlayer, DefusingPlayer *pDefuseRecord )
+{
+ if ( !pDefuseRecord || pDefuseRecord->m_flDefuseTimeoutTime < gpGlobals->curtime )
+ {
+ // they have not updated their +use in a while, assume they stopped
+ return false;
+ }
+
+ return CanPlayerStartDefuse( pPlayer );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Think_ARMED( void )
+{
+ // count down
+
+ if ( DODGameRules()->State_Get() != STATE_RND_RUNNING )
+ {
+ State_Transition( BOMB_TARGET_ACTIVE );
+
+ // reset the timer
+ CControlPoint *pCP = GetControlPoint();
+ if ( pCP )
+ {
+ pCP->CancelBombPlanted();
+ }
+ }
+
+ // manually advance frame so that it matches bomb timer length.
+ float flTimerLength = GetBombTimerLength();
+ float flTimeLeft = m_flExplodeTime - gpGlobals->curtime;
+ SetCycle( clamp( 1.0 - ( flTimeLeft / flTimerLength ), 0.0, 1.0 ) );
+
+ static int iAttachment = LookupAttachment( "wick" );//ed awesome
+
+ Vector pos;
+ QAngle ang;
+ GetAttachment( iAttachment, pos, ang );
+
+ Vector forward;
+ AngleVectors( ang, &forward );
+
+ CPVSFilter filter( pos );
+ TE_Sparks( filter, 0.0, &pos, 1, 1, &forward );
+
+ // So long as we have valid defusers, we will not explode
+
+ if ( m_DefusingPlayers.Count() > 0 )
+ {
+ // remove the undesirables
+ // make sure they are on ground still
+ // see if they have completed the defuse
+
+ for ( int i=m_DefusingPlayers.Count()-1;i>=0;i-- )
+ {
+ DefusingPlayer *pDefuseRecord = &m_DefusingPlayers[i];
+
+ CDODPlayer *pPlayer = pDefuseRecord->m_pPlayer;
+
+ if ( !CanPlayerContinueDefusing( pPlayer, pDefuseRecord ) )
+ {
+ ResetDefuse( i );
+ }
+ else
+ {
+ // they are still a valid defuser
+
+ // if their defuse complete time has passed
+ if ( pDefuseRecord->m_flDefuseCompleteTime < gpGlobals->curtime )
+ {
+ // Defuse Complete
+ BombDefused( pPlayer );
+
+ // remove everyone from the list
+ for ( int j=m_DefusingPlayers.Count()-1;j>=0;j-- )
+ {
+ ResetDefuse( j );
+ }
+
+ // break out of this loop
+ i = -1;
+ }
+ }
+ }
+ }
+ else if ( gpGlobals->curtime > m_flExplodeTime )
+ {
+ // no defusers, time is up
+ Explode();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Use_ACTIVE( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ CDODPlayer *pPlayer = ToDODPlayer( pActivator );
+
+ if ( !CanPlantHere( pPlayer ) )
+ return;
+
+ Vector pos = pPlayer->WorldSpaceCenter();
+
+ float flDist = ( pos - GetAbsOrigin() ).Length();
+
+ if ( flDist > DOD_BOMB_PLANT_RADIUS )
+ {
+ return;
+ }
+
+ if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
+ {
+ pPlayer->HintMessage( HINT_BOMB_DEFUSE_ONGROUND, true );
+ return;
+ }
+
+ CBaseCombatWeapon *pWeapon = NULL;
+
+ if ( ( pWeapon = pPlayer->Weapon_OwnsThisType( "weapon_basebomb" ) ) != NULL )
+ {
+ CDODBaseBombWeapon *pBomb = dynamic_cast<CDODBaseBombWeapon *>( pWeapon );
+
+ if ( pBomb )
+ {
+ // switch to their bomb, they will have to hit primary attack
+ pPlayer->Weapon_Switch( pBomb );
+
+ if ( pBomb == pPlayer->GetActiveWeapon() )
+ {
+ pBomb->PrimaryAttack();
+ }
+ }
+ }
+ else
+ {
+ // they don't have a bomb - play hint message
+ pPlayer->HintMessage( HINT_NEED_BOMB );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::CompletePlanting( CDODPlayer *pPlantingPlayer )
+{
+ if ( pPlantingPlayer && ( pPlantingPlayer->GetTeamNumber() == m_iBombingTeam || m_iBombingTeam == TEAM_UNASSIGNED ) )
+ {
+ m_pPlantingPlayer = pPlantingPlayer;
+
+ State_Transition( BOMB_TARGET_ARMED );
+ }
+}
+
+DefusingPlayer *CDODBombTarget::FindDefusingPlayer( CDODPlayer *pPlayer )
+{
+ DefusingPlayer *pRec = NULL;
+
+ for ( int i=0;i<m_DefusingPlayers.Count();i++ )
+ {
+ if ( m_DefusingPlayers[i].m_pPlayer == pPlayer )
+ {
+ pRec = &m_DefusingPlayers[i];
+ break;
+ }
+ }
+
+ return pRec;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::State_Use_ARMED( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ // check for people disarming
+ CDODPlayer *pPlayer = ToDODPlayer( pActivator );
+
+ if ( !pPlayer || pPlayer->GetTeamNumber() == m_iBombingTeam || pPlayer->GetTeamNumber() == TEAM_SPECTATOR )
+ return;
+
+ // check for distance, offground etc
+ if ( CanPlayerStartDefuse( pPlayer ) == false )
+ {
+ return;
+ }
+
+ DefusingPlayer *pDefusingPlayerRecord = FindDefusingPlayer( pPlayer );
+
+ // See if we already added this player to the defusing list
+ if ( pDefusingPlayerRecord )
+ {
+ // They are still defusing for the next 0.2 seconds
+ pDefusingPlayerRecord->m_flDefuseTimeoutTime = gpGlobals->curtime + 0.2;
+ }
+ else
+ {
+ // add player to the list
+ DefusingPlayer defusingPlayer;
+
+ defusingPlayer.m_pPlayer = pPlayer;
+ defusingPlayer.m_flDefuseCompleteTime = gpGlobals->curtime + DOD_BOMB_DEFUSE_TIME;
+ defusingPlayer.m_flDefuseTimeoutTime = gpGlobals->curtime + 0.2;
+
+ m_DefusingPlayers.AddToTail( defusingPlayer );
+
+ // tell the player they are defusing
+ pPlayer->SetDefusing( this );
+ pPlayer->SetProgressBarTime( DOD_BOMB_DEFUSE_TIME );
+
+ CControlPoint *pCP = GetControlPoint();
+ if ( pCP )
+ {
+ g_pObjectiveResource->SetBombBeingDefused( pCP->GetPointIndex(), true );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::InputEnable( inputdata_t &inputdata )
+{
+ if ( m_pCurStateInfo && m_pCurStateInfo->m_iState == BOMB_TARGET_INACTIVE )
+ {
+ State_Transition( BOMB_TARGET_ACTIVE );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::InputDisable( inputdata_t &inputdata )
+{
+ if ( m_pCurStateInfo && m_pCurStateInfo->m_iState != BOMB_TARGET_INACTIVE )
+ {
+ if ( m_pCurStateInfo->m_iState == BOMB_TARGET_ARMED )
+ {
+ // if planting, tell our cp we're not planting anymore
+ CControlPoint *pCP = GetControlPoint();
+ if ( pCP )
+ {
+ pCP->CancelBombPlanted();
+ }
+ }
+
+ State_Transition( BOMB_TARGET_INACTIVE );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CControlPoint *CDODBombTarget::GetControlPoint( void )
+{
+ if ( !m_pControlPoint )
+ {
+ if ( m_iszCapPointName == NULL_STRING )
+ return NULL;
+
+ // try to find it
+ m_pControlPoint = dynamic_cast<CControlPoint *>( gEntList.FindEntityByName( NULL, STRING(m_iszCapPointName) ) );
+
+ if ( !m_pControlPoint )
+ Warning( "Could not find dod_control_point named \"%s\" for dod_bomb_target \"%s\"\n", STRING(m_iszCapPointName), STRING( GetEntityName() ) );
+ }
+
+ return m_pControlPoint;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CDODBombTarget::CanPlantHere( CDODPlayer *pPlayer )
+{
+ if ( !m_pCurStateInfo )
+ return false;
+
+ if ( m_pCurStateInfo->m_iState != BOMB_TARGET_ACTIVE )
+ return false;
+
+ if ( pPlayer->GetTeamNumber() != m_iBombingTeam && m_iBombingTeam != TEAM_UNASSIGNED )
+ return false;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDODBombTarget::DefuseBlocked( CDODPlayer *pAttacker )
+{
+ CControlPoint *pPoint = GetControlPoint();
+
+ if ( !pPoint )
+ return;
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "dod_capture_blocked" );
+
+ if ( event )
+ {
+ event->SetInt( "cp", pPoint->GetPointIndex() );
+ event->SetString( "cpname", pPoint->GetName() );
+ event->SetInt( "blocker", pAttacker->entindex() );
+ event->SetInt( "priority", 9 );
+ event->SetBool( "bomb", true );
+
+ gameeventmanager->FireEvent( event );
+ }
+
+ pAttacker->AddScore( PLAYER_POINTS_FOR_BLOCK );
+
+ pAttacker->Stats_AreaDefended();
+
+}
+
+void CDODBombTarget::PlantBlocked( CDODPlayer *pAttacker )
+{
+ CControlPoint *pPoint = GetControlPoint();
+
+ if ( !pPoint )
+ return;
+
+ IGameEvent *event = gameeventmanager->CreateEvent( "dod_capture_blocked" );
+
+ if ( event )
+ {
+ event->SetInt( "cp", pPoint->GetPointIndex() );
+ event->SetString( "cpname", pPoint->GetName() );
+ event->SetInt( "blocker", pAttacker->entindex() );
+ event->SetInt( "priority", 9 );
+ event->SetBool( "bomb", true );
+
+ gameeventmanager->FireEvent( event );
+ }
+
+ pAttacker->AddScore( PLAYER_POINTS_FOR_BLOCK );
+
+ pAttacker->Stats_AreaDefended();
+}