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

865 lines
27 KiB
C++
Raw Permalink Blame History

//========= OverCharged 2018 ==================================================//
//
// Purpose: OP4 Displacer 20 ammo primary, 60 ammo secondary
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "NPCEvent.h"
#include "basehlcombatweapon.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 "gamestats.h"
#include "weapon_displacer.h"
#include "particle_parse.h"
#include "beam_flags.h"
#include "te_effect_dispatch.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
ConVar aa_wpn_displacer_target( "aa_wpn_displacer_target", "disp_target", FCVAR_REPLICATED, "Teleport near the named entity. Usualy made to work with info_displacer_destination" );
//-----------------------------------------------------------------------------
// CWeaponGreenBall
//-----------------------------------------------------------------------------
#define BOLT_MODEL /*aa_wpn_GreenBall_model.GetString()*/ "models/blackout.mdl" //"models/props_combine/headcrabcannister01a_skybox.mdl" //models/blackout.mdl
#define BOLT_AIR_VELOCITY 1750
//#define BOLT_WATER_VELOCITY 1200
//#define BOLT_SKIN_NORMAL 0
//#define BOLT_SKIN_GLOW 1
//extern ConVar sk_plr_dmg_displacer;
//extern ConVar sk_npc_dmg_displacer;
ConVar sk_plr_dmg_displacer( "sk_plr_dmg_displacer", "130" );
ConVar sk_npc_dmg_displacer( "sk_plr_dmg_displacer", "130" );
#ifndef CLIENT_DLL
void TE_StickyBolt( IRecipientFilter& filter, float delay, Vector vecDirection, const Vector *origin );
//-----------------------------------------------------------------------------
// GreenBall
//-----------------------------------------------------------------------------
class CGreenBallProjectile : public CBaseCombatCharacter
{
DECLARE_CLASS( CGreenBallProjectile, CBaseCombatCharacter );
public:
CGreenBallProjectile() { };
~CGreenBallProjectile();
Class_T Classify( void ) { return CLASS_NONE; }
public:
void Spawn( void );
void Precache( void );
void BubbleThink( void ); // changed
void BoltTouch(CBaseEntity *pOther);
bool CreateVPhysics( void );
unsigned int PhysicsSolidMaskForEntity() const;
static CGreenBallProjectile *BoltCreate( const Vector &vecOrigin, const QAngle &angAngles, int iDamage, CBasePlayer *pentOwner = NULL );
protected:
bool ShouldDrawWaterImpacts(const trace_t &shot_trace);
int m_nLightningSprite1;
bool CreateSprites( void );
//CHandle<CSprite> m_pGlowSprite;
//CHandle<CSpriteTrail> m_pGlowTrail;
int m_iDamage;
DECLARE_DATADESC();
DECLARE_SERVERCLASS();
};
LINK_ENTITY_TO_CLASS( GreenBall_projectile, CGreenBallProjectile );
BEGIN_DATADESC( CGreenBallProjectile )
// Function Pointers
DEFINE_FUNCTION( BubbleThink ),
DEFINE_FUNCTION( BoltTouch ),
// These are recreated on reload, they don't need storage
//DEFINE_FIELD( m_pGlowSprite, FIELD_EHANDLE ),
//DEFINE_FIELD( m_pGlowTrail, FIELD_EHANDLE ),
END_DATADESC()
IMPLEMENT_SERVERCLASS_ST( CGreenBallProjectile, DT_GreenBallProjectile )
END_SEND_TABLE()
CGreenBallProjectile *CGreenBallProjectile::BoltCreate( const Vector &vecOrigin, const QAngle &angAngles, int iDamage, CBasePlayer *pentOwner )
{
// Create a new entity with CGreenBallProjectile private data
CGreenBallProjectile *pGreenBallProjectile = (CGreenBallProjectile *)CreateEntityByName( "GreenBall_projectile" );
UTIL_SetOrigin( pGreenBallProjectile, vecOrigin );
pGreenBallProjectile->SetAbsAngles( angAngles );
pGreenBallProjectile->Spawn();
pGreenBallProjectile->SetOwnerEntity( pentOwner );
pGreenBallProjectile->m_iDamage = iDamage;
return pGreenBallProjectile;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CGreenBallProjectile::~CGreenBallProjectile( void )
{
/*if ( m_pGlowSprite )
{
UTIL_Remove( m_pGlowSprite );
}*/
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CGreenBallProjectile::CreateVPhysics( void )
{
// Create the object in the physics system
VPhysicsInitNormal( SOLID_BBOX, FSOLID_NOT_STANDABLE, false );
return true;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
unsigned int CGreenBallProjectile::PhysicsSolidMaskForEntity() const
{
return ( BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_HITBOX ) & ~CONTENTS_GRATE;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CGreenBallProjectile::CreateSprites( void )
{
//DispatchParticleEffect( "hl1_tp", PATTACH_ABSORIGIN_FOLLOW, this );
/*// Start up the eye glow
m_pGlowSprite = CSprite::SpriteCreate( "sprites/light_glow02_noz.vmt", GetLocalOrigin(), false );
if ( m_pGlowSprite != NULL )
{
m_pGlowSprite->FollowEntity( this );
m_pGlowSprite->SetTransparency( kRenderGlow, 255, 255, 255, 128, kRenderFxNoDissipation );
m_pGlowSprite->SetScale( 0.2f );
m_pGlowSprite->TurnOff();
}*/
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGreenBallProjectile::Spawn( void )
{
Precache( );
SetModel( BOLT_MODEL );
SetMoveType( MOVETYPE_FLY, MOVECOLLIDE_FLY_CUSTOM );
UTIL_SetSize( this, -Vector(10,10,10), Vector(10,10,10) );
SetSolid( SOLID_BBOX );
//AddEffects( EF_NODRAW );
AddEffects( EF_NOSHADOW ); // BriJee : NO SHADOW ON PARTICLE ENTITY
// Make sure we're updated if we're underwater
UpdateWaterState();
SetTouch( &CGreenBallProjectile::BoltTouch );
SetThink( &CGreenBallProjectile::BubbleThink );
SetNextThink( gpGlobals->curtime + 0.1f );
CreateSprites();
DispatchParticleEffect("DispBall_exhaust", PATTACH_ABSORIGIN_FOLLOW, this); //<2F><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
DispatchParticleEffect("Xen_teleport_idle", PATTACH_ABSORIGIN_FOLLOW, this); //<2F><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
DispatchParticleEffect("Xen_portal_big2", PATTACH_ABSORIGIN_FOLLOW, this); //<2F><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// Make us glow until we've hit the wall
//m_nSkin = BOLT_SKIN_GLOW;
}
void CGreenBallProjectile::Precache( void )
{
PrecacheModel( BOLT_MODEL );
//PrecacheModel( "sprites/light_glow02_noz.vmt" );
PrecacheScriptSound( "Weapon_Displacer.Explode" ); //ball explode
//PrecacheParticleSystem( "hl1_tp" );
//PrecacheParticleSystem("houndeye_wave_01");
m_nLightningSprite1 = PrecacheModel("sprites/bluelaser1.vmt");
BaseClass::Precache();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pOther -
//-----------------------------------------------------------------------------
void CGreenBallProjectile::BoltTouch(CBaseEntity *pOther)
{
if (pOther)
{
if ((!pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS)))
return;
/*if (pOther->IsBaseObject())//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
UTIL_Remove(pOther);*/
if (pOther->m_takedamage != DAMAGE_NO)
{
trace_t tr, tr2;
tr = BaseClass::GetTouchTrace();
Vector vecNormalizedVel = GetAbsVelocity();
ShouldDrawWaterImpacts(tr);
ClearMultiDamage();
VectorNormalize(vecNormalizedVel);
if (GetOwnerEntity() && GetOwnerEntity()->IsPlayer() && pOther->IsNPC())
{
//CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), m_iDamage, DMG_NEVERGIB );
CTakeDamageInfo dmgInfo(this, GetOwnerEntity(), sk_plr_dmg_displacer.GetFloat(), DMG_DISSOLVE); // BriJee : AR2 dmg effect//DMG_SHOCK
dmgInfo.AdjustPlayerDamageInflictedForSkillLevel();
CalculateMeleeDamageForce(&dmgInfo, vecNormalizedVel, tr.endpos, 0.7f);
dmgInfo.SetDamagePosition(tr.endpos);
pOther->DispatchTraceAttack(dmgInfo, vecNormalizedVel, &tr);
//MikeN this is funny
//UTIL_Remove(pOther);
RadiusDamage(CTakeDamageInfo(this, this, 125 * 10, DMG_DISSOLVE), GetAbsOrigin(), 256, CLASS_NONE, NULL);
RadiusDamage(CTakeDamageInfo(this, this, 125 * 10, DMG_BLAST), GetAbsOrigin(), 256, CLASS_NONE, NULL);
}
else
{
//CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), m_iDamage, DMG_BULLET | DMG_NEVERGIB );
CTakeDamageInfo dmgInfo(this, GetOwnerEntity(), sk_plr_dmg_displacer.GetFloat(), DMG_DISSOLVE);//DMG_NEVERGIB | DMG_SHOCK
CalculateMeleeDamageForce(&dmgInfo, vecNormalizedVel, tr.endpos, 0.7f);
dmgInfo.SetDamagePosition(tr.endpos);
pOther->DispatchTraceAttack(dmgInfo, vecNormalizedVel, &tr);
//MikeN this is funny
//UTIL_Remove(pOther);
RadiusDamage(CTakeDamageInfo(this, this, 125 * 10, DMG_DISSOLVE), GetAbsOrigin(), 256, CLASS_NONE, NULL);
RadiusDamage(CTakeDamageInfo(this, this, 125 * 10, DMG_BLAST), GetAbsOrigin(), 256, CLASS_NONE, NULL);
}
//MikeN this is funny
//UTIL_Remove(pOther);
ApplyMultiDamage();
//Adrian: keep going through the glass.
if (pOther->GetCollisionGroup() == COLLISION_GROUP_BREAKABLE_GLASS)
return;
SetAbsVelocity(Vector(0, 0, 0));
// play body "thwack" sound
//EmitSound( "Weapon_Crossbow.BoltHitBody" );
/*Vector vForward;
AngleVectors( GetAbsAngles(), &vForward );
VectorNormalize ( vForward );
UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vForward * 128, MASK_OPAQUE, pOther, COLLISION_GROUP_NONE, &tr2 );
if ( tr2.fraction != 1.0f )
{
// NDebugOverlay::Box( tr2.endpos, Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0, 255, 0, 0, 10 );
// NDebugOverlay::Box( GetAbsOrigin(), Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0, 0, 255, 0, 10 );
if ( tr2.m_pEnt == NULL || ( tr2.m_pEnt && tr2.m_pEnt->GetMoveType() == MOVETYPE_NONE ) )
{
CEffectData data;
data.m_vOrigin = tr2.endpos;
data.m_vNormal = vForward;
data.m_nEntIndex = tr2.fraction != 1.0f;
DispatchEffect( "BoltImpact", data );
}
}*/
SetTouch(NULL);
SetThink(NULL);
UTIL_Remove(this);
}
else
{
trace_t tr;
ShouldDrawWaterImpacts(tr);
Vector vForward;
AngleVectors(GetAbsAngles(), &vForward);
VectorNormalize(vForward);
UTIL_TraceLine(GetAbsOrigin(), GetAbsOrigin() + vForward * 128, MASK_OPAQUE, pOther, COLLISION_GROUP_NONE, &tr);
RadiusDamage(CTakeDamageInfo(this, this, 125 * 10, DMG_DISSOLVE), GetAbsOrigin(), 256, CLASS_NONE, NULL);
RadiusDamage(CTakeDamageInfo(this, this, 125 * 10, DMG_BLAST), GetAbsOrigin(), 256, CLASS_NONE, NULL);
UTIL_Remove(this);
}
}
else
{
trace_t tr;
ShouldDrawWaterImpacts(tr);
Vector vForward;
AngleVectors(GetAbsAngles(), &vForward);
VectorNormalize(vForward);
UTIL_TraceLine(GetAbsOrigin(), GetAbsOrigin() + vForward * 128, MASK_OPAQUE, this, COLLISION_GROUP_NONE, &tr);
RadiusDamage(CTakeDamageInfo(this, this, 125 * 10, DMG_DISSOLVE), GetAbsOrigin(), 256, CLASS_NONE, NULL);
RadiusDamage(CTakeDamageInfo(this, this, 125 * 10, DMG_BLAST), GetAbsOrigin(), 256, CLASS_NONE, NULL);
UTIL_Remove(this);
}
EmitSound("Weapon_Displacer.Explode");
DispatchParticleEffect("houndeye_wave_01", GetAbsOrigin(), RandomAngle(0, 360));
//Shockring
CBroadcastRecipientFilter filter2;
te->BeamRingPoint(filter2, 0, GetAbsOrigin(), //origin
64, //start radius
800, //end radius
m_nLightningSprite1, //texture
0, //halo index
0, //start frame
2, //framerate
0.4f, //life
128, //width
0, //spread
0, //amplitude
255, //r
255, //g
225, //b
32, //a
0, //speed
FBEAM_FADEOUT
);
DispatchParticleEffect("Xen_portal_big1", GetAbsOrigin(), RandomAngle(0, 360)); //<2F><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
}
//----------------------------------------------------------------------------------
// 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 CGreenBallProjectile::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;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGreenBallProjectile::BubbleThink( void )
{
QAngle angNewAngles;
VectorAngles( GetAbsVelocity()/2.0f, angNewAngles );
SetAbsAngles( angNewAngles );
SetNextThink( gpGlobals->curtime + 0.1f );
if ( GetWaterLevel() || GetAbsVelocity().Length() <= 0)
UTIL_Remove(this);
}
#endif
IMPLEMENT_SERVERCLASS_ST(CWeapondisplacer, DT_Weapondisplacer)
END_SEND_TABLE()
LINK_ENTITY_TO_CLASS( weapon_displacer, CWeapondisplacer );
PRECACHE_WEAPON_REGISTER( weapon_displacer );
BEGIN_DATADESC( CWeapondisplacer )
DEFINE_KEYFIELD( m_iLandmark, FIELD_STRING, "landmark" ),
DEFINE_FIELD(isFiring, FIELD_BOOLEAN),
END_DATADESC()
acttable_t CWeapondisplacer::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 },
};
IMPLEMENT_ACTTABLE(CWeapondisplacer);
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CWeapondisplacer::CWeapondisplacer( void )
{
isFiring = false;
m_bPrimary = false;
m_bSecondary = false;
}
void CWeapondisplacer::Precache( void )
{
BaseClass::Precache();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
void CWeapondisplacer::PrimaryAttack( void )
{
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( pOwner == NULL )
return;
if (IsNearWall() || GetOwnerIsRunning())
{
return;
}
if ( m_bShotDelayed )
return;
// Cannot fire underwater
if ( GetOwner() && GetOwner()->GetWaterLevel() == 3 )
{
m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f;
return;
}
if ( pOwner->GetAmmoCount( m_iPrimaryAmmoType ) < 20 ) // BriJee : Fix for 70 50 30 10 ammo count. Dont shoot if we have less than 20 ammo
{
WeaponSound( EMPTY );
m_bPrimary = false;
m_flNextPrimaryAttack = gpGlobals->curtime + 2.1f; // BriJee : Loop primaryattack sound fix
return;
}
m_bWeaponBlockWall = true;
isFiring = true;
m_bIsFiring = isFiring;
SendWeaponAnim(ACT_GAUSS_SPINUP); // spin anim start
//pOwner->SetAnimation( PLAYER_ATTACK1 );
WeaponSound( SPECIAL1 );
//WeaponSound( SINGLE );
m_bShotDelayed = true;
m_flDelayedFire = gpGlobals->curtime + GetViewModelSequenceDuration(); //2.0f;
m_bPrimary = true;
m_BeamFireState = FIRE_STARTUP;
m_flNextPrimaryAttack = gpGlobals->curtime + 3.5f; //GetViewModelSequenceDuration();
m_flNextSecondaryAttack = gpGlobals->curtime + 3.5f; //GetViewModelSequenceDuration();
//Msg("Primary True \n");
//DispatchParticleEffect("xelectrical_arc_01_parent", PATTACH_POINT_FOLLOW, pOwner->GetViewModel(), "muzzle", false);
//DispatchParticleEffect("Disp_muzzle_in", PATTACH_POINT_FOLLOW, pOwner->GetViewModel(), "muzzle", false);
}
void CWeapondisplacer::SecondaryAttack( void )
{
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( pOwner == NULL )
return;
if (IsNearWall() || GetOwnerIsRunning())
{
return;
}
if ( m_bShotDelayed )
return;
// Cannot fire underwater
if ( GetOwner() && GetOwner()->GetWaterLevel() == 3 )
{
m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f;
return;
}
//m_flAmmoRemoveDelay = -1;
m_bWeaponBlockWall = true;
isFiring = true;
m_bIsFiring = isFiring;
SendWeaponAnim(ACT_GAUSS_SPINUP);
WeaponSound( SPECIAL2 );
m_bShotDelayed = true;
m_flDelayedFire = gpGlobals->curtime + GetViewModelSequenceDuration(); //2.5f;
m_bSecondary = true;
m_BeamFireState = FIRE_STARTUP;
m_flNextPrimaryAttack = gpGlobals->curtime + 3.5f; //GetViewModelSequenceDuration();
m_flNextSecondaryAttack = gpGlobals->curtime + 3.5f; //GetViewModelSequenceDuration();
SecondaryAttackEffects();
//DispatchParticleEffect("Disp_muzzle_in", PATTACH_POINT_FOLLOW, pOwner->GetViewModel(), "muzzle", false);
//Msg("Secondary True \n");
}
void CWeapondisplacer::ItemPostFrame( void )
{
//if (!isFiring)
if (m_flNextPrimaryAttack < gpGlobals->curtime && m_flNextSecondaryAttack < gpGlobals->curtime)
m_bIsFiring = false;
if ( gpGlobals->curtime < m_flDelayedFire )
{
if (isFiring && GetActivity() != ACT_GAUSS_SPINUP && GetActivity() != ACT_GAUSS_SPINCYCLE)
SendWeaponAnim(ACT_GAUSS_SPINCYCLE);
DelayedAttack();
}
else
{
if (m_bShotDelayed)
{
m_bShotDelayed = false;
DelayedAttack();
}
}
BaseClass::ItemPostFrame();
}
void CWeapondisplacer::DelayedAttack( void )
{
CBasePlayer *pOwner = ToBasePlayer(GetOwner());
if (!pOwner)
return;
CEffectData fireData;
fireData.m_nEntIndex = pOwner->GetViewModel()->entindex();
fireData.m_vOrigin = pOwner->GetViewModel()->GetLocalOrigin();
fireData.m_vAngles = pOwner->GetViewModel()->GetLocalAngles();
fireData.m_nAttachmentIndex = 21;
DispatchEffect("FireEvent", fireData);
//DispatchParticleEffect("Disp_muzzle_root", PATTACH_POINT_FOLLOW, pOwner->GetViewModel(), "muzzle", false);
DispatchParticleEffect(STRING(GetWpnData().iMuzzleFlashDelayed), PATTACH_POINT_FOLLOW, pOwner->GetViewModel(), GetWpnData().iAttachment, false);
if (!m_bShotDelayed && m_bPrimary)
{
FireTheBall();
m_bWeaponBlockWall = false;
m_bPrimary = false;
m_BeamFireState = FIRE_NONE;
//m_bIsFiring = false;
}
if (!m_bShotDelayed && m_bSecondary)
{
m_bSecondary = false;
if ( pOwner->GetAmmoCount( m_iPrimaryAmmoType ) < 60 ) // BriJee: Less than 60 ammo? Disable teleportation
{
WeaponSound( EMPTY );
m_bWeaponBlockWall = false;
//EmitSound(denied)
isFiring = false;
m_bIsFiring = false;
m_BeamFireState = FIRE_NONE;
return;
}
//===============
CBaseEntity *pentTarget = NULL;
// The activator and caller are the same
pentTarget = gEntList.FindEntityByName( pentTarget, /*m_target*/ /*"tp_dark_room"*/ aa_wpn_displacer_target.GetString(), NULL, pOwner, pOwner );
if (!pentTarget)
{
//ClientPrint( pOwner, HUD_PRINTCENTER, "No displacers found" );
WeaponSound(EMPTY);
m_bWeaponBlockWall = false;
m_bSecondary = false;
m_bIsFiring = false;
m_BeamFireState = FIRE_NONE;
return;
}
//ClientPrint( pOwner, HUD_PRINTCENTER, "displacer Found" );
CBaseEntity *pentLandmark = NULL;
Vector vecLandmarkOffset(0, 0, 0);
if (m_iLandmark != NULL_STRING)
{
// The activator and caller are the same
pentLandmark = gEntList.FindEntityByName(pentLandmark, m_iLandmark, NULL, pOwner, pOwner );
if (pentLandmark)
{
vecLandmarkOffset = pOwner->GetAbsOrigin() - pentLandmark->GetAbsOrigin();
}
}
pOwner->SetGroundEntity( NULL );
Vector tmp = pentTarget->GetAbsOrigin();
if (!pentLandmark && pOwner->IsPlayer())
{
// make origin adjustments in case the teleport is a player. (origin in center, not at feet)
tmp.z -= pOwner->WorldAlignMins().z;
}
//
// Only modify the toucher's angles and zero their velocity if no landmark was specified.
//
const QAngle *pAngles = NULL;
Vector *pVelocity = NULL;
if (!pentLandmark && !HasSpawnFlags(0x20) )
{
pAngles = &pentTarget->GetAbsAngles();
pVelocity = NULL; //BUGBUG - This does not set the player's velocity to zero!!!
}
tmp += vecLandmarkOffset;
pOwner->Teleport( &tmp, pAngles, pVelocity );
WeaponSound( SPECIAL3 );
//pOwner->RemoveAmmo( 60, m_iPrimaryAmmoType );
RemoveAmmo(GetPrimaryAmmoType(), 60);
color32 TeleEffect = { 0,255,0,255 };
UTIL_ScreenFade( pOwner, TeleEffect, 0.2f, 0.1f, FFADE_IN );
m_bSecondary = false;
m_bIsFiring = false;
m_bWeaponBlockWall = false;
m_BeamFireState = FIRE_NONE;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeapondisplacer::FireTheBall( void )
{
if ( m_iPrimaryAmmoType <= 0 )
{
WeaponSound( EMPTY );
m_flNextPrimaryAttack = 0.15;
return;
}
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if ( pOwner == NULL )
return;
#ifndef CLIENT_DLL
Vector vecAiming = pOwner->GetAutoaimVector(0);
Vector vecSrc = pOwner->Weapon_ShootPosition();
QAngle angAiming;
VectorAngles(vecAiming, angAiming);
CBasePlayer *pPlayer = ToBasePlayer(GetOwner());
Vector vecThrow;
// Don't autoaim on grenade tosses
AngleVectors(pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow);
VectorScale(vecThrow, 1000.0f, vecThrow);
Vector vForward, vRight, vUp, vThrowPos, vThrowVel;
pPlayer->EyeVectors(&vForward, &vRight, &vUp);
vThrowPos = GetClientTracerVector();
trace_t tr;
UTIL_TraceLine(pOwner->EyePosition(), vThrowPos, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr);
/*vThrowPos = pOwner->Weapon_ShootPosition();
if (cvar->FindVar("oc_state_IRsight_on")->GetInt() == 1)
{
vThrowPos += vForward * 1.0f;
vThrowPos += vRight * 0.05f;// *1.0f;
vThrowPos += vUp * -4.4f;
//DevMsg("ISight enabled \n");
}
else if (cvar->FindVar("oc_state_IRsight_on")->GetInt() == 0)
{
vThrowPos += vForward * 1.0f;
vThrowPos += vRight * 5.4f;
vThrowPos += vUp * -4.4f;
//DevMsg("ISight disabled \n");*/
//}*/
#if defined(HL2_EPISODIC)
// !!!HACK - the other piece of the Alyx crossbow bolt hack for Outland_10 (see ::BoltTouch() for more detail)
if (FStrEq(STRING(gpGlobals->mapname), "ep2_outland_10"))
{
trace_t tr;
UTIL_TraceLine(vecSrc, vecSrc + vecAiming * 24.0f, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr);
if (tr.m_pEnt != NULL && tr.m_pEnt->Classify() == CLASS_PLAYER_ALLY_VITAL)
{
// If Alyx is right in front of the player, make sure the bolt starts outside of the player's BBOX, or the bolt
// will instantly collide with the player after the owner of the bolt is switched to Alyx in ::BoltTouch(). We
// avoid this altogether by making it impossible for the bolt to collide with the player.
vecSrc += vecAiming * 24.0f;
}
}
#endif
//CShockRifleProjectile *pShockRifleProjectile = CShockRifleProjectile::BoltCreate( vecSrc, angAiming, GetSDKWpnData().m_iDamage, pOwner );
CGreenBallProjectile *pGreenBallProjectile = CGreenBallProjectile::BoltCreate(tr.endpos, angAiming, 0, pOwner); // Light Kill : Test
pGreenBallProjectile->SetAbsVelocity(tr.endpos);
if ( pOwner->GetWaterLevel() == 3 ) // BriJee: HURT player if we shoot in water
{
//pShockRifleProjectile->Remove(); //->SetAbsVelocity( vecAiming * BOLT_WATER_VELOCITY );
CTakeDamageInfo hitself(this, this, 210, DMG_SHOCK );
pOwner->TakeDamage(hitself);
}
else
{
pGreenBallProjectile->SetAbsVelocity(vecAiming * BOLT_AIR_VELOCITY);
}
#endif
//m_iClip1--;
//pOwner->RemoveAmmo( 20, m_iPrimaryAmmoType );
RemoveAmmo(GetPrimaryAmmoType(), 20);
float X = -2.f;
if (abs(pPlayer->LocalEyeAngles().x) + abs(X) >= 89.0f)
{
X = X < 0 ? (89.0f - abs(pPlayer->LocalEyeAngles().x)) * -1.f : 89.0f - abs(pPlayer->LocalEyeAngles().x);
}
pOwner->ViewPunch( QAngle( X, 1, -7 ) );
WeaponSound( SINGLE );
//WeaponSound( SPECIAL2 );
isFiring = false;
SendWeaponAnim(GetPrimaryAttackActivity());
pOwner->SetAnimation( PLAYER_ATTACK1 );
/*if ( !m_iClip1 && pOwner->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
{
// HEV suit - indicate out of ammo condition
pOwner->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
}*/
m_flNextPrimaryAttack = gpGlobals->curtime + GetViewModelSequenceDuration();
m_flNextSecondaryAttack = m_flNextPrimaryAttack;
}