mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-29 17:43:01 +00:00
267 lines
6.4 KiB
C++
267 lines
6.4 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose: Implements the tripmine grenade.
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "beam_shared.h"
|
|
#include "shake.h"
|
|
#include "grenade_tripmine.h"
|
|
#include "vstdlib/random.h"
|
|
#include "engine/IEngineSound.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
extern const char* g_pModelNameLaser;
|
|
|
|
ConVar sk_plr_dmg_tripmine ( "sk_plr_dmg_tripmine","0");
|
|
ConVar sk_npc_dmg_tripmine ( "sk_npc_dmg_tripmine","0");
|
|
ConVar sk_tripmine_radius ( "sk_tripmine_radius","0");
|
|
|
|
LINK_ENTITY_TO_CLASS( npc_tripmine, CTripmineGrenade );
|
|
|
|
BEGIN_DATADESC( CTripmineGrenade )
|
|
|
|
DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ),
|
|
DEFINE_FIELD( m_flPowerUp, FIELD_TIME ),
|
|
DEFINE_FIELD( m_vecDir, FIELD_VECTOR ),
|
|
DEFINE_FIELD( m_vecEnd, FIELD_POSITION_VECTOR ),
|
|
DEFINE_FIELD( m_flBeamLength, FIELD_FLOAT ),
|
|
DEFINE_FIELD( m_pBeam, FIELD_CLASSPTR ),
|
|
DEFINE_FIELD( m_posOwner, FIELD_POSITION_VECTOR ),
|
|
DEFINE_FIELD( m_angleOwner, FIELD_VECTOR ),
|
|
|
|
// Function Pointers
|
|
DEFINE_FUNCTION( WarningThink ),
|
|
DEFINE_FUNCTION( PowerupThink ),
|
|
DEFINE_FUNCTION( BeamBreakThink ),
|
|
DEFINE_FUNCTION( DelayDeathThink ),
|
|
|
|
END_DATADESC()
|
|
|
|
CTripmineGrenade::CTripmineGrenade()
|
|
{
|
|
m_vecDir.Init();
|
|
m_vecEnd.Init();
|
|
m_posOwner.Init();
|
|
m_angleOwner.Init();
|
|
}
|
|
|
|
void CTripmineGrenade::Spawn( void )
|
|
{
|
|
Precache( );
|
|
// motor
|
|
SetMoveType( MOVETYPE_FLY );
|
|
SetSolid( SOLID_BBOX );
|
|
AddSolidFlags( FSOLID_NOT_SOLID );
|
|
SetModel( "models/Weapons/w_slam.mdl" );
|
|
|
|
|
|
m_flCycle = 0;
|
|
m_nBody = 3;
|
|
m_flDamage = sk_plr_dmg_tripmine.GetFloat();
|
|
m_DmgRadius = sk_tripmine_radius.GetFloat();
|
|
|
|
ResetSequenceInfo( );
|
|
m_flPlaybackRate = 0;
|
|
|
|
UTIL_SetSize(this, Vector( -4, -4, -2), Vector(4, 4, 2));
|
|
|
|
m_flPowerUp = gpGlobals->curtime + 2.0;
|
|
|
|
SetThink( PowerupThink );
|
|
SetNextThink( gpGlobals->curtime + 0.2 );
|
|
|
|
m_takedamage = DAMAGE_YES;
|
|
|
|
m_iHealth = 1;
|
|
|
|
EmitSound( "TripmineGrenade.Charge" );
|
|
|
|
// Tripmine sits at 90 on wall so rotate back to get m_vecDir
|
|
QAngle angles = GetLocalAngles();
|
|
angles.x -= 90;
|
|
|
|
AngleVectors( angles, &m_vecDir );
|
|
m_vecEnd = GetLocalOrigin() + m_vecDir * 2048;
|
|
}
|
|
|
|
|
|
void CTripmineGrenade::Precache( void )
|
|
{
|
|
PrecacheModel("models/Weapons/w_slam.mdl");
|
|
|
|
PrecacheScriptSound( "TripmineGrenade.Charge" );
|
|
PrecacheScriptSound( "TripmineGrenade.PowerUp" );
|
|
PrecacheScriptSound( "TripmineGrenade.StopSound" );
|
|
PrecacheScriptSound( "TripmineGrenade.Activate" );
|
|
PrecacheScriptSound( "TripmineGrenade.ShootRope" );
|
|
PrecacheScriptSound( "TripmineGrenade.Hook" );
|
|
}
|
|
|
|
|
|
void CTripmineGrenade::WarningThink( void )
|
|
{
|
|
// set to power up
|
|
SetThink( PowerupThink );
|
|
SetNextThink( gpGlobals->curtime + 1.0f );
|
|
}
|
|
|
|
|
|
void CTripmineGrenade::PowerupThink( void )
|
|
{
|
|
if (gpGlobals->curtime > m_flPowerUp)
|
|
{
|
|
MakeBeam( );
|
|
RemoveSolidFlags( FSOLID_NOT_SOLID );
|
|
m_bIsLive = true;
|
|
|
|
// play enabled sound
|
|
EmitSound( "TripmineGrenade.PowerUp" );;
|
|
}
|
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
|
}
|
|
|
|
|
|
void CTripmineGrenade::KillBeam( void )
|
|
{
|
|
if ( m_pBeam )
|
|
{
|
|
UTIL_Remove( m_pBeam );
|
|
m_pBeam = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void CTripmineGrenade::MakeBeam( void )
|
|
{
|
|
trace_t tr;
|
|
|
|
UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
|
|
|
|
m_flBeamLength = tr.fraction;
|
|
|
|
|
|
|
|
// If I hit a living thing, send the beam through me so it turns on briefly
|
|
// and then blows the living thing up
|
|
CBaseEntity *pEntity = tr.m_pEnt;
|
|
CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity );
|
|
|
|
// Draw length is not the beam length if entity is in the way
|
|
float drawLength = tr.fraction;
|
|
if (pBCC)
|
|
{
|
|
SetOwnerEntity( pBCC );
|
|
UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
|
|
m_flBeamLength = tr.fraction;
|
|
SetOwnerEntity( NULL );
|
|
|
|
}
|
|
|
|
// set to follow laser spot
|
|
SetThink( BeamBreakThink );
|
|
|
|
// Delay first think slightly so beam has time
|
|
// to appear if person right in front of it
|
|
SetNextThink( gpGlobals->curtime + 1.0f );
|
|
|
|
Vector vecTmpEnd = GetLocalOrigin() + m_vecDir * 2048 * drawLength;
|
|
|
|
m_pBeam = CBeam::BeamCreate( g_pModelNameLaser, 1.0 );
|
|
m_pBeam->PointEntInit( vecTmpEnd, this );
|
|
m_pBeam->SetColor( 0, 214, 198 );
|
|
m_pBeam->SetScrollRate( 25.6 );
|
|
m_pBeam->SetBrightness( 64 );
|
|
}
|
|
|
|
|
|
void CTripmineGrenade::BeamBreakThink( 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 );
|
|
}
|
|
}
|
|
|
|
trace_t tr;
|
|
|
|
// NOT MASK_SHOT because we want only simple hit boxes
|
|
UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
|
|
|
|
// ALERT( at_console, "%f : %f\n", tr.flFraction, m_flBeamLength );
|
|
|
|
// respawn detect.
|
|
if ( !m_pBeam )
|
|
{
|
|
MakeBeam( );
|
|
if ( tr.m_pEnt )
|
|
m_hOwner = tr.m_pEnt; // reset owner too
|
|
}
|
|
|
|
|
|
CBaseEntity *pEntity = tr.m_pEnt;
|
|
CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity );
|
|
|
|
if (pBCC || fabs( m_flBeamLength - tr.fraction ) > 0.001)
|
|
{
|
|
m_iHealth = 0;
|
|
Event_Killed( CTakeDamageInfo( (CBaseEntity*)m_hOwner, this, 100, GIB_NORMAL ) );
|
|
return;
|
|
}
|
|
|
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
|
}
|
|
|
|
int CTripmineGrenade::OnTakeDamage_Alive( const CTakeDamageInfo &info )
|
|
{
|
|
if (gpGlobals->curtime < m_flPowerUp && info.GetDamage() < m_iHealth)
|
|
{
|
|
// disable
|
|
// Create( "weapon_tripmine", GetLocalOrigin() + m_vecDir * 24, GetAngles() );
|
|
SetThink( SUB_Remove );
|
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
|
KillBeam();
|
|
return FALSE;
|
|
}
|
|
return BaseClass::OnTakeDamage_Alive( info );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input :
|
|
// Output :
|
|
//-----------------------------------------------------------------------------
|
|
void CTripmineGrenade::Event_Killed( const CTakeDamageInfo &info )
|
|
{
|
|
m_takedamage = DAMAGE_NO;
|
|
|
|
SetThink( DelayDeathThink );
|
|
SetNextThink( gpGlobals->curtime + 0.5 );
|
|
|
|
EmitSound( "TripmineGrenade.StopSound" );
|
|
}
|
|
|
|
|
|
void CTripmineGrenade::DelayDeathThink( void )
|
|
{
|
|
KillBeam();
|
|
trace_t tr;
|
|
UTIL_TraceLine ( GetAbsOrigin() + m_vecDir * 8, GetAbsOrigin() - m_vecDir * 64, MASK_SOLID, this, COLLISION_GROUP_NONE, & tr);
|
|
UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START );
|
|
|
|
Explode( &tr, DMG_BLAST );
|
|
}
|
|
|