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,397 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Implements the tripmine grenade.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "util.h"
|
||||
#include "shake.h"
|
||||
#include "grenade_tripwire.h"
|
||||
#include "grenade_homer.h"
|
||||
#include "rope.h"
|
||||
#include "rope_shared.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
ConVar sk_dmg_tripwire ( "sk_dmg_tripwire","0");
|
||||
ConVar sk_tripwire_radius ( "sk_tripwire_radius","0");
|
||||
|
||||
#define GRENADETRIPWIRE_MISSILEMDL "models/Weapons/ar2_grenade.mdl"
|
||||
|
||||
#define TGRENADE_LAUNCH_VEL 1200
|
||||
#define TGRENADE_SPIN_MAG 50
|
||||
#define TGRENADE_SPIN_SPEED 100
|
||||
#define TGRENADE_MISSILE_OFFSET 50
|
||||
#define TGRENADE_MAX_ROPE_LEN 1500
|
||||
|
||||
LINK_ENTITY_TO_CLASS( npc_tripwire, CTripwireGrenade );
|
||||
|
||||
BEGIN_DATADESC( CTripwireGrenade )
|
||||
|
||||
DEFINE_FIELD( m_flPowerUp, FIELD_TIME ),
|
||||
DEFINE_FIELD( m_nMissileCount, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_vecDir, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_vTargetPos, FIELD_POSITION_VECTOR ),
|
||||
DEFINE_FIELD( m_vTargetOffset, FIELD_VECTOR ),
|
||||
DEFINE_FIELD( m_pRope, FIELD_CLASSPTR ),
|
||||
DEFINE_FIELD( m_pHook, FIELD_CLASSPTR ),
|
||||
|
||||
// Function Pointers
|
||||
DEFINE_FUNCTION( WarningThink ),
|
||||
DEFINE_FUNCTION( PowerupThink ),
|
||||
DEFINE_FUNCTION( RopeBreakThink ),
|
||||
DEFINE_FUNCTION( FireThink ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
CTripwireGrenade::CTripwireGrenade()
|
||||
{
|
||||
m_vecDir.Init();
|
||||
}
|
||||
|
||||
void CTripwireGrenade::Spawn( void )
|
||||
{
|
||||
Precache( );
|
||||
|
||||
SetMoveType( MOVETYPE_FLY );
|
||||
SetSolid( SOLID_BBOX );
|
||||
AddSolidFlags( FSOLID_NOT_SOLID );
|
||||
|
||||
SetModel( "models/Weapons/w_slam.mdl" );
|
||||
|
||||
m_nMissileCount = 0;
|
||||
|
||||
UTIL_SetSize(this, Vector( -4, -4, -2), Vector(4, 4, 2));
|
||||
|
||||
m_flPowerUp = gpGlobals->curtime + 1.2;//<<CHECK>>get rid of this
|
||||
|
||||
SetThink( WarningThink );
|
||||
SetNextThink( gpGlobals->curtime + 1.0f );
|
||||
|
||||
m_takedamage = DAMAGE_YES;
|
||||
|
||||
m_iHealth = 1;
|
||||
|
||||
m_pRope = NULL;
|
||||
m_pHook = NULL;
|
||||
|
||||
// Tripwire grenade sits at 90 on wall so rotate back to get m_vecDir
|
||||
QAngle angles = GetLocalAngles();
|
||||
angles.x -= 90;
|
||||
|
||||
AngleVectors( angles, &m_vecDir );
|
||||
}
|
||||
|
||||
|
||||
void CTripwireGrenade::Precache( void )
|
||||
{
|
||||
PrecacheModel("models/Weapons/w_slam.mdl");
|
||||
|
||||
PrecacheModel(GRENADETRIPWIRE_MISSILEMDL);
|
||||
}
|
||||
|
||||
|
||||
void CTripwireGrenade::WarningThink( void )
|
||||
{
|
||||
// play activate sound
|
||||
EmitSound( "TripwireGrenade.Activate" );
|
||||
|
||||
// set to power up
|
||||
SetThink( PowerupThink );
|
||||
SetNextThink( gpGlobals->curtime + 1.0f );
|
||||
}
|
||||
|
||||
|
||||
void CTripwireGrenade::PowerupThink( void )
|
||||
{
|
||||
if (gpGlobals->curtime > m_flPowerUp)
|
||||
{
|
||||
MakeRope( );
|
||||
RemoveSolidFlags( FSOLID_NOT_SOLID );
|
||||
m_bIsLive = true;
|
||||
}
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
|
||||
|
||||
void CTripwireGrenade::BreakRope( void )
|
||||
{
|
||||
if (m_pRope)
|
||||
{
|
||||
m_pRope->m_RopeFlags |= ROPE_COLLIDE;
|
||||
m_pRope->DetachPoint(0);
|
||||
|
||||
Vector vVelocity;
|
||||
m_pHook->GetVelocity( &vVelocity, NULL );
|
||||
if (vVelocity.Length() > 1)
|
||||
{
|
||||
m_pRope->DetachPoint(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CTripwireGrenade::MakeRope( void )
|
||||
{
|
||||
SetThink( RopeBreakThink );
|
||||
|
||||
// Delay first think slightly so rope has time
|
||||
// to appear if person right in front of it
|
||||
SetNextThink( gpGlobals->curtime + 1.0f );
|
||||
|
||||
// Create hook for end of tripwire
|
||||
m_pHook = (CTripwireHook*)CBaseEntity::Create( "tripwire_hook", GetLocalOrigin(), GetLocalAngles() );
|
||||
if (m_pHook)
|
||||
{
|
||||
Vector vShootVel = 800*(m_vecDir + Vector(0,0,0.3)+RandomVector(-0.01,0.01));
|
||||
m_pHook->SetVelocity( vShootVel, vec3_origin);
|
||||
m_pHook->SetOwnerEntity( this );
|
||||
m_pHook->m_hGrenade = this;
|
||||
|
||||
m_pRope = CRopeKeyframe::Create(this,m_pHook,0,0);
|
||||
if (m_pRope)
|
||||
{
|
||||
m_pRope->m_Width = 1;
|
||||
m_pRope->m_RopeLength = 3;
|
||||
m_pRope->m_Slack = 100;
|
||||
|
||||
CPASAttenuationFilter filter( this,"TripwireGrenade.ShootRope" );
|
||||
EmitSound( filter, entindex(),"TripwireGrenade.ShootRope" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTripwireGrenade::Attach( void )
|
||||
{
|
||||
StopSound( "TripwireGrenade.ShootRope" );
|
||||
}
|
||||
|
||||
void CTripwireGrenade::RopeBreakThink( void )
|
||||
{
|
||||
// See if I can go solid yet (has dropper moved out of way?)
|
||||
if (IsSolidFlagSet(FSOLID_NOT_SOLID))
|
||||
{
|
||||
trace_t tr;
|
||||
Vector vUpBit = GetAbsOrigin();
|
||||
vUpBit.z += 5.0;
|
||||
|
||||
UTIL_TraceEntity( this, GetAbsOrigin(), vUpBit, MASK_SHOT, &tr );
|
||||
if ( !tr.startsolid && (tr.fraction == 1.0) )
|
||||
{
|
||||
RemoveSolidFlags( FSOLID_NOT_SOLID );
|
||||
}
|
||||
}
|
||||
|
||||
// Check if rope had gotten beyond it's max length
|
||||
float flRopeLength = (GetAbsOrigin()-m_pHook->GetAbsOrigin()).Length();
|
||||
if (flRopeLength > TGRENADE_MAX_ROPE_LEN)
|
||||
{
|
||||
// Shoot missiles at hook
|
||||
m_iHealth = 0;
|
||||
BreakRope();
|
||||
m_vTargetPos = m_pHook->GetAbsOrigin();
|
||||
CrossProduct ( m_vecDir, Vector(0,0,1), m_vTargetOffset );
|
||||
m_vTargetOffset *=TGRENADE_MISSILE_OFFSET;
|
||||
SetThink(FireThink);
|
||||
FireThink();
|
||||
}
|
||||
|
||||
// Check to see if can see hook
|
||||
// NOT MASK_SHOT because we want only simple hit boxes
|
||||
trace_t tr;
|
||||
UTIL_TraceLine( GetAbsOrigin(), m_pHook->GetAbsOrigin(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
// If can't see hook
|
||||
CBaseEntity *pEntity = tr.m_pEnt;
|
||||
if (tr.fraction != 1.0 && pEntity != m_pHook)
|
||||
{
|
||||
// Shoot missiles at place where rope was intersected
|
||||
m_iHealth = 0;
|
||||
BreakRope();
|
||||
m_vTargetPos = tr.endpos;
|
||||
CrossProduct ( m_vecDir, Vector(0,0,1), m_vTargetOffset );
|
||||
m_vTargetOffset *=TGRENADE_MISSILE_OFFSET;
|
||||
SetThink(FireThink);
|
||||
FireThink();
|
||||
return;
|
||||
}
|
||||
|
||||
SetNextThink( gpGlobals->curtime + 0.1f );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Die if I take any damage
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
int CTripwireGrenade::OnTakeDamage_Alive( const CTakeDamageInfo &info )
|
||||
{
|
||||
// Killed upon any damage
|
||||
Event_Killed( info );
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: If someone damaged, me shoot of my missiles and die
|
||||
// Input :
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTripwireGrenade::Event_Killed( const CTakeDamageInfo &info )
|
||||
{
|
||||
if (m_iHealth > 0)
|
||||
{
|
||||
// Fire missiles and blow up
|
||||
for (int i=0;i<6;i++)
|
||||
{
|
||||
Vector vTargetPos = GetAbsOrigin() + RandomVector(-600,600);
|
||||
FireMissile(vTargetPos);
|
||||
}
|
||||
BreakRope();
|
||||
UTIL_Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Fire a missile at the target position
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CTripwireGrenade::FireMissile(const Vector &vTargetPos)
|
||||
{
|
||||
Vector vTargetDir = (vTargetPos - GetAbsOrigin());
|
||||
VectorNormalize(vTargetDir);
|
||||
|
||||
float flGravity = 0.0001; // No gravity on the missiles
|
||||
bool bSmokeTrail = true;
|
||||
float flHomingSpeed = 0;
|
||||
Vector vLaunchVelocity = TGRENADE_LAUNCH_VEL*vTargetDir;
|
||||
float flSpinMagnitude = TGRENADE_SPIN_MAG;
|
||||
float flSpinSpeed = TGRENADE_SPIN_SPEED;
|
||||
|
||||
//<<CHECK>> hold in string_t
|
||||
CGrenadeHomer *pGrenade = CGrenadeHomer::CreateGrenadeHomer( MAKE_STRING(GRENADETRIPWIRE_MISSILEMDL), MAKE_STRING("TripwireGrenade.FlySound"), GetAbsOrigin(), vec3_angle, edict() );
|
||||
|
||||
pGrenade->Spawn( );
|
||||
pGrenade->SetSpin(flSpinMagnitude,flSpinSpeed);
|
||||
pGrenade->SetHoming(0,0,0,0,0);
|
||||
pGrenade->SetDamage(sk_dmg_tripwire.GetFloat());
|
||||
pGrenade->SetDamageRadius(sk_tripwire_radius.GetFloat());
|
||||
pGrenade->Launch(this,NULL,vLaunchVelocity,flHomingSpeed,flGravity,bSmokeTrail);
|
||||
|
||||
// Calculate travel time
|
||||
float flTargetDist = (GetAbsOrigin() - vTargetPos).Length();
|
||||
|
||||
pGrenade->m_flDetonateTime = gpGlobals->curtime + flTargetDist/TGRENADE_LAUNCH_VEL;
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Shoot off a series of missiles over time, then go intert
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CTripwireGrenade::FireThink()
|
||||
{
|
||||
SetNextThink( gpGlobals->curtime + 0.16f );
|
||||
|
||||
Vector vTargetPos = m_vTargetPos + (m_vTargetOffset * m_nMissileCount);
|
||||
FireMissile(vTargetPos);
|
||||
|
||||
vTargetPos = m_vTargetPos - (m_vTargetOffset * m_nMissileCount);
|
||||
FireMissile(vTargetPos);
|
||||
|
||||
|
||||
m_nMissileCount++;
|
||||
if (m_nMissileCount > 4)
|
||||
{
|
||||
m_iHealth = -1;
|
||||
SetThink( NULL );
|
||||
}
|
||||
}
|
||||
|
||||
// ####################################################################
|
||||
// CTripwireHook
|
||||
//
|
||||
// This is what the tripwire shoots out at the end of the rope
|
||||
// ####################################################################
|
||||
LINK_ENTITY_TO_CLASS( tripwire_hook, CTripwireHook );
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Save/Restore
|
||||
//---------------------------------------------------------
|
||||
BEGIN_DATADESC( CTripwireHook )
|
||||
|
||||
DEFINE_FIELD( m_hGrenade, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_bAttached, FIELD_BOOLEAN ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
void CTripwireHook::Spawn( void )
|
||||
{
|
||||
|
||||
Precache( );
|
||||
SetModel( "models/Weapons/w_grenade.mdl" );//<<CHECK>>
|
||||
|
||||
UTIL_SetSize(this, Vector( -1, -1, -1), Vector(1,1, 1));
|
||||
|
||||
m_takedamage = DAMAGE_NO;
|
||||
m_bAttached = false;
|
||||
|
||||
CreateVPhysics();
|
||||
}
|
||||
|
||||
bool CTripwireHook::CreateVPhysics()
|
||||
{
|
||||
// Create the object in the physics system
|
||||
IPhysicsObject *pPhysicsObject = VPhysicsInitNormal( SOLID_BBOX, 0, false );
|
||||
|
||||
// Make sure I get touch called for static geometry
|
||||
if ( pPhysicsObject )
|
||||
{
|
||||
int flags = pPhysicsObject->GetCallbackFlags();
|
||||
flags |= CALLBACK_GLOBAL_TOUCH_STATIC;
|
||||
pPhysicsObject->SetCallbackFlags(flags);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CTripwireHook::Precache( void )
|
||||
{
|
||||
PrecacheModel("models/Weapons/w_grenade.mdl"); //<<CHECK>>
|
||||
}
|
||||
|
||||
void CTripwireHook::EndTouch( CBaseEntity *pOther )
|
||||
{
|
||||
//<<CHECK>>do instead by clearing touch function
|
||||
if (!m_bAttached)
|
||||
{
|
||||
m_bAttached = true;
|
||||
|
||||
SetVelocity(vec3_origin, vec3_origin);
|
||||
SetMoveType( MOVETYPE_NONE );
|
||||
|
||||
EmitSound( "TripwireGrenade.Hook" );
|
||||
|
||||
// Let the tripwire grenade know that I've attached
|
||||
CTripwireGrenade* pGrenade = dynamic_cast<CTripwireGrenade*>((CBaseEntity*)m_hGrenade);
|
||||
if (pGrenade)
|
||||
{
|
||||
pGrenade->Attach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTripwireHook::SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity )
|
||||
{
|
||||
IPhysicsObject *pPhysicsObject = VPhysicsGetObject();
|
||||
if ( pPhysicsObject )
|
||||
{
|
||||
pPhysicsObject->AddVelocity( &velocity, &angVelocity );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user