Files
HL2Overcharged/game/server/overcharged/weapon_snark.cpp
2025-05-21 21:20:08 +03:00

289 lines
7.2 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: HL1 snark monster remake in modern form
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "npcevent.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 "npc_snark.h"
#include "beam_shared.h"
#include "weapon_snark.h"
#include "tier0/memdbgon.h"
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_bThrowState, FIELD_BOOLEAN ),
END_DATADESC()
acttable_t CWeaponSnark::m_acttable[] =
{
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_GRENADE, false }, // BJ : MP animstate for singleplayer
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_GRENADE, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_GRENADE, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_GRENADE, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_GRENADE, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SLAM, false },
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_THROW, true },
{ ACT_IDLE_RELAXED, ACT_IDLE, false },
{ ACT_RUN_RELAXED, ACT_RUN, false },
{ ACT_WALK_RELAXED, ACT_WALK, false },
};
IMPLEMENT_ACTTABLE(CWeaponSnark);
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CWeaponSnark::CWeaponSnark( void )
{
m_bReloadsSingly = false;
m_bThrowState = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponSnark::Precache( void )
{
BaseClass::Precache();
UTIL_PrecacheOther("npc_snark");
PrecacheScriptSound("WpnSnark.PrimaryAttack");
PrecacheScriptSound("WpnSnark.Deploy");
}
//-----------------------------------------------------------------------------
// 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;
if (IsNearWall() || GetOwnerIsRunning())
{
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_THROW );
SendWeaponAnim(GetWpnData().animData[0].ThrowPrimary);
pPlayer->SetAnimation( PLAYER_ATTACK1 );
QAngle spawnAng;
VectorAngles(pPlayer->BodyDirection2D(), spawnAng);
Vector Origin;
Origin = GetClientMuzzleVector();//pPlayer->Weapon_ShootPosition()
CNPC_snark *pSnark = (CNPC_snark*)Create("npc_snark", Origin, spawnAng, pPlayer);
if (pSnark)
{
pSnark->SetGroundEntity(NULL);
pSnark->AddSpawnFlags(SF_NPC_FALL_TO_GROUND);
pSnark->SetAbsVelocity(vecForward * 340 + pPlayer->GetAbsVelocity());
pSnark->AddClassRelationship(CLASS_PLAYER, D_HT, 9999);
}
// play hunt sound
CPASAttenuationFilter filter( this );
EmitSound(filter, entindex(), SNARK_THROW_SOUND);
CSoundEnt::InsertSound( SOUND_DANGER, GetAbsOrigin(), 200, 0.2 );
pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType );
m_bThrowState = true;
m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + GetFireRate();
SetWeaponIdleTime(m_flNextPrimaryAttack);
//m_flNextPrimaryAttack = gpGlobals->curtime + 0.6; //0.3
//SetWeaponIdleTime( gpGlobals->curtime + 1.0 );
}
void CWeaponSnark::SecondaryAttack(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;
if (IsNearWall() || GetOwnerIsRunning())
{
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_THROW );
SendWeaponAnim(GetWpnData().animData[0].ThrowSecondary);
pPlayer->SetAnimation(PLAYER_ATTACK1);
QAngle spawnAng;
VectorAngles(pPlayer->BodyDirection2D(), spawnAng);
Vector Origin;
Origin = GetClientMuzzleVector();//pPlayer->Weapon_ShootPosition()
CNPC_snark *pSnark = (CNPC_snark*)Create("npc_snark", Origin, spawnAng, pPlayer);
if (pSnark)
{
pSnark->SetGroundEntity(NULL);
pSnark->AddSpawnFlags(SF_NPC_FALL_TO_GROUND);
pSnark->SetAbsVelocity(vecForward * 150 + pPlayer->GetAbsVelocity());
pSnark->AddClassRelationship(CLASS_PLAYER, D_HT, 9999);
}
// play hunt sound
CPASAttenuationFilter filter(this);
EmitSound(filter, entindex(), SNARK_THROW_SOUND);
CSoundEnt::InsertSound(SOUND_DANGER, GetAbsOrigin(), 200, 0.2);
pPlayer->RemoveAmmo(1, m_iPrimaryAmmoType);
m_bThrowState = true;
m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + GetFireRate();
SetWeaponIdleTime(m_flNextPrimaryAttack);
//m_flNextSecondaryAttack = gpGlobals->curtime + 1.3; //0.3
//SetWeaponIdleTime(gpGlobals->curtime + 1.0);
}
void CWeaponSnark::WeaponIdle( void )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
{
return;
}
if ( !HasWeaponIdleTimeElapsed() )
return;
if ( m_bThrowState )
{
m_bThrowState = 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(), SNARK_DRAW_SOUND);
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;
}