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.
176 lines
5.0 KiB
176 lines
5.0 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include "cbase.h" |
|
#include "tf_player.h" |
|
#include "engine/IEngineSound.h" |
|
#include "grenade_rocket.h" |
|
|
|
extern short g_sModelIndexFireball; |
|
|
|
IMPLEMENT_SERVERCLASS_ST( CGrenadeRocket, DT_GrenadeRocket) |
|
END_SEND_TABLE() |
|
|
|
BEGIN_DATADESC( CGrenadeRocket ) |
|
|
|
DEFINE_FIELD( m_flDamage, FIELD_FLOAT ), |
|
|
|
// Function Pointers |
|
DEFINE_FUNCTION( MissileTouch ), |
|
DEFINE_FUNCTION( FollowThink ), |
|
|
|
END_DATADESC() |
|
LINK_ENTITY_TO_CLASS( grenade_rocket, CGrenadeRocket ); |
|
PRECACHE_REGISTER(grenade_rocket); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CGrenadeRocket::CGrenadeRocket() |
|
{ |
|
m_pRealOwner = NULL; |
|
m_hLockTarget = NULL; |
|
UseClientSideAnimation(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CGrenadeRocket::Precache( void ) |
|
{ |
|
PrecacheModel( "models/weapons/w_missile.mdl" ); |
|
|
|
PrecacheScriptSound( "GrenadeRocket.FlyLoop" ); |
|
|
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CGrenadeRocket::Spawn( void ) |
|
{ |
|
Precache(); |
|
|
|
SetMoveType( MOVETYPE_FLY ); |
|
SetSolid( SOLID_BBOX ); |
|
SetModel( "models/weapons/w_missile.mdl" ); |
|
UTIL_SetSize( this, vec3_origin, vec3_origin ); |
|
|
|
SetCollisionGroup( TFCOLLISION_GROUP_WEAPON ); |
|
SetTouch( MissileTouch ); |
|
|
|
SetDamage( 50 ); |
|
|
|
// Forward! |
|
Vector forward; |
|
AngleVectors( GetLocalAngles(), &forward, NULL, NULL ); |
|
SetAbsVelocity( forward * ROCKET_VELOCITY ); |
|
|
|
EmitSound( "GrenadeRocket.FlyLoop" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CGrenadeRocket::MissileTouch( CBaseEntity *pOther ) |
|
{ |
|
Assert( pOther ); |
|
if ( !pOther->IsSolid() ) |
|
return; |
|
|
|
Vector vecAbsOrigin = GetAbsOrigin(); |
|
CPASFilter filter( vecAbsOrigin ); |
|
te->Explosion( filter, 0.0, &vecAbsOrigin, g_sModelIndexFireball, 2.0, 15, TE_EXPLFLAG_NONE, 100, m_flDamage ); |
|
|
|
StopSound( "GrenadeRocket.FlyLoop" ); |
|
|
|
// Don't apply explosive damage if it hit a shield of any kind... |
|
bool bHittingShield = false; |
|
if (pOther->GetCollisionGroup() == TFCOLLISION_GROUP_SHIELD) |
|
{ |
|
bHittingShield = true; |
|
} |
|
else if ( pOther->IsPlayer() ) |
|
{ |
|
CBaseTFPlayer *pPlayer = static_cast<CBaseTFPlayer*>(pOther); |
|
|
|
trace_t tr; |
|
float flDamage = m_flDamage; |
|
bHittingShield = pPlayer->IsHittingShield( GetAbsVelocity(), &flDamage ); |
|
} |
|
|
|
if (!bHittingShield) |
|
{ |
|
RadiusDamage( CTakeDamageInfo( this, m_pRealOwner, m_flDamage, DMG_BLAST ), vecAbsOrigin, 100, CLASS_NONE, NULL ); |
|
} |
|
|
|
UTIL_Remove( this ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Make this rocket lock onto it's target and track it |
|
//----------------------------------------------------------------------------- |
|
void CGrenadeRocket::LockOnto( CBaseEntity *pTarget ) |
|
{ |
|
m_hLockTarget = pTarget; |
|
SetThink( FollowThink ); |
|
SetNextThink( gpGlobals->curtime + 0.1f ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Try and turn towards the target point |
|
//----------------------------------------------------------------------------- |
|
void CGrenadeRocket::FollowThink( void ) |
|
{ |
|
if ( m_hLockTarget == NULL ) |
|
return; |
|
|
|
// Weave slightly drunkenly to target |
|
Vector vecTarget = m_hLockTarget->GetAbsOrigin() - GetLocalOrigin(); |
|
VectorNormalize( vecTarget ); |
|
|
|
QAngle angles; |
|
VectorAngles( vecTarget, angles ); |
|
SetLocalAngles( angles ); |
|
|
|
Vector vecVelocity = GetAbsVelocity(); |
|
float flSpeed = vecVelocity.Length(); |
|
vecVelocity = vecVelocity * 0.2 + vecTarget * flSpeed * 1.2; |
|
// Clip to maxspeed |
|
if ( vecVelocity.Length() > ROCKET_VELOCITY ) |
|
{ |
|
VectorNormalize( vecVelocity ); |
|
vecVelocity *= ROCKET_VELOCITY; |
|
} |
|
SetAbsVelocity( vecVelocity ); |
|
|
|
SetNextThink( gpGlobals->curtime + 0.1f ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Create a missile |
|
//----------------------------------------------------------------------------- |
|
CGrenadeRocket *CGrenadeRocket::Create( const Vector &vecOrigin, const Vector &vecForward, edict_t *pentOwner = NULL, CBaseEntity *pRealOwner = NULL ) |
|
{ |
|
CGrenadeRocket *pRocket = (CGrenadeRocket *)CreateEntityByName("grenade_rocket" ); |
|
|
|
UTIL_SetOrigin( pRocket, vecOrigin ); |
|
QAngle angles; |
|
VectorAngles( vecForward, angles ); |
|
pRocket->SetLocalAngles( angles ); |
|
pRocket->Spawn(); |
|
pRocket->SetOwnerEntity( Instance( pentOwner ) ); |
|
pRocket->m_pRealOwner = pRealOwner; |
|
|
|
if (pentOwner) |
|
{ |
|
CBaseEntity *pOwnerEnt = GetContainingEntity( pentOwner ); |
|
pRocket->ChangeTeam( pOwnerEnt->GetTeamNumber() ); |
|
} |
|
|
|
return pRocket; |
|
}
|
|
|