This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions
@@ -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
+224
View File
@@ -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();
}
+27
View File
@@ -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
+53
View File
@@ -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;
}
+369
View File
@@ -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;
}
+88
View File
@@ -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
+160
View File
@@ -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
}
+136
View File
@@ -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
+621
View File
@@ -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
}
+76
View File
@@ -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
+116
View File
@@ -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];
}
+208
View File
@@ -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
+49
View File
@@ -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 );
}
+363
View File
@@ -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();
}
+60
View File
@@ -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
+35
View File
@@ -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 ) );
}
+37
View File
@@ -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
+363
View File
@@ -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 isnt 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
+79
View File
@@ -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
+78
View File
@@ -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 );
+114
View File
@@ -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
+49
View File
@@ -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
+168
View File
@@ -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 );
}
}
+80
View File
@@ -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 );
+163
View File
@@ -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
+85
View File
@@ -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
+246
View File
@@ -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 );
}
}
}