add hl1,portal,dod source code

This commit is contained in:
nillerusr
2022-04-16 12:05:19 +03:00
parent bc6873014e
commit 23a370d9bb
524 changed files with 174173 additions and 0 deletions
@@ -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
@@ -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
+305
View File
@@ -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();
}
+42
View File
@@ -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
+741
View File
@@ -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;
}
+65
View File
@@ -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
+373
View File
@@ -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;
}
+53
View File
@@ -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
+20
View File
@@ -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
+42
View File
@@ -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();
}
@@ -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
}
@@ -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
+739
View File
@@ -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
+91
View File
@@ -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
+289
View File
@@ -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
}
+648
View File
@@ -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
}
+529
View File
@@ -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 );
}
+719
View File
@@ -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;
}
}
+205
View File
@@ -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();
}
}
@@ -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;
}
+339
View File
@@ -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();
}
+237
View File
@@ -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 ) );
}
+53
View File
@@ -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
File diff suppressed because it is too large Load Diff
+135
View File
@@ -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
+600
View File
@@ -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
+107
View File
@@ -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
+417
View File
@@ -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 );
}
}
}