mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,266 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Indirect's mortar object
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "tf_player.h"
|
||||
#include "tf_team.h"
|
||||
#include "basecombatweapon.h"
|
||||
#include "tf_obj.h"
|
||||
#include "tf_obj_mortar.h"
|
||||
#include "techtree.h"
|
||||
#include "tf_shareddefs.h"
|
||||
#include "weapon_mortar.h"
|
||||
#include "vstdlib/random.h"
|
||||
#include "movevars_shared.h"
|
||||
#include "mortar_round.h"
|
||||
|
||||
|
||||
LINK_ENTITY_TO_CLASS(obj_mortar, CObjectMortar);
|
||||
PRECACHE_REGISTER(obj_mortar);
|
||||
|
||||
IMPLEMENT_SERVERCLASS_ST(CObjectMortar, DT_ObjectMortar)
|
||||
SendPropInt( SENDINFO( m_iRoundType ), 8, SPROP_UNSIGNED, 0 ),
|
||||
SendPropArray( SendPropInt( SENDINFO_ARRAY(m_iMortarRounds), 7, 0 ), m_iMortarRounds ),
|
||||
END_SEND_TABLE();
|
||||
|
||||
BEGIN_DATADESC( CObjectMortar )
|
||||
|
||||
DEFINE_THINKFUNC( ReloadingThink ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
// Mortar size
|
||||
#define MORTAR_MINS Vector(-16, -16, 0)
|
||||
#define MORTAR_MAXS Vector( 16, 16, 64)
|
||||
|
||||
ConVar obj_mortar_health( "obj_mortar_health","200", FCVAR_NONE, "Mortar object health" );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CObjectMortar::CObjectMortar()
|
||||
{
|
||||
for ( int i=0; i < m_iMortarRounds.Count(); i++ )
|
||||
m_iMortarRounds.Set( i, 0 );
|
||||
m_flLastBlastTime = -1;
|
||||
UseClientSideAnimation();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CObjectMortar::Spawn()
|
||||
{
|
||||
SetModel( "models/objects/obj_mortar.mdl" );
|
||||
|
||||
SetSolid( SOLID_BBOX );
|
||||
UTIL_SetSize(this, MORTAR_MINS, MORTAR_MAXS);
|
||||
m_takedamage = DAMAGE_YES;
|
||||
m_iHealth = obj_mortar_health.GetInt();
|
||||
m_iRoundType = MA_SHELL;
|
||||
m_iSalvoLeft = MORTAR_SALVO_SIZE;
|
||||
m_fObjectFlags |= OF_DONT_PREVENT_BUILD_NEAR_OBJ;
|
||||
|
||||
SetType( OBJ_MORTAR );
|
||||
|
||||
// Fill out the ammo levels
|
||||
for ( int i = 0; i < MA_LASTAMMOTYPE; i++ )
|
||||
{
|
||||
m_iMortarRounds.Set( i, MortarAmmoMax[i] );
|
||||
}
|
||||
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CObjectMortar::Precache()
|
||||
{
|
||||
PrecacheModel( "models/objects/obj_mortar.mdl" );
|
||||
PrecacheVGuiScreen( "screen_obj_mortar" );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets info about the control panels
|
||||
//-----------------------------------------------------------------------------
|
||||
void CObjectMortar::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName )
|
||||
{
|
||||
pPanelName = "screen_obj_mortar";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CObjectMortar::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
|
||||
{
|
||||
// Sapper removal
|
||||
if ( RemoveEnemyAttachments( pActivator ) )
|
||||
return;
|
||||
|
||||
if ( pActivator == GetOwner() )
|
||||
{
|
||||
int iOldType = m_iRoundType;
|
||||
m_iRoundType += 1;
|
||||
|
||||
// Cycle to the next ammo type
|
||||
while ( m_iRoundType != iOldType )
|
||||
{
|
||||
// Hit the end of the round types?
|
||||
if ( m_iRoundType == MA_LASTAMMOTYPE )
|
||||
{
|
||||
m_iRoundType = MA_SHELL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Does this round type need a technology?
|
||||
if ( MortarAmmoTechs[ m_iRoundType ] && MortarAmmoTechs[ m_iRoundType ][0] )
|
||||
{
|
||||
// Does the player have the technology?
|
||||
if ( GetOwner() && GetOwner()->HasNamedTechnology( MortarAmmoTechs[ m_iRoundType ] ) )
|
||||
{
|
||||
// Do we have ammo?
|
||||
if ( m_iMortarRounds[ m_iRoundType ] > 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Go to the next round type
|
||||
m_iRoundType += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Let other team's technician try to subvert it
|
||||
BaseClass::Use( pActivator, pCaller, useType, value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Fire a round from the mortar
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CObjectMortar::FireMortar( float flFiringPower, float flFiringAccuracy, bool bRangeUpgraded, bool bAccuracyUpgraded )
|
||||
{
|
||||
// Are we reloading?
|
||||
if ( IsReloading() )
|
||||
return false;
|
||||
// Do we have any ammo of this type left?
|
||||
if ( m_iMortarRounds[ m_iRoundType ] != -1 && m_iMortarRounds[ m_iRoundType ] == 0 )
|
||||
return false;
|
||||
|
||||
// Get target distance
|
||||
float flDistance;
|
||||
if ( bRangeUpgraded )
|
||||
{
|
||||
flDistance = MORTAR_RANGE_MIN + (flFiringPower * (MORTAR_RANGE_MAX_UPGRADED - MORTAR_RANGE_MIN));
|
||||
}
|
||||
else
|
||||
{
|
||||
flDistance = MORTAR_RANGE_MIN + (flFiringPower * (MORTAR_RANGE_MAX_INITIAL - MORTAR_RANGE_MIN));
|
||||
}
|
||||
|
||||
// Factor in inaccuracy
|
||||
float flInaccuracy;
|
||||
if ( bAccuracyUpgraded )
|
||||
{
|
||||
flInaccuracy = MORTAR_INACCURACY_MAX_UPGRADED * (flFiringAccuracy * 4); // flFiringAccuracy is a range from -0.25 to 0.25
|
||||
}
|
||||
else
|
||||
{
|
||||
flInaccuracy = MORTAR_INACCURACY_MAX_INITIAL * (flFiringAccuracy * 4); // flFiringAccuracy is a range from -0.25 to 0.25
|
||||
}
|
||||
flDistance += (flDistance * MORTAR_DIST_INACCURACY) * random->RandomFloat( -flInaccuracy, flInaccuracy );
|
||||
|
||||
Vector forward, right;
|
||||
AngleVectors( GetAbsAngles(), &forward, &right, NULL );
|
||||
Vector vecTargetOrg = GetAbsOrigin() + (forward * flDistance);
|
||||
// Add in sideways inaccuracy
|
||||
vecTargetOrg += (right * (flDistance * flInaccuracy) );
|
||||
|
||||
// Trace down from the sky and find the point we're actually going to hit
|
||||
trace_t tr;
|
||||
Vector vecSky = vecTargetOrg + Vector(0,0,1024);
|
||||
UTIL_TraceLine( vecSky, vecTargetOrg, MASK_ALL, this, COLLISION_GROUP_NONE, &tr );
|
||||
vecTargetOrg = tr.endpos;
|
||||
|
||||
Vector vecMidPoint = vec3_origin;
|
||||
// Start with a low arc, and keep aiming higher until we've got a roughly clear shot
|
||||
for (int i = 2048; i <= 4096; i += 1024)
|
||||
{
|
||||
trace_t tr1;
|
||||
trace_t tr2;
|
||||
|
||||
vecMidPoint = Vector(0,0,i) + GetAbsOrigin() + (vecTargetOrg - GetAbsOrigin()) * 0.5;
|
||||
UTIL_TraceLine(GetAbsOrigin(), vecMidPoint, MASK_ALL, this, COLLISION_GROUP_NONE, &tr1);
|
||||
UTIL_TraceLine(vecMidPoint, vecTargetOrg, MASK_ALL, this, COLLISION_GROUP_NONE, &tr2);
|
||||
|
||||
// Clear shot?
|
||||
// We want a clear shot for the first half, and a fairly clear shot on the fall
|
||||
if ( tr1.fraction == 1 && tr2.fraction > 0.5 )
|
||||
break;
|
||||
}
|
||||
|
||||
// How high should we travel to reach the apex
|
||||
float distance1 = (vecMidPoint.z - GetAbsOrigin().z);
|
||||
float distance2 = (vecMidPoint.z - vecTargetOrg.z);
|
||||
|
||||
// How long will it take to travel this distance
|
||||
float flGravity = GetCurrentGravity();
|
||||
float time1 = sqrt( distance1 / (0.5 * flGravity) );
|
||||
float time2 = sqrt( distance2 / (0.5 * flGravity) );
|
||||
if (time1 < 0.1)
|
||||
return false;
|
||||
|
||||
// how hard to launch to get there in time.
|
||||
Vector vecTargetVel = (vecTargetOrg - GetLocalOrigin()) / (time1 + time2);
|
||||
vecTargetVel.z = flGravity * time1;
|
||||
|
||||
// Create the round
|
||||
CMortarRound *pRound = CMortarRound::Create( GetLocalOrigin(), vecTargetVel, edict() );
|
||||
pRound->ChangeTeam( GetTeamNumber() );
|
||||
pRound->SetFallTime( time1 * 0.5 ); // Start a falling sound just a bit before we begin to fall
|
||||
pRound->SetRoundType( m_iRoundType );
|
||||
|
||||
// Decrease ammo count
|
||||
if ( m_iMortarRounds[ m_iRoundType ] > 0 )
|
||||
{
|
||||
m_iMortarRounds.Set( m_iRoundType, m_iMortarRounds[m_iRoundType]-1 );
|
||||
}
|
||||
|
||||
// Decrease salvo count
|
||||
if ( m_iSalvoLeft )
|
||||
{
|
||||
m_iSalvoLeft--;
|
||||
if ( m_iSalvoLeft <= 0 )
|
||||
{
|
||||
// Time to reload
|
||||
StartReloading();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Start reloading our next salvo
|
||||
//-----------------------------------------------------------------------------
|
||||
void CObjectMortar::StartReloading( void )
|
||||
{
|
||||
SetThink( ReloadingThink );
|
||||
SetNextThink( gpGlobals->curtime + MORTAR_RELOAD_TIME );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Finish reloading our salvo
|
||||
//-----------------------------------------------------------------------------
|
||||
void CObjectMortar::ReloadingThink( void )
|
||||
{
|
||||
SetThink( NULL );
|
||||
|
||||
m_iSalvoLeft = MORTAR_SALVO_SIZE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user