You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1396 lines
32 KiB
1396 lines
32 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "dod_gamerules.h" |
|
#include "takedamageinfo.h" |
|
#include "dod_shareddefs.h" |
|
#include "effect_dispatch_data.h" |
|
|
|
#include "weapon_dodbase.h" |
|
#include "weapon_dodbipodgun.h" |
|
#include "weapon_dodbaserpg.h" |
|
#include "weapon_dodsniper.h" |
|
|
|
#include "movevars_shared.h" |
|
#include "engine/IEngineSound.h" |
|
#include "SoundEmitterSystem/isoundemittersystembase.h" |
|
#include "engine/ivdebugoverlay.h" |
|
#include "obstacle_pushaway.h" |
|
#include "props_shared.h" |
|
|
|
#include "decals.h" |
|
#include "util_shared.h" |
|
|
|
#ifdef CLIENT_DLL |
|
|
|
#include "c_dod_player.h" |
|
#include "prediction.h" |
|
#include "clientmode_dod.h" |
|
#include "vgui_controls/AnimationController.h" |
|
|
|
#define CRecipientFilter C_RecipientFilter |
|
|
|
#else |
|
|
|
#include "dod_player.h" |
|
|
|
#endif |
|
|
|
ConVar dod_bonusround( "dod_bonusround", "1", FCVAR_REPLICATED, "If true, the winners of the round can attack in the intermission." ); |
|
ConVar sv_showimpacts("sv_showimpacts", "0", FCVAR_REPLICATED | FCVAR_CHEAT, "Shows client (red) and server (blue) bullet impact point" ); |
|
|
|
void DispatchEffect( const char *pName, const CEffectData &data ); |
|
|
|
bool CDODPlayer::CanMove( void ) const |
|
{ |
|
bool bValidMoveState = (State_Get() == STATE_ACTIVE || State_Get() == STATE_OBSERVER_MODE); |
|
|
|
if ( !bValidMoveState ) |
|
{ |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
// BUG! This is not called on the client at respawn, only first spawn! |
|
void CDODPlayer::SharedSpawn() |
|
{ |
|
BaseClass::SharedSpawn(); |
|
|
|
// Reset the animation state or we will animate to standing |
|
// when we spawn |
|
|
|
m_Shared.SetJumping( false ); |
|
|
|
m_flMinNextStepSoundTime = gpGlobals->curtime; |
|
|
|
m_bPlayingProneMoveSound = false; |
|
} |
|
|
|
float GetDensityFromMaterial( surfacedata_t *pSurfaceData ) |
|
{ |
|
float flMaterialMod = 1.0f; |
|
|
|
Assert( pSurfaceData ); |
|
|
|
// material mod is how many points of damage it costs to go through |
|
// 1 unit of the material |
|
|
|
switch( pSurfaceData->game.material ) |
|
{ |
|
//super soft |
|
// case CHAR_TEX_LEAVES: |
|
// flMaterialMod = 1.2f; |
|
// break; |
|
|
|
case CHAR_TEX_FLESH: |
|
flMaterialMod = 1.35f; |
|
break; |
|
|
|
//soft |
|
// case CHAR_TEX_STUCCO: |
|
// case CHAR_TEX_SNOW: |
|
case CHAR_TEX_GLASS: |
|
case CHAR_TEX_WOOD: |
|
case CHAR_TEX_TILE: |
|
flMaterialMod = 1.8f; |
|
break; |
|
|
|
//hard |
|
// case CHAR_TEX_SKY: |
|
// case CHAR_TEX_ROCK: |
|
// case CHAR_TEX_SAND: |
|
case CHAR_TEX_CONCRETE: |
|
case CHAR_TEX_DIRT: // "sand" |
|
flMaterialMod = 6.6f; |
|
break; |
|
|
|
//really hard |
|
// case CHAR_TEX_HEAVYMETAL: |
|
case CHAR_TEX_GRATE: |
|
case CHAR_TEX_METAL: |
|
flMaterialMod = 13.5f; |
|
break; |
|
|
|
case 'X': // invisible collision material |
|
flMaterialMod = 0.1f; |
|
break; |
|
|
|
//medium |
|
// case CHAR_TEX_BRICK: |
|
// case CHAR_TEX_GRAVEL: |
|
// case CHAR_TEX_GRASS: |
|
default: |
|
|
|
#ifndef CLIENT_DLL |
|
AssertMsg( 0, UTIL_VarArgs( "Material has unknown materialmod - '%c' \n", pSurfaceData->game.material ) ); |
|
#endif |
|
|
|
flMaterialMod = 5.0f; |
|
break; |
|
} |
|
|
|
Assert( flMaterialMod > 0 ); |
|
|
|
return flMaterialMod; |
|
} |
|
|
|
static bool TraceToExit( const Vector &start, |
|
const Vector &dir, |
|
Vector &end, |
|
const float flStepSize, |
|
const float flMaxDistance ) |
|
{ |
|
float flDistance = 0; |
|
Vector last = start; |
|
|
|
while ( flDistance < flMaxDistance ) |
|
{ |
|
flDistance += flStepSize; |
|
|
|
// no point in tracing past the max distance. |
|
// if this check fails, we save ourselves a traceline later |
|
if ( flDistance > flMaxDistance ) |
|
{ |
|
flDistance = flMaxDistance; |
|
} |
|
|
|
end = start + flDistance * dir; |
|
|
|
// point contents fails to return proper contents inside a func_detail brush, eg the dod_flash |
|
// stairs |
|
|
|
//int contents = UTIL_PointContents( end ); |
|
|
|
trace_t tr; |
|
UTIL_TraceLine( end, end, MASK_SOLID | CONTENTS_HITBOX, NULL, &tr ); |
|
|
|
//if ( (UTIL_PointContents ( end ) & MASK_SOLID) == 0 ) |
|
|
|
if ( !tr.startsolid ) |
|
{ |
|
// found first free point |
|
return true; |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
#include "ammodef.h" |
|
|
|
#define NEW_HITBOX_GROUP_CODE 1 |
|
#undef ARM_PENETRATION |
|
|
|
#ifndef CLIENT_DLL |
|
#include "ndebugoverlay.h" |
|
#endif |
|
void CDODPlayer::FireBullets( const FireBulletsInfo_t &info ) |
|
{ |
|
trace_t tr; |
|
trace_t reverseTr; //Used to find exit points |
|
static int iMaxPenetrations = 6; |
|
int iPenetrations = 0; |
|
float flDamage = info.m_flDamage; //Remaining damage in the bullet |
|
Vector vecSrc = info.m_vecSrc; |
|
Vector vecEnd = vecSrc + info.m_vecDirShooting * info.m_flDistance; |
|
|
|
static int iTraceMask = ( ( MASK_SOLID | CONTENTS_DEBRIS | CONTENTS_HITBOX | CONTENTS_PRONE_HELPER ) & ~CONTENTS_GRATE ); |
|
|
|
CBaseEntity *pLastHitEntity = this; // start with us so we don't trace ourselves |
|
|
|
int iDamageType = GetAmmoDef()->DamageType( info.m_iAmmoType ); |
|
int iCollisionGroup = COLLISION_GROUP_NONE; |
|
|
|
#ifdef GAME_DLL |
|
int iNumHeadshots = 0; |
|
#endif |
|
|
|
while ( flDamage > 0 && iPenetrations < iMaxPenetrations ) |
|
{ |
|
//DevMsg( 2, "penetration: %d, starting dmg: %.1f\n", iPenetrations, flDamage ); |
|
|
|
CBaseEntity *pPreviousHit = pLastHitEntity; |
|
|
|
// skip the shooter always |
|
CTraceFilterSkipTwoEntities ignoreShooterAndPrevious( this, pPreviousHit, iCollisionGroup ); |
|
UTIL_TraceLine( vecSrc, vecEnd, iTraceMask, &ignoreShooterAndPrevious, &tr ); |
|
|
|
const float rayExtension = 40.0f; |
|
UTIL_ClipTraceToPlayers( vecSrc, vecEnd + info.m_vecDirShooting * rayExtension, iTraceMask, &ignoreShooterAndPrevious, &tr ); |
|
|
|
if ( tr.fraction == 1.0f ) |
|
break; // we didn't hit anything, stop tracing shoot |
|
|
|
// New hitbox code that uses hitbox groups instead of trying to trace |
|
// through the player |
|
if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) |
|
{ |
|
switch( tr.hitgroup ) |
|
{ |
|
#ifdef GAME_DLL |
|
case HITGROUP_HEAD: |
|
{ |
|
if ( tr.m_pEnt->GetTeamNumber() != GetTeamNumber() ) |
|
{ |
|
iNumHeadshots++; |
|
} |
|
} |
|
break; |
|
#endif |
|
|
|
case HITGROUP_LEFTARM: |
|
case HITGROUP_RIGHTARM: |
|
{ |
|
//DevMsg( 2, "Hit arms, tracing against alt hitboxes.. \n" ); |
|
|
|
CDODPlayer *pPlayer = ToDODPlayer( tr.m_pEnt ); |
|
|
|
// set hitbox set to "dod_no_arms" |
|
pPlayer->SetHitboxSet( 1 ); |
|
|
|
trace_t newTr; |
|
|
|
// re-fire the trace |
|
UTIL_TraceLine( vecSrc, vecEnd, iTraceMask, &ignoreShooterAndPrevious, &newTr ); |
|
|
|
// if we hit the same player in the chest |
|
if ( tr.m_pEnt == newTr.m_pEnt ) |
|
{ |
|
//DevMsg( 2, ".. and we hit the chest.\n" ); |
|
|
|
Assert( tr.hitgroup != newTr.hitgroup ); // If we hit this, hitbox sets are broken |
|
|
|
// use that damage instead |
|
tr = newTr; |
|
} |
|
|
|
// set hitboxes back to "dod" |
|
pPlayer->SetHitboxSet( 0 ); |
|
} |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
} |
|
|
|
pLastHitEntity = tr.m_pEnt; |
|
|
|
if ( sv_showimpacts.GetBool() ) |
|
{ |
|
#ifdef CLIENT_DLL |
|
// draw red client impact markers |
|
debugoverlay->AddBoxOverlay( tr.endpos, Vector(-1,-1,-1), Vector(1,1,1), 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(-1,-1,-1), Vector(1,1,1), 0,0,255,127, 4 ); |
|
|
|
if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) |
|
{ |
|
CBasePlayer *player = ToBasePlayer( tr.m_pEnt ); |
|
player->DrawServerHitboxes( 4, true ); |
|
} |
|
#endif |
|
} |
|
|
|
#ifdef CLIENT_DLL |
|
// 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, iCollisionGroup, &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->GetTeamNumber() == GetTeamNumber() ) ) |
|
{ |
|
UTIL_ImpactTrace( &tr, iDamageType ); |
|
} |
|
} |
|
} |
|
#endif |
|
|
|
// Get surface where the bullet entered ( if it had different surfaces on enter and exit ) |
|
surfacedata_t *pSurfaceData = physprops->GetSurfaceData( tr.surface.surfaceProps ); |
|
Assert( pSurfaceData ); |
|
|
|
float flMaterialMod = GetDensityFromMaterial(pSurfaceData); |
|
|
|
if ( iDamageType & DMG_MACHINEGUN ) |
|
{ |
|
flMaterialMod *= 0.65; |
|
} |
|
|
|
// try to penetrate object |
|
Vector penetrationEnd; |
|
float flMaxDistance = flDamage / flMaterialMod; |
|
|
|
#ifndef CLIENT_DLL |
|
ClearMultiDamage(); |
|
|
|
float flActualDamage = flDamage; |
|
|
|
CTakeDamageInfo dmgInfo( info.m_pAttacker, info.m_pAttacker, flActualDamage, iDamageType ); |
|
CalculateBulletDamageForce( &dmgInfo, info.m_iAmmoType, info.m_vecDirShooting, tr.endpos ); |
|
tr.m_pEnt->DispatchTraceAttack( dmgInfo, info.m_vecDirShooting, &tr ); |
|
|
|
DevMsg( 2, "Giving damage ( %.1f ) to entity of type %s\n", flActualDamage, tr.m_pEnt->GetClassname() ); |
|
|
|
TraceAttackToTriggers( dmgInfo, tr.startpos, tr.endpos, info.m_vecDirShooting ); |
|
#endif |
|
|
|
int stepsize = 16; |
|
|
|
// displacement always stops the bullet |
|
if ( tr.IsDispSurface() ) |
|
{ |
|
DevMsg( 2, "bullet was stopped by displacement\n" ); |
|
ApplyMultiDamage(); |
|
break; |
|
} |
|
|
|
// trace through the solid to find the exit point and how much material we went through |
|
if ( !TraceToExit( tr.endpos, info.m_vecDirShooting, penetrationEnd, stepsize, flMaxDistance ) ) |
|
{ |
|
DevMsg( 2, "bullet was stopped\n" ); |
|
ApplyMultiDamage(); |
|
break; |
|
} |
|
|
|
// find exact penetration exit |
|
CTraceFilterSimple ignoreShooter( this, iCollisionGroup ); |
|
UTIL_TraceLine( penetrationEnd, tr.endpos, iTraceMask, &ignoreShooter, &reverseTr ); |
|
|
|
// Now we can apply the damage, after we have traced the entity |
|
// so it doesn't break or die before we have a change to test against it |
|
#ifndef CLIENT_DLL |
|
ApplyMultiDamage(); |
|
#endif |
|
|
|
// Continue looking for the exit point |
|
if( reverseTr.m_pEnt != tr.m_pEnt && reverseTr.m_pEnt != NULL ) |
|
{ |
|
// something was blocking, trace again |
|
CTraceFilterSkipTwoEntities ignoreShooterAndBlocker( this, reverseTr.m_pEnt, iCollisionGroup ); |
|
UTIL_TraceLine( penetrationEnd, tr.endpos, iTraceMask, &ignoreShooterAndBlocker, &reverseTr ); |
|
} |
|
|
|
if ( sv_showimpacts.GetBool() ) |
|
{ |
|
debugoverlay->AddLineOverlay( penetrationEnd, reverseTr.endpos, 255, 0, 0, true, 3.0 ); |
|
} |
|
|
|
// penetration was successful |
|
|
|
#ifdef CLIENT_DLL |
|
// bullet did penetrate object, exit Decal |
|
if ( !( reverseTr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) ) |
|
{ |
|
CBaseEntity *pEntity = reverseTr.m_pEnt; |
|
if ( !( !friendlyfire.GetBool() && pEntity && pEntity->GetTeamNumber() == GetTeamNumber() ) ) |
|
{ |
|
UTIL_ImpactTrace( &reverseTr, iDamageType ); |
|
} |
|
} |
|
#endif |
|
|
|
//setup new start end parameters for successive trace |
|
|
|
// New start point is our last exit point |
|
vecSrc = reverseTr.endpos + /* 1.0 * */ info.m_vecDirShooting; |
|
|
|
// Reduce bullet damage by material and distanced travelled through that material |
|
// if it is < 0 we won't go through the loop again |
|
float flTraceDistance = VectorLength( reverseTr.endpos - tr.endpos ); |
|
|
|
flDamage -= flMaterialMod * flTraceDistance; |
|
|
|
if( flDamage > 0 ) |
|
{ |
|
DevMsg( 2, "Completed penetration, new damage is %.1f\n", flDamage ); |
|
} |
|
else |
|
{ |
|
DevMsg( 2, "bullet was stopped\n" ); |
|
} |
|
|
|
iPenetrations++; |
|
} |
|
|
|
#ifdef GAME_DLL |
|
HandleHeadshotAchievement( iNumHeadshots ); |
|
#endif |
|
} |
|
|
|
void CDODPlayer::SetSprinting( bool bIsSprinting ) |
|
{ |
|
m_Shared.SetSprinting( bIsSprinting ); |
|
} |
|
|
|
bool CDODPlayer::IsSprinting( void ) |
|
{ |
|
float flVelSqr = GetAbsVelocity().LengthSqr(); |
|
|
|
return m_Shared.m_bIsSprinting && ( flVelSqr > 0.5f ); |
|
} |
|
|
|
bool CDODPlayer::CanAttack( void ) |
|
{ |
|
if ( IsSprinting() ) |
|
return false; |
|
|
|
if ( GetMoveType() == MOVETYPE_LADDER ) |
|
return false; |
|
|
|
if ( m_Shared.IsJumping() ) |
|
return false; |
|
|
|
if ( m_Shared.IsDefusing() ) |
|
return false; |
|
|
|
// cannot attack while prone moving. except if you have a bazooka |
|
if ( m_Shared.IsProne() && GetAbsVelocity().LengthSqr() > 1 ) |
|
{ |
|
return false; |
|
} |
|
|
|
if( m_Shared.IsGoingProne() || m_Shared.IsGettingUpFromProne() ) |
|
{ |
|
return false; |
|
} |
|
|
|
CDODGameRules *rules = DODGameRules(); |
|
|
|
Assert( rules ); |
|
|
|
DODRoundState state = rules->State_Get(); |
|
|
|
if ( dod_bonusround.GetBool() ) |
|
{ |
|
if ( GetTeamNumber() == TEAM_ALLIES ) |
|
{ |
|
return ( state == STATE_RND_RUNNING || state == STATE_ALLIES_WIN ); |
|
} |
|
else |
|
{ |
|
return ( state == STATE_RND_RUNNING || state == STATE_AXIS_WIN ); |
|
} |
|
} |
|
else |
|
return ( state == STATE_RND_RUNNING ); |
|
} |
|
|
|
|
|
void CDODPlayer::SetAnimation( PLAYER_ANIM playerAnim ) |
|
{ |
|
// In DoD, its CPlayerAnimState object manages ALL the animation state. |
|
return; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : |
|
// Output : const Vector |
|
//----------------------------------------------------------------------------- |
|
const Vector CDODPlayer::GetPlayerMins( void ) const |
|
{ |
|
if ( IsObserver() ) |
|
{ |
|
return VEC_OBS_HULL_MIN; |
|
} |
|
else |
|
{ |
|
if ( GetFlags() & FL_DUCKING ) |
|
{ |
|
return VEC_DUCK_HULL_MIN; |
|
} |
|
else if ( m_Shared.IsProne() ) |
|
{ |
|
return VEC_PRONE_HULL_MIN; |
|
} |
|
else |
|
{ |
|
return VEC_HULL_MIN; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : |
|
// Output : const Vector |
|
//----------------------------------------------------------------------------- |
|
const Vector CDODPlayer::GetPlayerMaxs( void ) const |
|
{ |
|
if ( IsObserver() ) |
|
{ |
|
return VEC_OBS_HULL_MAX_SCALED( this ); |
|
} |
|
else |
|
{ |
|
if ( GetFlags() & FL_DUCKING ) |
|
{ |
|
return VEC_DUCK_HULL_MAX_SCALED( this ); |
|
} |
|
else if ( m_Shared.IsProne() ) |
|
{ |
|
return VEC_PRONE_HULL_MAX_SCALED( this ); |
|
} |
|
else |
|
{ |
|
return VEC_HULL_MAX_SCALED( this ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : collisionGroup - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CDODPlayer::ShouldCollide( int collisionGroup, int contentsMask ) const |
|
{ |
|
if ( collisionGroup == COLLISION_GROUP_PLAYER_MOVEMENT || collisionGroup == COLLISION_GROUP_PROJECTILE ) |
|
{ |
|
switch( GetTeamNumber() ) |
|
{ |
|
case TEAM_ALLIES: |
|
if ( !( contentsMask & CONTENTS_TEAM2 ) ) |
|
return false; |
|
break; |
|
|
|
case TEAM_AXIS: |
|
if ( !( contentsMask & CONTENTS_TEAM1 ) ) |
|
return false; |
|
break; |
|
} |
|
} |
|
|
|
return BaseClass::ShouldCollide( collisionGroup, contentsMask ); |
|
} |
|
|
|
// --------------------------------------------------------------------------------------------------- // |
|
// CDODPlayerShared implementation. |
|
// --------------------------------------------------------------------------------------------------- // |
|
|
|
CDODPlayerShared::CDODPlayerShared() |
|
{ |
|
m_bProne = false; |
|
m_bForceProneChange = false; |
|
m_flNextProneCheck = 0; |
|
|
|
m_flSlowedUntilTime = 0; |
|
|
|
m_flUnProneTime = 0; |
|
m_flGoProneTime = 0; |
|
|
|
m_flDeployedHeight = STANDING_DEPLOY_HEIGHT; |
|
m_flDeployChangeTime = gpGlobals->curtime; |
|
|
|
SetDesiredPlayerClass( PLAYERCLASS_UNDEFINED ); |
|
|
|
m_flLastViewAnimationTime = gpGlobals->curtime; |
|
|
|
m_pViewOffsetAnim = NULL; |
|
} |
|
|
|
CDODPlayerShared::~CDODPlayerShared() |
|
{ |
|
if ( m_pViewOffsetAnim ) |
|
{ |
|
delete m_pViewOffsetAnim; |
|
m_pViewOffsetAnim = NULL; |
|
} |
|
} |
|
|
|
void CDODPlayerShared::Init( CDODPlayer *pPlayer ) |
|
{ |
|
m_pOuter = pPlayer; |
|
} |
|
|
|
bool CDODPlayerShared::IsDucking( void ) const |
|
{ |
|
return !!( m_pOuter->GetFlags() & FL_DUCKING ); |
|
} |
|
|
|
bool CDODPlayerShared::IsProne() const |
|
{ |
|
return m_bProne; |
|
} |
|
|
|
bool CDODPlayerShared::IsGettingUpFromProne() const |
|
{ |
|
return ( m_flUnProneTime > 0 ); |
|
} |
|
|
|
bool CDODPlayerShared::IsGoingProne() const |
|
{ |
|
return ( m_flGoProneTime > 0 ); |
|
} |
|
|
|
void CDODPlayerShared::SetSprinting( bool bSprinting ) |
|
{ |
|
if ( bSprinting && !m_bIsSprinting ) |
|
{ |
|
StartSprinting(); |
|
|
|
// only one penalty per key press |
|
if ( m_bGaveSprintPenalty == false ) |
|
{ |
|
m_flStamina -= INITIAL_SPRINT_STAMINA_PENALTY; |
|
m_bGaveSprintPenalty = true; |
|
} |
|
} |
|
else if ( !bSprinting && m_bIsSprinting ) |
|
{ |
|
StopSprinting(); |
|
} |
|
} |
|
|
|
// this is reset when we let go of the sprint key |
|
void CDODPlayerShared::ResetSprintPenalty( void ) |
|
{ |
|
m_bGaveSprintPenalty = false; |
|
} |
|
|
|
void CDODPlayerShared::StartSprinting( void ) |
|
{ |
|
m_bIsSprinting = true; |
|
|
|
#ifndef CLIENT_DLL |
|
m_pOuter->RemoveHintTimer( HINT_USE_SPRINT ); |
|
#endif |
|
} |
|
|
|
void CDODPlayerShared::StopSprinting( void ) |
|
{ |
|
m_bIsSprinting = false; |
|
} |
|
|
|
void CDODPlayerShared::SetProne( bool bProne, bool bNoAnimation /* = false */ ) |
|
{ |
|
m_bProne = bProne; |
|
|
|
if ( bNoAnimation ) |
|
{ |
|
m_flGoProneTime = 0; |
|
m_flUnProneTime = 0; |
|
|
|
// cancel the view animation! |
|
m_bForceProneChange = true; |
|
} |
|
|
|
if ( !bProne /*&& IsSniperZoomed()*/ ) // forceunzoom for going prone is in StartGoingProne |
|
{ |
|
ForceUnzoom(); |
|
} |
|
} |
|
|
|
void CDODPlayerShared::SetJumping( bool bJumping ) |
|
{ |
|
m_bJumping = bJumping; |
|
|
|
if ( IsSniperZoomed() ) |
|
{ |
|
ForceUnzoom(); |
|
} |
|
} |
|
|
|
void CDODPlayerShared::ForceUnzoom( void ) |
|
{ |
|
CWeaponDODBase *pWeapon = GetActiveDODWeapon(); |
|
if( pWeapon && ( pWeapon->GetDODWpnData().m_WeaponType & WPN_MASK_GUN ) ) |
|
{ |
|
CDODSniperWeapon *pSniper = dynamic_cast<CDODSniperWeapon *>(pWeapon); |
|
|
|
if ( pSniper ) |
|
{ |
|
pSniper->ZoomOut(); |
|
} |
|
} |
|
} |
|
|
|
bool CDODPlayerShared::IsBazookaDeployed( void ) const |
|
{ |
|
CWeaponDODBase *pWeapon = GetActiveDODWeapon(); |
|
if( pWeapon && pWeapon->GetDODWpnData().m_WeaponType == WPN_TYPE_BAZOOKA ) |
|
{ |
|
CDODBaseRocketWeapon *pBazooka = (CDODBaseRocketWeapon *)pWeapon; |
|
return pBazooka->IsDeployed() && !pBazooka->m_bInReload; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
bool CDODPlayerShared::IsBazookaOnlyDeployed( void ) const |
|
{ |
|
CWeaponDODBase *pWeapon = GetActiveDODWeapon(); |
|
if( pWeapon && pWeapon->GetDODWpnData().m_WeaponType == WPN_TYPE_BAZOOKA ) |
|
{ |
|
CDODBaseRocketWeapon *pBazooka = (CDODBaseRocketWeapon *)pWeapon; |
|
return pBazooka->IsDeployed(); |
|
} |
|
|
|
return false; |
|
} |
|
|
|
bool CDODPlayerShared::IsSniperZoomed( void ) const |
|
{ |
|
CWeaponDODBase *pWeapon = GetActiveDODWeapon(); |
|
if( pWeapon && ( pWeapon->GetDODWpnData().m_WeaponType & WPN_MASK_GUN ) ) |
|
{ |
|
CWeaponDODBaseGun *pGun = (CWeaponDODBaseGun *)pWeapon; |
|
Assert( pGun ); |
|
return pGun->IsSniperZoomed(); |
|
} |
|
|
|
return false; |
|
} |
|
|
|
bool CDODPlayerShared::IsInMGDeploy( void ) const |
|
{ |
|
CWeaponDODBase *pWeapon = GetActiveDODWeapon(); |
|
if( pWeapon && pWeapon->GetDODWpnData().m_WeaponType == WPN_TYPE_MG ) |
|
{ |
|
CDODBipodWeapon *pMG = dynamic_cast<CDODBipodWeapon *>( pWeapon ); |
|
Assert( pMG ); |
|
return pMG->IsDeployed(); |
|
} |
|
|
|
return false; |
|
} |
|
|
|
bool CDODPlayerShared::IsProneDeployed( void ) const |
|
{ |
|
return ( IsProne() && IsInMGDeploy() ); |
|
} |
|
|
|
bool CDODPlayerShared::IsSandbagDeployed( void ) const |
|
{ |
|
return ( !IsProne() && IsInMGDeploy() ); |
|
} |
|
|
|
void CDODPlayerShared::SetDesiredPlayerClass( int playerclass ) |
|
{ |
|
m_iDesiredPlayerClass = playerclass; |
|
} |
|
|
|
int CDODPlayerShared::DesiredPlayerClass( void ) |
|
{ |
|
return m_iDesiredPlayerClass; |
|
} |
|
|
|
void CDODPlayerShared::SetPlayerClass( int playerclass ) |
|
{ |
|
m_iPlayerClass = playerclass; |
|
} |
|
|
|
int CDODPlayerShared::PlayerClass( void ) |
|
{ |
|
return m_iPlayerClass; |
|
} |
|
|
|
void CDODPlayerShared::SetStamina( float flStamina ) |
|
{ |
|
m_flStamina = clamp( flStamina, 0, 100 ); |
|
} |
|
|
|
CWeaponDODBase* CDODPlayerShared::GetActiveDODWeapon() const |
|
{ |
|
CBaseCombatWeapon *pWeapon = m_pOuter->GetActiveWeapon(); |
|
if ( pWeapon ) |
|
{ |
|
Assert( dynamic_cast< CWeaponDODBase* >( pWeapon ) == static_cast< CWeaponDODBase* >( pWeapon ) ); |
|
return static_cast< CWeaponDODBase* >( pWeapon ); |
|
} |
|
else |
|
{ |
|
return NULL; |
|
} |
|
} |
|
|
|
void CDODPlayerShared::SetDeployed( bool bDeployed, float flHeight /* = -1 */ ) |
|
{ |
|
if( gpGlobals->curtime - m_flDeployChangeTime < 0.2 ) |
|
{ |
|
Assert(0); |
|
} |
|
|
|
m_flDeployChangeTime = gpGlobals->curtime; |
|
m_vecDeployedAngles = m_pOuter->EyeAngles(); |
|
|
|
if( flHeight > 0 ) |
|
{ |
|
m_flDeployedHeight = flHeight; |
|
} |
|
else |
|
{ |
|
m_flDeployedHeight = m_pOuter->GetViewOffset()[2]; |
|
} |
|
} |
|
|
|
QAngle CDODPlayerShared::GetDeployedAngles( void ) const |
|
{ |
|
return m_vecDeployedAngles; |
|
} |
|
|
|
void CDODPlayerShared::SetDeployedYawLimits( float flLeftYaw, float flRightYaw ) |
|
{ |
|
m_flDeployedYawLimitLeft = flLeftYaw; |
|
m_flDeployedYawLimitRight = -flRightYaw; |
|
|
|
m_vecDeployedAngles = m_pOuter->EyeAngles(); |
|
} |
|
|
|
void CDODPlayerShared::ClampDeployedAngles( QAngle *vecTestAngles ) |
|
{ |
|
Assert( vecTestAngles ); |
|
|
|
// Clamp Pitch |
|
vecTestAngles->x = clamp( vecTestAngles->x, MAX_DEPLOY_PITCH, MIN_DEPLOY_PITCH ); |
|
|
|
// Clamp Yaw - do a bit more work as yaw will wrap around and cause problems |
|
float flDeployedYawCenter = GetDeployedAngles().y; |
|
|
|
float flDelta = AngleNormalize( vecTestAngles->y - flDeployedYawCenter ); |
|
|
|
if( flDelta < m_flDeployedYawLimitRight ) |
|
{ |
|
vecTestAngles->y = flDeployedYawCenter + m_flDeployedYawLimitRight; |
|
} |
|
else if( flDelta > m_flDeployedYawLimitLeft ) |
|
{ |
|
vecTestAngles->y = flDeployedYawCenter + m_flDeployedYawLimitLeft; |
|
} |
|
|
|
/* |
|
Msg( "delta %.1f ( left %.1f, right %.1f ) ( %.1f -> %.1f )\n", |
|
flDelta, |
|
flDeployedYawCenter + m_flDeployedYawLimitLeft, |
|
flDeployedYawCenter + m_flDeployedYawLimitRight, |
|
before, |
|
vecTestAngles->y ); |
|
*/ |
|
|
|
} |
|
|
|
float CDODPlayerShared::GetDeployedHeight( void ) const |
|
{ |
|
return m_flDeployedHeight; |
|
} |
|
|
|
float CDODPlayerShared::GetSlowedTime( void ) const |
|
{ |
|
return m_flSlowedUntilTime; |
|
} |
|
|
|
void CDODPlayerShared::SetSlowedTime( float t ) |
|
{ |
|
m_flSlowedUntilTime = gpGlobals->curtime + t; |
|
} |
|
|
|
void CDODPlayerShared::StartGoingProne( void ) |
|
{ |
|
// make the prone sound |
|
CPASFilter filter( m_pOuter->GetAbsOrigin() ); |
|
filter.UsePredictionRules(); |
|
m_pOuter->EmitSound( filter, m_pOuter->entindex(), "Player.GoProne" ); |
|
|
|
// slow to prone speed |
|
m_flGoProneTime = gpGlobals->curtime + TIME_TO_PRONE; |
|
|
|
m_flUnProneTime = 0.0f; //reset |
|
|
|
if ( IsSniperZoomed() ) |
|
ForceUnzoom(); |
|
} |
|
|
|
void CDODPlayerShared::StandUpFromProne( void ) |
|
{ |
|
// make the prone sound |
|
CPASFilter filter( m_pOuter->GetAbsOrigin() ); |
|
filter.UsePredictionRules(); |
|
m_pOuter->EmitSound( filter, m_pOuter->entindex(), "Player.UnProne" ); |
|
|
|
// speed up to target speed |
|
m_flUnProneTime = gpGlobals->curtime + TIME_TO_PRONE; |
|
|
|
m_flGoProneTime = 0.0f; //reset |
|
} |
|
|
|
bool CDODPlayerShared::CanChangePosition( void ) |
|
{ |
|
if ( IsInMGDeploy() ) |
|
return false; |
|
|
|
if ( IsGettingUpFromProne() ) |
|
return false; |
|
|
|
if ( IsGoingProne() ) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
void CDODPlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ) |
|
{ |
|
Vector knee; |
|
Vector feet; |
|
float height; |
|
int fLadder; |
|
|
|
if ( m_flStepSoundTime > 0 ) |
|
{ |
|
m_flStepSoundTime -= 1000.0f * gpGlobals->frametime; |
|
if ( m_flStepSoundTime < 0 ) |
|
{ |
|
m_flStepSoundTime = 0; |
|
} |
|
} |
|
|
|
if ( m_flStepSoundTime > 0 ) |
|
return; |
|
|
|
if ( GetFlags() & (FL_FROZEN|FL_ATCONTROLS)) |
|
return; |
|
|
|
if ( GetMoveType() == MOVETYPE_NOCLIP || GetMoveType() == MOVETYPE_OBSERVER ) |
|
return; |
|
|
|
if ( !sv_footsteps.GetFloat() ) |
|
return; |
|
|
|
float speed = VectorLength( vecVelocity ); |
|
float groundspeed = Vector2DLength( vecVelocity.AsVector2D() ); |
|
|
|
// determine if we are on a ladder |
|
fLadder = ( GetMoveType() == MOVETYPE_LADDER ); |
|
|
|
float flDuck; |
|
|
|
if ( ( GetFlags() & FL_DUCKING) || fLadder ) |
|
{ |
|
flDuck = 100; |
|
} |
|
else |
|
{ |
|
flDuck = 0; |
|
} |
|
|
|
static float flMinProneSpeed = 10.0f; |
|
static float flMinSpeed = 70.0f; |
|
static float flRunSpeed = 110.0f; |
|
|
|
bool onground = ( GetFlags() & FL_ONGROUND ); |
|
bool movingalongground = ( groundspeed > 0.0f ); |
|
bool moving_fast_enough = ( speed >= flMinSpeed ); |
|
|
|
// always play a step sound if we are moving faster than |
|
|
|
// To hear step sounds you must be either on a ladder or moving along the ground AND |
|
// You must be moving fast enough |
|
|
|
CheckProneMoveSound( groundspeed, onground ); |
|
|
|
if ( !moving_fast_enough || !(fLadder || ( onground && movingalongground )) ) |
|
{ |
|
return; |
|
} |
|
|
|
bool bWalking = ( speed < flRunSpeed ); // or ducking! |
|
|
|
VectorCopy( vecOrigin, knee ); |
|
VectorCopy( vecOrigin, feet ); |
|
|
|
height = GetPlayerMaxs()[ 2 ] - GetPlayerMins()[ 2 ]; |
|
|
|
knee[2] = vecOrigin[2] + 0.2 * height; |
|
|
|
float flVol; |
|
|
|
// find out what we're stepping in or on... |
|
if ( fLadder ) |
|
{ |
|
psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "ladder" ) ); |
|
flVol = 1.0; |
|
m_flStepSoundTime = 350; |
|
} |
|
else if ( enginetrace->GetPointContents( knee ) & MASK_WATER ) |
|
{ |
|
static int iSkipStep = 0; |
|
|
|
if ( iSkipStep == 0 ) |
|
{ |
|
iSkipStep++; |
|
return; |
|
} |
|
|
|
if ( iSkipStep++ == 3 ) |
|
{ |
|
iSkipStep = 0; |
|
} |
|
psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "wade" ) ); |
|
flVol = 0.65; |
|
m_flStepSoundTime = 600; |
|
} |
|
else if ( enginetrace->GetPointContents( feet ) & MASK_WATER ) |
|
{ |
|
psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "water" ) ); |
|
flVol = bWalking ? 0.2 : 0.5; |
|
m_flStepSoundTime = bWalking ? 400 : 300; |
|
} |
|
else |
|
{ |
|
if ( !psurface ) |
|
return; |
|
|
|
if ( bWalking ) |
|
{ |
|
m_flStepSoundTime = 400; |
|
} |
|
else |
|
{ |
|
if ( speed > 200 ) |
|
{ |
|
int speeddiff = PLAYER_SPEED_SPRINT - PLAYER_SPEED_RUN; |
|
int diff = speed - PLAYER_SPEED_RUN; |
|
|
|
float percent = (float)diff / (float)speeddiff; |
|
|
|
m_flStepSoundTime = 300.0f - 30.0f * percent; |
|
} |
|
else |
|
{ |
|
m_flStepSoundTime = 400; |
|
} |
|
} |
|
|
|
switch ( psurface->game.material ) |
|
{ |
|
default: |
|
case CHAR_TEX_CONCRETE: |
|
flVol = bWalking ? 0.2 : 0.5; |
|
break; |
|
|
|
case CHAR_TEX_METAL: |
|
flVol = bWalking ? 0.2 : 0.5; |
|
break; |
|
|
|
case CHAR_TEX_DIRT: |
|
flVol = bWalking ? 0.25 : 0.55; |
|
break; |
|
|
|
case CHAR_TEX_VENT: |
|
flVol = bWalking ? 0.4 : 0.7; |
|
break; |
|
|
|
case CHAR_TEX_GRATE: |
|
flVol = bWalking ? 0.2 : 0.5; |
|
break; |
|
|
|
case CHAR_TEX_TILE: |
|
flVol = bWalking ? 0.2 : 0.5; |
|
break; |
|
|
|
case CHAR_TEX_SLOSH: |
|
flVol = bWalking ? 0.2 : 0.5; |
|
break; |
|
} |
|
} |
|
|
|
m_flStepSoundTime += flDuck; // slower step time if ducking |
|
|
|
if ( GetFlags() & FL_DUCKING ) |
|
{ |
|
flVol *= 0.65; |
|
} |
|
|
|
// protect us from prediction errors a little bit |
|
if ( m_flMinNextStepSoundTime > gpGlobals->curtime ) |
|
{ |
|
return; |
|
} |
|
|
|
m_flMinNextStepSoundTime = gpGlobals->curtime + 0.1f; |
|
|
|
PlayStepSound( feet, psurface, flVol, false ); |
|
} |
|
|
|
void CDODPlayer::CheckProneMoveSound( int groundspeed, bool onground ) |
|
{ |
|
#ifdef CLIENT_DLL |
|
bool bShouldPlay = (groundspeed > 10) && (onground == true) && m_Shared.IsProne() && IsAlive(); |
|
|
|
if ( m_bPlayingProneMoveSound && !bShouldPlay ) |
|
{ |
|
StopSound( "Player.MoveProne" ); |
|
m_bPlayingProneMoveSound= false; |
|
} |
|
else if ( !m_bPlayingProneMoveSound && bShouldPlay ) |
|
{ |
|
CRecipientFilter filter; |
|
filter.AddRecipientsByPAS( WorldSpaceCenter() ); |
|
EmitSound( filter, entindex(), "Player.MoveProne" ); |
|
|
|
m_bPlayingProneMoveSound = true; |
|
} |
|
#endif |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : step - |
|
// fvol - |
|
// force - force sound to play |
|
//----------------------------------------------------------------------------- |
|
void CDODPlayer::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ) |
|
{ |
|
if ( gpGlobals->maxClients > 1 && !sv_footsteps.GetFloat() ) |
|
return; |
|
|
|
#if defined( CLIENT_DLL ) |
|
// during prediction play footstep sounds only once |
|
if ( prediction->InPrediction() && !prediction->IsFirstTimePredicted() ) |
|
return; |
|
#endif |
|
|
|
if ( !psurface ) |
|
return; |
|
|
|
unsigned short stepSoundName = m_Local.m_nStepside ? psurface->sounds.stepleft : psurface->sounds.stepright; |
|
m_Local.m_nStepside = !m_Local.m_nStepside; |
|
|
|
if ( !stepSoundName ) |
|
return; |
|
|
|
IPhysicsSurfaceProps *physprops = MoveHelper( )->GetSurfaceProps(); |
|
const char *pSoundName = physprops->GetString( stepSoundName ); |
|
CSoundParameters params; |
|
|
|
// we don't always know the model, so go by team |
|
char *pModelNameForGender = DOD_PLAYERMODEL_AXIS_RIFLEMAN; |
|
|
|
if( GetTeamNumber() == TEAM_ALLIES ) |
|
pModelNameForGender = DOD_PLAYERMODEL_US_RIFLEMAN; |
|
|
|
if ( !CBaseEntity::GetParametersForSound( pSoundName, params, pModelNameForGender ) ) |
|
return; |
|
|
|
CRecipientFilter filter; |
|
filter.AddRecipientsByPAS( vecOrigin ); |
|
|
|
#ifndef CLIENT_DLL |
|
// im MP, server removed all players in origins PVS, these players |
|
// generate the footsteps clientside |
|
if ( gpGlobals->maxClients > 1 ) |
|
filter.RemoveRecipientsByPVS( vecOrigin ); |
|
#endif |
|
|
|
EmitSound_t ep; |
|
ep.m_nChannel = params.channel; |
|
ep.m_pSoundName = params.soundname; |
|
ep.m_flVolume = fvol; |
|
ep.m_SoundLevel = params.soundlevel; |
|
ep.m_nFlags = 0; |
|
ep.m_nPitch = params.pitch; |
|
ep.m_pOrigin = &vecOrigin; |
|
|
|
EmitSound( filter, entindex(), ep ); |
|
} |
|
|
|
Activity CDODPlayer::TranslateActivity( Activity baseAct, bool *pRequired /* = NULL */ ) |
|
{ |
|
Activity translated = baseAct; |
|
|
|
if ( GetActiveWeapon() ) |
|
{ |
|
translated = GetActiveWeapon()->ActivityOverride( baseAct, pRequired ); |
|
} |
|
else if (pRequired) |
|
{ |
|
*pRequired = false; |
|
} |
|
|
|
return translated; |
|
} |
|
|
|
void CDODPlayerShared::SetCPIndex( int index ) |
|
{ |
|
#ifdef CLIENT_DLL |
|
|
|
if ( m_pOuter->IsLocalPlayer() ) |
|
{ |
|
if ( index == -1 ) |
|
{ |
|
// just left an area |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "ObjectiveIconShrink" ); |
|
} |
|
else |
|
{ |
|
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "ObjectiveIconGrow" ); |
|
} |
|
} |
|
|
|
#endif |
|
|
|
m_iCPIndex = index; |
|
} |
|
|
|
void CDODPlayerShared::SetLastViewAnimTime( float flTime ) |
|
{ |
|
m_flLastViewAnimationTime = flTime; |
|
} |
|
|
|
float CDODPlayerShared::GetLastViewAnimTime( void ) |
|
{ |
|
return m_flLastViewAnimationTime; |
|
} |
|
|
|
void CDODPlayerShared::ResetViewOffsetAnimation( void ) |
|
{ |
|
if ( m_pViewOffsetAnim ) |
|
{ |
|
//cancel it! |
|
m_pViewOffsetAnim->Reset(); |
|
} |
|
} |
|
|
|
void CDODPlayerShared::ViewOffsetAnimation( Vector vecDest, float flTime, ViewAnimationType type ) |
|
{ |
|
if ( !m_pViewOffsetAnim ) |
|
{ |
|
m_pViewOffsetAnim = CViewOffsetAnimation::CreateViewOffsetAnim( m_pOuter ); |
|
} |
|
|
|
Assert( m_pViewOffsetAnim ); |
|
|
|
if ( m_pViewOffsetAnim ) |
|
{ |
|
m_pViewOffsetAnim->StartAnimation( m_pOuter->GetViewOffset(), vecDest, flTime, type ); |
|
} |
|
} |
|
|
|
void CDODPlayerShared::ViewAnimThink( void ) |
|
{ |
|
// Check for the flag that will reset our view animations |
|
// when the player respawns |
|
if ( m_bForceProneChange ) |
|
{ |
|
ResetViewOffsetAnimation(); |
|
|
|
m_pOuter->SetViewOffset( VEC_VIEW_SCALED( m_pOuter ) ); |
|
|
|
m_bForceProneChange = false; |
|
} |
|
|
|
if ( m_pViewOffsetAnim ) |
|
{ |
|
m_pViewOffsetAnim->Think(); |
|
} |
|
} |
|
|
|
void CDODPlayerShared::ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) |
|
{ |
|
Vector org = m_pOuter->GetAbsOrigin(); |
|
|
|
if ( IsProne() ) |
|
{ |
|
static Vector vecProneMin(-44, -44, 0 ); |
|
static Vector vecProneMax(44, 44, 24 ); |
|
|
|
VectorAdd( vecProneMin, org, *pVecWorldMins ); |
|
VectorAdd( vecProneMax, org, *pVecWorldMaxs ); |
|
} |
|
else |
|
{ |
|
static Vector vecMin(-32, -32, 0 ); |
|
static Vector vecMax(32, 32, 72 ); |
|
|
|
VectorAdd( vecMin, org, *pVecWorldMins ); |
|
VectorAdd( vecMax, org, *pVecWorldMaxs ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Sets whether this player is dominating the specified other player |
|
//----------------------------------------------------------------------------- |
|
void CDODPlayerShared::SetPlayerDominated( CDODPlayer *pPlayer, bool bDominated ) |
|
{ |
|
int iPlayerIndex = pPlayer->entindex(); |
|
m_bPlayerDominated.Set( iPlayerIndex, bDominated ); |
|
pPlayer->m_Shared.SetPlayerDominatingMe( m_pOuter, bDominated ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Sets whether this player is being dominated by the other player |
|
//----------------------------------------------------------------------------- |
|
void CDODPlayerShared::SetPlayerDominatingMe( CDODPlayer *pPlayer, bool bDominated ) |
|
{ |
|
int iPlayerIndex = pPlayer->entindex(); |
|
m_bPlayerDominatingMe.Set( iPlayerIndex, bDominated ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns whether this player is dominating the specified other player |
|
//----------------------------------------------------------------------------- |
|
bool CDODPlayerShared::IsPlayerDominated( int iPlayerIndex ) |
|
{ |
|
#ifdef CLIENT_DLL |
|
// On the client, we only have data for the local player. |
|
// As a result, it's only valid to ask for dominations related to the local player |
|
C_DODPlayer *pLocalPlayer = C_DODPlayer::GetLocalDODPlayer(); |
|
if ( !pLocalPlayer ) |
|
return false; |
|
|
|
Assert( m_pOuter->IsLocalPlayer() || pLocalPlayer->entindex() == iPlayerIndex ); |
|
|
|
if ( m_pOuter->IsLocalPlayer() ) |
|
return m_bPlayerDominated.Get( iPlayerIndex ); |
|
|
|
return pLocalPlayer->m_Shared.IsPlayerDominatingMe( m_pOuter->entindex() ); |
|
#else |
|
// Server has all the data. |
|
return m_bPlayerDominated.Get( iPlayerIndex ); |
|
#endif |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CDODPlayerShared::IsPlayerDominatingMe( int iPlayerIndex ) |
|
{ |
|
return m_bPlayerDominatingMe.Get( iPlayerIndex ); |
|
}
|
|
|