Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

256 lines
5.0 KiB

5 years ago
//========= Copyright 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; }
#elif defined( HL1_DLL )
virtual Class_T Classify( void ) { return CLASS_MACHINE; }
#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();
}
}