summaryrefslogtreecommitdiff
path: root/game/server/tf2/tf_vehicle_tank.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/server/tf2/tf_vehicle_tank.cpp')
-rw-r--r--game/server/tf2/tf_vehicle_tank.cpp262
1 files changed, 262 insertions, 0 deletions
diff --git a/game/server/tf2/tf_vehicle_tank.cpp b/game/server/tf2/tf_vehicle_tank.cpp
new file mode 100644
index 0000000..96fea85
--- /dev/null
+++ b/game/server/tf2/tf_vehicle_tank.cpp
@@ -0,0 +1,262 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: A moving vehicle that is used as a battering ram
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "tf_vehicle_tank.h"
+#include "engine/IEngineSound.h"
+#include "VGuiScreen.h"
+#include "ammodef.h"
+#include "in_buttons.h"
+#include "vehicle_mortar_shared.h"
+#include "movevars_shared.h"
+#include "mortar_round.h"
+#include "explode.h"
+#include "tf_gamerules.h"
+#include "shake.h"
+#include "basetempentity.h"
+#include "weapon_grenade_rocket.h"
+
+
+#define TANK_MINS Vector(-30, -50, -10)
+#define TANK_MAXS Vector( 30, 50, 55)
+#define TANK_MODEL "models/objects/vehicle_tank.mdl"
+
+// N seconds between tank shots.
+#define TANK_FIRE_INTERVAL 2
+
+#define TANK_MAX_RANGE 1800
+
+
+const char *g_pTurretThinkContextName = "TurretThinkContext";
+
+ConVar vehicle_tank_damage( "vehicle_tank_damage","150", FCVAR_NONE, "Tank Rocket damage" );
+ConVar vehicle_tank_range( "vehicle_tank_range","1000", FCVAR_NONE, "Tank Rocket range" );
+ConVar vehicle_tank_radius( "vehicle_tank_radius","128", FCVAR_NONE, "Tank rocket explosive radius" );
+
+
+// How fast the turret rotates to where the driver is facing.
+#define TURRET_DEGREES_PER_SEC 30
+
+
+IMPLEMENT_SERVERCLASS_ST( CVehicleTank, DT_VehicleTank )
+ SendPropAngle( SENDINFO( m_flTurretYaw ), 11 ),
+ SendPropAngle( SENDINFO( m_flTurretPitch ), 11 ),
+END_SEND_TABLE()
+
+
+LINK_ENTITY_TO_CLASS( vehicle_tank, CVehicleTank );
+PRECACHE_REGISTER( vehicle_tank );
+
+
+// CVars
+ConVar vehicle_tank_health( "vehicle_tank_health","800", FCVAR_NONE, "Tank health" );
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CVehicleTank::CVehicleTank()
+{
+ m_flClientYaw = 0;
+ m_flClientPitch = 0;
+
+ m_flTurretYaw = 0;
+ m_flTurretPitch = 0;
+
+ m_flNextFireTime = 0;
+
+ UseClientSideAnimation();
+}
+
+
+CVehicleTank::~CVehicleTank()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CVehicleTank::Precache()
+{
+ PrecacheModel( TANK_MODEL );
+ PrecacheVGuiScreen( "screen_vulnerable_point" );
+
+ PrecacheScriptSound( "VehicleTank.FireSound" );
+
+
+ BaseClass::Precache();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CVehicleTank::Spawn()
+{
+ SetModel( TANK_MODEL );
+
+ // This size is used for placement only...
+ SetSize( TANK_MINS, TANK_MAXS );
+ m_takedamage = DAMAGE_YES;
+ m_iHealth = vehicle_tank_health.GetInt();
+
+ SetType( OBJ_VEHICLE_TANK );
+ SetMaxPassengerCount( 3 );
+
+ // This can go away when the tank is using a real tank model.
+ SetActivity( ACT_DEPLOY );
+
+ SetContextThink( TurretThink, gpGlobals->curtime, g_pTurretThinkContextName );
+
+ BaseClass::Spawn();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Gets info about the control panels
+//-----------------------------------------------------------------------------
+void CVehicleTank::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName )
+{
+ //pPanelName = "screen_vehicle_siege_tower";
+ pPanelName = "screen_vulnerable_point";
+}
+
+float MoveAngleTowards( float flAngle, float flTowards, float flRate )
+{
+ // Translate so flTowards is 0, then interpolate towards 0 or 360.
+ flAngle -= flTowards;
+
+ // Move yaw to the client yaw using the shortest path.
+ flAngle = anglemod( flAngle );
+ if ( flAngle > 180 )
+ {
+ flAngle = MIN( 360, flAngle + flRate );
+ }
+ else
+ {
+ flAngle = MAX( 0, flAngle - flRate );
+ }
+
+ // Translate back.
+ flAngle += flTowards;
+ return flAngle;
+}
+
+
+void CVehicleTank::TurretThink()
+{
+ float flStartYaw = m_flTurretYaw;
+ float flStartPitch = m_flTurretPitch;
+
+ m_flTurretYaw = MoveAngleTowards( m_flTurretYaw, m_flClientYaw, gpGlobals->frametime * TURRET_DEGREES_PER_SEC );
+ m_flTurretPitch = MoveAngleTowards( m_flTurretPitch, m_flClientPitch, gpGlobals->frametime * TURRET_DEGREES_PER_SEC );
+
+ SetBoneController( 0, m_flTurretYaw );
+ SetBoneController( 1, m_flTurretPitch );
+
+ SetContextThink( TurretThink, gpGlobals->curtime, g_pTurretThinkContextName );
+}
+
+
+//-----------------------------------------------------------------------------
+// Here's where we deal with weapons
+//-----------------------------------------------------------------------------
+void CVehicleTank::OnItemPostFrame( CBaseTFPlayer *pDriver )
+{
+ // I can't do anything if I'm not active
+ if ( !ShouldBeActive() )
+ return;
+
+ // Make sure we're allowed to fire here
+ if ( !IsReadyToDrive() )
+ return;
+
+ if ( GetPassengerRole( pDriver ) != VEHICLE_ROLE_DRIVER )
+ return;
+
+ if ( pDriver->m_nButtons & IN_ATTACK )
+ {
+ // Time to fire?
+ if ( gpGlobals->curtime >= m_flNextFireTime )
+ {
+ Fire();
+ }
+ }
+ else if ( pDriver->m_nButtons & (IN_ATTACK2 | IN_SPEED) )
+ {
+ //StartBoost();
+ BaseClass::OnItemPostFrame( pDriver );
+ }
+}
+
+
+void CVehicleTank::Fire()
+{
+ // NOTE: this code reverses the steps taken in C_VehicleTank::ClientThink to
+ // reconstruct the fire direction.
+
+ // Build local angles.
+ QAngle angles;
+ angles[YAW] = m_flTurretYaw + 90;
+ angles[PITCH] = -m_flTurretPitch;
+ angles[ROLL] = 0;
+
+ // Convert to a forward vector.
+ Vector vForward, vLocalForward;
+ AngleVectors( angles, &vLocalForward );
+
+ // Move the vector to world space.
+ matrix3x4_t tankToWorld;
+ AngleMatrix( GetAbsAngles(), tankToWorld );
+ VectorTransform( vLocalForward, tankToWorld, vForward );
+
+
+ Vector vFireOrigin;
+ QAngle dummy;
+ GetAttachment( LookupAttachment( "muzzle" ), vFireOrigin, dummy );
+
+ // Create the rocket.
+ CWeaponGrenadeRocket *pRocket = CWeaponGrenadeRocket::Create( vFireOrigin, vForward, vehicle_tank_range.GetFloat(), this );
+ if ( pRocket )
+ {
+ pRocket->SetRealOwner( GetDriverPlayer() );
+ pRocket->SetDamage( vehicle_tank_damage.GetFloat() );
+ pRocket->SetDamageRadius( vehicle_tank_radius.GetFloat() );
+
+ // Apply a screen shake.
+ UTIL_ScreenShake( vFireOrigin, 12, 60, 1.5, 512, SHAKE_START, true );
+
+ // BOOM!
+ CPASAttenuationFilter pasAttenuation( this, "VehicleTank.FireSound" );
+ EmitSound( pasAttenuation, entindex(), "VehicleTank.FireSound" );
+ }
+
+ m_flNextFireTime = gpGlobals->curtime + TANK_FIRE_INTERVAL;
+}
+
+
+bool CVehicleTank::ClientCommand( CBaseTFPlayer *pPlayer, const char *pCmd, ICommandArguments *pArg )
+{
+ ResetDeteriorationTime();
+
+ if ( FStrEq( pCmd, "TurretAngles" ) )
+ {
+ m_flClientYaw = atof( pArg->Argv(1) );
+ m_flClientPitch = atof( pArg->Argv(2) );
+ return true;
+ }
+
+ return BaseClass::ClientCommand( pPlayer, pCmd, pArg );
+}
+
+
+bool CVehicleTank::IsPassengerUsingStandardWeapons( int nRole )
+{
+ return ( nRole != VEHICLE_ROLE_DRIVER );
+}
+
+