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

711 lines
19 KiB
C++

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "basehlcombatweapon.h"
#include "basecombatcharacter.h"
#include "player.h"
#include "soundent.h"
#include "te_particlesystem.h"
#include "ndebugoverlay.h"
#include "in_buttons.h"
#include "ai_basenpc.h"
#include "ai_memory.h"
#include "shake.h"
#include "gamerules.h"
#include "te_effect_dispatch.h"
#include "decals.h"
#include "IEffects.h"
#include "AmmoDef.h"
#include "soundenvelope.h"
#include "particle_parse.h"
#include "game.h"
#include "NPCevent.h"
#include "weapon_laser.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define LASER_AMMOUSING_TIME 0.1
#define LASER_DAMAGE_TIME 0.02
#define LASER_BEAM_TEXTURE "effects/Laser/laser.vmt"
#define LASER_HALO_BEAM_TEXTURE "effects/Laser/laserhalo.vmt"
#define ADDITIONAL_SPRITE "effects/Laser/aquaDot.vmt"
#define MAX_BURN_RADIUS 256
#define RADIUS_GROW_RATE 50.0
#define LASER_TARGET_INVALID Vector( FLT_MAX, FLT_MAX, FLT_MAX )
extern ConVar sk_plr_dmg_laser_wide("sk_plr_dmg_laser_wide", "7");
ConVar oc_weapon_laser_firewater_frequency("oc_weapon_laser_firewater_frequency", "0", (FCVAR_REPLICATED), "Egon damage.");
IMPLEMENT_SERVERCLASS_ST(CWeaponLaser, DT_WeaponLaser)
END_SEND_TABLE()
LINK_ENTITY_TO_CLASS(info_target_laser, CPointEntity);
LINK_ENTITY_TO_CLASS(weapon_laser, CWeaponLaser);
PRECACHE_WEAPON_REGISTER(weapon_laser);
BEGIN_DATADESC(CWeaponLaser)
DEFINE_FIELD(m_bFirstPlay, FIELD_BOOLEAN),
DEFINE_FIELD(m_flBurnRadius, FIELD_FLOAT),
DEFINE_FIELD(m_vecLaserTarget, FIELD_VECTOR),
DEFINE_FIELD(m_BeamFireState, FIELD_INTEGER),
DEFINE_FIELD(m_SSprite, FIELD_EHANDLE),
DEFINE_FIELD(m_flChargeTime, FIELD_TIME),
DEFINE_FIELD(m_flDmgTime, FIELD_TIME),
DEFINE_FIELD(m_flAmmoTime, FIELD_TIME),
DEFINE_FIELD(m_hBeam, FIELD_EHANDLE),
DEFINE_FIELD(m_hHaloBeam, FIELD_EHANDLE),
END_DATADESC()
//-----------------------------------------------------------------------------
// Maps base activities to weapons-specific ones so our characters do the right things.
//-----------------------------------------------------------------------------
acttable_t CWeaponLaser::m_acttable[] =
{
{ ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PHYSGUN, false },
{ ACT_HL2MP_RUN, ACT_HL2MP_RUN_PHYSGUN, false },
{ ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PHYSGUN, false },
{ ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PHYSGUN, false },
{ ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN, false },
{ ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PHYSGUN, false },
{ ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PHYSGUN, false },
{ ACT_IDLE, ACT_IDLE_SMG1, true },
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, true },
{ ACT_RELOAD, ACT_RELOAD_SHOTGUN, false },
{ ACT_WALK, ACT_WALK_RIFLE, true },
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SHOTGUN, true },
// Readiness activities (not aiming)
{ ACT_IDLE_RELAXED, ACT_IDLE_SHOTGUN_RELAXED, false },//never aims
{ ACT_IDLE_STIMULATED, ACT_IDLE_SHOTGUN_STIMULATED, false },
{ ACT_IDLE_AGITATED, ACT_IDLE_SHOTGUN_AGITATED, false },//always aims
{ ACT_WALK_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims
{ ACT_WALK_STIMULATED, ACT_WALK_RIFLE_STIMULATED, false },
{ ACT_WALK_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims
{ ACT_RUN_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims
{ ACT_RUN_STIMULATED, ACT_RUN_RIFLE_STIMULATED, false },
{ ACT_RUN_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims
// Readiness activities (aiming)
{ ACT_IDLE_AIM_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims
{ ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_RIFLE_STIMULATED, false },
{ ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims
{ ACT_WALK_AIM_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims
{ ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_RIFLE_STIMULATED, false },
{ ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims
{ ACT_RUN_AIM_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims
{ ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_RIFLE_STIMULATED, false },
{ ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims
//End readiness activities
{ ACT_WALK_AIM, ACT_WALK_AIM_SHOTGUN, true },
{ ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true },
{ ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true },
{ ACT_RUN, ACT_RUN_RIFLE, true },
{ ACT_RUN_AIM, ACT_RUN_AIM_SHOTGUN, true },
{ ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true },
{ ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true },
{ ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SHOTGUN, true },
{ ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SHOTGUN_LOW, true },
{ ACT_RELOAD_LOW, ACT_RELOAD_SHOTGUN_LOW, false },
{ ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SHOTGUN, false },
//{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SNIPER_RIFLE, true }
};
IMPLEMENT_ACTTABLE(CWeaponLaser);
CWeaponLaser::CWeaponLaser(void)
{
m_BeamFireState = FIRE_NONE;
m_bFirstPlay = true;
m_flChargeTime = gpGlobals->curtime;
m_flDmgTime = gpGlobals->curtime;
m_flAmmoTime = gpGlobals->curtime;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponLaser::Precache(void)
{
PrecacheMaterial(LASER_BEAM_TEXTURE);
PrecacheMaterial(LASER_HALO_BEAM_TEXTURE);
PrecacheMaterial(ADDITIONAL_SPRITE);
BaseClass::Precache();
}
void CWeaponLaser::UseAmmo(int count)
{
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
if (!pPlayer)
{
return;
}
if (pPlayer->GetAmmoCount(m_iPrimaryAmmoType) >= count)
RemoveAmmo(GetPrimaryAmmoType(), count); //pPlayer->RemoveAmmo(count, m_iPrimaryAmmoType);
else
RemoveAmmo(GetPrimaryAmmoType(), pPlayer->GetAmmoCount(m_iPrimaryAmmoType)); //pPlayer->RemoveAmmo(pPlayer->GetAmmoCount(m_iPrimaryAmmoType), m_iPrimaryAmmoType);
}
Activity CWeaponLaser::GetPrimaryAttackActivity(void)
{
if (m_BeamFireState == FIRE_STARTUP)
return BaseClass::GetPrimaryAttackActivity();
else if (m_BeamFireState == FIRE_LOOP)
return GetWpnData().animData[m_bFireMode].FirePrimarySpecial;
return BaseClass::GetPrimaryAttackActivity();
}
void CWeaponLaser::PrimaryAttack(void)
{
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
if (!pPlayer)
{
return;
}
if (pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0)
{
return;
}
if (GetActivity() != GetPrimaryAttackActivity())
SendWeaponAnim(GetPrimaryAttackActivity());
switch (m_BeamFireState)
{
case FIRE_NONE:
{
m_BeamFireState = FIRE_STARTUP;
}
break;
case FIRE_STARTUP:
{
if (m_flNextPrimaryAttack <= gpGlobals->curtime)
{
if (m_BeamFireState == FIRE_STARTUP)
Charge();
WeaponSound(SPECIAL1);
m_BeamFireState = FIRE_LOOP;
m_bFirstPlay = true;
m_flNextSecondaryAttack = m_flNextPrimaryAttack = m_flDmgTime = m_flAmmoTime = gpGlobals->curtime + GetWpnData().mode_fire_rate_automatic_startup_delay;
}
}
break;
case FIRE_LOOP:
{
m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->curtime;// +GetFireRate();
if (pPlayer->GetWaterLevel() != 3)
{
if (m_bFirstPlay)
{
/*CEffectData Data;
Data.m_nEntIndex = pPlayer->GetViewModel()->entindex();
data.m_vOrigin =
DispatchEffect("LaserSparksMuzzle", Data);*/
m_flDmgTime = m_flAmmoTime = gpGlobals->curtime + GetFireRate();
WeaponSound(SINGLE);
StopWeaponSound(SPECIAL1);
m_bFirstPlay = false;
}
Vector vecAiming = pPlayer->GetAutoaimVector(0);
Vector vecSrc = pPlayer->EyePosition();
Fire(vecSrc, vecAiming, pPlayer);
/*data.m_nEntIndex = pPlayer->GetViewModel()->entindex();
DispatchEffect("MuzzleLight", data);*/
FireClientPrimaryAttack();
}
else
DryFire();
if (GetWpnData().allowLoopSound)
StartLoopSound();
}
break;
case FIRE_END:
{
StopWeaponSound(SPECIAL1);
DestroyBeam();
StopLoopSound();
}
break;
default:
break;
}
/*if (pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0)
{
// HEV suit - indicate out of ammo condition
pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
}*/
}
void CWeaponLaser::ApplyDamage(const Vector &vecDir, trace_t &tr, CBasePlayer *pPlayer)
{
if (m_flDmgTime <= gpGlobals->curtime)
{
// wide mode does damage to the ent, and radius damage
if (tr.m_pEnt && tr.m_pEnt->m_takedamage != DAMAGE_NO)
{
ClearMultiDamage();
auto dmgType = tr.m_pEnt->IsCombatCharacter() ? DMG_BURN : DMG_BULLET;
if (tr.m_pEnt && tr.m_pEnt->IsAlive() && (tr.m_pEnt->GetFlags() & FL_ONFIRE) == 0)
{
CTakeDamageInfo info(this, pPlayer, sk_plr_dmg_laser_wide.GetFloat(), dmgType);
CalculateMeleeDamageForce(&info, vecDir, tr.endpos);
tr.m_pEnt->DispatchTraceAttack(info, vecDir, &tr);
ApplyMultiDamage();
}
if (tr.m_pEnt && tr.m_pEnt->IsAlive() && (tr.m_pEnt->GetFlags() & FL_ONFIRE) != 0)
{
CTakeDamageInfo info(this, pPlayer, sk_plr_dmg_laser_wide.GetFloat(), DMG_BULLET);
CalculateMeleeDamageForce(&info, vecDir, tr.endpos);
tr.m_pEnt->DispatchTraceAttack(info, vecDir, &tr);
ApplyMultiDamage();
}
RadiusDamage(CTakeDamageInfo(this, this, sk_plr_dmg_laser_wide.GetFloat() / 4, dmgType), tr.endpos, 10.0f, CLASS_NONE, NULL);
}
//UTIL_Smoke(tr.endpos, random->RandomInt(5, 10), 10);//Äûì îò ëó÷à
//UTIL_DecalTrace(&tr, "RedGlowFade");
UTIL_DecalTrace(&tr, "FadingScorch"); //Ãàðü îò ëó÷à
//m_flDmgTime = gpGlobals->curtime + LASER_DAMAGE_TIME;
ShouldDrawWaterImpacts(tr);
m_flDmgTime = gpGlobals->curtime + GetFireRate();
}
}
void CWeaponLaser::AmmoUsing()
{
// Wide mode uses 10 charges per second in single player
if (m_flAmmoTime <= gpGlobals->curtime)
{
UseAmmo(1);
m_flAmmoTime = gpGlobals->curtime + LASER_AMMOUSING_TIME;
}
}
void CWeaponLaser::Fire(const Vector &vecOrigSrc, const Vector &vecDir, CBasePlayer *pPlayer)
{
Vector vecDest = vecOrigSrc + (vecDir * MAX_TRACE_LENGTH);
trace_t tr;
UTIL_TraceLine(vecOrigSrc, vecDest, MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr);
if (tr.allsolid)
return;
/*CEffectData data;
data.m_vOrigin = tr.endpos + (tr.plane.normal * 1.0f);
data.m_vNormal = tr.plane.normal;
DispatchEffect("LaserSparksImpact", data);*/
UTIL_ImpactTrace(&tr, GetDamageType(), "LaserSparksImpact");
ApplyDamage(vecDir, tr, pPlayer);
AmmoUsing();
AddViewKick();
Vector vecUp, vecRight;
QAngle angDir;
VectorAngles(vecDir, angDir);
AngleVectors(angDir, NULL, &vecRight, &vecUp);
Vector tmpSrc = vecOrigSrc + (vecUp * -8) + (vecRight * 3);
UpdateBeam(tmpSrc, tr.endpos, pPlayer);
if (pPlayer)
{
CEffectData data;
data.m_nEntIndex = pPlayer->entindex();
data.m_vOrigin = tr.endpos;
data.m_vStart.x = GetWpnData().iMuzzleFlashLightR;
data.m_vStart.y = GetWpnData().iMuzzleFlashLightG;
data.m_vStart.z = GetWpnData().iMuzzleFlashLightB;
DispatchEffect("LaserWeaponLight", data);
}
/*CPASFilter filter(GetAbsOrigin());
te->DynamicLight(filter, 0.0, &tr.endpos, 0, 213, 255, 0, 250, 0.09, 0);*/
//DispatchParticleEffect("ball", tmpSrc, tr.endpos, vec3_angle, NULL);
//UpdateEffect( tr.endpos );
//UTIL_ImpactTrace( &tr, GetAmmoDef()->DamageType(m_iPrimaryAmmoType), "ImpactGauss" ); // ñëåä íà ñòåíå
}
void CWeaponLaser::UpdateBeam(const Vector &startPoint, const Vector &endPoint, CBasePlayer *pPlayer)
{
if (!m_hBeam)
{
CreateBeam(pPlayer);
}
else
{
m_hBeam->SetStartPos(endPoint);
}
if (m_hHaloBeam)
{
m_hHaloBeam->SetStartPos(endPoint);
}
if (m_SSprite)
{
m_SSprite->SetAbsOrigin(endPoint);
m_SSprite->SetBrightness(random->RandomFloat(180.f, 255.f));
m_SSprite->SetScale(random->RandomFloat(1.0f, 2.0f));
}
}
void CWeaponLaser::CreateBeam(CBasePlayer *pPlayer)
{
if (!m_hBeam)
{
int width = 2.0f;
m_hBeam = CBeam::BeamCreate(LASER_BEAM_TEXTURE, width*0.5);
m_hBeam->SetWidth(width);
if (cvar->FindVar("oc_player_draw_body")->GetInt() && cvar->FindVar("oc_player_true_firstperson_vm")->GetInt())
m_hBeam->PointEntInit(this->GetAbsOrigin(), this);
else
m_hBeam->PointEntInit(pPlayer->GetViewModel()->GetAbsOrigin(), pPlayer->GetViewModel());
m_hBeam->SetEndAttachment(1);
m_hBeam->SetScrollRate(950);
m_hBeam->AddSpawnFlags(SF_BEAM_TEMPORARY);
if (cvar->FindVar("oc_player_draw_body")->GetInt() && cvar->FindVar("oc_player_true_firstperson_vm")->GetInt())
m_hBeam->SetOwnerEntity(this);
else
m_hBeam->SetOwnerEntity(pPlayer->GetViewModel());
m_hBeam->SetBrightness(2255);
m_hBeam->SetColor(0, 213, 255);
//m_hBeam->SetHaloTexture(PrecacheModel(LASER_HALO_BEAM_TEXTURE));
}
else
{
Vector vForward, vRight, vUp, vThrowPos;
pPlayer->EyeVectors(&vForward, &vRight, &vUp);
vThrowPos = pPlayer->EyePosition();
/*if (cvar->FindVar("oc_state_IRsight_on")->GetInt() == 1)
{
vThrowPos += vForward * 22.0f;
vThrowPos += vRight * 0.7f;// *1.0f;
vThrowPos += vUp * -3.4f;
CPASFilter filter(GetAbsOrigin());
te->DynamicLight(filter, 0.0, &vThrowPos, 0, 213, 255, 0, 170, 0.12, 0);
}
else if (cvar->FindVar("oc_state_IRsight_on")->GetInt() == 0)
{
vThrowPos += vForward * 22.0f;
vThrowPos += vRight * 5.4f;
vThrowPos += vUp * -3.4f;
CPASFilter filter(GetAbsOrigin());
te->DynamicLight(filter, 0.0, &vThrowPos, 0, 213, 255, 0, 170, 0.12, 0);
}*/
}
if (!m_hHaloBeam)
{
int width = 4.0f;
m_hHaloBeam = CBeam::BeamCreate(LASER_HALO_BEAM_TEXTURE, width*0.5);
if (cvar->FindVar("oc_player_draw_body")->GetInt() && cvar->FindVar("oc_player_true_firstperson_vm")->GetInt())
m_hHaloBeam->PointEntInit(this->GetAbsOrigin(), this);
else
m_hHaloBeam->PointEntInit(pPlayer->GetViewModel()->GetAbsOrigin(), pPlayer->GetViewModel());
m_hHaloBeam->SetEndWidth(width);
m_hHaloBeam->SetEndAttachment(1);
m_hHaloBeam->SetScrollRate(950);
m_hHaloBeam->AddSpawnFlags(SF_BEAM_TEMPORARY);
if (cvar->FindVar("oc_player_draw_body")->GetInt() && cvar->FindVar("oc_player_true_firstperson_vm")->GetInt())
m_hHaloBeam->SetOwnerEntity(this);
else
m_hHaloBeam->SetOwnerEntity(pPlayer);
m_hHaloBeam->SetBrightness(50);
m_hHaloBeam->SetColor(0, 213, 255);
}
if (!m_SSprite)
{
m_SSprite = CSprite::SpriteCreate(ADDITIONAL_SPRITE, m_hBeam->GetAbsEndPos(), false);
m_SSprite->SetParent(m_hBeam);
m_SSprite->SetScale(1.0);
m_SSprite->SetColor(0, 213, 255);
m_SSprite->SetTransparency(kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation);
m_SSprite->AddSpawnFlags(SF_SPRITE_TEMPORARY);
}
}
void CWeaponLaser::DestroyBeam(void)
{
m_BeamFireState = FIRE_NONE;
if (m_bFirstPlay)
m_bFirstPlay = false;
m_flNextSecondaryAttack = m_flDmgTime = m_flChargeTime = m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
StopLoopSound();
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
if (pPlayer)
{
//GetParticleSystemIndex("")
StopParticleEffects(pPlayer->GetViewModel());
if (pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0)
m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->curtime + 0.3f;
}
if (m_hBeam)
{
UTIL_Remove(m_hBeam);
m_hBeam = NULL;
}
if (m_hHaloBeam)
{
UTIL_Remove(m_hHaloBeam);
m_hHaloBeam = NULL;
}
if (m_SSprite)
{
m_SSprite->Expand(10, 500);
m_SSprite = NULL;
}
}
bool CWeaponLaser::Holster(CBaseCombatWeapon *pSwitchingTo)
{
bool bRet;
pSwitchingTo = NULL;
bRet = BaseClass::Holster(pSwitchingTo);
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
if (!pPlayer)
return false;
StopWeaponSound(SINGLE);
StopWeaponSound(SPECIAL1);
m_BeamFireState = FIRE_NONE;
DestroyBeam();
if (bRet)
{
pSwitchingTo = NULL;
}
return bRet;
}
bool CWeaponLaser::WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions)
{
CAI_BaseNPC* npcOwner = GetOwner()->MyNPCPointer();
if (!npcOwner)
{
return false;
}
m_vecLaserTarget = targetPos;
return true;
}
int CWeaponLaser::WeaponRangeAttack1Condition(float flDot, float flDist)
{
if (m_flNextPrimaryAttack > gpGlobals->curtime)
{
return COND_NONE;
}
if (m_vecLaserTarget == LASER_TARGET_INVALID)
{
// No target!
return COND_NONE;
}
if (flDist > m_fMaxRange1)
{
return COND_TOO_FAR_TO_ATTACK;
}
else if (flDot < 0.5f) // UNDONE: Why check this here? Isn't the AI checking this already?
{
return COND_NOT_FACING_ATTACK;
}
return COND_CAN_RANGE_ATTACK1;
}
void CWeaponLaser::Charge(void)
{
}
void CWeaponLaser::ItemPostFrame(void)
{
BaseClass::ItemPostFrame();
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
if (!pPlayer)
return;
if (!m_bReloadComplete &&
!m_bInReload &&
(IsNearWall() ||
GetOwnerIsRunning()))
{
DestroyBeam();
StopWeaponSound(SPECIAL1);
return;
}
if (pPlayer->m_nButtons & IN_ZOOM)
{
if (m_BeamFireState != FIRE_END)
m_BeamFireState = FIRE_END;
}
if (pPlayer->GetWaterLevel() == 3)
{
if (m_BeamFireState != FIRE_END)
m_BeamFireState = FIRE_END;
}
if (pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 && (m_hBeam || m_hHaloBeam || m_SSprite))
{
DestroyBeam();
StopWeaponSound(SPECIAL1);
return;
}
switch (m_BeamFireState)
{
case FIRE_STARTUP:
{
if (pPlayer->m_afButtonReleased & IN_ATTACK)
{
StopWeaponSound(SPECIAL1);
StopLoopSound();
m_BeamFireState = FIRE_END;
}
}
break;
case FIRE_LOOP:
{
if (pPlayer->m_afButtonReleased & IN_ATTACK)
{
StopWeaponSound(SPECIAL1);
StopLoopSound();
m_BeamFireState = FIRE_END;
}
}
break;
case FIRE_END:
{
StopWeaponSound(SPECIAL1);
DestroyBeam();
}
break;
default:
break;
}
/*if (!(pPlayer->m_nButtons & IN_DUCK))
pPlayer->SetMaxSpeed(hl2_normspeed.GetFloat()*0.5f);
else if (pPlayer->m_nButtons & IN_DUCK)
pPlayer->SetMaxSpeed(hl2_normspeed.GetFloat());
else if (pPlayer->GetFlags() & FL_DUCKING)
pPlayer->SetMaxSpeed(hl2_normspeed.GetFloat());
if (pPlayer->m_nButtons & IN_SPEED)
pPlayer->SetMaxSpeed(hl2_normspeed.GetFloat());*/
}
//----------------------------------------------------------------------------------
// Purpose: Check for water
//----------------------------------------------------------------------------------
#define FSetBit(iBitVector, bits) ((iBitVector) |= (bits))
#define FBitSet(iBitVector, bit) ((iBitVector) & (bit))
#define TraceContents( vec ) ( enginetrace->GetPointContents( vec ) )
#define WaterContents( vec ) ( FBitSet( TraceContents( vec ), CONTENTS_WATER|CONTENTS_SLIME ) )
bool CWeaponLaser::ShouldDrawWaterImpacts(const trace_t &shot_trace)
{
//FIXME: This doesn't handle the case of trying to splash while being underwater, but that's not going to look good
// right now anyway...
// We must start outside the water
if (WaterContents(shot_trace.startpos))
return false;
// We must end inside of water
if (!WaterContents(shot_trace.endpos))
return false;
trace_t waterTrace;
UTIL_TraceLine(shot_trace.startpos, shot_trace.endpos, (CONTENTS_WATER | CONTENTS_SLIME), UTIL_GetLocalPlayer(), COLLISION_GROUP_NONE, &waterTrace);
if (waterTrace.fraction < 1.0f)
{
CEffectData data;
data.m_fFlags = 0;
data.m_vOrigin = waterTrace.endpos;
data.m_vNormal = waterTrace.plane.normal;
data.m_flScale = random->RandomFloat(2.0, 4.0f); // Water effect scale
// See if we hit slime
if (FBitSet(waterTrace.contents, CONTENTS_SLIME))
{
FSetBit(data.m_fFlags, FX_WATER_IN_SLIME);
}
CPASFilter filter(data.m_vOrigin);
te->DispatchEffect(filter, 0.0, data.m_vOrigin, "watersplash", data);
}
return true;
}