Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.

209 lines
4.8 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Snark
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "npcevent.h"
#include "hl1_basecombatweapon_shared.h"
#include "basecombatcharacter.h"
#include "ai_basenpc.h"
#include "player.h"
#include "gamerules.h"
#include "in_buttons.h"
#include "soundent.h"
#include "game.h"
#include "vstdlib/random.h"
#include "engine/IEngineSound.h"
#include "hl1_npc_snark.h"
#include "beam_shared.h"
//-----------------------------------------------------------------------------
// CWeaponSnark
//-----------------------------------------------------------------------------
#define SNARK_NEST_MODEL "models/w_sqknest.mdl"
class CWeaponSnark : public CBaseHL1CombatWeapon
{
DECLARE_CLASS( CWeaponSnark, CBaseHL1CombatWeapon );
public:
CWeaponSnark( void );
void Precache( void );
void PrimaryAttack( void );
void WeaponIdle( void );
bool Deploy( void );
bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
DECLARE_SERVERCLASS();
DECLARE_DATADESC();
private:
bool m_bJustThrown;
};
LINK_ENTITY_TO_CLASS( weapon_snark, CWeaponSnark );
PRECACHE_WEAPON_REGISTER( weapon_snark );
IMPLEMENT_SERVERCLASS_ST( CWeaponSnark, DT_WeaponSnark )
END_SEND_TABLE()
BEGIN_DATADESC( CWeaponSnark )
DEFINE_FIELD( m_bJustThrown, FIELD_BOOLEAN ),
END_DATADESC()
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CWeaponSnark::CWeaponSnark( void )
{
m_bReloadsSingly = false;
m_bFiresUnderwater = true;
m_bJustThrown = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponSnark::Precache( void )
{
BaseClass::Precache();
PrecacheScriptSound( "WpnSnark.PrimaryAttack" );
PrecacheScriptSound( "WpnSnark.Deploy" );
UTIL_PrecacheOther("monster_snark");
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponSnark::PrimaryAttack( void )
{
// Only the player fires this way so we can cast
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
{
return;
}
if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
return;
Vector vecForward;
pPlayer->EyeVectors( &vecForward );
// find place to toss monster
// Does this need to consider a crouched player?
Vector vecStart = pPlayer->WorldSpaceCenter() + (vecForward * 20);
Vector vecEnd = vecStart + (vecForward * 44);
trace_t tr;
UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr );
if ( tr.allsolid || tr.startsolid || tr.fraction <= 0.25 )
return;
// player "shoot" animation
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
pPlayer->SetAnimation( PLAYER_ATTACK1 );
CSnark *pSnark = (CSnark*)Create( "monster_snark", tr.endpos, pPlayer->EyeAngles(), GetOwner() );
if ( pSnark )
{
pSnark->SetAbsVelocity( vecForward * 200 + pPlayer->GetAbsVelocity() );
}
// play hunt sound
CPASAttenuationFilter filter( this );
EmitSound( filter, entindex(), "WpnSnark.PrimaryAttack" );
CSoundEnt::InsertSound( SOUND_DANGER, GetAbsOrigin(), 200, 0.2 );
pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType );
m_bJustThrown = true;
m_flNextPrimaryAttack = gpGlobals->curtime + 0.3;
SetWeaponIdleTime( gpGlobals->curtime + 1.0 );
}
void CWeaponSnark::WeaponIdle( void )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
{
return;
}
if ( !HasWeaponIdleTimeElapsed() )
return;
if ( m_bJustThrown )
{
m_bJustThrown = false;
if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
{
if ( !pPlayer->SwitchToNextBestWeapon( pPlayer->GetActiveWeapon() ) )
Holster();
}
else
{
SendWeaponAnim( ACT_VM_DRAW );
SetWeaponIdleTime( gpGlobals->curtime + random->RandomFloat( 10, 15 ) );
}
}
else
{
if ( random->RandomFloat( 0, 1 ) <= 0.75 )
{
SendWeaponAnim( ACT_VM_IDLE );
}
else
{
SendWeaponAnim( ACT_VM_FIDGET );
}
}
}
bool CWeaponSnark::Deploy( void )
{
CPASAttenuationFilter filter( this );
EmitSound( filter, entindex(), "WpnSnark.Deploy" );
return BaseClass::Deploy();
}
bool CWeaponSnark::Holster( CBaseCombatWeapon *pSwitchingTo )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
{
return false;
}
if ( !BaseClass::Holster( pSwitchingTo ) )
{
return false;
}
if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
{
SetThink( &CWeaponSnark::DestroyItem );
SetNextThink( gpGlobals->curtime + 0.1 );
}
pPlayer->SetNextAttack( gpGlobals->curtime + 0.5 );
return true;
}