summaryrefslogtreecommitdiff
path: root/game/shared/hl1
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/hl1
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/shared/hl1')
-rw-r--r--game/shared/hl1/hl1_basecombatweapon_shared.cpp230
-rw-r--r--game/shared/hl1/hl1_basecombatweapon_shared.h50
-rw-r--r--game/shared/hl1/hl1_gamemovement.cpp305
-rw-r--r--game/shared/hl1/hl1_gamemovement.h42
-rw-r--r--game/shared/hl1/hl1_gamerules.cpp741
-rw-r--r--game/shared/hl1/hl1_gamerules.h65
-rw-r--r--game/shared/hl1/hl1_player_shared.cpp373
-rw-r--r--game/shared/hl1/hl1_player_shared.h53
-rw-r--r--game/shared/hl1/hl1_shareddefs.h20
-rw-r--r--game/shared/hl1/hl1_usermessages.cpp42
-rw-r--r--game/shared/hl1/hl1mp_basecombatweapon_shared.cpp135
-rw-r--r--game/shared/hl1/hl1mp_basecombatweapon_shared.h42
-rw-r--r--game/shared/hl1/hl1mp_gamerules.cpp739
-rw-r--r--game/shared/hl1/hl1mp_gamerules.h91
-rw-r--r--game/shared/hl1/hl1mp_weapon_357.cpp289
-rw-r--r--game/shared/hl1/hl1mp_weapon_crossbow.cpp648
-rw-r--r--game/shared/hl1/hl1mp_weapon_egon.cpp529
-rw-r--r--game/shared/hl1/hl1mp_weapon_gauss.cpp719
-rw-r--r--game/shared/hl1/hl1mp_weapon_glock.cpp205
-rw-r--r--game/shared/hl1/hl1mp_weapon_handgrenade.cpp456
-rw-r--r--game/shared/hl1/hl1mp_weapon_hornetgun.cpp339
-rw-r--r--game/shared/hl1/hl1mp_weapon_mp5.cpp237
-rw-r--r--game/shared/hl1/hl1mp_weapon_mp5.h53
-rw-r--r--game/shared/hl1/hl1mp_weapon_rpg.cpp1080
-rw-r--r--game/shared/hl1/hl1mp_weapon_rpg.h135
-rw-r--r--game/shared/hl1/hl1mp_weapon_sachel.cpp600
-rw-r--r--game/shared/hl1/hl1mp_weapon_satchel.h107
-rw-r--r--game/shared/hl1/hl1mp_weapon_shotgun.cpp417
28 files changed, 8742 insertions, 0 deletions
diff --git a/game/shared/hl1/hl1_basecombatweapon_shared.cpp b/game/shared/hl1/hl1_basecombatweapon_shared.cpp
new file mode 100644
index 0000000..e51b434
--- /dev/null
+++ b/game/shared/hl1/hl1_basecombatweapon_shared.cpp
@@ -0,0 +1,230 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "hl1_basecombatweapon_shared.h"
+
+#include "hl1_player_shared.h"
+
+LINK_ENTITY_TO_CLASS( basehl1combatweapon, CBaseHL1CombatWeapon );
+
+IMPLEMENT_NETWORKCLASS_ALIASED( BaseHL1CombatWeapon , DT_BaseHL1CombatWeapon )
+
+BEGIN_NETWORK_TABLE( CBaseHL1CombatWeapon , DT_BaseHL1CombatWeapon )
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CBaseHL1CombatWeapon )
+END_PREDICTION_DATA()
+
+
+void CBaseHL1CombatWeapon::Spawn( void )
+{
+ Precache();
+
+ SetSolid( SOLID_BBOX );
+ m_flNextEmptySoundTime = 0.0f;
+
+ // Weapons won't show up in trace calls if they are being carried...
+ RemoveEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID );
+
+ m_iState = WEAPON_NOT_CARRIED;
+ // Assume
+ m_nViewModelIndex = 0;
+
+ // If I use clips, set my clips to the default
+ if ( UsesClipsForAmmo1() )
+ {
+ m_iClip1 = GetDefaultClip1();
+ }
+ else
+ {
+ SetPrimaryAmmoCount( GetDefaultClip1() );
+ m_iClip1 = WEAPON_NOCLIP;
+ }
+ if ( UsesClipsForAmmo2() )
+ {
+ m_iClip2 = GetDefaultClip2();
+ }
+ else
+ {
+ SetSecondaryAmmoCount( GetDefaultClip2() );
+ m_iClip2 = WEAPON_NOCLIP;
+ }
+
+ SetModel( GetWorldModel() );
+
+#if !defined( CLIENT_DLL )
+ FallInit();
+ SetCollisionGroup( COLLISION_GROUP_WEAPON );
+
+ m_takedamage = DAMAGE_EVENTS_ONLY;
+
+ SetBlocksLOS( false );
+
+ // Default to non-removeable, because we don't want the
+ // game_weapon_manager entity to remove weapons that have
+ // been hand-placed by level designers. We only want to remove
+ // weapons that have been dropped by NPC's.
+ SetRemoveable( false );
+#endif
+
+ //Make weapons easier to pick up in MP.
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ CollisionProp()->UseTriggerBounds( true, 36 );
+ }
+ else
+ {
+ CollisionProp()->UseTriggerBounds( true, 24 );
+ }
+
+ // Use more efficient bbox culling on the client. Otherwise, it'll setup bones for most
+ // characters even when they're not in the frustum.
+ AddEffects( EF_BONEMERGE_FASTCULL );
+}
+
+#if defined( CLIENT_DLL )
+
+#define HL1_BOB_CYCLE_MIN 1.0f
+#define HL1_BOB_CYCLE_MAX 0.45f
+#define HL1_BOB 0.002f
+#define HL1_BOB_UP 0.5f
+
+float g_lateralBob;
+float g_verticalBob;
+
+static ConVar cl_bobcycle( "cl_bobcycle","0.8" );
+static ConVar cl_bob( "cl_bob","0.002" );
+static ConVar cl_bobup( "cl_bobup","0.5" );
+
+// Register these cvars if needed for easy tweaking
+static ConVar v_iyaw_cycle( "v_iyaw_cycle", "2"/*, FCVAR_UNREGISTERED*/ );
+static ConVar v_iroll_cycle( "v_iroll_cycle", "0.5"/*, FCVAR_UNREGISTERED*/ );
+static ConVar v_ipitch_cycle( "v_ipitch_cycle", "1"/*, FCVAR_UNREGISTERED*/ );
+static ConVar v_iyaw_level( "v_iyaw_level", "0.3"/*, FCVAR_UNREGISTERED*/ );
+static ConVar v_iroll_level( "v_iroll_level", "0.1"/*, FCVAR_UNREGISTERED*/ );
+static ConVar v_ipitch_level( "v_ipitch_level", "0.3"/*, FCVAR_UNREGISTERED*/ );
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : float
+//-----------------------------------------------------------------------------
+float CBaseHL1CombatWeapon::CalcViewmodelBob( void )
+{
+ static float bobtime;
+ static float lastbobtime;
+ float cycle;
+
+ CBasePlayer *player = ToBasePlayer( GetOwner() );
+ //Assert( player );
+
+ //NOTENOTE: For now, let this cycle continue when in the air, because it snaps badly without it
+
+ if ( ( !gpGlobals->frametime ) || ( player == NULL ) )
+ {
+ //NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!)
+ return 0.0f;// just use old value
+ }
+
+ //Find the speed of the player
+ float speed = player->GetLocalVelocity().Length2D();
+
+ //FIXME: This maximum speed value must come from the server.
+ // MaxSpeed() is not sufficient for dealing with sprinting - jdw
+
+ speed = clamp( speed, -320, 320 );
+
+ float bob_offset = RemapVal( speed, 0, 320, 0.0f, 1.0f );
+
+ bobtime += ( gpGlobals->curtime - lastbobtime ) * bob_offset;
+ lastbobtime = gpGlobals->curtime;
+
+ //Calculate the vertical bob
+ cycle = bobtime - (int)(bobtime/HL1_BOB_CYCLE_MAX)*HL1_BOB_CYCLE_MAX;
+ cycle /= HL1_BOB_CYCLE_MAX;
+
+ if ( cycle < HL1_BOB_UP )
+ {
+ cycle = M_PI * cycle / HL1_BOB_UP;
+ }
+ else
+ {
+ cycle = M_PI + M_PI*(cycle-HL1_BOB_UP)/(1.0 - HL1_BOB_UP);
+ }
+
+ g_verticalBob = speed*0.005f;
+ g_verticalBob = g_verticalBob*0.3 + g_verticalBob*0.7*sin(cycle);
+
+ g_verticalBob = clamp( g_verticalBob, -7.0f, 4.0f );
+
+ //Calculate the lateral bob
+ cycle = bobtime - (int)(bobtime/HL1_BOB_CYCLE_MAX*2)*HL1_BOB_CYCLE_MAX*2;
+ cycle /= HL1_BOB_CYCLE_MAX*2;
+
+ if ( cycle < HL1_BOB_UP )
+ {
+ cycle = M_PI * cycle / HL1_BOB_UP;
+ }
+ else
+ {
+ cycle = M_PI + M_PI*(cycle-HL1_BOB_UP)/(1.0 - HL1_BOB_UP);
+ }
+
+ g_lateralBob = speed*0.005f;
+ g_lateralBob = g_lateralBob*0.3 + g_lateralBob*0.7*sin(cycle);
+ g_lateralBob = clamp( g_lateralBob, -7.0f, 4.0f );
+
+ //NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!)
+ return 0.0f;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &origin -
+// &angles -
+// viewmodelindex -
+//-----------------------------------------------------------------------------
+void CBaseHL1CombatWeapon::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles )
+{
+ Vector forward, right;
+ AngleVectors( angles, &forward, &right, NULL );
+
+ CalcViewmodelBob();
+
+ // Apply bob, but scaled down to 40%
+ VectorMA( origin, g_verticalBob * 0.1f, forward, origin );
+
+ // Z bob a bit more
+ origin[2] += g_verticalBob * 0.1f;
+
+ // bob the angles
+ angles[ ROLL ] += g_verticalBob * 0.5f;
+ angles[ PITCH ] -= g_verticalBob * 0.4f;
+
+ angles[ YAW ] -= g_lateralBob * 0.3f;
+
+ VectorMA( origin, g_lateralBob * 0.8f, right, origin );
+}
+
+
+#else
+
+Vector CBaseHL1CombatWeapon::GetSoundEmissionOrigin() const
+{
+ if ( gpGlobals->maxClients == 1 || !GetOwner() )
+ return CBaseCombatWeapon::GetSoundEmissionOrigin();
+
+// Vector vecOwner = GetOwner()->GetSoundEmissionOrigin();
+// Vector vecThis = WorldSpaceCenter();
+// DevMsg("SoundEmissionOrigin: Owner: %4.1f,%4.1f,%4.1f Default:%4.1f,%4.1f,%4.1f\n",
+// vecOwner.x, vecOwner.y, vecOwner.z,
+// vecThis.x, vecThis.y, vecThis.z );
+
+ // TEMP fix for HL1MP... sounds are sometimes beeing emitted underneath the ground
+ return GetOwner()->GetSoundEmissionOrigin();
+}
+
+#endif \ No newline at end of file
diff --git a/game/shared/hl1/hl1_basecombatweapon_shared.h b/game/shared/hl1/hl1_basecombatweapon_shared.h
new file mode 100644
index 0000000..48d209d
--- /dev/null
+++ b/game/shared/hl1/hl1_basecombatweapon_shared.h
@@ -0,0 +1,50 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "basecombatweapon_shared.h"
+
+#ifndef BASEHLCOMBATWEAPON_SHARED_H
+#define BASEHLCOMBATWEAPON_SHARED_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#if defined( CLIENT_DLL )
+#define CBaseHL1CombatWeapon C_BaseHL1CombatWeapon
+#endif
+
+class CBaseHL1CombatWeapon : public CBaseCombatWeapon
+{
+ DECLARE_CLASS( CBaseHL1CombatWeapon, CBaseCombatWeapon );
+public:
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+public:
+ void Spawn( void );
+
+public:
+// Server Only Methods
+#if !defined( CLIENT_DLL )
+ DECLARE_DATADESC();
+
+ virtual void Precache();
+
+ void FallInit( void ); // prepare to fall to the ground
+ virtual void FallThink( void ); // make the weapon fall to the ground after spawning
+
+ void EjectShell( CBaseEntity *pPlayer, int iType );
+
+ Vector GetSoundEmissionOrigin() const;
+#else
+
+ virtual void AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles );
+ virtual float CalcViewmodelBob( void );
+
+#endif
+};
+
+#endif // BASEHLCOMBATWEAPON_SHARED_H
diff --git a/game/shared/hl1/hl1_gamemovement.cpp b/game/shared/hl1/hl1_gamemovement.cpp
new file mode 100644
index 0000000..d968e36
--- /dev/null
+++ b/game/shared/hl1/hl1_gamemovement.cpp
@@ -0,0 +1,305 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+//========= Copyright � 1996-2001, Valve LLC, All rights reserved. ============
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================
+#include "cbase.h"
+#include "gamemovement.h"
+#include "in_buttons.h"
+#include <stdarg.h>
+#include "movevars_shared.h"
+#include "engine/IEngineTrace.h"
+#include "SoundEmitterSystem/isoundemittersystembase.h"
+#include "decals.h"
+#include "tier0/vprof.h"
+#include "hl1_gamemovement.h"
+
+
+// Expose our interface.
+static CHL1GameMovement g_GameMovement;
+IGameMovement *g_pGameMovement = ( IGameMovement * )&g_GameMovement;
+
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CGameMovement, IGameMovement, INTERFACENAME_GAMEMOVEMENT, g_GameMovement );
+
+#ifdef CLIENT_DLL
+#include "hl1/c_hl1mp_player.h"
+#else
+#include "hl1mp_player.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CHL1GameMovement::CheckJumpButton( void )
+{
+ m_pHL1Player = ToHL1Player( player );
+
+ Assert( m_pHL1Player );
+
+ if (m_pHL1Player->pl.deadflag)
+ {
+ mv->m_nOldButtons |= IN_JUMP ; // don't jump again until released
+ return false;
+ }
+
+ // See if we are waterjumping. If so, decrement count and return.
+ if (m_pHL1Player->m_flWaterJumpTime)
+ {
+ m_pHL1Player->m_flWaterJumpTime -= gpGlobals->frametime;
+ if (m_pHL1Player->m_flWaterJumpTime < 0)
+ m_pHL1Player->m_flWaterJumpTime = 0;
+
+ return false;
+ }
+
+ // If we are in the water most of the way...
+ if ( m_pHL1Player->GetWaterLevel() >= 2 )
+ {
+ // swimming, not jumping
+ SetGroundEntity( NULL );
+
+ if(m_pHL1Player->GetWaterType() == CONTENTS_WATER) // We move up a certain amount
+ mv->m_vecVelocity[2] = 100;
+ else if (m_pHL1Player->GetWaterType() == CONTENTS_SLIME)
+ mv->m_vecVelocity[2] = 80;
+
+ // play swiming sound
+ if ( m_pHL1Player->m_flSwimSoundTime <= 0 )
+ {
+ // Don't play sound again for 1 second
+ m_pHL1Player->m_flSwimSoundTime = 1000;
+ PlaySwimSound();
+ }
+
+ return false;
+ }
+
+ // No more effect
+ if (m_pHL1Player->GetGroundEntity() == NULL)
+ {
+ mv->m_nOldButtons |= IN_JUMP;
+ return false; // in air, so no effect
+ }
+
+ if ( mv->m_nOldButtons & IN_JUMP )
+ return false; // don't pogo stick
+
+ // In the air now.
+ SetGroundEntity( NULL );
+
+ m_pHL1Player->PlayStepSound( (Vector &)mv->GetAbsOrigin(), player->GetSurfaceData(), 1.0, true );
+
+ MoveHelper()->PlayerSetAnimation( PLAYER_JUMP );
+
+ float flGroundFactor = 1.0f;
+ if ( player->GetSurfaceData() )
+ {
+ flGroundFactor = 1.0;//player->GetSurfaceData()->game.jumpFactor;
+ }
+
+ // Acclerate upward
+ // If we are ducking...
+ float startz = mv->m_vecVelocity[2];
+ if ( ( m_pHL1Player->m_Local.m_bDucking ) || ( m_pHL1Player->GetFlags() & FL_DUCKING ) )
+ {
+ // d = 0.5 * g * t^2 - distance traveled with linear accel
+ // t = sqrt(2.0 * 45 / g) - how long to fall 45 units
+ // v = g * t - velocity at the end (just invert it to jump up that high)
+ // v = g * sqrt(2.0 * 45 / g )
+ // v^2 = g * g * 2.0 * 45 / g
+ // v = sqrt( g * 2.0 * 45 )
+
+ // Adjust for super long jump module
+ // UNDONE -- note this should be based on forward angles, not current velocity.
+ if ( m_pHL1Player->m_bHasLongJump &&
+ ( mv->m_nButtons & IN_DUCK ) &&
+ ( m_pHL1Player->m_Local.m_flDucktime > 0 ) &&
+ mv->m_vecVelocity.Length() > 50 )
+ {
+ m_pHL1Player->m_Local.m_vecPunchAngle.Set( PITCH, -5 );
+
+ mv->m_vecVelocity = m_vecForward * PLAYER_LONGJUMP_SPEED * 1.6;
+ mv->m_vecVelocity.z = sqrt(2 * 800 * 56.0);
+ }
+ else
+ {
+ mv->m_vecVelocity[2] = flGroundFactor * sqrt(2 * 800 * 45.0); // 2 * gravity * height
+ }
+ }
+ else
+ {
+ mv->m_vecVelocity[2] += flGroundFactor * sqrt(2 * 800 * 45.0); // 2 * gravity * height
+ }
+ FinishGravity();
+
+ mv->m_outWishVel.z += mv->m_vecVelocity[2] - startz;
+ mv->m_outStepHeight += 0.1f;
+
+ if ( gpGlobals->maxClients > 1 )
+#ifdef CLIENT_DLL
+ (dynamic_cast<C_HL1MP_Player*>(m_pHL1Player))->DoAnimationEvent( PLAYERANIMEVENT_JUMP );
+#else
+ (dynamic_cast<CHL1MP_Player*>(m_pHL1Player))->DoAnimationEvent( PLAYERANIMEVENT_JUMP );
+#endif
+
+ // Flag that we jumped.
+ mv->m_nOldButtons |= IN_JUMP; // don't jump again until released
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: See if duck button is pressed and do the appropriate things
+//-----------------------------------------------------------------------------
+void CHL1GameMovement::Duck( void )
+{
+ int buttonsChanged = ( mv->m_nOldButtons ^ mv->m_nButtons ); // These buttons have changed this frame
+ int buttonsPressed = buttonsChanged & mv->m_nButtons; // The changed ones still down are "pressed"
+ int buttonsReleased = buttonsChanged & mv->m_nOldButtons; // The changed ones which were previously down are "released"
+
+ // Check to see if we are in the air.
+ bool bInAir = ( player->GetGroundEntity() == NULL );
+ bool bInDuck = ( player->GetFlags() & FL_DUCKING ) ? true : false;
+
+ if ( mv->m_nButtons & IN_DUCK )
+ {
+ mv->m_nOldButtons |= IN_DUCK;
+ }
+ else
+ {
+ mv->m_nOldButtons &= ~IN_DUCK;
+ }
+
+ // Handle death.
+ if ( IsDead() )
+ {
+ if ( bInDuck )
+ {
+ // Unduck
+ FinishUnDuck();
+ }
+ return;
+ }
+
+ HandleDuckingSpeedCrop();
+
+ // If the player is holding down the duck button, the player is in duck transition, ducking, or duck-jumping.
+ if ( ( mv->m_nButtons & IN_DUCK ) || player->m_Local.m_bDucking || bInDuck )
+ {
+ if ( ( mv->m_nButtons & IN_DUCK ) )
+ {
+ // Have the duck button pressed, but the player currently isn't in the duck position.
+ if ( ( buttonsPressed & IN_DUCK ) && !bInDuck )
+ {
+ // Use 1 second so super long jump will work
+ player->m_Local.m_flDucktime = GAMEMOVEMENT_DUCK_TIME;
+ player->m_Local.m_bDucking = true;
+ }
+
+ // The player is in duck transition and not duck-jumping.
+ if ( player->m_Local.m_bDucking )
+ {
+ float flDuckMilliseconds = MAX( 0.0f, GAMEMOVEMENT_DUCK_TIME - ( float )player->m_Local.m_flDucktime );
+ float flDuckSeconds = flDuckMilliseconds / GAMEMOVEMENT_DUCK_TIME;
+
+ // Finish in duck transition when transition time is over, in "duck", in air.
+ if ( ( flDuckSeconds > TIME_TO_DUCK ) || bInDuck || bInAir )
+ {
+ FinishDuck();
+ }
+ else
+ {
+ // Calc parametric time
+ float flDuckFraction = SimpleSpline( flDuckSeconds / TIME_TO_DUCK );
+ SetDuckedEyeOffset( flDuckFraction );
+ }
+ }
+ }
+ else
+ {
+ // Try to unduck unless automovement is not allowed
+ // NOTE: When not onground, you can always unduck
+ if ( player->m_Local.m_bAllowAutoMovement || bInAir )
+ {
+ if ( ( buttonsReleased & IN_DUCK ) && bInDuck )
+ {
+ // Use 1 second so super long jump will work
+ player->m_Local.m_flDucktime = GAMEMOVEMENT_DUCK_TIME;
+ }
+
+ // Check to see if we are capable of unducking.
+ if ( CanUnduck() )
+ {
+ // or unducking
+ if ( ( player->m_Local.m_bDucking || player->m_Local.m_bDucked ) )
+ {
+ float flDuckMilliseconds = MAX( 0.0f, GAMEMOVEMENT_DUCK_TIME - (float)player->m_Local.m_flDucktime );
+ float flDuckSeconds = flDuckMilliseconds / GAMEMOVEMENT_DUCK_TIME;
+
+ // Finish ducking immediately if duck time is over or not on ground
+ if ( flDuckSeconds > TIME_TO_UNDUCK || ( bInAir ) )
+ {
+ FinishUnDuck();
+ }
+ else
+ {
+ // Calc parametric time
+ float flDuckFraction = SimpleSpline( 1.0f - ( flDuckSeconds / TIME_TO_UNDUCK ) );
+ SetDuckedEyeOffset( flDuckFraction );
+ player->m_Local.m_bDucking = true;
+ }
+ }
+ }
+ else
+ {
+ // Still under something where we can't unduck, so make sure we reset this timer so
+ // that we'll unduck once we exit the tunnel, etc.
+ player->m_Local.m_flDucktime = GAMEMOVEMENT_DUCK_TIME;
+ SetDuckedEyeOffset( 1.0f );
+ }
+ }
+ }
+ }
+}
+
+void CHL1GameMovement::HandleDuckingSpeedCrop()
+{
+ if ( !( m_iSpeedCropped & SPEED_CROPPED_DUCK ) )
+ {
+ if ( player->GetFlags() & FL_DUCKING )
+ {
+ float frac = 0.33333333f;
+ mv->m_flForwardMove *= frac;
+ mv->m_flSideMove *= frac;
+ mv->m_flUpMove *= frac;
+ m_iSpeedCropped |= SPEED_CROPPED_DUCK;
+ }
+ }
+}
+
+void CHL1GameMovement::CheckParameters( void )
+{
+ if ( mv->m_nButtons & IN_SPEED )
+ {
+ mv->m_flClientMaxSpeed = 100;
+ }
+ else
+ {
+ mv->m_flClientMaxSpeed = mv->m_flMaxSpeed;
+ }
+
+ CHL1_Player* pHL1Player = dynamic_cast<CHL1_Player*>(player);
+ if( pHL1Player && pHL1Player->IsPullingObject() )
+ {
+ mv->m_flClientMaxSpeed = mv->m_flMaxSpeed * 0.5f;
+ }
+
+ BaseClass::CheckParameters();
+}
diff --git a/game/shared/hl1/hl1_gamemovement.h b/game/shared/hl1/hl1_gamemovement.h
new file mode 100644
index 0000000..d685c54
--- /dev/null
+++ b/game/shared/hl1/hl1_gamemovement.h
@@ -0,0 +1,42 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef C_HL1_GAMEMOVEMENT_H
+#define C_HL1_GAMEMOVEMENT_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#ifdef CLIENT_DLL
+ #include "hl1/hl1_c_player.h"
+#else
+ #include "hl1_player.h"
+#endif
+
+#if defined( CLIENT_DLL )
+ class CHL1_Player;
+ #define CHL1_Player C_HL1_Player
+#endif
+
+#define PLAYER_LONGJUMP_SPEED 350 // how fast we longjump
+
+class CHL1GameMovement : public CGameMovement
+{
+public:
+ DECLARE_CLASS( CHL1GameMovement, CGameMovement );
+
+ virtual bool CheckJumpButton( void );
+
+ // Duck
+ virtual void Duck( void );
+ virtual void HandleDuckingSpeedCrop();
+ virtual void CheckParameters( void );
+
+protected:
+ CHL1_Player *m_pHL1Player;
+};
+
+#endif //C_HL1_GAMEMOVEMENT_H \ No newline at end of file
diff --git a/game/shared/hl1/hl1_gamerules.cpp b/game/shared/hl1/hl1_gamerules.cpp
new file mode 100644
index 0000000..f9b9ecc
--- /dev/null
+++ b/game/shared/hl1/hl1_gamerules.cpp
@@ -0,0 +1,741 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: The Half-Life 1 game rules, such as the relationship tables and ammo
+// damage cvars.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "hl1_gamerules.h"
+#include "ammodef.h"
+
+
+#ifdef CLIENT_DLL
+
+#else
+
+ #include "player.h"
+ #include "game.h"
+ #include "gamerules.h"
+ #include "teamplay_gamerules.h"
+ #include "hl1_player.h"
+ #include "voice_gamemgr.h"
+ #include "hl1mp_weapon_satchel.h"
+#endif
+
+
+REGISTER_GAMERULES_CLASS( CHalfLife1 );
+
+
+ConVar sk_plr_dmg_crowbar ( "sk_plr_dmg_crowbar", "0", FCVAR_REPLICATED );
+
+ConVar sk_npc_dmg_9mm_bullet ( "sk_npc_dmg_9mm_bullet", "0", FCVAR_REPLICATED );
+ConVar sk_plr_dmg_9mm_bullet ( "sk_plr_dmg_9mm_bullet", "0", FCVAR_REPLICATED );
+ConVar sk_max_9mm_bullet ( "sk_max_9mm_bullet", "0", FCVAR_REPLICATED );
+
+ConVar sk_npc_dmg_9mmAR_bullet ( "sk_npc_dmg_9mmAR_bullet", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_357_bullet ( "sk_plr_dmg_357_bullet", "0", FCVAR_REPLICATED );
+ConVar sk_max_357_bullet ( "sk_max_357_bullet", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_buckshot ( "sk_plr_dmg_buckshot", "0", FCVAR_REPLICATED );
+ConVar sk_max_buckshot ( "sk_max_buckshot", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_mp5_grenade ( "sk_plr_dmg_mp5_grenade", "0", FCVAR_REPLICATED );
+ConVar sk_max_mp5_grenade ( "sk_max_mp5_grenade", "0", FCVAR_REPLICATED );
+ConVar sk_mp5_grenade_radius ( "sk_mp5_grenade_radius", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_rpg ( "sk_plr_dmg_rpg", "0", FCVAR_REPLICATED );
+ConVar sk_max_rpg_rocket ( "sk_max_rpg_rocket", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_xbow_bolt_plr ( "sk_plr_dmg_xbow_bolt_plr", "0", FCVAR_REPLICATED );
+ConVar sk_plr_dmg_xbow_bolt_npc ( "sk_plr_dmg_xbow_bolt_npc", "0", FCVAR_REPLICATED );
+ConVar sk_max_xbow_bolt ( "sk_max_xbow_bolt", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_egon_narrow ( "sk_plr_dmg_egon_narrow", "0", FCVAR_REPLICATED );
+ConVar sk_plr_dmg_egon_wide ( "sk_plr_dmg_egon_wide", "0", FCVAR_REPLICATED );
+ConVar sk_max_uranium ( "sk_max_uranium", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_gauss ( "sk_plr_dmg_gauss", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_grenade ( "sk_plr_dmg_grenade", "0", FCVAR_REPLICATED );
+ConVar sk_max_grenade ( "sk_max_grenade", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_hornet ( "sk_plr_dmg_hornet", "0", FCVAR_REPLICATED );
+ConVar sk_npc_dmg_hornet ( "sk_npc_dmg_hornet", "0", FCVAR_REPLICATED );
+ConVar sk_max_hornet ( "sk_max_hornet", "0", FCVAR_REPLICATED );
+
+ConVar sk_max_snark ( "sk_max_snark", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_tripmine ( "sk_plr_dmg_tripmine", "0", FCVAR_REPLICATED );
+ConVar sk_max_tripmine ( "sk_max_tripmine", "0", FCVAR_REPLICATED );
+
+ConVar sk_plr_dmg_satchel ( "sk_plr_dmg_satchel", "0", FCVAR_REPLICATED );
+ConVar sk_max_satchel ( "sk_max_satchel", "0", FCVAR_REPLICATED );
+
+ConVar sk_npc_dmg_12mm_bullet ( "sk_npc_dmg_12mm_bullet", "0", FCVAR_REPLICATED );
+
+ConVar sk_mp_dmg_multiplier ( "sk_mp_dmg_multiplier", "2.0" );
+
+// Damage Queries.
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CHalfLife1::Damage_GetShowOnHud( void )
+{
+ int iDamage = (DMG_POISON | DMG_ACID | DMG_DISSOLVE/*DMG_FREEZE | DMG_SLOWFREEZE*/ | DMG_DROWN | DMG_BURN | DMG_SLOWBURN | DMG_NERVEGAS | DMG_RADIATION | DMG_SHOCK);
+ return iDamage;
+}
+
+#ifndef CLIENT_DLL
+
+ extern bool g_fGameOver;
+
+ const char *CHalfLife1::GetGameDescription( void )
+ {
+ if ( IsMultiplayer() )
+ {
+ return "Half-Life 1: Deathmatch";
+ }
+ else
+ {
+ return "Half-Life 1";
+ }
+ }
+
+ class CVoiceGameMgrHelper : public IVoiceGameMgrHelper
+ {
+ public:
+ virtual bool CanPlayerHearPlayer( CBasePlayer *pListener, CBasePlayer *pTalker, bool &bProximity )
+ {
+ return true;
+ }
+ };
+ CVoiceGameMgrHelper g_VoiceGameMgrHelper;
+ IVoiceGameMgrHelper *g_pVoiceGameMgrHelper = &g_VoiceGameMgrHelper;
+
+ //-----------------------------------------------------------------------------
+ // Purpose:
+ // Input :
+ // Output :
+ //-----------------------------------------------------------------------------
+ CHalfLife1::CHalfLife1()
+ {
+ }
+
+ //-----------------------------------------------------------------------------
+ // Purpose: called each time a player uses a "cmd" command
+ // Input : *pEdict - the player who issued the command
+ // Use engine.Cmd_Argv, engine.Cmd_Argv, and engine.Cmd_Argc to get
+ // pointers the character string command.
+ //-----------------------------------------------------------------------------
+ bool CHalfLife1::ClientCommand( CBaseEntity *pEdict, const CCommand &args )
+ {
+ if( BaseClass::ClientCommand( pEdict, args ) )
+ return true;
+
+ CHL1_Player *pPlayer = (CHL1_Player *) pEdict;
+
+ if ( pPlayer->ClientCommand( args ) )
+ return true;
+
+ return false;
+ }
+
+ //-----------------------------------------------------------------------------
+ // Purpose: Player has just spawned. Equip them.
+ //-----------------------------------------------------------------------------
+ void CHalfLife1::PlayerSpawn( CBasePlayer *pPlayer )
+ {
+ // pPlayer->EquipSuit();
+ }
+
+
+ //-----------------------------------------------------------------------------
+ // Purpose: MULTIPLAYER BODY QUE HANDLING
+ //-----------------------------------------------------------------------------
+ class CCorpse : public CBaseAnimating
+ {
+ DECLARE_CLASS( CCorpse, CBaseAnimating );
+ public:
+
+ DECLARE_SERVERCLASS();
+
+ virtual int ObjectCaps( void ) { return FCAP_DONT_SAVE; }
+
+ public:
+ CNetworkVar( int, m_nReferencePlayer );
+ };
+
+ IMPLEMENT_SERVERCLASS_ST(CCorpse, DT_Corpse)
+ SendPropInt( SENDINFO(m_nReferencePlayer), 10, SPROP_UNSIGNED )
+ END_SEND_TABLE()
+
+ LINK_ENTITY_TO_CLASS( bodyque, CCorpse );
+
+
+ CCorpse *g_pBodyQueueHead;
+
+ void InitBodyQue(void)
+ {
+ CCorpse *pEntity = ( CCorpse * )CreateEntityByName( "bodyque" );
+ pEntity->AddEFlags( EFL_KEEP_ON_RECREATE_ENTITIES );
+ g_pBodyQueueHead = pEntity;
+ CCorpse *p = g_pBodyQueueHead;
+
+ // Reserve 3 more slots for dead bodies
+ for ( int i = 0; i < 3; i++ )
+ {
+ CCorpse *next = ( CCorpse * )CreateEntityByName( "bodyque" );
+ next->AddEFlags( EFL_KEEP_ON_RECREATE_ENTITIES );
+ p->SetOwnerEntity( next );
+ p = next;
+ }
+
+ p->SetOwnerEntity( g_pBodyQueueHead );
+ }
+
+ //-----------------------------------------------------------------------------
+ // Purpose: make a body que entry for the given ent so the ent can be respawned elsewhere
+ // GLOBALS ASSUMED SET: g_eoBodyQueueHead
+ //-----------------------------------------------------------------------------
+ void CopyToBodyQue( CBaseAnimating *pCorpse )
+ {
+ if ( pCorpse->IsEffectActive( EF_NODRAW ) )
+ return;
+
+ CCorpse *pHead = g_pBodyQueueHead;
+
+ pHead->CopyAnimationDataFrom( pCorpse );
+
+ pHead->SetMoveType( MOVETYPE_FLYGRAVITY );
+ pHead->SetAbsVelocity( pCorpse->GetAbsVelocity() );
+ pHead->ClearFlags();
+ pHead->m_nReferencePlayer = ENTINDEX( pCorpse );
+
+ pHead->SetLocalAngles( pCorpse->GetAbsAngles() );
+ UTIL_SetOrigin(pHead, pCorpse->GetAbsOrigin());
+
+ UTIL_SetSize(pHead, pCorpse->WorldAlignMins(), pCorpse->WorldAlignMaxs());
+ g_pBodyQueueHead = (CCorpse *)pHead->GetOwnerEntity();
+ }
+
+ //------------------------------------------------------------------------------
+ // Purpose : Initialize all default class relationships
+ // Input :
+ // Output :
+ //------------------------------------------------------------------------------
+ void CHalfLife1::InitDefaultAIRelationships( void )
+ {
+ int i, j;
+
+ // Allocate memory for default relationships
+ CBaseCombatCharacter::AllocateDefaultRelationships();
+
+ // --------------------------------------------------------------
+ // First initialize table so we can report missing relationships
+ // --------------------------------------------------------------
+ for (i=0;i<NUM_AI_CLASSES;i++)
+ {
+ for (j=0;j<NUM_AI_CLASSES;j++)
+ {
+ // By default all relationships are neutral of priority zero
+ CBaseCombatCharacter::SetDefaultRelationship( (Class_T)i, (Class_T)j, D_NU, 0 );
+ }
+ }
+
+
+ // ------------------------------------------------------------
+ // > CLASS_NONE
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_PLAYER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_HUMAN_PASSIVE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_PLAYER_ALLY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_ALIEN_PREY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_ALIEN_MONSTER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_ALIEN_PREDATOR, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_HUMAN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_INSECT, D_NU, 0 );
+
+
+ // ------------------------------------------------------------
+ // > CLASS_HUMAN_PASSIVE
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_PLAYER, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_HUMAN_PASSIVE, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_PLAYER_ALLY, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_ALIEN_PREY, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_ALIEN_MILITARY, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_ALIEN_PREDATOR, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_INSECT, D_NU, 0 );
+
+
+
+ // ------------------------------------------------------------
+ // > CLASS_PLAYER
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_PLAYER, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_HUMAN_PASSIVE, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_PLAYER_ALLY, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_ALIEN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_ALIEN_PREDATOR, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_MACHINE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_ALIEN_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_PLAYER_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_PLAYER_ALLY
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_PLAYER, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_HUMAN_PASSIVE, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_PLAYER_ALLY, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_ALIEN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_ALIEN_PREDATOR, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_MACHINE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_ALIEN_PREY
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_ALIEN_PREY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_ALIEN_MONSTER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_ALIEN_PREDATOR, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_ALIEN_MILITARY
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_ALIEN_PREY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_ALIEN_MONSTER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_ALIEN_PREDATOR, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_MACHINE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_ALIEN_MONSTER
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_ALIEN_PREY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_ALIEN_MONSTER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_ALIEN_PREDATOR, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_MACHINE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_ALIEN_PREDATOR
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_ALIEN_MONSTER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_ALIEN_PREDATOR, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_HUMAN_MILITARY
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_ALIEN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_ALIEN_PREDATOR, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_HUMAN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_MACHINE
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_HUMAN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_ALIEN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_ALIEN_PREDATOR, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_ALIEN_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_PLAYER_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_ALIEN_BIOWEAPON
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_ALIEN_MILITARY, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_ALIEN_PREDATOR, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_PLAYER_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_PLAYER_BIOWEAPON
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_ALIEN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_ALIEN_PREDATOR, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_ALIEN_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_INSECT, D_NU, 0 );
+
+
+ // ------------------------------------------------------------
+ // > CLASS_INSECT
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_NONE, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_MACHINE, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_PLAYER, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_HUMAN_PASSIVE, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_HUMAN_MILITARY, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_ALIEN_MONSTER, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_ALIEN_PREY, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_ALIEN_PREDATOR, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_PLAYER_ALLY, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_INSECT, D_NU, 0 );
+ }
+
+ //------------------------------------------------------------------------------
+ // Purpose : Return classify text for classify type
+ // Input :
+ // Output :
+ //------------------------------------------------------------------------------
+ const char* CHalfLife1::AIClassText(int classType)
+ {
+ switch (classType)
+ {
+ case CLASS_NONE: return "CLASS_NONE";
+ case CLASS_HUMAN_PASSIVE: return "CLASS_HUMAN_PASSIVE";
+ case CLASS_PLAYER_ALLY: return "CLASS_PLAYER_ALLY";
+ case CLASS_PLAYER: return "CLASS_PLAYER";
+ case CLASS_ALIEN_PREY: return "CLASS_ALIEN_PREY";
+ case CLASS_ALIEN_MILITARY: return "CLASS_ALIEN_MILITARY";
+ case CLASS_ALIEN_MONSTER: return "CLASS_ALIEN_MONSTER";
+ case CLASS_ALIEN_PREDATOR: return "CLASS_ALIEN_PREDATOR";
+ case CLASS_HUMAN_MILITARY: return "CLASS_HUMAN_MILITARY";
+ case CLASS_MACHINE: return "CLASS_MACHINE";
+ case CLASS_ALIEN_BIOWEAPON: return "CLASS_ALIEN_BIOWEAPON";
+ case CLASS_PLAYER_BIOWEAPON: return "CLASS_PLAYER_BIOWEAPON";
+
+ default: return "MISSING CLASS in ClassifyText()";
+ }
+ }
+
+
+ void CHalfLife1::PlayerThink( CBasePlayer *pPlayer )
+ {
+ }
+
+
+ bool CHalfLife1::CanHavePlayerItem( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon )
+ {
+ if ( FClassnameIs( pWeapon, "weapon_satchel" ) )
+ {
+ CWeaponSatchel *satchel = static_cast< CWeaponSatchel * >( pPlayer->Weapon_OwnsThisType( "weapon_satchel" ) );
+ if ( satchel )
+ {
+ if ( satchel->HasChargeDeployed() )
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+
+ float CHalfLife1::FlPlayerFallDamage( CBasePlayer *pPlayer )
+ {
+ CBaseEntity *pGroundEntity = pPlayer->GetGroundEntity();
+
+ if( pGroundEntity && pGroundEntity->ClassMatches( "func_breakable" ) )
+ {
+ // FIXME touchtrace will be wrong.
+ pGroundEntity->Touch( pPlayer );
+
+ if( pGroundEntity->m_iHealth <= 0 )
+ {
+ // The breakable broke when we hit it, don't take falling damage
+ return 0;
+ }
+ }
+
+ return BaseClass::FlPlayerFallDamage( pPlayer );
+ }
+
+
+ class CTraceFilterHitAllExcept : public CTraceFilter
+ {
+ public:
+ // It does have a base, but we'll never network anything below here..
+ DECLARE_CLASS_NOBASE( CTraceFilterHitAllExcept );
+
+ CTraceFilterHitAllExcept( const IHandleEntity *passedict )
+ {
+ m_pPassEnt = passedict;
+ }
+
+ bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
+ {
+ if ( m_pPassEnt && ( m_pPassEnt == pServerEntity ) )
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private:
+ const IHandleEntity *m_pPassEnt;
+ };
+
+ void CHalfLife1::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore )
+ {
+ CBaseEntity *pEntity = NULL;
+ trace_t tr;
+ float flAdjustedDamage, falloff;
+ Vector vecSpot;
+
+ Vector vecSrc = vecSrcIn;
+
+ if ( flRadius )
+ falloff = info.GetDamage() / flRadius;
+ else
+ falloff = 1.0;
+
+ int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false;
+
+ vecSrc.z += 1;// in case grenade is lying on the ground
+
+ // iterate on all entities in the vicinity.
+ for ( CEntitySphereQuery sphere( vecSrc, flRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() )
+ {
+ if ( pEntity->m_takedamage != DAMAGE_NO )
+ {
+ // UNDONE: this should check a damage mask, not an ignore
+ if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
+ {// houndeyes don't hurt other houndeyes with their attack
+ continue;
+ }
+
+ // blast's don't tavel into or out of water
+ if (bInWater && pEntity->GetWaterLevel() == 0)
+ continue;
+ if (!bInWater && pEntity->GetWaterLevel() == 3)
+ continue;
+
+ // radius damage can only be blocked by the world
+ vecSpot = pEntity->BodyTarget( vecSrc );
+
+ CTraceFilterHitAllExcept traceFilter( info.GetInflictor() );
+ UTIL_TraceLine( vecSrc, vecSpot, CONTENTS_SOLID, &traceFilter, &tr );
+
+ if ( tr.fraction == 1.0 || tr.m_pEnt == pEntity )
+ {// the explosion can 'see' this entity, so hurt them!
+ if (tr.startsolid)
+ {
+ // if we're stuck inside them, fixup the position and distance
+ tr.endpos = vecSrc;
+ tr.fraction = 0.0;
+ }
+
+ // decrease damage for an ent that's farther from the bomb.
+ flAdjustedDamage = ( vecSrc - tr.endpos ).Length() * falloff;
+ flAdjustedDamage = info.GetDamage() - flAdjustedDamage;
+
+ if ( flAdjustedDamage > 0 )
+ {
+ CTakeDamageInfo adjustedInfo = info;
+ adjustedInfo.SetDamage( flAdjustedDamage );
+
+ Vector vecDir = vecSpot - vecSrc;
+ VectorNormalize( vecDir );
+
+ // If we don't have a damage force, manufacture one
+ if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin )
+ {
+ CalculateExplosiveDamageForce( &adjustedInfo, vecDir, vecSrc );
+ }
+ else
+ {
+ // Assume the force passed in is the maximum force. Decay it based on falloff.
+ float flForce = adjustedInfo.GetDamageForce().Length() * falloff;
+ adjustedInfo.SetDamageForce( vecDir * flForce );
+ adjustedInfo.SetDamagePosition( vecSrc );
+ }
+
+ if (tr.fraction != 1.0)
+ {
+ ClearMultiDamage( );
+ Vector dir = tr.endpos - vecSrc;
+ VectorNormalize( dir );
+ pEntity->DispatchTraceAttack( adjustedInfo, dir, &tr );
+ ApplyMultiDamage();
+ }
+ else
+ {
+ pEntity->TakeDamage( adjustedInfo );
+ }
+ // Now hit all triggers along the way that respond to damage...
+ Vector dir = tr.endpos - vecSrc;
+ pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, tr.endpos, dir );
+ }
+ }
+ }
+ }
+ }
+#endif
+
+
+
+// ------------------------------------------------------------------------------------- //
+// CHalfLife1 shared implementation.
+// ------------------------------------------------------------------------------------- //
+
+bool CHalfLife1::ShouldCollide( int collisionGroup0, int collisionGroup1 )
+{
+ // HL2 treats movement and tracing against players the same, so just remap here
+ if ( collisionGroup0 == COLLISION_GROUP_PLAYER_MOVEMENT )
+ {
+ collisionGroup0 = COLLISION_GROUP_PLAYER;
+ }
+
+ if( collisionGroup1 == COLLISION_GROUP_PLAYER_MOVEMENT )
+ {
+ collisionGroup1 = COLLISION_GROUP_PLAYER;
+ }
+
+ if ( collisionGroup0 > collisionGroup1 )
+ {
+ // swap so that lowest is always first
+ int tmp = collisionGroup0;
+ collisionGroup0 = collisionGroup1;
+ collisionGroup1 = tmp;
+ }
+
+ return BaseClass::ShouldCollide( collisionGroup0, collisionGroup1 );
+}
+
+// ------------------------------------------------------------------------------------- //
+// Global functions.
+// ------------------------------------------------------------------------------------- //
+
+// shared ammo definition
+// JAY: Trying to make a more physical bullet response
+#define BULLET_MASS_GRAINS_TO_LB(grains) (0.002285*(grains)/16.0f)
+#define BULLET_MASS_GRAINS_TO_KG(grains) lbs2kg(BULLET_MASS_GRAINS_TO_LB(grains))
+
+// exaggerate all of the forces, but use real numbers to keep them consistent
+#define BULLET_IMPULSE_EXAGGERATION 3
+
+// convert a velocity in ft/sec and a mass in grains to an impulse in kg in/s
+#define BULLET_IMPULSE(grains, ftpersec) ((ftpersec)*12*BULLET_MASS_GRAINS_TO_KG(grains)*BULLET_IMPULSE_EXAGGERATION)
+
+CAmmoDef *GetAmmoDef()
+{
+ static CAmmoDef def;
+ static bool bInitted = false;
+
+ if ( !bInitted )
+ {
+ bInitted = true;
+
+ def.AddAmmoType( "9mmRound", DMG_BULLET | DMG_NEVERGIB, TRACER_LINE, "sk_plr_dmg_9mm_bullet", "sk_npc_dmg_9mm_bullet","sk_max_9mm_bullet", BULLET_IMPULSE(500, 1325), 0 );
+ def.AddAmmoType( "357Round", DMG_BULLET | DMG_NEVERGIB, TRACER_NONE, "sk_plr_dmg_357_bullet", NULL, "sk_max_357_bullet", BULLET_IMPULSE(650, 6000), 0 );
+ def.AddAmmoType( "Buckshot", DMG_BULLET | DMG_BUCKSHOT, TRACER_LINE, "sk_plr_dmg_buckshot", NULL, "sk_max_buckshot", BULLET_IMPULSE(200, 1200), 0 );
+ def.AddAmmoType( "XBowBolt", DMG_BULLET | DMG_NEVERGIB, TRACER_LINE, "sk_plr_dmg_xbow_bolt_plr",NULL, "sk_max_xbow_bolt", BULLET_IMPULSE( 200, 1200), 0 );
+ def.AddAmmoType( "MP5_Grenade", DMG_BURN | DMG_BLAST, TRACER_NONE, "sk_plr_dmg_mp5_grenade", NULL, "sk_max_mp5_grenade", 0, 0 );
+ def.AddAmmoType( "RPG_Rocket", DMG_BURN | DMG_BLAST, TRACER_NONE, "sk_plr_dmg_rpg", NULL, "sk_max_rpg_rocket", 0, 0 );
+ def.AddAmmoType( "Uranium", DMG_ENERGYBEAM, TRACER_NONE, NULL, NULL, "sk_max_uranium", 0, 0 );
+ def.AddAmmoType( "Grenade", DMG_BURN | DMG_BLAST, TRACER_NONE, "sk_plr_dmg_grenade", NULL, "sk_max_grenade", 0, 0 );
+ def.AddAmmoType( "Hornet", DMG_BULLET, TRACER_NONE, "sk_plr_dmg_hornet", "sk_npc_dmg_hornet", "sk_max_hornet", BULLET_IMPULSE(100, 1200), 0 );
+ def.AddAmmoType( "Snark", DMG_SLASH, TRACER_NONE, "sk_snark_dmg_bite", NULL, "sk_max_snark", 0, 0 );
+ def.AddAmmoType( "TripMine", DMG_BURN | DMG_BLAST, TRACER_NONE, "sk_plr_dmg_tripmine", NULL, "sk_max_tripmine", 0, 0 );
+ def.AddAmmoType( "Satchel", DMG_BURN | DMG_BLAST, TRACER_NONE, "sk_plr_dmg_satchel", NULL, "sk_max_satchel", 0, 0 );
+
+ def.AddAmmoType( "12mmRound", DMG_BULLET | DMG_NEVERGIB, TRACER_LINE, NULL, "sk_npc_dmg_12mm_bullet",NULL, BULLET_IMPULSE(300, 1200), 0 );
+
+ def.AddAmmoType( "Gravity", DMG_CRUSH, TRACER_NONE, 0, 0, 8, 0, 0 );
+ }
+
+ return &def;
+}
diff --git a/game/shared/hl1/hl1_gamerules.h b/game/shared/hl1/hl1_gamerules.h
new file mode 100644
index 0000000..a31f688
--- /dev/null
+++ b/game/shared/hl1/hl1_gamerules.h
@@ -0,0 +1,65 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: The HL2 Game rules object
+//
+// $Workfile: $
+// $Date: $
+//
+//-----------------------------------------------------------------------------
+// $Log: $
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef HL1_GAMERULES_H
+#define HL1_GAMERULES_H
+#pragma once
+
+#include "gamerules.h"
+#include "singleplay_gamerules.h"
+
+
+#ifdef CLIENT_DLL
+ #define CHalfLife1 C_HalfLife1
+#endif
+
+
+class CHalfLife1 : public CSingleplayRules
+{
+public:
+
+ DECLARE_CLASS( CHalfLife1, CSingleplayRules );
+
+ // Damage Queries.
+ virtual int Damage_GetShowOnHud( void );
+
+ // Client/server shared implementation.
+ virtual bool ShouldCollide( int collisionGroup0, int collisionGroup1 );
+
+
+#ifndef CLIENT_DLL
+
+ CHalfLife1();
+ virtual ~CHalfLife1() {}
+
+ virtual bool ClientCommand( CBaseEntity *pEdict, const CCommand &args );
+ virtual void PlayerSpawn( CBasePlayer *pPlayer );
+
+ virtual void InitDefaultAIRelationships( void );
+ virtual const char * AIClassText(int classType);
+ virtual const char * GetGameDescription( void );
+ virtual float FlPlayerFallDamage( CBasePlayer *pPlayer );
+
+ // Ammo
+ virtual void PlayerThink( CBasePlayer *pPlayer );
+ bool CanHavePlayerItem( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon );
+
+ void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore );
+
+ int DefaultFOV( void ) { return 90; }
+
+#endif
+
+};
+
+#endif // HL1_GAMERULES_H
diff --git a/game/shared/hl1/hl1_player_shared.cpp b/game/shared/hl1/hl1_player_shared.cpp
new file mode 100644
index 0000000..2d74018
--- /dev/null
+++ b/game/shared/hl1/hl1_player_shared.cpp
@@ -0,0 +1,373 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#include "cbase.h"
+#include "tier0/vprof.h"
+
+#ifdef CLIENT_DLL
+#include "hl1_player_shared.h"
+#include "hl1/c_hl1mp_player.h"
+//#define CRecipientFilter C_RecipientFilter
+#else
+#include "hl1mp_player.h"
+#endif
+
+// When moving this fast, he plays run anim.
+#define ARBITRARY_RUN_SPEED 175.0f
+
+#define MAX_STANDING_RUN_SPEED 320
+#define MAX_CROUCHED_RUN_SPEED 110
+
+
+// ------------------------------------------------------------------------------------------------ //
+// CPlayerAnimState declaration.
+// ------------------------------------------------------------------------------------------------ //
+
+class CPlayerAnimState : public IHL1MPPlayerAnimState, public CBasePlayerAnimState
+{
+public:
+
+ DECLARE_CLASS( CPlayerAnimState, CBasePlayerAnimState );
+
+ CPlayerAnimState();
+ void Init( CHL1MP_Player *pPlayer );
+
+ // This is called by both the client and the server in the same way to trigger events for
+ // players firing, jumping, throwing grenades, etc.
+ virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData );
+ virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle );
+ virtual float SetOuterBodyYaw( float flValue );
+ virtual Activity CalcMainActivity();
+ virtual float GetCurrentMaxGroundSpeed();
+ virtual void ClearAnimationState();
+ virtual bool ShouldUpdateAnimState();
+ virtual int SelectWeightedSequence( Activity activity ) ;
+
+ float CalcMovementPlaybackRate( bool *bIsMoving );
+
+ virtual void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr );
+
+
+private:
+
+ const char* GetWeaponSuffix();
+ bool HandleJumping();
+ bool HandleDeath( Activity *deathActivity );
+
+
+private:
+
+ CHL1MP_Player *m_pOuter;
+
+ bool m_bJumping;
+ bool m_bFirstJumpFrame;
+ float m_flJumpStartTime;
+
+ bool m_bFiring;
+ float m_flFireStartTime;
+
+ bool m_bDying;
+ Activity m_DeathActivity;
+};
+
+
+IHL1MPPlayerAnimState* CreatePlayerAnimState( CHL1MP_Player *pPlayer )
+{
+ CPlayerAnimState *pRet = new CPlayerAnimState;
+ pRet->Init( pPlayer );
+ return pRet;
+}
+
+
+// ----------------------------------------------------------------------------- //
+// CPlayerAnimState implementation.
+// ----------------------------------------------------------------------------- //
+
+CPlayerAnimState::CPlayerAnimState()
+{
+ m_pOuter = NULL;
+ m_bJumping = false;
+ m_bFirstJumpFrame = false;
+ m_bFiring = false;
+}
+
+
+void CPlayerAnimState::Init( CHL1MP_Player *pPlayer )
+{
+ m_pOuter = pPlayer;
+
+ CModAnimConfig config;
+ config.m_flMaxBodyYawDegrees = 90;
+ config.m_LegAnimType = LEGANIM_GOLDSRC;
+ config.m_bUseAimSequences = true;
+
+ BaseClass::Init( pPlayer, config );
+}
+
+
+const char* CPlayerAnimState::GetWeaponSuffix()
+{
+ CBaseCombatWeapon *pWeapon = m_pOuter->GetActiveWeapon();
+ if ( pWeapon )
+ return pWeapon->GetWpnData().szAnimationPrefix;
+ else
+ return "shotgun";
+}
+
+
+int CPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle )
+{
+ const char *pWeaponSuffix = GetWeaponSuffix();
+ if ( !pWeaponSuffix )
+ return 0;
+
+ if ( strcmp( pWeaponSuffix, "glock" ) == 0 )
+ pWeaponSuffix = "onehanded";
+
+ // Are we aiming or firing?
+ const char *pAimOrShoot = "aim";
+ if ( m_bFiring )
+ pAimOrShoot = "shoot";
+
+ // Are we standing or crouching?
+ int iSequence = 0;
+ const char *pPrefix = "ref";
+ if ( m_bDying )
+ {
+ // While dying, only play the main sequence.. don't layer this one on top.
+ *flAimSequenceWeight = 0;
+ }
+ else
+ {
+ switch ( GetCurrentMainSequenceActivity() )
+ {
+ case ACT_CROUCHIDLE:
+ case ACT_RUN_CROUCH:
+ pPrefix = "crouch";
+ break;
+ }
+ }
+
+ iSequence = CalcSequenceIndex( "%s_%s_%s", pPrefix, pAimOrShoot, pWeaponSuffix );
+
+ // Check if we're done firing.
+ if ( m_bFiring )
+ {
+ float dur = m_pOuter->SequenceDuration( iSequence );
+ *flCycle = (gpGlobals->curtime - m_flFireStartTime) / dur;
+ if ( *flCycle >= 1 )
+ {
+ *flCycle = 1;
+ m_bFiring = false;
+ }
+ }
+
+ return iSequence;
+}
+
+
+void CPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
+{
+ if ( event == PLAYERANIMEVENT_JUMP )
+ {
+ // Main animation goes to ACT_HOP.
+ m_bJumping = true;
+ m_bFirstJumpFrame = true;
+ m_flJumpStartTime = gpGlobals->curtime;
+ }
+ else if ( event == PLAYERANIMEVENT_FIRE_GUN )
+ {
+ // The middle part of the aim layer sequence becomes "shoot" until that animation is complete.
+ m_bFiring = true;
+ m_flFireStartTime = gpGlobals->curtime;
+ }
+}
+
+
+float CPlayerAnimState::SetOuterBodyYaw( float flValue )
+{
+// m_pOuter->SetBoneController( 0, flValue );
+
+ float fAcc = flValue / 4;
+
+ for ( int i = 0; i < 4; i++ )
+ {
+ m_pOuter->SetBoneController( i, fAcc );
+ }
+
+ return flValue;
+}
+
+
+bool CPlayerAnimState::HandleJumping()
+{
+ if ( m_bJumping )
+ {
+ if ( m_bFirstJumpFrame )
+ {
+ m_bFirstJumpFrame = false;
+ RestartMainSequence(); // Reset the animation.
+ }
+
+ // Don't check if he's on the ground for a sec.. sometimes the client still has the
+ // on-ground flag set right when the message comes in.
+ if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f )
+ {
+ if ( m_pOuter->GetFlags() & FL_ONGROUND )
+ {
+ m_bJumping = false;
+ RestartMainSequence(); // Reset the animation.
+ }
+ }
+ }
+
+ // Are we still jumping? If so, keep playing the jump animation.
+ return m_bJumping;
+}
+
+int CPlayerAnimState::SelectWeightedSequence( Activity activity )
+{
+ return m_pOuter->m_iRealSequence;
+}
+
+bool CPlayerAnimState::HandleDeath( Activity *deathActivity )
+{
+ if ( m_bDying )
+ {
+ if ( m_pOuter->IsAlive() )
+ {
+ m_bDying = false;
+ }
+ else
+ {
+ *deathActivity = m_DeathActivity;
+ }
+ }
+ return m_bDying;
+}
+
+
+Activity CPlayerAnimState::CalcMainActivity()
+{
+ Activity deathActivity = ACT_IDLE;
+ if ( HandleDeath( &deathActivity ) )
+ {
+ return deathActivity;
+ }
+ else if ( HandleJumping() )
+ {
+ return ACT_HOP;
+ }
+ else
+ {
+ Activity idealActivity = ACT_IDLE;
+ float flOuterSpeed = GetOuterXYSpeed();
+
+ if ( m_pOuter->GetFlags() & FL_DUCKING )
+ {
+ if ( flOuterSpeed > 0.1f )
+ idealActivity = ACT_RUN_CROUCH;
+ else
+ idealActivity = ACT_CROUCHIDLE;
+ }
+ else
+ {
+ if ( flOuterSpeed > 0.1f )
+ {
+ if ( flOuterSpeed > ARBITRARY_RUN_SPEED )
+ idealActivity = ACT_RUN;
+ else
+ idealActivity = ACT_WALK;
+ }
+ else
+ {
+ idealActivity = ACT_IDLE;
+ }
+ }
+
+ return idealActivity ;
+ }
+}
+
+
+float CPlayerAnimState::GetCurrentMaxGroundSpeed()
+{
+ Activity act = GetCurrentMainSequenceActivity();
+ if ( act == ACT_CROUCHIDLE || act == ACT_RUN_CROUCH )
+ return MAX_CROUCHED_RUN_SPEED;
+ else
+ return MAX_STANDING_RUN_SPEED;
+}
+
+
+void CPlayerAnimState::ClearAnimationState()
+{
+ m_bJumping = false;
+ m_bFiring = false;
+ m_bDying = false;
+
+ BaseClass::ClearAnimationState();
+}
+
+
+bool CPlayerAnimState::ShouldUpdateAnimState()
+{
+ return true;
+}
+
+float CPlayerAnimState::CalcMovementPlaybackRate( bool *bIsMoving )
+{
+ // Determine ideal playback rate
+ Vector vel;
+ GetOuterAbsVelocity( vel );
+
+ float flReturnValue = BaseClass::CalcMovementPlaybackRate( bIsMoving );
+
+ Activity eActivity = GetOuter()->GetSequenceActivity( GetOuter()->GetSequence() ) ;
+
+ if ( eActivity == ACT_RUN || eActivity == ACT_WALK || eActivity == ACT_CROUCH )
+ {
+ VectorNormalize( vel );
+
+ Vector vForward;
+ AngleVectors( GetOuter()->EyeAngles(), &vForward );
+
+ float flDot = DotProduct( vel, vForward );
+
+ if ( flDot < 0 )
+ {
+ flReturnValue *= -1;
+ }
+ }
+
+ return flReturnValue;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CPlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr )
+{
+ VPROF( "CBasePlayerAnimState::ComputePoseParam_BodyPitch" );
+
+ // Get pitch from v_angle
+ float flPitch = -m_flEyePitch;
+ if ( flPitch > 180.0f )
+ {
+ flPitch -= 360.0f;
+ }
+ flPitch = clamp( flPitch, -50, 45 );
+
+ // See if we have a blender for pitch
+ int pitch = GetOuter()->LookupPoseParameter( pStudioHdr, "XR" );
+ if ( pitch < 0 )
+ return;
+
+ GetOuter()->SetPoseParameter( pStudioHdr, pitch, flPitch );
+ g_flLastBodyPitch = flPitch;
+}
+
diff --git a/game/shared/hl1/hl1_player_shared.h b/game/shared/hl1/hl1_player_shared.h
new file mode 100644
index 0000000..5536637
--- /dev/null
+++ b/game/shared/hl1/hl1_player_shared.h
@@ -0,0 +1,53 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef HL1_PLAYER_SHARED_H
+#define HL1_PLAYER_SHARED_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "cbase.h"
+#include "base_playeranimstate.h"
+
+// Shared header file for players
+#if defined( CLIENT_DLL )
+//#define CHL1_Player C_BaseHLPlayer //FIXME: Lovely naming job between server and client here...
+class C_HL1MP_Player;
+#define CHL1MP_Player C_HL1MP_Player
+#else
+//#include "hl1_player.h"
+class CHL1MP_Player;
+#endif
+
+#include "studio.h"
+
+enum PlayerAnimEvent_t
+{
+ PLAYERANIMEVENT_FIRE_GUN=0,
+ PLAYERANIMEVENT_THROW_GRENADE,
+ PLAYERANIMEVENT_JUMP,
+ PLAYERANIMEVENT_RELOAD,
+ PLAYERANIMEVENT_DIE,
+
+ PLAYERANIMEVENT_COUNT
+};
+
+class IHL1MPPlayerAnimState : virtual public IPlayerAnimState
+{
+public:
+ // This is called by both the client and the server in the same way to trigger events for
+ // players firing, jumping, throwing grenades, etc.
+ virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData ) = 0;
+};
+
+IHL1MPPlayerAnimState* CreatePlayerAnimState( CHL1MP_Player *pPlayer );
+
+// If this is set, then the game code needs to make sure to send player animation events
+// to the local player if he's the one being watched.
+extern ConVar cl_showanimstate;
+
+#endif // HL1_PLAYER_SHARED_H
diff --git a/game/shared/hl1/hl1_shareddefs.h b/game/shared/hl1/hl1_shareddefs.h
new file mode 100644
index 0000000..4285bfe
--- /dev/null
+++ b/game/shared/hl1/hl1_shareddefs.h
@@ -0,0 +1,20 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef HL1_SHAREDDEFS_H
+#define HL1_SHAREDDEFS_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+//--------------
+// HL1 SPECIFIC
+//--------------
+#define DMG_MISSILEDEFENSE (DMG_LASTGENERICFLAG<<2) // The only kind of damage missiles take. (special missile defense)
+
+
+#endif // HL1_SHAREDDEFS_H
diff --git a/game/shared/hl1/hl1_usermessages.cpp b/game/shared/hl1/hl1_usermessages.cpp
new file mode 100644
index 0000000..75744c2
--- /dev/null
+++ b/game/shared/hl1/hl1_usermessages.cpp
@@ -0,0 +1,42 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "usermessages.h"
+#include "shake.h"
+#include "voice_gamemgr.h"
+// NVNT include to register in haptic user messages
+#include "haptics/haptic_msgs.h"
+
+void RegisterUserMessages( void )
+{
+ usermessages->Register( "Geiger", 1 );
+ usermessages->Register( "Train", 1 );
+ usermessages->Register( "HudText", -1 );
+ usermessages->Register( "SayText", -1 );
+ usermessages->Register( "SayText2", -1 );
+ usermessages->Register( "TextMsg", -1 );
+ usermessages->Register( "HudMsg", -1 );
+ usermessages->Register( "ResetHUD", 1 ); // called every respawn
+ usermessages->Register( "GameTitle", 0 );
+ usermessages->Register( "ItemPickup", -1 );
+ usermessages->Register( "ShowMenu", -1 );
+ usermessages->Register( "Shake", 13 );
+ usermessages->Register( "Fade", 10 );
+ usermessages->Register( "VGUIMenu", -1 ); // Show VGUI menu
+ usermessages->Register( "Rumble", 3 ); // Send a rumble to a controller
+ usermessages->Register( "Battery", 2 );
+ usermessages->Register( "Damage", 18 );
+ usermessages->Register( "VoiceMask", VOICE_MAX_PLAYERS_DW*4 * 2 + 1 );
+ usermessages->Register( "RequestState", 0 );
+ usermessages->Register( "CloseCaption", -1 ); // Show a caption (by string id number)(duration in 10th of a second)
+ usermessages->Register( "HintText", -1 ); // Displays hint text display
+ usermessages->Register( "KeyHintText", -1 ); // Displays hint text display
+ usermessages->Register( "AmmoDenied", 2 );
+
+ // NVNT register haptic user messages
+ RegisterHapticMessages();
+} \ No newline at end of file
diff --git a/game/shared/hl1/hl1mp_basecombatweapon_shared.cpp b/game/shared/hl1/hl1mp_basecombatweapon_shared.cpp
new file mode 100644
index 0000000..fe31f64
--- /dev/null
+++ b/game/shared/hl1/hl1mp_basecombatweapon_shared.cpp
@@ -0,0 +1,135 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "hl1mp_basecombatweapon_shared.h"
+
+#include "effect_dispatch_data.h"
+
+#ifdef CLIENT_DLL
+ #include "c_te_effect_dispatch.h"
+#else
+ #include "te_effect_dispatch.h"
+#endif
+
+#include "hl1_player_shared.h"
+
+LINK_ENTITY_TO_CLASS( basehl1mpcombatweapon, CBaseHL1MPCombatWeapon );
+
+IMPLEMENT_NETWORKCLASS_ALIASED( BaseHL1MPCombatWeapon , DT_BaseHL1MPCombatWeapon )
+
+BEGIN_NETWORK_TABLE( CBaseHL1MPCombatWeapon , DT_BaseHL1MPCombatWeapon )
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CBaseHL1MPCombatWeapon )
+END_PREDICTION_DATA()
+
+
+CBaseHL1MPCombatWeapon::CBaseHL1MPCombatWeapon()
+{
+ SetPredictionEligible( true );
+ AddSolidFlags( FSOLID_TRIGGER ); // Nothing collides with these but it gets touches.
+}
+
+
+void CBaseHL1MPCombatWeapon::EjectShell( CBaseEntity *pPlayer, int iType )
+{
+ QAngle angShellAngles = pPlayer->GetAbsAngles();
+
+ Vector vecForward, vecRight, vecUp;
+ AngleVectors( angShellAngles, &vecForward, &vecRight, &vecUp );
+
+ Vector vecShellPosition = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset();
+ switch ( iType )
+ {
+ case 0:
+ default:
+ vecShellPosition += vecRight * 4;
+ vecShellPosition += vecUp * -12;
+ vecShellPosition += vecForward * 20;
+ break;
+ case 1:
+ vecShellPosition += vecRight * 6;
+ vecShellPosition += vecUp * -12;
+ vecShellPosition += vecForward * 32;
+ break;
+ }
+
+ Vector vecShellVelocity = vec3_origin; // pPlayer->GetAbsVelocity();
+ vecShellVelocity += vecRight * random->RandomFloat( 50, 70 );
+ vecShellVelocity += vecUp * random->RandomFloat( 100, 150 );
+ vecShellVelocity += vecForward * 25;
+
+ angShellAngles.x = 0;
+ angShellAngles.z = 0;
+
+ CEffectData data;
+ data.m_vStart = vecShellVelocity;
+ data.m_vOrigin = vecShellPosition;
+ data.m_vAngles = angShellAngles;
+ data.m_fFlags = iType;
+
+ DispatchEffect( "HL1ShellEject", data );
+}
+
+
+#ifdef CLIENT_DLL
+
+void CBaseHL1MPCombatWeapon::OnDataChanged( DataUpdateType_t type )
+{
+ BaseClass::OnDataChanged( type );
+
+ if ( GetPredictable() && !ShouldPredict() )
+ ShutdownPredictable();
+}
+
+
+bool CBaseHL1MPCombatWeapon::ShouldPredict()
+{
+ if ( GetOwner() && GetOwner() == C_BasePlayer::GetLocalPlayer() )
+ return true;
+
+ return BaseClass::ShouldPredict();
+}
+
+
+void CBaseHL1MPCombatWeapon::ApplyBoneMatrixTransform( matrix3x4_t& transform )
+{
+ BaseClass::ApplyBoneMatrixTransform( transform );
+}
+
+#endif
+
+
+bool CBaseHL1MPCombatWeapon::IsPredicted() const
+{
+ return true;
+}
+
+
+CBasePlayer* CBaseHL1MPCombatWeapon::GetPlayerOwner() const
+{
+ return dynamic_cast< CBasePlayer* >( GetOwner() );
+}
+
+
+void CBaseHL1MPCombatWeapon::WeaponSound( WeaponSound_t sound_type, float soundtime /* = 0.0f */ )
+{
+#ifdef CLIENT_DLL
+ // If we have some sounds from the weapon classname.txt file, play a random one of them
+ const char *shootsound = GetWpnData().aShootSounds[ sound_type ];
+ if ( !shootsound || !shootsound[0] )
+ return;
+
+ CBroadcastRecipientFilter filter; // this is client side only
+ if ( !te->CanPredict() )
+ return;
+
+ CBaseEntity::EmitSound( filter, GetPlayerOwner()->entindex(), shootsound, &GetPlayerOwner()->GetAbsOrigin() );
+#else
+ BaseClass::WeaponSound( sound_type, soundtime );
+#endif
+}
diff --git a/game/shared/hl1/hl1mp_basecombatweapon_shared.h b/game/shared/hl1/hl1mp_basecombatweapon_shared.h
new file mode 100644
index 0000000..3e417a7
--- /dev/null
+++ b/game/shared/hl1/hl1mp_basecombatweapon_shared.h
@@ -0,0 +1,42 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+#include "hl1_basecombatweapon_shared.h"
+
+#ifndef BASEHL1MPCOMBATWEAPON_SHARED_H
+#define BASEHL1MPCOMBATWEAPON_SHARED_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#if defined( CLIENT_DLL )
+#define CBaseHL1MPCombatWeapon C_BaseHL1MPCombatWeapon
+#endif
+
+
+class CBaseHL1MPCombatWeapon : public CBaseHL1CombatWeapon
+{
+ DECLARE_CLASS( CBaseHL1MPCombatWeapon, CBaseHL1CombatWeapon );
+public :
+ CBaseHL1MPCombatWeapon();
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+public :
+ void EjectShell( CBaseEntity *pPlayer, int iType );
+
+ CBasePlayer* GetPlayerOwner() const;
+ virtual void WeaponSound( WeaponSound_t sound_type, float soundtime = 0.0f );
+
+#ifdef CLIENT_DLL
+ void OnDataChanged( DataUpdateType_t type );
+ bool ShouldPredict();
+
+ void ApplyBoneMatrixTransform( matrix3x4_t& transform );
+#endif
+ bool IsPredicted() const;
+
+};
+
+
+#endif // #ifndef BASEHL1MPCOMBATWEAPON_SHARED_H \ No newline at end of file
diff --git a/game/shared/hl1/hl1mp_gamerules.cpp b/game/shared/hl1/hl1mp_gamerules.cpp
new file mode 100644
index 0000000..84c76d6
--- /dev/null
+++ b/game/shared/hl1/hl1mp_gamerules.cpp
@@ -0,0 +1,739 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+#include "cbase.h"
+#include "hl1mp_gamerules.h"
+#include "viewport_panel_names.h"
+#include "gameeventdefs.h"
+#include <KeyValues.h>
+#include "ammodef.h"
+
+#ifdef CLIENT_DLL
+
+#include "hl1/c_hl1mp_player.h"
+
+#else
+
+#include "eventqueue.h"
+#include "player.h"
+#include "gamerules.h"
+#include "game.h"
+#include "items.h"
+#include "entitylist.h"
+#include "in_buttons.h"
+#include <ctype.h>
+#include "voice_gamemgr.h"
+#include "iscorer.h"
+#include "hl1mp_player.h"
+#include "team.h"
+#include "voice_gamemgr.h"
+
+#ifdef DEBUG
+#include "hl1mp_bot_temp.h"
+#endif
+
+ConVar sv_hl1mp_weapon_respawn_time( "sv_hl1mp_weapon_respawn_time", "20", FCVAR_GAMEDLL | FCVAR_NOTIFY );
+ConVar sv_hl1mp_item_respawn_time( "sv_hl1mp_item_respawn_time", "30", FCVAR_GAMEDLL | FCVAR_NOTIFY );
+
+
+extern ConVar mp_chattime;
+
+extern CBaseEntity *g_pLastCombineSpawn;
+extern CBaseEntity *g_pLastRebelSpawn;
+
+//#define WEAPON_MAX_DISTANCE_FROM_SPAWN 64
+
+#endif
+
+
+REGISTER_GAMERULES_CLASS( CHL1MPRules );
+
+BEGIN_NETWORK_TABLE_NOBASE( CHL1MPRules, DT_HL1MPRules )
+
+ #ifdef CLIENT_DLL
+ RecvPropBool( RECVINFO( m_bTeamPlayEnabled ) ),
+ #else
+ SendPropBool( SENDINFO( m_bTeamPlayEnabled ) ),
+ #endif
+
+END_NETWORK_TABLE()
+
+
+LINK_ENTITY_TO_CLASS( hl1mp_gamerules, CHL1MPGameRulesProxy );
+IMPLEMENT_NETWORKCLASS_ALIASED( HL1MPGameRulesProxy, DT_HL1MPGameRulesProxy )
+
+
+#ifdef CLIENT_DLL
+ void RecvProxy_HL1MPRules( const RecvProp *pProp, void **pOut, void *pData, int objectID )
+ {
+ CHL1MPRules *pRules = HL1MPRules();
+ Assert( pRules );
+ *pOut = pRules;
+ }
+
+ BEGIN_RECV_TABLE( CHL1MPGameRulesProxy, DT_HL1MPGameRulesProxy )
+ RecvPropDataTable( "hl1mp_gamerules_data", 0, 0, &REFERENCE_RECV_TABLE( DT_HL1MPRules ), RecvProxy_HL1MPRules )
+ END_RECV_TABLE()
+#else
+ void* SendProxy_HL1MPRules( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID )
+ {
+ CHL1MPRules *pRules = HL1MPRules();
+ Assert( pRules );
+ return pRules;
+ }
+
+ BEGIN_SEND_TABLE( CHL1MPGameRulesProxy, DT_HL1MPGameRulesProxy )
+ SendPropDataTable( "hl1mp_gamerules_data", 0, &REFERENCE_SEND_TABLE( DT_HL1MPRules ), SendProxy_HL1MPRules )
+ END_SEND_TABLE()
+#endif
+
+#ifndef CLIENT_DLL
+
+#if 0
+ class CVoiceGameMgrHelper : public IVoiceGameMgrHelper
+ {
+ public:
+ virtual bool CanPlayerHearPlayer( CBasePlayer *pListener, CBasePlayer *pTalker )
+ {
+ return ( pListener->GetTeamNumber() == pTalker->GetTeamNumber() );
+ }
+ };
+ CVoiceGameMgrHelper g_VoiceGameMgrHelper;
+ IVoiceGameMgrHelper *g_pVoiceGameMgrHelper = &g_VoiceGameMgrHelper;
+#endif
+
+#ifdef DEBUG
+
+ // Handler for the "bot" command.
+ void Bot_f()
+ {
+ // Look at -count.
+ int count = 1;
+ count = clamp( count, 1, 16 );
+
+ int iTeam = 0;
+
+ // Look at -frozen.
+ bool bFrozen = false;
+
+ // Ok, spawn all the bots.
+ while ( --count >= 0 )
+ {
+ BotPutInServer( bFrozen, iTeam );
+ }
+ }
+
+
+ ConCommand cc_Bot( "bot", Bot_f, "Add a bot.", FCVAR_CHEAT );
+
+#endif
+
+#endif
+
+
+
+
+CHL1MPRules::CHL1MPRules()
+{
+#ifndef CLIENT_DLL
+ m_bTeamPlayEnabled = teamplay.GetBool();
+
+ if ( IsTeamplay() )
+ {
+ // Create basic server teams
+
+ CTeam *pTeam = static_cast<CTeam*>(CreateEntityByName( "team_manager" ));
+ pTeam->Init( "Unassigned", 0 );
+ g_Teams.AddToTail( pTeam );
+
+ pTeam = static_cast<CTeam*>(CreateEntityByName( "team_manager" ));
+ pTeam->Init( "Spectator", 1 );
+ g_Teams.AddToTail( pTeam );
+
+ char *pName;
+ char szTeamlist[TEAMPLAY_TEAMLISTLENGTH];
+
+ // loop through all teams, recounting everything
+ int num_teams = 0;
+
+ // Copy all of the teams from the teamlist
+ // make a copy because strtok is destructive
+ Q_strncpy( szTeamlist, teamlist.GetString(), sizeof(teamlist) );
+ pName = szTeamlist;
+ pName = strtok( pName, "," );
+ while ( pName != NULL && *pName )
+ {
+ if ( GetTeamIndex( pName ) < 0 )
+ {
+ // create team
+ pTeam = static_cast<CTeam*>(CreateEntityByName( "team_manager" ));
+ pTeam->Init( pName, num_teams + 2 );
+ g_Teams.AddToTail( pTeam );
+
+ num_teams++;
+ }
+ pName = strtok( NULL, "," );
+ }
+
+ // Manually create teams
+ if ( num_teams == 0 )
+ {
+ pTeam = static_cast<CTeam*>(CreateEntityByName( "team_manager" ) );
+ pTeam->Init( "robo", num_teams + 2 );
+ g_Teams.AddToTail( pTeam );
+ num_teams++;
+
+ pTeam = static_cast<CTeam*>(CreateEntityByName( "team_manager" ) );
+ pTeam->Init( "hgrunt", num_teams + 2 );
+ g_Teams.AddToTail( pTeam );
+ num_teams++;
+ }
+
+ }
+#endif
+}
+
+CHL1MPRules::~CHL1MPRules( void )
+{
+#ifndef CLIENT_DLL
+ // Note, don't delete each team since they are in the gEntList and will
+ // automatically be deleted from there, instead.
+ g_Teams.Purge();
+#endif
+}
+
+void CHL1MPRules::CreateStandardEntities( void )
+{
+
+#ifndef CLIENT_DLL
+ // Create the entity that will send our data to the client.
+
+ BaseClass::CreateStandardEntities();
+
+#ifdef _DEBUG
+ CBaseEntity *pEnt =
+#endif
+ CBaseEntity::Create( "hl1mp_gamerules", vec3_origin, vec3_angle );
+ Assert( pEnt );
+#endif
+}
+
+float CHL1MPRules::GetAmmoDamage( CBaseEntity *pAttacker, CBaseEntity *pVictim, int nAmmoType )
+{
+ return BaseClass::GetAmmoDamage( pAttacker, pVictim, nAmmoType ) * GetDamageMultiplier();
+}
+
+float CHL1MPRules::GetDamageMultiplier( void )
+{
+ if ( IsMultiplayer() )
+ return sk_mp_dmg_multiplier.GetFloat();
+ else
+ return 1.0f;
+}
+
+
+bool CHL1MPRules::ClientCommand( CBaseEntity *pEdict, const CCommand &args )
+{
+#ifndef CLIENT_DLL
+ if( BaseClass::ClientCommand( pEdict, args ) )
+ return true;
+
+
+ CHL1MP_Player *pPlayer = (CHL1MP_Player *) pEdict;
+
+ if ( pPlayer->ClientCommand( args ) )
+ return true;
+#endif
+
+ return false;
+}
+
+
+#ifdef CLIENT_DLL
+#else
+
+
+void CHL1MPRules::Think ( void )
+{
+ CGameRules::Think();
+
+ if ( g_fGameOver ) // someone else quit the game already
+ {
+ // check to see if we should change levels now
+ if ( m_flIntermissionEndTime < gpGlobals->curtime )
+ {
+ ChangeLevel(); // intermission is over
+ }
+
+ return;
+ }
+
+ float flTimeLimit = mp_timelimit.GetFloat() * 60;
+ float flFragLimit = fraglimit.GetFloat();
+
+ if ( flTimeLimit != 0 && gpGlobals->curtime >= flTimeLimit )
+ {
+ GoToIntermission();
+ return;
+ }
+
+ if ( flFragLimit )
+ {
+ if( IsTeamplay() == true )
+ {
+ for (int i = TEAM_SPECTATOR+1; i < GetNumberOfTeams(); i++)
+ {
+ if ( GetGlobalTeam(i)->GetScore() >= flFragLimit )
+ {
+ GoToIntermission();
+ return;
+ }
+ }
+ }
+ else
+ {
+ // check if any player is over the frag limit
+ for ( int i = 1; i <= gpGlobals->maxClients; i++ )
+ {
+ CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
+
+ if ( pPlayer && pPlayer->FragCount() >= flFragLimit )
+ {
+ GoToIntermission();
+ return;
+ }
+ }
+ }
+ }
+
+// ManageObjectRelocation();
+}
+
+
+void CHL1MPRules::GoToIntermission()
+{
+#ifndef CLIENT_DLL
+ if ( g_fGameOver )
+ return;
+
+ g_fGameOver = true;
+
+ m_flIntermissionEndTime = gpGlobals->curtime + mp_chattime.GetInt();
+
+ for ( int i = 0; i < MAX_PLAYERS; i++ )
+ {
+ CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
+
+ if ( !pPlayer )
+ continue;
+
+ pPlayer->ShowViewPortPanel( PANEL_SCOREBOARD );
+ pPlayer->AddFlag( FL_FROZEN );
+ }
+#endif
+}
+
+
+const char * CHL1MPRules::SetDefaultPlayerTeam( CBasePlayer *pPlayer )
+{
+ if ( !IsTeamplay() )
+ {
+ CMultiplayRules::SetDefaultPlayerTeam( pPlayer );
+ return "";
+ }
+
+ int clientIndex = pPlayer->entindex();
+
+ char szTeam[128];
+ Q_FileBase( engine->GetClientConVarValue( clientIndex, "cl_playermodel" ), szTeam, 128 );
+
+ const char * team = szTeam;
+
+ int iTeam = GetTeamIndex( team );
+ if ( iTeam == -1 || !IsValidTeam( team ) )
+ {
+ team = TeamWithFewestPlayers();
+ iTeam = GetTeamIndex(team);
+ }
+
+ pPlayer->ChangeTeam( iTeam );
+
+ return team;
+}
+
+
+const char * CHL1MPRules::TeamWithFewestPlayers( void )
+{
+ const char * szName = "";
+ int iNumPlayers = 0xFFFF;
+ for (int i = TEAM_SPECTATOR+1; i < GetNumberOfTeams(); i++)
+ {
+ if ( GetGlobalTeam(i)->GetNumPlayers() < iNumPlayers )
+ {
+ szName = GetGlobalTeam(i)->GetName();
+ iNumPlayers = GetGlobalTeam(i)->GetNumPlayers();
+ }
+ }
+
+ return szName;
+}
+
+
+void CHL1MPRules::InitHUD( CBasePlayer *pPlayer )
+{
+ SetDefaultPlayerTeam( pPlayer );
+ BaseClass::InitHUD( pPlayer );
+}
+
+
+void CHL1MPRules::ChangePlayerTeam( CBasePlayer *pPlayer, const char *pTeamName, bool bKill, bool bGib )
+{
+ BaseClass::ChangePlayerTeam( pPlayer, pTeamName, bKill, bGib );
+}
+
+
+void CHL1MPRules::ClientSettingsChanged( CBasePlayer *pPlayer )
+{
+ CHL1MP_Player *pHL1Player = ToHL1MPPlayer( pPlayer );
+
+ if ( pHL1Player == NULL )
+ return;
+
+ // strip down to just the name
+ char szTempCurrentModel[128];
+ Q_FileBase( modelinfo->GetModelName( pPlayer->GetModel() ), szTempCurrentModel, 128 );
+ const char *pCurrentModel = szTempCurrentModel;
+
+ char szTempModelName[128];
+ Q_FileBase( engine->GetClientConVarValue( engine->IndexOfEdict( pPlayer->edict() ), "cl_playermodel" ), szTempModelName, 128 );
+ const char *szModelName = szTempModelName;
+
+ //If we're different.
+ if ( strlen( szModelName ) > 0 && stricmp( szModelName, pCurrentModel ) )
+ {
+ //Too soon, set the cvar back to what it was.
+ //Note: this will make this function be called again
+ //but since our models will match it'll just skip this whole dealio.
+ if ( pHL1Player->GetNextModelChangeTime() >= gpGlobals->curtime )
+ {
+ char szReturnString[512];
+
+ Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", pCurrentModel );
+ engine->ClientCommand ( pHL1Player->edict(), szReturnString );
+
+ Q_snprintf( szReturnString, sizeof( szReturnString ), "Please wait %d more seconds before trying to switch.\n", (int)(pHL1Player->GetNextModelChangeTime() - gpGlobals->curtime) );
+ ClientPrint( pHL1Player, HUD_PRINTTALK, szReturnString );
+ return;
+ }
+
+ if ( HL1MPRules()->IsTeamplay() == false )
+ {
+ pHL1Player->SetPlayerModel();
+
+ //const char *pszCurrentModelName = modelinfo->GetModelName( pHL1Player->GetModel() );
+
+ //char szReturnString[128];
+ //Q_snprintf( szReturnString, sizeof( szReturnString ), "Your player model is: %s\n", pszCurrentModelName );
+
+ //Printing the model path for the average player is way too verbose - ml
+ //ClientPrint( pHL1Player, HUD_PRINTTALK, szReturnString );
+ }
+ else
+ {
+ int iTeam = GetTeamIndex( szModelName );
+ if ( iTeam == -1 || !IsValidTeam( szModelName ) )
+ {
+ const char * team = TeamWithFewestPlayers();
+ iTeam = GetTeamIndex( team );
+ }
+
+ pPlayer->ChangeTeam( iTeam );
+ }
+ }
+
+ BaseClass::ClientSettingsChanged( pPlayer );
+}
+
+
+int CHL1MPRules::GetTeamIndex( const char * pName )
+{
+ for ( int i = 0; i < GetNumberOfTeams(); i++ )
+ {
+ if ( strcmp( g_Teams[i]->GetName(), pName ) == 0 )
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+float CHL1MPRules::FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon )
+{
+ if ( weaponstay.GetInt() > 0 )
+ {
+ // make sure it's only certain weapons
+ if ( !(pWeapon->GetWeaponFlags() & ITEM_FLAG_LIMITINWORLD) )
+ {
+ return 0;
+ }
+ }
+
+ return sv_hl1mp_weapon_respawn_time.GetInt();
+}
+
+
+float CHL1MPRules::FlItemRespawnTime( CItem *pItem )
+{
+ return sv_hl1mp_item_respawn_time.GetInt();
+}
+
+
+
+// This is a direct rip from CHalfLife1
+void CHL1MPRules::InitDefaultAIRelationships( void )
+{
+ int i, j;
+
+ // Allocate memory for default relationships
+ CBaseCombatCharacter::AllocateDefaultRelationships();
+
+ // --------------------------------------------------------------
+ // First initialize table so we can report missing relationships
+ // --------------------------------------------------------------
+ for (i=0;i<NUM_AI_CLASSES;i++)
+ {
+ for (j=0;j<NUM_AI_CLASSES;j++)
+ {
+ // By default all relationships are neutral of priority zero
+ CBaseCombatCharacter::SetDefaultRelationship( (Class_T)i, (Class_T)j, D_NU, 0 );
+ }
+ }
+
+ // ------------------------------------------------------------
+ // > CLASS_NONE
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_PLAYER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_HUMAN_PASSIVE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_PLAYER_ALLY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_ALIEN_PREY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_ALIEN_MONSTER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_ALIEN_PREDATOR, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_HUMAN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_NONE, CLASS_INSECT, D_NU, 0 );
+
+
+ // ------------------------------------------------------------
+ // > CLASS_HUMAN_PASSIVE
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_PLAYER, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_HUMAN_PASSIVE, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_PLAYER_ALLY, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_ALIEN_PREY, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_ALIEN_MILITARY, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_ALIEN_PREDATOR, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_PASSIVE, CLASS_INSECT, D_NU, 0 );
+
+
+
+ // ------------------------------------------------------------
+ // > CLASS_PLAYER
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_PLAYER, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_HUMAN_PASSIVE, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_PLAYER_ALLY, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_ALIEN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_ALIEN_PREDATOR, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_MACHINE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_ALIEN_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_PLAYER_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_PLAYER_ALLY
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_PLAYER, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_HUMAN_PASSIVE, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_PLAYER_ALLY, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_ALIEN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_ALIEN_PREDATOR, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_MACHINE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_ALLY, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_ALIEN_PREY
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_ALIEN_PREY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_ALIEN_MONSTER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_ALIEN_PREDATOR, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREY, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_ALIEN_MILITARY
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_ALIEN_PREY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_ALIEN_MONSTER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_ALIEN_PREDATOR, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_MACHINE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MILITARY, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_ALIEN_MONSTER
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_ALIEN_PREY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_ALIEN_MONSTER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_ALIEN_PREDATOR, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_MACHINE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_MONSTER, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_ALIEN_PREDATOR
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_ALIEN_MONSTER, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_ALIEN_PREDATOR, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_PREDATOR, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_HUMAN_MILITARY
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_ALIEN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_ALIEN_PREDATOR, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_HUMAN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_HUMAN_MILITARY, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_MACHINE
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_HUMAN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_ALIEN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_ALIEN_PREDATOR, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_ALIEN_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_PLAYER_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_MACHINE, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_ALIEN_BIOWEAPON
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_ALIEN_MILITARY, D_LI, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_ALIEN_PREDATOR, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_PLAYER_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_ALIEN_BIOWEAPON, CLASS_INSECT, D_NU, 0 );
+
+ // ------------------------------------------------------------
+ // > CLASS_PLAYER_BIOWEAPON
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_NONE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_MACHINE, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_PLAYER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_HUMAN_PASSIVE, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_HUMAN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_ALIEN_MILITARY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_ALIEN_MONSTER, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_ALIEN_PREY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_ALIEN_PREDATOR, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_PLAYER_ALLY, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_ALIEN_BIOWEAPON, D_HT, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_PLAYER_BIOWEAPON, CLASS_INSECT, D_NU, 0 );
+
+
+ // ------------------------------------------------------------
+ // > CLASS_INSECT
+ // ------------------------------------------------------------
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_NONE, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_MACHINE, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_PLAYER, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_HUMAN_PASSIVE, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_HUMAN_MILITARY, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_ALIEN_MILITARY, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_ALIEN_MONSTER, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_ALIEN_PREY, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_ALIEN_PREDATOR, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_PLAYER_ALLY, D_FR, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_ALIEN_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_PLAYER_BIOWEAPON, D_NU, 0 );
+ CBaseCombatCharacter::SetDefaultRelationship( CLASS_INSECT, CLASS_INSECT, D_NU, 0 );
+}
+
+
+#endif
diff --git a/game/shared/hl1/hl1mp_gamerules.h b/game/shared/hl1/hl1mp_gamerules.h
new file mode 100644
index 0000000..c68743a
--- /dev/null
+++ b/game/shared/hl1/hl1mp_gamerules.h
@@ -0,0 +1,91 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+#ifndef HL1MP_GAMERULES_H
+#define HL1MP_GAMERULES_H
+#pragma once
+
+
+#include "gamerules.h"
+#include "teamplay_gamerules.h"
+
+extern ConVar sk_mp_dmg_multiplier ;
+
+#ifdef CLIENT_DLL
+ #define CHL1MPRules C_HL1MPRules
+ #define CHL1MPGameRulesProxy C_HL1MPGameRulesProxy
+#endif
+
+
+class CHL1MPGameRulesProxy : public CGameRulesProxy
+{
+public:
+ DECLARE_CLASS( CHL1MPGameRulesProxy, CGameRulesProxy );
+ DECLARE_NETWORKCLASS();
+};
+
+
+class CHL1MPRules : public CTeamplayRules
+{
+public:
+ DECLARE_CLASS( CHL1MPRules, CTeamplayRules );
+
+#ifdef CLIENT_DLL
+ DECLARE_CLIENTCLASS_NOBASE();
+#else
+ DECLARE_SERVERCLASS_NOBASE();
+#endif
+
+ CHL1MPRules();
+ virtual ~CHL1MPRules();
+
+ virtual void CreateStandardEntities( void );
+
+ virtual bool IsTeamplay( void )
+ {
+ return m_bTeamPlayEnabled;
+ }
+
+ virtual float GetAmmoDamage( CBaseEntity *pAttacker, CBaseEntity *pVictim, int nAmmoType );
+ virtual float GetDamageMultiplier( void );
+
+ virtual bool IsConnectedUserInfoChangeAllowed( CBasePlayer *pPlayer )
+ {
+ return true;
+ }
+ bool ClientCommand( CBaseEntity *pEdict, const CCommand &args );
+
+#ifdef CLIENT_DLL
+#else
+ virtual const char *GetGameDescription( void ) { return "Half-Life Deathmatch: Source"; } // this is the game name that gets seen in the server browser
+
+ virtual void Think ( void );
+
+ virtual void GoToIntermission( void );
+
+ virtual void InitDefaultAIRelationships( void );
+
+ virtual float FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon );
+ virtual float FlItemRespawnTime( CItem *pItem );
+
+ virtual const char *SetDefaultPlayerTeam( CBasePlayer *pPlayer );
+ virtual void InitHUD( CBasePlayer *pPlayer );
+ virtual void ChangePlayerTeam( CBasePlayer *pPlayer, const char *pTeamName, bool bKill, bool bGib );
+ virtual void ClientSettingsChanged( CBasePlayer *pPlayer );
+
+ virtual int GetTeamIndex( const char * pName );
+#endif
+
+private:
+
+ const char *TeamWithFewestPlayers( void );
+
+ CNetworkVar( bool, m_bTeamPlayEnabled );
+};
+
+
+inline CHL1MPRules* HL1MPRules()
+{
+ return dynamic_cast<CHL1MPRules*>(g_pGameRules);
+}
+
+
+#endif
diff --git a/game/shared/hl1/hl1mp_weapon_357.cpp b/game/shared/hl1/hl1mp_weapon_357.cpp
new file mode 100644
index 0000000..33d6757
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_357.cpp
@@ -0,0 +1,289 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: 357 - hand gun
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "npcevent.h"
+#include "hl1mp_basecombatweapon_shared.h"
+#ifdef CLIENT_DLL
+#include "c_baseplayer.h"
+#else
+#include "player.h"
+#endif
+#include "gamerules.h"
+#include "in_buttons.h"
+#ifndef CLIENT_DLL
+#include "soundent.h"
+#include "game.h"
+#endif
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+
+#ifdef CLIENT_DLL
+#define CWeapon357 C_Weapon357
+#endif
+
+//-----------------------------------------------------------------------------
+// CWeapon357
+//-----------------------------------------------------------------------------
+
+class CWeapon357 : public CBaseHL1MPCombatWeapon
+{
+ DECLARE_CLASS( CWeapon357, CBaseHL1CombatWeapon );
+public:
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+ CWeapon357( void );
+
+ void Precache( void );
+ bool Deploy( void );
+ void PrimaryAttack( void );
+ void SecondaryAttack( void );
+ bool Reload( void );
+ void WeaponIdle( void );
+ bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
+
+// DECLARE_SERVERCLASS();
+// DECLARE_DATADESC();
+
+private:
+ void ToggleZoom( void );
+
+private:
+ CNetworkVar( float, m_fInZoom );
+};
+
+IMPLEMENT_NETWORKCLASS_ALIASED( Weapon357, DT_Weapon357 );
+
+BEGIN_NETWORK_TABLE( CWeapon357, DT_Weapon357 )
+#ifdef CLIENT_DLL
+ RecvPropFloat( RECVINFO( m_fInZoom ) ),
+#else
+ SendPropFloat( SENDINFO( m_fInZoom ) ),
+#endif
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CWeapon357 )
+#ifdef CLIENT_DLL
+ DEFINE_PRED_FIELD( m_fInZoom, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
+#endif
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( weapon_357, CWeapon357 );
+
+PRECACHE_WEAPON_REGISTER( weapon_357 );
+
+//IMPLEMENT_SERVERCLASS_ST( CWeapon357, DT_Weapon357 )
+//END_SEND_TABLE()
+
+//BEGIN_DATADESC( CWeapon357 )
+//END_DATADESC()
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CWeapon357::CWeapon357( void )
+{
+ m_bReloadsSingly = false;
+ m_bFiresUnderwater = false;
+ m_fInZoom = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeapon357::Precache( void )
+{
+ BaseClass::Precache();
+
+#ifndef CLIENT_DLL
+ UTIL_PrecacheOther( "ammo_357" );
+#endif
+}
+
+bool CWeapon357::Deploy( void )
+{
+// Bodygroup stuff not currently working correctly
+// if ( g_pGameRules->IsMultiplayer() )
+// {
+ // enable laser sight geometry.
+// SetBodygroup( 4, 1 );
+// }
+// else
+// {
+// SetBodygroup( 4, 0 );
+// }
+
+ return BaseClass::Deploy();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeapon357::PrimaryAttack( void )
+{
+ // Only the player fires this way so we can cast
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ if ( m_iClip1 <= 0 )
+ {
+ if ( !m_bFireOnEmpty )
+ {
+ Reload();
+ }
+ else
+ {
+ WeaponSound( EMPTY );
+ m_flNextPrimaryAttack = 0.15;
+ }
+
+ return;
+ }
+
+ WeaponSound( SINGLE );
+ pPlayer->DoMuzzleFlash();
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.75;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.75;
+
+ m_iClip1--;
+
+ Vector vecSrc = pPlayer->Weapon_ShootPosition();
+ Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
+
+// pPlayer->FireBullets( 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 );
+
+ FireBulletsInfo_t info( 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType );
+ info.m_pAttacker = pPlayer;
+
+ pPlayer->FireBullets( info );
+
+#ifndef CLIENT_DLL
+ pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
+#endif
+
+ pPlayer->ViewPunch( QAngle( -10, 0, 0 ) );
+
+#ifndef CLIENT_DLL
+ CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 600, 0.2 );
+#endif
+
+ if ( !m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ {
+ // HEV suit - indicate out of ammo condition
+ pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeapon357::SecondaryAttack( void )
+{
+ // only in multiplayer
+ if ( !g_pGameRules->IsMultiplayer() )
+ {
+#ifndef CLIENT_DLL
+ // unless we have cheats on
+ if ( !sv_cheats->GetBool() )
+ {
+ return;
+ }
+#endif
+ }
+
+ ToggleZoom();
+
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.5;
+}
+
+
+bool CWeapon357::Reload( void )
+{
+ bool fRet;
+
+ fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD );
+ if ( fRet )
+ {
+ if ( m_fInZoom )
+ {
+ ToggleZoom();
+ }
+ }
+
+ return fRet;
+}
+
+
+void CWeapon357::WeaponIdle( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( pPlayer )
+ {
+ pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
+ }
+
+ if ( !HasWeaponIdleTimeElapsed() )
+ return;
+
+ if ( random->RandomFloat( 0, 1 ) <= 0.9 )
+ {
+ SendWeaponAnim( ACT_VM_IDLE );
+ }
+ else
+ {
+ SendWeaponAnim( ACT_VM_FIDGET );
+ }
+}
+
+
+bool CWeapon357::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+ if ( m_fInZoom )
+ {
+ ToggleZoom();
+ }
+
+ return BaseClass::Holster( pSwitchingTo );
+}
+
+
+void CWeapon357::ToggleZoom( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+#ifndef CLIENT_DLL
+ if ( m_fInZoom )
+ {
+ if ( pPlayer->SetFOV( this, 0 ) )
+ {
+ m_fInZoom = false;
+ pPlayer->ShowViewModel( true );
+ }
+ }
+ else
+ {
+ if ( pPlayer->SetFOV( this, 40 ) )
+ {
+ m_fInZoom = true;
+ pPlayer->ShowViewModel( false );
+ }
+ }
+#endif
+}
diff --git a/game/shared/hl1/hl1mp_weapon_crossbow.cpp b/game/shared/hl1/hl1mp_weapon_crossbow.cpp
new file mode 100644
index 0000000..7118ac1
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_crossbow.cpp
@@ -0,0 +1,648 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Crossbow
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "npcevent.h"
+#include "hl1mp_basecombatweapon_shared.h"
+//#include "basecombatcharacter.h"
+//#include "AI_BaseNPC.h"
+#ifdef CLIENT_DLL
+#include "c_baseplayer.h"
+#else
+#include "player.h"
+#endif
+//#include "player.h"
+#include "gamerules.h"
+#include "in_buttons.h"
+#ifdef CLIENT_DLL
+#else
+#include "soundent.h"
+#include "entitylist.h"
+#include "game.h"
+#endif
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+#include "IEffects.h"
+#ifdef CLIENT_DLL
+#include "c_te_effect_dispatch.h"
+#else
+#include "te_effect_dispatch.h"
+#endif
+
+#define BOLT_MODEL "models/crossbow_bolt.mdl"
+
+#define BOLT_AIR_VELOCITY 2000
+#define BOLT_WATER_VELOCITY 1000
+
+extern ConVar sk_plr_dmg_xbow_bolt_plr;
+extern ConVar sk_plr_dmg_xbow_bolt_npc;
+
+extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the fireball
+
+#if !defined(CLIENT_DLL)
+
+//-----------------------------------------------------------------------------
+// Crossbow Bolt
+//-----------------------------------------------------------------------------
+class CCrossbowBolt : public CBaseCombatCharacter
+{
+ DECLARE_CLASS( CCrossbowBolt, CBaseCombatCharacter );
+
+public:
+ CCrossbowBolt()
+ {
+ m_bExplode = true;
+ }
+
+ Class_T Classify( void ) { return CLASS_NONE; }
+
+public:
+ void Spawn( void );
+ void Precache( void );
+ void BubbleThink( void );
+ void BoltTouch( CBaseEntity *pOther );
+ void ExplodeThink( void );
+ void SetExplode( bool bVal ) { m_bExplode = bVal; }
+ bool CreateVPhysics( void );
+ unsigned int PhysicsSolidMaskForEntity() const;
+
+ static CCrossbowBolt *BoltCreate( const Vector &vecOrigin, const QAngle &angAngles, CBasePlayer *pentOwner = NULL );
+
+ DECLARE_DATADESC();
+
+private:
+ bool m_bExplode;
+};
+LINK_ENTITY_TO_CLASS( crossbow_bolt, CCrossbowBolt );
+
+BEGIN_DATADESC( CCrossbowBolt )
+ // Function Pointers
+ DEFINE_FUNCTION( BubbleThink ),
+ DEFINE_FUNCTION( BoltTouch ),
+ DEFINE_FUNCTION( ExplodeThink ),
+END_DATADESC()
+
+CCrossbowBolt *CCrossbowBolt::BoltCreate( const Vector &vecOrigin, const QAngle &angAngles, CBasePlayer *pentOwner )
+{
+ // Create a new entity with CCrossbowBolt private data
+ CCrossbowBolt *pBolt = (CCrossbowBolt *)CreateEntityByName( "crossbow_bolt" );
+ UTIL_SetOrigin( pBolt, vecOrigin );
+ pBolt->SetAbsAngles( angAngles );
+ pBolt->Spawn();
+ pBolt->SetOwnerEntity( pentOwner );
+
+ return pBolt;
+}
+
+void CCrossbowBolt::Spawn( )
+{
+ Precache( );
+
+ SetModel( BOLT_MODEL );
+ UTIL_SetSize( this, -Vector(1, 1, 1), Vector(1, 1, 1) );
+
+ SetSolid( SOLID_BBOX );
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
+ SetGravity( UTIL_ScaleForGravity( 40 ) ); // use a really low gravity (40 in/s^2)
+
+ SetTouch( &CCrossbowBolt::BoltTouch );
+
+ SetThink( &CCrossbowBolt::BubbleThink );
+ SetNextThink( gpGlobals->curtime + 0.2 );
+
+ m_bExplode = true;
+}
+
+
+void CCrossbowBolt::Precache( )
+{
+ PrecacheModel( BOLT_MODEL );
+ PrecacheScriptSound( "BaseGrenade.Explode" );
+}
+
+void CCrossbowBolt::BoltTouch( CBaseEntity *pOther )
+{
+ if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) )
+ return;
+
+ SetTouch( NULL );
+ SetThink( NULL );
+
+ if ( pOther->m_takedamage != DAMAGE_NO )
+ {
+ trace_t tr, tr2;
+ tr = BaseClass::GetTouchTrace( );
+ Vector vecNormalizedVel = GetAbsVelocity();
+
+ ClearMultiDamage( );
+ VectorNormalize( vecNormalizedVel );
+
+ if ( pOther->IsPlayer() )
+ {
+ float m_fDamage = sk_plr_dmg_xbow_bolt_plr.GetFloat() * g_pGameRules->GetDamageMultiplier();
+
+ // If multiplayer sniper bolt, multiply damage by 4
+ if ( g_pGameRules->IsMultiplayer() && !m_bExplode )
+ m_fDamage *= 4;
+
+ CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), m_fDamage,DMG_NEVERGIB );
+ CalculateMeleeDamageForce( &dmgInfo, vecNormalizedVel, tr.endpos );
+ pOther->DispatchTraceAttack( dmgInfo, vecNormalizedVel, &tr );
+ }
+ else
+ {
+ CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), sk_plr_dmg_xbow_bolt_npc.GetFloat() * g_pGameRules->GetDamageMultiplier(), DMG_BULLET | DMG_NEVERGIB );
+ CalculateMeleeDamageForce( &dmgInfo, vecNormalizedVel, tr.endpos );
+ pOther->DispatchTraceAttack( dmgInfo, vecNormalizedVel, &tr );
+ }
+
+ ApplyMultiDamage();
+
+ 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 );
+
+ CEffectData data;
+
+ data.m_vOrigin = tr2.endpos;
+ data.m_vNormal = vForward;
+ data.m_nEntIndex = tr2.fraction != 1.0f;
+
+ DispatchEffect( "BoltImpact", data );
+ }
+
+ if ( !g_pGameRules->IsMultiplayer() || !m_bExplode )
+ {
+ UTIL_Remove( this );
+ }
+ }
+ else
+ {
+ EmitSound( "Weapon_Crossbow.BoltHitWorld" );
+
+ SetThink( &CCrossbowBolt::SUB_Remove );
+ SetNextThink( gpGlobals->curtime );// this will get changed below if the bolt is allowed to stick in what it hit.
+
+ if ( m_bExplode == false )
+ {
+ Vector vForward;
+ AngleVectors( GetAbsAngles(), &vForward );
+ VectorNormalize ( vForward );
+
+ CEffectData data;
+
+ data.m_vOrigin = GetAbsOrigin();
+ data.m_vNormal = vForward;
+ data.m_nEntIndex = 0;
+
+ DispatchEffect( "BoltImpact", data );
+ }
+
+ if ( UTIL_PointContents( GetAbsOrigin() ) != CONTENTS_WATER)
+ {
+ g_pEffects->Sparks( GetAbsOrigin() );
+ }
+ }
+
+ // Set up an explosion in one tenth of a second
+ if ( g_pGameRules->IsMultiplayer() && m_bExplode )
+ {
+ SetThink( &CCrossbowBolt::ExplodeThink );
+ SetNextThink( gpGlobals->curtime + 0.1f );
+ }
+}
+
+void CCrossbowBolt::ExplodeThink( void )
+{
+ // int iContents = UTIL_PointContents( pev->origin );
+ CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), sk_plr_dmg_xbow_bolt_npc.GetFloat() * g_pGameRules->GetDamageMultiplier(), DMG_BLAST );
+
+ ::RadiusDamage( dmgInfo, GetAbsOrigin(), 128, CLASS_NONE, NULL );
+
+#if !defined( CLIENT_DLL )
+ CPASFilter filter( GetAbsOrigin() );
+
+ te->Explosion( filter, /* filter */
+ 0.0, /* delay */
+ &GetAbsOrigin(), /* pos */
+ g_sModelIndexFireball, /* modelindex */
+ 0.2, /* scale */
+ 25, /* framerate */
+ TE_EXPLFLAG_NONE, /* flags */
+ 128, /* radius */
+ 64, /* magnitude */
+ NULL, /* normal */
+ 'C' ); /* materialType */
+
+ //CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 );
+ EmitSound( "BaseGrenade.Explode" );
+#endif
+
+
+ SetThink( &CCrossbowBolt::SUB_Remove );
+ SetNextThink( gpGlobals->curtime );
+
+ AddEffects( EF_NODRAW );
+}
+
+void CCrossbowBolt::BubbleThink( void )
+{
+ QAngle angNewAngles;
+
+ VectorAngles( GetAbsVelocity(), angNewAngles );
+ SetAbsAngles( angNewAngles );
+
+ SetNextThink( gpGlobals->curtime + 0.1f );
+
+ if ( GetWaterLevel() == 0 )
+ return;
+
+ UTIL_BubbleTrail( GetAbsOrigin() - GetAbsVelocity() * 0.1, GetAbsOrigin(), 1 );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CCrossbowBolt::CreateVPhysics( void )
+{
+ // Create the object in the physics system
+ VPhysicsInitNormal( SOLID_BBOX, FSOLID_NOT_STANDABLE, false );
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+unsigned int CCrossbowBolt::PhysicsSolidMaskForEntity() const
+{
+ return ( BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_HITBOX ) & ~CONTENTS_GRATE;
+}
+
+
+#endif // crossbowbolt
+
+//-----------------------------------------------------------------------------
+// CWeaponCrossbow
+//-----------------------------------------------------------------------------
+
+#ifdef CLIENT_DLL
+#define CWeaponCrossbow C_WeaponCrossbow
+#endif
+
+class CWeaponCrossbow : public CBaseHL1MPCombatWeapon
+{
+ DECLARE_CLASS( CWeaponCrossbow, CBaseHL1MPCombatWeapon );
+public:
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+ CWeaponCrossbow( void );
+
+ void Precache( void );
+ void PrimaryAttack( void );
+ void SecondaryAttack( void );
+ bool Reload( void );
+ void WeaponIdle( void );
+ bool Deploy( void );
+ bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
+
+// DECLARE_SERVERCLASS();
+ DECLARE_DATADESC();
+
+#ifndef CLIENT_DLL
+// DECLARE_ACTTABLE();
+#endif
+
+private:
+ void FireBolt( void );
+ void ToggleZoom( void );
+
+private:
+// bool m_fInZoom;
+ CNetworkVar( bool, m_fInZoom );
+};
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponCrossbow, DT_WeaponCrossbow );
+
+BEGIN_NETWORK_TABLE( CWeaponCrossbow, DT_WeaponCrossbow )
+#ifdef CLIENT_DLL
+ RecvPropBool( RECVINFO( m_fInZoom ) ),
+#else
+ SendPropBool( SENDINFO( m_fInZoom ) ),
+#endif
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CWeaponCrossbow )
+#ifdef CLIENT_DLL
+ DEFINE_PRED_FIELD( m_fInZoom, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
+#endif
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( weapon_crossbow, CWeaponCrossbow );
+
+PRECACHE_WEAPON_REGISTER( weapon_crossbow );
+
+//IMPLEMENT_SERVERCLASS_ST( CWeaponCrossbow, DT_WeaponCrossbow )
+//END_SEND_TABLE()
+
+BEGIN_DATADESC( CWeaponCrossbow )
+END_DATADESC()
+
+#if 0
+#ifndef CLIENT_DLL
+
+acttable_t CWeaponCrossbow::m_acttable[] =
+{
+ { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_CROSSBOW, false },
+// { ACT_HL2MP_RUN, ACT_HL2MP_RUN_CROSSBOW, false },
+// { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_CROSSBOW, false },
+// { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_CROSSBOW, false },
+// { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW, false },
+// { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_CROSSBOW, false },
+// { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_CROSSBOW, false },
+};
+
+IMPLEMENT_ACTTABLE(CWeaponCrossbow);
+
+#endif
+#endif
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CWeaponCrossbow::CWeaponCrossbow( void )
+{
+ m_bReloadsSingly = false;
+ m_bFiresUnderwater = true;
+ m_fInZoom = false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponCrossbow::Precache( void )
+{
+#ifndef CLIENT_DLL
+ UTIL_PrecacheOther( "crossbow_bolt" );
+#endif
+
+ PrecacheScriptSound( "Weapon_Crossbow.BoltHitBody" );
+ PrecacheScriptSound( "Weapon_Crossbow.BoltHitWorld" );
+
+ BaseClass::Precache();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponCrossbow::PrimaryAttack( void )
+{
+ if ( m_fInZoom && g_pGameRules->IsMultiplayer() )
+ {
+// FireSniperBolt();
+ FireBolt();
+ }
+ else
+ {
+ FireBolt();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponCrossbow::SecondaryAttack( void )
+{
+ ToggleZoom();
+ m_flNextSecondaryAttack = gpGlobals->curtime + 1.0;
+}
+
+
+void CWeaponCrossbow::FireBolt( void )
+{
+ if ( m_iClip1 <= 0 )
+ {
+ if ( !m_bFireOnEmpty )
+ {
+ Reload();
+ }
+ else
+ {
+ WeaponSound( EMPTY );
+ m_flNextPrimaryAttack = 0.15;
+ }
+
+ return;
+ }
+
+ CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
+
+ if ( pOwner == NULL )
+ return;
+
+ Vector vecAiming = pOwner->GetAutoaimVector( AUTOAIM_2DEGREES );
+ Vector vecSrc = pOwner->Weapon_ShootPosition();
+
+ QAngle angAiming;
+ VectorAngles( vecAiming, angAiming );
+
+#ifndef CLIENT_DLL
+ CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate( vecSrc, angAiming, pOwner );
+
+ // In multiplayer, secondary fire is instantaneous.
+ if ( g_pGameRules->IsMultiplayer() && m_fInZoom )
+ {
+ Vector vecEnd = vecSrc + ( vecAiming * MAX_TRACE_LENGTH );
+
+ trace_t trace;
+ UTIL_TraceLine( vecSrc, vecEnd, MASK_SHOT, GetOwner(), COLLISION_GROUP_NONE, &trace );
+ pBolt->SetAbsOrigin( trace.endpos );
+
+ // We hit someone
+ if ( trace.m_pEnt && trace.m_pEnt->m_takedamage )
+ {
+ pBolt->SetExplode( false );
+ pBolt->BoltTouch( trace.m_pEnt );
+ return;
+ }
+ }
+ else
+ {
+ if ( pOwner->GetWaterLevel() == 3 )
+ {
+ pBolt->SetAbsVelocity( vecAiming * BOLT_WATER_VELOCITY );
+ }
+ else
+ {
+ pBolt->SetAbsVelocity( vecAiming * BOLT_AIR_VELOCITY );
+ }
+ }
+
+ pBolt->SetLocalAngularVelocity( QAngle( 0, 0, 10 ) );
+
+ if ( m_fInZoom || !g_pGameRules->IsMultiplayer() )
+ {
+ pBolt->SetExplode( false );
+
+ }
+#endif
+
+ m_iClip1--;
+
+ pOwner->ViewPunch( QAngle( -2, 0, 0 ) );
+
+ WeaponSound( SINGLE );
+ WeaponSound( RELOAD );
+
+#ifdef CLIENT_DLL
+#else
+ CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 200, 0.2 );
+#endif
+
+ if ( m_iClip1 > 0 )
+ {
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+ }
+ else if ( pOwner->GetAmmoCount(m_iPrimaryAmmoType) > 0 )
+ {
+ SendWeaponAnim( ACT_VM_SECONDARYATTACK );
+ }
+
+ 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 + 0.75;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.75;
+
+ if ( m_iClip1 > 0 )
+ {
+ SetWeaponIdleTime( gpGlobals->curtime + 5.0 );
+ }
+ else
+ {
+ SetWeaponIdleTime( gpGlobals->curtime + 0.75 );
+ }
+}
+
+
+bool CWeaponCrossbow::Reload( void )
+{
+ bool fRet;
+
+ fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD );
+ if ( fRet )
+ {
+ if ( m_fInZoom )
+ {
+ ToggleZoom();
+ }
+
+ WeaponSound( RELOAD );
+ }
+
+ return fRet;
+}
+
+
+void CWeaponCrossbow::WeaponIdle( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( pPlayer )
+ {
+ pPlayer->GetAutoaimVector( AUTOAIM_2DEGREES );
+ }
+
+ if ( !HasWeaponIdleTimeElapsed() )
+ return;
+
+ int iAnim;
+ float flRand = random->RandomFloat( 0, 1 );
+ if ( flRand <= 0.75 )
+ {
+ if ( m_iClip1 <= 0 )
+ iAnim = ACT_CROSSBOW_IDLE_UNLOADED;
+ else
+ iAnim = ACT_VM_IDLE;
+ }
+ else
+ {
+ if ( m_iClip1 <= 0 )
+ iAnim = ACT_CROSSBOW_FIDGET_UNLOADED;
+ else
+ iAnim = ACT_VM_FIDGET;
+ }
+
+ SendWeaponAnim( iAnim );
+}
+
+
+bool CWeaponCrossbow::Deploy( void )
+{
+ if ( m_iClip1 <= 0 )
+ {
+ return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_CROSSBOW_DRAW_UNLOADED, (char*)GetAnimPrefix() );
+ }
+
+ return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_VM_DRAW, (char*)GetAnimPrefix() );
+}
+
+
+bool CWeaponCrossbow::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+ if ( m_fInZoom )
+ {
+ ToggleZoom();
+ }
+
+ return BaseClass::Holster( pSwitchingTo );
+}
+
+
+void CWeaponCrossbow::ToggleZoom( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+#if !defined(CLIENT_DLL)
+ if ( m_fInZoom )
+ {
+ if ( pPlayer->SetFOV( this, 0 ) )
+ {
+ m_fInZoom = false;
+ }
+ }
+ else
+ {
+ if ( pPlayer->SetFOV( this, 20 ) )
+ {
+ m_fInZoom = true;
+ }
+ }
+#endif
+}
diff --git a/game/shared/hl1/hl1mp_weapon_egon.cpp b/game/shared/hl1/hl1mp_weapon_egon.cpp
new file mode 100644
index 0000000..335f687
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_egon.cpp
@@ -0,0 +1,529 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Egon
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "npcevent.h"
+#include "hl1mp_basecombatweapon_shared.h"
+#include "Sprite.h"
+#include "beam_shared.h"
+#include "takedamageinfo.h"
+//#include "basecombatcharacter.h"
+//#include "AI_BaseNPC.h"
+
+#ifdef CLIENT_DLL
+#include "c_baseplayer.h"
+#include "hl1/hl1_c_player.h"
+#else
+#include "player.h"
+#include "hl1_player.h"
+#endif
+
+//#include "player.h"
+#include "gamerules.h"
+#include "in_buttons.h"
+
+#ifdef CLIENT_DLL
+#else
+#include "soundent.h"
+#include "game.h"
+#endif
+
+
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+#include "IEffects.h"
+#ifdef CLIENT_DLL
+#include "c_te_effect_dispatch.h"
+#else
+#include "te_effect_dispatch.h"
+#endif
+
+
+enum EGON_FIRESTATE { FIRE_OFF, FIRE_STARTUP, FIRE_CHARGE };
+
+#define EGON_PULSE_INTERVAL 0.1
+#define EGON_DISCHARGE_INTERVAL 0.1
+
+#define EGON_BEAM_SPRITE "sprites/xbeam1.vmt"
+#define EGON_FLARE_SPRITE "sprites/XSpark1.vmt"
+
+extern ConVar sk_plr_dmg_egon_wide;
+
+//-----------------------------------------------------------------------------
+// CWeaponEgon
+//-----------------------------------------------------------------------------
+
+#ifdef CLIENT_DLL
+#define CWeaponEgon C_WeaponEgon
+#endif
+
+class CWeaponEgon : public CBaseHL1MPCombatWeapon
+{
+ DECLARE_CLASS( CWeaponEgon, CBaseHL1MPCombatWeapon );
+public:
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+ CWeaponEgon(void);
+
+ virtual bool Deploy( void );
+ void PrimaryAttack( void );
+ virtual void Precache( void );
+
+ void SecondaryAttack( void )
+ {
+ PrimaryAttack();
+ }
+
+ void WeaponIdle( void );
+ bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
+
+ // DECLARE_SERVERCLASS();
+ // DECLARE_DATADESC();
+
+private:
+ bool HasAmmo( void );
+ void UseAmmo( int count );
+ void Attack( void );
+ void EndAttack( void );
+ void Fire( const Vector &vecOrigSrc, const Vector &vecDir );
+ void UpdateEffect( const Vector &startPoint, const Vector &endPoint );
+ void CreateEffect( void );
+ void DestroyEffect( void );
+
+ EGON_FIRESTATE m_fireState;
+ float m_flAmmoUseTime; // since we use < 1 point of ammo per update, we subtract ammo on a timer.
+ float m_flShakeTime;
+ float m_flStartFireTime;
+ float m_flDmgTime;
+ CHandle<CSprite> m_hSprite;
+ CHandle<CBeam> m_hBeam;
+ CHandle<CBeam> m_hNoise;
+};
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponEgon, DT_WeaponEgon );
+
+BEGIN_NETWORK_TABLE( CWeaponEgon, DT_WeaponEgon )
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CWeaponEgon )
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( weapon_egon, CWeaponEgon );
+PRECACHE_WEAPON_REGISTER( weapon_egon );
+
+/*
+IMPLEMENT_SERVERCLASS_ST( CWeaponEgon, DT_WeaponEgon )
+END_SEND_TABLE()
+*/
+
+ /*
+BEGIN_DATADESC( CWeaponEgon )
+ DEFINE_FIELD( m_fireState, FIELD_INTEGER ),
+ DEFINE_FIELD( m_flAmmoUseTime, FIELD_TIME ),
+ DEFINE_FIELD( m_flShakeTime, FIELD_TIME ),
+ DEFINE_FIELD( m_flStartFireTime, FIELD_TIME ),
+ DEFINE_FIELD( m_flDmgTime, FIELD_TIME ),
+ DEFINE_FIELD( m_hSprite, FIELD_EHANDLE ),
+ DEFINE_FIELD( m_hBeam, FIELD_EHANDLE ),
+ DEFINE_FIELD( m_hNoise, FIELD_EHANDLE ),
+END_DATADESC()
+ */
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CWeaponEgon::CWeaponEgon( void )
+{
+ m_bReloadsSingly = false;
+ m_bFiresUnderwater = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponEgon::Precache( void )
+{
+ PrecacheScriptSound( "Weapon_Gluon.Start" );
+ PrecacheScriptSound( "Weapon_Gluon.Run" );
+ PrecacheScriptSound( "Weapon_Gluon.Off" );
+
+ PrecacheModel( EGON_BEAM_SPRITE );
+ PrecacheModel( EGON_FLARE_SPRITE );
+
+ BaseClass::Precache();
+}
+
+bool CWeaponEgon::Deploy( void )
+{
+ m_fireState = FIRE_OFF;
+
+ return BaseClass::Deploy();
+}
+
+bool CWeaponEgon::HasAmmo( void )
+{
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return false;
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ return false;
+
+ return true;
+}
+
+void CWeaponEgon::UseAmmo( int count )
+{
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) >= count )
+ pPlayer->RemoveAmmo( count, m_iPrimaryAmmoType );
+ else
+ pPlayer->RemoveAmmo( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ), m_iPrimaryAmmoType );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponEgon::PrimaryAttack( void )
+{
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ // don't fire underwater
+ if ( pPlayer->GetWaterLevel() == 3 )
+ {
+ if ( m_fireState != FIRE_OFF || m_hBeam )
+ {
+ EndAttack();
+ }
+ else
+ {
+ WeaponSound( EMPTY );
+ }
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.5;
+ return;
+ }
+
+ Vector vecAiming = pPlayer->GetAutoaimVector( 0 );
+ Vector vecSrc = pPlayer->Weapon_ShootPosition( );
+
+ 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.
+
+ EmitSound( "Weapon_Gluon.Start" );
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+
+ m_flShakeTime = 0;
+ m_flStartFireTime = gpGlobals->curtime;
+
+ SetWeaponIdleTime( gpGlobals->curtime + 0.1 );
+
+ m_flDmgTime = gpGlobals->curtime + EGON_PULSE_INTERVAL;
+ m_fireState = FIRE_STARTUP;
+ }
+ break;
+
+ case FIRE_STARTUP:
+ {
+ Fire( vecSrc, vecAiming );
+
+ if ( gpGlobals->curtime >= ( m_flStartFireTime + 2.0 ) )
+ {
+ EmitSound( "Weapon_Gluon.Run" );
+
+ m_fireState = FIRE_CHARGE;
+ }
+
+ if ( !HasAmmo() )
+ {
+ EndAttack();
+ m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 1.0;
+ }
+ }
+ case FIRE_CHARGE:
+ {
+ Fire( vecSrc, vecAiming );
+
+ if ( !HasAmmo() )
+ {
+ EndAttack();
+ m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 1.0;
+ }
+ }
+ break;
+ }
+}
+
+void CWeaponEgon::Fire( const Vector &vecOrigSrc, const Vector &vecDir )
+{
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ //CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 450, 0.1 );
+ WeaponSound( SINGLE );
+
+ 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;
+
+ CBaseEntity *pEntity = tr.m_pEnt;
+ if ( pEntity == NULL )
+ return;
+
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ if ( m_hSprite )
+ {
+ if ( pEntity->m_takedamage != DAMAGE_NO )
+ {
+ m_hSprite->TurnOn();
+ }
+ else
+ {
+ m_hSprite->TurnOff();
+ }
+ }
+ }
+
+ if ( m_flDmgTime < gpGlobals->curtime )
+ {
+ // wide mode does damage to the ent, and radius damage
+ if ( pEntity->m_takedamage != DAMAGE_NO )
+ {
+ ClearMultiDamage();
+ CTakeDamageInfo info( this, pPlayer, sk_plr_dmg_egon_wide.GetFloat() * g_pGameRules->GetDamageMultiplier(), DMG_ENERGYBEAM | DMG_ALWAYSGIB );
+ CalculateMeleeDamageForce( &info, vecDir, tr.endpos );
+ pEntity->DispatchTraceAttack( info, vecDir, &tr );
+ ApplyMultiDamage();
+ }
+
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ // radius damage a little more potent in multiplayer.
+#ifndef CLIENT_DLL
+ RadiusDamage( CTakeDamageInfo( this, pPlayer, sk_plr_dmg_egon_wide.GetFloat() * g_pGameRules->GetDamageMultiplier() / 4, DMG_ENERGYBEAM | DMG_BLAST | DMG_ALWAYSGIB ), tr.endpos, 128, CLASS_NONE, NULL );
+#endif
+ }
+
+ if ( !pPlayer->IsAlive() )
+ return;
+
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ //multiplayer uses 5 ammo/second
+ if ( gpGlobals->curtime >= m_flAmmoUseTime )
+ {
+ UseAmmo( 1 );
+ m_flAmmoUseTime = gpGlobals->curtime + 0.2;
+ }
+ }
+ else
+ {
+ // Wide mode uses 10 charges per second in single player
+ if ( gpGlobals->curtime >= m_flAmmoUseTime )
+ {
+ UseAmmo( 1 );
+ m_flAmmoUseTime = gpGlobals->curtime + 0.1;
+ }
+ }
+
+ m_flDmgTime = gpGlobals->curtime + EGON_DISCHARGE_INTERVAL;
+ if ( m_flShakeTime < gpGlobals->curtime )
+ {
+#ifndef CLIENT_DLL
+ UTIL_ScreenShake( tr.endpos, 5.0, 150.0, 0.75, 250.0, SHAKE_START );
+#endif
+ m_flShakeTime = gpGlobals->curtime + 1.5;
+ }
+ }
+
+ Vector vecUp, vecRight;
+ QAngle angDir;
+
+ VectorAngles( vecDir, angDir );
+ AngleVectors( angDir, NULL, &vecRight, &vecUp );
+
+ Vector tmpSrc = vecOrigSrc + (vecUp * -8) + (vecRight * 3);
+ UpdateEffect( tmpSrc, tr.endpos );
+}
+
+void CWeaponEgon::UpdateEffect( const Vector &startPoint, const Vector &endPoint )
+{
+ if ( !m_hBeam )
+ {
+ CreateEffect();
+ }
+
+ if ( m_hBeam )
+ {
+ m_hBeam->SetStartPos( endPoint );
+ }
+
+ if ( m_hSprite )
+ {
+ m_hSprite->SetAbsOrigin( endPoint );
+
+ m_hSprite->m_flFrame += 8 * gpGlobals->frametime;
+ if ( m_hSprite->m_flFrame > m_hSprite->Frames() )
+ m_hSprite->m_flFrame = 0;
+ }
+
+ if ( m_hNoise )
+ {
+ m_hNoise->SetStartPos( endPoint );
+ }
+}
+
+void CWeaponEgon::CreateEffect( void )
+{
+#ifndef CLIENT_DLL
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ DestroyEffect();
+
+ m_hBeam = CBeam::BeamCreate( EGON_BEAM_SPRITE, 3.5 );
+ 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( pPlayer );
+ m_hBeam->SetScrollRate( 10 );
+ m_hBeam->SetBrightness( 200 );
+ m_hBeam->SetColor( 50, 50, 255 );
+ m_hBeam->SetNoise( 0.2 );
+
+ m_hNoise = CBeam::BeamCreate( EGON_BEAM_SPRITE, 5.0 );
+ m_hNoise->PointEntInit( GetAbsOrigin(), this );
+ m_hNoise->SetEndAttachment( 1 );
+ m_hNoise->AddSpawnFlags( SF_BEAM_TEMPORARY );
+ m_hNoise->SetOwnerEntity( pPlayer );
+ m_hNoise->SetScrollRate( 25 );
+ m_hNoise->SetBrightness( 200 );
+ m_hNoise->SetColor( 50, 50, 255 );
+ m_hNoise->SetNoise( 0.8 );
+
+ m_hSprite = CSprite::SpriteCreate( EGON_FLARE_SPRITE, GetAbsOrigin(), false );
+ m_hSprite->SetScale( 1.0 );
+ m_hSprite->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation );
+ m_hSprite->AddSpawnFlags( SF_SPRITE_TEMPORARY );
+ m_hSprite->SetOwnerEntity( pPlayer );
+#endif
+}
+
+
+void CWeaponEgon::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;
+ }
+ if ( m_hSprite )
+ {
+ m_hSprite->Expand( 10, 500 );
+ m_hSprite = NULL;
+ }
+#endif
+}
+
+void CWeaponEgon::EndAttack( void )
+{
+ StopSound( "Weapon_Gluon.Run" );
+
+ if ( m_fireState != FIRE_OFF )
+ {
+ EmitSound( "Weapon_Gluon.Off" );
+ }
+
+ SetWeaponIdleTime( gpGlobals->curtime + 2.0 );
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.5;
+
+ m_fireState = FIRE_OFF;
+
+ DestroyEffect();
+}
+
+bool CWeaponEgon::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+ EndAttack();
+
+ return BaseClass::Holster( pSwitchingTo );
+}
+
+void CWeaponEgon::WeaponIdle( void )
+{
+ if ( !HasWeaponIdleTimeElapsed() )
+ return;
+
+ if ( m_fireState != FIRE_OFF )
+ EndAttack();
+
+ int iAnim;
+
+ float flRand = random->RandomFloat( 0,1 );
+ float flIdleTime;
+ if ( flRand <= 0.5 )
+ {
+ iAnim = ACT_VM_IDLE;
+ flIdleTime = gpGlobals->curtime + random->RandomFloat( 10, 15 );
+ }
+ else
+ {
+ iAnim = ACT_VM_FIDGET;
+ flIdleTime = gpGlobals->curtime + 3.0;
+ }
+
+ SendWeaponAnim( iAnim );
+
+ SetWeaponIdleTime( flIdleTime );
+}
diff --git a/game/shared/hl1/hl1mp_weapon_gauss.cpp b/game/shared/hl1/hl1mp_weapon_gauss.cpp
new file mode 100644
index 0000000..e40f95d
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_gauss.cpp
@@ -0,0 +1,719 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Gauss
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "npcevent.h"
+#include "hl1mp_basecombatweapon_shared.h"
+//#include "basecombatcharacter.h"
+//#include "AI_BaseNPC.h"
+#include "takedamageinfo.h"
+#ifdef CLIENT_DLL
+#include "hl1/hl1_c_player.h"
+#else
+#include "hl1_player.h"
+#endif
+#include "gamerules.h"
+#include "in_buttons.h"
+#ifdef CLIENT_DLL
+#else
+#include "soundent.h"
+#include "game.h"
+#endif
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+#include "soundenvelope.h"
+//#include "hl1_player.h"
+#include "shake.h"
+#include "effect_dispatch_data.h"
+#ifdef CLIENT_DLL
+#include "c_te_effect_dispatch.h"
+#else
+#include "te_effect_dispatch.h"
+#endif
+#include "SoundEmitterSystem/isoundemittersystembase.h"
+
+#define GAUSS_GLOW_SPRITE "sprites/hotglow.vmt"
+#define GAUSS_BEAM_SPRITE "sprites/smoke.vmt"
+
+
+extern ConVar sk_plr_dmg_gauss;
+
+#ifdef CLIENT_DLL
+#define CWeaponGauss C_WeaponGauss
+#endif
+
+//-----------------------------------------------------------------------------
+// CWeaponGauss
+//-----------------------------------------------------------------------------
+
+
+class CWeaponGauss : public CBaseHL1MPCombatWeapon
+{
+ DECLARE_CLASS( CWeaponGauss, CBaseHL1MPCombatWeapon );
+public:
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+ CWeaponGauss( void );
+
+ void Precache( void );
+ void PrimaryAttack( void );
+ void SecondaryAttack( void );
+ void WeaponIdle( void );
+ void AddViewKick( void );
+ bool Deploy( void );
+ bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
+
+// DECLARE_SERVERCLASS();
+ DECLARE_DATADESC();
+
+private:
+ void StopSpinSound( void );
+ float GetFullChargeTime( void );
+ void StartFire( void );
+ void Fire( Vector vecOrigSrc, Vector vecDir, float flDamage );
+
+private:
+// int m_nAttackState;
+// bool m_bPrimaryFire;
+ CNetworkVar( int, m_nAttackState);
+ CNetworkVar( bool, m_bPrimaryFire);
+
+ CSoundPatch *m_sndCharge;
+};
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponGauss, DT_WeaponGauss );
+
+BEGIN_NETWORK_TABLE( CWeaponGauss, DT_WeaponGauss )
+#ifdef CLIENT_DLL
+ RecvPropInt( RECVINFO( m_nAttackState ) ),
+ RecvPropBool( RECVINFO( m_bPrimaryFire ) ),
+#else
+ SendPropInt( SENDINFO( m_nAttackState ) ),
+ SendPropBool( SENDINFO( m_bPrimaryFire ) ),
+#endif
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CWeaponGauss )
+#ifdef CLIENT_DLL
+ DEFINE_PRED_FIELD( m_nAttackState, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
+ DEFINE_PRED_FIELD( m_bPrimaryFire, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
+#endif
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( weapon_gauss, CWeaponGauss );
+
+PRECACHE_WEAPON_REGISTER( weapon_gauss );
+
+//IMPLEMENT_SERVERCLASS_ST( CWeaponGauss, DT_WeaponGauss )
+//END_SEND_TABLE()
+
+BEGIN_DATADESC( CWeaponGauss )
+ DEFINE_FIELD( m_nAttackState, FIELD_INTEGER ),
+ DEFINE_FIELD( m_bPrimaryFire, FIELD_BOOLEAN ),
+ DEFINE_SOUNDPATCH( m_sndCharge ),
+END_DATADESC()
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CWeaponGauss::CWeaponGauss( void )
+{
+ m_bReloadsSingly = false;
+ m_bFiresUnderwater = false;
+
+ m_bPrimaryFire = false;
+ m_nAttackState = 0;
+ m_sndCharge = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponGauss::Precache( void )
+{
+ PrecacheModel( GAUSS_GLOW_SPRITE );
+ PrecacheModel( GAUSS_BEAM_SPRITE );
+
+ PrecacheScriptSound( "Weapon_Gauss.Zap1" );
+ PrecacheScriptSound( "Weapon_Gauss.Zap2" );
+ PrecacheScriptSound( "Weapon_Gauss.Fire" );
+ PrecacheScriptSound( "Weapon_Gauss.StaticDischarge" );
+ PrecacheScriptSound( "Weapon_Gauss.Spin" );
+
+ BaseClass::Precache();
+}
+
+float CWeaponGauss::GetFullChargeTime( void )
+{
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ return 1.5;
+ }
+ else
+ {
+ return 4;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponGauss::PrimaryAttack( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) < 2 )
+ {
+ WeaponSound( EMPTY );
+ pPlayer->SetNextAttack( gpGlobals->curtime + 0.5 );
+ return;
+ }
+
+//FIXME pPlayer->m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME;
+ m_bPrimaryFire = true;
+
+ pPlayer->RemoveAmmo( 2, m_iPrimaryAmmoType );
+
+ StartFire();
+ m_nAttackState = 0;
+ SetWeaponIdleTime( gpGlobals->curtime + 1.0 );
+ pPlayer->SetNextAttack( gpGlobals->curtime + 0.2 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponGauss::SecondaryAttack( void )
+{
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ // don't fire underwater
+ if ( pPlayer->GetWaterLevel() == 3 )
+ {
+ if ( m_nAttackState != 0 )
+ {
+ EmitSound( "Weapon_Gauss.Zap1" );
+ SendWeaponAnim( ACT_VM_IDLE );
+ m_nAttackState = 0;
+ }
+ else
+ {
+ WeaponSound( EMPTY );
+ }
+
+ m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
+ return;
+ }
+
+ if ( m_nAttackState == 0 )
+ {
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ {
+ WeaponSound( EMPTY );
+ pPlayer->SetNextAttack( gpGlobals->curtime + 0.5 );
+ return;
+ }
+
+ m_bPrimaryFire = false;
+
+ pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType ); // take one ammo just to start the spin
+ pPlayer->m_flNextAmmoBurn = gpGlobals->curtime;
+
+ // spin up
+//FIXME pPlayer->m_iWeaponVolume = GAUSS_PRIMARY_CHARGE_VOLUME;
+
+ SendWeaponAnim( ACT_GAUSS_SPINUP );
+ m_nAttackState = 1;
+ SetWeaponIdleTime( gpGlobals->curtime + 0.5 );
+ pPlayer->m_flStartCharge = gpGlobals->curtime;
+ pPlayer->m_flAmmoStartCharge = gpGlobals->curtime + GetFullChargeTime();
+
+ //Start looping sound
+ if ( m_sndCharge == NULL )
+ {
+ CPASAttenuationFilter filter( this );
+ m_sndCharge = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_WEAPON, "Weapon_Gauss.Spin", ATTN_NORM );
+ }
+
+ if ( m_sndCharge != NULL )
+ {
+ (CSoundEnvelopeController::GetController()).Play( m_sndCharge, 1.0f, 110 );
+ }
+ }
+ else if (m_nAttackState == 1)
+ {
+ if ( HasWeaponIdleTimeElapsed() )
+ {
+ SendWeaponAnim( ACT_GAUSS_SPINCYCLE );
+ m_nAttackState = 2;
+ }
+ }
+ else
+ {
+ // during the charging process, eat one bit of ammo every once in a while
+ if ( gpGlobals->curtime >= pPlayer->m_flNextAmmoBurn && pPlayer->m_flNextAmmoBurn != 1000 )
+ {
+ pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType );
+
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ pPlayer->m_flNextAmmoBurn = gpGlobals->curtime + 0.1;
+ }
+ else
+ {
+ pPlayer->m_flNextAmmoBurn = gpGlobals->curtime + 0.3;
+ }
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ {
+ // out of ammo! force the gun to fire
+ StartFire();
+ m_nAttackState = 0;
+ SetWeaponIdleTime( gpGlobals->curtime + 1.0 );
+ pPlayer->SetNextAttack( gpGlobals->curtime + 1 );
+ return;
+ }
+
+ if ( gpGlobals->curtime >= pPlayer->m_flAmmoStartCharge )
+ {
+ // don't eat any more ammo after gun is fully charged.
+ pPlayer->m_flNextAmmoBurn = 1000;
+ }
+
+ int pitch = ( gpGlobals->curtime - pPlayer->m_flStartCharge ) * ( 150 / GetFullChargeTime() ) + 100;
+ if ( pitch > 250 )
+ pitch = 250;
+
+ // ALERT( at_console, "%d %d %d\n", m_nAttackState, m_iSoundState, pitch );
+
+// if ( m_iSoundState == 0 )
+// ALERT( at_console, "sound state %d\n", m_iSoundState );
+
+ if ( m_sndCharge != NULL )
+ {
+ (CSoundEnvelopeController::GetController()).SoundChangePitch( m_sndCharge, pitch, 0 );
+ }
+
+//FIXME m_pPlayer->m_iWeaponVolume = GAUSS_PRIMARY_CHARGE_VOLUME;
+
+ // m_flTimeWeaponIdle = gpGlobals->curtime + 0.1;
+ if ( pPlayer->m_flStartCharge < gpGlobals->curtime - 10 )
+ {
+ // Player charged up too long. Zap him.
+ EmitSound( "Weapon_Gauss.Zap1" );
+ EmitSound( "Weapon_Gauss.Zap2" );
+
+ m_nAttackState = 0;
+ SetWeaponIdleTime( gpGlobals->curtime + 1.0 );
+ pPlayer->SetNextAttack( gpGlobals->curtime + 1.0 );
+
+#if !defined(CLIENT_DLL )
+ // Add DMG_CRUSH because we don't want any physics force
+ pPlayer->TakeDamage( CTakeDamageInfo( this, this, 50, DMG_SHOCK | DMG_CRUSH ) );
+
+ color32 gaussDamage = {255,128,0,128};
+ UTIL_ScreenFade( pPlayer, gaussDamage, 2, 0.5, FFADE_IN );
+#endif
+
+ SendWeaponAnim( ACT_VM_IDLE );
+
+ StopSpinSound();
+ // Player may have been killed and this weapon dropped, don't execute any more code after this!
+ return;
+ }
+ }
+}
+
+//=========================================================
+// StartFire- since all of this code has to run and then
+// call Fire(), it was easier at this point to rip it out
+// of weaponidle() and make its own function then to try to
+// merge this into Fire(), which has some identical variable names
+//=========================================================
+void CWeaponGauss::StartFire( void )
+{
+ float flDamage;
+
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ Vector vecAiming = pPlayer->GetAutoaimVector( 0 );
+ Vector vecSrc = pPlayer->Weapon_ShootPosition( );
+
+ if ( gpGlobals->curtime - pPlayer->m_flStartCharge > GetFullChargeTime() )
+ {
+ flDamage = 200;
+ }
+ else
+ {
+ flDamage = 200 * (( gpGlobals->curtime - pPlayer->m_flStartCharge) / GetFullChargeTime() );
+ }
+
+ if ( m_bPrimaryFire )
+ {
+ flDamage = sk_plr_dmg_gauss.GetFloat() * g_pGameRules->GetDamageMultiplier();
+ }
+
+ //ALERT ( at_console, "Time:%f Damage:%f\n", gpGlobals->curtime - m_pPlayer->m_flStartCharge, flDamage );
+ Vector vecNewVel = pPlayer->GetAbsVelocity();
+ float flZVel = vecNewVel.z;
+
+ if ( !m_bPrimaryFire )
+ {
+ vecNewVel = vecNewVel - vecAiming * flDamage * 5;
+ pPlayer->SetAbsVelocity( vecNewVel );
+ }
+
+ if ( !g_pGameRules->IsMultiplayer() )
+ {
+ // in deathmatch, gauss can pop you up into the air. Not in single play.
+ vecNewVel.z = flZVel;
+ pPlayer->SetAbsVelocity( vecNewVel );
+ }
+
+ // player "shoot" animation
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ // time until aftershock 'static discharge' sound
+ pPlayer->m_flPlayAftershock = gpGlobals->curtime + random->RandomFloat( 0.3, 0.8 );
+
+ Fire( vecSrc, vecAiming, flDamage );
+}
+
+void CWeaponGauss::Fire( Vector vecOrigSrc, Vector vecDir, float flDamage )
+{
+ CBaseEntity *pIgnore;
+ Vector vecSrc = vecOrigSrc;
+ Vector vecDest = vecSrc + vecDir * MAX_TRACE_LENGTH;
+ bool fFirstBeam = true;
+ bool fHasPunched = false;
+ float flMaxFrac = 1.0;
+ int nMaxHits = 10;
+
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+//FIXME pPlayer->m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME;
+
+ StopSpinSound();
+
+ pIgnore = pPlayer;
+
+// ALERT( at_console, "%f %f\n", tr.flFraction, flMaxFrac );
+
+ while ( flDamage > 10 && nMaxHits > 0 )
+ {
+ trace_t tr;
+
+ nMaxHits--;
+
+ // ALERT( at_console, "." );
+ UTIL_TraceLine( vecSrc, vecDest, MASK_SHOT, pIgnore, COLLISION_GROUP_NONE, &tr );
+
+ if ( tr.allsolid )
+ break;
+
+ CBaseEntity *pEntity = tr.m_pEnt;
+ if (pEntity == NULL)
+ break;
+
+ CBroadcastRecipientFilter filter;
+ CEffectData data6;
+ if ( fFirstBeam )
+ {
+ pPlayer->DoMuzzleFlash();
+ fFirstBeam = false;
+
+ data6.m_vOrigin = tr.endpos;
+// data6.m_nEntIndex = pPlayer->GetViewModel()->entindex();
+#ifdef CLIENT_DLL
+ data6.m_hEntity = pPlayer;
+#else
+ data6.m_nEntIndex = pPlayer->entindex();
+#endif
+ data6.m_fFlags = m_bPrimaryFire;
+ te->DispatchEffect( filter, 0.0, data6.m_vOrigin, "HL1GaussBeam", data6 );
+ }
+ else
+ {
+ data6.m_vOrigin = tr.endpos;
+ data6.m_vStart = vecSrc;
+ data6.m_fFlags = m_bPrimaryFire;
+ te->DispatchEffect( filter, 0.0, data6.m_vOrigin, "HL1GaussBeamReflect", data6 );
+ }
+
+ bool fShouldDamageEntity = ( pEntity->m_takedamage != DAMAGE_NO );
+
+ if ( fShouldDamageEntity )
+ {
+ ClearMultiDamage();
+ CTakeDamageInfo info( this, pPlayer, flDamage, DMG_ENERGYBEAM );
+ CalculateMeleeDamageForce( &info, vecDir, tr.endpos );
+ pEntity->DispatchTraceAttack( info, vecDir, &tr );
+ ApplyMultiDamage();
+ }
+
+ if ( pEntity->IsBSPModel() && !fShouldDamageEntity )
+ {
+ float n;
+
+ pIgnore = NULL;
+
+ n = -DotProduct( tr.plane.normal, vecDir );
+
+ if ( n < 0.5 ) // 60 degrees
+ {
+ // ALERT( at_console, "reflect %f\n", n );
+ // reflect
+ Vector vecReflect;
+
+ vecReflect = 2.0 * tr.plane.normal * n + vecDir;
+ flMaxFrac = flMaxFrac - tr.fraction;
+ vecDir = vecReflect;
+ vecSrc = tr.endpos;// + vecDir * 8;
+ vecDest = vecSrc + vecDir * MAX_TRACE_LENGTH;
+
+#if !defined(CLIENT_DLL)
+ // explode a bit
+ RadiusDamage( CTakeDamageInfo( this, pPlayer, flDamage * n, DMG_BLAST ), tr.endpos, flDamage * n * 2.5, CLASS_NONE, NULL );
+#endif
+
+ CEffectData data1;
+ data1.m_vOrigin = tr.endpos;
+ data1.m_vNormal = tr.plane.normal;
+ data1.m_flMagnitude = flDamage * n;
+ DispatchEffect( "HL1GaussReflect", data1 );
+
+ // lose energy
+ if (n == 0)
+ n = 0.1;
+
+ flDamage = flDamage * (1 - n);
+ }
+ else
+ {
+ // tunnel
+ UTIL_ImpactTrace( &tr, DMG_ENERGYBEAM );
+
+ CEffectData data4;
+ data4.m_vOrigin = tr.endpos;
+ data4.m_flMagnitude = flDamage;
+ DispatchEffect( "HL1GaussWallImpact1", data4 );
+
+ // limit it to one hole punch
+ if ( fHasPunched )
+ break;
+
+ fHasPunched = true;
+
+ // try punching through wall if secondary attack (primary is incapable of breaking through)
+ if ( !m_bPrimaryFire )
+ {
+ trace_t punch_tr;
+
+ UTIL_TraceLine( tr.endpos + vecDir * 8, vecDest, MASK_SHOT, pIgnore, COLLISION_GROUP_NONE, &punch_tr);
+ if ( !punch_tr.allsolid )
+ {
+ trace_t exit_tr;
+ // trace backwards to find exit point
+ UTIL_TraceLine( punch_tr.endpos, tr.endpos, MASK_SHOT, pIgnore, COLLISION_GROUP_NONE, &exit_tr);
+
+ float n = (exit_tr.endpos - tr.endpos).Length( );
+
+ if ( n < flDamage )
+ {
+ if (n == 0)
+ n = 1;
+
+ flDamage -= n;
+
+ CEffectData data2;
+ data2.m_vOrigin = tr.endpos;
+ data2.m_vNormal = vecDir;
+ DispatchEffect( "HL1GaussWallPunchEnter", data2 );
+
+ UTIL_ImpactTrace( &exit_tr, DMG_ENERGYBEAM );
+
+ CEffectData data3;
+ data3.m_vOrigin = exit_tr.endpos;
+ data3.m_vNormal = vecDir;
+ data3.m_flMagnitude = flDamage;
+ DispatchEffect( "HL1GaussWallPunchExit", data3 );
+
+ // ALERT( at_console, "punch %f\n", n );
+
+ // exit blast damage
+ float flDamageRadius;
+
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ flDamageRadius = flDamage * 1.75; // Old code == 2.5
+ }
+ else
+ {
+ flDamageRadius = flDamage * 2.5;
+ }
+
+#if !defined( CLIENT_DLL)
+ RadiusDamage( CTakeDamageInfo( this, pPlayer, flDamage, DMG_BLAST ), exit_tr.endpos + vecDir * 8, flDamageRadius, CLASS_NONE, NULL );
+
+ CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 1024, 3.0 );
+#endif
+
+ vecSrc = exit_tr.endpos + vecDir;
+ }
+ }
+ else
+ {
+ //ALERT( at_console, "blocked %f\n", n );
+ flDamage = 0;
+ }
+ }
+ else
+ {
+ //ALERT( at_console, "blocked solid\n" );
+ if ( m_bPrimaryFire )
+ {
+ // slug doesn't punch through ever with primary
+ // fire, so leave a little glowy bit and make some balls
+ CEffectData data5;
+ data5.m_vOrigin = tr.endpos;
+ data5.m_vNormal = tr.plane.normal;
+ DispatchEffect( "HL1GaussWallImpact2", data5 );
+#if !defined( CLIENT_DLL)
+ CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 600, 0.5 );
+#endif
+ }
+
+ flDamage = 0;
+ }
+
+ }
+ }
+ else
+ {
+ vecSrc = tr.endpos + vecDir;
+ pIgnore = pEntity;
+ }
+ }
+
+ pPlayer->ViewPunch( QAngle( -2, 0, 0 ) );
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+
+ CPASAttenuationFilter filter( this );
+
+ CSoundParameters params;
+ if ( GetParametersForSound( "Weapon_Gauss.Fire", params, NULL ) )
+ {
+ EmitSound_t ep( params );
+ ep.m_flVolume = 0.5 + flDamage * (1.0 / 400.0);
+ EmitSound( filter, entindex(), ep );
+ }
+}
+
+void CWeaponGauss::WeaponIdle( void )
+{
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ // play aftershock static discharge
+ if ( pPlayer->m_flPlayAftershock && pPlayer->m_flPlayAftershock < gpGlobals->curtime )
+ {
+ EmitSound( "Weapon_Gauss.StaticDischarge" );
+ pPlayer->m_flPlayAftershock = 0.0;
+ }
+
+ if ( !HasWeaponIdleTimeElapsed() )
+ return;
+
+ if ( m_nAttackState != 0 )
+ {
+ StartFire();
+ m_nAttackState = 0;
+ SetWeaponIdleTime( gpGlobals->curtime + 2.0 );
+ }
+ else
+ {
+ float flRand = random->RandomFloat( 0, 1 );
+ if ( flRand <= 0.75 )
+ {
+ SendWeaponAnim( ACT_VM_IDLE );
+ SetWeaponIdleTime( gpGlobals->curtime + random->RandomFloat( 10, 15 ) );
+ }
+ else
+ {
+ SendWeaponAnim( ACT_VM_FIDGET );
+ SetWeaponIdleTime( gpGlobals->curtime + 3 );
+ }
+ }
+}
+
+/*
+==================================================
+AddViewKick
+==================================================
+*/
+
+void CWeaponGauss::AddViewKick( void )
+{
+}
+
+bool CWeaponGauss::Deploy( void )
+{
+ if ( DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_VM_DRAW, (char*)GetAnimPrefix() ) )
+ {
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( pPlayer )
+ {
+ pPlayer->m_flPlayAftershock = 0.0;
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool CWeaponGauss::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+
+ StopSpinSound();
+ m_nAttackState = 0;
+
+ return BaseClass::Holster(pSwitchingTo);
+}
+
+void CWeaponGauss::StopSpinSound( void )
+{
+ if ( m_sndCharge != NULL )
+ {
+ (CSoundEnvelopeController::GetController()).SoundDestroy( m_sndCharge );
+ m_sndCharge = NULL;
+ }
+}
diff --git a/game/shared/hl1/hl1mp_weapon_glock.cpp b/game/shared/hl1/hl1mp_weapon_glock.cpp
new file mode 100644
index 0000000..a80b069
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_glock.cpp
@@ -0,0 +1,205 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Glock - hand gun
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "npcevent.h"
+#include "hl1mp_basecombatweapon_shared.h"
+//#include "basecombatcharacter.h"
+//#include "AI_BaseNPC.h"
+#ifdef CLIENT_DLL
+#include "c_baseplayer.h"
+#else
+#include "player.h"
+#endif
+#include "gamerules.h"
+#include "in_buttons.h"
+#ifdef CLIENT_DLL
+#else
+#include "soundent.h"
+#include "game.h"
+#endif
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+
+#ifdef CLIENT_DLL
+#define CWeaponGlock C_WeaponGlock
+#endif
+
+class CWeaponGlock : public CBaseHL1MPCombatWeapon
+{
+ DECLARE_CLASS( CWeaponGlock, CBaseHL1MPCombatWeapon );
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+public:
+
+ CWeaponGlock(void);
+
+ void Precache( void );
+ void PrimaryAttack( void );
+ void SecondaryAttack( void );
+ bool Reload( void );
+ void WeaponIdle( void );
+ void DryFire( void );
+
+private:
+ void GlockFire( float flSpread , float flCycleTime, bool fUseAutoAim );
+};
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponGlock, DT_WeaponGlock );
+
+BEGIN_NETWORK_TABLE( CWeaponGlock, DT_WeaponGlock )
+END_NETWORK_TABLE()
+
+LINK_ENTITY_TO_CLASS( weapon_glock, CWeaponGlock );
+
+BEGIN_PREDICTION_DATA( CWeaponGlock )
+END_PREDICTION_DATA()
+
+PRECACHE_WEAPON_REGISTER( weapon_glock );
+
+
+CWeaponGlock::CWeaponGlock( void )
+{
+ m_bReloadsSingly = false;
+ m_bFiresUnderwater = true;
+}
+
+
+void CWeaponGlock::Precache( void )
+{
+
+ BaseClass::Precache();
+}
+
+
+void CWeaponGlock::DryFire( void )
+{
+ WeaponSound( EMPTY );
+ SendWeaponAnim( ACT_VM_DRYFIRE );
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
+}
+
+
+void CWeaponGlock::PrimaryAttack( void )
+{
+ GlockFire( 0.01, 0.3, TRUE );
+}
+
+
+void CWeaponGlock::SecondaryAttack( void )
+{
+ GlockFire( 0.1, 0.2, FALSE );
+}
+
+
+void CWeaponGlock::GlockFire( float flSpread , float flCycleTime, bool fUseAutoAim )
+{
+ // Only the player fires this way so we can cast
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ if ( m_iClip1 <= 0 )
+ {
+ if ( !m_bFireOnEmpty )
+ {
+ Reload();
+ }
+ else
+ {
+ DryFire();
+ }
+
+ return;
+ }
+
+ WeaponSound( SINGLE );
+
+ pPlayer->DoMuzzleFlash();
+
+ m_iClip1--;
+
+ if ( m_iClip1 == 0 )
+ SendWeaponAnim( ACT_GLOCK_SHOOTEMPTY );
+ else
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + flCycleTime;
+ m_flNextSecondaryAttack = gpGlobals->curtime + flCycleTime;
+
+ Vector vecSrc = pPlayer->Weapon_ShootPosition();
+ Vector vecAiming;
+
+ if ( fUseAutoAim )
+ {
+ vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
+ }
+ else
+ {
+ vecAiming = pPlayer->GetAutoaimVector( 0 );
+ }
+
+// pPlayer->FireBullets( 1, vecSrc, vecAiming, Vector( flSpread, flSpread, flSpread ), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 );
+ FireBulletsInfo_t info( 1, vecSrc, vecAiming, Vector( flSpread, flSpread, flSpread ), MAX_TRACE_LENGTH, m_iPrimaryAmmoType );
+ info.m_pAttacker = pPlayer;
+ pPlayer->FireBullets( info );
+
+ EjectShell( pPlayer, 0 );
+
+ pPlayer->ViewPunch( QAngle( -2, 0, 0 ) );
+#if !defined(CLIENT_DLL)
+ pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
+
+ CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 400, 0.2 );
+#endif
+
+ if ( !m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ {
+ // HEV suit - indicate out of ammo condition
+ pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
+ }
+
+ SetWeaponIdleTime( gpGlobals->curtime + random->RandomFloat( 10, 15 ) );
+}
+
+
+bool CWeaponGlock::Reload( void )
+{
+ bool iResult;
+
+ if ( m_iClip1 == 0 )
+ iResult = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_GLOCK_SHOOT_RELOAD );
+ else
+ iResult = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD );
+
+ return iResult;
+}
+
+
+
+void CWeaponGlock::WeaponIdle( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( pPlayer )
+ {
+ pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
+ }
+
+ // only idle if the slid isn't back
+ if ( m_iClip1 != 0 )
+ {
+ BaseClass::WeaponIdle();
+ }
+}
diff --git a/game/shared/hl1/hl1mp_weapon_handgrenade.cpp b/game/shared/hl1/hl1mp_weapon_handgrenade.cpp
new file mode 100644
index 0000000..5676138
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_handgrenade.cpp
@@ -0,0 +1,456 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Hand grenade
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "npcevent.h"
+#include "hl1mp_basecombatweapon_shared.h"
+//#include "basecombatcharacter.h"
+//#include "AI_BaseNPC.h"
+#ifdef CLIENT_DLL
+#include "hl1/hl1_c_player.h"
+#else
+#include "hl1_player.h"
+#endif
+#include "gamerules.h"
+#include "in_buttons.h"
+#ifdef CLIENT_DLL
+#else
+#include "soundent.h"
+#include "game.h"
+#endif
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+#ifdef CLIENT_DLL
+#else
+#include "hl1_basegrenade.h"
+#endif
+
+
+#define HANDGRENADE_MODEL "models/w_grenade.mdl"
+
+
+#ifndef CLIENT_DLL
+
+extern ConVar sk_plr_dmg_grenade;
+
+//-----------------------------------------------------------------------------
+// CHandGrenade
+//-----------------------------------------------------------------------------
+LINK_ENTITY_TO_CLASS( grenade_hand, CHandGrenade );
+
+BEGIN_DATADESC( CHandGrenade )
+ DEFINE_ENTITYFUNC( BounceTouch ),
+END_DATADESC()
+
+
+void CHandGrenade::Spawn( void )
+{
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
+ SetSolid( SOLID_BBOX );
+ AddSolidFlags( FSOLID_NOT_STANDABLE );
+
+ SetModel( HANDGRENADE_MODEL );
+
+ UTIL_SetSize( this, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) );
+
+ m_bHasWarnedAI = false;
+}
+
+
+void CHandGrenade::Precache( void )
+{
+ BaseClass::Precache( );
+
+ PrecacheScriptSound( "Weapon_HandGrenade.GrenadeBounce" );
+
+ PrecacheModel( HANDGRENADE_MODEL );
+}
+
+
+void CHandGrenade::ShootTimed( CBaseCombatCharacter *pOwner, Vector vecVelocity, float flTime )
+{
+ SetAbsVelocity( vecVelocity );
+
+ SetThrower( pOwner );
+ SetOwnerEntity( pOwner );
+
+ SetTouch( &CHandGrenade::BounceTouch ); // Bounce if touched
+
+ m_flDetonateTime = gpGlobals->curtime + flTime;
+ SetThink( &CBaseGrenade::TumbleThink );
+ SetNextThink( gpGlobals->curtime + 0.1 );
+ if ( flTime < 0.1 )
+ {
+ SetNextThink( gpGlobals->curtime );
+ SetAbsVelocity( vec3_origin );
+ }
+
+// SetSequence( SelectWeightedSequence( ACT_GRENADE_TOSS ) );
+ SetSequence( 0 );
+ m_flPlaybackRate = 1.0;
+
+ SetAbsAngles( QAngle( 0,0,60) );
+
+ AngularImpulse angImpulse;
+ angImpulse[0] = random->RandomInt( -200, 200 );
+ angImpulse[1] = random->RandomInt( 400, 500 );
+ angImpulse[2] = random->RandomInt( -100, 100 );
+ ApplyLocalAngularVelocityImpulse( angImpulse );
+
+ SetGravity( UTIL_ScaleForGravity( 400 ) ); // use a lower gravity for grenades to make them easier to see
+ SetFriction( 0.8 );
+
+ SetDamage( sk_plr_dmg_grenade.GetFloat() );
+ SetDamageRadius( GetDamage() * 2.5 );
+}
+
+
+void CHandGrenade ::BounceSound( void )
+{
+ EmitSound( "Weapon_HandGrenade.GrenadeBounce" );
+}
+
+
+void CHandGrenade::BounceTouch( CBaseEntity *pOther )
+{
+ if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER | FSOLID_VOLUME_CONTENTS) )
+ return;
+
+ // don't hit the guy that launched this grenade
+ if ( pOther == GetThrower() )
+ return;
+
+ // Do a special test for players
+ if ( pOther->IsPlayer() )
+ {
+ // Never hit a player again (we'll explode and fixup anyway)
+ SetCollisionGroup( COLLISION_GROUP_DEBRIS );
+ }
+ // only do damage if we're moving fairly fast
+ if ( (pOther->m_takedamage != DAMAGE_NO) && (m_flNextAttack < gpGlobals->curtime && GetAbsVelocity().Length() > 100))
+ {
+ if ( GetThrower() )
+ {
+ trace_t tr;
+ tr = CBaseEntity::GetTouchTrace( );
+ ClearMultiDamage( );
+ Vector forward;
+ AngleVectors( GetAbsAngles(), &forward );
+
+ CTakeDamageInfo info( this, GetThrower(), 1, DMG_CLUB );
+ CalculateMeleeDamageForce( &info, forward, tr.endpos );
+ pOther->DispatchTraceAttack( info, forward, &tr );
+ ApplyMultiDamage();
+ }
+ m_flNextAttack = gpGlobals->curtime + 1.0; // debounce
+ }
+
+ Vector vecTestVelocity;
+ // m_vecAngVelocity = Vector (300, 300, 300);
+
+ // this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical
+ // or thrown very far tend to slow down too quickly for me to always catch just by testing velocity.
+ // trimming the Z velocity a bit seems to help quite a bit.
+ vecTestVelocity = GetAbsVelocity();
+ vecTestVelocity.z *= 0.45;
+
+ if ( !m_bHasWarnedAI && vecTestVelocity.Length() <= 60 )
+ {
+ // grenade is moving really slow. It's probably very close to where it will ultimately stop moving.
+ // emit the danger sound.
+
+ // register a radius louder than the explosion, so we make sure everyone gets out of the way
+ CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), m_flDamage / 0.4, 0.3 );
+ m_bHasWarnedAI = TRUE;
+ }
+
+ // HACKHACK - On ground isn't always set, so look for ground underneath
+ trace_t tr;
+ UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
+
+ if ( tr.fraction < 1.0 )
+ {
+ // add a bit of static friction
+// SetAbsVelocity( GetAbsVelocity() * 0.8 );
+ SetSequence( SelectWeightedSequence( ACT_IDLE ) );
+ SetAbsAngles( vec3_angle );
+ }
+
+ // play bounce sound
+ BounceSound();
+
+ m_flPlaybackRate = GetAbsVelocity().Length() / 200.0;
+ if (m_flPlaybackRate > 1.0)
+ m_flPlaybackRate = 1;
+ else if (m_flPlaybackRate < 0.5)
+ m_flPlaybackRate = 0;
+}
+
+#endif
+
+#ifdef CLIENT_DLL
+#define CWeaponHandGrenade C_WeaponHandGrenade
+#endif
+
+//-----------------------------------------------------------------------------
+// CWeaponHandGrenade
+//-----------------------------------------------------------------------------
+
+class CWeaponHandGrenade : public CBaseHL1MPCombatWeapon
+{
+ DECLARE_CLASS( CWeaponHandGrenade, CBaseHL1MPCombatWeapon );
+public:
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+ CWeaponHandGrenade( void );
+
+ void Precache( void );
+ void PrimaryAttack( void );
+ void WeaponIdle( void );
+ bool Deploy( void );
+ bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
+
+// DECLARE_SERVERCLASS();
+ DECLARE_DATADESC();
+
+private:
+// float m_flStartThrow;
+// float m_flReleaseThrow;
+ CNetworkVar( float, m_flStartThrow );
+ CNetworkVar( float, m_flReleaseThrow );
+};
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponHandGrenade, DT_WeaponHandGrenade );
+
+BEGIN_NETWORK_TABLE( CWeaponHandGrenade, DT_WeaponHandGrenade )
+#ifdef CLIENT_DLL
+ RecvPropFloat( RECVINFO( m_flStartThrow ) ),
+ RecvPropFloat( RECVINFO( m_flReleaseThrow ) ),
+#else
+ SendPropFloat( SENDINFO( m_flStartThrow ) ),
+ SendPropFloat( SENDINFO( m_flReleaseThrow ) ),
+#endif
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CWeaponHandGrenade )
+#ifdef CLIENT_DLL
+ DEFINE_PRED_FIELD( m_flStartThrow, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
+ DEFINE_PRED_FIELD( m_flReleaseThrow, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
+#endif
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( weapon_handgrenade, CWeaponHandGrenade );
+
+PRECACHE_WEAPON_REGISTER( weapon_handgrenade );
+
+//IMPLEMENT_SERVERCLASS_ST( CWeaponHandGrenade, DT_WeaponHandGrenade )
+//END_SEND_TABLE()
+
+BEGIN_DATADESC( CWeaponHandGrenade )
+END_DATADESC()
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CWeaponHandGrenade::CWeaponHandGrenade( void )
+{
+ m_bReloadsSingly = false;
+ m_bFiresUnderwater = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponHandGrenade::Precache( void )
+{
+#ifndef CLIENT_DLL
+ UTIL_PrecacheOther( "grenade_hand" );
+#endif
+
+ BaseClass::Precache();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponHandGrenade::PrimaryAttack( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ if ( ( m_flStartThrow <= 0 ) && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) > 0 )
+ {
+ m_flStartThrow = gpGlobals->curtime;
+ m_flReleaseThrow = 0;
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+ SetWeaponIdleTime( gpGlobals->curtime + 0.5 );
+ }
+}
+
+
+void CWeaponHandGrenade::WeaponIdle( void )
+{
+ if ( m_flReleaseThrow == 0 && m_flStartThrow )
+ m_flReleaseThrow = gpGlobals->curtime;
+
+ if ( !HasWeaponIdleTimeElapsed() )
+ return;
+
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ if ( m_flStartThrow )
+ {
+ Vector vecAiming = pPlayer->GetAutoaimVector( 0 );
+
+ QAngle angThrow;
+ VectorAngles( vecAiming, angThrow );
+
+ Vector vecUp;
+ Vector vecRight;
+ AngleVectors( angThrow, NULL, &vecRight, &vecUp );
+
+ if ( angThrow.x > 180 ) // player is pitching up
+ angThrow.x = -15 - ( 360 - angThrow.x ) * ( ( 90 - 10 ) / 90.0 );
+ else // player is pitching down
+ angThrow.x = -15 + angThrow.x * ( ( 90 + 10 ) / 90.0 );
+
+ float flVel = ( 90 - angThrow.x ) * 4;
+ if ( flVel > 500 )
+ flVel = 500;
+
+ Vector vecFwd;
+ AngleVectors( angThrow, &vecFwd );
+
+ Vector vecSrc = pPlayer->EyePosition() + vecFwd * 16;
+ Vector vecThrow = vecFwd * flVel + pPlayer->GetAbsVelocity();
+
+ QAngle angles;
+ VectorAngles( vecThrow, angles );
+#ifndef CLIENT_DLL
+ CHandGrenade *pGrenade = (CHandGrenade*)Create( "grenade_hand", vecSrc, angles );
+ if ( pGrenade )
+ {
+ // always explode 3 seconds after the pin was pulled
+ float flTime = m_flStartThrow - gpGlobals->curtime + 3.0;
+ if ( flTime < 0 )
+ {
+ flTime = 0;
+ }
+
+ pGrenade->ShootTimed( pPlayer, vecThrow, flTime );
+ }
+#endif
+
+ if ( flVel < 500 )
+ {
+ SendWeaponAnim( ACT_HANDGRENADE_THROW1 );
+ }
+ else if ( flVel < 1000 )
+ {
+ SendWeaponAnim( ACT_HANDGRENADE_THROW2 );
+ }
+ else
+ {
+ SendWeaponAnim( ACT_HANDGRENADE_THROW3 );
+ }
+
+ // player "shoot" animation
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ m_flReleaseThrow = 0;
+ m_flStartThrow = 0;
+
+ SetWeaponIdleTime( gpGlobals->curtime + 0.5 );
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.5;
+
+ pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType );
+
+ return;
+ }
+ else if ( m_flReleaseThrow > 0 )
+ {
+ // we've finished the throw, restart.
+ m_flStartThrow = 0;
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) > 0 )
+ {
+ SendWeaponAnim( ACT_VM_DRAW );
+ }
+ else
+ {
+// RetireWeapon();
+ return;
+ }
+
+ SetWeaponIdleTime( gpGlobals->curtime + random->RandomFloat( 10, 15 ) );
+ m_flReleaseThrow = -1;
+ return;
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) > 0 )
+ {
+ float flRand = random->RandomFloat( 0, 1 );
+ if ( flRand <= 0.75 )
+ {
+ SendWeaponAnim( ACT_VM_IDLE );
+ SetWeaponIdleTime( gpGlobals->curtime + random->RandomFloat( 10, 15 ) );// how long till we do this again.
+ }
+ else
+ {
+ SendWeaponAnim( ACT_VM_FIDGET );
+ }
+ }
+}
+
+bool CWeaponHandGrenade::Deploy( void )
+{
+ m_flReleaseThrow = -1;
+
+ return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_VM_DRAW, (char*)GetAnimPrefix() );
+}
+
+bool CWeaponHandGrenade::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( !pPlayer )
+ {
+ return false;
+ }
+
+ if ( m_flStartThrow > 0 )
+ {
+ return false;
+ }
+
+ if ( !BaseClass::Holster( pSwitchingTo ) )
+ {
+ return false;
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ {
+#ifndef CLIENT_DLL
+ SetThink( &CWeaponHandGrenade::DestroyItem );
+ SetNextThink( gpGlobals->curtime + 0.1 );
+#endif
+ }
+
+ pPlayer->SetNextAttack( gpGlobals->curtime + 0.5 );
+
+ return true;
+}
diff --git a/game/shared/hl1/hl1mp_weapon_hornetgun.cpp b/game/shared/hl1/hl1mp_weapon_hornetgun.cpp
new file mode 100644
index 0000000..e35c3dc
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_hornetgun.cpp
@@ -0,0 +1,339 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Hornetgun
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "npcevent.h"
+#include "hl1mp_basecombatweapon_shared.h"
+//#include "basecombatcharacter.h"
+//#include "AI_BaseNPC.h"
+#include "gamerules.h"
+#include "in_buttons.h"
+#ifdef CLIENT_DLL
+#include "hl1/c_hl1mp_player.h"
+#else
+#include "hl1mp_player.h"
+#include "soundent.h"
+#include "game.h"
+#endif
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+#if !defined(CLIENT_DLL)
+#include "hl1_npc_hornet.h"
+#endif
+
+
+//-----------------------------------------------------------------------------
+// CWeaponHgun
+//-----------------------------------------------------------------------------
+
+#ifdef CLIENT_DLL
+#define CWeaponHgun C_WeaponHgun
+#endif
+
+class CWeaponHgun : public CBaseHL1MPCombatWeapon
+{
+ DECLARE_CLASS( CWeaponHgun, CBaseHL1MPCombatWeapon );
+public:
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+ CWeaponHgun( void );
+
+ void Precache( void );
+ void PrimaryAttack( void );
+ void SecondaryAttack( void );
+ void WeaponIdle( void );
+ bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
+ bool Reload( void );
+
+ virtual void ItemPostFrame( void );
+
+// DECLARE_SERVERCLASS();
+ DECLARE_DATADESC();
+
+private:
+
+// float m_flRechargeTime;
+// int m_iFirePhase;
+
+ CNetworkVar( float, m_flRechargeTime );
+ CNetworkVar( int, m_iFirePhase );
+};
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponHgun, DT_WeaponHgun );
+
+BEGIN_NETWORK_TABLE( CWeaponHgun, DT_WeaponHgun )
+#ifdef CLIENT_DLL
+ RecvPropFloat( RECVINFO( m_flRechargeTime ) ),
+ RecvPropInt( RECVINFO( m_iFirePhase ) ),
+#else
+ SendPropFloat( SENDINFO( m_flRechargeTime ) ),
+ SendPropInt( SENDINFO( m_iFirePhase ) ),
+#endif
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CWeaponHgun )
+#ifdef CLIENT_DLL
+ DEFINE_PRED_FIELD( m_flRechargeTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
+ DEFINE_PRED_FIELD( m_iFirePhase, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
+#endif
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( weapon_hornetgun, CWeaponHgun );
+
+PRECACHE_WEAPON_REGISTER( weapon_hornetgun );
+
+//IMPLEMENT_SERVERCLASS_ST( CWeaponHgun, DT_WeaponHgun )
+//END_SEND_TABLE()
+
+BEGIN_DATADESC( CWeaponHgun )
+ DEFINE_FIELD( m_flRechargeTime, FIELD_TIME ),
+ DEFINE_FIELD( m_iFirePhase, FIELD_INTEGER ),
+END_DATADESC()
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CWeaponHgun::CWeaponHgun( void )
+{
+ m_bReloadsSingly = false;
+ m_bFiresUnderwater = true;
+
+ m_flRechargeTime = 0.0;
+ m_iFirePhase = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponHgun::Precache( void )
+{
+#ifndef CLIENT_DLL
+ UTIL_PrecacheOther( "hornet" );
+#endif
+
+ BaseClass::Precache();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponHgun::PrimaryAttack( void )
+{
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ {
+ return;
+ }
+
+ WeaponSound( SINGLE );
+#if !defined(CLIENT_DLL)
+ CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 200, 0.2 );
+#endif
+ pPlayer->DoMuzzleFlash();
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ Vector vForward, vRight, vUp;
+ QAngle vecAngles;
+
+ pPlayer->EyeVectors( &vForward, &vRight, &vUp );
+ VectorAngles( vForward, vecAngles );
+
+#if !defined(CLIENT_DLL)
+ CBaseEntity *pHornet = CBaseEntity::Create( "hornet", pPlayer->Weapon_ShootPosition() + vForward * 16 + vRight * 8 + vUp * -12, vecAngles, pPlayer );
+ pHornet->SetAbsVelocity( vForward * 300 );
+#endif
+
+ m_flRechargeTime = gpGlobals->curtime + 0.5;
+
+ pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType );
+
+ pPlayer->ViewPunch( QAngle( -2, 0, 0 ) );
+
+ m_flNextPrimaryAttack = m_flNextPrimaryAttack + 0.25;
+
+ if (m_flNextPrimaryAttack < gpGlobals->curtime )
+ {
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.25;
+ }
+
+ SetWeaponIdleTime( random->RandomFloat( 10, 15 ) );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponHgun::SecondaryAttack( void )
+{
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ {
+ return;
+ }
+
+ WeaponSound( SINGLE );
+#if !defined(CLIENT_DLL)
+ CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 200, 0.2 );
+#endif
+ pPlayer->DoMuzzleFlash();
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ CBaseEntity *pHornet;
+ Vector vecSrc;
+
+ Vector vForward, vRight, vUp;
+ QAngle vecAngles;
+
+ pPlayer->EyeVectors( &vForward, &vRight, &vUp );
+ VectorAngles( vForward, vecAngles );
+
+ vecSrc = pPlayer->Weapon_ShootPosition() + vForward * 16 + vRight * 8 + vUp * -12;
+
+ m_iFirePhase++;
+ switch ( m_iFirePhase )
+ {
+ case 1:
+ vecSrc = vecSrc + vUp * 8;
+ break;
+ case 2:
+ vecSrc = vecSrc + vUp * 8;
+ vecSrc = vecSrc + vRight * 8;
+ break;
+ case 3:
+ vecSrc = vecSrc + vRight * 8;
+ break;
+ case 4:
+ vecSrc = vecSrc + vUp * -8;
+ vecSrc = vecSrc + vRight * 8;
+ break;
+ case 5:
+ vecSrc = vecSrc + vUp * -8;
+ break;
+ case 6:
+ vecSrc = vecSrc + vUp * -8;
+ vecSrc = vecSrc + vRight * -8;
+ break;
+ case 7:
+ vecSrc = vecSrc + vRight * -8;
+ break;
+ case 8:
+ vecSrc = vecSrc + vUp * 8;
+ vecSrc = vecSrc + vRight * -8;
+ m_iFirePhase = 0;
+ break;
+ }
+
+#ifdef CLIENT_DLL
+ pHornet = NULL;
+#else
+ pHornet = CBaseEntity::Create( "hornet", vecSrc, vecAngles, pPlayer );
+ pHornet->SetAbsVelocity( vForward * 1200 );
+ pHornet->SetThink( &CNPC_Hornet::StartDart );
+#endif
+
+ m_flRechargeTime = gpGlobals->curtime + 0.5;
+
+ pPlayer->ViewPunch( QAngle( -2, 0, 0 ) );
+ pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType );
+
+ m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + 0.1;
+ SetWeaponIdleTime( random->RandomFloat( 10, 15 ) );
+}
+
+void CWeaponHgun::WeaponIdle( void )
+{
+ if ( !HasWeaponIdleTimeElapsed() )
+ return;
+
+ int iAnim;
+ float flRand = random->RandomFloat( 0, 1 );
+ if ( flRand <= 0.75 )
+ {
+ iAnim = ACT_VM_IDLE;
+ }
+ else
+ {
+ iAnim = ACT_VM_FIDGET;
+ }
+
+ SendWeaponAnim( iAnim );
+}
+
+bool CWeaponHgun::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+ bool bRet;
+
+ bRet = BaseClass::Holster( pSwitchingTo );
+
+ if ( bRet )
+ {
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( pPlayer )
+ {
+#if !defined(CLIENT_DLL)
+ //!!!HACKHACK - can't select hornetgun if it's empty! no way to get ammo for it, either.
+ int iCount = pPlayer->GetAmmoCount( m_iPrimaryAmmoType );
+ if ( iCount <= 0 )
+ {
+ pPlayer->GiveAmmo( iCount+1, m_iPrimaryAmmoType, true );
+ }
+#endif
+ }
+ }
+
+ return bRet;
+}
+
+bool CWeaponHgun::Reload( void )
+{
+ if ( m_flRechargeTime >= gpGlobals->curtime )
+ {
+ return true;
+ }
+
+ CHL1_Player *pPlayer = ToHL1Player( GetOwner() );
+ if ( !pPlayer )
+ {
+ return true;
+ }
+
+#ifdef CLIENT_DLL
+#else
+ if ( !g_pGameRules->CanHaveAmmo( pPlayer, m_iPrimaryAmmoType ) )
+ return true;
+
+ while ( ( m_flRechargeTime < gpGlobals->curtime ) && g_pGameRules->CanHaveAmmo( pPlayer, m_iPrimaryAmmoType ) )
+ {
+ pPlayer->GiveAmmo( 1, m_iPrimaryAmmoType, true );
+ m_flRechargeTime += 0.5;
+ }
+#endif
+
+ return true;
+}
+
+void CWeaponHgun::ItemPostFrame( void )
+{
+ Reload();
+
+ BaseClass::ItemPostFrame();
+}
diff --git a/game/shared/hl1/hl1mp_weapon_mp5.cpp b/game/shared/hl1/hl1mp_weapon_mp5.cpp
new file mode 100644
index 0000000..46b7fb9
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_mp5.cpp
@@ -0,0 +1,237 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+//#include "basecombatweapon.h"
+#include "hl1mp_basecombatweapon_shared.h"
+#include "npcevent.h"
+//#include "basecombatcharacter.h"
+//#include "AI_BaseNPC.h"
+#ifdef CLIENT_DLL
+#include "hl1/hl1_c_player.h"
+#else
+#include "player.h"
+#endif
+#include "hl1mp_weapon_mp5.h"
+//#include "hl1_weapon_mp5.h"
+#ifdef CLIENT_DLL
+#else
+#include "hl1_grenade_mp5.h"
+#endif
+#include "gamerules.h"
+#ifdef CLIENT_DLL
+#else
+#include "soundent.h"
+#include "game.h"
+#endif
+#include "in_buttons.h"
+#include "engine/IEngineSound.h"
+
+extern ConVar sk_plr_dmg_mp5_grenade;
+extern ConVar sk_max_mp5_grenade;
+extern ConVar sk_mp5_grenade_radius;
+
+//=========================================================
+//=========================================================
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponMP5, DT_WeaponMP5 );
+
+BEGIN_NETWORK_TABLE( CWeaponMP5, DT_WeaponMP5 )
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CWeaponMP5 )
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( weapon_mp5, CWeaponMP5 );
+
+PRECACHE_WEAPON_REGISTER(weapon_mp5);
+
+//IMPLEMENT_SERVERCLASS_ST( CWeaponMP5, DT_WeaponMP5 )
+//END_SEND_TABLE()
+
+BEGIN_DATADESC( CWeaponMP5 )
+END_DATADESC()
+
+CWeaponMP5::CWeaponMP5( )
+{
+ m_bReloadsSingly = false;
+ m_bFiresUnderwater = false;
+}
+
+void CWeaponMP5::Precache( void )
+{
+ BaseClass::Precache();
+
+#ifndef CLIENT_DLL
+ UTIL_PrecacheOther( "grenade_mp5" );
+#endif
+}
+
+
+void CWeaponMP5::PrimaryAttack( void )
+{
+ // Only the player fires this way so we can cast
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ if ( m_iClip1 <= 0 )
+ {
+ DryFire();
+ return;
+ }
+
+ WeaponSound( SINGLE );
+
+ pPlayer->DoMuzzleFlash();
+
+ m_iClip1--;
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.1;
+
+ Vector vecSrc = pPlayer->Weapon_ShootPosition();
+ Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
+
+ if ( !g_pGameRules->IsMultiplayer() )
+ {
+ // optimized multiplayer. Widened to make it easier to hit a moving player
+// pPlayer->FireBullets( 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2 );
+ FireBulletsInfo_t info( 1, vecSrc, vecAiming, VECTOR_CONE_6DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType );
+ info.m_pAttacker = pPlayer;
+ info.m_iTracerFreq = 2;
+
+ pPlayer->FireBullets( info );
+ }
+ else
+ {
+ // single player spread
+// pPlayer->FireBullets( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2 );
+ FireBulletsInfo_t info( 1, vecSrc, vecAiming, VECTOR_CONE_3DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType );
+ info.m_pAttacker = pPlayer;
+ info.m_iTracerFreq = 2;
+
+ pPlayer->FireBullets( info );
+ }
+
+ EjectShell( pPlayer, 0 );
+
+ pPlayer->ViewPunch( QAngle( random->RandomFloat( -2, 2 ), 0, 0 ) );
+#ifdef CLIENT_DLL
+ pPlayer->DoMuzzleFlash();
+#else
+ pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
+#endif
+
+#ifdef CLIENT_DLL
+#else
+ CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 600, 0.2 );
+#endif
+
+ if ( !m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ {
+ // HEV suit - indicate out of ammo condition
+ pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
+ }
+
+ SetWeaponIdleTime( gpGlobals->curtime + random->RandomFloat( 10, 15 ) );
+}
+
+
+void CWeaponMP5::SecondaryAttack( void )
+{
+ // Only the player fires this way so we can cast
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ if (!pPlayer)
+ {
+ return;
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iSecondaryAmmoType ) <= 0 )
+ {
+ DryFire( );
+ return;
+ }
+
+ WeaponSound(WPN_DOUBLE);
+
+ pPlayer->DoMuzzleFlash();
+
+ Vector vecSrc = pPlayer->Weapon_ShootPosition();
+ Vector vecThrow = pPlayer->GetAutoaimVector( 0 ) * 800;
+ QAngle angGrenAngle;
+
+ VectorAngles( vecThrow, angGrenAngle );
+
+#ifdef CLIENT_DLL
+#else
+ CGrenadeMP5 * m_pMyGrenade = (CGrenadeMP5*)Create( "grenade_mp5", vecSrc, angGrenAngle, GetOwner() );
+ m_pMyGrenade->SetAbsVelocity( vecThrow );
+ m_pMyGrenade->SetLocalAngularVelocity( QAngle( random->RandomFloat( -100, -500 ), 0, 0 ) );
+ m_pMyGrenade->SetMoveType( MOVETYPE_FLYGRAVITY );
+ m_pMyGrenade->SetThrower( GetOwner() );
+ m_pMyGrenade->SetDamage( sk_plr_dmg_mp5_grenade.GetFloat() * g_pGameRules->GetDamageMultiplier() );
+#endif
+
+ SendWeaponAnim( ACT_VM_SECONDARYATTACK );
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ pPlayer->ViewPunch( QAngle( -10, 0, 0 ) );
+
+ // Register a muzzleflash for the AI.
+#if !defined(CLIENT_DLL)
+ pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
+#endif
+
+#ifdef CLIENT_DLL
+#else
+ CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 600, 0.2 );
+#endif
+
+ // Decrease ammo
+ pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType );
+ if ( pPlayer->GetAmmoCount( m_iSecondaryAmmoType ) <= 0 )
+ {
+ // HEV suit - indicate out of ammo condition
+ pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
+ }
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 1.0;
+ SetWeaponIdleTime( gpGlobals->curtime + 5.0 );
+}
+
+
+void CWeaponMP5::DryFire( void )
+{
+ WeaponSound( EMPTY );
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.15;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.15;
+}
+
+
+void CWeaponMP5::WeaponIdle( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( pPlayer )
+ {
+ pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
+ }
+
+ bool bElapsed = HasWeaponIdleTimeElapsed();
+
+ BaseClass::WeaponIdle();
+
+ if( bElapsed )
+ SetWeaponIdleTime( gpGlobals->curtime + random->RandomInt( 3, 5 ) );
+}
diff --git a/game/shared/hl1/hl1mp_weapon_mp5.h b/game/shared/hl1/hl1mp_weapon_mp5.h
new file mode 100644
index 0000000..427c630
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_mp5.h
@@ -0,0 +1,53 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Projectile shot from the MP5
+//
+// $Workfile: $
+// $Date: $
+//
+//-----------------------------------------------------------------------------
+// $Log: $
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef WEAPONMP5_H
+#define WEAPONMP5_H
+
+#ifdef CLIENT_DLL
+#else
+#include "hl1_basegrenade.h"
+#endif
+#include "hl1mp_basecombatweapon_shared.h"
+
+#ifdef CLIENT_DLL
+class CGrenadeMP5;
+#else
+#endif
+
+#ifdef CLIENT_DLL
+#define CWeaponMP5 C_WeaponMP5
+#endif
+
+class CWeaponMP5 : public CBaseHL1MPCombatWeapon
+{
+ DECLARE_CLASS( CWeaponMP5, CBaseHL1MPCombatWeapon );
+public:
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+ CWeaponMP5();
+
+ void Precache( void );
+ void PrimaryAttack( void );
+ void SecondaryAttack( void );
+ void DryFire( void );
+ void WeaponIdle( void );
+
+// DECLARE_SERVERCLASS();
+ DECLARE_DATADESC();
+};
+
+
+#endif //WEAPONMP5_H
diff --git a/game/shared/hl1/hl1mp_weapon_rpg.cpp b/game/shared/hl1/hl1mp_weapon_rpg.cpp
new file mode 100644
index 0000000..98cf2fa
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_rpg.cpp
@@ -0,0 +1,1080 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: RPG
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "npcevent.h"
+#include "in_buttons.h"
+#include "hl1mp_basecombatweapon_shared.h"
+#include "hl1mp_weapon_rpg.h"
+
+#ifdef CLIENT_DLL
+#include "hl1/c_hl1mp_player.h"
+#include "model_types.h"
+#include "beamdraw.h"
+#include "fx_line.h"
+#include "view.h"
+#else
+#include "basecombatcharacter.h"
+#include "movie_explosion.h"
+#include "hl1mp_player.h"
+#include "rope.h"
+#include "soundent.h"
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+#include "explode.h"
+#include "util.h"
+#include "te_effect_dispatch.h"
+#include "shake.h"
+#endif
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+extern ConVar sk_plr_dmg_rpg;
+
+
+void TE_BeamFollow( IRecipientFilter& filter, float delay,
+ int iEntIndex, int modelIndex, int haloIndex, float life, float width, float endWidth,
+ float fadeLength,float r, float g, float b, float a );
+
+#define RPG_LASER_SPRITE "sprites/redglow_mp1"
+
+class CLaserDot : public CBaseEntity
+{
+ DECLARE_CLASS( CLaserDot, CBaseEntity );
+public:
+
+ CLaserDot( void );
+ ~CLaserDot( void );
+
+ static CLaserDot *Create( const Vector &origin, CBaseEntity *pOwner = NULL, bool bVisibleDot = true );
+
+ void SetTargetEntity( CBaseEntity *pTarget ) { m_hTargetEnt = pTarget; }
+ CBaseEntity *GetTargetEntity( void ) { return m_hTargetEnt; }
+
+ void SetLaserPosition( const Vector &origin, const Vector &normal );
+ Vector GetChasePosition();
+ void TurnOn( void );
+ void TurnOff( void );
+ bool IsOn() const { return m_bIsOn; }
+
+ void Toggle( void );
+
+ int ObjectCaps() { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DONT_SAVE; }
+
+ void MakeInvisible( void );
+
+#ifdef CLIENT_DLL
+
+ virtual bool IsTransparent( void ) { return true; }
+ virtual RenderGroup_t GetRenderGroup( void ) { return RENDER_GROUP_TRANSLUCENT_ENTITY; }
+ virtual int DrawModel( int flags );
+ virtual void OnDataChanged( DataUpdateType_t updateType );
+ virtual bool ShouldDraw( void ) { return (IsEffectActive(EF_NODRAW)==false); }
+
+ CMaterialReference m_hSpriteMaterial;
+#endif
+
+protected:
+ Vector m_vecSurfaceNormal;
+ EHANDLE m_hTargetEnt;
+ bool m_bVisibleLaserDot;
+// bool m_bIsOn;
+ CNetworkVar( bool, m_bIsOn );
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_DATADESC();
+public:
+ CLaserDot *m_pNext;
+};
+
+
+#ifndef CLIENT_DLL
+
+//=============================================================================
+// RPG Rocket
+//=============================================================================
+
+
+BEGIN_DATADESC( CRpgRocket )
+ DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ),
+ DEFINE_FIELD( m_vecAbsVelocity, FIELD_VECTOR ),
+ DEFINE_FIELD( m_flIgniteTime, FIELD_TIME ),
+ //DEFINE_FIELD( m_iTrail, FIELD_INTEGER ),
+
+ // Function Pointers
+ DEFINE_ENTITYFUNC( RocketTouch ),
+ DEFINE_THINKFUNC( IgniteThink ),
+ DEFINE_THINKFUNC( SeekThink ),
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( rpg_rocket, CRpgRocket );
+
+IMPLEMENT_SERVERCLASS_ST(CRpgRocket, DT_RpgRocket)
+END_SEND_TABLE()
+
+CRpgRocket::CRpgRocket()
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//
+//
+//-----------------------------------------------------------------------------
+void CRpgRocket::Precache( void )
+{
+ PrecacheModel( "models/rpgrocket.mdl" );
+ PrecacheModel( "sprites/animglow01.vmt" );
+
+ PrecacheScriptSound( "Weapon_RPG.RocketIgnite" );
+
+ m_iTrail = PrecacheModel("sprites/smoke.vmt");
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//
+//
+//-----------------------------------------------------------------------------
+void CRpgRocket::Spawn( void )
+{
+ Precache();
+
+ SetSolid( SOLID_BBOX );
+ SetModel("models/rpgrocket.mdl");
+ UTIL_SetSize( this, -Vector(0,0,0), Vector(0,0,0) );
+
+ SetTouch( &CRpgRocket::RocketTouch );
+
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
+ SetThink( &CRpgRocket::IgniteThink );
+
+ SetNextThink( gpGlobals->curtime + 0.4f );
+
+ QAngle angAngs;
+ Vector vecFwd;
+
+ angAngs = GetAbsAngles();
+ angAngs.x -= 30;
+ AngleVectors( angAngs, &vecFwd );
+ SetAbsVelocity( vecFwd * 250 );
+
+ SetGravity( UTIL_ScaleForGravity( 400 ) ); // use a lower gravity for rockets
+
+ m_flDamage = sk_plr_dmg_rpg.GetFloat();
+ m_DmgRadius = m_flDamage * 2.5;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pOther -
+//-----------------------------------------------------------------------------
+void CRpgRocket::RocketTouch( CBaseEntity *pOther )
+{
+ if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) )
+ return;
+
+ if ( m_hOwner != NULL )
+ {
+ m_hOwner->NotifyRocketDied();
+ }
+
+ StopSound( "Weapon_RPG.RocketIgnite" );
+ ExplodeTouch( pOther );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CRpgRocket::IgniteThink( void )
+{
+ SetMoveType( MOVETYPE_FLY );
+
+ AddEffects( EF_DIMLIGHT );
+
+ EmitSound( "Weapon_RPG.RocketIgnite" );
+
+ SetThink( &CRpgRocket::SeekThink );
+ SetNextThink( gpGlobals->curtime + 0.1f );
+
+ CBroadcastRecipientFilter filter;
+ TE_BeamFollow( filter, 0.0,
+ entindex(),
+ m_iTrail,
+ 0,
+ 4,
+ 5,
+ 5,
+ 0,
+ 224,
+ 224,
+ 255,
+ 255 );
+
+ m_flIgniteTime = gpGlobals->curtime;
+}
+
+#define RPG_HOMING_SPEED 0.125f
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CRpgRocket::SeekThink( void )
+{
+ CBaseEntity *pOther = NULL;
+ Vector vecTarget;
+ Vector vecFwd;
+ Vector vecDir;
+ float flDist, flMax, flDot;
+ trace_t tr;
+
+ AngleVectors( GetAbsAngles(), &vecFwd );
+
+ vecTarget = vecFwd;
+ flMax = 4096;
+
+ // Examine all entities within a reasonable radius
+ while ( (pOther = gEntList.FindEntityByClassname( pOther, "laser_spot" ) ) != NULL)
+ {
+ CLaserDot *pDot = dynamic_cast<CLaserDot*>(pOther);
+
+// if ( pDot->IsActive() )
+ if ( pDot->IsOn() )
+ {
+ UTIL_TraceLine( GetAbsOrigin(), pDot->GetAbsOrigin(), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
+ if ( tr.fraction >= 0.90 )
+ {
+ vecDir = pDot->GetAbsOrigin() - GetAbsOrigin();
+ flDist = VectorLength( vecDir );
+ VectorNormalize( vecDir );
+ flDot = DotProduct( vecFwd, vecDir );
+ if ( (flDot > 0) && (flDist * (1 - flDot) < flMax) )
+ {
+ flMax = flDist * (1 - flDot);
+ vecTarget = vecDir;
+ }
+ }
+ }
+ }
+
+ QAngle vecAng;
+ VectorAngles( vecTarget, vecAng );
+ SetAbsAngles( vecAng );
+
+ // this acceleration and turning math is totally wrong, but it seems to respond well so don't change it.
+ float flSpeed = GetAbsVelocity().Length();
+ if ( gpGlobals->curtime - m_flIgniteTime < 1.0 )
+ {
+ SetAbsVelocity( GetAbsVelocity() * 0.2 + vecTarget * (flSpeed * 0.8 + 400) );
+ if ( GetWaterLevel() == 3 )
+ {
+ // go slow underwater
+ if ( GetAbsVelocity().Length() > 300 )
+ {
+ Vector vecVel = GetAbsVelocity();
+ VectorNormalize( vecVel );
+ SetAbsVelocity( vecVel * 300 );
+ }
+
+ UTIL_BubbleTrail( GetAbsOrigin() - GetAbsVelocity() * 0.1, GetAbsOrigin(), 4 );
+ }
+ else
+ {
+ if ( GetAbsVelocity().Length() > 2000 )
+ {
+ Vector vecVel = GetAbsVelocity();
+ VectorNormalize( vecVel );
+ SetAbsVelocity( vecVel * 2000 );
+ }
+ }
+ }
+ else
+ {
+ if ( IsEffectActive( EF_DIMLIGHT ) )
+ {
+ ClearEffects();
+ }
+
+ SetAbsVelocity( GetAbsVelocity() * 0.2 + vecTarget * flSpeed * 0.798 );
+
+ if ( GetWaterLevel() == 0 && GetAbsVelocity().Length() < 1500 )
+ {
+ Detonate();
+ }
+ }
+
+ SetNextThink( gpGlobals->curtime + 0.1f );
+}
+
+void CRpgRocket::Detonate( void )
+{
+ StopSound( "Weapon_RPG.RocketIgnite" );
+ BaseClass::Detonate();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//
+// Input : &vecOrigin -
+// &vecAngles -
+// NULL -
+//
+// Output : CRpgRocket
+//-----------------------------------------------------------------------------
+CRpgRocket *CRpgRocket::Create( const Vector &vecOrigin, const QAngle &angAngles, CBasePlayer *pentOwner )
+{
+ CRpgRocket *pRocket = (CRpgRocket *)CreateEntityByName( "rpg_rocket" );
+ UTIL_SetOrigin( pRocket, vecOrigin );
+ pRocket->SetAbsAngles( angAngles );
+ pRocket->Spawn();
+ pRocket->SetOwnerEntity( pentOwner );
+
+ return pRocket;
+}
+
+#endif // endif #ifndef CLIENT_DLL
+
+
+//=============================================================================
+// Laser Dot
+//=============================================================================
+
+IMPLEMENT_NETWORKCLASS_ALIASED( LaserDot, DT_LaserDot )
+
+BEGIN_NETWORK_TABLE( CLaserDot, DT_LaserDot )
+#ifdef CLIENT_DLL
+ RecvPropBool( RECVINFO( m_bIsOn ) ),
+#else
+ SendPropBool( SENDINFO( m_bIsOn ) ),
+#endif
+END_NETWORK_TABLE()
+
+#ifndef CLIENT_DLL
+// a list of laser dots to search quickly
+CEntityClassList<CLaserDot> g_LaserDotList;
+template <> CLaserDot *CEntityClassList<CLaserDot>::m_pClassList = NULL;
+CLaserDot *GetLaserDotList()
+{
+ return g_LaserDotList.m_pClassList;
+}
+
+#endif
+
+LINK_ENTITY_TO_CLASS( laser_spot, CLaserDot );
+
+BEGIN_DATADESC( CLaserDot )
+ DEFINE_FIELD( m_vecSurfaceNormal, FIELD_VECTOR ),
+ DEFINE_FIELD( m_hTargetEnt, FIELD_EHANDLE ),
+ DEFINE_FIELD( m_bVisibleLaserDot, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bIsOn, FIELD_BOOLEAN ),
+
+ //DEFINE_FIELD( m_pNext, FIELD_CLASSPTR ), // don't save - regenerated by constructor
+END_DATADESC()
+
+
+//-----------------------------------------------------------------------------
+// Finds missiles in cone
+//-----------------------------------------------------------------------------
+CBaseEntity *CreateLaserDot( const Vector &origin, CBaseEntity *pOwner, bool bVisibleDot )
+{
+ return CLaserDot::Create( origin, pOwner, bVisibleDot );
+}
+
+void SetLaserDotTarget( CBaseEntity *pLaserDot, CBaseEntity *pTarget )
+{
+ CLaserDot *pDot = assert_cast< CLaserDot* >(pLaserDot );
+ pDot->SetTargetEntity( pTarget );
+}
+
+void EnableLaserDot( CBaseEntity *pLaserDot, bool bEnable )
+{
+ CLaserDot *pDot = assert_cast< CLaserDot* >(pLaserDot );
+ if ( bEnable )
+ {
+ pDot->TurnOn();
+ }
+ else
+ {
+ pDot->TurnOff();
+ }
+}
+
+CLaserDot::CLaserDot( void )
+{
+ m_hTargetEnt = NULL;
+ m_bIsOn = true;
+#ifndef CLIENT_DLL
+ g_LaserDotList.Insert( this );
+#endif
+}
+
+CLaserDot::~CLaserDot( void )
+{
+#ifndef CLIENT_DLL
+ g_LaserDotList.Remove( this );
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &origin -
+// Output : CLaserDot
+//-----------------------------------------------------------------------------
+CLaserDot *CLaserDot::Create( const Vector &origin, CBaseEntity *pOwner, bool bVisibleDot )
+{
+#ifndef CLIENT_DLL
+ CLaserDot *pLaserDot = (CLaserDot *) CBaseEntity::Create( "laser_spot", origin, QAngle(0,0,0) );
+
+ if ( pLaserDot == NULL )
+ return NULL;
+
+ pLaserDot->m_bVisibleLaserDot = bVisibleDot;
+ pLaserDot->SetMoveType( MOVETYPE_NONE );
+ pLaserDot->AddSolidFlags( FSOLID_NOT_SOLID );
+ pLaserDot->AddEffects( EF_NOSHADOW );
+ UTIL_SetSize( pLaserDot, -Vector(6,6,6), Vector(6,6,6) );
+
+ pLaserDot->SetOwnerEntity( pOwner );
+
+ pLaserDot->AddEFlags( EFL_FORCE_CHECK_TRANSMIT );
+
+ if ( !bVisibleDot )
+ {
+ pLaserDot->MakeInvisible();
+ }
+
+ return pLaserDot;
+#else
+ return NULL;
+#endif
+}
+
+void CLaserDot::SetLaserPosition( const Vector &origin, const Vector &normal )
+{
+ SetAbsOrigin( origin );
+ m_vecSurfaceNormal = normal;
+}
+
+Vector CLaserDot::GetChasePosition()
+{
+ return GetAbsOrigin() - m_vecSurfaceNormal * 10;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CLaserDot::TurnOn( void )
+{
+ m_bIsOn = true;
+ RemoveEffects(EF_NODRAW);
+
+ if ( m_bVisibleLaserDot )
+ {
+ //BaseClass::TurnOn();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CLaserDot::TurnOff( void )
+{
+ m_bIsOn = false;
+ AddEffects(EF_NODRAW);
+ if ( m_bVisibleLaserDot )
+ {
+ //BaseClass::TurnOff();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CLaserDot::MakeInvisible( void )
+{
+}
+
+#ifdef CLIENT_DLL
+
+//-----------------------------------------------------------------------------
+// Purpose: Draw our sprite
+//-----------------------------------------------------------------------------
+int CLaserDot::DrawModel( int flags )
+{
+ color32 color={255,255,255,255};
+ Vector vecAttachment, vecDir;
+ QAngle angles;
+
+ float scale;
+ Vector endPos;
+
+ C_HL1MP_Player *pOwner = ToHL1MPPlayer( GetOwnerEntity() );
+
+ if ( pOwner != NULL && pOwner->IsDormant() == false )
+ {
+ // Always draw the dot in front of our faces when in first-person
+ if ( pOwner->IsLocalPlayer() )
+ {
+ // Take our view position and orientation
+ vecAttachment = CurrentViewOrigin();
+ vecDir = CurrentViewForward();
+ }
+ else
+ {
+ // Take the eye position and direction
+ vecAttachment = pOwner->EyePosition();
+
+ QAngle angles = pOwner->EyeAngles();
+ AngleVectors( angles, &vecDir );
+ }
+
+ trace_t tr;
+ UTIL_TraceLine( vecAttachment, vecAttachment + ( vecDir * MAX_TRACE_LENGTH ), MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr );
+
+ // Backup off the hit plane
+ endPos = tr.endpos + ( tr.plane.normal * 4.0f );
+ }
+ else
+ {
+ // Just use our position if we can't predict it otherwise
+ endPos = GetAbsOrigin();
+ }
+
+ // Randomly flutter
+ scale = 16.0f + random->RandomFloat( -4.0f, 4.0f );
+
+ // Draw our laser dot in space
+ CMatRenderContextPtr pRenderContext( materials );
+ pRenderContext->Bind( m_hSpriteMaterial, this );
+ DrawSprite( endPos, scale, scale, color );
+
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Setup our sprite reference
+//-----------------------------------------------------------------------------
+void CLaserDot::OnDataChanged( DataUpdateType_t updateType )
+{
+ if ( updateType == DATA_UPDATE_CREATED )
+ {
+ m_hSpriteMaterial.Init( RPG_LASER_SPRITE, TEXTURE_GROUP_CLIENT_EFFECTS );
+ }
+}
+
+#endif //CLIENT_DLL
+
+//=============================================================================
+// RPG Weapon
+//=============================================================================
+
+LINK_ENTITY_TO_CLASS( weapon_rpg, CWeaponRPG );
+
+PRECACHE_WEAPON_REGISTER( weapon_rpg );
+
+//IMPLEMENT_SERVERCLASS_ST( CWeaponRPG, DT_WeaponRPG )
+//END_SEND_TABLE()
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponRPG, DT_WeaponRPG )
+
+BEGIN_DATADESC( CWeaponRPG )
+DEFINE_FIELD( m_bIntialStateUpdate, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_bGuiding, FIELD_BOOLEAN ),
+#ifndef CLIENT_DLL
+ DEFINE_FIELD( m_hLaserDot, FIELD_EHANDLE ),
+#endif
+ DEFINE_FIELD( m_hMissile, FIELD_EHANDLE ),
+ DEFINE_FIELD( m_bLaserDotSuspended, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_flLaserDotReviveTime, FIELD_TIME ),
+END_DATADESC()
+
+
+BEGIN_NETWORK_TABLE( CWeaponRPG, DT_WeaponRPG )
+#ifdef CLIENT_DLL
+ RecvPropBool( RECVINFO( m_bIntialStateUpdate ) ),
+ RecvPropBool( RECVINFO( m_bGuiding ) ),
+ RecvPropBool( RECVINFO( m_bLaserDotSuspended ) ),
+// RecvPropEHandle( RECVINFO( m_hMissile ), RecvProxy_MissileDied ),
+// RecvPropVector( RECVINFO( m_vecLaserDot ) ),
+#else
+ SendPropBool( SENDINFO( m_bIntialStateUpdate ) ),
+ SendPropBool( SENDINFO( m_bGuiding ) ),
+ SendPropBool( SENDINFO( m_bLaserDotSuspended ) ),
+// SendPropEHandle( SENDINFO( m_hMissile ) ),
+// SendPropVector( SENDINFO( m_vecLaserDot ) ),
+#endif
+END_NETWORK_TABLE()
+
+
+BEGIN_PREDICTION_DATA( CWeaponRPG )
+#ifdef CLIENT_DLL
+ DEFINE_PRED_FIELD( m_bIntialStateUpdate, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
+ DEFINE_PRED_FIELD( m_bGuiding, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
+ DEFINE_PRED_FIELD( m_bLaserDotSuspended, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
+ DEFINE_PRED_FIELD( m_flLaserDotReviveTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
+#endif
+END_PREDICTION_DATA()
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CWeaponRPG::CWeaponRPG( void )
+{
+ m_bReloadsSingly = false;
+ m_bFiresUnderwater = true;
+ m_bGuiding = true;
+ m_bIntialStateUpdate = false;
+ m_bLaserDotSuspended = false;
+}
+
+
+CWeaponRPG::~CWeaponRPG()
+{
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot != NULL )
+ {
+ UTIL_Remove( m_hLaserDot );
+ m_hLaserDot = NULL;
+ }
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponRPG::ItemPostFrame( void )
+{
+ BaseClass::ItemPostFrame();
+
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ if ( pPlayer == NULL )
+ return;
+
+ //If we're pulling the weapon out for the first time, wait to draw the laser
+ if ( m_bIntialStateUpdate )
+ {
+ if ( GetActivity() != ACT_VM_DRAW )
+ {
+ if ( IsGuiding() && !m_bLaserDotSuspended )
+ {
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot != NULL )
+ {
+ m_hLaserDot->TurnOn();
+ }
+#endif
+ }
+
+ m_bIntialStateUpdate = false;
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ //Player has toggled guidance state
+ if ( pPlayer->m_afButtonPressed & IN_ATTACK2 )
+ {
+ if ( IsGuiding() )
+ {
+ StopGuiding();
+ }
+ else
+ {
+ StartGuiding();
+ }
+ }
+
+ //Move the laser
+ UpdateSpot();
+}
+
+
+void CWeaponRPG::Drop( const Vector &vecVelocity )
+{
+ StopGuiding();
+
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot != NULL )
+ {
+ UTIL_Remove( m_hLaserDot );
+ m_hLaserDot = NULL;
+ }
+#endif
+
+ BaseClass::Drop( vecVelocity );
+}
+
+
+int CWeaponRPG::GetDefaultClip1( void ) const
+{
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ // more default ammo in multiplay.
+ return BaseClass::GetDefaultClip1() * 2;
+ }
+ else
+ {
+ return BaseClass::GetDefaultClip1();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponRPG::Precache( void )
+{
+#ifndef CLIENT_DLL
+ UTIL_PrecacheOther( "laser_spot" );
+ UTIL_PrecacheOther( "rpg_rocket" );
+#endif
+
+// PrecacheModel( RPG_LASER_SPRITE );
+ PrecacheModel( "sprites/redglow_mp1.vmt" );
+
+ BaseClass::Precache();
+}
+
+
+bool CWeaponRPG::Deploy( void )
+{
+ m_bIntialStateUpdate = true;
+ m_bLaserDotSuspended = false;
+ CreateLaserPointer();
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot != NULL )
+ {
+ m_hLaserDot->TurnOff();
+ }
+#endif
+
+ if ( m_iClip1 <= 0 )
+ {
+ return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_RPG_DRAW_UNLOADED, (char*)GetAnimPrefix() );
+ }
+
+ return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_VM_DRAW, (char*)GetAnimPrefix() );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponRPG::PrimaryAttack( void )
+{
+ // Can't have an active missile out
+ if ( m_hMissile != NULL )
+ return;
+
+ // Can't be reloading
+ if ( GetActivity() == ACT_VM_RELOAD )
+ return;
+
+ if ( m_iClip1 <= 0 )
+ {
+ if ( !m_bFireOnEmpty )
+ {
+ Reload();
+ }
+ else
+ {
+ WeaponSound( EMPTY );
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
+ }
+ }
+
+ Vector vecOrigin;
+ Vector vecForward;
+
+ CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
+
+ if ( pOwner == NULL )
+ return;
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+ WeaponSound( SINGLE );
+#ifndef CLIENT_DLL
+ CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 400, 0.2 );
+#endif
+ pOwner->DoMuzzleFlash();
+
+#ifndef CLIENT_DLL
+ // Register a muzzleflash for the AI
+ pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 );
+#endif
+
+ Vector vForward, vRight, vUp;
+
+ pOwner->EyeVectors( &vForward, &vRight, &vUp );
+
+ Vector muzzlePoint = pOwner->Weapon_ShootPosition() + vForward * 16.0f + vRight * 8.0f + vUp * -8.0f;
+
+#ifndef CLIENT_DLL
+ QAngle vecAngles;
+ VectorAngles( vForward, vecAngles );
+
+ CRpgRocket * pMissile = CRpgRocket::Create( muzzlePoint, vecAngles, pOwner );
+ pMissile->m_hOwner = this;
+ pMissile->SetAbsVelocity( pMissile->GetAbsVelocity() + vForward * DotProduct( pOwner->GetAbsVelocity(), vForward ) );
+
+ m_hMissile = pMissile;
+#endif
+
+ pOwner->ViewPunch( QAngle( -5, 0, 0 ) );
+
+ m_iClip1--;
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + 1.5;
+ SetWeaponIdleTime( 1.5 );
+
+ UpdateSpot();
+}
+
+
+void CWeaponRPG::WeaponIdle( void )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+
+ if ( pOwner == NULL )
+ return;
+
+ if ( !HasWeaponIdleTimeElapsed() )
+ return;
+
+ int iAnim;
+ float flRand = random->RandomFloat( 0, 1 );
+ if ( flRand <= 0.75 || IsGuiding() )
+ {
+ if ( m_iClip1 <= 0 )
+ iAnim = ACT_RPG_IDLE_UNLOADED;
+ else
+ iAnim = ACT_VM_IDLE;
+ }
+ else
+ {
+ if ( m_iClip1 <= 0 )
+ iAnim = ACT_RPG_FIDGET_UNLOADED;
+ else
+ iAnim = ACT_VM_FIDGET;
+ }
+
+ SendWeaponAnim( iAnim );
+}
+
+
+void CWeaponRPG::NotifyRocketDied( void )
+{
+ m_hMissile = NULL;
+
+ // Can't be reloading
+ if ( GetActivity() == ACT_VM_RELOAD )
+ return;
+
+// Reload();
+}
+
+
+bool CWeaponRPG::Reload( void )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+
+#if 0
+ if ( pOwner == NULL )
+ return false;
+
+ if ( pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
+ return false;
+
+ WeaponSound( RELOAD );
+
+ SendWeaponAnim( ACT_VM_RELOAD );
+
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot != NULL )
+ {
+ m_hLaserDot->TurnOff();
+ }
+#endif
+
+ m_bLaserDotSuspended = true;
+ m_flLaserDotReviveTime = gpGlobals->curtime + 2.1;
+ m_flNextPrimaryAttack = gpGlobals->curtime + 2.1;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 2.1;
+
+ return true;
+#endif
+
+ // Can't be reloading
+ if ( GetActivity() == ACT_VM_RELOAD )
+ return false;
+
+ if ( pOwner == NULL )
+ return false;
+
+ if ( m_iClip1 > 0 )
+ return false;
+
+ if ( pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
+ return false;
+
+ // because the RPG waits to autoreload when no missiles are active while the LTD is on, the
+ // weapons code is constantly calling into this function, but is often denied because
+ // a) missiles are in flight, but the LTD is on
+ // or
+ // b) player is totally out of ammo and has nothing to switch to, and should be allowed to
+ // shine the designator around
+ //
+ // Set the next attack time into the future so that WeaponIdle will get called more often
+ // than reload, allowing the RPG LTD to be updated
+
+ if ( ( m_hMissile != NULL ) && IsGuiding() )
+ {
+ // no reloading when there are active missiles tracking the designator.
+ // ward off future autoreload attempts by setting next attack time into the future for a bit.
+ return false;
+ }
+
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot != NULL )
+ {
+ m_hLaserDot->TurnOff();
+ }
+#endif
+
+ m_bLaserDotSuspended = true;
+ m_flLaserDotReviveTime = gpGlobals->curtime + 2.1;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 2.1;
+
+ return DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD );
+}
+
+
+bool CWeaponRPG::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+ // can't put away while guiding a missile.
+ if ( IsGuiding() && ( m_hMissile != NULL ) )
+ return false;
+
+// StopGuiding();
+
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot != NULL )
+ {
+ m_hLaserDot->TurnOff();
+ UTIL_Remove( m_hLaserDot );
+ m_hLaserDot = NULL;
+ }
+#endif
+
+ m_bLaserDotSuspended = false;
+
+ return BaseClass::Holster( pSwitchingTo );
+}
+
+
+void CWeaponRPG::UpdateSpot( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ if ( pPlayer == NULL )
+ return;
+
+ CreateLaserPointer();
+
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot == NULL )
+ return;
+#endif
+
+ if ( IsGuiding() && m_bLaserDotSuspended && ( m_flLaserDotReviveTime <= gpGlobals->curtime ) )
+ {
+#ifndef CLIENT_DLL
+ m_hLaserDot->TurnOn();
+#endif
+ m_bLaserDotSuspended = false;
+ }
+
+ //Move the laser dot, if active
+ trace_t tr;
+ Vector muzzlePos = pPlayer->Weapon_ShootPosition();
+
+ Vector forward;
+ AngleVectors( pPlayer->EyeAngles() + pPlayer->m_Local.m_vecPunchAngle, &forward );
+
+ Vector endPos = muzzlePos + ( forward * MAX_TRACE_LENGTH );
+
+ // Trace out for the endpoint
+ UTIL_TraceLine( muzzlePos, endPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );
+
+ // Move the laser sprite
+ Vector laserPos = tr.endpos + ( tr.plane.normal * 2.0f );
+#ifndef CLIENT_DLL
+ m_hLaserDot->SetLaserPosition( laserPos, tr.plane.normal );
+#endif
+}
+
+
+void CWeaponRPG::CreateLaserPointer( void )
+{
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot != NULL )
+ return;
+
+ m_hLaserDot = CLaserDot::Create( GetAbsOrigin(), GetOwner() );
+ if ( !IsGuiding() )
+ {
+ if ( m_hLaserDot )
+ {
+ m_hLaserDot->TurnOff();
+ }
+ }
+#endif
+}
+
+
+bool CWeaponRPG::IsGuiding( void )
+{
+ return m_bGuiding;
+}
+
+
+void CWeaponRPG::StartGuiding( void )
+{
+ m_bGuiding = true;
+
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot != NULL )
+ {
+ m_hLaserDot->TurnOn();
+ }
+#endif
+
+ UpdateSpot();
+}
+
+void CWeaponRPG::StopGuiding( void )
+{
+ m_bGuiding = false;
+
+#ifndef CLIENT_DLL
+ if ( m_hLaserDot != NULL )
+ {
+ m_hLaserDot->TurnOff();
+ }
+#endif
+}
diff --git a/game/shared/hl1/hl1mp_weapon_rpg.h b/game/shared/hl1/hl1mp_weapon_rpg.h
new file mode 100644
index 0000000..8e57e03
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_rpg.h
@@ -0,0 +1,135 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: RPG
+//
+//=============================================================================//
+
+
+#ifndef WEAPON_RPG_H
+#define WEAPON_RPG_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#include "hl1mp_basecombatweapon_shared.h"
+
+#ifdef CLIENT_DLL
+#include "iviewrender_beams.h"
+#include "c_smoke_trail.h"
+#endif
+
+#ifndef CLIENT_DLL
+#include "smoke_trail.h"
+#include "Sprite.h"
+#include "npcevent.h"
+#include "beam_shared.h"
+#include "hl1_basegrenade.h"
+
+class CWeaponRPG;
+
+//###########################################################################
+// CRpgRocket
+//###########################################################################
+class CRpgRocket : public CHL1BaseGrenade
+{
+ DECLARE_CLASS( CRpgRocket, CHL1BaseGrenade );
+ DECLARE_SERVERCLASS();
+
+public:
+ CRpgRocket();
+
+ Class_T Classify( void ) { return CLASS_NONE; }
+
+ void Spawn( void );
+ void Precache( void );
+ void RocketTouch( CBaseEntity *pOther );
+ void IgniteThink( void );
+ void SeekThink( void );
+
+ virtual void Detonate( void );
+
+ static CRpgRocket *Create( const Vector &vecOrigin, const QAngle &angAngles, CBasePlayer *pentOwner = NULL );
+
+ CHandle<CWeaponRPG> m_hOwner;
+ float m_flIgniteTime;
+ int m_iTrail;
+
+ DECLARE_DATADESC();
+};
+
+
+#endif
+
+#ifdef CLIENT_DLL
+#define CLaserDot C_LaserDot
+#endif
+
+class CLaserDot;
+
+#ifdef CLIENT_DLL
+#define CWeaponRPG C_WeaponRPG
+#endif
+
+//-----------------------------------------------------------------------------
+// CWeaponRPG
+//-----------------------------------------------------------------------------
+class CWeaponRPG : public CBaseHL1MPCombatWeapon
+{
+ DECLARE_CLASS( CWeaponRPG, CBaseHL1MPCombatWeapon );
+public:
+
+ CWeaponRPG( void );
+ ~CWeaponRPG();
+
+ void ItemPostFrame( void );
+ void Precache( void );
+ bool Deploy( void );
+ void PrimaryAttack( void );
+ void WeaponIdle( void );
+ bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
+ void NotifyRocketDied( void );
+ bool Reload( void );
+
+ void Drop( const Vector &vecVelocity );
+
+ virtual int GetDefaultClip1( void ) const;
+
+// DECLARE_SERVERCLASS();
+ DECLARE_DATADESC();
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+private:
+ void CreateLaserPointer( void );
+ void UpdateSpot( void );
+ bool IsGuiding( void );
+ void StartGuiding( void );
+ void StopGuiding( void );
+
+#ifndef CLIENT_DLL
+// DECLARE_ACTTABLE();
+#endif
+
+private:
+// bool m_bGuiding;
+// CHandle<CLaserDot> m_hLaserDot;
+// CHandle<CRpgRocket> m_hMissile;
+// bool m_bIntialStateUpdate;
+// bool m_bLaserDotSuspended;
+// float m_flLaserDotReviveTime;
+
+ CNetworkVar( bool, m_bGuiding );
+ CNetworkVar( bool, m_bIntialStateUpdate );
+ CNetworkVar( bool, m_bLaserDotSuspended );
+ CNetworkVar( float, m_flLaserDotReviveTime );
+
+ CNetworkHandle( CBaseEntity, m_hMissile );
+
+#ifndef CLIENT_DLL
+ CHandle<CLaserDot> m_hLaserDot;
+#endif
+};
+
+
+#endif // WEAPON_RPG_H
diff --git a/game/shared/hl1/hl1mp_weapon_sachel.cpp b/game/shared/hl1/hl1mp_weapon_sachel.cpp
new file mode 100644
index 0000000..cc26019
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_sachel.cpp
@@ -0,0 +1,600 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Satchel charge
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "npcevent.h"
+#include "hl1_basecombatweapon_shared.h"
+//#include "basecombatweapon.h"
+//#include "basecombatcharacter.h"
+#ifdef CLIENT_DLL
+#include "c_baseplayer.h"
+#else
+#include "player.h"
+#endif
+//#include "AI_BaseNPC.h"
+//#include "player.h"
+#include "gamerules.h"
+#include "in_buttons.h"
+#ifndef CLIENT_DLL
+#include "soundent.h"
+#include "game.h"
+#endif
+#include "vstdlib/random.h"
+#include "engine/IEngineSound.h"
+#include "hl1mp_weapon_satchel.h"
+
+
+//-----------------------------------------------------------------------------
+// CWeaponSatchel
+//-----------------------------------------------------------------------------
+
+
+#define SATCHEL_VIEW_MODEL "models/v_satchel.mdl"
+#define SATCHEL_WORLD_MODEL "models/w_satchel.mdl"
+#define SATCHELRADIO_VIEW_MODEL "models/v_satchel_radio.mdl"
+#define SATCHELRADIO_WORLD_MODEL "models/w_satchel.mdl" // this needs fixing if we do multiplayer
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponSatchel, DT_WeaponSatchel );
+
+BEGIN_NETWORK_TABLE( CWeaponSatchel, DT_WeaponSatchel )
+#ifdef CLIENT_DLL
+ RecvPropInt( RECVINFO( m_iRadioViewIndex ) ),
+ RecvPropInt( RECVINFO( m_iRadioWorldIndex ) ),
+ RecvPropInt( RECVINFO( m_iSatchelViewIndex ) ),
+ RecvPropInt( RECVINFO( m_iSatchelWorldIndex ) ),
+ RecvPropInt( RECVINFO( m_iChargeReady ) ),
+#else
+ SendPropInt( SENDINFO( m_iRadioViewIndex ) ),
+ SendPropInt( SENDINFO( m_iRadioWorldIndex ) ),
+ SendPropInt( SENDINFO( m_iSatchelViewIndex ) ),
+ SendPropInt( SENDINFO( m_iSatchelWorldIndex ) ),
+ SendPropInt( SENDINFO( m_iChargeReady ) ),
+#endif
+END_NETWORK_TABLE()
+
+LINK_ENTITY_TO_CLASS( weapon_satchel, CWeaponSatchel );
+
+PRECACHE_WEAPON_REGISTER( weapon_satchel );
+
+//IMPLEMENT_SERVERCLASS_ST( CWeaponSatchel, DT_WeaponSatchel )
+//END_SEND_TABLE()
+
+
+BEGIN_PREDICTION_DATA( CWeaponSatchel )
+#ifdef CLIENT_DLL
+ DEFINE_PRED_FIELD( m_iRadioViewIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
+ DEFINE_PRED_FIELD( m_iRadioWorldIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
+ DEFINE_PRED_FIELD( m_iSatchelViewIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
+ DEFINE_PRED_FIELD( m_iSatchelWorldIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ),
+ DEFINE_PRED_FIELD( m_iChargeReady, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
+#endif
+END_PREDICTION_DATA()
+
+
+BEGIN_DATADESC( CWeaponSatchel )
+ DEFINE_FIELD( m_iChargeReady, FIELD_INTEGER ),
+
+// DEFINE_FIELD( m_iRadioViewIndex, FIELD_INTEGER ),
+// DEFINE_FIELD( m_iRadioWorldIndex, FIELD_INTEGER ),
+// DEFINE_FIELD( m_iSatchelViewIndex, FIELD_INTEGER ),
+// DEFINE_FIELD( m_iSatchelWorldIndex, FIELD_INTEGER ),
+END_DATADESC()
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CWeaponSatchel::CWeaponSatchel( void )
+{
+ m_bReloadsSingly = false;
+ m_bFiresUnderwater = true;
+}
+
+void CWeaponSatchel::Equip( CBaseCombatCharacter *pOwner )
+{
+ BaseClass::Equip( pOwner );
+
+ m_iChargeReady = 0; // this satchel charge weapon now forgets that any satchels are deployed by it.
+}
+
+bool CWeaponSatchel::HasAnyAmmo( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( !pPlayer )
+ {
+ return false;
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) > 0 )
+ {
+ // player is carrying some satchels
+ return true;
+ }
+
+ if ( HasChargeDeployed() )
+ {
+ // player isn't carrying any satchels, but has some out
+ return true;
+ }
+
+ return BaseClass::HasAnyAmmo();
+}
+
+bool CWeaponSatchel::CanDeploy( void )
+{
+ if ( HasAnyAmmo() )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponSatchel::Precache( void )
+{
+ m_iSatchelViewIndex = PrecacheModel( SATCHEL_VIEW_MODEL );
+ m_iSatchelWorldIndex = PrecacheModel( SATCHEL_WORLD_MODEL );
+ m_iRadioViewIndex = PrecacheModel( SATCHELRADIO_VIEW_MODEL );
+ m_iRadioWorldIndex = PrecacheModel( SATCHELRADIO_WORLD_MODEL );
+
+#ifndef CLIENT_DLL
+ UTIL_PrecacheOther( "monster_satchel" );
+#endif
+
+ BaseClass::Precache();
+}
+
+void CWeaponSatchel::ItemPostFrame( void )
+{
+ CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
+ if (!pOwner)
+ {
+ return;
+ }
+
+ if ( (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
+ {
+ // If the firing button was just pressed, reset the firing time
+ if ( pOwner->m_afButtonPressed & IN_ATTACK )
+ {
+ m_flNextPrimaryAttack = gpGlobals->curtime;
+ }
+
+ PrimaryAttack();
+ }
+
+ BaseClass::ItemPostFrame();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponSatchel::PrimaryAttack( void )
+{
+ switch ( m_iChargeReady )
+ {
+ case 0:
+ {
+ Throw();
+ }
+ break;
+ case 1:
+ {
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+
+#ifndef CLIENT_DLL
+ CBaseEntity *pSatchel = NULL;
+
+ while ( (pSatchel = gEntList.FindEntityByClassname( pSatchel, "monster_satchel" ) ) != NULL)
+ {
+ if ( pSatchel->GetOwnerEntity() == pPlayer )
+ {
+ pSatchel->Use( pPlayer, pPlayer, USE_ON, 0 );
+ }
+ }
+#endif
+
+ m_iChargeReady = 2;
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.5;
+ SetWeaponIdleTime( gpGlobals->curtime + 0.5 );
+ break;
+ }
+
+ case 2:
+ // we're reloading, don't allow fire
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponSatchel::SecondaryAttack( void )
+{
+ if ( m_iChargeReady != 2 )
+ {
+ Throw();
+ }
+}
+
+void CWeaponSatchel::Throw( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( !pPlayer )
+ {
+ return;
+ }
+
+ if ( pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) > 0 )
+ {
+ Vector vecForward;
+ pPlayer->EyeVectors( &vecForward );
+
+ Vector vecSrc = pPlayer->WorldSpaceCenter();
+ Vector vecThrow = vecForward * 274 + pPlayer->GetAbsVelocity();
+
+#ifndef CLIENT_DLL
+ CBaseEntity *pSatchel = Create( "monster_satchel", vecSrc, QAngle( 0, 0, 90 ), pPlayer );
+ if ( pSatchel )
+ {
+ pSatchel->SetAbsVelocity( vecThrow );
+ QAngle angVel = pSatchel->GetLocalAngularVelocity();
+ angVel.y = 400;
+ pSatchel->SetLocalAngularVelocity( angVel );
+
+ ActivateRadioModel();
+
+ SendWeaponAnim( ACT_VM_DRAW );
+
+ // player "shoot" animation
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ m_iChargeReady = 1;
+
+ pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType );
+
+ }
+#endif
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.5;
+ }
+}
+
+void CWeaponSatchel::WeaponIdle( void )
+{
+ if ( !HasWeaponIdleTimeElapsed() )
+ return;
+
+ switch( m_iChargeReady )
+ {
+ case 0:
+ case 1:
+ SendWeaponAnim( ACT_VM_FIDGET );
+ break;
+ case 2:
+ {
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ if ( pPlayer && (pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0) )
+ {
+ m_iChargeReady = 0;
+ if ( !pPlayer->SwitchToNextBestWeapon( pPlayer->GetActiveWeapon() ) )
+ {
+ Holster();
+ }
+
+ return;
+ }
+
+ ActivateSatchelModel();
+
+ SendWeaponAnim( ACT_VM_DRAW );
+
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.5;
+ m_iChargeReady = 0;
+ break;
+ }
+ }
+
+ SetWeaponIdleTime( gpGlobals->curtime + random->RandomFloat( 10, 15 ) );// how long till we do this again.
+}
+
+bool CWeaponSatchel::Deploy( void )
+{
+ SetWeaponIdleTime( gpGlobals->curtime + random->RandomFloat( 10, 15 ) );
+
+ if ( HasChargeDeployed() )
+ {
+ ActivateRadioModel();
+ }
+ else
+ {
+ ActivateSatchelModel();
+ }
+
+ bool bRet = BaseClass::Deploy();
+ if ( bRet )
+ {
+ //
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( pPlayer )
+ {
+ pPlayer->SetNextAttack( gpGlobals->curtime + 1.0 );
+ }
+ }
+
+ return bRet;
+
+}
+
+bool CWeaponSatchel::Holster( CBaseCombatWeapon *pSwitchingTo )
+{
+ if ( !BaseClass::Holster( pSwitchingTo ) )
+ {
+ return false;
+ }
+
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+ if ( pPlayer )
+ {
+ pPlayer->SetNextAttack( gpGlobals->curtime + 0.5 );
+
+ if ( (pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0) && !HasChargeDeployed() )
+ {
+#ifndef CLIENT_DLL
+ SetThink( &CWeaponSatchel::DestroyItem );
+ SetNextThink( gpGlobals->curtime + 0.1 );
+#endif
+ }
+ }
+
+ return true;
+}
+
+void CWeaponSatchel::ActivateSatchelModel( void )
+{
+ m_iViewModelIndex = m_iSatchelViewIndex;
+ m_iWorldModelIndex = m_iSatchelWorldIndex;
+ SetModel( GetViewModel() );
+}
+
+void CWeaponSatchel::ActivateRadioModel( void )
+{
+ m_iViewModelIndex = m_iRadioViewIndex;
+ m_iWorldModelIndex = m_iRadioWorldIndex;
+ SetModel( GetViewModel() );
+}
+
+const char *CWeaponSatchel::GetViewModel( int ) const
+{
+ if ( m_iViewModelIndex == m_iSatchelViewIndex )
+ {
+ return SATCHEL_VIEW_MODEL;
+ }
+ else
+ {
+ return SATCHELRADIO_VIEW_MODEL;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char *CWeaponSatchel::GetWorldModel( void ) const
+{
+ if ( m_iViewModelIndex == m_iSatchelViewIndex )
+ {
+ return SATCHEL_WORLD_MODEL;
+ }
+ else
+ {
+ return SATCHELRADIO_WORLD_MODEL;
+ }
+}
+
+void CWeaponSatchel::OnRestore( void )
+{
+ BaseClass::OnRestore();
+ if ( HasChargeDeployed() )
+ {
+ ActivateRadioModel();
+ }
+ else
+ {
+ ActivateSatchelModel();
+ }
+}
+
+#ifndef CLIENT_DLL
+//-----------------------------------------------------------------------------
+// CSatchelCharge
+//-----------------------------------------------------------------------------
+
+#define SATCHEL_CHARGE_MODEL "models/w_satchel.mdl"
+
+
+extern ConVar sk_plr_dmg_satchel;
+
+
+BEGIN_DATADESC( CSatchelCharge )
+ DEFINE_FIELD( m_flNextBounceSoundTime, FIELD_TIME ),
+ DEFINE_FIELD( m_bInAir, FIELD_BOOLEAN ),
+ DEFINE_FIELD( m_vLastPosition, FIELD_POSITION_VECTOR ),
+
+ // Function Pointers
+ DEFINE_ENTITYFUNC( SatchelTouch ),
+ DEFINE_THINKFUNC( SatchelThink ),
+ DEFINE_USEFUNC( SatchelUse ),
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( monster_satchel, CSatchelCharge );
+
+//=========================================================
+// Deactivate - do whatever it is we do to an orphaned
+// satchel when we don't want it in the world anymore.
+//=========================================================
+void CSatchelCharge::Deactivate( void )
+{
+ AddSolidFlags( FSOLID_NOT_SOLID );
+ UTIL_Remove( this );
+}
+
+
+void CSatchelCharge::Spawn( void )
+{
+ Precache( );
+ // motor
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_SLIDE );
+ SetSolid( SOLID_BBOX );
+
+ SetModel( SATCHEL_CHARGE_MODEL );
+
+ UTIL_SetSize( this, Vector( -4, -4, 0), Vector(4, 4, 8) );
+
+ SetTouch( &CSatchelCharge::SatchelTouch );
+ SetUse( &CSatchelCharge::SatchelUse );
+ SetThink( &CSatchelCharge::SatchelThink );
+ SetNextThink( gpGlobals->curtime + 0.1f );
+
+ m_flDamage = sk_plr_dmg_satchel.GetFloat();
+ m_DmgRadius = m_flDamage * 2.5;
+ m_takedamage = DAMAGE_NO;
+ m_iHealth = 1;
+
+ SetGravity( UTIL_ScaleForGravity( 560 ) ); // slightly lower gravity
+ SetFriction( 0.97 ); //used in SatchelTouch to slow us when sliding
+ SetSequence( LookupSequence( "onback" ) );
+
+ m_bInAir = false;
+ m_flNextBounceSoundTime = 0;
+
+ m_vLastPosition = vec3_origin;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CSatchelCharge::SatchelUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
+{
+ SetThink( &CBaseGrenade::Detonate );
+ SetNextThink( gpGlobals->curtime );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+void CSatchelCharge::SatchelTouch( CBaseEntity *pOther )
+{
+ Assert( pOther );
+ if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER | FSOLID_VOLUME_CONTENTS) || GetWaterLevel() > 0 )
+ return;
+
+ StudioFrameAdvance( );
+
+ UpdateSlideSound();
+
+ if ( m_bInAir )
+ {
+ BounceSound();
+ m_bInAir = false;
+ }
+
+ // add a bit of static friction
+ SetAbsVelocity( GetAbsVelocity() * GetFriction() );
+ SetLocalAngularVelocity( GetLocalAngularVelocity() * GetFriction() );
+}
+
+void CSatchelCharge::UpdateSlideSound( void )
+{
+ // HACKHACK - On ground isn't always set, so look for ground underneath
+ trace_t tr;
+ UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );
+
+ if ( !(tr.fraction < 1.0) )
+ {
+ m_bInAir = true;
+ }
+}
+
+void CSatchelCharge::SatchelThink( void )
+{
+ UpdateSlideSound();
+
+ StudioFrameAdvance( );
+ SetNextThink( gpGlobals->curtime + 0.1f );
+
+ if (!IsInWorld())
+ {
+ UTIL_Remove( this );
+ return;
+ }
+
+ Vector vecNewVel = GetAbsVelocity();
+
+ if ( GetWaterLevel() > 0 )
+ {
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
+ vecNewVel *= 0.8;
+ SetLocalAngularVelocity( GetLocalAngularVelocity() * 0.9 );
+
+ vecNewVel.z = 0;
+ SetGravity( -0.2 );
+ }
+ else if ( GetWaterLevel() == 0 )
+ {
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_SLIDE );
+
+ SetGravity( 1.0 );
+ }
+
+ SetAbsVelocity( vecNewVel );
+}
+
+void CSatchelCharge::Precache( void )
+{
+ PrecacheModel( SATCHEL_CHARGE_MODEL );
+ PrecacheScriptSound( "SatchelCharge.Bounce" );
+}
+
+void CSatchelCharge::BounceSound( void )
+{
+ if ( gpGlobals->curtime > m_flNextBounceSoundTime )
+ {
+ EmitSound( "SatchelCharge.Bounce" );
+
+ m_flNextBounceSoundTime = gpGlobals->curtime + 0.1;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+// Input :
+// Output :
+//-----------------------------------------------------------------------------
+CSatchelCharge::CSatchelCharge(void)
+{
+ m_vLastPosition.Init();
+}
+
+#endif
diff --git a/game/shared/hl1/hl1mp_weapon_satchel.h b/game/shared/hl1/hl1mp_weapon_satchel.h
new file mode 100644
index 0000000..c7ed022
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_satchel.h
@@ -0,0 +1,107 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef HL1_WEAPON_SATCHEL_H
+#define HL1_WEAPON_SATCHEL_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#ifndef CLIENT_DLL
+#include "hl1_basegrenade.h"
+#include "hl1_basecombatweapon_shared.h"
+#endif
+
+
+#ifdef CLIENT_DLL
+#define CWeaponSatchel C_WeaponSatchel
+#endif
+
+
+//-----------------------------------------------------------------------------
+// CWeaponSatchel
+//-----------------------------------------------------------------------------
+
+class CWeaponSatchel : public CBaseHL1CombatWeapon
+{
+ DECLARE_CLASS( CWeaponSatchel, CBaseHL1CombatWeapon );
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+public:
+
+ CWeaponSatchel( void );
+
+ void Equip( CBaseCombatCharacter *pOwner );
+ bool HasAnyAmmo( void );
+ bool CanDeploy( void );
+ void Precache( void );
+ void PrimaryAttack( void );
+ void SecondaryAttack( void );
+ void WeaponIdle( void );
+ bool Deploy( void );
+ bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
+
+ void ItemPostFrame( void );
+ const char *GetViewModel( int viewmodelindex = 0 ) const;
+ const char *GetWorldModel( void ) const;
+
+ bool HasChargeDeployed() { return ( m_iChargeReady != 0 ); }
+
+ void OnRestore( void );
+
+// DECLARE_SERVERCLASS();
+ DECLARE_DATADESC();
+
+private:
+ void Throw( void );
+ void ActivateSatchelModel( void );
+ void ActivateRadioModel( void );
+
+private:
+ CNetworkVar( int, m_iRadioViewIndex );
+ CNetworkVar( int, m_iRadioWorldIndex );
+ CNetworkVar( int, m_iSatchelViewIndex );
+ CNetworkVar( int, m_iSatchelWorldIndex );
+ CNetworkVar( int, m_iChargeReady );
+};
+
+
+#ifndef CLIENT_DLL
+//-----------------------------------------------------------------------------
+// CSatchelCharge
+//-----------------------------------------------------------------------------
+
+class CSatchelCharge : public CHL1BaseGrenade
+{
+public:
+ DECLARE_CLASS( CSatchelCharge, CHL1BaseGrenade );
+
+ CSatchelCharge();
+
+ void Spawn( void );
+ void Precache( void );
+ void SatchelTouch( CBaseEntity *pOther );
+ void SatchelThink( void );
+ void SatchelUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
+
+ DECLARE_DATADESC();
+
+private:
+ Vector m_vLastPosition;
+ float m_flNextBounceSoundTime;
+ bool m_bInAir;
+
+private:
+ void BounceSound( void );
+ void UpdateSlideSound( void );
+ void Deactivate( void );
+};
+#endif
+
+
+#endif // HL1_WEAPON_SATCHEL_H
diff --git a/game/shared/hl1/hl1mp_weapon_shotgun.cpp b/game/shared/hl1/hl1mp_weapon_shotgun.cpp
new file mode 100644
index 0000000..ce730f7
--- /dev/null
+++ b/game/shared/hl1/hl1mp_weapon_shotgun.cpp
@@ -0,0 +1,417 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This is the Shotgun weapon
+//
+// $Workfile: $
+// $Date: $
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "npcevent.h"
+#include "hl1mp_basecombatweapon_shared.h"
+//#include "basecombatcharacter.h"
+//#include "AI_BaseNPC.h"
+#ifdef CLIENT_DLL
+#include "c_baseplayer.h"
+#else
+#include "player.h"
+#endif
+#include "gamerules.h" // For g_pGameRules
+#include "in_buttons.h"
+//#include "soundent.h"
+#include "vstdlib/random.h"
+
+
+#ifdef CLIENT_DLL
+#define CWeaponShotgun C_WeaponShotgun
+#endif
+
+// special deathmatch shotgun spreads
+#define VECTOR_CONE_DM_SHOTGUN Vector( 0.08716, 0.04362, 0.00 )// 10 degrees by 5 degrees
+#define VECTOR_CONE_DM_DOUBLESHOTGUN Vector( 0.17365, 0.04362, 0.00 ) // 20 degrees by 5 degrees
+
+
+class CWeaponShotgun : public CBaseHL1MPCombatWeapon
+{
+ DECLARE_CLASS( CWeaponShotgun, CBaseHL1MPCombatWeapon );
+
+ DECLARE_NETWORKCLASS();
+ DECLARE_PREDICTABLE();
+
+private:
+// float m_flPumpTime;
+// int m_fInSpecialReload;
+
+ CNetworkVar( float, m_flPumpTime);
+ CNetworkVar( int, m_fInSpecialReload );
+
+public:
+ void Precache( void );
+
+ bool Reload( void );
+ void FillClip( void );
+ void WeaponIdle( void );
+ void PrimaryAttack( void );
+ void SecondaryAttack( void );
+ void DryFire( void );
+
+// DECLARE_SERVERCLASS();
+// DECLARE_DATADESC();
+
+ CWeaponShotgun(void);
+
+//#ifndef CLIENT_DLL
+// DECLARE_ACTTABLE();
+//#endif
+};
+
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponShotgun, DT_WeaponShotgun );
+
+BEGIN_NETWORK_TABLE( CWeaponShotgun, DT_WeaponShotgun )
+#ifdef CLIENT_DLL
+ RecvPropFloat( RECVINFO( m_flPumpTime ) ),
+ RecvPropInt( RECVINFO( m_fInSpecialReload ) ),
+#else
+ SendPropFloat( SENDINFO( m_flPumpTime ) ),
+ SendPropInt( SENDINFO( m_fInSpecialReload ) ),
+#endif
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CWeaponShotgun )
+#ifdef CLIENT_DLL
+ DEFINE_PRED_FIELD( m_flPumpTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
+ DEFINE_PRED_FIELD( m_fInSpecialReload, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
+#endif
+END_PREDICTION_DATA()
+
+LINK_ENTITY_TO_CLASS( weapon_shotgun, CWeaponShotgun );
+PRECACHE_WEAPON_REGISTER(weapon_shotgun);
+
+//IMPLEMENT_SERVERCLASS_ST( CWeaponShotgun, DT_WeaponShotgun )
+//END_SEND_TABLE()
+
+//BEGIN_DATADESC( CWeaponShotgun )
+//END_DATADESC()
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CWeaponShotgun::CWeaponShotgun( void )
+{
+ m_bReloadsSingly = true;
+ m_bFiresUnderwater = false;
+ m_flPumpTime = 0.0;
+ m_fInSpecialReload = 0;
+}
+
+
+void CWeaponShotgun::Precache( void )
+{
+ BaseClass::Precache();
+}
+
+void CWeaponShotgun::PrimaryAttack( void )
+{
+ // Only the player fires this way so we can cast
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ if (!pPlayer)
+ {
+ return;
+ }
+
+ if ( m_iClip1 <= 0 )
+ {
+ Reload();
+ if ( m_iClip1 <= 0 )
+ DryFire( );
+
+ return;
+ }
+
+ // MUST call sound before removing a round from the clip of a CMachineGun
+ WeaponSound( SINGLE );
+
+ pPlayer->DoMuzzleFlash();
+
+ SendWeaponAnim( ACT_VM_PRIMARYATTACK );
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ // Don't fire again until fire animation has completed
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.75;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.75;
+ m_iClip1 -= 1;
+
+ Vector vecSrc = pPlayer->Weapon_ShootPosition();
+ Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
+
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ FireBulletsInfo_t info( 4, vecSrc, vecAiming, VECTOR_CONE_DM_SHOTGUN, MAX_TRACE_LENGTH, m_iPrimaryAmmoType );
+ info.m_pAttacker = pPlayer;
+
+ pPlayer->FireBullets( info );
+ }
+ else
+ {
+ FireBulletsInfo_t info( 6, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType );
+ info.m_pAttacker = pPlayer;
+
+ pPlayer->FireBullets( info );
+
+// pPlayer->FireBullets( 6, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 );
+ }
+
+ EjectShell( pPlayer, 1 );
+
+#if !defined(CLIENT_DLL)
+ pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 1.0 );
+#endif
+
+ pPlayer->ViewPunch( QAngle( -5, 0, 0 ) );
+
+// CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 600, 0.2 );
+ WeaponSound( SINGLE );
+
+ if ( !m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ {
+ // HEV suit - indicate out of ammo condition
+ pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
+ }
+
+ if ( m_iClip1 > 0 )
+ {
+ m_flPumpTime = gpGlobals->curtime + 0.5;
+ }
+
+ m_fInSpecialReload = 0;
+}
+
+
+void CWeaponShotgun::SecondaryAttack( void )
+{
+ // Only the player fires this way so we can cast
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ if (!pPlayer)
+ {
+ return;
+ }
+
+ if ( m_iClip1 <= 1 )
+ {
+ Reload();
+ if ( m_iClip1 <= 0 )
+ DryFire( );
+
+ return;
+ }
+
+ if ( pPlayer->GetWaterLevel() == 3 )
+ {
+ // This weapon doesn't fire underwater
+ WeaponSound(EMPTY);
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.2;
+ return;
+ }
+
+ // MUST call sound before removing a round from the clip of a CMachineGun
+ WeaponSound( WPN_DOUBLE );
+
+ pPlayer->DoMuzzleFlash();
+
+ SendWeaponAnim( ACT_VM_SECONDARYATTACK );
+ pPlayer->SetAnimation( PLAYER_ATTACK1 );
+
+ // Don't fire again until fire animation has completed
+ m_flNextPrimaryAttack = gpGlobals->curtime + 1.5;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 1.5;
+
+ m_iClip1 -= 2; // Shotgun uses same clip for primary and secondary attacks
+
+ Vector vecSrc = pPlayer->Weapon_ShootPosition();
+ Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
+
+ // Fire the bullets
+ if ( g_pGameRules->IsMultiplayer() )
+ {
+ FireBulletsInfo_t info( 8, vecSrc, vecAiming, VECTOR_CONE_DM_DOUBLESHOTGUN, MAX_TRACE_LENGTH, m_iPrimaryAmmoType );
+ info.m_pAttacker = pPlayer;
+
+ pPlayer->FireBullets( info );
+
+// pPlayer->FireBullets( 8, vecSrc, vecAiming, VECTOR_CONE_DM_DOUBLESHOTGUN, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 );
+ }
+ else
+ {
+ FireBulletsInfo_t info( 12, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType );
+
+ pPlayer->FireBullets( info );
+// pPlayer->FireBullets( 12, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 );
+ }
+
+ EjectShell( pPlayer, 1 );
+ EjectShell( pPlayer, 1 );
+
+ pPlayer->ViewPunch( QAngle( -10, 0, 0 ) );
+#if !defined(CLIENT_DLL)
+ pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 1.0 );
+#endif
+
+// CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 800, 0.2 );
+ WeaponSound( SINGLE );
+
+ if ( !m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ {
+ // HEV suit - indicate out of ammo condition
+ pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0);
+ }
+
+ if ( m_iClip1 > 0 )
+ {
+ m_flPumpTime = gpGlobals->curtime + 0.5;
+ }
+
+ m_fInSpecialReload = 0;
+}
+
+
+bool CWeaponShotgun::Reload( void )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+
+ if ( pOwner == NULL )
+ return false;
+
+ if ( pOwner->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
+ return false;
+
+ if ( m_iClip1 >= GetMaxClip1() )
+ return false;
+
+ // don't reload until recoil is done
+ if ( m_flNextPrimaryAttack > gpGlobals->curtime )
+ return false;
+
+ // check to see if we're ready to reload
+ if ( m_fInSpecialReload == 0 )
+ {
+ SendWeaponAnim( ACT_SHOTGUN_RELOAD_START );
+ m_fInSpecialReload = 1;
+
+ pOwner->m_flNextAttack = gpGlobals->curtime + 0.6;
+ SetWeaponIdleTime( gpGlobals->curtime + 0.6 );
+ m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 1.0;
+
+ return true;
+ }
+ else if ( m_fInSpecialReload == 1 )
+ {
+ if ( !HasWeaponIdleTimeElapsed() )
+ return false;
+
+ // was waiting for gun to move to side
+ m_fInSpecialReload = 2;
+
+ // Play reload on different channel as otherwise steals channel away from fire sound
+ WeaponSound( RELOAD );
+ SendWeaponAnim( ACT_VM_RELOAD );
+
+ SetWeaponIdleTime( gpGlobals->curtime + 0.5 );
+ }
+ else
+ {
+ FillClip();
+ m_fInSpecialReload = 1;
+ }
+
+ return true;
+}
+
+
+void CWeaponShotgun::FillClip( void )
+{
+ CBaseCombatCharacter *pOwner = GetOwner();
+
+ if ( pOwner == NULL )
+ return;
+
+ // Add them to the clip
+ m_iClip1++;
+ pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
+}
+
+
+void CWeaponShotgun::DryFire( void )
+{
+ WeaponSound( EMPTY );
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.75;
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.75;
+}
+
+
+void CWeaponShotgun::WeaponIdle( void )
+{
+ CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
+
+ if ( pPlayer == NULL )
+ return;
+
+ pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES );
+
+ if ( m_flPumpTime && m_flPumpTime < gpGlobals->curtime )
+ {
+ // play pumping sound
+ WeaponSound( SPECIAL1 );
+ m_flPumpTime = 0;
+ }
+
+ if ( HasWeaponIdleTimeElapsed() )
+ {
+ if ( m_iClip1 == 0 && m_fInSpecialReload == 0 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) > 0 )
+ {
+ Reload();
+ }
+ else if ( m_fInSpecialReload != 0 )
+ {
+ if ( m_iClip1 != 8 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) > 0 )
+ {
+ Reload( );
+ }
+ else
+ {
+ // reload debounce has timed out
+ SendWeaponAnim( ACT_SHOTGUN_PUMP );
+
+ // play cocking sound
+ WeaponSound( SPECIAL1 );
+ m_fInSpecialReload = 0;
+ SetWeaponIdleTime( gpGlobals->curtime + 1.5 );
+ }
+ }
+ else
+ {
+ int iAnim;
+ float flRand = random->RandomFloat( 0, 1 );
+
+ if ( flRand <= 0.8 )
+ {
+ iAnim = ACT_SHOTGUN_IDLE_DEEP;
+ }
+ else if ( flRand <= 0.95 )
+ {
+ iAnim = ACT_VM_IDLE;
+ }
+ else
+ {
+ iAnim = ACT_SHOTGUN_IDLE4;
+ }
+
+ SendWeaponAnim( iAnim );
+ }
+ }
+}