diff options
Diffstat (limited to 'game/client/portal/c_npc_portal_turret_floor.cpp')
| -rw-r--r-- | game/client/portal/c_npc_portal_turret_floor.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/game/client/portal/c_npc_portal_turret_floor.cpp b/game/client/portal/c_npc_portal_turret_floor.cpp new file mode 100644 index 0000000..73e6081 --- /dev/null +++ b/game/client/portal/c_npc_portal_turret_floor.cpp @@ -0,0 +1,168 @@ +//========= 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 ) ); +}
\ No newline at end of file |