mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-23 14:46:53 +00:00
444 lines
12 KiB
C++
444 lines
12 KiB
C++
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "basehlcombatweapon.h"
|
||
|
#include "engine/IEngineSound.h"
|
||
|
#include "npcevent.h"
|
||
|
#include "in_buttons.h"
|
||
|
#include "antlion_maker.h"
|
||
|
#include "grenade_bugbait.h"
|
||
|
#include "gamestats.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
//
|
||
|
// Bug Bait Weapon
|
||
|
//
|
||
|
|
||
|
class CWeaponBugBait : public CBaseHLCombatWeapon
|
||
|
{
|
||
|
DECLARE_CLASS( CWeaponBugBait, CBaseHLCombatWeapon );
|
||
|
public:
|
||
|
|
||
|
DECLARE_SERVERCLASS();
|
||
|
|
||
|
CWeaponBugBait( void );
|
||
|
|
||
|
void Spawn( void );
|
||
|
void FallInit( void );
|
||
|
|
||
|
int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; }
|
||
|
|
||
|
void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator );
|
||
|
|
||
|
void Drop( const Vector &vecVelocity );
|
||
|
void BugbaitStickyTouch( CBaseEntity *pOther );
|
||
|
void OnPickedUp( CBaseCombatCharacter *pNewOwner );
|
||
|
bool Deploy( void );
|
||
|
bool Holster( CBaseCombatWeapon *pSwitchingTo );
|
||
|
|
||
|
void ItemPostFrame( void );
|
||
|
void Precache( void );
|
||
|
void PrimaryAttack( void );
|
||
|
void SecondaryAttack( void );
|
||
|
void ThrowGrenade( CBasePlayer *pPlayer );
|
||
|
|
||
|
bool HasAnyAmmo( void ) { return true; }
|
||
|
|
||
|
bool Reload( void );
|
||
|
|
||
|
void SetSporeEmitterState( bool state = true );
|
||
|
|
||
|
bool ShouldDisplayHUDHint() { return true; }
|
||
|
|
||
|
DECLARE_DATADESC();
|
||
|
|
||
|
protected:
|
||
|
|
||
|
bool m_bDrawBackFinished;
|
||
|
bool m_bRedraw;
|
||
|
bool m_bEmitSpores;
|
||
|
EHANDLE m_hSporeTrail;
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_SERVERCLASS_ST(CWeaponBugBait, DT_WeaponBugBait)
|
||
|
END_SEND_TABLE()
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( weapon_bugbait, CWeaponBugBait );
|
||
|
#ifndef HL2MP
|
||
|
PRECACHE_WEAPON_REGISTER( weapon_bugbait );
|
||
|
#endif
|
||
|
|
||
|
BEGIN_DATADESC( CWeaponBugBait )
|
||
|
|
||
|
DEFINE_FIELD( m_hSporeTrail, FIELD_EHANDLE ),
|
||
|
DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ),
|
||
|
DEFINE_FIELD( m_bEmitSpores, FIELD_BOOLEAN ),
|
||
|
DEFINE_FIELD( m_bDrawBackFinished, FIELD_BOOLEAN ),
|
||
|
|
||
|
DEFINE_FUNCTION( BugbaitStickyTouch ),
|
||
|
|
||
|
END_DATADESC()
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CWeaponBugBait::CWeaponBugBait( void )
|
||
|
{
|
||
|
m_bDrawBackFinished = false;
|
||
|
m_bRedraw = false;
|
||
|
m_hSporeTrail = NULL;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::Spawn( void )
|
||
|
{
|
||
|
BaseClass::Spawn();
|
||
|
|
||
|
// Increase the bugbait's pickup volume. It spawns inside the antlion guard's body,
|
||
|
// and playtesters seem to be wary about moving into the body.
|
||
|
SetSize( Vector( -4, -4, -4), Vector(4, 4, 4) );
|
||
|
CollisionProp()->UseTriggerBounds( true, 100 );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::FallInit( void )
|
||
|
{
|
||
|
// Bugbait shouldn't be physics, because it musn't roll/move away from it's spawnpoint.
|
||
|
// The game will break if the player can't pick it up, so it must stay still.
|
||
|
SetModel( GetWorldModel() );
|
||
|
|
||
|
VPhysicsDestroyObject();
|
||
|
SetMoveType( MOVETYPE_FLYGRAVITY );
|
||
|
SetSolid( SOLID_BBOX );
|
||
|
AddSolidFlags( FSOLID_TRIGGER );
|
||
|
|
||
|
SetPickupTouch();
|
||
|
|
||
|
SetThink( &CBaseCombatWeapon::FallThink );
|
||
|
|
||
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::Precache( void )
|
||
|
{
|
||
|
BaseClass::Precache();
|
||
|
|
||
|
UTIL_PrecacheOther( "npc_grenade_bugbait" );
|
||
|
|
||
|
PrecacheScriptSound( "Weapon_Bugbait.Splat" );
|
||
|
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::Drop( const Vector &vecVelocity )
|
||
|
{
|
||
|
BaseClass::Drop( vecVelocity );
|
||
|
|
||
|
// On touch, stick & stop moving. Increase our thinktime a bit so we don't stomp the touch for a bit
|
||
|
SetNextThink( gpGlobals->curtime + 3.0 );
|
||
|
SetTouch( &CWeaponBugBait::BugbaitStickyTouch );
|
||
|
|
||
|
m_hSporeTrail = SporeExplosion::CreateSporeExplosion();
|
||
|
if ( m_hSporeTrail )
|
||
|
{
|
||
|
SporeExplosion *pSporeExplosion = (SporeExplosion *)m_hSporeTrail.Get();
|
||
|
|
||
|
QAngle angles;
|
||
|
VectorAngles( Vector(0,0,1), angles );
|
||
|
|
||
|
pSporeExplosion->SetAbsAngles( angles );
|
||
|
pSporeExplosion->SetAbsOrigin( GetAbsOrigin() );
|
||
|
pSporeExplosion->SetParent( this );
|
||
|
|
||
|
pSporeExplosion->m_flSpawnRate = 16.0f;
|
||
|
pSporeExplosion->m_flParticleLifetime = 0.5f;
|
||
|
pSporeExplosion->SetRenderColor( 0.0f, 0.5f, 0.25f, 0.15f );
|
||
|
|
||
|
pSporeExplosion->m_flStartSize = 32;
|
||
|
pSporeExplosion->m_flEndSize = 48;
|
||
|
pSporeExplosion->m_flSpawnRadius = 4;
|
||
|
|
||
|
pSporeExplosion->SetLifetime( 9999 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Stick to the world when we touch it
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::BugbaitStickyTouch( CBaseEntity *pOther )
|
||
|
{
|
||
|
if ( !pOther->IsWorld() )
|
||
|
return;
|
||
|
|
||
|
// Stop moving, wait for pickup
|
||
|
SetMoveType( MOVETYPE_NONE );
|
||
|
SetThink( NULL );
|
||
|
SetPickupTouch();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *pPicker -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::OnPickedUp( CBaseCombatCharacter *pNewOwner )
|
||
|
{
|
||
|
BaseClass::OnPickedUp( pNewOwner );
|
||
|
|
||
|
if ( m_hSporeTrail )
|
||
|
{
|
||
|
UTIL_Remove( m_hSporeTrail );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::PrimaryAttack( void )
|
||
|
{
|
||
|
if ( m_bRedraw )
|
||
|
return;
|
||
|
|
||
|
CBaseCombatCharacter *pOwner = GetOwner();
|
||
|
|
||
|
if ( pOwner == NULL )
|
||
|
return;
|
||
|
|
||
|
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||
|
|
||
|
if ( pPlayer == NULL )
|
||
|
return;
|
||
|
|
||
|
SendWeaponAnim( ACT_VM_HAULBACK );
|
||
|
|
||
|
m_flTimeWeaponIdle = FLT_MAX;
|
||
|
m_flNextPrimaryAttack = FLT_MAX;
|
||
|
|
||
|
m_iPrimaryAttacks++;
|
||
|
gamestats->Event_WeaponFired( pPlayer, true, GetClassname() );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::SecondaryAttack( void )
|
||
|
{
|
||
|
// Squeeze!
|
||
|
CPASAttenuationFilter filter( this );
|
||
|
|
||
|
EmitSound( filter, entindex(), "Weapon_Bugbait.Splat" );
|
||
|
|
||
|
if ( CGrenadeBugBait::ActivateBugbaitTargets( GetOwner(), GetAbsOrigin(), true ) == false )
|
||
|
{
|
||
|
g_AntlionMakerManager.BroadcastFollowGoal( GetOwner() );
|
||
|
}
|
||
|
|
||
|
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
|
||
|
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
|
||
|
|
||
|
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||
|
if ( pOwner )
|
||
|
{
|
||
|
m_iSecondaryAttacks++;
|
||
|
gamestats->Event_WeaponFired( pOwner, false, GetClassname() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *pPlayer -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::ThrowGrenade( CBasePlayer *pPlayer )
|
||
|
{
|
||
|
Vector vForward, vRight, vUp, vThrowPos, vThrowVel;
|
||
|
|
||
|
pPlayer->EyeVectors( &vForward, &vRight, &vUp );
|
||
|
|
||
|
vThrowPos = pPlayer->EyePosition();
|
||
|
|
||
|
vThrowPos += vForward * 18.0f;
|
||
|
vThrowPos += vRight * 12.0f;
|
||
|
|
||
|
pPlayer->GetVelocity( &vThrowVel, NULL );
|
||
|
vThrowVel += vForward * 1000;
|
||
|
|
||
|
CGrenadeBugBait *pGrenade = BugBaitGrenade_Create( vThrowPos, vec3_angle, vThrowVel, QAngle(600,random->RandomInt(-1200,1200),0), pPlayer );
|
||
|
|
||
|
if ( pGrenade != NULL )
|
||
|
{
|
||
|
// If the shot is clear to the player, give the missile a grace period
|
||
|
trace_t tr;
|
||
|
UTIL_TraceLine( pPlayer->EyePosition(), pPlayer->EyePosition() + ( vForward * 128 ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
|
||
|
|
||
|
if ( tr.fraction == 1.0 )
|
||
|
{
|
||
|
pGrenade->SetGracePeriod( 0.1f );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_bRedraw = true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *pEvent -
|
||
|
// *pOperator -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator )
|
||
|
{
|
||
|
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||
|
switch( pEvent->event )
|
||
|
{
|
||
|
case EVENT_WEAPON_SEQUENCE_FINISHED:
|
||
|
m_bDrawBackFinished = true;
|
||
|
break;
|
||
|
|
||
|
case EVENT_WEAPON_THROW:
|
||
|
ThrowGrenade( pOwner );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
BaseClass::Operator_HandleAnimEvent( pEvent, pOperator );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Output : Returns true on success, false on failure.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CWeaponBugBait::Reload( void )
|
||
|
{
|
||
|
if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) )
|
||
|
{
|
||
|
//Redraw the weapon
|
||
|
SendWeaponAnim( ACT_VM_DRAW );
|
||
|
|
||
|
//Update our times
|
||
|
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
|
||
|
|
||
|
//Mark this as done
|
||
|
m_bRedraw = false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::ItemPostFrame( void )
|
||
|
{
|
||
|
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||
|
|
||
|
if ( pOwner == NULL )
|
||
|
return;
|
||
|
|
||
|
// See if we're cocked and ready to throw
|
||
|
if ( m_bDrawBackFinished )
|
||
|
{
|
||
|
if ( ( pOwner->m_nButtons & IN_ATTACK ) == false )
|
||
|
{
|
||
|
SendWeaponAnim( ACT_VM_THROW );
|
||
|
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
|
||
|
m_bDrawBackFinished = false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//See if we're attacking
|
||
|
if ( ( pOwner->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack < gpGlobals->curtime ) )
|
||
|
{
|
||
|
PrimaryAttack();
|
||
|
}
|
||
|
else if ( ( pOwner->m_nButtons & IN_ATTACK2 ) && ( m_flNextSecondaryAttack < gpGlobals->curtime ) )
|
||
|
{
|
||
|
SecondaryAttack();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( m_bRedraw )
|
||
|
{
|
||
|
if ( IsViewModelSequenceFinished() )
|
||
|
{
|
||
|
Reload();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WeaponIdle();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CWeaponBugBait::Deploy( void )
|
||
|
{
|
||
|
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||
|
|
||
|
if ( pOwner == NULL )
|
||
|
return false;
|
||
|
|
||
|
/*
|
||
|
if ( m_hSporeTrail == NULL )
|
||
|
{
|
||
|
m_hSporeTrail = SporeTrail::CreateSporeTrail();
|
||
|
|
||
|
m_hSporeTrail->m_bEmit = true;
|
||
|
m_hSporeTrail->m_flSpawnRate = 100.0f;
|
||
|
m_hSporeTrail->m_flParticleLifetime = 2.0f;
|
||
|
m_hSporeTrail->m_flStartSize = 1.0f;
|
||
|
m_hSporeTrail->m_flEndSize = 4.0f;
|
||
|
m_hSporeTrail->m_flSpawnRadius = 8.0f;
|
||
|
|
||
|
m_hSporeTrail->m_vecEndColor = Vector( 0, 0, 0 );
|
||
|
|
||
|
CBaseViewModel *vm = pOwner->GetViewModel();
|
||
|
|
||
|
if ( vm != NULL )
|
||
|
{
|
||
|
m_hSporeTrail->FollowEntity( vm );
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
m_bRedraw = false;
|
||
|
m_bDrawBackFinished = false;
|
||
|
|
||
|
return BaseClass::Deploy();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CWeaponBugBait::Holster( CBaseCombatWeapon *pSwitchingTo )
|
||
|
{
|
||
|
m_bRedraw = false;
|
||
|
m_bDrawBackFinished = false;
|
||
|
|
||
|
return BaseClass::Holster( pSwitchingTo );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : true -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponBugBait::SetSporeEmitterState( bool state )
|
||
|
{
|
||
|
m_bEmitSpores = state;
|
||
|
}
|