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.
262 lines
6.7 KiB
262 lines
6.7 KiB
//========= 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 ); |
|
} |
|
|
|
|
|
|