mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "sdk_basegrenade_projectile.h"
|
||||
|
||||
float GetCurrentGravity( void );
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
#include "c_sdk_player.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "soundent.h"
|
||||
|
||||
BEGIN_DATADESC( CBaseGrenadeProjectile )
|
||||
DEFINE_THINKFUNC( DangerSoundThink ),
|
||||
END_DATADESC()
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( BaseGrenadeProjectile, DT_BaseGrenadeProjectile )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CBaseGrenadeProjectile, DT_BaseGrenadeProjectile )
|
||||
#ifdef CLIENT_DLL
|
||||
RecvPropVector( RECVINFO( m_vInitialVelocity ) )
|
||||
#else
|
||||
SendPropVector( SENDINFO( m_vInitialVelocity ),
|
||||
20, // nbits
|
||||
0, // flags
|
||||
-3000, // low value
|
||||
3000 // high value
|
||||
)
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
|
||||
void CBaseGrenadeProjectile::PostDataUpdate( DataUpdateType_t type )
|
||||
{
|
||||
BaseClass::PostDataUpdate( type );
|
||||
|
||||
if ( type == DATA_UPDATE_CREATED )
|
||||
{
|
||||
// Now stick our initial velocity into the interpolation history
|
||||
CInterpolatedVar< Vector > &interpolator = GetOriginInterpolator();
|
||||
|
||||
interpolator.ClearHistory();
|
||||
float changeTime = GetLastChangeTime( LATCH_SIMULATION_VAR );
|
||||
|
||||
// Add a sample 1 second back.
|
||||
Vector vCurOrigin = GetLocalOrigin() - m_vInitialVelocity;
|
||||
interpolator.AddToHead( changeTime - 1.0, &vCurOrigin, false );
|
||||
|
||||
// Add the current sample.
|
||||
vCurOrigin = GetLocalOrigin();
|
||||
interpolator.AddToHead( changeTime, &vCurOrigin, false );
|
||||
}
|
||||
}
|
||||
|
||||
int CBaseGrenadeProjectile::DrawModel( int flags )
|
||||
{
|
||||
// During the first half-second of our life, don't draw ourselves if he's
|
||||
// still playing his throw animation.
|
||||
// (better yet, we could draw ourselves in his hand).
|
||||
if ( GetThrower() != C_BasePlayer::GetLocalPlayer() )
|
||||
{
|
||||
if ( gpGlobals->curtime - m_flSpawnTime < 0.5 )
|
||||
{
|
||||
C_SDKPlayer *pPlayer = dynamic_cast<C_SDKPlayer*>( GetThrower() );
|
||||
if ( pPlayer && pPlayer->m_PlayerAnimState->IsThrowingGrenade() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::DrawModel( flags );
|
||||
}
|
||||
|
||||
void CBaseGrenadeProjectile::Spawn()
|
||||
{
|
||||
m_flSpawnTime = gpGlobals->curtime;
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void CBaseGrenadeProjectile::Spawn( void )
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetSolidFlags( FSOLID_NOT_STANDABLE );
|
||||
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM );
|
||||
SetSolid( SOLID_BBOX ); // So it will collide with physics props!
|
||||
|
||||
// smaller, cube bounding box so we rest on the ground
|
||||
SetSize( Vector ( -2, -2, -2 ), Vector ( 2, 2, 2 ) );
|
||||
}
|
||||
|
||||
void CBaseGrenadeProjectile::DangerSoundThink( void )
|
||||
{
|
||||
if (!IsInWorld())
|
||||
{
|
||||
Remove( );
|
||||
return;
|
||||
}
|
||||
|
||||
if( gpGlobals->curtime > m_flDetonateTime )
|
||||
{
|
||||
Detonate();
|
||||
return;
|
||||
}
|
||||
|
||||
CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, GetAbsVelocity().Length( ), 0.2 );
|
||||
|
||||
SetNextThink( gpGlobals->curtime + 0.2 );
|
||||
|
||||
if (GetWaterLevel() != 0)
|
||||
{
|
||||
SetAbsVelocity( GetAbsVelocity() * 0.5 );
|
||||
}
|
||||
}
|
||||
|
||||
//Sets the time at which the grenade will explode
|
||||
void CBaseGrenadeProjectile::SetDetonateTimerLength( float timer )
|
||||
{
|
||||
m_flDetonateTime = gpGlobals->curtime + timer;
|
||||
}
|
||||
|
||||
void CBaseGrenadeProjectile::ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity )
|
||||
{
|
||||
//Assume all surfaces have the same elasticity
|
||||
float flSurfaceElasticity = 1.0;
|
||||
|
||||
//Don't bounce off of players with perfect elasticity
|
||||
if( trace.m_pEnt && trace.m_pEnt->IsPlayer() )
|
||||
{
|
||||
flSurfaceElasticity = 0.3;
|
||||
}
|
||||
|
||||
// if its breakable glass and we kill it, don't bounce.
|
||||
// give some damage to the glass, and if it breaks, pass
|
||||
// through it.
|
||||
bool breakthrough = false;
|
||||
|
||||
if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable" ) )
|
||||
{
|
||||
breakthrough = true;
|
||||
}
|
||||
|
||||
if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable_surf" ) )
|
||||
{
|
||||
breakthrough = true;
|
||||
}
|
||||
|
||||
if (breakthrough)
|
||||
{
|
||||
CTakeDamageInfo info( this, this, 10, DMG_CLUB );
|
||||
trace.m_pEnt->DispatchTraceAttack( info, GetAbsVelocity(), &trace );
|
||||
|
||||
ApplyMultiDamage();
|
||||
|
||||
if( trace.m_pEnt->m_iHealth <= 0 )
|
||||
{
|
||||
// slow our flight a little bit
|
||||
Vector vel = GetAbsVelocity();
|
||||
|
||||
vel *= 0.4;
|
||||
|
||||
SetAbsVelocity( vel );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float flTotalElasticity = GetElasticity() * flSurfaceElasticity;
|
||||
flTotalElasticity = clamp( flTotalElasticity, 0.0f, 0.9f );
|
||||
|
||||
// NOTE: A backoff of 2.0f is a reflection
|
||||
Vector vecAbsVelocity;
|
||||
PhysicsClipVelocity( GetAbsVelocity(), trace.plane.normal, vecAbsVelocity, 2.0f );
|
||||
vecAbsVelocity *= flTotalElasticity;
|
||||
|
||||
// Get the total velocity (player + conveyors, etc.)
|
||||
VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity );
|
||||
float flSpeedSqr = DotProduct( vecVelocity, vecVelocity );
|
||||
|
||||
// Stop if on ground.
|
||||
if ( trace.plane.normal.z > 0.7f ) // Floor
|
||||
{
|
||||
// Verify that we have an entity.
|
||||
CBaseEntity *pEntity = trace.m_pEnt;
|
||||
Assert( pEntity );
|
||||
|
||||
SetAbsVelocity( vecAbsVelocity );
|
||||
|
||||
if ( flSpeedSqr < ( 30 * 30 ) )
|
||||
{
|
||||
if ( pEntity->IsStandable() )
|
||||
{
|
||||
SetGroundEntity( pEntity );
|
||||
}
|
||||
|
||||
// Reset velocities.
|
||||
SetAbsVelocity( vec3_origin );
|
||||
SetLocalAngularVelocity( vec3_angle );
|
||||
|
||||
//align to the ground so we're not standing on end
|
||||
QAngle angle;
|
||||
VectorAngles( trace.plane.normal, angle );
|
||||
|
||||
// rotate randomly in yaw
|
||||
angle[1] = random->RandomFloat( 0, 360 );
|
||||
|
||||
// TODO: rotate around trace.plane.normal
|
||||
|
||||
SetAbsAngles( angle );
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector vecDelta = GetBaseVelocity() - vecAbsVelocity;
|
||||
Vector vecBaseDir = GetBaseVelocity();
|
||||
VectorNormalize( vecBaseDir );
|
||||
float flScale = vecDelta.Dot( vecBaseDir );
|
||||
|
||||
VectorScale( vecAbsVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, vecVelocity );
|
||||
VectorMA( vecVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, GetBaseVelocity() * flScale, vecVelocity );
|
||||
PhysicsPushEntity( vecVelocity, &trace );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we get *too* slow, we'll stick without ever coming to rest because
|
||||
// we'll get pushed down by gravity faster than we can escape from the wall.
|
||||
if ( flSpeedSqr < ( 30 * 30 ) )
|
||||
{
|
||||
// Reset velocities.
|
||||
SetAbsVelocity( vec3_origin );
|
||||
SetLocalAngularVelocity( vec3_angle );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAbsVelocity( vecAbsVelocity );
|
||||
}
|
||||
}
|
||||
|
||||
BounceSound();
|
||||
}
|
||||
|
||||
void CBaseGrenadeProjectile::SetupInitialTransmittedGrenadeVelocity( const Vector &velocity )
|
||||
{
|
||||
m_vInitialVelocity = velocity;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef BASECSGRENADE_PROJECTILE_H
|
||||
#define BASECSGRENADE_PROJECTILE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "basegrenade_shared.h"
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#define CBaseGrenadeProjectile C_BaseGrenadeProjectile
|
||||
#endif
|
||||
|
||||
|
||||
class CBaseGrenadeProjectile : public CBaseGrenade
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CBaseGrenadeProjectile, CBaseGrenade );
|
||||
DECLARE_NETWORKCLASS();
|
||||
|
||||
virtual void Spawn();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// This gets sent to the client and placed in the client's interpolation history
|
||||
// so the projectile starts out moving right off the bat.
|
||||
CNetworkVector( m_vInitialVelocity );
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
CBaseGrenadeProjectile() {}
|
||||
CBaseGrenadeProjectile( const CBaseGrenadeProjectile& ) {}
|
||||
virtual int DrawModel( int flags );
|
||||
virtual void PostDataUpdate( DataUpdateType_t type );
|
||||
|
||||
float m_flSpawnTime;
|
||||
#else
|
||||
DECLARE_DATADESC();
|
||||
|
||||
//Constants for all CS Grenades
|
||||
static inline float GetGrenadeGravity() { return 0.4f; }
|
||||
static inline const float GetGrenadeFriction() { return 0.2f; }
|
||||
static inline const float GetGrenadeElasticity() { return 0.45f; }
|
||||
|
||||
//Think function to emit danger sounds for the AI
|
||||
void DangerSoundThink( void );
|
||||
|
||||
virtual float GetShakeAmplitude( void ) { return 0.0f; }
|
||||
|
||||
// Specify what velocity we want the grenade to have on the client immediately.
|
||||
// Without this, the entity wouldn't have an interpolation history initially, so it would
|
||||
// sit still until it had gotten a few updates from the server.
|
||||
void SetupInitialTransmittedGrenadeVelocity( const Vector &velocity );
|
||||
|
||||
protected:
|
||||
|
||||
//Set the time to detonate ( now + timer )
|
||||
void SetDetonateTimerLength( float timer );
|
||||
|
||||
private:
|
||||
|
||||
//Custom collision to allow for constant elasticity on hit surfaces
|
||||
virtual void ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity );
|
||||
|
||||
float m_flDetonateTime;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif // BASECSGRENADE_PROJECTILE_H
|
||||
@@ -0,0 +1,224 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "sdk_fx_shared.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
#include "ilagcompensationmanager.h"
|
||||
#endif
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
#include "fx_impact.h"
|
||||
#include "c_sdk_player.h"
|
||||
|
||||
// this is a cheap ripoff from CBaseCombatWeapon::WeaponSound():
|
||||
void FX_WeaponSound(
|
||||
int iPlayerIndex,
|
||||
WeaponSound_t sound_type,
|
||||
const Vector &vOrigin,
|
||||
CSDKWeaponInfo *pWeaponInfo )
|
||||
{
|
||||
|
||||
// If we have some sounds from the weapon classname.txt file, play a random one of them
|
||||
const char *shootsound = pWeaponInfo->aShootSounds[ sound_type ];
|
||||
if ( !shootsound || !shootsound[0] )
|
||||
return;
|
||||
|
||||
CBroadcastRecipientFilter filter; // this is client side only
|
||||
if ( !te->CanPredict() )
|
||||
return;
|
||||
|
||||
CBaseEntity::EmitSound( filter, iPlayerIndex, shootsound, &vOrigin );
|
||||
}
|
||||
|
||||
class CGroupedSound
|
||||
{
|
||||
public:
|
||||
string_t m_SoundName;
|
||||
Vector m_vPos;
|
||||
};
|
||||
|
||||
CUtlVector<CGroupedSound> g_GroupedSounds;
|
||||
|
||||
|
||||
// Called by the ImpactSound function.
|
||||
void ShotgunImpactSoundGroup( const char *pSoundName, const Vector &vEndPos )
|
||||
{
|
||||
// Don't play the sound if it's too close to another impact sound.
|
||||
for ( int i=0; i < g_GroupedSounds.Count(); i++ )
|
||||
{
|
||||
CGroupedSound *pSound = &g_GroupedSounds[i];
|
||||
|
||||
if ( vEndPos.DistToSqr( pSound->m_vPos ) < 300*300 )
|
||||
{
|
||||
if ( Q_stricmp( pSound->m_SoundName, pSoundName ) == 0 )
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, play the sound and add it to the list.
|
||||
CLocalPlayerFilter filter;
|
||||
C_BaseEntity::EmitSound( filter, NULL, pSoundName, &vEndPos );
|
||||
|
||||
int j = g_GroupedSounds.AddToTail();
|
||||
g_GroupedSounds[j].m_SoundName = pSoundName;
|
||||
g_GroupedSounds[j].m_vPos = vEndPos;
|
||||
}
|
||||
|
||||
|
||||
void StartGroupingSounds()
|
||||
{
|
||||
Assert( g_GroupedSounds.Count() == 0 );
|
||||
SetImpactSoundRoute( ShotgunImpactSoundGroup );
|
||||
}
|
||||
|
||||
|
||||
void EndGroupingSounds()
|
||||
{
|
||||
g_GroupedSounds.Purge();
|
||||
SetImpactSoundRoute( NULL );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "sdk_player.h"
|
||||
#include "te_firebullets.h"
|
||||
|
||||
// Server doesn't play sounds anyway.
|
||||
void StartGroupingSounds() {}
|
||||
void EndGroupingSounds() {}
|
||||
void FX_WeaponSound ( int iPlayerIndex,
|
||||
WeaponSound_t sound_type,
|
||||
const Vector &vOrigin,
|
||||
CSDKWeaponInfo *pWeaponInfo ) {};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// This runs on both the client and the server.
|
||||
// On the server, it only does the damage calculations.
|
||||
// On the client, it does all the effects.
|
||||
void FX_FireBullets(
|
||||
int iPlayerIndex,
|
||||
const Vector &vOrigin,
|
||||
const QAngle &vAngles,
|
||||
int iWeaponID,
|
||||
int iMode,
|
||||
int iSeed,
|
||||
float flSpread
|
||||
)
|
||||
{
|
||||
bool bDoEffects = true;
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
C_SDKPlayer *pPlayer = ToSDKPlayer( ClientEntityList().GetBaseEntity( iPlayerIndex ) );
|
||||
#else
|
||||
CSDKPlayer *pPlayer = ToSDKPlayer( UTIL_PlayerByIndex( iPlayerIndex) );
|
||||
#endif
|
||||
|
||||
const char * weaponAlias = WeaponIDToAlias( iWeaponID );
|
||||
|
||||
if ( !weaponAlias )
|
||||
{
|
||||
DevMsg("FX_FireBullets: weapon alias for ID %i not found\n", iWeaponID );
|
||||
return;
|
||||
}
|
||||
|
||||
char wpnName[128];
|
||||
Q_snprintf( wpnName, sizeof( wpnName ), "weapon_%s", weaponAlias );
|
||||
WEAPON_FILE_INFO_HANDLE hWpnInfo = LookupWeaponInfoSlot( wpnName );
|
||||
|
||||
if ( hWpnInfo == GetInvalidWeaponInfoHandle() )
|
||||
{
|
||||
DevMsg("FX_FireBullets: LookupWeaponInfoSlot failed for weapon %s\n", wpnName );
|
||||
return;
|
||||
}
|
||||
|
||||
CSDKWeaponInfo *pWeaponInfo = static_cast< CSDKWeaponInfo* >( GetFileWeaponInfoFromHandle( hWpnInfo ) );
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
// Do the firing animation event.
|
||||
if ( pPlayer && !pPlayer->IsDormant() )
|
||||
{
|
||||
if ( iMode == Primary_Mode )
|
||||
pPlayer->m_PlayerAnimState->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_PRIMARY );
|
||||
else
|
||||
pPlayer->m_PlayerAnimState->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_SECONDARY );
|
||||
}
|
||||
#else
|
||||
// if this is server code, send the effect over to client as temp entity
|
||||
// Dispatch one message for all the bullet impacts and sounds.
|
||||
TE_FireBullets(
|
||||
iPlayerIndex,
|
||||
vOrigin,
|
||||
vAngles,
|
||||
iWeaponID,
|
||||
iMode,
|
||||
iSeed,
|
||||
flSpread
|
||||
);
|
||||
|
||||
bDoEffects = false; // no effects on server
|
||||
#endif
|
||||
|
||||
iSeed++;
|
||||
|
||||
int iDamage = pWeaponInfo->m_iDamage;
|
||||
int iAmmoType = pWeaponInfo->iAmmoType;
|
||||
|
||||
WeaponSound_t sound_type = SINGLE;
|
||||
|
||||
if ( bDoEffects)
|
||||
{
|
||||
FX_WeaponSound( iPlayerIndex, sound_type, vOrigin, pWeaponInfo );
|
||||
}
|
||||
|
||||
|
||||
// Fire bullets, calculate impacts & effects
|
||||
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
StartGroupingSounds();
|
||||
|
||||
#if !defined (CLIENT_DLL)
|
||||
// Move other players back to history positions based on local player's lag
|
||||
lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() );
|
||||
#endif
|
||||
|
||||
for ( int iBullet=0; iBullet < pWeaponInfo->m_iBullets; iBullet++ )
|
||||
{
|
||||
RandomSeed( iSeed ); // init random system with this seed
|
||||
|
||||
// Get circular gaussian spread.
|
||||
float x, y;
|
||||
x = RandomFloat( -0.5, 0.5 ) + RandomFloat( -0.5, 0.5 );
|
||||
y = RandomFloat( -0.5, 0.5 ) + RandomFloat( -0.5, 0.5 );
|
||||
|
||||
iSeed++; // use new seed for next bullet
|
||||
|
||||
pPlayer->FireBullet(
|
||||
vOrigin,
|
||||
vAngles,
|
||||
flSpread,
|
||||
iDamage,
|
||||
iAmmoType,
|
||||
pPlayer,
|
||||
bDoEffects,
|
||||
x,y );
|
||||
}
|
||||
|
||||
#if !defined (CLIENT_DLL)
|
||||
lagcompensation->FinishLagCompensation( pPlayer );
|
||||
#endif
|
||||
|
||||
EndGroupingSounds();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef FX_CS_SHARED_H
|
||||
#define FX_CS_SHARED_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// This runs on both the client and the server.
|
||||
// On the server, it only does the damage calculations.
|
||||
// On the client, it does all the effects.
|
||||
void FX_FireBullets(
|
||||
int iPlayer,
|
||||
const Vector &vOrigin,
|
||||
const QAngle &vAngles,
|
||||
int iWeaponID,
|
||||
int iMode,
|
||||
int iSeed,
|
||||
float flSpread
|
||||
);
|
||||
|
||||
|
||||
#endif // FX_CS_SHARED_H
|
||||
@@ -0,0 +1,53 @@
|
||||
//========= 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 "sdk_gamerules.h"
|
||||
#include "sdk_shareddefs.h"
|
||||
#include "in_buttons.h"
|
||||
#include "movevars_shared.h"
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_sdk_player.h"
|
||||
#else
|
||||
#include "sdk_player.h"
|
||||
#endif
|
||||
|
||||
|
||||
class CSDKGameMovement : public CGameMovement
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CSDKGameMovement, CGameMovement );
|
||||
|
||||
CSDKGameMovement();
|
||||
};
|
||||
|
||||
|
||||
// Expose our interface.
|
||||
static CSDKGameMovement g_GameMovement;
|
||||
IGameMovement *g_pGameMovement = ( IGameMovement * )&g_GameMovement;
|
||||
|
||||
EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CGameMovement, IGameMovement,INTERFACENAME_GAMEMOVEMENT, g_GameMovement );
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------- //
|
||||
// CSDKGameMovement.
|
||||
// ---------------------------------------------------------------------------------------- //
|
||||
|
||||
CSDKGameMovement::CSDKGameMovement()
|
||||
{
|
||||
//m_vecViewOffsetNormal = SDK_PLAYER_VIEW_OFFSET;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,369 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: The TF Game rules
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "sdk_gamerules.h"
|
||||
#include "ammodef.h"
|
||||
#include "KeyValues.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#include "voice_gamemgr.h"
|
||||
#include "team.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
LINK_ENTITY_TO_CLASS(info_player_terrorist, CPointEntity);
|
||||
LINK_ENTITY_TO_CLASS(info_player_counterterrorist,CPointEntity);
|
||||
#endif
|
||||
|
||||
REGISTER_GAMERULES_CLASS( CSDKGameRules );
|
||||
|
||||
|
||||
BEGIN_NETWORK_TABLE_NOBASE( CSDKGameRules, DT_SDKGameRules )
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
|
||||
LINK_ENTITY_TO_CLASS( sdk_gamerules, CSDKGameRulesProxy );
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( SDKGameRulesProxy, DT_SDKGameRulesProxy )
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
void RecvProxy_SDKGameRules( const RecvProp *pProp, void **pOut, void *pData, int objectID )
|
||||
{
|
||||
CSDKGameRules *pRules = SDKGameRules();
|
||||
Assert( pRules );
|
||||
*pOut = pRules;
|
||||
}
|
||||
|
||||
BEGIN_RECV_TABLE( CSDKGameRulesProxy, DT_SDKGameRulesProxy )
|
||||
RecvPropDataTable( "sdk_gamerules_data", 0, 0, &REFERENCE_RECV_TABLE( DT_SDKGameRules ), RecvProxy_SDKGameRules )
|
||||
END_RECV_TABLE()
|
||||
#else
|
||||
void *SendProxy_SDKGameRules( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID )
|
||||
{
|
||||
CSDKGameRules *pRules = SDKGameRules();
|
||||
Assert( pRules );
|
||||
pRecipients->SetAllRecipients();
|
||||
return pRules;
|
||||
}
|
||||
|
||||
BEGIN_SEND_TABLE( CSDKGameRulesProxy, DT_SDKGameRulesProxy )
|
||||
SendPropDataTable( "sdk_gamerules_data", 0, &REFERENCE_SEND_TABLE( DT_SDKGameRules ), SendProxy_SDKGameRules )
|
||||
END_SEND_TABLE()
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
|
||||
#else
|
||||
|
||||
// --------------------------------------------------------------------------------------------------- //
|
||||
// Voice helper
|
||||
// --------------------------------------------------------------------------------------------------- //
|
||||
|
||||
class CVoiceGameMgrHelper : public IVoiceGameMgrHelper
|
||||
{
|
||||
public:
|
||||
virtual bool CanPlayerHearPlayer( CBasePlayer *pListener, CBasePlayer *pTalker )
|
||||
{
|
||||
// Dead players can only be heard by other dead team mates
|
||||
if ( pTalker->IsAlive() == false )
|
||||
{
|
||||
if ( pListener->IsAlive() == false )
|
||||
return ( pListener->InSameTeam( pTalker ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ( pListener->InSameTeam( pTalker ) );
|
||||
}
|
||||
};
|
||||
CVoiceGameMgrHelper g_VoiceGameMgrHelper;
|
||||
IVoiceGameMgrHelper *g_pVoiceGameMgrHelper = &g_VoiceGameMgrHelper;
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------------------- //
|
||||
// Globals.
|
||||
// --------------------------------------------------------------------------------------------------- //
|
||||
|
||||
// NOTE: the indices here must match TEAM_TERRORIST, TEAM_CT, TEAM_SPECTATOR, etc.
|
||||
char *sTeamNames[] =
|
||||
{
|
||||
"Unassigned",
|
||||
"Spectator",
|
||||
"Terrorist",
|
||||
"Counter-Terrorist"
|
||||
};
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------------------- //
|
||||
// Global helper functions.
|
||||
// --------------------------------------------------------------------------------------------------- //
|
||||
|
||||
// World.cpp calls this but we don't use it in SDK.
|
||||
void InitBodyQue()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------------------- //
|
||||
// CSDKGameRules implementation.
|
||||
// --------------------------------------------------------------------------------------------------- //
|
||||
|
||||
CSDKGameRules::CSDKGameRules()
|
||||
{
|
||||
// Create the team managers
|
||||
for ( int i = 0; i < ARRAYSIZE( sTeamNames ); i++ )
|
||||
{
|
||||
CTeam *pTeam = static_cast<CTeam*>(CreateEntityByName( "sdk_team_manager" ));
|
||||
pTeam->Init( sTeamNames[i], i );
|
||||
|
||||
g_Teams.AddToTail( pTeam );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CSDKGameRules::~CSDKGameRules()
|
||||
{
|
||||
// Note, don't delete each team since they are in the gEntList and will
|
||||
// automatically be deleted from there, instead.
|
||||
g_Teams.Purge();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: TF2 Specific Client Commands
|
||||
// Input :
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CSDKGameRules::ClientCommand( CBaseEntity *pEdict, const CCommand &args )
|
||||
{
|
||||
return BaseClass::ClientCommand( pEdict, args );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Player has just spawned. Equip them.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void CSDKGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore )
|
||||
{
|
||||
RadiusDamage( info, vecSrcIn, flRadius, iClassIgnore, false );
|
||||
}
|
||||
|
||||
// Add the ability to ignore the world trace
|
||||
void CSDKGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, bool bIgnoreWorld )
|
||||
{
|
||||
CBaseEntity *pEntity = NULL;
|
||||
trace_t tr;
|
||||
float flAdjustedDamage, falloff;
|
||||
Vector vecSpot;
|
||||
Vector vecToTarget;
|
||||
Vector vecEndPos;
|
||||
|
||||
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 );
|
||||
|
||||
|
||||
|
||||
bool bHit = false;
|
||||
|
||||
if( bIgnoreWorld )
|
||||
{
|
||||
vecEndPos = vecSpot;
|
||||
bHit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
UTIL_TraceLine( vecSrc, vecSpot, MASK_SOLID_BRUSHONLY, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if (tr.startsolid)
|
||||
{
|
||||
// if we're stuck inside them, fixup the position and distance
|
||||
tr.endpos = vecSrc;
|
||||
tr.fraction = 0.0;
|
||||
}
|
||||
|
||||
vecEndPos = tr.endpos;
|
||||
|
||||
if( tr.fraction == 1.0 || tr.m_pEnt == pEntity )
|
||||
{
|
||||
bHit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bHit )
|
||||
{
|
||||
// the explosion can 'see' this entity, so hurt them!
|
||||
//vecToTarget = ( vecSrc - vecEndPos );
|
||||
vecToTarget = ( vecEndPos - vecSrc );
|
||||
|
||||
// decrease damage for an ent that's farther from the bomb.
|
||||
flAdjustedDamage = vecToTarget.Length() * falloff;
|
||||
flAdjustedDamage = info.GetDamage() - flAdjustedDamage;
|
||||
|
||||
if ( flAdjustedDamage > 0 )
|
||||
{
|
||||
CTakeDamageInfo adjustedInfo = info;
|
||||
adjustedInfo.SetDamage( flAdjustedDamage );
|
||||
|
||||
Vector dir = vecToTarget;
|
||||
VectorNormalize( dir );
|
||||
|
||||
// If we don't have a damage force, manufacture one
|
||||
if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin )
|
||||
{
|
||||
CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc, 1.5 /* explosion scale! */ );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume the force passed in is the maximum force. Decay it based on falloff.
|
||||
float flForce = adjustedInfo.GetDamageForce().Length() * falloff;
|
||||
adjustedInfo.SetDamageForce( dir * flForce );
|
||||
adjustedInfo.SetDamagePosition( vecSrc );
|
||||
}
|
||||
|
||||
pEntity->TakeDamage( adjustedInfo );
|
||||
|
||||
// Now hit all triggers along the way that respond to damage...
|
||||
pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, vecEndPos, dir );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSDKGameRules::Think()
|
||||
{
|
||||
BaseClass::Think();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
bool CSDKGameRules::ShouldCollide( int collisionGroup0, int collisionGroup1 )
|
||||
{
|
||||
if ( collisionGroup0 > collisionGroup1 )
|
||||
{
|
||||
// swap so that lowest is always first
|
||||
swap(collisionGroup0,collisionGroup1);
|
||||
}
|
||||
|
||||
//Don't stand on COLLISION_GROUP_WEAPON
|
||||
if( collisionGroup0 == COLLISION_GROUP_PLAYER_MOVEMENT &&
|
||||
collisionGroup1 == COLLISION_GROUP_WEAPON )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return BaseClass::ShouldCollide( collisionGroup0, collisionGroup1 );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Init CS ammo definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// 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 1
|
||||
|
||||
// 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( BULLET_PLAYER_50AE, DMG_BULLET, TRACER_LINE, 0, 0, "ammo_50AE_max", 2400, 0, 10, 14 );
|
||||
def.AddAmmoType( AMMO_GRENADE, DMG_BLAST, TRACER_LINE, 0, 0, 1/*max carry*/, 1, 0 );
|
||||
def.AddAmmoType( AMMO_BULLETS, DMG_BULLET, TRACER_LINE, 0, 0, 1/*max carry*/, 1, 0 );
|
||||
}
|
||||
|
||||
return &def;
|
||||
}
|
||||
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
|
||||
const char *CSDKGameRules::GetChatPrefix( bool bTeamOnly, CBasePlayer *pPlayer )
|
||||
{
|
||||
return "(chat prefix)";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Find the relationship between players (teamplay vs. deathmatch)
|
||||
//-----------------------------------------------------------------------------
|
||||
int CSDKGameRules::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
// half life multiplay has a simple concept of Player Relationships.
|
||||
// you are either on another player's team, or you are not.
|
||||
if ( !pPlayer || !pTarget || !pTarget->IsPlayer() || IsTeamplay() == false )
|
||||
return GR_NOTTEAMMATE;
|
||||
|
||||
if ( (*GetTeamID(pPlayer) != '\0') && (*GetTeamID(pTarget) != '\0') && !stricmp( GetTeamID(pPlayer), GetTeamID(pTarget) ) )
|
||||
return GR_TEAMMATE;
|
||||
|
||||
#endif
|
||||
|
||||
return GR_NOTTEAMMATE;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: The TF Game rules object
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef SDK_GAMERULES_H
|
||||
#define SDK_GAMERULES_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "teamplay_gamerules.h"
|
||||
#include "convar.h"
|
||||
#include "gamevars_shared.h"
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_baseplayer.h"
|
||||
#else
|
||||
#include "player.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#define CSDKGameRules C_SDKGameRules
|
||||
#define CSDKGameRulesProxy C_SDKGameRulesProxy
|
||||
#endif
|
||||
|
||||
|
||||
class CSDKGameRulesProxy : public CGameRulesProxy
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CSDKGameRulesProxy, CGameRulesProxy );
|
||||
DECLARE_NETWORKCLASS();
|
||||
};
|
||||
|
||||
|
||||
class CSDKGameRules : public CTeamplayRules
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CSDKGameRules, CTeamplayRules );
|
||||
|
||||
virtual bool ShouldCollide( int collisionGroup0, int collisionGroup1 );
|
||||
|
||||
virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget );
|
||||
virtual bool IsTeamplay( void ) { return false; }
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars.
|
||||
|
||||
#else
|
||||
|
||||
DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars.
|
||||
|
||||
CSDKGameRules();
|
||||
virtual ~CSDKGameRules();
|
||||
|
||||
virtual bool ClientCommand( CBaseEntity *pEdict, const CCommand &args );
|
||||
virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore );
|
||||
virtual void Think();
|
||||
|
||||
virtual const char *GetChatPrefix( bool bTeamOnly, CBasePlayer *pPlayer );
|
||||
|
||||
private:
|
||||
|
||||
void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, bool bIgnoreWorld );
|
||||
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets us at the team fortress game rules
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline CSDKGameRules* SDKGameRules()
|
||||
{
|
||||
return static_cast<CSDKGameRules*>(g_pGameRules);
|
||||
}
|
||||
|
||||
|
||||
#endif // SDK_GAMERULES_H
|
||||
@@ -0,0 +1,160 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
#include "c_sdk_player.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "sdk_player.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include "gamevars_shared.h"
|
||||
#include "takedamageinfo.h"
|
||||
#include "effect_dispatch_data.h"
|
||||
#include "engine/ivdebugoverlay.h"
|
||||
|
||||
ConVar sv_showimpacts("sv_showimpacts", "0", FCVAR_REPLICATED, "Shows client (red) and server (blue) bullet impact point" );
|
||||
|
||||
void DispatchEffect( const char *pName, const CEffectData &data );
|
||||
|
||||
CWeaponSDKBase* CSDKPlayer::SDKAnim_GetActiveWeapon()
|
||||
{
|
||||
return GetActiveSDKWeapon();
|
||||
}
|
||||
|
||||
bool CSDKPlayer::SDKAnim_CanMove()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSDKPlayer::FireBullet(
|
||||
Vector vecSrc, // shooting postion
|
||||
const QAngle &shootAngles, //shooting angle
|
||||
float vecSpread, // spread vector
|
||||
int iDamage, // base damage
|
||||
int iBulletType, // ammo type
|
||||
CBaseEntity *pevAttacker, // shooter
|
||||
bool bDoEffects, // create impact effect ?
|
||||
float x, // spread x factor
|
||||
float y // spread y factor
|
||||
)
|
||||
{
|
||||
float fCurrentDamage = iDamage; // damage of the bullet at it's current trajectory
|
||||
float flCurrentDistance = 0.0; //distance that the bullet has traveled so far
|
||||
|
||||
Vector vecDirShooting, vecRight, vecUp;
|
||||
AngleVectors( shootAngles, &vecDirShooting, &vecRight, &vecUp );
|
||||
|
||||
if ( !pevAttacker )
|
||||
pevAttacker = this; // the default attacker is ourselves
|
||||
|
||||
// add the spray
|
||||
Vector vecDir = vecDirShooting +
|
||||
x * vecSpread * vecRight +
|
||||
y * vecSpread * vecUp;
|
||||
|
||||
VectorNormalize( vecDir );
|
||||
|
||||
float flMaxRange = 8000;
|
||||
|
||||
Vector vecEnd = vecSrc + vecDir * flMaxRange; // max bullet range is 10000 units
|
||||
|
||||
trace_t tr; // main enter bullet trace
|
||||
|
||||
UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, this, COLLISION_GROUP_NONE, &tr );
|
||||
|
||||
if ( tr.fraction == 1.0f )
|
||||
return; // we didn't hit anything, stop tracing shoot
|
||||
|
||||
if ( sv_showimpacts.GetBool() )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
// draw red client impact markers
|
||||
debugoverlay->AddBoxOverlay( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), QAngle( 0, 0, 0), 255,0,0,127, 4 );
|
||||
|
||||
if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() )
|
||||
{
|
||||
C_BasePlayer *player = ToBasePlayer( tr.m_pEnt );
|
||||
player->DrawClientHitboxes( 4, true );
|
||||
}
|
||||
#else
|
||||
// draw blue server impact markers
|
||||
NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255,127, 4 );
|
||||
|
||||
if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() )
|
||||
{
|
||||
CBasePlayer *player = ToBasePlayer( tr.m_pEnt );
|
||||
player->DrawServerHitboxes( 4, true );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//calculate the damage based on the distance the bullet travelled.
|
||||
flCurrentDistance += tr.fraction * flMaxRange;
|
||||
|
||||
// damage get weaker of distance
|
||||
fCurrentDamage *= pow ( 0.85f, (flCurrentDistance / 500));
|
||||
|
||||
int iDamageType = DMG_BULLET | DMG_NEVERGIB;
|
||||
|
||||
if( bDoEffects )
|
||||
{
|
||||
// See if the bullet ended up underwater + started out of the water
|
||||
if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) )
|
||||
{
|
||||
trace_t waterTrace;
|
||||
UTIL_TraceLine( vecSrc, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), this, COLLISION_GROUP_NONE, &waterTrace );
|
||||
|
||||
if( waterTrace.allsolid != 1 )
|
||||
{
|
||||
CEffectData data;
|
||||
data.m_vOrigin = waterTrace.endpos;
|
||||
data.m_vNormal = waterTrace.plane.normal;
|
||||
data.m_flScale = random->RandomFloat( 8, 12 );
|
||||
|
||||
if ( waterTrace.contents & CONTENTS_SLIME )
|
||||
{
|
||||
data.m_fFlags |= FX_WATER_IN_SLIME;
|
||||
}
|
||||
|
||||
DispatchEffect( "gunshotsplash", data );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Do Regular hit effects
|
||||
|
||||
// Don't decal nodraw surfaces
|
||||
if ( !( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) )
|
||||
{
|
||||
CBaseEntity *pEntity = tr.m_pEnt;
|
||||
if ( !( !friendlyfire.GetBool() && pEntity && pEntity->IsPlayer() && pEntity->GetTeamNumber() == GetTeamNumber() ) )
|
||||
{
|
||||
UTIL_ImpactTrace( &tr, iDamageType );
|
||||
}
|
||||
}
|
||||
}
|
||||
} // bDoEffects
|
||||
|
||||
// add damage to entity that we hit
|
||||
|
||||
#ifdef GAME_DLL
|
||||
ClearMultiDamage();
|
||||
|
||||
CTakeDamageInfo info( pevAttacker, pevAttacker, fCurrentDamage, iDamageType );
|
||||
CalculateBulletDamageForce( &info, iBulletType, vecDir, tr.endpos );
|
||||
tr.m_pEnt->DispatchTraceAttack( info, vecDir, &tr );
|
||||
|
||||
TraceAttackToTriggers( info, tr.startpos, tr.endpos, vecDir );
|
||||
|
||||
ApplyMultiDamage();
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Shared Player Variables / Functions and variables that may or may not be networked
|
||||
//
|
||||
//===========================================================================================//
|
||||
|
||||
#ifndef SDK_PLAYER_SHARED_H
|
||||
#define SDK_PLAYER_SHARED_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "networkvar.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
class C_SDKPlayer;
|
||||
#else
|
||||
class CSDKPlayer;
|
||||
#endif
|
||||
|
||||
class CSDKPlayerShared
|
||||
{
|
||||
public:
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
friend class C_SDKPlayer;
|
||||
typedef C_SDKPlayer OuterClass;
|
||||
DECLARE_PREDICTABLE();
|
||||
#else
|
||||
friend class CSDKPlayer;
|
||||
typedef CSDKPlayer OuterClass;
|
||||
#endif
|
||||
|
||||
DECLARE_EMBEDDED_NETWORKVAR()
|
||||
DECLARE_CLASS_NOBASE( CSDKPlayerShared );
|
||||
|
||||
CSDKPlayerShared();
|
||||
~CSDKPlayerShared();
|
||||
|
||||
#if defined ( SDK_USE_STAMINA ) || defined ( SDK_USE_SPRINTING )
|
||||
void SetStamina( float stamina );
|
||||
float GetStamina( void ) { return m_flStamina; }
|
||||
#endif // SDK_USE_STAMINA || SDK_USE_SPRINTING
|
||||
|
||||
void Init( OuterClass *pOuter );
|
||||
|
||||
bool IsSniperZoomed( void ) const;
|
||||
bool IsDucking( void ) const;
|
||||
|
||||
#if defined ( SDK_USE_PLAYERCLASSES )
|
||||
void SetDesiredPlayerClass( int playerclass );
|
||||
int DesiredPlayerClass( void );
|
||||
|
||||
void SetPlayerClass( int playerclass );
|
||||
int PlayerClass( void );
|
||||
#endif
|
||||
|
||||
CWeaponSDKBase* GetActiveSDKWeapon() const;
|
||||
|
||||
#if defined ( SDK_USE_PRONE )
|
||||
void StartGoingProne( void );
|
||||
void StandUpFromProne( void );
|
||||
bool IsProne() const;
|
||||
bool IsGettingUpFromProne() const;
|
||||
bool IsGoingProne() const;
|
||||
void SetProne( bool bProne, bool bNoAnimation = false );
|
||||
bool CanChangePosition( void );
|
||||
#endif
|
||||
|
||||
bool IsJumping( void ) { return m_bJumping; }
|
||||
void SetJumping( bool bJumping );
|
||||
|
||||
void ForceUnzoom( void );
|
||||
|
||||
#ifdef SDK_USE_SPRINTING
|
||||
bool IsSprinting( void ) { return m_bIsSprinting; }
|
||||
|
||||
void SetSprinting( bool bSprinting );
|
||||
void StartSprinting( void );
|
||||
void StopSprinting( void );
|
||||
|
||||
void ResetSprintPenalty( void );
|
||||
#endif
|
||||
|
||||
void ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs );
|
||||
|
||||
private:
|
||||
|
||||
#if defined ( SDK_USE_PRONE )
|
||||
CNetworkVar( bool, m_bProne );
|
||||
#endif
|
||||
|
||||
#if defined ( SDK_USE_PLAYERCLASSES )
|
||||
CNetworkVar( int, m_iPlayerClass );
|
||||
CNetworkVar( int, m_iDesiredPlayerClass );
|
||||
#endif
|
||||
|
||||
|
||||
#if defined ( SDK_USE_SPRINTING )
|
||||
CNetworkVar( bool, m_bIsSprinting );
|
||||
bool m_bGaveSprintPenalty;
|
||||
#endif
|
||||
|
||||
#if defined ( SDK_USE_STAMINA ) || defined ( SDK_USE_SPRINTING )
|
||||
CNetworkVar( float, m_flStamina );
|
||||
#endif // SDK_USE_STAMINA || SDK_USE_SPRINTING
|
||||
|
||||
public:
|
||||
|
||||
#ifdef SDK_USE_PRONE
|
||||
float m_flNextProneCheck; // Prevent it switching their prone state constantly.
|
||||
|
||||
CNetworkVar( float, m_flUnProneTime );
|
||||
CNetworkVar( float, m_flGoProneTime );
|
||||
CNetworkVar( bool, m_bForceProneChange );
|
||||
#endif
|
||||
|
||||
bool m_bJumping;
|
||||
|
||||
float m_flLastViewAnimationTime;
|
||||
|
||||
//Tony; player speeds; at spawn server and client update both of these based on class (if any)
|
||||
float m_flRunSpeed;
|
||||
float m_flSprintSpeed;
|
||||
float m_flProneSpeed;
|
||||
|
||||
private:
|
||||
|
||||
OuterClass *m_pOuter;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //SDK_PLAYER_SHARED_H
|
||||
@@ -0,0 +1,621 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "base_playeranimstate.h"
|
||||
#include "tier0/vprof.h"
|
||||
#include "animation.h"
|
||||
#include "studio.h"
|
||||
#include "apparent_velocity_helper.h"
|
||||
#include "utldict.h"
|
||||
|
||||
#include "sdk_playeranimstate.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
#include "weapon_basesdkgrenade.h"
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_sdk_player.h"
|
||||
#include "bone_setup.h"
|
||||
#include "interpolatedvar.h"
|
||||
#else
|
||||
#include "sdk_player.h"
|
||||
#endif
|
||||
|
||||
#define ANIM_TOPSPEED_WALK 100
|
||||
#define ANIM_TOPSPEED_RUN 250
|
||||
#define ANIM_TOPSPEED_RUN_CROUCH 85
|
||||
|
||||
#define DEFAULT_IDLE_NAME "idle_upper_"
|
||||
#define DEFAULT_CROUCH_IDLE_NAME "crouch_idle_upper_"
|
||||
#define DEFAULT_CROUCH_WALK_NAME "crouch_walk_upper_"
|
||||
#define DEFAULT_WALK_NAME "walk_upper_"
|
||||
#define DEFAULT_RUN_NAME "run_upper_"
|
||||
|
||||
#define DEFAULT_FIRE_IDLE_NAME "idle_shoot_"
|
||||
#define DEFAULT_FIRE_CROUCH_NAME "crouch_idle_shoot_"
|
||||
#define DEFAULT_FIRE_CROUCH_WALK_NAME "crouch_walk_shoot_"
|
||||
#define DEFAULT_FIRE_WALK_NAME "walk_shoot_"
|
||||
#define DEFAULT_FIRE_RUN_NAME "run_shoot_"
|
||||
|
||||
|
||||
#define FIRESEQUENCE_LAYER (AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS)
|
||||
#define RELOADSEQUENCE_LAYER (FIRESEQUENCE_LAYER + 1)
|
||||
#define GRENADESEQUENCE_LAYER (RELOADSEQUENCE_LAYER + 1)
|
||||
#define NUM_LAYERS_WANTED (GRENADESEQUENCE_LAYER + 1)
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------ //
|
||||
// CSDKPlayerAnimState declaration.
|
||||
// ------------------------------------------------------------------------------------------------ //
|
||||
|
||||
class CSDKPlayerAnimState : public CBasePlayerAnimState, public ISDKPlayerAnimState
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CSDKPlayerAnimState, CBasePlayerAnimState );
|
||||
friend ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
|
||||
|
||||
CSDKPlayerAnimState();
|
||||
|
||||
virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData );
|
||||
virtual bool IsThrowingGrenade();
|
||||
virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle );
|
||||
virtual void ClearAnimationState();
|
||||
virtual bool CanThePlayerMove();
|
||||
virtual float GetCurrentMaxGroundSpeed();
|
||||
virtual Activity CalcMainActivity();
|
||||
virtual void DebugShowAnimState( int iStartLine );
|
||||
virtual void ComputeSequences( CStudioHdr *pStudioHdr );
|
||||
virtual void ClearAnimationLayers();
|
||||
|
||||
|
||||
void InitSDK( CBaseAnimatingOverlay *pPlayer, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
|
||||
|
||||
protected:
|
||||
|
||||
int CalcFireLayerSequence(PlayerAnimEvent_t event);
|
||||
void ComputeFireSequence(CStudioHdr *pStudioHdr);
|
||||
|
||||
void ComputeReloadSequence(CStudioHdr *pStudioHdr);
|
||||
int CalcReloadLayerSequence();
|
||||
|
||||
bool IsOuterGrenadePrimed();
|
||||
void ComputeGrenadeSequence( CStudioHdr *pStudioHdr );
|
||||
int CalcGrenadePrimeSequence();
|
||||
int CalcGrenadeThrowSequence();
|
||||
int GetOuterGrenadeThrowCounter();
|
||||
|
||||
const char* GetWeaponSuffix();
|
||||
bool HandleJumping();
|
||||
|
||||
void UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd );
|
||||
|
||||
private:
|
||||
|
||||
// Current state variables.
|
||||
bool m_bJumping; // Set on a jump event.
|
||||
float m_flJumpStartTime;
|
||||
bool m_bFirstJumpFrame;
|
||||
|
||||
// Aim sequence plays reload while this is on.
|
||||
bool m_bReloading;
|
||||
float m_flReloadCycle;
|
||||
int m_iReloadSequence;
|
||||
|
||||
// This is set to true if ANY animation is being played in the fire layer.
|
||||
bool m_bFiring; // If this is on, then it'll continue the fire animation in the fire layer
|
||||
// until it completes.
|
||||
int m_iFireSequence; // (For any sequences in the fire layer, including grenade throw).
|
||||
float m_flFireCycle;
|
||||
|
||||
// These control grenade animations.
|
||||
bool m_bThrowingGrenade;
|
||||
bool m_bPrimingGrenade;
|
||||
float m_flGrenadeCycle;
|
||||
int m_iGrenadeSequence;
|
||||
int m_iLastThrowGrenadeCounter; // used to detect when the guy threw the grenade.
|
||||
|
||||
ISDKPlayerAnimStateHelpers *m_pHelpers;
|
||||
};
|
||||
|
||||
|
||||
ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
|
||||
{
|
||||
CSDKPlayerAnimState *pRet = new CSDKPlayerAnimState;
|
||||
pRet->InitSDK( pEntity, pHelpers, legAnimType, bUseAimSequences );
|
||||
return pRet;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------ //
|
||||
// CSDKPlayerAnimState implementation.
|
||||
// ------------------------------------------------------------------------------------------------ //
|
||||
|
||||
CSDKPlayerAnimState::CSDKPlayerAnimState()
|
||||
{
|
||||
m_pOuter = NULL;
|
||||
m_bReloading = false;
|
||||
}
|
||||
|
||||
|
||||
void CSDKPlayerAnimState::InitSDK( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences )
|
||||
{
|
||||
CModAnimConfig config;
|
||||
config.m_flMaxBodyYawDegrees = 90;
|
||||
config.m_LegAnimType = legAnimType;
|
||||
config.m_bUseAimSequences = bUseAimSequences;
|
||||
|
||||
m_pHelpers = pHelpers;
|
||||
|
||||
BaseClass::Init( pEntity, config );
|
||||
}
|
||||
|
||||
|
||||
void CSDKPlayerAnimState::ClearAnimationState()
|
||||
{
|
||||
m_bJumping = false;
|
||||
m_bFiring = false;
|
||||
m_bReloading = false;
|
||||
m_bThrowingGrenade = m_bPrimingGrenade = false;
|
||||
m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
|
||||
|
||||
BaseClass::ClearAnimationState();
|
||||
}
|
||||
|
||||
|
||||
void CSDKPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData )
|
||||
{
|
||||
Assert( event != PLAYERANIMEVENT_THROW_GRENADE );
|
||||
|
||||
if ( event == PLAYERANIMEVENT_FIRE_GUN_PRIMARY ||
|
||||
event == PLAYERANIMEVENT_FIRE_GUN_SECONDARY )
|
||||
{
|
||||
// Regardless of what we're doing in the fire layer, restart it.
|
||||
m_flFireCycle = 0;
|
||||
m_iFireSequence = CalcFireLayerSequence( event );
|
||||
m_bFiring = m_iFireSequence != -1;
|
||||
}
|
||||
else if ( event == PLAYERANIMEVENT_JUMP )
|
||||
{
|
||||
// Play the jump animation.
|
||||
m_bJumping = true;
|
||||
m_bFirstJumpFrame = true;
|
||||
m_flJumpStartTime = gpGlobals->curtime;
|
||||
}
|
||||
else if ( event == PLAYERANIMEVENT_RELOAD )
|
||||
{
|
||||
m_iReloadSequence = CalcReloadLayerSequence();
|
||||
if ( m_iReloadSequence != -1 )
|
||||
{
|
||||
m_bReloading = true;
|
||||
m_flReloadCycle = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( !"CSDKPlayerAnimState::DoAnimationEvent" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float g_flThrowGrenadeFraction = 0.25;
|
||||
bool CSDKPlayerAnimState::IsThrowingGrenade()
|
||||
{
|
||||
if ( m_bThrowingGrenade )
|
||||
{
|
||||
// An animation event would be more appropriate here.
|
||||
return m_flGrenadeCycle < g_flThrowGrenadeFraction;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
|
||||
return bThrowPending || IsOuterGrenadePrimed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CSDKPlayerAnimState::CalcReloadLayerSequence()
|
||||
{
|
||||
const char *pSuffix = GetWeaponSuffix();
|
||||
if ( !pSuffix )
|
||||
return -1;
|
||||
|
||||
CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
|
||||
if ( !pWeapon )
|
||||
return -1;
|
||||
|
||||
// First, look for reload_<weapon name>.
|
||||
char szName[512];
|
||||
Q_snprintf( szName, sizeof( szName ), "reload_%s", pSuffix );
|
||||
int iReloadSequence = m_pOuter->LookupSequence( szName );
|
||||
if ( iReloadSequence != -1 )
|
||||
return iReloadSequence;
|
||||
|
||||
//SDKTODO
|
||||
/*
|
||||
// Ok, look for generic categories.. pistol, shotgun, rifle, etc.
|
||||
if ( pWeapon->GetSDKWpnData().m_WeaponType == WEAPONTYPE_PISTOL )
|
||||
{
|
||||
Q_snprintf( szName, sizeof( szName ), "reload_pistol" );
|
||||
iReloadSequence = m_pOuter->LookupSequence( szName );
|
||||
if ( iReloadSequence != -1 )
|
||||
return iReloadSequence;
|
||||
}
|
||||
*/
|
||||
|
||||
// Fall back to reload_m4.
|
||||
iReloadSequence = CalcSequenceIndex( "reload_m4" );
|
||||
if ( iReloadSequence > 0 )
|
||||
return iReloadSequence;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
void CSDKPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd )
|
||||
{
|
||||
if ( !bEnabled )
|
||||
return;
|
||||
|
||||
// Increment the fire sequence's cycle.
|
||||
flCurCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, iSequence ) * gpGlobals->frametime;
|
||||
if ( flCurCycle > 1 )
|
||||
{
|
||||
if ( bWaitAtEnd )
|
||||
{
|
||||
flCurCycle = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not firing anymore.
|
||||
bEnabled = false;
|
||||
iSequence = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now dump the state into its animation layer.
|
||||
C_AnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer );
|
||||
|
||||
pLayer->m_flCycle = flCurCycle;
|
||||
pLayer->m_nSequence = iSequence;
|
||||
|
||||
pLayer->m_flPlaybackRate = 1.0;
|
||||
pLayer->m_flWeight = 1.0f;
|
||||
pLayer->m_nOrder = iLayer;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
bool CSDKPlayerAnimState::IsOuterGrenadePrimed()
|
||||
{
|
||||
CBaseCombatCharacter *pChar = m_pOuter->MyCombatCharacterPointer();
|
||||
if ( pChar )
|
||||
{
|
||||
CBaseSDKGrenade *pGren = dynamic_cast<CBaseSDKGrenade*>( pChar->GetActiveWeapon() );
|
||||
return pGren && pGren->IsPinPulled();
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CSDKPlayerAnimState::ComputeGrenadeSequence( CStudioHdr *pStudioHdr )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
if ( m_bThrowingGrenade )
|
||||
{
|
||||
UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bThrowingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Priming the grenade isn't an event.. we just watch the player for it.
|
||||
// Also play the prime animation first if he wants to throw the grenade.
|
||||
bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter());
|
||||
if ( IsOuterGrenadePrimed() || bThrowPending )
|
||||
{
|
||||
if ( !m_bPrimingGrenade )
|
||||
{
|
||||
// If this guy just popped into our PVS, and he's got his grenade primed, then
|
||||
// let's assume that it's all the way primed rather than playing the prime
|
||||
// animation from the start.
|
||||
if ( TimeSinceLastAnimationStateClear() < 0.4f )
|
||||
m_flGrenadeCycle = 1;
|
||||
else
|
||||
m_flGrenadeCycle = 0;
|
||||
|
||||
m_iGrenadeSequence = CalcGrenadePrimeSequence();
|
||||
}
|
||||
|
||||
m_bPrimingGrenade = true;
|
||||
UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bPrimingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, true );
|
||||
|
||||
// If we're waiting to throw and we're done playing the prime animation...
|
||||
if ( bThrowPending && m_flGrenadeCycle == 1 )
|
||||
{
|
||||
m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter();
|
||||
|
||||
// Now play the throw animation.
|
||||
m_iGrenadeSequence = CalcGrenadeThrowSequence();
|
||||
if ( m_iGrenadeSequence != -1 )
|
||||
{
|
||||
// Configure to start playing
|
||||
m_bThrowingGrenade = true;
|
||||
m_bPrimingGrenade = false;
|
||||
m_flGrenadeCycle = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bPrimingGrenade = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int CSDKPlayerAnimState::CalcGrenadePrimeSequence()
|
||||
{
|
||||
return CalcSequenceIndex( "idle_shoot_gren1" );
|
||||
}
|
||||
|
||||
|
||||
int CSDKPlayerAnimState::CalcGrenadeThrowSequence()
|
||||
{
|
||||
return CalcSequenceIndex( "idle_shoot_gren2" );
|
||||
}
|
||||
|
||||
|
||||
int CSDKPlayerAnimState::GetOuterGrenadeThrowCounter()
|
||||
{
|
||||
CSDKPlayer *pPlayer = dynamic_cast<CSDKPlayer*>( m_pOuter );
|
||||
if ( pPlayer )
|
||||
return pPlayer->m_iThrowGrenadeCounter;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CSDKPlayerAnimState::ComputeReloadSequence( CStudioHdr *pStudioHdr )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
UpdateLayerSequenceGeneric( pStudioHdr, RELOADSEQUENCE_LAYER, m_bReloading, m_flReloadCycle, m_iReloadSequence, false );
|
||||
#else
|
||||
// Server doesn't bother with different fire sequences.
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int CSDKPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle )
|
||||
{
|
||||
const char *pSuffix = GetWeaponSuffix();
|
||||
if ( !pSuffix )
|
||||
return 0;
|
||||
|
||||
if ( bForceIdle )
|
||||
{
|
||||
switch ( GetCurrentMainSequenceActivity() )
|
||||
{
|
||||
case ACT_CROUCHIDLE:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );
|
||||
|
||||
default:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( GetCurrentMainSequenceActivity() )
|
||||
{
|
||||
case ACT_RUN:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_RUN_NAME, pSuffix );
|
||||
|
||||
case ACT_WALK:
|
||||
case ACT_RUNTOIDLE:
|
||||
case ACT_IDLETORUN:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_WALK_NAME, pSuffix );
|
||||
|
||||
case ACT_CROUCHIDLE:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix );
|
||||
|
||||
case ACT_RUN_CROUCH:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_WALK_NAME, pSuffix );
|
||||
|
||||
case ACT_IDLE:
|
||||
default:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char* CSDKPlayerAnimState::GetWeaponSuffix()
|
||||
{
|
||||
// Figure out the weapon suffix.
|
||||
CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
|
||||
if ( !pWeapon )
|
||||
return "Pistol";
|
||||
|
||||
const char *pSuffix = pWeapon->GetSDKWpnData().m_szAnimExtension;
|
||||
|
||||
return pSuffix;
|
||||
}
|
||||
|
||||
|
||||
int CSDKPlayerAnimState::CalcFireLayerSequence(PlayerAnimEvent_t event)
|
||||
{
|
||||
// Figure out the weapon suffix.
|
||||
CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon();
|
||||
if ( !pWeapon )
|
||||
return 0;
|
||||
|
||||
const char *pSuffix = GetWeaponSuffix();
|
||||
if ( !pSuffix )
|
||||
return 0;
|
||||
|
||||
// Don't rely on their weapon here because the player has usually switched to their
|
||||
// pistol or rifle by the time the PLAYERANIMEVENT_THROW_GRENADE message gets to the client.
|
||||
if ( event == PLAYERANIMEVENT_THROW_GRENADE )
|
||||
{
|
||||
pSuffix = "Gren";
|
||||
}
|
||||
|
||||
switch ( GetCurrentMainSequenceActivity() )
|
||||
{
|
||||
case ACT_PLAYER_RUN_FIRE:
|
||||
case ACT_RUN:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_RUN_NAME, pSuffix );
|
||||
|
||||
case ACT_PLAYER_WALK_FIRE:
|
||||
case ACT_WALK:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_WALK_NAME, pSuffix );
|
||||
|
||||
case ACT_PLAYER_CROUCH_FIRE:
|
||||
case ACT_CROUCHIDLE:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_NAME, pSuffix );
|
||||
|
||||
case ACT_PLAYER_CROUCH_WALK_FIRE:
|
||||
case ACT_RUN_CROUCH:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_WALK_NAME, pSuffix );
|
||||
|
||||
default:
|
||||
case ACT_PLAYER_IDLE_FIRE:
|
||||
return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_IDLE_NAME, pSuffix );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CSDKPlayerAnimState::CanThePlayerMove()
|
||||
{
|
||||
return m_pHelpers->SDKAnim_CanMove();
|
||||
}
|
||||
|
||||
|
||||
float CSDKPlayerAnimState::GetCurrentMaxGroundSpeed()
|
||||
{
|
||||
Activity currentActivity = m_pOuter->GetSequenceActivity( m_pOuter->GetSequence() );
|
||||
if ( currentActivity == ACT_WALK || currentActivity == ACT_IDLE )
|
||||
return ANIM_TOPSPEED_WALK;
|
||||
else if ( currentActivity == ACT_RUN )
|
||||
return ANIM_TOPSPEED_RUN;
|
||||
else if ( currentActivity == ACT_RUN_CROUCH )
|
||||
return ANIM_TOPSPEED_RUN_CROUCH;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool CSDKPlayerAnimState::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;
|
||||
}
|
||||
|
||||
|
||||
Activity CSDKPlayerAnimState::CalcMainActivity()
|
||||
{
|
||||
float flOuterSpeed = GetOuterXYSpeed();
|
||||
|
||||
if ( HandleJumping() )
|
||||
{
|
||||
return ACT_HOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
Activity idealActivity = ACT_IDLE;
|
||||
|
||||
if ( m_pOuter->GetFlags() & FL_DUCKING )
|
||||
{
|
||||
if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
|
||||
idealActivity = ACT_RUN_CROUCH;
|
||||
else
|
||||
idealActivity = ACT_CROUCHIDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( flOuterSpeed > MOVING_MINIMUM_SPEED )
|
||||
{
|
||||
if ( flOuterSpeed > ARBITRARY_RUN_SPEED )
|
||||
idealActivity = ACT_RUN;
|
||||
else
|
||||
idealActivity = ACT_WALK;
|
||||
}
|
||||
else
|
||||
{
|
||||
idealActivity = ACT_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
return idealActivity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CSDKPlayerAnimState::DebugShowAnimState( int iStartLine )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
engine->Con_NPrintf( iStartLine++, "fire : %s, cycle: %.2f\n", m_bFiring ? GetSequenceName( m_pOuter->GetModelPtr(), m_iFireSequence ) : "[not firing]", m_flFireCycle );
|
||||
engine->Con_NPrintf( iStartLine++, "reload: %s, cycle: %.2f\n", m_bReloading ? GetSequenceName( m_pOuter->GetModelPtr(), m_iReloadSequence ) : "[not reloading]", m_flReloadCycle );
|
||||
BaseClass::DebugShowAnimState( iStartLine );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CSDKPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr )
|
||||
{
|
||||
BaseClass::ComputeSequences( pStudioHdr );
|
||||
|
||||
ComputeFireSequence( pStudioHdr );
|
||||
ComputeReloadSequence( pStudioHdr );
|
||||
ComputeGrenadeSequence( pStudioHdr );
|
||||
}
|
||||
|
||||
|
||||
void CSDKPlayerAnimState::ClearAnimationLayers()
|
||||
{
|
||||
if ( !m_pOuter )
|
||||
return;
|
||||
|
||||
m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED );
|
||||
for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ )
|
||||
{
|
||||
m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CSDKPlayerAnimState::ComputeFireSequence( CStudioHdr *pStudioHdr )
|
||||
{
|
||||
#ifdef CLIENT_DLL
|
||||
UpdateLayerSequenceGeneric( pStudioHdr, FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false );
|
||||
#else
|
||||
// Server doesn't bother with different fire sequences.
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef SDK_PLAYERANIMSTATE_H
|
||||
#define SDK_PLAYERANIMSTATE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "convar.h"
|
||||
#include "iplayeranimstate.h"
|
||||
#include "base_playeranimstate.h"
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
class C_BaseAnimatingOverlay;
|
||||
class C_WeaponSDKBase;
|
||||
#define CBaseAnimatingOverlay C_BaseAnimatingOverlay
|
||||
#define CWeaponSDKBase C_WeaponSDKBase
|
||||
#define CSDKPlayer C_SDKPlayer
|
||||
#else
|
||||
class CBaseAnimatingOverlay;
|
||||
class CWeaponSDKBase;
|
||||
class CSDKPlayer;
|
||||
#endif
|
||||
|
||||
|
||||
// When moving this fast, he plays run anim.
|
||||
#define ARBITRARY_RUN_SPEED 175.0f
|
||||
|
||||
|
||||
enum PlayerAnimEvent_t
|
||||
{
|
||||
PLAYERANIMEVENT_FIRE_GUN_PRIMARY=0,
|
||||
PLAYERANIMEVENT_FIRE_GUN_SECONDARY,
|
||||
PLAYERANIMEVENT_THROW_GRENADE,
|
||||
PLAYERANIMEVENT_JUMP,
|
||||
PLAYERANIMEVENT_RELOAD,
|
||||
|
||||
PLAYERANIMEVENT_COUNT
|
||||
};
|
||||
|
||||
|
||||
class ISDKPlayerAnimState : 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 ) = 0;
|
||||
|
||||
// Returns true if we're playing the grenade prime or throw animation.
|
||||
virtual bool IsThrowingGrenade() = 0;
|
||||
};
|
||||
|
||||
|
||||
// This abstracts the differences between SDK players and hostages.
|
||||
class ISDKPlayerAnimStateHelpers
|
||||
{
|
||||
public:
|
||||
virtual CWeaponSDKBase* SDKAnim_GetActiveWeapon() = 0;
|
||||
virtual bool SDKAnim_CanMove() = 0;
|
||||
};
|
||||
|
||||
|
||||
ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences );
|
||||
|
||||
// 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 // SDK_PLAYERANIMSTATE_H
|
||||
@@ -0,0 +1,137 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "sdk_playerclass_info_parse.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
#include <KeyValues.h>
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//Tony; due to the nature of the base code.. I must do this !
|
||||
|
||||
FilePlayerClassInfo_t* CreatePlayerClassInfo()
|
||||
{
|
||||
#if defined ( SDK_USE_PLAYERCLASSES )
|
||||
return new CSDKPlayerClassInfo;
|
||||
#else
|
||||
return new FilePlayerClassInfo_t;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined ( SDK_USE_PLAYERCLASSES )
|
||||
|
||||
CSDKPlayerClassInfo::CSDKPlayerClassInfo()
|
||||
{
|
||||
m_iTeam= TEAM_UNASSIGNED;
|
||||
|
||||
m_iPrimaryWeapon= WEAPON_NONE;
|
||||
m_iSecondaryWeapon= WEAPON_NONE;
|
||||
m_iMeleeWeapon= WEAPON_NONE;
|
||||
|
||||
m_iNumGrensType1 = 0;
|
||||
m_iGrenType1 = WEAPON_NONE;
|
||||
|
||||
m_iNumGrensType2 = 0;
|
||||
m_iGrenType2 = WEAPON_NONE;
|
||||
|
||||
m_szLimitCvar[0] = '\0';
|
||||
m_flRunSpeed = SDK_DEFAULT_PLAYER_RUNSPEED;
|
||||
m_flSprintSpeed = SDK_DEFAULT_PLAYER_RUNSPEED;
|
||||
m_flProneSpeed = SDK_DEFAULT_PLAYER_RUNSPEED;
|
||||
|
||||
m_iArmor = 0;
|
||||
}
|
||||
|
||||
void CSDKPlayerClassInfo::Parse( KeyValues *pKeyValuesData, const char *szWeaponName )
|
||||
{
|
||||
BaseClass::Parse( pKeyValuesData, szWeaponName );
|
||||
|
||||
m_iTeam= pKeyValuesData->GetInt( "team", TEAM_UNASSIGNED );
|
||||
|
||||
// Figure out what team can have this player class
|
||||
m_iTeam = TEAM_UNASSIGNED;
|
||||
|
||||
//Tony; don't check for teams unless we're using teams. You could do a free for all, but class / character based game if you wanted.
|
||||
#ifdef SDK_USE_TEAMS
|
||||
const char *pTeam = pKeyValuesData->GetString( "team", NULL );
|
||||
if ( pTeam )
|
||||
{
|
||||
if ( Q_stricmp( pTeam, "BLUE" ) == 0 )
|
||||
{
|
||||
m_iTeam = SDK_TEAM_BLUE;
|
||||
}
|
||||
else if ( Q_stricmp( pTeam, "RED" ) == 0 )
|
||||
{
|
||||
m_iTeam = SDK_TEAM_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( false );
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *pszPrimaryWeapon = pKeyValuesData->GetString( "primaryweapon", NULL );
|
||||
m_iPrimaryWeapon = AliasToWeaponID( pszPrimaryWeapon );
|
||||
Assert( m_iPrimaryWeapon != WEAPON_NONE ); // require player to have a primary weapon
|
||||
|
||||
const char *pszSecondaryWeapon = pKeyValuesData->GetString( "secondaryweapon", NULL );
|
||||
|
||||
if ( pszSecondaryWeapon )
|
||||
{
|
||||
m_iSecondaryWeapon = AliasToWeaponID( pszSecondaryWeapon );
|
||||
// Assert( m_iSecondaryWeapon != WEAPON_NONE );
|
||||
}
|
||||
else
|
||||
m_iSecondaryWeapon = WEAPON_NONE;
|
||||
|
||||
const char *pszMeleeWeapon = pKeyValuesData->GetString( "meleeweapon", NULL );
|
||||
if ( pszMeleeWeapon )
|
||||
{
|
||||
m_iMeleeWeapon = AliasToWeaponID( pszMeleeWeapon );
|
||||
// Assert( m_iMeleeWeapon != WEAPON_NONE );
|
||||
}
|
||||
else
|
||||
m_iMeleeWeapon = WEAPON_NONE;
|
||||
|
||||
m_iNumGrensType1 = pKeyValuesData->GetInt( "numgrens", 0 );
|
||||
if ( m_iNumGrensType1 > 0 )
|
||||
{
|
||||
const char *pszGrenType1 = pKeyValuesData->GetString( "grenadetype", NULL );
|
||||
m_iGrenType1 = AliasToWeaponID( pszGrenType1 );
|
||||
// Assert( m_iGrenType1 != WEAPON_NONE );
|
||||
}
|
||||
|
||||
m_iNumGrensType2 = pKeyValuesData->GetInt( "numgrens2", 0 );
|
||||
if ( m_iNumGrensType2 > 0 )
|
||||
{
|
||||
const char *pszGrenType2 = pKeyValuesData->GetString( "grenadetype2", NULL );
|
||||
m_iGrenType2 = AliasToWeaponID( pszGrenType2 );
|
||||
// Assert( m_iGrenType2 != WEAPON_NONE );
|
||||
}
|
||||
|
||||
Q_strncpy( m_szLimitCvar, pKeyValuesData->GetString( "limitcvar", "!! Missing limit cvar on Player Class" ), sizeof(m_szLimitCvar) );
|
||||
|
||||
Assert( Q_strlen( m_szLimitCvar ) > 0 && "Every class must specify a limitcvar" );
|
||||
|
||||
// HUD player status health images (when the player is hurt)
|
||||
Q_strncpy( m_szClassImage, pKeyValuesData->GetString( "classimage", "white" ), sizeof( m_szClassImage ) );
|
||||
Q_strncpy( m_szClassImageBG, pKeyValuesData->GetString( "classimagebg", "white" ), sizeof( m_szClassImageBG ) );
|
||||
|
||||
m_flRunSpeed = pKeyValuesData->GetFloat( "RunSpeed", SDK_DEFAULT_PLAYER_RUNSPEED );
|
||||
m_flSprintSpeed = pKeyValuesData->GetFloat( "SprintSpeed", SDK_DEFAULT_PLAYER_RUNSPEED );
|
||||
m_flProneSpeed = pKeyValuesData->GetFloat( "ProneSpeed", SDK_DEFAULT_PLAYER_RUNSPEED );
|
||||
|
||||
m_iArmor = pKeyValuesData->GetInt( "armor", 0 );
|
||||
|
||||
}
|
||||
#endif // SDK_USE_PLAYERCLASSES
|
||||
@@ -0,0 +1,53 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef SDK_PLAYERCLASS_INFO_PARSE_H
|
||||
#define SDK_PLAYERCLASS_INFO_PARSE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "playerclass_info_parse.h"
|
||||
#include "networkvar.h"
|
||||
|
||||
#if defined ( SDK_USE_PLAYERCLASSES )
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
class CSDKPlayerClassInfo : public FilePlayerClassInfo_t
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS_GAMEROOT( CSDKPlayerClassInfo, FilePlayerClassInfo_t );
|
||||
|
||||
CSDKPlayerClassInfo();
|
||||
|
||||
virtual void Parse( ::KeyValues *pKeyValuesData, const char *szWeaponName );
|
||||
|
||||
int m_iTeam; //which team. 2 == team 1, 3 == team 2
|
||||
|
||||
int m_iPrimaryWeapon;
|
||||
int m_iSecondaryWeapon;
|
||||
int m_iMeleeWeapon;
|
||||
|
||||
int m_iNumGrensType1;
|
||||
int m_iGrenType1;
|
||||
|
||||
int m_iNumGrensType2;
|
||||
int m_iGrenType2;
|
||||
|
||||
char m_szLimitCvar[64]; //which cvar controls the class limit for this class
|
||||
|
||||
char m_szClassImage[SDK_PLAYERCLASS_IMAGE_LENGTH];
|
||||
char m_szClassImageBG[SDK_PLAYERCLASS_IMAGE_LENGTH];
|
||||
|
||||
float m_flRunSpeed;
|
||||
float m_flSprintSpeed;
|
||||
float m_flProneSpeed;
|
||||
|
||||
int m_iArmor;
|
||||
};
|
||||
#endif // SDK_USE_PLAYERCLASSES
|
||||
|
||||
#endif // DOD_PLAYERCLASS_INFO_PARSE_H
|
||||
@@ -0,0 +1,116 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// the 1 / 2 / 3 respectively are all identical in our template mod to start, I've made the base ones (pc_class1, pc_class2, pc_class3) and then duplicated them for the teams.
|
||||
//Tony; for our template we have two versions.
|
||||
#if defined ( SDK_USE_PLAYERCLASSES ) && defined ( SDK_USE_TEAMS )
|
||||
const char *pszTeamBlueClasses[] =
|
||||
{
|
||||
"blue_class1",
|
||||
"blue_class2",
|
||||
"blue_class3",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *pszTeamRedClasses[] =
|
||||
{
|
||||
"red_class1",
|
||||
"red_class2",
|
||||
"red_class3",
|
||||
NULL
|
||||
};
|
||||
ConVar mp_limit_blue_class1( "mp_limit_blue_class1", "-1", FCVAR_REPLICATED, "Class limit for Blue class 1" );
|
||||
ConVar mp_limit_blue_class2( "mp_limit_blue_class2", "-1", FCVAR_REPLICATED, "Class limit for Blue class 2" );
|
||||
ConVar mp_limit_blue_class3( "mp_limit_blue_class3", "-1", FCVAR_REPLICATED, "Class limit for Blue class 3" );
|
||||
|
||||
ConVar mp_limit_red_class1( "mp_limit_red_class1", "-1", FCVAR_REPLICATED, "Class limit for Red class 1" );
|
||||
ConVar mp_limit_red_class2( "mp_limit_red_class2", "-1", FCVAR_REPLICATED, "Class limit for Red class 2" );
|
||||
ConVar mp_limit_red_class3( "mp_limit_red_class3", "-1", FCVAR_REPLICATED, "Class limit for Red class 3" );
|
||||
|
||||
//Tony; not using teams, but we are using classes
|
||||
#elif defined ( SDK_USE_PLAYERCLASSES ) && !defined( SDK_USE_TEAMS )
|
||||
const char *pszPlayerClasses[] =
|
||||
{
|
||||
"pc_class1",
|
||||
"pc_class2",
|
||||
"pc_class3",
|
||||
NULL
|
||||
};
|
||||
ConVar mp_limit_pc_class1( "mp_limit_pc_class1", "-1", FCVAR_REPLICATED, "Class limit for class 1" );
|
||||
ConVar mp_limit_pc_class2( "mp_limit_pc_class2", "-1", FCVAR_REPLICATED, "Class limit for class 2" );
|
||||
ConVar mp_limit_pc_class3( "mp_limit_pc_class3", "-1", FCVAR_REPLICATED, "Class limit for class 3" );
|
||||
#endif
|
||||
|
||||
const char *pszTeamNames[] =
|
||||
{
|
||||
"#SDK_Team_Unassigned",
|
||||
"#SDK_Team_Spectator",
|
||||
#if defined ( SDK_USE_TEAMS )
|
||||
"#SDK_Team_Blue",
|
||||
"#SDK_Team_Red",
|
||||
#endif
|
||||
};
|
||||
|
||||
//Tony; We need to precache all possible player models that we're going to use
|
||||
const char *pszPossiblePlayerModels[] =
|
||||
{
|
||||
SDK_PLAYER_MODEL,
|
||||
"models/player/american_rifleman.mdl",
|
||||
"models/player/german_rifleman.mdl",
|
||||
NULL
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// Global Weapon Definitions
|
||||
// ----------------------------------------------------------------------------- //
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
static const char * s_WeaponAliasInfo[] =
|
||||
{
|
||||
"none", // WEAPON_NONE
|
||||
"mp5", // SDK_WEAPON_MP5
|
||||
"shotgun", // SDK_WEAPON_SHOTGUN
|
||||
"grenade", // SDK_WEAPON_GRENADE
|
||||
"pistol", // SDK_WEAPON_PISTOL
|
||||
"crowbar", // SDK_WEAPON_CROWBAR
|
||||
NULL, // WEAPON_NONE
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Given an alias, return the associated weapon ID
|
||||
//
|
||||
int AliasToWeaponID( const char *alias )
|
||||
{
|
||||
if (alias)
|
||||
{
|
||||
for( int i=0; s_WeaponAliasInfo[i] != NULL; ++i )
|
||||
if (!Q_stricmp( s_WeaponAliasInfo[i], alias ))
|
||||
return i;
|
||||
}
|
||||
|
||||
return WEAPON_NONE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Given a weapon ID, return its alias
|
||||
//
|
||||
const char *WeaponIDToAlias( int id )
|
||||
{
|
||||
if ( (id >= WEAPON_MAX) || (id < 0) )
|
||||
return NULL;
|
||||
|
||||
return s_WeaponAliasInfo[id];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef SDK_SHAREDDEFS_H
|
||||
#define SDK_SHAREDDEFS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//=========================
|
||||
// GAMEPLAY RELATED OPTIONS
|
||||
//=========================
|
||||
// NOTES: The Wizard automatically replaces these strings! If you extract the source as is, you will have to add the defines manually!
|
||||
//
|
||||
// Will your mod be team based?
|
||||
// define SDK_USE_TEAMS
|
||||
#define SDK_USE_TEAMS
|
||||
|
||||
//
|
||||
// Do you use player classes?
|
||||
// define SDK_USE_PLAYERCLASSES
|
||||
#define SDK_USE_PLAYERCLASSES
|
||||
|
||||
//================================
|
||||
// PLAYER MOVEMENT RELATED OPTIONS
|
||||
//================================
|
||||
|
||||
//
|
||||
// Do your players have stamina? - this is a pre-requisite for sprinting, if you define sprinting, and don't uncomment this, it will be included anyway.
|
||||
// define SDK_USE_STAMINA
|
||||
#define SDK_USE_STAMINA
|
||||
|
||||
//
|
||||
// Are your players able to sprint?
|
||||
// define SDK_USE_SPRINTING
|
||||
#define SDK_USE_SPRINTING
|
||||
|
||||
//Tony; stamina is a pre-requisite to sprinting, if you don't declare stamina but you do declare sprinting
|
||||
//stamina needs to be included.
|
||||
#if defined ( SDK_USE_SPRINTING ) && !defined( SDK_USE_STAMINA )
|
||||
#define SDK_USE_STAMINA
|
||||
#endif
|
||||
//
|
||||
// Can your players go prone?
|
||||
// define SDK_USE_PRONE
|
||||
#define SDK_USE_PRONE
|
||||
|
||||
//=====================
|
||||
// EXTRA WEAPON OPTIONS
|
||||
//=====================
|
||||
|
||||
//
|
||||
// If you're allowing sprinting, do you want to be able to shoot while sprinting?
|
||||
// define SDK_SHOOT_WHILE_SPRINTING
|
||||
#define SDK_SHOOT_WHILE_SPRINTING
|
||||
|
||||
//
|
||||
// Do you want your players to be able to shoot while climing ladders?
|
||||
// define SDK_SHOOT_ON_LADDERS
|
||||
#define SDK_SHOOT_ON_LADDERS
|
||||
|
||||
//
|
||||
// Do you want your players to be able to shoot while jumping?
|
||||
// define SDK_SHOOT_WHILE_JUMPING
|
||||
#define SDK_SHOOT_WHILE_JUMPING
|
||||
|
||||
|
||||
|
||||
#define SDK_GAME_DESCRIPTION "SDK Template mod v1"
|
||||
|
||||
//================================================================================
|
||||
// Most elements below here are specific to the options above.
|
||||
//================================================================================
|
||||
|
||||
#if defined ( SDK_USE_TEAMS )
|
||||
|
||||
enum sdkteams_e
|
||||
{
|
||||
SDK_TEAM_BLUE = LAST_SHARED_TEAM+1,
|
||||
SDK_TEAM_RED,
|
||||
};
|
||||
|
||||
#endif // SDK_USE_TEAMS
|
||||
|
||||
#if defined ( SDK_USE_PRONE )
|
||||
|
||||
#define TIME_TO_PRONE 1.2f
|
||||
#define VEC_PRONE_HULL_MIN SDKGameRules()->GetSDKViewVectors()->m_vProneHullMin
|
||||
#define VEC_PRONE_HULL_MAX SDKGameRules()->GetSDKViewVectors()->m_vProneHullMax
|
||||
#define VEC_PRONE_VIEW SDKGameRules()->GetSDKViewVectors()->m_vProneView
|
||||
|
||||
#endif // SDK_USE_PRONE
|
||||
|
||||
#if defined ( SDK_USE_SPRINTING )
|
||||
|
||||
#define INITIAL_SPRINT_STAMINA_PENALTY 15
|
||||
#define LOW_STAMINA_THRESHOLD 35
|
||||
|
||||
#endif // SDK_USE_SPRINTING
|
||||
|
||||
#if defined ( SDK_USE_PLAYERCLASSES )
|
||||
#define SDK_NUM_PLAYERCLASSES 3 //Tony; our template sample has 3 player classes.
|
||||
#define SDK_PLAYERCLASS_IMAGE_LENGTH 64
|
||||
|
||||
#define PLAYERCLASS_RANDOM -2
|
||||
#define PLAYERCLASS_UNDEFINED -1
|
||||
|
||||
#if defined ( SDK_USE_TEAMS )
|
||||
//Tony; using teams with classes, so make sure the team class panel names are defined.
|
||||
#define PANEL_CLASS_BLUE "class_blue"
|
||||
#define PANEL_CLASS_RED "class_red"
|
||||
|
||||
extern const char *pszTeamBlueClasses[];
|
||||
extern const char *pszTeamRedClasses[];
|
||||
#else
|
||||
#define PANEL_CLASS_NOTEAMS "class_noteams"
|
||||
extern const char *pszPlayerClasses[];
|
||||
#endif // SDK_USE_TEAMS
|
||||
|
||||
#endif // SDK_USE_PLAYERCLASSES
|
||||
|
||||
#define SDK_PLAYER_MODEL "models/player/american_rifleman.mdl"
|
||||
|
||||
//Tony; We need to precache all possible player models that we're going to use
|
||||
extern const char *pszPossiblePlayerModels[];
|
||||
|
||||
extern const char *pszTeamNames[];
|
||||
|
||||
//Tony; these defines handle the default speeds for all of these - all are listed regardless of which option is enabled.
|
||||
#define SDK_DEFAULT_PLAYER_RUNSPEED 220
|
||||
#define SDK_DEFAULT_PLAYER_SPRINTSPEED 330
|
||||
#define SDK_DEFAULT_PLAYER_PRONESPEED 50
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Weapon IDs for all SDK Game weapons
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
WEAPON_NONE = 0,
|
||||
|
||||
SDK_WEAPON_NONE = WEAPON_NONE,
|
||||
SDK_WEAPON_MP5,
|
||||
SDK_WEAPON_SHOTGUN,
|
||||
SDK_WEAPON_GRENADE,
|
||||
SDK_WEAPON_PISTOL,
|
||||
SDK_WEAPON_CROWBAR,
|
||||
|
||||
|
||||
WEAPON_MAX, // number of weapons weapon index
|
||||
} SDKWeaponID;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FM_AUTOMATIC = 0,
|
||||
FM_SEMIAUTOMATIC,
|
||||
FM_BURST,
|
||||
|
||||
} SDK_Weapon_Firemodes;
|
||||
|
||||
const char *WeaponIDToAlias( int id );
|
||||
int AliasToWeaponID( const char *alias );
|
||||
|
||||
|
||||
// The various states the player can be in during the join game process.
|
||||
enum SDKPlayerState
|
||||
{
|
||||
// Happily running around in the game.
|
||||
// You can't move though if CSGameRules()->IsFreezePeriod() returns true.
|
||||
// This state can jump to a bunch of other states like STATE_PICKINGCLASS or STATE_DEATH_ANIM.
|
||||
STATE_ACTIVE=0,
|
||||
|
||||
// This is the state you're in when you first enter the server.
|
||||
// It's switching between intro cameras every few seconds, and there's a level info
|
||||
// screen up.
|
||||
STATE_WELCOME, // Show the level intro screen.
|
||||
|
||||
// During these states, you can either be a new player waiting to join, or
|
||||
// you can be a live player in the game who wants to change teams.
|
||||
// Either way, you can't move while choosing team or class (or while any menu is up).
|
||||
#if defined ( SDK_USE_TEAMS )
|
||||
STATE_PICKINGTEAM, // Choosing team.
|
||||
#endif
|
||||
#if defined ( SDK_USE_PLAYERCLASSES )
|
||||
STATE_PICKINGCLASS, // Choosing class.
|
||||
#endif
|
||||
|
||||
STATE_DEATH_ANIM, // Playing death anim, waiting for that to finish.
|
||||
STATE_OBSERVER_MODE, // Noclipping around, watching players, etc.
|
||||
|
||||
NUM_PLAYER_STATES
|
||||
};
|
||||
#define SDK_PLAYER_DEATH_TIME 5.0f //Minimum Time before respawning
|
||||
|
||||
// Special Damage types
|
||||
enum
|
||||
{
|
||||
SDK_DMG_CUSTOM_NONE = 0,
|
||||
SDK_DMG_CUSTOM_SUICIDE,
|
||||
};
|
||||
|
||||
// Player avoidance
|
||||
#define PUSHAWAY_THINK_INTERVAL (1.0f / 20.0f)
|
||||
|
||||
#endif // SDK_SHAREDDEFS_H
|
||||
@@ -0,0 +1,49 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "usermessages.h"
|
||||
#include "shake.h"
|
||||
#include "voice_gamemgr.h"
|
||||
|
||||
void RegisterUserMessages()
|
||||
{
|
||||
usermessages->Register( "Geiger", 1 ); // geiger info data
|
||||
usermessages->Register( "Train", 1 ); // train control data
|
||||
usermessages->Register( "HudText", -1 );
|
||||
usermessages->Register( "SayText", -1 );
|
||||
usermessages->Register( "TextMsg", -1 );
|
||||
usermessages->Register( "HudMsg", -1 );
|
||||
usermessages->Register( "ResetHUD", 1 ); // called every respawn
|
||||
usermessages->Register( "GameTitle", 0 ); // show game title
|
||||
usermessages->Register( "ItemPickup", -1 ); // for item history on screen
|
||||
usermessages->Register( "ShowMenu", -1 ); // show hud menu
|
||||
usermessages->Register( "Shake", 13 ); // shake view
|
||||
usermessages->Register( "Fade", 10 ); // fade HUD in/out
|
||||
usermessages->Register( "VGUIMenu", -1 ); // Show VGUI menu
|
||||
usermessages->Register( "CloseCaption", -1 ); // Show a caption (by string id number)(duration in 10th of a second)
|
||||
|
||||
usermessages->Register( "SendAudio", -1 ); // play radion command
|
||||
|
||||
usermessages->Register( "VoiceMask", VOICE_MAX_PLAYERS_DW*4 * 2 + 1 );
|
||||
usermessages->Register( "RequestState", 0 );
|
||||
|
||||
usermessages->Register( "BarTime", -1 ); // For the C4 progress bar.
|
||||
usermessages->Register( "Damage", -1 ); // for HUD damage indicators
|
||||
usermessages->Register( "RadioText", -1 ); // for HUD damage indicators
|
||||
usermessages->Register( "HintText", -1 ); // Displays hint text display
|
||||
usermessages->Register( "KeyHintText", -1 ); // Displays hint text display
|
||||
|
||||
usermessages->Register( "ReloadEffect", 2 ); // a player reloading..
|
||||
usermessages->Register( "PlayerAnimEvent", -1 ); // jumping, firing, reload, etc.
|
||||
|
||||
usermessages->Register( "AmmoDenied", 2 );
|
||||
usermessages->Register( "UpdateRadar", -1 );
|
||||
|
||||
// Used to send a sample HUD message
|
||||
usermessages->Register( "GameMessage", -1 );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Base code for any melee based weapon
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
|
||||
#include "weapon_sdkbase.h"
|
||||
#include "sdk_weapon_melee.h"
|
||||
|
||||
#include "sdk_gamerules.h"
|
||||
#include "ammodef.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "in_buttons.h"
|
||||
#include "animation.h"
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
#include "c_sdk_player.h"
|
||||
#else
|
||||
#include "sdk_player.h"
|
||||
#include "ndebugoverlay.h"
|
||||
#include "te_effect_dispatch.h"
|
||||
#include "ilagcompensationmanager.h"
|
||||
#endif
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponSDKMelee, DT_WeaponSDKMelee )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CWeaponSDKMelee, DT_WeaponSDKMelee )
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( CWeaponSDKMelee )
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
#define MELEE_HULL_DIM 16
|
||||
|
||||
static const Vector g_meleeMins(-MELEE_HULL_DIM,-MELEE_HULL_DIM,-MELEE_HULL_DIM);
|
||||
static const Vector g_meleeMaxs(MELEE_HULL_DIM,MELEE_HULL_DIM,MELEE_HULL_DIM);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CWeaponSDKMelee::CWeaponSDKMelee()
|
||||
{
|
||||
m_bFiresUnderwater = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Spawn the weapon
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponSDKMelee::Spawn( void )
|
||||
{
|
||||
m_fMinRange1 = 0;
|
||||
m_fMinRange2 = 0;
|
||||
m_fMaxRange1 = 64;
|
||||
m_fMaxRange2 = 64;
|
||||
//Call base class first
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Precache the weapon
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponSDKMelee::Precache( void )
|
||||
{
|
||||
//Call base class first
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Update weapon
|
||||
//------------------------------------------------------------------------------
|
||||
void CWeaponSDKMelee::ItemPostFrame( void )
|
||||
{
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
if ( pPlayer == NULL )
|
||||
return;
|
||||
|
||||
if ( (pPlayer->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) && pPlayer->CanAttack() )
|
||||
{
|
||||
PrimaryAttack();
|
||||
}
|
||||
else if ( (pPlayer->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime) && pPlayer->CanAttack() )
|
||||
{
|
||||
SecondaryAttack();
|
||||
}
|
||||
else
|
||||
{
|
||||
WeaponIdle();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CWeaponSDKMelee::PrimaryAttack()
|
||||
{
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
CSDKPlayer *pPlayer = ToSDKPlayer( GetPlayerOwner() );
|
||||
// Move other players back to history positions based on local player's lag
|
||||
lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() );
|
||||
#endif
|
||||
Swing( false );
|
||||
#ifndef CLIENT_DLL
|
||||
// Move other players back to history positions based on local player's lag
|
||||
lagcompensation->FinishLagCompensation( pPlayer );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose :
|
||||
// Input :
|
||||
// Output :
|
||||
//------------------------------------------------------------------------------
|
||||
void CWeaponSDKMelee::SecondaryAttack()
|
||||
{
|
||||
Swing( true );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose: Implement impact function
|
||||
//------------------------------------------------------------------------------
|
||||
void CWeaponSDKMelee::Hit( trace_t &traceHit, Activity nHitActivity )
|
||||
{
|
||||
CSDKPlayer *pPlayer = ToSDKPlayer( GetOwner() );
|
||||
|
||||
//Do view kick
|
||||
// AddViewKick();
|
||||
|
||||
CBaseEntity *pHitEntity = traceHit.m_pEnt;
|
||||
|
||||
//Apply damage to a hit target
|
||||
if ( pHitEntity != NULL )
|
||||
{
|
||||
Vector hitDirection;
|
||||
pPlayer->EyeVectors( &hitDirection, NULL, NULL );
|
||||
VectorNormalize( hitDirection );
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
CTakeDamageInfo info( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB );
|
||||
|
||||
if( pPlayer && pHitEntity->IsNPC() )
|
||||
{
|
||||
// If bonking an NPC, adjust damage.
|
||||
info.AdjustPlayerDamageInflictedForSkillLevel();
|
||||
}
|
||||
|
||||
CalculateMeleeDamageForce( &info, hitDirection, traceHit.endpos );
|
||||
|
||||
pHitEntity->DispatchTraceAttack( info, hitDirection, &traceHit );
|
||||
ApplyMultiDamage();
|
||||
|
||||
// Now hit all triggers along the ray that...
|
||||
TraceAttackToTriggers( info, traceHit.startpos, traceHit.endpos, hitDirection );
|
||||
#endif
|
||||
WeaponSound( MELEE_HIT );
|
||||
}
|
||||
|
||||
// Apply an impact effect
|
||||
ImpactEffect( traceHit );
|
||||
}
|
||||
|
||||
Activity CWeaponSDKMelee::ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CSDKPlayer *pOwner )
|
||||
{
|
||||
int i, j, k;
|
||||
float distance;
|
||||
const float *minmaxs[2] = {mins.Base(), maxs.Base()};
|
||||
trace_t tmpTrace;
|
||||
Vector vecHullEnd = hitTrace.endpos;
|
||||
Vector vecEnd;
|
||||
|
||||
distance = 1e6f;
|
||||
Vector vecSrc = hitTrace.startpos;
|
||||
|
||||
vecHullEnd = vecSrc + ((vecHullEnd - vecSrc)*2);
|
||||
UTIL_TraceLine( vecSrc, vecHullEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &tmpTrace );
|
||||
if ( tmpTrace.fraction == 1.0 )
|
||||
{
|
||||
for ( i = 0; i < 2; i++ )
|
||||
{
|
||||
for ( j = 0; j < 2; j++ )
|
||||
{
|
||||
for ( k = 0; k < 2; k++ )
|
||||
{
|
||||
vecEnd.x = vecHullEnd.x + minmaxs[i][0];
|
||||
vecEnd.y = vecHullEnd.y + minmaxs[j][1];
|
||||
vecEnd.z = vecHullEnd.z + minmaxs[k][2];
|
||||
|
||||
UTIL_TraceLine( vecSrc, vecEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &tmpTrace );
|
||||
if ( tmpTrace.fraction < 1.0 )
|
||||
{
|
||||
float thisDistance = (tmpTrace.endpos - vecSrc).Length();
|
||||
if ( thisDistance < distance )
|
||||
{
|
||||
hitTrace = tmpTrace;
|
||||
distance = thisDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hitTrace = tmpTrace;
|
||||
}
|
||||
|
||||
|
||||
return ACT_VM_HITCENTER;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &traceHit -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CWeaponSDKMelee::ImpactWater( const Vector &start, const Vector &end )
|
||||
{
|
||||
//FIXME: This doesn't handle the case of trying to splash while being underwater, but that's not going to look good
|
||||
// right now anyway...
|
||||
|
||||
// We must start outside the water
|
||||
if ( UTIL_PointContents( start ) & (CONTENTS_WATER|CONTENTS_SLIME))
|
||||
return false;
|
||||
|
||||
// We must end inside of water
|
||||
if ( !(UTIL_PointContents( end ) & (CONTENTS_WATER|CONTENTS_SLIME)))
|
||||
return false;
|
||||
|
||||
trace_t waterTrace;
|
||||
|
||||
UTIL_TraceLine( start, end, (CONTENTS_WATER|CONTENTS_SLIME), GetOwner(), COLLISION_GROUP_NONE, &waterTrace );
|
||||
|
||||
if ( waterTrace.fraction < 1.0f )
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
CEffectData data;
|
||||
|
||||
data.m_fFlags = 0;
|
||||
data.m_vOrigin = waterTrace.endpos;
|
||||
data.m_vNormal = waterTrace.plane.normal;
|
||||
data.m_flScale = 8.0f;
|
||||
|
||||
// See if we hit slime
|
||||
if ( waterTrace.contents & CONTENTS_SLIME )
|
||||
{
|
||||
data.m_fFlags |= FX_WATER_IN_SLIME;
|
||||
}
|
||||
|
||||
DispatchEffect( "watersplash", data );
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CWeaponSDKMelee::ImpactEffect( trace_t &traceHit )
|
||||
{
|
||||
// See if we hit water (we don't do the other impact effects in this case)
|
||||
if ( ImpactWater( traceHit.startpos, traceHit.endpos ) )
|
||||
return;
|
||||
|
||||
//FIXME: need new decals
|
||||
UTIL_ImpactTrace( &traceHit, DMG_CLUB );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Purpose : Starts the swing of the weapon and determines the animation
|
||||
// Input : bIsSecondary - is this a secondary attack?
|
||||
//------------------------------------------------------------------------------
|
||||
void CWeaponSDKMelee::Swing( int bIsSecondary )
|
||||
{
|
||||
trace_t traceHit;
|
||||
|
||||
// Try a ray
|
||||
CSDKPlayer *pOwner = ToSDKPlayer( GetOwner() );
|
||||
if ( !pOwner )
|
||||
return;
|
||||
|
||||
Vector swingStart = pOwner->Weapon_ShootPosition( );
|
||||
Vector forward;
|
||||
|
||||
pOwner->EyeVectors( &forward, NULL, NULL );
|
||||
|
||||
Vector swingEnd = swingStart + forward * GetRange();
|
||||
UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit );
|
||||
Activity nHitActivity = ACT_VM_HITCENTER;
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
// Like bullets, melee traces have to trace against triggers.
|
||||
CTakeDamageInfo triggerInfo( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB );
|
||||
TraceAttackToTriggers( triggerInfo, traceHit.startpos, traceHit.endpos, vec3_origin );
|
||||
#endif
|
||||
|
||||
if ( traceHit.fraction == 1.0 )
|
||||
{
|
||||
float meleeHullRadius = 1.732f * MELEE_HULL_DIM; // hull is +/- 16, so use cuberoot of 2 to determine how big the hull is from center to the corner point
|
||||
|
||||
// Back off by hull "radius"
|
||||
swingEnd -= forward * meleeHullRadius;
|
||||
|
||||
UTIL_TraceHull( swingStart, swingEnd, g_meleeMins, g_meleeMaxs, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit );
|
||||
if ( traceHit.fraction < 1.0 && traceHit.m_pEnt )
|
||||
{
|
||||
Vector vecToTarget = traceHit.m_pEnt->GetAbsOrigin() - swingStart;
|
||||
VectorNormalize( vecToTarget );
|
||||
|
||||
float dot = vecToTarget.Dot( forward );
|
||||
|
||||
// YWB: Make sure they are sort of facing the guy at least...
|
||||
if ( dot < 0.70721f )
|
||||
{
|
||||
// Force amiss
|
||||
traceHit.fraction = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
nHitActivity = ChooseIntersectionPointAndActivity( traceHit, g_meleeMins, g_meleeMaxs, pOwner );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WeaponSound( SINGLE );
|
||||
|
||||
// -------------------------
|
||||
// Miss
|
||||
// -------------------------
|
||||
if ( traceHit.fraction == 1.0f )
|
||||
{
|
||||
nHitActivity = bIsSecondary ? ACT_VM_MISSCENTER2 : ACT_VM_MISSCENTER;
|
||||
|
||||
// We want to test the first swing again
|
||||
Vector testEnd = swingStart + forward * GetRange();
|
||||
|
||||
// See if we happened to hit water
|
||||
ImpactWater( swingStart, testEnd );
|
||||
}
|
||||
else
|
||||
{
|
||||
Hit( traceHit, nHitActivity );
|
||||
}
|
||||
|
||||
// Send the anim
|
||||
SendWeaponAnim( nHitActivity );
|
||||
|
||||
pOwner->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY );
|
||||
|
||||
//Setup our next attack times
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Base code for any melee based weapon
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#ifndef SDK_WEAPON_MELEE_H
|
||||
#define SDK_WEAPON_MELEE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
#define CWeaponSDKMelee C_WeaponSDKMelee
|
||||
#endif
|
||||
|
||||
//=========================================================
|
||||
// CBaseHLBludgeonWeapon
|
||||
//=========================================================
|
||||
class CWeaponSDKMelee : public CWeaponSDKBase
|
||||
{
|
||||
DECLARE_CLASS( CWeaponSDKMelee, CWeaponSDKBase );
|
||||
public:
|
||||
CWeaponSDKMelee();
|
||||
|
||||
DECLARE_NETWORKCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
virtual void Spawn( void );
|
||||
virtual void Precache( void );
|
||||
|
||||
//Attack functions
|
||||
virtual void PrimaryAttack( void );
|
||||
virtual void SecondaryAttack( void );
|
||||
|
||||
virtual void ItemPostFrame( void );
|
||||
|
||||
//Functions to select animation sequences
|
||||
virtual Activity GetPrimaryAttackActivity( void ) { return ACT_VM_HITCENTER; }
|
||||
virtual Activity GetSecondaryAttackActivity( void ) { return ACT_VM_HITCENTER2; }
|
||||
|
||||
virtual float GetRange( void ) { return 32.0f; }
|
||||
virtual float GetDamageForActivity( Activity hitActivity ) { return GetSDKWpnData().m_iDamage; }
|
||||
|
||||
CWeaponSDKMelee( const CWeaponSDKMelee & );
|
||||
|
||||
protected:
|
||||
virtual void ImpactEffect( trace_t &trace );
|
||||
|
||||
private:
|
||||
bool ImpactWater( const Vector &start, const Vector &end );
|
||||
void Swing( int bIsSecondary );
|
||||
void Hit( trace_t &traceHit, Activity nHitActivity );
|
||||
Activity ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CSDKPlayer *pOwner );
|
||||
};
|
||||
|
||||
|
||||
#endif // SDK_WEAPON_MELEE_H
|
||||
@@ -0,0 +1,35 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include <KeyValues.h>
|
||||
#include "sdk_weapon_parse.h"
|
||||
|
||||
|
||||
FileWeaponInfo_t* CreateWeaponInfo()
|
||||
{
|
||||
return new CSDKWeaponInfo;
|
||||
}
|
||||
|
||||
|
||||
CSDKWeaponInfo::CSDKWeaponInfo()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CSDKWeaponInfo::Parse( KeyValues *pKeyValuesData, const char *szWeaponName )
|
||||
{
|
||||
BaseClass::Parse( pKeyValuesData, szWeaponName );
|
||||
|
||||
m_iDamage = pKeyValuesData->GetInt( "Damage", 42 ); // Douglas Adams 1952 - 2001
|
||||
m_iBullets = pKeyValuesData->GetInt( "Bullets", 1 );
|
||||
m_flCycleTime = pKeyValuesData->GetFloat( "CycleTime", 0.15 );
|
||||
|
||||
const char *pAnimEx = pKeyValuesData->GetString( "PlayerAnimationExtension", "mp5" );
|
||||
Q_strncpy( m_szAnimExtension, pAnimEx, sizeof( m_szAnimExtension ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef SDK_WEAPON_PARSE_H
|
||||
#define SDK_WEAPON_PARSE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "weapon_parse.h"
|
||||
#include "networkvar.h"
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
class CSDKWeaponInfo : public FileWeaponInfo_t
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS_GAMEROOT( CSDKWeaponInfo, FileWeaponInfo_t );
|
||||
|
||||
CSDKWeaponInfo();
|
||||
|
||||
virtual void Parse( ::KeyValues *pKeyValuesData, const char *szWeaponName );
|
||||
|
||||
char m_szAnimExtension[16]; // string used to generate player animations with this weapon
|
||||
|
||||
// Parameters for FX_FireBullets:
|
||||
int m_iDamage;
|
||||
int m_iBullets;
|
||||
float m_flCycleTime;
|
||||
};
|
||||
|
||||
|
||||
#endif // SDK_WEAPON_PARSE_H
|
||||
@@ -0,0 +1,363 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
#include "gamerules.h"
|
||||
#include "npcevent.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "weapon_basesdkgrenade.h"
|
||||
#include "in_buttons.h"
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
#include "c_sdk_player.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "sdk_player.h"
|
||||
#include "items.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define GRENADE_TIMER 1.5f //Seconds
|
||||
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( BaseSDKGrenade, DT_BaseSDKGrenade )
|
||||
|
||||
BEGIN_NETWORK_TABLE(CBaseSDKGrenade, DT_BaseSDKGrenade)
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
SendPropBool( SENDINFO(m_bRedraw) ),
|
||||
SendPropBool( SENDINFO(m_bPinPulled) ),
|
||||
SendPropFloat( SENDINFO(m_fThrowTime), 0, SPROP_NOSCALE ),
|
||||
#else
|
||||
RecvPropBool( RECVINFO(m_bRedraw) ),
|
||||
RecvPropBool( RECVINFO(m_bPinPulled) ),
|
||||
RecvPropFloat( RECVINFO(m_fThrowTime) ),
|
||||
#endif
|
||||
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
BEGIN_PREDICTION_DATA( CBaseSDKGrenade )
|
||||
DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
END_PREDICTION_DATA()
|
||||
#endif
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_basesdkgrenade, CBaseSDKGrenade );
|
||||
|
||||
|
||||
CBaseSDKGrenade::CBaseSDKGrenade()
|
||||
{
|
||||
m_bRedraw = false;
|
||||
m_bPinPulled = false;
|
||||
m_fThrowTime = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseSDKGrenade::Precache()
|
||||
{
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseSDKGrenade::Deploy()
|
||||
{
|
||||
m_bRedraw = false;
|
||||
m_bPinPulled = false;
|
||||
m_fThrowTime = 0;
|
||||
|
||||
return BaseClass::Deploy();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseSDKGrenade::Holster( CBaseCombatWeapon *pSwitchingTo )
|
||||
{
|
||||
m_bRedraw = false;
|
||||
m_bPinPulled = false; // when this is holstered make sure the pin isn’t pulled.
|
||||
m_fThrowTime = 0;
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
// If they attempt to switch weapons before the throw animation is done,
|
||||
// allow it, but kill the weapon if we have to.
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
|
||||
if( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
|
||||
{
|
||||
CBaseCombatCharacter *pOwner = (CBaseCombatCharacter *)pPlayer;
|
||||
pOwner->Weapon_Drop( this );
|
||||
UTIL_Remove(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
return BaseClass::Holster( pSwitchingTo );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseSDKGrenade::PrimaryAttack()
|
||||
{
|
||||
if ( m_bRedraw || m_bPinPulled )
|
||||
return;
|
||||
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
if ( !pPlayer || pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
|
||||
return;
|
||||
|
||||
// The pull pin animation has to finish, then we wait until they aren't holding the primary
|
||||
// attack button, then throw the grenade.
|
||||
SendWeaponAnim( ACT_VM_PULLPIN );
|
||||
m_bPinPulled = true;
|
||||
|
||||
// Don't let weapon idle interfere in the middle of a throw!
|
||||
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
|
||||
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseSDKGrenade::SecondaryAttack()
|
||||
{
|
||||
if ( m_bRedraw )
|
||||
return;
|
||||
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
|
||||
if ( pPlayer == NULL )
|
||||
return;
|
||||
|
||||
//See if we're ducking
|
||||
if ( pPlayer->GetFlags() & FL_DUCKING )
|
||||
{
|
||||
//Send the weapon animation
|
||||
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
|
||||
}
|
||||
else
|
||||
{
|
||||
//Send the weapon animation
|
||||
SendWeaponAnim( ACT_VM_HAULBACK );
|
||||
}
|
||||
|
||||
// Don't let weapon idle interfere in the middle of a throw!
|
||||
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
|
||||
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CBaseSDKGrenade::Reload()
|
||||
{
|
||||
if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) )
|
||||
{
|
||||
//Redraw the weapon
|
||||
SendWeaponAnim( ACT_VM_DRAW );
|
||||
|
||||
//Update our times
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
|
||||
|
||||
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseSDKGrenade::ItemPostFrame()
|
||||
{
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
CBaseViewModel *vm = pPlayer->GetViewModel( m_nViewModelIndex );
|
||||
if ( !vm )
|
||||
return;
|
||||
|
||||
// If they let go of the fire button, they want to throw the grenade.
|
||||
if ( m_bPinPulled && !(pPlayer->m_nButtons & IN_ATTACK) )
|
||||
{
|
||||
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE );
|
||||
|
||||
StartGrenadeThrow();
|
||||
|
||||
DecrementAmmo( pPlayer );
|
||||
|
||||
m_bPinPulled = false;
|
||||
SendWeaponAnim( ACT_VM_THROW );
|
||||
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
|
||||
}
|
||||
else if ((m_fThrowTime > 0) && (m_fThrowTime < gpGlobals->curtime))
|
||||
{
|
||||
ThrowGrenade();
|
||||
}
|
||||
else if( m_bRedraw )
|
||||
{
|
||||
// Has the throw animation finished playing
|
||||
if( m_flTimeWeaponIdle < gpGlobals->curtime )
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
// if we're officially out of grenades, ditch this weapon
|
||||
if( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
|
||||
{
|
||||
pPlayer->Weapon_Drop( this, NULL, NULL );
|
||||
UTIL_Remove(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
pPlayer->SwitchToNextBestWeapon( this );
|
||||
}
|
||||
#endif
|
||||
return; //don't animate this grenade any more!
|
||||
}
|
||||
}
|
||||
else if( !m_bRedraw )
|
||||
{
|
||||
BaseClass::ItemPostFrame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
void CBaseSDKGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner )
|
||||
{
|
||||
}
|
||||
|
||||
void CBaseSDKGrenade::DropGrenade()
|
||||
{
|
||||
m_bRedraw = true;
|
||||
m_fThrowTime = 0.0f;
|
||||
}
|
||||
|
||||
void CBaseSDKGrenade::ThrowGrenade()
|
||||
{
|
||||
m_bRedraw = true;
|
||||
m_fThrowTime = 0.0f;
|
||||
}
|
||||
|
||||
void CBaseSDKGrenade::StartGrenadeThrow()
|
||||
{
|
||||
m_fThrowTime = gpGlobals->curtime + 0.1f;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
BEGIN_DATADESC( CBaseSDKGrenade )
|
||||
DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ),
|
||||
END_DATADESC()
|
||||
|
||||
int CBaseSDKGrenade::CapabilitiesGet()
|
||||
{
|
||||
return bits_CAP_WEAPON_RANGE_ATTACK1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pOwner -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CBaseSDKGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner )
|
||||
{
|
||||
pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
|
||||
}
|
||||
|
||||
void CBaseSDKGrenade::StartGrenadeThrow()
|
||||
{
|
||||
m_fThrowTime = gpGlobals->curtime + 0.1f;
|
||||
}
|
||||
|
||||
void CBaseSDKGrenade::ThrowGrenade()
|
||||
{
|
||||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||||
if ( !pPlayer )
|
||||
{
|
||||
Assert( false );
|
||||
return;
|
||||
}
|
||||
|
||||
QAngle angThrow = pPlayer->LocalEyeAngles();
|
||||
|
||||
Vector vForward, vRight, vUp;
|
||||
|
||||
if (angThrow.x < 90 )
|
||||
angThrow.x = -10 + angThrow.x * ((90 + 10) / 90.0);
|
||||
else
|
||||
{
|
||||
angThrow.x = 360.0f - angThrow.x;
|
||||
angThrow.x = -10 + angThrow.x * -((90 - 10) / 90.0);
|
||||
}
|
||||
|
||||
float flVel = (90 - angThrow.x) * 6;
|
||||
|
||||
if (flVel > 750)
|
||||
flVel = 750;
|
||||
|
||||
AngleVectors( angThrow, &vForward, &vRight, &vUp );
|
||||
|
||||
Vector vecSrc = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset();
|
||||
|
||||
vecSrc += vForward * 16;
|
||||
|
||||
Vector vecThrow = vForward * flVel + pPlayer->GetAbsVelocity();
|
||||
|
||||
EmitGrenade( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer );
|
||||
|
||||
m_bRedraw = true;
|
||||
m_fThrowTime = 0.0f;
|
||||
}
|
||||
|
||||
void CBaseSDKGrenade::DropGrenade()
|
||||
{
|
||||
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||||
if ( !pPlayer )
|
||||
{
|
||||
Assert( false );
|
||||
return;
|
||||
}
|
||||
|
||||
Vector vForward;
|
||||
pPlayer->EyeVectors( &vForward );
|
||||
Vector vecSrc = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset() + vForward * 16;
|
||||
|
||||
Vector vecVel = pPlayer->GetAbsVelocity();
|
||||
|
||||
EmitGrenade( vecSrc, vec3_angle, vecVel, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer );
|
||||
|
||||
m_bRedraw = true;
|
||||
m_fThrowTime = 0.0f;
|
||||
}
|
||||
|
||||
void CBaseSDKGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer )
|
||||
{
|
||||
Assert( 0 && "CBaseSDKGrenade::EmitGrenade should not be called. Make sure to implement this in your subclass!\n" );
|
||||
}
|
||||
|
||||
bool CBaseSDKGrenade::AllowsAutoSwitchFrom( void ) const
|
||||
{
|
||||
return !m_bPinPulled;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef WEAPON_BASESDKGRENADE_H
|
||||
#define WEAPON_BASESDKGRENADE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#include "weapon_sdkbase.h"
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
#define CBaseSDKGrenade C_BaseSDKGrenade
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
class CBaseSDKGrenade : public CWeaponSDKBase
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CBaseSDKGrenade, CWeaponSDKBase );
|
||||
DECLARE_NETWORKCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
CBaseSDKGrenade();
|
||||
|
||||
virtual void Precache();
|
||||
|
||||
bool Deploy();
|
||||
bool Holster( CBaseCombatWeapon *pSwitchingTo );
|
||||
|
||||
void PrimaryAttack();
|
||||
void SecondaryAttack();
|
||||
|
||||
bool Reload();
|
||||
|
||||
virtual void ItemPostFrame();
|
||||
|
||||
void DecrementAmmo( CBaseCombatCharacter *pOwner );
|
||||
virtual void StartGrenadeThrow();
|
||||
virtual void ThrowGrenade();
|
||||
virtual void DropGrenade();
|
||||
|
||||
bool IsPinPulled() const;
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
DECLARE_DATADESC();
|
||||
|
||||
virtual bool AllowsAutoSwitchFrom( void ) const;
|
||||
|
||||
int CapabilitiesGet();
|
||||
|
||||
// Each derived grenade class implements this.
|
||||
virtual void EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
CNetworkVar( bool, m_bRedraw ); // Draw the weapon again after throwing a grenade
|
||||
CNetworkVar( bool, m_bPinPulled ); // Set to true when the pin has been pulled but the grenade hasn't been thrown yet.
|
||||
CNetworkVar( float, m_fThrowTime ); // the time at which the grenade will be thrown. If this value is 0 then the time hasn't been set yet.
|
||||
|
||||
private:
|
||||
CBaseSDKGrenade( const CBaseSDKGrenade & ) {}
|
||||
};
|
||||
|
||||
|
||||
inline bool CBaseSDKGrenade::IsPinPulled() const
|
||||
{
|
||||
return m_bPinPulled;
|
||||
}
|
||||
|
||||
|
||||
#endif // WEAPON_BASESDKGRENADE_H
|
||||
@@ -0,0 +1,78 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
#include "sdk_weapon_melee.h"
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
|
||||
#define CWeaponCrowbar C_WeaponCrowbar
|
||||
#include "c_sdk_player.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "sdk_player.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
class CWeaponCrowbar : public CWeaponSDKMelee
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CWeaponCrowbar, CWeaponSDKMelee );
|
||||
DECLARE_NETWORKCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
DECLARE_ACTTABLE();
|
||||
|
||||
CWeaponCrowbar();
|
||||
|
||||
virtual SDKWeaponID GetWeaponID( void ) const { return SDK_WEAPON_CROWBAR; }
|
||||
virtual float GetRange( void ) { return 64.0f; } //Tony; let the crowbar swing further.
|
||||
virtual bool CanWeaponBeDropped() const { return false; }
|
||||
|
||||
private:
|
||||
|
||||
CWeaponCrowbar( const CWeaponCrowbar & );
|
||||
};
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponCrowbar, DT_WeaponCrowbar )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CWeaponCrowbar, DT_WeaponCrowbar )
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( CWeaponCrowbar )
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_crowbar, CWeaponCrowbar );
|
||||
PRECACHE_WEAPON_REGISTER( weapon_crowbar );
|
||||
|
||||
|
||||
|
||||
CWeaponCrowbar::CWeaponCrowbar()
|
||||
{
|
||||
}
|
||||
|
||||
//Tony; todo; add ACT_MP_PRONE* activities, so we have them.
|
||||
acttable_t CWeaponCrowbar::m_acttable[] =
|
||||
{
|
||||
{ ACT_MP_STAND_IDLE, ACT_DOD_STAND_AIM_SPADE, false },
|
||||
{ ACT_MP_CROUCH_IDLE, ACT_DOD_CROUCH_AIM_SPADE, false },
|
||||
{ ACT_MP_PRONE_IDLE, ACT_DOD_PRONE_AIM_SPADE, false },
|
||||
|
||||
{ ACT_MP_RUN, ACT_DOD_RUN_AIM_SPADE, false },
|
||||
{ ACT_MP_WALK, ACT_DOD_WALK_AIM_SPADE, false },
|
||||
{ ACT_MP_CROUCHWALK, ACT_DOD_CROUCHWALK_AIM_SPADE, false },
|
||||
{ ACT_MP_PRONE_CRAWL, ACT_DOD_PRONEWALK_AIM_SPADE, false },
|
||||
{ ACT_SPRINT, ACT_DOD_SPRINT_AIM_SPADE, false },
|
||||
|
||||
{ ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_DOD_PRIMARYATTACK_SPADE, false },
|
||||
{ ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_DOD_PRIMARYATTACK_SPADE, false },
|
||||
{ ACT_MP_ATTACK_PRONE_PRIMARYFIRE, ACT_DOD_PRIMARYATTACK_PRONE_SPADE, false },
|
||||
};
|
||||
|
||||
IMPLEMENT_ACTTABLE( CWeaponCrowbar );
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
#include "gamerules.h"
|
||||
#include "npcevent.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "weapon_grenade.h"
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
#else
|
||||
|
||||
#include "sdk_player.h"
|
||||
#include "items.h"
|
||||
#include "sdk_basegrenade_projectile.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define GRENADE_TIMER 3.0f //Seconds
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( SDKGrenade, DT_SDKGrenade )
|
||||
|
||||
BEGIN_NETWORK_TABLE(CSDKGrenade, DT_SDKGrenade)
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( CSDKGrenade )
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_grenade, CSDKGrenade );
|
||||
PRECACHE_WEAPON_REGISTER( weapon_grenade );
|
||||
|
||||
|
||||
#ifdef GAME_DLL
|
||||
|
||||
#define GRENADE_MODEL "models/Weapons/w_eq_fraggrenade_thrown.mdl"
|
||||
|
||||
class CGrenadeProjectile : public CBaseGrenadeProjectile
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CGrenadeProjectile, CBaseGrenadeProjectile );
|
||||
|
||||
|
||||
// Overrides.
|
||||
public:
|
||||
virtual void Spawn()
|
||||
{
|
||||
SetModel( GRENADE_MODEL );
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
virtual void Precache()
|
||||
{
|
||||
PrecacheModel( GRENADE_MODEL );
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
// Grenade stuff.
|
||||
public:
|
||||
|
||||
static CGrenadeProjectile* Create(
|
||||
const Vector &position,
|
||||
const QAngle &angles,
|
||||
const Vector &velocity,
|
||||
const AngularImpulse &angVelocity,
|
||||
CBaseCombatCharacter *pOwner,
|
||||
float timer )
|
||||
{
|
||||
CGrenadeProjectile *pGrenade = (CGrenadeProjectile*)CBaseEntity::Create( "grenade_projectile", position, angles, pOwner );
|
||||
|
||||
// Set the timer for 1 second less than requested. We're going to issue a SOUND_DANGER
|
||||
// one second before detonation.
|
||||
|
||||
pGrenade->SetDetonateTimerLength( 1.5 );
|
||||
pGrenade->SetAbsVelocity( velocity );
|
||||
pGrenade->SetupInitialTransmittedGrenadeVelocity( velocity );
|
||||
pGrenade->SetThrower( pOwner );
|
||||
|
||||
pGrenade->SetGravity( BaseClass::GetGrenadeGravity() );
|
||||
pGrenade->SetFriction( BaseClass::GetGrenadeFriction() );
|
||||
pGrenade->SetElasticity( BaseClass::GetGrenadeElasticity() );
|
||||
|
||||
pGrenade->m_flDamage = 100;
|
||||
pGrenade->m_DmgRadius = pGrenade->m_flDamage * 3.5f;
|
||||
pGrenade->ChangeTeam( pOwner->GetTeamNumber() );
|
||||
pGrenade->ApplyLocalAngularVelocityImpulse( angVelocity );
|
||||
|
||||
// make NPCs afaid of it while in the air
|
||||
pGrenade->SetThink( &CGrenadeProjectile::DangerSoundThink );
|
||||
pGrenade->SetNextThink( gpGlobals->curtime );
|
||||
|
||||
return pGrenade;
|
||||
}
|
||||
};
|
||||
|
||||
LINK_ENTITY_TO_CLASS( grenade_projectile, CGrenadeProjectile );
|
||||
PRECACHE_WEAPON_REGISTER( grenade_projectile );
|
||||
|
||||
BEGIN_DATADESC( CSDKGrenade )
|
||||
END_DATADESC()
|
||||
|
||||
void CSDKGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer )
|
||||
{
|
||||
CGrenadeProjectile::Create( vecSrc, vecAngles, vecVel, angImpulse, pPlayer, GRENADE_TIMER );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef WEAPON_GRENADE_H
|
||||
#define WEAPON_GRENADE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "weapon_basesdkgrenade.h"
|
||||
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
#define CSDKGrenade C_SDKGrenade
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Fragmentation grenades
|
||||
//-----------------------------------------------------------------------------
|
||||
class CSDKGrenade : public CBaseSDKGrenade
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CSDKGrenade, CBaseSDKGrenade );
|
||||
DECLARE_NETWORKCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
CSDKGrenade() {}
|
||||
|
||||
virtual SDKWeaponID GetWeaponID( void ) const { return WEAPON_GRENADE; }
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
#else
|
||||
DECLARE_DATADESC();
|
||||
|
||||
virtual void EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer );
|
||||
|
||||
#endif
|
||||
|
||||
CSDKGrenade( const CSDKGrenade & ) {}
|
||||
};
|
||||
|
||||
|
||||
#endif // WEAPON_GRENADE_H
|
||||
@@ -0,0 +1,168 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
#include "sdk_fx_shared.h"
|
||||
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
|
||||
#define CWeaponMP5 C_WeaponMP5
|
||||
#include "c_sdk_player.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "sdk_player.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
class CWeaponMP5 : public CWeaponSDKBase
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CWeaponMP5, CWeaponSDKBase );
|
||||
DECLARE_NETWORKCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
CWeaponMP5();
|
||||
|
||||
virtual void PrimaryAttack();
|
||||
virtual bool Deploy();
|
||||
virtual bool Reload();
|
||||
virtual void WeaponIdle();
|
||||
|
||||
virtual SDKWeaponID GetWeaponID( void ) const { return WEAPON_MP5; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
CWeaponMP5( const CWeaponMP5 & );
|
||||
|
||||
void Fire( float flSpread );
|
||||
};
|
||||
|
||||
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 );
|
||||
|
||||
|
||||
|
||||
CWeaponMP5::CWeaponMP5()
|
||||
{
|
||||
}
|
||||
|
||||
bool CWeaponMP5::Deploy( )
|
||||
{
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
pPlayer->m_iShotsFired = 0;
|
||||
|
||||
return BaseClass::Deploy();
|
||||
}
|
||||
|
||||
bool CWeaponMP5::Reload( )
|
||||
{
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
|
||||
if (pPlayer->GetAmmoCount( GetPrimaryAmmoType() ) <= 0)
|
||||
return false;
|
||||
|
||||
int iResult = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD );
|
||||
if ( !iResult )
|
||||
return false;
|
||||
|
||||
pPlayer->SetAnimation( PLAYER_RELOAD );
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
if ((iResult) && (pPlayer->GetFOV() != pPlayer->GetDefaultFOV()))
|
||||
{
|
||||
pPlayer->SetFOV( pPlayer, pPlayer->GetDefaultFOV() );
|
||||
}
|
||||
#endif
|
||||
|
||||
pPlayer->m_iShotsFired = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWeaponMP5::PrimaryAttack( void )
|
||||
{
|
||||
const CSDKWeaponInfo &pWeaponInfo = GetSDKWpnData();
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
|
||||
float flCycleTime = pWeaponInfo.m_flCycleTime;
|
||||
|
||||
bool bPrimaryMode = true;
|
||||
|
||||
float flSpread = 0.01f;
|
||||
|
||||
// more spread when jumping
|
||||
if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) )
|
||||
flSpread = 0.05f;
|
||||
|
||||
pPlayer->m_iShotsFired++;
|
||||
|
||||
// Out of ammo?
|
||||
if ( m_iClip1 <= 0 )
|
||||
{
|
||||
if (m_bFireOnEmpty)
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
|
||||
|
||||
m_iClip1--;
|
||||
|
||||
// player "shoot" animation
|
||||
pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
FX_FireBullets(
|
||||
pPlayer->entindex(),
|
||||
pPlayer->Weapon_ShootPosition(),
|
||||
pPlayer->EyeAngles() + pPlayer->GetPunchAngle(),
|
||||
GetWeaponID(),
|
||||
bPrimaryMode?Primary_Mode:Secondary_Mode,
|
||||
CBaseEntity::GetPredictionRandomSeed() & 255,
|
||||
flSpread );
|
||||
|
||||
pPlayer->DoMuzzleFlash();
|
||||
|
||||
m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + flCycleTime;
|
||||
|
||||
if (!m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0)
|
||||
{
|
||||
// HEV suit - indicate out of ammo condition
|
||||
pPlayer->SetSuitUpdate("!HEV_AMO0", false, 0);
|
||||
}
|
||||
|
||||
// start idle animation in 5 seconds
|
||||
SetWeaponIdleTime( gpGlobals->curtime + 5.0 );
|
||||
}
|
||||
|
||||
void CWeaponMP5::WeaponIdle()
|
||||
{
|
||||
if (m_flTimeWeaponIdle > gpGlobals->curtime)
|
||||
return;
|
||||
|
||||
// only idle if the slid isn't back
|
||||
if ( m_iClip1 != 0 )
|
||||
{
|
||||
SetWeaponIdleTime( gpGlobals->curtime + 5.0f );
|
||||
SendWeaponAnim( ACT_VM_IDLE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=====================================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
|
||||
#define CWeaponPistol C_WeaponPistol
|
||||
#include "c_sdk_player.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "sdk_player.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
class CWeaponPistol : public CWeaponSDKBase
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CWeaponPistol, CWeaponSDKBase );
|
||||
DECLARE_NETWORKCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
DECLARE_ACTTABLE();
|
||||
|
||||
CWeaponPistol();
|
||||
|
||||
virtual SDKWeaponID GetWeaponID( void ) const { return SDK_WEAPON_PISTOL; }
|
||||
virtual int GetFireMode() const { return FM_SEMIAUTOMATIC; }
|
||||
|
||||
private:
|
||||
|
||||
CWeaponPistol( const CWeaponPistol & );
|
||||
};
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponPistol, DT_WeaponPistol )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CWeaponPistol, DT_WeaponPistol )
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( CWeaponPistol )
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_pistol, CWeaponPistol );
|
||||
PRECACHE_WEAPON_REGISTER( weapon_pistol );
|
||||
|
||||
|
||||
|
||||
CWeaponPistol::CWeaponPistol()
|
||||
{
|
||||
}
|
||||
|
||||
//Tony; todo; add ACT_MP_PRONE* activities, so we have them.
|
||||
acttable_t CWeaponPistol::m_acttable[] =
|
||||
{
|
||||
{ ACT_MP_STAND_IDLE, ACT_DOD_STAND_IDLE_PISTOL, false },
|
||||
{ ACT_MP_CROUCH_IDLE, ACT_DOD_CROUCH_IDLE_PISTOL, false },
|
||||
{ ACT_MP_PRONE_IDLE, ACT_DOD_PRONE_AIM_PISTOL, false },
|
||||
|
||||
{ ACT_MP_RUN, ACT_DOD_RUN_AIM_PISTOL, false },
|
||||
{ ACT_MP_WALK, ACT_DOD_WALK_AIM_PISTOL, false },
|
||||
{ ACT_MP_CROUCHWALK, ACT_DOD_CROUCHWALK_AIM_PISTOL, false },
|
||||
{ ACT_MP_PRONE_CRAWL, ACT_DOD_PRONEWALK_IDLE_PISTOL, false },
|
||||
{ ACT_SPRINT, ACT_DOD_SPRINT_IDLE_PISTOL, false },
|
||||
|
||||
{ ACT_MP_ATTACK_STAND_PRIMARYFIRE, ACT_DOD_PRIMARYATTACK_PISTOL, false },
|
||||
{ ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, ACT_DOD_PRIMARYATTACK_PISTOL, false },
|
||||
{ ACT_MP_ATTACK_PRONE_PRIMARYFIRE, ACT_DOD_PRIMARYATTACK_PRONE_PISTOL, false },
|
||||
|
||||
{ ACT_MP_RELOAD_STAND, ACT_DOD_RELOAD_PISTOL, false },
|
||||
{ ACT_MP_RELOAD_CROUCH, ACT_DOD_RELOAD_CROUCH_PISTOL, false },
|
||||
{ ACT_MP_RELOAD_PRONE, ACT_DOD_RELOAD_PRONE_PISTOL, false },
|
||||
};
|
||||
|
||||
IMPLEMENT_ACTTABLE( CWeaponPistol );
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "in_buttons.h"
|
||||
#include "takedamageinfo.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
#include "ammodef.h"
|
||||
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
|
||||
#include "c_sdk_player.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "sdk_player.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// Global functions.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
static const char * s_WeaponAliasInfo[] =
|
||||
{
|
||||
"none", // WEAPON_NONE
|
||||
"mp5", // WEAPON_MP5
|
||||
"shotgun", // WEAPON_SHOTGUN
|
||||
"grenade", // WEAPON_GRENADE
|
||||
NULL, // WEAPON_NONE
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Given an alias, return the associated weapon ID
|
||||
//
|
||||
int AliasToWeaponID( const char *alias )
|
||||
{
|
||||
if (alias)
|
||||
{
|
||||
for( int i=0; s_WeaponAliasInfo[i] != NULL; ++i )
|
||||
if (!Q_stricmp( s_WeaponAliasInfo[i], alias ))
|
||||
return i;
|
||||
}
|
||||
|
||||
return WEAPON_NONE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Given a weapon ID, return its alias
|
||||
//
|
||||
const char *WeaponIDToAlias( int id )
|
||||
{
|
||||
if ( (id >= WEAPON_MAX) || (id < 0) )
|
||||
return NULL;
|
||||
|
||||
return s_WeaponAliasInfo[id];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// CWeaponSDKBase tables.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponSDKBase, DT_WeaponSDKBase )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CWeaponSDKBase, DT_WeaponSDKBase )
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
#else
|
||||
// world weapon models have no animations
|
||||
SendPropExclude( "DT_AnimTimeMustBeFirst", "m_flAnimTime" ),
|
||||
SendPropExclude( "DT_BaseAnimating", "m_nSequence" ),
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
BEGIN_PREDICTION_DATA( CWeaponSDKBase )
|
||||
DEFINE_PRED_FIELD( m_flTimeWeaponIdle, FIELD_FLOAT, FTYPEDESC_OVERRIDE | FTYPEDESC_NOERRORCHECK ),
|
||||
END_PREDICTION_DATA()
|
||||
#endif
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_sdk_base, CWeaponSDKBase );
|
||||
|
||||
|
||||
#ifdef GAME_DLL
|
||||
|
||||
BEGIN_DATADESC( CWeaponSDKBase )
|
||||
|
||||
// New weapon Think and Touch Functions go here..
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// CWeaponCSBase implementation.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
CWeaponSDKBase::CWeaponSDKBase()
|
||||
{
|
||||
SetPredictionEligible( true );
|
||||
|
||||
AddSolidFlags( FSOLID_TRIGGER ); // Nothing collides with these but it gets touches.
|
||||
}
|
||||
|
||||
const CSDKWeaponInfo &CWeaponSDKBase::GetSDKWpnData() const
|
||||
{
|
||||
const FileWeaponInfo_t *pWeaponInfo = &GetWpnData();
|
||||
const CSDKWeaponInfo *pSDKInfo;
|
||||
|
||||
#ifdef _DEBUG
|
||||
pSDKInfo = dynamic_cast< const CSDKWeaponInfo* >( pWeaponInfo );
|
||||
Assert( pSDKInfo );
|
||||
#else
|
||||
pSDKInfo = static_cast< const CSDKWeaponInfo* >( pWeaponInfo );
|
||||
#endif
|
||||
|
||||
return *pSDKInfo;
|
||||
}
|
||||
|
||||
bool CWeaponSDKBase::PlayEmptySound()
|
||||
{
|
||||
CPASAttenuationFilter filter( this );
|
||||
filter.UsePredictionRules();
|
||||
|
||||
EmitSound( filter, entindex(), "Default.ClipEmpty_Rifle" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CSDKPlayer* CWeaponSDKBase::GetPlayerOwner() const
|
||||
{
|
||||
return dynamic_cast< CSDKPlayer* >( GetOwner() );
|
||||
}
|
||||
|
||||
#ifdef GAME_DLL
|
||||
|
||||
void CWeaponSDKBase::SendReloadEvents()
|
||||
{
|
||||
CSDKPlayer *pPlayer = dynamic_cast< CSDKPlayer* >( GetOwner() );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
// Send a message to any clients that have this entity to play the reload.
|
||||
CPASFilter filter( pPlayer->GetAbsOrigin() );
|
||||
filter.RemoveRecipient( pPlayer );
|
||||
|
||||
UserMessageBegin( filter, "ReloadEffect" );
|
||||
WRITE_SHORT( pPlayer->entindex() );
|
||||
MessageEnd();
|
||||
|
||||
// Make the player play his reload animation.
|
||||
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_RELOAD );
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef WEAPON_SDKBASE_H
|
||||
#define WEAPON_SDKBASE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "sdk_playeranimstate.h"
|
||||
#include "sdk_weapon_parse.h"
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
#define CWeaponSDKBase C_WeaponSDKBase
|
||||
#endif
|
||||
|
||||
class CSDKPlayer;
|
||||
|
||||
// These are the names of the ammo types that the weapon script files reference.
|
||||
#define AMMO_BULLETS "AMMO_BULLETS"
|
||||
#define AMMO_ROCKETS "AMMO_ROCKETS"
|
||||
#define AMMO_GRENADE "AMMO_GRENADE"
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Weapon IDs for all SDK Game weapons
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
WEAPON_NONE = 0,
|
||||
|
||||
WEAPON_MP5,
|
||||
WEAPON_SHOTGUN,
|
||||
WEAPON_GRENADE,
|
||||
|
||||
WEAPON_MAX, // number of weapons weapon index
|
||||
} SDKWeaponID;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
Primary_Mode = 0,
|
||||
Secondary_Mode,
|
||||
} SDKWeaponMode;
|
||||
|
||||
const char *WeaponIDToAlias( int id );
|
||||
|
||||
class CWeaponSDKBase : public CBaseCombatWeapon
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CWeaponSDKBase, CBaseCombatWeapon );
|
||||
DECLARE_NETWORKCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
CWeaponSDKBase();
|
||||
|
||||
#ifdef GAME_DLL
|
||||
DECLARE_DATADESC();
|
||||
#endif
|
||||
|
||||
// All predicted weapons need to implement and return true
|
||||
virtual bool IsPredicted() const { return true; }
|
||||
virtual SDKWeaponID GetWeaponID( void ) const { return WEAPON_NONE; }
|
||||
|
||||
// Get SDK weapon specific weapon data.
|
||||
CSDKWeaponInfo const &GetSDKWpnData() const;
|
||||
|
||||
// Get a pointer to the player that owns this weapon
|
||||
CSDKPlayer* GetPlayerOwner() const;
|
||||
|
||||
// override to play custom empty sounds
|
||||
virtual bool PlayEmptySound();
|
||||
|
||||
#ifdef GAME_DLL
|
||||
virtual void SendReloadEvents();
|
||||
#endif
|
||||
|
||||
private:
|
||||
CWeaponSDKBase( const CWeaponSDKBase & );
|
||||
};
|
||||
|
||||
|
||||
#endif // WEAPON_SDKBASE_H
|
||||
@@ -0,0 +1,246 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "weapon_sdkbase.h"
|
||||
#include "sdk_fx_shared.h"
|
||||
|
||||
|
||||
#if defined( CLIENT_DLL )
|
||||
|
||||
#define CWeaponShotgun C_WeaponShotgun
|
||||
#include "c_sdk_player.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "sdk_player.h"
|
||||
#include "te_firebullets.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
class CWeaponShotgun : public CWeaponSDKBase
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CWeaponShotgun, CWeaponSDKBase );
|
||||
DECLARE_NETWORKCLASS();
|
||||
DECLARE_PREDICTABLE();
|
||||
|
||||
CWeaponShotgun();
|
||||
|
||||
virtual void PrimaryAttack();
|
||||
virtual bool Reload();
|
||||
virtual void WeaponIdle();
|
||||
|
||||
virtual SDKWeaponID GetWeaponID( void ) const { return WEAPON_SHOTGUN; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
CWeaponShotgun( const CWeaponShotgun & );
|
||||
|
||||
float m_flPumpTime;
|
||||
CNetworkVar( int, m_fInSpecialReload );
|
||||
|
||||
};
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponShotgun, DT_WeaponShotgun )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CWeaponShotgun, DT_WeaponShotgun )
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
RecvPropInt( RECVINFO( m_fInSpecialReload ) )
|
||||
#else
|
||||
SendPropInt( SENDINFO( m_fInSpecialReload ), 2, SPROP_UNSIGNED )
|
||||
#endif
|
||||
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( CWeaponShotgun )
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( weapon_shotgun, CWeaponShotgun );
|
||||
PRECACHE_WEAPON_REGISTER( weapon_shotgun );
|
||||
|
||||
|
||||
|
||||
CWeaponShotgun::CWeaponShotgun()
|
||||
{
|
||||
m_flPumpTime = 0;
|
||||
}
|
||||
|
||||
void CWeaponShotgun::PrimaryAttack()
|
||||
{
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
// don't fire underwater
|
||||
if (pPlayer->GetWaterLevel() == 3)
|
||||
{
|
||||
PlayEmptySound( );
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + 0.15;
|
||||
return;
|
||||
}
|
||||
|
||||
// Out of ammo?
|
||||
if ( m_iClip1 <= 0 )
|
||||
{
|
||||
Reload();
|
||||
if ( m_iClip1 == 0 )
|
||||
{
|
||||
PlayEmptySound();
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
|
||||
|
||||
m_iClip1--;
|
||||
pPlayer->DoMuzzleFlash();
|
||||
|
||||
// player "shoot" animation
|
||||
pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
|
||||
// Dispatch the FX right away with full accuracy.
|
||||
FX_FireBullets(
|
||||
pPlayer->entindex(),
|
||||
pPlayer->Weapon_ShootPosition(),
|
||||
pPlayer->EyeAngles() + 2.0f * pPlayer->GetPunchAngle(),
|
||||
GetWeaponID(),
|
||||
Primary_Mode,
|
||||
CBaseEntity::GetPredictionRandomSeed() & 255, // wrap it for network traffic so it's the same between client and server
|
||||
0.0675 );
|
||||
|
||||
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_flNextPrimaryAttack = gpGlobals->curtime + 0.875;
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + 0.875;
|
||||
if (m_iClip1 != 0)
|
||||
SetWeaponIdleTime( gpGlobals->curtime + 2.5 );
|
||||
else
|
||||
SetWeaponIdleTime( gpGlobals->curtime + 0.875 );
|
||||
m_fInSpecialReload = 0;
|
||||
|
||||
// Update punch angles.
|
||||
QAngle angle = pPlayer->GetPunchAngle();
|
||||
|
||||
if ( pPlayer->GetFlags() & FL_ONGROUND )
|
||||
{
|
||||
angle.x -= SharedRandomInt( "ShotgunPunchAngleGround", 4, 6 );
|
||||
}
|
||||
else
|
||||
{
|
||||
angle.x -= SharedRandomInt( "ShotgunPunchAngleAir", 8, 11 );
|
||||
}
|
||||
|
||||
pPlayer->SetPunchAngle( angle );
|
||||
}
|
||||
|
||||
|
||||
bool CWeaponShotgun::Reload()
|
||||
{
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
|
||||
if (pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 || m_iClip1 == GetMaxClip1())
|
||||
return true;
|
||||
|
||||
// don't reload until recoil is done
|
||||
if (m_flNextPrimaryAttack > gpGlobals->curtime)
|
||||
return true;
|
||||
|
||||
// check to see if we're ready to reload
|
||||
if (m_fInSpecialReload == 0)
|
||||
{
|
||||
pPlayer->SetAnimation( PLAYER_RELOAD );
|
||||
|
||||
SendWeaponAnim( ACT_SHOTGUN_RELOAD_START );
|
||||
m_fInSpecialReload = 1;
|
||||
pPlayer->m_flNextAttack = gpGlobals->curtime + 0.5;
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
|
||||
m_flNextSecondaryAttack = gpGlobals->curtime + 0.5;
|
||||
SetWeaponIdleTime( gpGlobals->curtime + 0.5 );
|
||||
return true;
|
||||
}
|
||||
else if (m_fInSpecialReload == 1)
|
||||
{
|
||||
if (m_flTimeWeaponIdle > gpGlobals->curtime)
|
||||
return true;
|
||||
// was waiting for gun to move to side
|
||||
m_fInSpecialReload = 2;
|
||||
|
||||
SendWeaponAnim( ACT_VM_RELOAD );
|
||||
SetWeaponIdleTime( gpGlobals->curtime + 0.45 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add them to the clip
|
||||
m_iClip1 += 1;
|
||||
|
||||
#ifdef GAME_DLL
|
||||
SendReloadEvents();
|
||||
#endif
|
||||
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
|
||||
if ( pPlayer )
|
||||
pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType );
|
||||
|
||||
m_fInSpecialReload = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CWeaponShotgun::WeaponIdle()
|
||||
{
|
||||
CSDKPlayer *pPlayer = GetPlayerOwner();
|
||||
|
||||
if (m_flPumpTime && m_flPumpTime < gpGlobals->curtime)
|
||||
{
|
||||
// play pumping sound
|
||||
m_flPumpTime = 0;
|
||||
}
|
||||
|
||||
if (m_flTimeWeaponIdle < gpGlobals->curtime)
|
||||
{
|
||||
if (m_iClip1 == 0 && m_fInSpecialReload == 0 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ))
|
||||
{
|
||||
Reload( );
|
||||
}
|
||||
else if (m_fInSpecialReload != 0)
|
||||
{
|
||||
if (m_iClip1 != 8 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ))
|
||||
{
|
||||
Reload( );
|
||||
}
|
||||
else
|
||||
{
|
||||
// reload debounce has timed out
|
||||
//MIKETODO: shotgun anims
|
||||
SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH );
|
||||
|
||||
// play cocking sound
|
||||
m_fInSpecialReload = 0;
|
||||
SetWeaponIdleTime( gpGlobals->curtime + 1.5 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SendWeaponAnim( ACT_VM_IDLE );
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user