summaryrefslogtreecommitdiff
path: root/game/server/tf2/tf_walker_ministrider.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/tf2/tf_walker_ministrider.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/server/tf2/tf_walker_ministrider.cpp')
-rw-r--r--game/server/tf2/tf_walker_ministrider.cpp515
1 files changed, 515 insertions, 0 deletions
diff --git a/game/server/tf2/tf_walker_ministrider.cpp b/game/server/tf2/tf_walker_ministrider.cpp
new file mode 100644
index 0000000..3bc406a
--- /dev/null
+++ b/game/server/tf2/tf_walker_ministrider.cpp
@@ -0,0 +1,515 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "tf_walker_ministrider.h"
+#include "in_buttons.h"
+#include "studio.h"
+#include "shake.h"
+#include "tf_gamerules.h"
+#include "npcevent.h"
+#include "ndebugoverlay.h"
+#include "te_effect_dispatch.h"
+#include "beam_shared.h"
+#include "ai_activity.h"
+
+#define WALKER_MINI_STRIDER_MODEL "models/objects/alien_vehicle_strider.mdl"
+#define STRIDER_TORSO_VERTICAL_SLIDE_SPEED 100
+
+float LARGE_GUN_FIRE_TIME = 3;
+
+// Skirmisher CVars
+ConVar tf_skirmisher_speed( "tf_skirmisher_speed", "300" );
+ConVar tf_skirmisher_machinegun_range( "tf_skirmisher_machinegun_range", "2000" );
+ConVar tf_skirmisher_machinegun_damage( "tf_skirmisher_machinegun_damage", "20" );
+ConVar tf_skirmisher_machinegun_rof( "tf_skirmisher_machinegun_rof", "10" );
+
+IMPLEMENT_SERVERCLASS_ST( CWalkerMiniStrider, DT_WalkerMiniStrider )
+END_SEND_TABLE()
+
+LINK_ENTITY_TO_CLASS( walker_mini_strider, CWalkerMiniStrider );
+PRECACHE_REGISTER( walker_mini_strider );
+
+
+
+CWalkerMiniStrider::CWalkerMiniStrider()
+{
+ m_flWantedZ = -1;
+ m_bFiringMachineGun = m_bFiringLargeGun = false;
+ m_flOriginToLowestLegHeight = 133;
+ m_State = STATE_NORMAL;
+ m_bFiringLeftGun = true;
+ m_flNextFootstepSoundTime = 0;
+}
+
+
+CWalkerMiniStrider::~CWalkerMiniStrider()
+{
+ UTIL_Remove( m_pEnergyBeam );
+}
+
+
+void CWalkerMiniStrider::Precache()
+{
+ PrecacheModel( WALKER_MINI_STRIDER_MODEL );
+
+ PrecacheScriptSound( "Skirmisher.Footstep" );
+ PrecacheScriptSound( "Skirmisher.GunSound" );
+ PrecacheScriptSound( "Skirmisher.GunChargeSound" );
+
+ BaseClass::Precache();
+}
+
+
+void CWalkerMiniStrider::Spawn()
+{
+ SpawnWalker(
+ WALKER_MINI_STRIDER_MODEL, // Model name.
+ OBJ_WALKER_MINI_STRIDER, // Object type.
+ Vector( 0, 0, 140 ) + Vector( -100, -100, -100 ), // Placement dimensions.
+ Vector( 0, 0, 140 ) + Vector( 100, 100, 100 ),
+ 200, // Health.
+ 1, // Max passengers.
+ 1.0 // 1x speed multiplier
+ );
+
+ SetVelocityDecayRate( 110 );
+}
+
+
+bool CWalkerMiniStrider::IsPassengerVisible( int nRole )
+{
+ if ( nRole == VEHICLE_ROLE_DRIVER )
+ return false;
+
+ return true;
+}
+
+
+void CWalkerMiniStrider::StartFiringMachineGun()
+{
+ StopFiringLargeGun();
+ m_bFiringMachineGun = true;
+ m_flNextShootTime = gpGlobals->curtime;
+}
+
+
+void CWalkerMiniStrider::StopFiringMachineGun()
+{
+ m_bFiringMachineGun = false;
+}
+
+
+Vector CWalkerMiniStrider::GetLargeGunShootOrigin()
+{
+ Vector vRet;
+ QAngle dummyAngle;
+ if ( GetAttachment( LookupAttachment( "LargeGun" ), vRet, dummyAngle ) )
+ {
+ return vRet;
+ }
+ else
+ {
+ return GetAbsOrigin();
+ }
+}
+
+
+void CWalkerMiniStrider::StartFiringLargeGun()
+{
+ CBasePlayer *pPlayer = GetPassenger( VEHICLE_ROLE_DRIVER );
+ Assert( pPlayer );
+ if ( !pPlayer )
+ return;
+
+ // Figure out what we're shooting at.
+ Vector vSrc = GetLargeGunShootOrigin();
+
+ Vector vEyePos = pPlayer->EyePosition();
+ Vector vEyeForward;
+ AngleVectors( pPlayer->LocalEyeAngles(), &vEyeForward );
+
+ trace_t trace;
+ UTIL_TraceLine( vEyePos, vEyePos + vEyeForward * 2000, MASK_SOLID, this, COLLISION_GROUP_NONE, &trace );
+ if ( trace.fraction < 1 )
+ {
+ m_vLargeGunForward = trace.endpos - vSrc;
+ VectorNormalize( m_vLargeGunForward );
+
+ trace_t trace;
+ UTIL_TraceLine( vSrc, vSrc + m_vLargeGunForward * 2000, MASK_SOLID, this, COLLISION_GROUP_NONE, &trace );
+ if ( trace.fraction < 1 )
+ {
+ EnableWalkMode( false );
+
+ m_vLargeGunTargetPos = trace.endpos;
+ m_flLargeGunCountdown = LARGE_GUN_FIRE_TIME;
+ m_bFiringLargeGun = true;
+
+ // Show an energy beam until we actually shoot.
+ m_pEnergyBeam = CBeam::BeamCreate( "sprites/physbeam.vmt", 25 );
+ m_pEnergyBeam->SetColor( 255, 0, 0 );
+ m_pEnergyBeam->SetBrightness( 100 );
+ m_pEnergyBeam->SetNoise( 4 );
+ m_pEnergyBeam->PointsInit( vSrc, m_vLargeGunTargetPos );
+ m_pEnergyBeam->LiveForTime( LARGE_GUN_FIRE_TIME );
+
+ // Play a charge-up sound.
+ CPASAttenuationFilter filter( this, "Skirmisher.GunChargeSound" );
+ EmitSound( filter, 0, "Skirmisher.GunChargeSound", &vSrc );
+ }
+ }
+}
+
+
+void CWalkerMiniStrider::StopFiringLargeGun()
+{
+ if ( m_bFiringLargeGun )
+ {
+ m_bFiringLargeGun = false;
+
+ UTIL_Remove( m_pEnergyBeam );
+ m_pEnergyBeam = NULL;
+
+ EnableWalkMode( true );
+ }
+}
+
+
+void CWalkerMiniStrider::UpdateLargeGun()
+{
+ float dt = GetTimeDelta();
+
+ if ( !m_bFiringLargeGun )
+ return;
+
+ m_flLargeGunCountdown -= dt;
+ if ( m_flLargeGunCountdown <= 0 )
+ {
+ // Fire!
+ Vector vSrc = GetLargeGunShootOrigin();
+ trace_t trace;
+ UTIL_TraceLine( vSrc, vSrc + m_vLargeGunForward * 2000, MASK_SOLID, this, COLLISION_GROUP_NONE, &trace );
+ if ( trace.fraction < 1 )
+ {
+ CBasePlayer *pDriver = GetPassenger( VEHICLE_ROLE_DRIVER );
+ if ( pDriver )
+ {
+ UTIL_ImpactTrace( &trace, DMG_ENERGYBEAM, "Strider" );
+
+ Vector vHitPos = trace.endpos;
+ float flDamageRadius = 100;
+ float flDamage = 100;
+
+ CPASFilter filter( vHitPos );
+ te->Explosion( filter, 0.0,
+ &vHitPos,
+ g_sModelIndexFireball,
+ 2.0,
+ 15,
+ TE_EXPLFLAG_NONE,
+ flDamageRadius,
+ flDamage );
+
+ UTIL_ScreenShake( vHitPos, 10.0, 150.0, 1.0, 100, SHAKE_START );
+ RadiusDamage( CTakeDamageInfo( this, pDriver, flDamage, DMG_BLAST ), vHitPos, flDamageRadius, CLASS_NONE, NULL );
+ }
+ }
+
+ StopFiringLargeGun();
+ }
+}
+
+
+void CWalkerMiniStrider::Crouch()
+{
+ if ( m_State == STATE_CROUCHING || m_State == STATE_CROUCHED )
+ return;
+
+ // Disable the base class's walking functionality while we're crouched.
+ EnableWalkMode( false );
+
+ SetActivity( ACT_CROUCH );
+ m_flCrouchTimer = SequenceDuration();
+ m_State = STATE_CROUCHING;
+}
+
+
+void CWalkerMiniStrider::UnCrouch()
+{
+ if ( m_State == STATE_CROUCHING || m_State == STATE_UNCROUCHING || m_State == STATE_NORMAL )
+ return;
+
+ SetActivity( ACT_STAND );
+
+ m_flCrouchTimer = SequenceDuration();
+
+ m_State = STATE_UNCROUCHING;
+}
+
+
+void CWalkerMiniStrider::UpdateCrouch()
+{
+ float dt = GetTimeDelta();
+
+ m_flCrouchTimer -= dt;
+ if ( m_flCrouchTimer <= 0 )
+ {
+ if ( m_State == STATE_CROUCHING )
+ {
+ m_State = STATE_CROUCHED;
+ SetActivity( ACT_CROUCHIDLE );
+ }
+ else if ( m_State == STATE_UNCROUCHING )
+ {
+ EnableWalkMode( true );
+ m_State = STATE_NORMAL;
+ SetActivity( ACT_IDLE );
+ }
+ }
+}
+
+
+void CWalkerMiniStrider::FireMachineGun()
+{
+ CBaseEntity *pDriver = GetPassenger( VEHICLE_ROLE_DRIVER );
+ if ( pDriver )
+ {
+ // Alternate the gun we're firing
+ char *attachmentNames[2] = { "MachineGun_Left", "MachineGun_Right" };
+ int iAttachment = LookupAttachment( attachmentNames[!m_bFiringLeftGun] );
+ m_bFiringLeftGun = !m_bFiringLeftGun;
+
+ Vector vAttachmentPos;
+ QAngle vAttachmentAngles;
+ GetAttachment( iAttachment, vAttachmentPos, vAttachmentAngles );
+
+ Vector vEyePos = pDriver->EyePosition();
+ Vector vEyeForward;
+ QAngle vecAngles = pDriver->LocalEyeAngles();
+ // Use the skirmisher's yaw
+ vecAngles[YAW] = GetAbsAngles()[YAW];
+ AngleVectors( vecAngles, &vEyeForward );
+
+ // Trace ahead to find out where the crosshair is aiming
+ trace_t trace;
+ float flMaxRange = tf_skirmisher_machinegun_range.GetFloat();
+ UTIL_TraceLine(
+ vEyePos,
+ vEyePos + vEyeForward * flMaxRange,
+ MASK_SOLID,
+ this,
+ COLLISION_GROUP_NONE,
+ &trace );
+
+ Vector vecDir;
+ if ( trace.fraction < 1.0 )
+ {
+ vecDir = (trace.endpos - vAttachmentPos );
+ VectorNormalize( vecDir );
+ }
+ else
+ {
+ vecDir = vEyeForward;
+ }
+
+ // Shoot!
+ TFGameRules()->FireBullets( CTakeDamageInfo( this, pDriver, tf_skirmisher_machinegun_damage.GetFloat(), DMG_BULLET ),
+ 1, // Num shots
+ vAttachmentPos,
+ vecDir,
+ VECTOR_CONE_3DEGREES, // Spread
+ flMaxRange, // Range
+ DMG_BULLET,
+ 1, // Tracer freq
+ entindex(),
+ iAttachment, // Attachment ID
+ "MinigunTracer" );
+
+ m_flNextShootTime += (1.0f / tf_skirmisher_machinegun_rof.GetFloat());
+
+ // Play the fire sound.
+ Vector vCenter = WorldSpaceCenter();
+ CPASAttenuationFilter filter( this, "Skirmisher.GunSound" );
+ EmitSound( filter, 0, "Skirmisher.GunSound", &vCenter );
+ }
+}
+
+
+void CWalkerMiniStrider::WalkerThink()
+{
+ float dt = GetTimeDelta();
+
+ BaseClass::WalkerThink();
+
+ // Shoot the machine gun?
+ if ( !m_bFiringLargeGun )
+ {
+ if ( m_LastButtons & IN_ATTACK )
+ {
+ if ( !m_bFiringMachineGun )
+ StartFiringMachineGun();
+ }
+ else if ( m_bFiringMachineGun )
+ {
+ StopFiringMachineGun();
+ }
+ }
+
+ // Fire the large gun?
+ if ( !m_bFiringMachineGun )
+ {
+ if ( m_LastButtons & IN_ATTACK2 )
+ {
+ if ( !m_bFiringLargeGun )
+ StartFiringLargeGun();
+ }
+ }
+
+
+ UpdateCrouch();
+
+ // Make sure it's crouched when there is no driver.
+ if ( GetPassenger( VEHICLE_ROLE_DRIVER ) )
+ {
+ if ( m_LastButtons & IN_DUCK )
+ {
+ Crouch();
+ }
+ else
+ {
+ UnCrouch();
+ }
+ }
+ else
+ {
+ Crouch();
+ }
+
+ if ( m_bFiringMachineGun )
+ {
+ while ( gpGlobals->curtime > m_flNextShootTime )
+ {
+ FireMachineGun();
+ }
+ }
+
+ UpdateLargeGun();
+
+ // Move our torso within range of our feet.
+ if ( m_flOriginToLowestLegHeight != -1 )
+ {
+ Vector vCenter = WorldSpaceCenter();
+
+ //NDebugOverlay::EntityBounds( this, 255, 100, 0, 0 ,0 );
+ //NDebugOverlay::Line( vCenter, vCenter-Vector(0,0,2000), 255,0,0, true, 0 );
+
+ trace_t trace;
+ UTIL_TraceLine(
+ vCenter,
+ vCenter - Vector( 0, 0, 2000 ),
+ MASK_SOLID_BRUSHONLY,
+ this,
+ COLLISION_GROUP_NONE,
+ &trace );
+
+ if ( trace.fraction < 1 )
+ {
+ m_flWantedZ = trace.endpos.z + m_flOriginToLowestLegHeight;
+ }
+
+ // Move our Z towards the wanted Z.
+ if ( m_flWantedZ != -1 )
+ {
+ Vector vCur = vCenter;
+ vCur.z = Approach( m_flWantedZ, vCur.z, STRIDER_TORSO_VERTICAL_SLIDE_SPEED * dt );
+ SetAbsOrigin( GetAbsOrigin() + Vector( 0, 0, vCur.z - vCenter.z ) );
+ }
+ }
+}
+
+
+void CWalkerMiniStrider::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ // Sapper removal
+ if ( RemoveEnemyAttachments( pActivator ) )
+ return;
+
+ CBaseTFPlayer *pPlayer = dynamic_cast<CBaseTFPlayer*>(pActivator);
+ if ( !pPlayer || !InSameTeam( pPlayer ) )
+ return;
+
+ // Ok, put them in the driver role.
+ AttemptToBoardVehicle( pPlayer );
+}
+
+
+void CWalkerMiniStrider::SetupMove( CBasePlayer *pPlayer, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move )
+{
+ BaseClass::SetupMove( pPlayer, ucmd, pHelper, move );
+}
+
+
+bool CWalkerMiniStrider::StartBuilding( CBaseEntity *pBuilder )
+{
+ return BaseClass::StartBuilding( pBuilder );
+}
+
+
+Vector CWalkerMiniStrider::GetWalkerLocalMovement()
+{
+ float dt = GetTimeDelta();
+
+ Vector vForward, vRight;
+ AngleVectors( GetLocalAngles(), &vForward, &vRight, NULL );
+
+ float flSpeed = (tf_skirmisher_speed.GetFloat() / 100) * dt;
+ Vector vMovement =
+ vForward * (GetSteerVelocity().x * flSpeed) +
+ vRight * (GetSteerVelocity().y * flSpeed);
+
+ return GetLocalOrigin() + vMovement;
+}
+
+
+void CWalkerMiniStrider::SetPassenger( int nRole, CBasePlayer *pPassenger )
+{
+ BaseClass::SetPassenger( nRole, pPassenger );
+
+ if ( nRole == VEHICLE_ROLE_DRIVER && pPassenger )
+ UnCrouch();
+}
+
+
+void CWalkerMiniStrider::FootHit( const char *pFootName )
+{
+ if ( gpGlobals->curtime >= m_flNextFootstepSoundTime )
+ {
+ Vector footPosition;
+ QAngle angles;
+
+ ((BaseClass*)this)->GetAttachment( pFootName, footPosition, angles );
+ CPASAttenuationFilter filter( this, "Skirmisher.Footstep" );
+ EmitSound( filter, entindex(), "Skirmisher.Footstep", &footPosition );
+
+ m_flNextFootstepSoundTime = gpGlobals->curtime + 0.2;
+ }
+}
+
+
+void CWalkerMiniStrider::HandleAnimEvent( animevent_t *pEvent )
+{
+ switch( pEvent->event )
+ {
+ case 1:
+ case 2:
+ case 3:
+ {
+ FootHit( "back foot" );
+ }
+ break;
+ }
+}