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.
168 lines
4.3 KiB
168 lines
4.3 KiB
2 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "c_ai_basenpc.h"
|
||
|
#include "beam_shared.h"
|
||
|
#include "prop_portal_shared.h"
|
||
|
|
||
|
|
||
|
#define FLOOR_TURRET_PORTAL_EYE_ATTACHMENT 1
|
||
|
#define FLOOR_TURRET_PORTAL_LASER_ATTACHMENT 2
|
||
|
#define FLOOR_TURRET_PORTAL_LASER_RANGE 8192
|
||
|
|
||
|
#define FLOOR_TURRET_PORTAL_END_POINT_PULSE_SCALE 4.0f
|
||
|
|
||
|
|
||
|
class C_NPC_Portal_FloorTurret : public C_AI_BaseNPC
|
||
|
{
|
||
|
public:
|
||
|
DECLARE_CLASS( C_NPC_Portal_FloorTurret, C_AI_BaseNPC );
|
||
|
DECLARE_CLIENTCLASS();
|
||
|
|
||
|
virtual ~C_NPC_Portal_FloorTurret( void );
|
||
|
|
||
|
virtual void Spawn( void );
|
||
|
virtual void ClientThink( void );
|
||
|
|
||
|
bool IsLaserOn( void ) { return m_pBeam != NULL; }
|
||
|
void LaserOff( void );
|
||
|
void LaserOn( void );
|
||
|
float LaserEndPointSize( void );
|
||
|
|
||
|
private:
|
||
|
CBeam *m_pBeam;
|
||
|
|
||
|
bool m_bOutOfAmmo;
|
||
|
bool m_bLaserOn;
|
||
|
int m_sLaserHaloSprite;
|
||
|
float m_fPulseOffset;
|
||
|
|
||
|
float m_bBeamFlickerOff;
|
||
|
float m_fBeamFlickerTime;
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
IMPLEMENT_CLIENTCLASS_DT( C_NPC_Portal_FloorTurret, DT_NPC_Portal_FloorTurret, CNPC_Portal_FloorTurret )
|
||
|
|
||
|
RecvPropBool( RECVINFO( m_bOutOfAmmo ) ),
|
||
|
RecvPropBool( RECVINFO( m_bLaserOn ) ),
|
||
|
RecvPropInt( RECVINFO( m_sLaserHaloSprite ) ),
|
||
|
|
||
|
END_RECV_TABLE()
|
||
|
|
||
|
|
||
|
C_NPC_Portal_FloorTurret::~C_NPC_Portal_FloorTurret( void )
|
||
|
{
|
||
|
LaserOff();
|
||
|
if( m_pBeam )
|
||
|
m_pBeam->Remove();
|
||
|
}
|
||
|
|
||
|
|
||
|
void C_NPC_Portal_FloorTurret::Spawn( void )
|
||
|
{
|
||
|
SetThink( &C_NPC_Portal_FloorTurret::ClientThink );
|
||
|
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||
|
|
||
|
m_pBeam = NULL;
|
||
|
m_fPulseOffset = RandomFloat( 0.0f, 2.0f * M_PI );
|
||
|
|
||
|
m_bBeamFlickerOff = false;
|
||
|
m_fBeamFlickerTime = 0.0f;
|
||
|
|
||
|
BaseClass::Spawn();
|
||
|
}
|
||
|
|
||
|
void C_NPC_Portal_FloorTurret::ClientThink( void )
|
||
|
{
|
||
|
if ( m_bOutOfAmmo && m_fBeamFlickerTime < gpGlobals->curtime )
|
||
|
{
|
||
|
m_fBeamFlickerTime = gpGlobals->curtime + RandomFloat( 0.05f, 0.3f );
|
||
|
m_bBeamFlickerOff = !m_bBeamFlickerOff;
|
||
|
}
|
||
|
|
||
|
if ( m_bLaserOn && !m_bBeamFlickerOff )
|
||
|
LaserOn();
|
||
|
else
|
||
|
LaserOff();
|
||
|
}
|
||
|
|
||
|
void C_NPC_Portal_FloorTurret::LaserOff( void )
|
||
|
{
|
||
|
if( m_pBeam )
|
||
|
{
|
||
|
m_pBeam->AddEffects( EF_NODRAW );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void C_NPC_Portal_FloorTurret::LaserOn( void )
|
||
|
{
|
||
|
if ( !IsBoneAccessAllowed() )
|
||
|
{
|
||
|
LaserOff();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Vector vecMuzzle;
|
||
|
QAngle angMuzzleDir;
|
||
|
GetAttachment( FLOOR_TURRET_PORTAL_LASER_ATTACHMENT, vecMuzzle, angMuzzleDir );
|
||
|
|
||
|
Vector vecEye;
|
||
|
QAngle angEyeDir;
|
||
|
GetAttachment( FLOOR_TURRET_PORTAL_EYE_ATTACHMENT, vecEye, angEyeDir );
|
||
|
|
||
|
Vector vecMuzzleDir;
|
||
|
AngleVectors( angEyeDir, &vecMuzzleDir );
|
||
|
|
||
|
if (!m_pBeam)
|
||
|
{
|
||
|
m_pBeam = CBeam::BeamCreate( "effects/redlaser1.vmt", 0.2 );
|
||
|
m_pBeam->SetColor( 255, 32, 32 );
|
||
|
m_pBeam->SetBrightness( 255 );
|
||
|
m_pBeam->SetNoise( 0 );
|
||
|
m_pBeam->SetWidth( IsX360() ? ( 1.5f ) : ( 0.75f ) ); // On low end TVs these lasers are very hard to see at a distance
|
||
|
m_pBeam->SetEndWidth( 0 );
|
||
|
m_pBeam->SetScrollRate( 0 );
|
||
|
m_pBeam->SetFadeLength( 0 );
|
||
|
m_pBeam->SetHaloTexture( m_sLaserHaloSprite );
|
||
|
m_pBeam->SetHaloScale( 4.0f );
|
||
|
m_pBeam->SetCollisionGroup( COLLISION_GROUP_NONE );
|
||
|
m_pBeam->PointsInit( vecMuzzle + vecMuzzleDir, vecMuzzle );
|
||
|
m_pBeam->SetBeamFlag( FBEAM_REVERSED );
|
||
|
m_pBeam->SetStartEntity( this );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pBeam->RemoveEffects( EF_NODRAW );
|
||
|
}
|
||
|
|
||
|
// Trace to find an endpoint
|
||
|
Vector vEndPoint;
|
||
|
float fEndFraction;
|
||
|
Ray_t rayPath;
|
||
|
rayPath.Init( vecMuzzle, vecMuzzle + vecMuzzleDir * FLOOR_TURRET_PORTAL_LASER_RANGE );
|
||
|
|
||
|
CTraceFilterSkipClassname traceFilter( this, "prop_energy_ball", COLLISION_GROUP_NONE );
|
||
|
|
||
|
if ( UTIL_Portal_TraceRay_Beam( rayPath, MASK_SHOT, &traceFilter, &fEndFraction ) )
|
||
|
vEndPoint = vecMuzzle + vecMuzzleDir * FLOOR_TURRET_PORTAL_LASER_RANGE; // Trace went through portal and endpoint is unknown
|
||
|
else
|
||
|
vEndPoint = vecMuzzle + vecMuzzleDir * FLOOR_TURRET_PORTAL_LASER_RANGE * fEndFraction; // Trace hit a wall
|
||
|
|
||
|
// The beam is backwards, sort of. The endpoint is the sniper. This is
|
||
|
// so that the beam can be tapered to very thin where it emits from the turret.
|
||
|
m_pBeam->PointsInit( vEndPoint, vecMuzzle );
|
||
|
|
||
|
m_pBeam->SetHaloScale( LaserEndPointSize() );
|
||
|
}
|
||
|
|
||
|
float C_NPC_Portal_FloorTurret::LaserEndPointSize( void )
|
||
|
{
|
||
|
return ( ( MAX( 0.0f, sinf( gpGlobals->curtime * M_PI + m_fPulseOffset ) ) ) * FLOOR_TURRET_PORTAL_END_POINT_PULSE_SCALE + 3.0f ) * ( IsX360() ? ( 3.0f ) : ( 1.5f ) );
|
||
|
}
|