mirror of
https://github.com/celisej567/source-engine.git
synced 2026-09-27 16:15:14 +03:00
upload "kind" alien swarm
This commit is contained in:
877
game/shared/swarm/asw_weapon_chainsaw_shared.cpp
Normal file
877
game/shared/swarm/asw_weapon_chainsaw_shared.cpp
Normal file
@@ -0,0 +1,877 @@
|
||||
#include "cbase.h"
|
||||
#include "npcevent.h"
|
||||
#include "Sprite.h"
|
||||
#include "beam_shared.h"
|
||||
#include "takedamageinfo.h"
|
||||
#include "gamerules.h"
|
||||
#include "in_buttons.h"
|
||||
#include "soundenvelope.h"
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_baseplayer.h"
|
||||
#include "c_asw_player.h"
|
||||
#include "c_asw_marine.h"
|
||||
#include "ivieweffects.h"
|
||||
#include "c_te_effect_dispatch.h"
|
||||
#include "prediction.h"
|
||||
#include "fx.h"
|
||||
#define CASW_Player C_ASW_Player
|
||||
#define CASW_Marine C_ASW_Marine
|
||||
#else
|
||||
#include "asw_lag_compensation.h"
|
||||
#include "player.h"
|
||||
#include "asw_player.h"
|
||||
#include "asw_marine.h"
|
||||
#include "soundent.h"
|
||||
#include "game.h"
|
||||
#include "te_effect_dispatch.h"
|
||||
#include "asw_marine_speech.h"
|
||||
#include "asw_weapon_ammo_bag_shared.h"
|
||||
#endif
|
||||
|
||||
#include "vstdlib/random.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "IEffects.h"
|
||||
|
||||
#include "asw_marine_skills.h"
|
||||
#include "shake.h"
|
||||
#include "asw_util_shared.h"
|
||||
#include "asw_weapon_chainsaw_shared.h"
|
||||
#include "asw_weapon_parse.h"
|
||||
|
||||
#define ASW_CHAINSAW_CHARGE_UP_TIME 1.0
|
||||
#define ASW_CHAINSAW_PULSE_INTERVAL 0.1
|
||||
#define ASW_CHAINSAW_DISCHARGE_INTERVAL 0.1
|
||||
#define ASW_CHAINSAW_RANGE 30
|
||||
|
||||
#define ASW_CHAINSAW_BEAM_SPRITE "swarm/sprites/mlaserbeam.vmt"
|
||||
#define ASW_CHAINSAW_FLARE_SPRITE "swarm/sprites/mlaserspark.vmt"
|
||||
|
||||
extern ConVar sk_plr_dmg_asw_cs;
|
||||
extern int g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( ASW_Weapon_Chainsaw, DT_ASW_Weapon_Chainsaw );
|
||||
|
||||
BEGIN_NETWORK_TABLE( CASW_Weapon_Chainsaw, DT_ASW_Weapon_Chainsaw )
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
BEGIN_PREDICTION_DATA( CASW_Weapon_Chainsaw )
|
||||
DEFINE_FIELD( m_fireState, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_flAmmoUseTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flShakeTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flStartFireTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flDmgTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flFireAnimTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flLastHitTime, FIELD_FLOAT ),
|
||||
END_PREDICTION_DATA()
|
||||
#endif
|
||||
|
||||
LINK_ENTITY_TO_CLASS( asw_weapon_chainsaw, CASW_Weapon_Chainsaw );
|
||||
PRECACHE_WEAPON_REGISTER( asw_weapon_chainsaw );
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
BEGIN_DATADESC( CASW_Weapon_Chainsaw )
|
||||
DEFINE_FIELD( m_fireState, FIELD_INTEGER ),
|
||||
DEFINE_FIELD( m_flAmmoUseTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flShakeTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flStartFireTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flDmgTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_flFireAnimTime, FIELD_FLOAT ),
|
||||
DEFINE_FIELD( m_hBeam, FIELD_EHANDLE ),
|
||||
DEFINE_FIELD( m_hNoise, FIELD_EHANDLE ),
|
||||
END_DATADESC()
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CASW_Weapon_Chainsaw::CASW_Weapon_Chainsaw( void )
|
||||
{
|
||||
m_flFireAnimTime = 0.0f;
|
||||
m_flTargetChainsawPitch = 0.0f;
|
||||
m_flDmgTime = 0.0f;
|
||||
m_bReloadsSingly = false;
|
||||
m_bFiresUnderwater = true;
|
||||
m_bPlayedIdleSound = false;
|
||||
m_pChainsawAttackSound = NULL;
|
||||
m_pChainsawAttackOffSound = NULL;
|
||||
#ifdef GAME_DLL
|
||||
m_fLastForcedFireTime = 0; // last time we forced an AI marine to push its fire button
|
||||
#endif
|
||||
}
|
||||
|
||||
CASW_Weapon_Chainsaw::~CASW_Weapon_Chainsaw()
|
||||
{
|
||||
if (m_fireState != FIRE_OFF)
|
||||
{
|
||||
EndAttack();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_bPlayedIdleSound)
|
||||
{
|
||||
StopSound( "ASW_Chainsaw.Start" );
|
||||
if ( CBaseEntity::IsAbsQueriesValid() )
|
||||
EmitSound( "ASW_Chainsaw.Stop" );
|
||||
}
|
||||
}
|
||||
StopChainsawSound();
|
||||
StopAttackOffSound();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASW_Weapon_Chainsaw::Precache( void )
|
||||
{
|
||||
PrecacheScriptSound( "ASW_Chainsaw.Start" );
|
||||
PrecacheScriptSound( "ASW_Chainsaw.Stop" );
|
||||
PrecacheScriptSound( "ASW_Chainsaw.attackOn" );
|
||||
PrecacheScriptSound( "ASW_Chainsaw.attackOff" );
|
||||
|
||||
PrecacheModel( ASW_CHAINSAW_BEAM_SPRITE );
|
||||
PrecacheModel( ASW_CHAINSAW_FLARE_SPRITE );
|
||||
PrecacheParticleSystem( "mining_laser_exhaust" );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
bool CASW_Weapon_Chainsaw::HasAmmo()
|
||||
{
|
||||
return true;
|
||||
//return m_iClip1 > 0;
|
||||
}
|
||||
|
||||
bool CASW_Weapon_Chainsaw::Deploy( void )
|
||||
{
|
||||
SetFiringState(FIRE_OFF);
|
||||
|
||||
m_bPlayedIdleSound = true;
|
||||
EmitSound( "ASW_Chainsaw.Start" );
|
||||
SetWeaponIdleTime( gpGlobals->curtime + 0.7f );
|
||||
|
||||
return BaseClass::Deploy();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CASW_Weapon_Chainsaw::PrimaryAttack( void )
|
||||
{
|
||||
// If my clip is empty (and I use clips) start reload
|
||||
//if ( UsesClipsForAmmo1() && !m_iClip1 )
|
||||
//{
|
||||
//Reload();
|
||||
//return;
|
||||
//}
|
||||
|
||||
CASW_Player *pPlayer = GetCommander();
|
||||
CASW_Marine *pMarine = GetMarine();
|
||||
if ( !pMarine || !pMarine->IsAlive())
|
||||
{
|
||||
EndAttack();
|
||||
return;
|
||||
}
|
||||
|
||||
// don't fire underwater
|
||||
if ( pMarine->GetWaterLevel() == 3 )
|
||||
{
|
||||
if ( m_fireState != FIRE_OFF || m_hBeam )
|
||||
{
|
||||
EndAttack();
|
||||
}
|
||||
else
|
||||
{
|
||||
WeaponSound( EMPTY );
|
||||
}
|
||||
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + GetWeaponInfo()->m_flFireRate;
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + GetWeaponInfo()->m_flFireRate;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef GAME_DLL // check for turning on lag compensation
|
||||
if (pPlayer && pMarine->IsInhabited())
|
||||
{
|
||||
CASW_Lag_Compensation::RequestLagCompensation( pPlayer, pPlayer->GetCurrentUserCommand() );
|
||||
}
|
||||
#endif
|
||||
|
||||
Vector vecSrc = pMarine->Weapon_ShootPosition( );
|
||||
Vector vecAiming = vec3_origin;
|
||||
if ( pPlayer && pMarine->IsInhabited() )
|
||||
{
|
||||
vecAiming = pPlayer->GetAutoaimVectorForMarine(pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount()); // 45 degrees = 0.707106781187
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
vecAiming = pMarine->GetActualShootTrajectory( vecSrc );
|
||||
#endif
|
||||
}
|
||||
|
||||
// make vecaiming go down at 45 degrees
|
||||
vecAiming.z = 0;
|
||||
VectorNormalize(vecAiming);
|
||||
vecAiming.z = -1.0f;
|
||||
VectorNormalize(vecAiming);
|
||||
|
||||
switch( m_fireState )
|
||||
{
|
||||
case FIRE_OFF:
|
||||
{
|
||||
//if ( !HasAmmo() )
|
||||
//{
|
||||
//m_flNextPrimaryAttack = gpGlobals->curtime + 0.25;
|
||||
//m_flNextSecondaryAttack = gpGlobals->curtime + 0.25;
|
||||
//WeaponSound( EMPTY );
|
||||
//return;
|
||||
//}
|
||||
|
||||
m_flAmmoUseTime = gpGlobals->curtime;// start using ammo ASAP.
|
||||
|
||||
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
|
||||
|
||||
m_flShakeTime = 0;
|
||||
m_flStartFireTime = gpGlobals->curtime;
|
||||
|
||||
SetWeaponIdleTime( gpGlobals->curtime + 0.1 );
|
||||
|
||||
m_flDmgTime = gpGlobals->curtime + ASW_CHAINSAW_PULSE_INTERVAL;
|
||||
SetFiringState(FIRE_STARTUP);
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRE_STARTUP:
|
||||
{
|
||||
Fire( vecSrc, vecAiming );
|
||||
#ifndef CLIENT_DLL
|
||||
pMarine->OnWeaponFired( this, 1 );
|
||||
#endif
|
||||
|
||||
if ( gpGlobals->curtime >= ( m_flStartFireTime + ASW_CHAINSAW_CHARGE_UP_TIME ) )
|
||||
{
|
||||
//EmitSound( "ASW_Chainsaw.AttackLoop" );
|
||||
|
||||
SetFiringState(FIRE_CHARGE);
|
||||
}
|
||||
|
||||
if ( !HasAmmo() )
|
||||
{
|
||||
EndAttack();
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + 1.0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FIRE_CHARGE:
|
||||
{
|
||||
Fire( vecSrc, vecAiming );
|
||||
#ifndef CLIENT_DLL
|
||||
pMarine->OnWeaponFired( this, 1 );
|
||||
#endif
|
||||
|
||||
if ( !HasAmmo() )
|
||||
{
|
||||
EndAttack();
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + 1.0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::Fire( const Vector &vecOrigSrc, const Vector &vecDir )
|
||||
{
|
||||
CASW_Marine *pMarine = GetMarine();
|
||||
if ( !pMarine )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StopAttackOffSound();
|
||||
StartChainsawSound();
|
||||
|
||||
if ( m_flFireAnimTime < gpGlobals->curtime )
|
||||
{
|
||||
pMarine->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_PRIMARY );
|
||||
|
||||
m_flFireAnimTime = gpGlobals->curtime + 0.1f;
|
||||
}
|
||||
|
||||
Vector vecDest = vecOrigSrc + (vecDir * ASW_CHAINSAW_RANGE);
|
||||
|
||||
bool bDamageTime = m_flDmgTime < gpGlobals->curtime;
|
||||
bool bHit = false;
|
||||
|
||||
Ray_t ray;
|
||||
ray.Init( vecOrigSrc, vecDest, Vector( -5, -5, -5 ), Vector( 5, 5, 25 ) );
|
||||
|
||||
CBaseEntity *(pEntities[ 8 ]);
|
||||
|
||||
CHurtableEntitiesEnum hurtableEntities( pEntities, 8 );
|
||||
partition->EnumerateElementsAlongRay( PARTITION_ENGINE_NON_STATIC_EDICTS | PARTITION_ENGINE_SOLID_EDICTS, ray, false, &hurtableEntities );
|
||||
|
||||
trace_t tr;
|
||||
|
||||
for ( int i = 0; i < hurtableEntities.GetCount(); ++i )
|
||||
{
|
||||
CBaseEntity *pEntity = pEntities[ i ];
|
||||
if ( pEntity == NULL || pEntity == pMarine )
|
||||
continue;
|
||||
|
||||
bHit = true;
|
||||
|
||||
if ( bDamageTime )
|
||||
{
|
||||
// wide mode does damage to the ent, and radius damage
|
||||
if ( pEntity->m_takedamage != DAMAGE_NO )
|
||||
{
|
||||
CTraceFilterOnlyHitThis filter( pEntity );
|
||||
UTIL_TraceHull( vecOrigSrc, vecDest, Vector( -5, -5, -2 ), Vector( 5, 5, 25 ), MASK_SHOT, &filter, &tr );
|
||||
|
||||
ClearMultiDamage();
|
||||
float fDamage = 0.5f * GetWeaponInfo()->m_flBaseDamage + MarineSkills()->GetSkillBasedValueByMarine( pMarine, ASW_MARINE_SKILL_MELEE, ASW_MARINE_SUBSKILL_MELEE_DMG );
|
||||
CTakeDamageInfo info( this, pMarine, fDamage * g_pGameRules->GetDamageMultiplier(), DMG_SLASH );
|
||||
info.SetWeapon( this );
|
||||
CalculateMeleeDamageForce( &info, vecDir, tr.endpos );
|
||||
pEntity->DispatchTraceAttack( info, vecDir, &tr );
|
||||
ApplyMultiDamage();
|
||||
}
|
||||
|
||||
// radius damage a little more potent in multiplayer.
|
||||
#ifndef CLIENT_DLL
|
||||
//RadiusDamage( CTakeDamageInfo( this, pMarine, sk_plr_dmg_asw_ml.GetFloat() * g_pGameRules->GetDamageMultiplier() / 4, DMG_ENERGYBEAM | DMG_BLAST | DMG_ALWAYSGIB ), tr.endpos, 128, CLASS_NONE, NULL );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if ( bHit )
|
||||
{
|
||||
if ( bDamageTime )
|
||||
{
|
||||
m_bIsFiring = true;
|
||||
|
||||
m_flLastHitTime = gpGlobals->curtime;
|
||||
m_flTargetChainsawPitch = 0.0f;
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
pMarine->OnWeaponFired( this, 1 );
|
||||
#endif
|
||||
|
||||
if ( !pMarine->IsAlive() )
|
||||
return;
|
||||
|
||||
// uses 5 ammo/second
|
||||
if ( gpGlobals->curtime >= m_flAmmoUseTime )
|
||||
{
|
||||
// chainsaw no longer uses ammo
|
||||
|
||||
m_flAmmoUseTime = gpGlobals->curtime + 0.2;
|
||||
|
||||
/*
|
||||
// decrement ammo
|
||||
//m_iClip1 -= 1;
|
||||
|
||||
#ifdef GAME_DLL
|
||||
CASW_Marine *pMarine = GetMarine();
|
||||
if (pMarine && m_iClip1 <= 0 && pMarine->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
|
||||
{
|
||||
// check he doesn't have ammo in an ammo bay
|
||||
CASW_Weapon_Ammo_Bag* pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(0));
|
||||
if (!pAmmoBag)
|
||||
pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(1));
|
||||
if (!pAmmoBag || !pAmmoBag->CanGiveAmmoToWeapon(this))
|
||||
pMarine->GetMarineSpeech()->Chatter(CHATTER_NO_AMMO);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
m_flDmgTime = gpGlobals->curtime + ASW_CHAINSAW_DISCHARGE_INTERVAL;
|
||||
if ( m_flShakeTime < gpGlobals->curtime )
|
||||
{
|
||||
CASW_Player *pPlayer = pMarine->GetCommander();
|
||||
if (pPlayer && pMarine->IsInhabited())
|
||||
{
|
||||
// #ifndef CLIENT_DLL
|
||||
// if (gpGlobals->maxClients == 1) // only shake the screen from the server in singleplayer (in multi it'll be predicted)
|
||||
// {
|
||||
// ASW_TransmitShakeEvent( pPlayer, 5.0f, 100.0f, 1.75f, SHAKE_START );
|
||||
// }
|
||||
// #else
|
||||
// ASW_TransmitShakeEvent( pPlayer, 5.0f, 100.0f, 1.75f, SHAKE_START );
|
||||
// #endif
|
||||
}
|
||||
|
||||
m_flShakeTime = gpGlobals->curtime + 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
Vector vecUp, vecRight;
|
||||
QAngle angDir;
|
||||
|
||||
VectorAngles( vecDir, angDir );
|
||||
AngleVectors( angDir, NULL, &vecRight, &vecUp );
|
||||
|
||||
Vector tmpSrc = vecOrigSrc + (vecUp * -8) + (vecRight * 3);
|
||||
//UTIL_ImpactTrace( &tr, DMG_SLASH );
|
||||
UpdateEffect( tmpSrc, tr.endpos );
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::UpdateEffect( const Vector &startPoint, const Vector &endPoint )
|
||||
{
|
||||
//if ( !m_hBeam )
|
||||
//{
|
||||
//CreateEffect();
|
||||
//}
|
||||
|
||||
//if ( m_hBeam )
|
||||
//{
|
||||
//m_hBeam->SetStartPos( endPoint );
|
||||
//}
|
||||
|
||||
CASW_Marine* pOwner = GetMarine();
|
||||
|
||||
if (!pOwner)
|
||||
return;
|
||||
|
||||
// make sparks come out at end point
|
||||
Vector vecNormal = startPoint - endPoint;
|
||||
vecNormal.NormalizeInPlace();
|
||||
#ifndef CLIENT_DLL
|
||||
CEffectData data;
|
||||
data.m_vOrigin = endPoint;
|
||||
data.m_vNormal = vecNormal;
|
||||
CPASFilter filter( data.m_vOrigin );
|
||||
filter.SetIgnorePredictionCull(true);
|
||||
|
||||
if (gpGlobals->maxClients > 1 && pOwner->IsInhabited() && pOwner->GetCommander())
|
||||
{
|
||||
// multiplayer game, where this marine is currently being controlled by a client, who will spawn his own effect
|
||||
// so just make the beam effect for all other clients
|
||||
filter.RemoveRecipient(pOwner->GetCommander());
|
||||
}
|
||||
|
||||
DispatchEffect( filter, 0.0, "ASWWelderSparks", data );
|
||||
#else
|
||||
FX_Sparks( endPoint, 1, 2, vecNormal, 5, 32, 160 );
|
||||
#endif
|
||||
|
||||
if ( m_hNoise )
|
||||
{
|
||||
m_hNoise->SetStartPos( endPoint );
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::CreateEffect( void )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
CASW_Marine *pMarine = GetMarine();
|
||||
if ( !pMarine )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DestroyEffect();
|
||||
|
||||
m_hBeam = CBeam::BeamCreate( ASW_CHAINSAW_BEAM_SPRITE, 1.75 );
|
||||
m_hBeam->PointEntInit( GetAbsOrigin(), this );
|
||||
m_hBeam->SetBeamFlags( FBEAM_SINENOISE );
|
||||
m_hBeam->SetEndAttachment( 1 );
|
||||
m_hBeam->AddSpawnFlags( SF_BEAM_TEMPORARY ); // Flag these to be destroyed on save/restore or level transition
|
||||
m_hBeam->SetOwnerEntity( pMarine );
|
||||
m_hBeam->SetScrollRate( 10 );
|
||||
m_hBeam->SetBrightness( 200 );
|
||||
m_hBeam->SetColor( 255, 255, 255 );
|
||||
m_hBeam->SetNoise( 0.025 );
|
||||
|
||||
m_hNoise = CBeam::BeamCreate( ASW_CHAINSAW_BEAM_SPRITE, 2.5 );
|
||||
m_hNoise->PointEntInit( GetAbsOrigin(), this );
|
||||
m_hNoise->SetEndAttachment( 1 );
|
||||
m_hNoise->AddSpawnFlags( SF_BEAM_TEMPORARY );
|
||||
m_hNoise->SetOwnerEntity( pMarine );
|
||||
m_hNoise->SetScrollRate( 25 );
|
||||
m_hNoise->SetBrightness( 200 );
|
||||
m_hNoise->SetColor( 255, 255, 255 );
|
||||
m_hNoise->SetNoise( 0.8 );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CASW_Weapon_Chainsaw::DestroyEffect( void )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
if ( m_hBeam )
|
||||
{
|
||||
UTIL_Remove( m_hBeam );
|
||||
m_hBeam = NULL;
|
||||
}
|
||||
if ( m_hNoise )
|
||||
{
|
||||
UTIL_Remove( m_hNoise );
|
||||
m_hNoise = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::EndAttack( void )
|
||||
{
|
||||
|
||||
|
||||
if ( m_fireState != FIRE_OFF )
|
||||
{
|
||||
StartAttackOffSound();
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
DispatchParticleEffect( "mining_laser_exhaust", PATTACH_POINT_FOLLOW, this, "eject1" );
|
||||
#endif
|
||||
}
|
||||
|
||||
StopChainsawSound();
|
||||
|
||||
SetWeaponIdleTime( gpGlobals->curtime + 2.0 );
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + GetWeaponInfo()->m_flFireRate;
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + GetWeaponInfo()->m_flFireRate;
|
||||
|
||||
SetFiringState(FIRE_OFF);
|
||||
|
||||
ClearIsFiring();
|
||||
|
||||
DestroyEffect();
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::Drop( const Vector &vecVelocity )
|
||||
{
|
||||
if (m_fireState != FIRE_OFF)
|
||||
{
|
||||
EndAttack();
|
||||
}
|
||||
|
||||
StopChainsawSound( true );
|
||||
StopAttackOffSound();
|
||||
StopSound( "ASW_Chainsaw.Start" );
|
||||
EmitSound( "ASW_Chainsaw.Stop" );
|
||||
|
||||
BaseClass::Drop( vecVelocity );
|
||||
}
|
||||
|
||||
bool CASW_Weapon_Chainsaw::Holster( CBaseCombatWeapon *pSwitchingTo )
|
||||
{
|
||||
if (m_fireState != FIRE_OFF)
|
||||
{
|
||||
EndAttack();
|
||||
}
|
||||
|
||||
StopChainsawSound( true );
|
||||
StopAttackOffSound();
|
||||
StopSound( "ASW_Chainsaw.Start" );
|
||||
EmitSound( "ASW_Chainsaw.Stop" );
|
||||
|
||||
return BaseClass::Holster( pSwitchingTo );
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::WeaponIdle( void )
|
||||
{
|
||||
if ( !HasWeaponIdleTimeElapsed() )
|
||||
return;
|
||||
|
||||
//Msg("%f CASW_Weapon_Chainsaw::WeaponIdle\n", gpGlobals->curtime);
|
||||
|
||||
float flIdleTime;
|
||||
if ( m_fireState != FIRE_OFF )
|
||||
{
|
||||
//Msg(" ending attack\n", gpGlobals->curtime);
|
||||
EndAttack();
|
||||
flIdleTime = gpGlobals->curtime + 1.4f;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Msg(" idle looping\n", gpGlobals->curtime);
|
||||
//EmitSound( "ASW_Chainsaw.IdleLoop" );
|
||||
flIdleTime = gpGlobals->curtime + 1.7f;
|
||||
}
|
||||
|
||||
//int iAnim;
|
||||
|
||||
//float flRand = random->RandomFloat( 0,1 );
|
||||
|
||||
//if ( flRand <= 0.5 )
|
||||
//{
|
||||
//iAnim = ACT_VM_IDLE;
|
||||
//flIdleTime = gpGlobals->curtime + 1.4f;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
//iAnim = ACT_VM_FIDGET;
|
||||
//flIdleTime = gpGlobals->curtime + 3.0;
|
||||
//}
|
||||
|
||||
//SendWeaponAnim( iAnim );
|
||||
|
||||
SetWeaponIdleTime( flIdleTime );
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::SetFiringState(CHAINSAW_FIRE_STATE state)
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
//Msg("[C] SetFiringState %d\n", state);
|
||||
#else
|
||||
//Msg("[C] SetFiringState %d\n", state);
|
||||
#endif
|
||||
m_fireState = state;
|
||||
}
|
||||
|
||||
bool CASW_Weapon_Chainsaw::ShouldMarineMoveSlow()
|
||||
{
|
||||
return m_fireState != FIRE_OFF;
|
||||
}
|
||||
|
||||
#ifdef GAME_DLL
|
||||
void CASW_Weapon_Chainsaw::GetButtons(bool& bAttack1, bool& bAttack2, bool& bReload, bool& bOldReload, bool& bOldAttack1 )
|
||||
{
|
||||
CASW_Marine *pMarine = GetMarine();
|
||||
|
||||
// make AI fire this weapon whenever they have an enemy within a certain range
|
||||
if (pMarine && !pMarine->IsInhabited())
|
||||
{
|
||||
bool bHasEnemy = (pMarine->GetEnemy() && pMarine->GetEnemy()->GetAbsOrigin().DistTo(pMarine->GetAbsOrigin()) < 250.0f);
|
||||
|
||||
if (bHasEnemy)
|
||||
m_fLastForcedFireTime = gpGlobals->curtime;
|
||||
|
||||
bAttack1 = (bHasEnemy || gpGlobals->curtime < m_fLastForcedFireTime + 1.0f); // fire for 2 seconds after killing our enemy
|
||||
bAttack2 = false;
|
||||
bReload = false;
|
||||
bOldReload = false;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
BaseClass::GetButtons( bAttack1, bAttack2, bReload, bOldReload, bOldAttack1 );
|
||||
}
|
||||
#endif
|
||||
|
||||
void CASW_Weapon_Chainsaw::ItemPostFrame()
|
||||
{
|
||||
BaseClass::ItemPostFrame();
|
||||
|
||||
AdjustChainsawPitch();
|
||||
if ( m_fireState == FIRE_OFF )
|
||||
{
|
||||
StopChainsawSound();
|
||||
}
|
||||
}
|
||||
|
||||
ConVar asw_chainsaw_pitch_bite_rate( "asw_chainsaw_pitch_bite_rate", "50.0", FCVAR_CHEAT | FCVAR_REPLICATED, "How quickly the chainsaw pitch changes when attack hits somethings" );
|
||||
ConVar asw_chainsaw_pitch_return_rate( "asw_chainsaw_pitch_return_rate", "50.0", FCVAR_CHEAT | FCVAR_REPLICATED, "How quickly the pitch returns to normal when attacking chainsaw doesn't hit anything" );
|
||||
ConVar asw_chainsaw_pitch_return_delay( "asw_chainsaw_pitch_return_delay", "1.0", FCVAR_CHEAT | FCVAR_REPLICATED, "How long after attacking something before the chainsaw pitch returns to normal" );
|
||||
ConVar asw_chainsaw_pitch_target( "asw_chainsaw_pitch_target", "95.0", FCVAR_CHEAT | FCVAR_REPLICATED, "Target pitch when chainsaw starts to attack something" );
|
||||
ConVar asw_chainsaw_pitch_range( "asw_chainsaw_pitch_range", "5.0", FCVAR_CHEAT | FCVAR_REPLICATED, "Random variation applied above and below target pitch" );
|
||||
ConVar asw_chainsaw_attack_fade_time( "asw_chainsaw_attack_fade_time", "0.5", FCVAR_CHEAT | FCVAR_REPLICATED, "Time for chainsaw attack sound to fade out" );
|
||||
|
||||
ConVar asw_chainsaw_shake_amplitude( "asw_chainsaw_shake_amplitude", "12.5", FCVAR_CHEAT | FCVAR_REPLICATED );
|
||||
ConVar asw_chainsaw_shake_frequency( "asw_chainsaw_shake_frequency", "100.0", FCVAR_CHEAT | FCVAR_REPLICATED );
|
||||
ConVar asw_chainsaw_debug( "asw_chainsaw_debug", "0", FCVAR_CHEAT | FCVAR_REPLICATED );
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
ConVar asw_chainsaw_shake_duration( "asw_chainsaw_shake_duration", "1.0", FCVAR_CHEAT );
|
||||
#endif
|
||||
|
||||
void CASW_Weapon_Chainsaw::AdjustChainsawPitch()
|
||||
{
|
||||
if ( !m_pChainsawAttackSound )
|
||||
{
|
||||
if ( asw_chainsaw_debug.GetBool() )
|
||||
{
|
||||
Msg( "No chainsaw attack sound, aborting\n" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Translated into the pitch values as represented in the soundscripts that would mean roughly that you
|
||||
// change the pitch value to randomly land between 85 and 90. (Pitch value 100 equals no change. Pitch value 50 is one octave lower.)
|
||||
// The pitch down should happen over 100 milliseconds. 400 ms later (half as second after the impact triggered the pitch down)
|
||||
// reset to the original pitch value over 250 ms.
|
||||
|
||||
float flTransitionRate = 50.0f;
|
||||
|
||||
// check for returning to normal pitch
|
||||
if ( ( gpGlobals->curtime - m_flLastHitTime ) > asw_chainsaw_pitch_return_delay.GetFloat() )
|
||||
{
|
||||
m_flTargetChainsawPitch = 100.0f;
|
||||
flTransitionRate = asw_chainsaw_pitch_return_rate.GetFloat();
|
||||
}
|
||||
else if ( m_flTargetChainsawPitch == 0.0f ) // just started attacking something
|
||||
{
|
||||
float flPitchMin = asw_chainsaw_pitch_target.GetFloat() - asw_chainsaw_pitch_range.GetFloat();
|
||||
float flPitchMax = asw_chainsaw_pitch_target.GetFloat() + asw_chainsaw_pitch_range.GetFloat();
|
||||
if ( asw_chainsaw_debug.GetBool() )
|
||||
{
|
||||
Msg( "pitch min/max( %f %f )\n", flPitchMin, flPitchMax );
|
||||
}
|
||||
m_flTargetChainsawPitch = RandomFloat( flPitchMin, flPitchMax );
|
||||
flTransitionRate = asw_chainsaw_pitch_bite_rate.GetFloat();
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
if ( !( prediction && prediction->InPrediction() && !prediction->IsFirstTimePredicted() ) )
|
||||
{
|
||||
// move this somewhere else....
|
||||
ScreenShake_t shake;
|
||||
shake.command = SHAKE_STOP;
|
||||
shake.amplitude = 0;
|
||||
|
||||
HACK_GETLOCALPLAYER_GUARD( "ASW_AdjustChainsawPitch" );
|
||||
GetViewEffects()->Shake( shake );
|
||||
|
||||
shake.command = SHAKE_START;
|
||||
shake.amplitude = asw_chainsaw_shake_amplitude.GetFloat();
|
||||
shake.frequency = asw_chainsaw_shake_frequency.GetFloat();
|
||||
shake.duration = asw_chainsaw_shake_duration.GetFloat();
|
||||
|
||||
GetViewEffects()->Shake( shake );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float flCurPitch = CSoundEnvelopeController::GetController().SoundGetPitch( m_pChainsawAttackSound );
|
||||
if ( flCurPitch != m_flTargetChainsawPitch )
|
||||
{
|
||||
if ( asw_chainsaw_debug.GetBool() )
|
||||
{
|
||||
Msg( "Changing chainsaw pitch to %f transition rate %f\n", m_flTargetChainsawPitch, flTransitionRate );
|
||||
}
|
||||
|
||||
flCurPitch = Approach( m_flTargetChainsawPitch, flCurPitch, flTransitionRate * gpGlobals->curtime );
|
||||
CSoundEnvelopeController::GetController().SoundChangePitch( m_pChainsawAttackSound, flCurPitch, 0.0f );
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::StartChainsawSound()
|
||||
{
|
||||
if ( !m_pChainsawAttackSound )
|
||||
{
|
||||
if ( asw_chainsaw_debug.GetBool() )
|
||||
{
|
||||
DevMsg( "Start Chainsaw Attach Sound\n" );
|
||||
}
|
||||
|
||||
StopSound( "ASW_Chainsaw.Start" );
|
||||
|
||||
CPASAttenuationFilter filter( this );
|
||||
m_pChainsawAttackSound = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), "ASW_Chainsaw.attackOn" );
|
||||
CSoundEnvelopeController::GetController().Play( m_pChainsawAttackSound, 1.0, 100 );
|
||||
}
|
||||
else
|
||||
{
|
||||
float fVolume = CSoundEnvelopeController::GetController().SoundGetVolume( m_pChainsawAttackSound );
|
||||
if ( fVolume < 1.0f )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pChainsawAttackSound, Approach( 1.0f, fVolume, ( 1.0f / asw_chainsaw_attack_fade_time.GetFloat() ) * gpGlobals->frametime ), 0.0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::StopChainsawSound( bool bForce /*= false*/ )
|
||||
{
|
||||
if ( m_pChainsawAttackSound )
|
||||
{
|
||||
if ( asw_chainsaw_debug.GetBool() )
|
||||
{
|
||||
DevMsg( "Stop Chainsaw Attach Sound\n" );
|
||||
}
|
||||
|
||||
float fVolume = bForce ? 0.0f : CSoundEnvelopeController::GetController().SoundGetVolume( m_pChainsawAttackSound );
|
||||
if ( fVolume == 0.0f )
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_pChainsawAttackSound );
|
||||
m_pChainsawAttackSound = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pChainsawAttackSound, Approach( 0.0f, fVolume, ( 1.0f / asw_chainsaw_attack_fade_time.GetFloat() ) * gpGlobals->frametime ), 0.0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::StartAttackOffSound()
|
||||
{
|
||||
float flCurPitch = 100;
|
||||
|
||||
if ( m_pChainsawAttackSound )
|
||||
{
|
||||
if ( asw_chainsaw_debug.GetBool() )
|
||||
{
|
||||
DevMsg( "Start Chainsaw Off Sound\n" );
|
||||
}
|
||||
|
||||
flCurPitch = CSoundEnvelopeController::GetController().SoundGetPitch( m_pChainsawAttackSound );
|
||||
}
|
||||
|
||||
if ( !m_pChainsawAttackOffSound )
|
||||
{
|
||||
CPASAttenuationFilter filter( this );
|
||||
m_pChainsawAttackOffSound = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), "ASW_Chainsaw.attackOff" );
|
||||
CSoundEnvelopeController::GetController().Play( m_pChainsawAttackOffSound, 0.0, flCurPitch );
|
||||
}
|
||||
|
||||
CSoundEnvelopeController::GetController().SoundChangeVolume( m_pChainsawAttackOffSound, 1.0, asw_chainsaw_attack_fade_time.GetFloat() );
|
||||
CSoundEnvelopeController::GetController().SoundChangePitch( m_pChainsawAttackOffSound, 100, 1.0f / asw_chainsaw_pitch_return_rate.GetFloat() );
|
||||
}
|
||||
|
||||
void CASW_Weapon_Chainsaw::StopAttackOffSound()
|
||||
{
|
||||
if ( m_pChainsawAttackOffSound )
|
||||
{
|
||||
if ( asw_chainsaw_debug.GetBool() )
|
||||
{
|
||||
DevMsg( "Stop Chainsaw Off Sound\n" );
|
||||
}
|
||||
|
||||
CSoundEnvelopeController::GetController().SoundDestroy( m_pChainsawAttackOffSound );
|
||||
m_pChainsawAttackOffSound = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define ASW_CHAINSAW_SYNC_KILL_RANGE 60
|
||||
|
||||
bool CASW_Weapon_Chainsaw::CheckSyncKill( byte &forced_action, short &sync_kill_ent )
|
||||
{
|
||||
// sync kills disabled
|
||||
return false;
|
||||
/*
|
||||
// If not firing, don't do anything
|
||||
if ( !IsFiring() ) //m_fireState <= FIRE_OFF
|
||||
return false;
|
||||
|
||||
// check for enemies in front of the player
|
||||
CASW_Marine *pMarine = GetMarine();
|
||||
if ( !pMarine )
|
||||
return false;
|
||||
|
||||
if ( pMarine->GetCurrentMeleeAttack() )
|
||||
return false;
|
||||
|
||||
Vector vecSrc = pMarine->Weapon_ShootPosition();
|
||||
Vector vecDir;
|
||||
AngleVectors( pMarine->EyeAngles(), &vecDir );
|
||||
Vector vecDest = vecSrc + ( vecDir * ASW_CHAINSAW_SYNC_KILL_RANGE );
|
||||
|
||||
trace_t tr;
|
||||
UTIL_TraceHull( vecSrc, vecDest, Vector( -5, -5, -5 ), Vector( 5, 5, 5 ), MASK_SHOT, pMarine, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction < 1.0f && tr.m_pEnt && tr.m_pEnt->Classify() == CLASS_ASW_DRONE )
|
||||
{
|
||||
forced_action = FORCED_ACTION_CHAINSAW_SYNC_KILL;
|
||||
sync_kill_ent = tr.m_pEnt->entindex();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
Reference in New Issue
Block a user