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.
253 lines
5.0 KiB
253 lines
5.0 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Implements a moving target that moves along a path of path_tracks |
|
// and can be shot and killed. When the target it killed it fires an |
|
// OnDeath output. |
|
// |
|
// m_flSpeed is the travel speed |
|
// m_iHealth is current health |
|
// m_iMaxHealth is the amount to reset to each time it starts |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "entityoutput.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
#define FGUNTARGET_START_ON 0x0001 |
|
|
|
|
|
class CGunTarget : public CBaseToggle |
|
{ |
|
DECLARE_CLASS( CGunTarget, CBaseToggle ); |
|
|
|
public: |
|
|
|
virtual void Spawn( void ); |
|
virtual void Activate( void ); |
|
bool CreateVPhysics( void ); |
|
|
|
virtual int BloodColor( void ) { return DONT_BLEED; } |
|
|
|
#if defined( HL2_DLL ) |
|
virtual Class_T Classify( void ) { return CLASS_MILITARY; } |
|
#else |
|
virtual Class_T Classify( void ) { return CLASS_NONE; } |
|
#endif |
|
virtual int OnTakeDamage( const CTakeDamageInfo &info ); |
|
virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ) { return GetAbsOrigin(); } |
|
|
|
// Input handlers |
|
void InputStart( inputdata_t &inputdata ); |
|
void InputStop( inputdata_t &inputdata ); |
|
void InputToggle( inputdata_t &inputdata ); |
|
|
|
DECLARE_DATADESC(); |
|
|
|
protected: |
|
|
|
void Next( void ); |
|
void Start( void ); |
|
void Wait( void ); |
|
void Stop( void ); |
|
|
|
private: |
|
|
|
bool m_on; |
|
EHANDLE m_hTargetEnt; |
|
|
|
// Outputs |
|
COutputEvent m_OnDeath; |
|
}; |
|
|
|
|
|
LINK_ENTITY_TO_CLASS( func_guntarget, CGunTarget ); |
|
|
|
BEGIN_DATADESC( CGunTarget ) |
|
|
|
DEFINE_FIELD( m_on, FIELD_BOOLEAN ), |
|
DEFINE_FIELD( m_hTargetEnt, FIELD_EHANDLE ), |
|
|
|
// Function Pointers |
|
DEFINE_FUNCTION( Next ), |
|
DEFINE_FUNCTION( Start ), |
|
DEFINE_FUNCTION( Wait ), |
|
|
|
// Inputs |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ), |
|
DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), |
|
|
|
// Outputs |
|
DEFINE_OUTPUT(m_OnDeath, "OnDeath"), |
|
|
|
END_DATADESC() |
|
|
|
|
|
|
|
void CGunTarget::Spawn( void ) |
|
{ |
|
SetSolid( SOLID_BSP ); |
|
SetMoveType( MOVETYPE_PUSH ); |
|
|
|
SetModel( STRING( GetModelName() ) ); |
|
|
|
if ( m_flSpeed == 0 ) |
|
m_flSpeed = 100; |
|
|
|
// Don't take damage until "on" |
|
m_takedamage = DAMAGE_NO; |
|
AddFlag( FL_NPC ); |
|
|
|
m_on = false; |
|
m_iMaxHealth = m_iHealth; |
|
|
|
if ( HasSpawnFlags(FGUNTARGET_START_ON) ) |
|
{ |
|
SetMoveDone( &CGunTarget::Start ); |
|
SetMoveDoneTime( 0.3 ); |
|
} |
|
CreateVPhysics(); |
|
} |
|
|
|
|
|
bool CGunTarget::CreateVPhysics( void ) |
|
{ |
|
VPhysicsInitShadow( false, false ); |
|
return true; |
|
} |
|
|
|
void CGunTarget::Activate( void ) |
|
{ |
|
BaseClass::Activate(); |
|
|
|
CBaseEntity *pTarg; |
|
// now find our next target |
|
pTarg = GetNextTarget(); |
|
if ( pTarg ) |
|
{ |
|
m_hTargetEnt = pTarg; |
|
Vector nextPos = pTarg->GetAbsOrigin(); |
|
Teleport( &nextPos, NULL, NULL ); |
|
} |
|
} |
|
|
|
|
|
void CGunTarget::Start( void ) |
|
{ |
|
m_takedamage = DAMAGE_YES; |
|
AddFlag( FL_AIMTARGET ); |
|
m_hTargetEnt = GetNextTarget(); |
|
if ( m_hTargetEnt == NULL ) |
|
return; |
|
m_iHealth = m_iMaxHealth; |
|
Next(); |
|
} |
|
|
|
|
|
void CGunTarget::Next( void ) |
|
{ |
|
SetThink( NULL ); |
|
|
|
m_hTargetEnt = GetNextTarget(); |
|
CBaseEntity *pTarget = m_hTargetEnt; |
|
|
|
if ( !pTarget ) |
|
{ |
|
Stop(); |
|
return; |
|
} |
|
|
|
SetMoveDone( &CGunTarget::Wait ); |
|
LinearMove( pTarget->GetLocalOrigin(), m_flSpeed ); |
|
} |
|
|
|
|
|
void CGunTarget::Wait( void ) |
|
{ |
|
CBaseEntity *pTarget = m_hTargetEnt; |
|
|
|
if ( !pTarget ) |
|
{ |
|
Stop(); |
|
return; |
|
} |
|
|
|
variant_t emptyVariant; |
|
pTarget->AcceptInput( "InPass", this, this, emptyVariant, 0 ); |
|
|
|
m_flWait = pTarget->GetDelay(); |
|
|
|
m_target = pTarget->m_target; |
|
SetMoveDone( &CGunTarget::Next ); |
|
if (m_flWait != 0) |
|
{// -1 wait will wait forever! |
|
SetMoveDoneTime( m_flWait ); |
|
} |
|
else |
|
{ |
|
Next();// do it RIGHT now! |
|
} |
|
} |
|
|
|
|
|
void CGunTarget::Stop( void ) |
|
{ |
|
SetAbsVelocity( vec3_origin ); |
|
SetMoveDoneTime( -1 ); |
|
m_takedamage = DAMAGE_NO; |
|
} |
|
|
|
|
|
int CGunTarget::OnTakeDamage( const CTakeDamageInfo &info ) |
|
{ |
|
if ( m_iHealth > 0 ) |
|
{ |
|
m_iHealth -= info.GetDamage(); |
|
if ( m_iHealth <= 0 ) |
|
{ |
|
m_iHealth = 0; |
|
Stop(); |
|
|
|
m_OnDeath.FireOutput( info.GetInflictor(), this ); |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Input handler that starts the target moving. |
|
//----------------------------------------------------------------------------- |
|
void CGunTarget::InputStart( inputdata_t &inputdata ) |
|
{ |
|
Start(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Input handler that stops the target from moving. |
|
//----------------------------------------------------------------------------- |
|
void CGunTarget::InputStop( inputdata_t &inputdata ) |
|
{ |
|
Stop(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Input handler that toggles the start/stop state of the target. |
|
//----------------------------------------------------------------------------- |
|
void CGunTarget::InputToggle( inputdata_t &inputdata ) |
|
{ |
|
if ( m_on ) |
|
{ |
|
Stop(); |
|
} |
|
else |
|
{ |
|
Start(); |
|
} |
|
}
|
|
|