void C_HL2MP_Player::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov ) { // third or first person ragdolls if ( m_lifeState != LIFE_ALIVE && !IsObserver() ) { // First person ragdolls if ( cl_fp_ragdoll.GetBool() && m_hRagdoll.Get() ) { // pointer to the ragdoll C_HL2MPRagdoll *pRagdoll = (C_HL2MPRagdoll*)m_hRagdoll.Get(); // gets its origin and angles pRagdoll->GetAttachment( pRagdoll->LookupAttachment( "eyes" ), eyeOrigin, eyeAngles ); Vector vForward; AngleVectors( eyeAngles, &vForward ); if ( cl_fp_ragdoll_auto.GetBool() ) { // DM: Don't use first person view when we are very close to something trace_t tr; UTIL_TraceLine( eyeOrigin, eyeOrigin + ( vForward * 10000 ), MASK_ALL, pRagdoll, COLLISION_GROUP_NONE, &tr ); if ( (!(tr.fraction < 1) || (tr.endpos.DistTo(eyeOrigin) > 25)) ) return; } else return; } eyeOrigin = vec3_origin; eyeAngles = vec3_angle; Vector origin = EyePosition(); IRagdoll *pRagdoll = GetRepresentativeRagdoll(); if ( pRagdoll ) { origin = pRagdoll->GetRagdollOrigin(); origin.z += VEC_DEAD_VIEWHEIGHT.z; // look over ragdoll, not through } BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov ); eyeOrigin = origin; Vector vForward; AngleVectors( eyeAngles, &vForward ); VectorNormalize( vForward ); VectorMA( origin, -CHASE_CAM_DISTANCE, vForward, eyeOrigin ); Vector WALL_MIN( -WALL_OFFSET, -WALL_OFFSET, -WALL_OFFSET ); Vector WALL_MAX( WALL_OFFSET, WALL_OFFSET, WALL_OFFSET ); trace_t trace; // clip against world // HACK don't recompute positions while doing RayTrace C_BaseEntity::EnableAbsRecomputations( false ); UTIL_TraceHull( origin, eyeOrigin, WALL_MIN, WALL_MAX, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace ); C_BaseEntity::EnableAbsRecomputations( true ); if (trace.fraction < 1.0) { eyeOrigin = trace.endpos; } return; } BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov ); }
//----------------------------------------------------------------------------- // Actual Eye position + angles //----------------------------------------------------------------------------- Vector CBasePlayer::EyePosition( ) { #ifdef CLIENT_DLL IClientVehicle *pVehicle = GetVehicle(); #else IServerVehicle *pVehicle = GetVehicle(); #endif if ( pVehicle ) { Assert( pVehicle ); int nRole = pVehicle->GetPassengerRole( this ); Vector vecEyeOrigin; QAngle angEyeAngles; pVehicle->GetVehicleViewPosition( nRole, &vecEyeOrigin, &angEyeAngles ); return vecEyeOrigin; } else { #ifdef CLIENT_DLL if ( IsObserver() ) { if ( m_iObserverMode == OBS_MODE_CHASE ) { if ( IsLocalPlayer() ) { return MainViewOrigin(); } } } #endif return BaseClass::EyePosition(); } }
//----------------------------------------------------------------------------- // Purpose: // Input : eyeOrigin - // eyeAngles - // zNear - // zFar - // fov - //----------------------------------------------------------------------------- void CBasePlayer::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov ) { #if defined( CLIENT_DLL ) IClientVehicle *pVehicle; #else IServerVehicle *pVehicle; #endif pVehicle = GetVehicle(); if ( !pVehicle ) { if ( IsObserver() ) { CalcObserverView( eyeOrigin, eyeAngles, fov ); } else { CalcPlayerView( eyeOrigin, eyeAngles, fov ); } } else { CalcVehicleView( pVehicle, eyeOrigin, eyeAngles, zNear, zFar, fov ); } }
void CHL2MP_Player::PlayerDeathThink() { if( !IsObserver() ) { BaseClass::PlayerDeathThink(); } }
//----------------------------------------------------------------------------- // Actual Eye position + angles //----------------------------------------------------------------------------- Vector CBasePlayer::EyePosition( ) { if ( GetVehicle() != NULL ) { // Return the cached result CacheVehicleView(); return m_vecVehicleViewOrigin; } else { #ifdef CLIENT_DLL if ( IsObserver() ) { if ( m_iObserverMode == OBS_MODE_CHASE ) { if ( IsLocalPlayer() ) { return MainViewOrigin(); } } } #endif return BaseClass::EyePosition(); } }
//----------------------------------------------------------------------------- // Purpose: Sets HL2 specific defaults. //----------------------------------------------------------------------------- void CHL2MP_Player::Spawn(void) { #ifdef GE_DLL m_bSpawnInterpCounter = !m_bSpawnInterpCounter; BaseClass::Spawn(); #else m_flNextModelChangeTime = 0.0f; m_flNextTeamChangeTime = 0.0f; PickDefaultSpawnTeam(); BaseClass::Spawn(); if ( !IsObserver() ) { pl.deadflag = false; RemoveSolidFlags( FSOLID_NOT_SOLID ); RemoveEffects( EF_NODRAW ); GiveDefaultItems(); } RemoveEffects( EF_NOINTERP ); m_nRenderFX = kRenderNormal; m_Local.m_iHideHUD = 0; AddFlag(FL_ONGROUND); // set the player on the ground at the start of the round. m_impactEnergyScale = HL2MPPLAYER_PHYSDAMAGE_SCALE; if ( HL2MPRules()->IsIntermission() ) { AddFlag( FL_FROZEN ); } else { RemoveFlag( FL_FROZEN ); } m_bSpawnInterpCounter = !m_bSpawnInterpCounter; m_Local.m_bDucked = false; SetPlayerUnderwater(false); m_bReady = false; #endif //Tony; do the spawn animevent DoAnimationEvent( PLAYERANIMEVENT_SPAWN ); SetContextThink( &CHL2MP_Player::HL2MPPushawayThink, gpGlobals->curtime + PUSHAWAY_THINK_INTERVAL, HL2MP_PUSHAWAY_THINK_CONTEXT ); }
//----------------------------------------------------------------------------- // Purpose: Returns the players Maxs - overridden for prone // Input : // Output : const Vector //----------------------------------------------------------------------------- const Vector CSDKPlayer::GetPlayerMaxs( void ) const { if ( IsObserver() ) { return VEC_OBS_HULL_MAX; } else { return VEC_HULL_MAX; } }
//----------------------------------------------------------------------------- // Purpose: Sets HL2 specific defaults. //----------------------------------------------------------------------------- void CHL2MP_Player::Spawn(void) { m_flNextModelChangeTime = 0.0f; m_flNextTeamChangeTime = 0.0f; PickDefaultSpawnTeam(); BaseClass::Spawn(); if ( !IsObserver() ) { pl.deadflag = false; RemoveSolidFlags( FSOLID_NOT_SOLID ); RemoveEffects( EF_NODRAW ); GiveDefaultItems(); } SetNumAnimOverlays( 3 ); ResetAnimation(); m_nRenderFX = kRenderNormal; m_Local.m_iHideHUD = 0; AddFlag(FL_ONGROUND); // set the player on the ground at the start of the round. m_impactEnergyScale = HL2MPPLAYER_PHYSDAMAGE_SCALE; if ( HL2MPRules()->IsIntermission() ) { AddFlag( FL_FROZEN ); } else { RemoveFlag( FL_FROZEN ); } m_iSpawnInterpCounter = (m_iSpawnInterpCounter + 1) % 8; m_Local.m_bDucked = false; SetPlayerUnderwater(false); m_bReady = false; m_flNextKickAttack = gpGlobals->curtime; CBaseViewModel *Leg = GetViewModel(1); Leg->SetWeaponModel("models/weapons/v_kick.mdl", NULL); }
//----------------------------------------------------------------------------- // Purpose: Sets HL2 specific defaults. //----------------------------------------------------------------------------- void CHL2MP_Player::Spawn(void) { m_flNextModelChangeTime = 0.0f; m_flNextTeamChangeTime = 0.0f; PickDefaultSpawnTeam(); BaseClass::Spawn(); if ( !IsObserver() ) { pl.deadflag = false; RemoveSolidFlags( FSOLID_NOT_SOLID ); RemoveEffects( EF_NODRAW ); GiveDefaultItems(); } m_nRenderFX = kRenderNormal; m_Local.m_iHideHUD = 0; AddFlag(FL_ONGROUND); // set the player on the ground at the start of the round. m_impactEnergyScale = HL2MPPLAYER_PHYSDAMAGE_SCALE; if ( HL2MPRules()->IsIntermission() ) { AddFlag( FL_FROZEN ); } else { RemoveFlag( FL_FROZEN ); } m_iSpawnInterpCounter = (m_iSpawnInterpCounter + 1) % 8; m_Local.m_bDucked = false; SetPlayerUnderwater(false); m_bReady = false; //Tony; do the spawn animevent DoAnimationEvent( PLAYERANIMEVENT_SPAWN ); }
//----------------------------------------------------------------------------- // Actual Eye position + angles //----------------------------------------------------------------------------- Vector CBasePlayer::EyePosition( ) { #ifdef CLIENT_DLL if ( IsObserver() ) { if ( GetObserverMode() == OBS_MODE_CHASE ) { if ( IsLocalPlayer() ) { return MainViewOrigin(); } } } #endif return BaseClass::EyePosition(); }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : const Vector //----------------------------------------------------------------------------- const Vector CBasePlayer::GetPlayerMaxs( void ) const { if ( IsObserver() ) { return VEC_OBS_HULL_MAX; } else { if ( GetFlags() & FL_DUCKING ) { return VEC_DUCK_HULL_MAX; } else { return VEC_HULL_MAX; } } }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : const Vector //----------------------------------------------------------------------------- const Vector CBasePlayer::GetPlayerMins( void ) const { if ( IsObserver() ) { return VEC_OBS_HULL_MIN_SCALED( this ); } else { if ( GetFlags() & FL_DUCKING ) { return VEC_DUCK_HULL_MIN_SCALED( this ); } else { return VEC_HULL_MIN_SCALED( this ); } } }
//----------------------------------------------------------------------------- // Purpose: Returns the players mins - overridden for prone // Input : // Output : const Vector //----------------------------------------------------------------------------- const Vector CBliinkPlayer::GetPlayerMins( void ) const { if ( IsObserver() ) { return VEC_OBS_HULL_MIN; } else { if ( GetFlags() & FL_DUCKING ) { return VEC_DUCK_HULL_MIN; } else { return VEC_HULL_MIN; } } }
void C_HL2MP_Player::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov ) { if ( m_lifeState != LIFE_ALIVE && !IsObserver() ) { Vector origin = EyePosition(); IRagdoll *pRagdoll = GetRepresentativeRagdoll(); if ( pRagdoll ) { origin = pRagdoll->GetRagdollOrigin(); origin.z += VEC_DEAD_VIEWHEIGHT.z; // look over ragdoll, not through } BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov ); eyeOrigin = origin; Vector vForward; AngleVectors( eyeAngles, &vForward ); VectorNormalize( vForward ); VectorMA( origin, -CHASE_CAM_DISTANCE, vForward, eyeOrigin ); Vector WALL_MIN( -WALL_OFFSET, -WALL_OFFSET, -WALL_OFFSET ); Vector WALL_MAX( WALL_OFFSET, WALL_OFFSET, WALL_OFFSET ); trace_t trace; // clip against world C_BaseEntity::PushEnableAbsRecomputations( false ); // HACK don't recompute positions while doing RayTrace UTIL_TraceHull( origin, eyeOrigin, WALL_MIN, WALL_MAX, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace ); C_BaseEntity::PopEnableAbsRecomputations(); if (trace.fraction < 1.0) { eyeOrigin = trace.endpos; } return; } BaseClass::CalcView( eyeOrigin, eyeAngles, zNear, zFar, fov ); }
void CBasePlayer::AvoidPhysicsProps( CUserCmd *pCmd ) { #ifndef _XBOX // Don't avoid if noclipping or in movetype none switch ( GetMoveType() ) { case MOVETYPE_NOCLIP: case MOVETYPE_NONE: return; default: break; } if ( !IsObserver() ) return; AvoidPushawayProps( this, pCmd ); #endif }
bool C_CFPlayer::IsFirstPersonSpectating( C_BaseEntity* pTarget ) { if (!IsObserver()) return false; if (GetObserverMode() != OBS_MODE_IN_EYE) return false; if (!GetObserverTarget()) return false; if (GetObserverTarget() != pTarget) return false; if (ToCFPlayer(pTarget) && ToCFPlayer(pTarget)->ShouldForceThirdPerson()) return false; return true; }
//----------------------------------------------------------------------------- // Purpose: Handles USE keypress //----------------------------------------------------------------------------- void CBasePlayer::PlayerUse ( void ) { #ifdef GAME_DLL // Was use pressed or released? if ( ! ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) ) return; if ( IsObserver() ) { // do special use operation in oberserver mode if ( m_afButtonPressed & IN_USE ) ObserverUse( true ); else if ( m_afButtonReleased & IN_USE ) ObserverUse( false ); return; } #endif }
//----------------------------------------------------------------------------- // Purpose: // Input : eyeOrigin - // eyeAngles - // zNear - // zFar - // fov - //----------------------------------------------------------------------------- void CBasePlayer::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov ) { #if defined( CLIENT_DLL ) if( UseVR() ) g_ClientVirtualReality.CancelTorsoTransformOverride(); #endif if ( IsObserver() ) { CalcObserverView( eyeOrigin, eyeAngles, fov ); } else { CalcPlayerView( eyeOrigin, eyeAngles, fov ); } // NVNT update fov on the haptics dll for input scaling. #if defined( CLIENT_DLL ) if(IsLocalPlayer() && haptics) haptics->UpdatePlayerFOV(fov); #endif }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : const Vector //----------------------------------------------------------------------------- const Vector CDODPlayer::GetPlayerMaxs( void ) const { if ( IsObserver() ) { return VEC_OBS_HULL_MAX; } else { if ( GetFlags() & FL_DUCKING ) { return VEC_DUCK_HULL_MAX; } else if ( m_Shared.IsProne() ) { return VEC_PRONE_HULL_MAX; } else { return VEC_HULL_MAX; } } }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : const Vector //----------------------------------------------------------------------------- const Vector CBasePlayer::GetPlayerMins( void ) const { if ( IsObserver() ) { return VEC_OBS_HULL_MIN; } else { //DHL - Skillet if ( GetFlags() & FL_PRONE ) { return VEC_PRONE_HULL_MIN; } if ( GetFlags() & FL_DUCKING ) { return VEC_DUCK_HULL_MIN; } else { return VEC_HULL_MIN; } } }
//----------------------------------------------------------------------------- // Purpose: Returns the players Maxs - overridden for prone // Input : // Output : const Vector //----------------------------------------------------------------------------- const Vector CSDKPlayer::GetPlayerMaxs( void ) const { if ( IsObserver() ) { return VEC_OBS_HULL_MAX; } else { if ( GetFlags() & FL_DUCKING ) { return VEC_DUCK_HULL_MAX; } #if defined ( SDK_USE_PRONE ) else if ( m_Shared.IsProne() ) { return VEC_PRONE_HULL_MAX; } #endif // SDK_USE_PRONE else { return VEC_HULL_MAX; } } }
//----------------------------------------------------------------------------- // Purpose: Returns the players Maxs - overridden for prone // Input : // Output : const Vector //----------------------------------------------------------------------------- const Vector CSDKPlayer::GetPlayerMaxs( void ) const { if ( IsObserver() ) { return VEC_OBS_HULL_MAX; } else { if ( GetFlags() & FL_DUCKING ) return VEC_DUCK_HULL_MAX; else if ( m_Shared.IsDiving() ) return VEC_DIVE_HULL_MAX; #if defined ( SDK_USE_PRONE ) else if ( m_Shared.IsProne() ) return VEC_PRONE_HULL_MAX; #endif // SDK_USE_PRONE else if ( m_Shared.IsSliding() ) return VEC_SLIDE_HULL_MAX; else if ( m_Shared.IsRolling() ) return VEC_DUCK_HULL_MAX; else return VEC_HULL_MAX; } }
void CBasePlayer::PlayerDeathThink() { if( GetFlags().Any( FL_ONGROUND ) ) { const float flForward = GetAbsVelocity().Length() - 20; if( flForward <= 0 ) SetAbsVelocity( g_vecZero ); else SetAbsVelocity( flForward * GetAbsVelocity().Normalize() ); } if( HasWeapons() ) { // we drop the guns here because weapons that have an area effect and can kill their user // will sometimes crash coming back from CBasePlayer::Killed() if they kill their owner because the // player class sometimes is freed. It's safer to manipulate the weapons once we know // we aren't calling into any of their code anymore through the player pointer. PackDeadPlayerItems(); } if( GetModelIndex() && ( !m_fSequenceFinished ) && ( GetDeadFlag() == DEAD_DYING ) ) { StudioFrameAdvance(); m_iRespawnFrames++; // Note, these aren't necessarily real "frames", so behavior is dependent on # of client movement commands if( m_iRespawnFrames < 120 ) // Animations should be no longer than this return; } // once we're done animating our death and we're on the ground, we want to set movetype to None so our dead body won't do collisions and stuff anymore // this prevents a bug where the dead body would go to a player's head if he walked over it while the dead player was clicking their button to respawn if( GetMoveType() != MOVETYPE_NONE && GetFlags().Any( FL_ONGROUND ) ) SetMoveType( MOVETYPE_NONE ); if( GetDeadFlag() == DEAD_DYING ) SetDeadFlag( DEAD_DEAD ); StopAnimation(); GetEffects() |= EF_NOINTERP; SetFrameRate( 0.0 ); const bool fAnyButtonDown = ( GetButtons().Any( ~IN_SCORE ) ) != 0; // wait for all buttons released if( GetDeadFlag() == DEAD_DEAD ) { if( fAnyButtonDown ) return; if( g_pGameRules->FPlayerCanRespawn( this ) ) { m_fDeadTime = gpGlobals->time; SetDeadFlag( DEAD_RESPAWNABLE ); } return; } // if the player has been dead for one second longer than allowed by forcerespawn, // forcerespawn isn't on. Send the player off to an intermission camera until they // choose to respawn. if( g_pGameRules->IsMultiplayer() && ( gpGlobals->time > ( m_fDeadTime + 6 ) ) && !( m_afPhysicsFlags & PFLAG_OBSERVER ) ) { // go to dead camera. StartDeathCam(); } if( IsObserver() ) // player is in spectator mode return; // wait for any button down, or mp_forcerespawn is set and the respawn time is up if( !fAnyButtonDown && !( g_pGameRules->IsMultiplayer() && forcerespawn.value > 0 && ( gpGlobals->time > ( m_fDeadTime + 5 ) ) ) ) return; GetButtons().ClearAll(); m_iRespawnFrames = 0; //ALERT(at_console, "Respawn\n"); g_pGameRules->PlayerRespawn( this, !( m_afPhysicsFlags & PFLAG_OBSERVER ) );// don't copy a corpse if we're in deathcam. SetNextThink( -1 ); }
void UpdateClientEffects(CBasePlayer *pObserver, int oldMode) { bool clearProgress = false; bool clearBlindness = false; bool blindnessOk = (fadetoblack.value == 0); bool clearNightvision = false; if (pObserver->IsObserver() == OBS_IN_EYE) { clearProgress = true; clearBlindness = true; clearNightvision = true; if (pObserver->m_hObserverTarget->IsPlayer()) { CBasePlayer *pPlayer = UTIL_PlayerByIndex(pObserver->m_hObserverTarget->entindex()); if (pPlayer) { if (pPlayer->m_progressStart && pPlayer->m_progressEnd > pPlayer->m_progressStart) { if (pPlayer->m_progressEnd > gpGlobals->time) { float percentRemaining = gpGlobals->time - pPlayer->m_progressStart; pObserver->SetProgressBarTime2(int(pPlayer->m_progressEnd - pPlayer->m_progressStart), percentRemaining); clearProgress = false; } } if (blindnessOk && pPlayer->m_blindStartTime && pPlayer->m_blindFadeTime) { float fadeTime, holdTime, alpha, ratio; float endTime = pPlayer->m_blindFadeTime + pPlayer->m_blindHoldTime + pPlayer->m_blindStartTime; if (endTime > gpGlobals->time) { clearBlindness = false; fadeTime = pPlayer->m_blindFadeTime; alpha = float(pPlayer->m_blindAlpha); holdTime = pPlayer->m_blindHoldTime + pPlayer->m_blindStartTime - gpGlobals->time; if (holdTime <= 0) { holdTime = 0; ratio = (endTime - gpGlobals->time) / fadeTime; alpha = pPlayer->m_blindAlpha * ratio; fadeTime = ratio * fadeTime; } UTIL_ScreenFade(pObserver, Vector(255, 255, 255), fadeTime, holdTime, alpha); } } clearNightvision = false; if (pPlayer->m_bNightVisionOn != pObserver->m_bNightVisionOn) { MESSAGE_BEGIN(MSG_ONE, gmsgNVGToggle, NULL, pObserver->pev); WRITE_BYTE(pPlayer->m_bNightVisionOn ? STATUS_NIGHTVISION_ON : STATUS_NIGHTVISION_OFF); MESSAGE_END(); pObserver->m_bNightVisionOn = pPlayer->m_bNightVisionOn; } } } } else if (oldMode == OBS_IN_EYE) { clearProgress = true; clearBlindness = true; clearNightvision = true; } if (clearProgress) pObserver->SetProgressBarTime(0); if (blindnessOk && clearBlindness) UTIL_ScreenFade(pObserver, Vector(0, 0, 0), 0.001); if (clearNightvision) { MESSAGE_BEGIN(MSG_ONE, gmsgNVGToggle, NULL, pObserver->pev); WRITE_BYTE(STATUS_NIGHTVISION_OFF); MESSAGE_END(); pObserver->m_bNightVisionOn = false; } }
void CBasePlayer::PreThink() { const int buttonsChanged = ( m_afButtonLast ^ GetButtons().Get() ); // These buttons have changed this frame // Debounced button codes for pressed/released // UNDONE: Do we need auto-repeat? m_afButtonPressed = buttonsChanged & GetButtons().Get(); // The changed ones still down are "pressed" m_afButtonReleased = buttonsChanged & ( ~GetButtons().Get() ); // The ones not down are "released" g_pGameRules->PlayerThink( this ); bool bCheckVehicles = true; #if USE_ANGELSCRIPT uint32_t uiFlags = PreThinkFlag::NONE; CallGlobalEvent( g_PlayerPreThinkEvent, CallFlag::NONE, this, &uiFlags ); bCheckVehicles = !( uiFlags & PreThinkFlag::SKIP_VEHICLES ); #endif if( g_fGameOver ) return; // intermission or finale UTIL_MakeVectors( GetViewAngle() ); // is this still used? ItemPreFrame(); WaterMove(); if( g_pGameRules && g_pGameRules->FAllowFlashlight() ) m_iHideHUD &= ~HIDEHUD_FLASHLIGHT; else m_iHideHUD |= HIDEHUD_FLASHLIGHT; // JOHN: checks if new client data (for HUD and view control) needs to be sent to the client UpdateClientData(); CheckTimeBasedDamage(); CheckSuitUpdate(); // Observer Button Handling if( IsObserver() ) { Observer_HandleButtons(); Observer_CheckTarget(); Observer_CheckProperties(); SetImpulse( 0 ); return; } if( GetDeadFlag() >= DEAD_DYING ) { PlayerDeathThink(); return; } // So the correct flags get sent to client asap. // if( m_afPhysicsFlags & PFLAG_ONTRAIN ) GetFlags() |= FL_ONTRAIN; else GetFlags().ClearFlags( FL_ONTRAIN ); if( bCheckVehicles ) { #if USE_OPFOR //We're on a rope. - Solokiller if( m_afPhysicsFlags & PFLAG_ONROPE && m_pRope ) { SetAbsVelocity( g_vecZero ); const Vector vecAttachPos = m_pRope->GetAttachedObjectsPosition(); SetAbsOrigin( vecAttachPos ); Vector vecForce; /* //TODO: This causes sideways acceleration that doesn't occur in Op4. - Solokiller //TODO: should be IN_MOVERIGHT and IN_MOVELEFT - Solokiller if( GetButtons().Any( IN_DUCK ) ) { vecForce.x = gpGlobals->v_right.x; vecForce.y = gpGlobals->v_right.y; vecForce.z = 0; m_pRope->ApplyForceFromPlayer( vecForce ); } if( GetButtons().Any( IN_JUMP ) ) { vecForce.x = -gpGlobals->v_right.x; vecForce.y = -gpGlobals->v_right.y; vecForce.z = 0; m_pRope->ApplyForceFromPlayer( vecForce ); } */ //Determine if any force should be applied to the rope, or if we should move around. - Solokiller if( GetButtons().Any( IN_BACK | IN_FORWARD ) ) { if( ( gpGlobals->v_forward.x * gpGlobals->v_forward.x + gpGlobals->v_forward.y * gpGlobals->v_forward.y - gpGlobals->v_forward.z * gpGlobals->v_forward.z ) <= 0.0 ) { if( m_bIsClimbing ) { const float flDelta = gpGlobals->time - m_flLastClimbTime; m_flLastClimbTime = gpGlobals->time; if( GetButtons().Any( IN_FORWARD ) ) { if( gpGlobals->v_forward.z < 0.0 ) { if( !m_pRope->MoveDown( flDelta ) ) { //Let go of the rope, detach. - Solokiller SetMoveType( MOVETYPE_WALK ); SetSolidType( SOLID_SLIDEBOX ); m_afPhysicsFlags &= ~PFLAG_ONROPE; m_pRope->DetachObject(); m_pRope = nullptr; m_bIsClimbing = false; } } else { m_pRope->MoveUp( flDelta ); } } if( GetButtons().Any( IN_BACK ) ) { if( gpGlobals->v_forward.z < 0.0 ) { m_pRope->MoveUp( flDelta ); } else if( !m_pRope->MoveDown( flDelta ) ) { //Let go of the rope, detach. - Solokiller SetMoveType( MOVETYPE_WALK ); SetSolidType( SOLID_SLIDEBOX ); m_afPhysicsFlags &= ~PFLAG_ONROPE; m_pRope->DetachObject(); m_pRope = nullptr; m_bIsClimbing = false; } } } else { m_bIsClimbing = true; m_flLastClimbTime = gpGlobals->time; } } else { vecForce.x = gpGlobals->v_forward.x; vecForce.y = gpGlobals->v_forward.y; vecForce.z = 0.0; if( GetButtons().Any( IN_BACK ) ) { vecForce.x = -gpGlobals->v_forward.x; vecForce.y = -gpGlobals->v_forward.y; vecForce.z = 0; } m_pRope->ApplyForceFromPlayer( vecForce ); m_bIsClimbing = false; } } else { m_bIsClimbing = false; } if( m_afButtonPressed & IN_JUMP ) { //We've jumped off the rope, give us some momentum - Solokiller SetMoveType( MOVETYPE_WALK ); SetSolidType( SOLID_SLIDEBOX ); this->m_afPhysicsFlags &= ~PFLAG_ONROPE; Vector vecDir = gpGlobals->v_up * 165.0 + gpGlobals->v_forward * 150.0; Vector vecVelocity = m_pRope->GetAttachedObjectsVelocity() * 2; vecVelocity.NormalizeInPlace(); vecVelocity = vecVelocity * 200; SetAbsVelocity( vecVelocity + vecDir ); m_pRope->DetachObject(); m_pRope = nullptr; m_bIsClimbing = false; } return; } #endif // Train speed control if( m_afPhysicsFlags & PFLAG_ONTRAIN ) { CBaseEntity *pTrain = GetGroundEntity(); //To match original behavior, Instance returns the world if entity is null - Solokiller if( !pTrain ) pTrain = CWorld::GetInstance(); float vel; if( !pTrain ) { TraceResult trainTrace; // Maybe this is on the other side of a level transition UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -38 ), ignore_monsters, ENT( pev ), &trainTrace ); // HACKHACK - Just look for the func_tracktrain classname if( trainTrace.flFraction != 1.0 && trainTrace.pHit ) pTrain = CBaseEntity::Instance( trainTrace.pHit ); if( !pTrain || !( pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE ) || !pTrain->OnControls( this ) ) { //ALERT( at_error, "In train mode with no train!\n" ); m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_iTrain = TRAIN_NEW | TRAIN_OFF; return; } } else if( !GetFlags().Any( FL_ONGROUND ) || pTrain->GetSpawnFlags().Any( SF_TRACKTRAIN_NOCONTROL ) || ( GetButtons().Any( IN_MOVELEFT | IN_MOVERIGHT ) ) ) { // Turn off the train if you jump, strafe, or the train controls go dead m_afPhysicsFlags &= ~PFLAG_ONTRAIN; m_iTrain = TRAIN_NEW | TRAIN_OFF; return; } SetAbsVelocity( g_vecZero ); vel = 0; if( m_afButtonPressed & IN_FORWARD ) { vel = 1; pTrain->Use( this, this, USE_SET, ( float ) vel ); } else if( m_afButtonPressed & IN_BACK ) { vel = -1; pTrain->Use( this, this, USE_SET, ( float ) vel ); } if( vel ) { m_iTrain = TrainSpeed( pTrain->GetSpeed(), pTrain->GetImpulse() ); m_iTrain |= TRAIN_ACTIVE | TRAIN_NEW; } } else if( m_iTrain & TRAIN_ACTIVE ) m_iTrain = TRAIN_NEW; // turn off train } if( GetButtons().Any( IN_JUMP ) ) { // If on a ladder, jump off the ladder // else Jump Jump(); } // If trying to duck, already ducked, or in the process of ducking if( GetButtons().Any( IN_DUCK ) || GetFlags().Any( FL_DUCKING ) || ( m_afPhysicsFlags & PFLAG_DUCKING ) ) Duck(); if( !GetFlags().Any( FL_ONGROUND ) ) { m_flFallVelocity = -GetAbsVelocity().z; } // StudioFrameAdvance( );//!!!HACKHACK!!! Can't be hit by traceline when not animating? // Clear out ladder pointer m_hEnemy = NULL; if( m_afPhysicsFlags & PFLAG_ONBARNACLE ) { SetAbsVelocity( g_vecZero ); } }
bool CSDKPlayer::PlayerUse() { #ifdef GAME_DLL // Was use pressed or released? if ( ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) && !IsObserver() ) { Vector forward, up; EyeVectors( &forward, NULL, &up ); Vector vecSearchCenter = EyePosition(); CBaseEntity *pObject = nullptr; CBaseEntity *pNearest = nullptr; float flNearest = FLT_MAX; // Look for grenades so we can prioritize picking them up first. for ( CEntitySphereQuery sphere( vecSearchCenter, PLAYER_USE_RADIUS ); ( pObject = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) { if ( !pObject ) continue; if ( !IsUseableEntity( pObject, FCAP_USE_IN_RADIUS ) ) continue; CWeaponSDKBase* pWeapon = dynamic_cast<CWeaponSDKBase*>(pObject); if (!pWeapon) continue; if (pWeapon->GetWeaponID() != SDK_WEAPON_GRENADE) continue; // If we're full up on grenades, pass over to whatever other weapons are lying around. if (!g_pGameRules->CanHavePlayerItem(this, pWeapon)) continue; // see if it's more roughly in front of the player than previous guess Vector point; pObject->CollisionProp()->CalcNearestPoint( vecSearchCenter, &point ); Vector dir = point - vecSearchCenter; VectorNormalize(dir); float dot = DotProduct( dir, forward ); // Need to be looking at the object more or less if ( dot < 0.8 ) continue; float dist = CalcDistanceToLine( point, vecSearchCenter, forward ); ConVarRef sv_debug_player_use("sv_debug_player_use"); if ( sv_debug_player_use.GetBool() ) { Msg("Radius found %s, dist %.2f\n", pObject->GetClassname(), dist ); } // Not worried about shit being behind a wall at this point. // Just greedily gobble up all nearby grenades since there's // no penalty to the player for doing so. if ( dist < flNearest ) { pNearest = pObject; flNearest = dist; } } if (pNearest) { // This is a grenade. Use it to pick it up. variant_t emptyVariant; pNearest->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE ); return true; } } #endif bool bUsed = BaseClass::PlayerUse(); if (bUsed) return bUsed; if (!(m_afButtonPressed & IN_USE)) return false; if (!IsAlive()) return false; return false; }
//----------------------------------------------------------------------------- // Purpose: Handles USE keypress //----------------------------------------------------------------------------- void CBasePlayer::PlayerUse ( void ) { #ifdef GAME_DLL // Was use pressed or released? if ( ! ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) ) return; if ( IsObserver() ) { // do special use operation in oberserver mode if ( m_afButtonPressed & IN_USE ) ObserverUse( true ); else if ( m_afButtonReleased & IN_USE ) ObserverUse( false ); return; } #if !defined(_XBOX) // push objects in turbo physics mode if ( (m_nButtons & IN_USE) && sv_turbophysics.GetBool() ) { Vector forward, up; EyeVectors( &forward, NULL, &up ); trace_t tr; // Search for objects in a sphere (tests for entities that are not solid, yet still useable) Vector searchCenter = EyePosition(); CUsePushFilter filter; UTIL_TraceLine( searchCenter, searchCenter + forward * 96.0f, MASK_SOLID, &filter, &tr ); // try the hit entity if there is one, or the ground entity if there isn't. CBaseEntity *entity = tr.m_pEnt; if ( entity ) { IPhysicsObject *pObj = entity->VPhysicsGetObject(); if ( pObj ) { Vector vPushAway = (entity->WorldSpaceCenter() - WorldSpaceCenter()); vPushAway.z = 0; float flDist = VectorNormalize( vPushAway ); flDist = max( flDist, 1 ); float flForce = sv_pushaway_force.GetFloat() / flDist; flForce = min( flForce, sv_pushaway_max_force.GetFloat() ); pObj->ApplyForceOffset( vPushAway * flForce, WorldSpaceCenter() ); } } } #endif if ( m_afButtonPressed & IN_USE ) { // Controlling some latched entity? if ( ClearUseEntity() ) { return; } else { if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) { m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; m_iTrain = TRAIN_NEW|TRAIN_OFF; return; } else { // Start controlling the train! CBaseEntity *pTrain = GetGroundEntity(); if ( pTrain && !(m_nButtons & IN_JUMP) && (GetFlags() & FL_ONGROUND) && (pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) && pTrain->OnControls(this) ) { m_afPhysicsFlags |= PFLAG_DIROVERRIDE; m_iTrain = TrainSpeed(pTrain->m_flSpeed, ((CFuncTrackTrain*)pTrain)->GetMaxSpeed()); m_iTrain |= TRAIN_NEW; EmitSound( "Player.UseTrain" ); return; } } } } CBaseEntity *pUseEntity = FindUseEntity(); // Found an object if ( pUseEntity ) { //!!!UNDONE: traceline here to prevent +USEing buttons through walls int caps = pUseEntity->ObjectCaps(); variant_t emptyVariant; if ( ( (m_nButtons & IN_USE) && (caps & FCAP_CONTINUOUS_USE) ) || ( (m_afButtonPressed & IN_USE) && (caps & (FCAP_IMPULSE_USE|FCAP_ONOFF_USE)) ) ) { if ( caps & FCAP_CONTINUOUS_USE ) { m_afPhysicsFlags |= PFLAG_USING; } if ( pUseEntity->ObjectCaps() & FCAP_ONOFF_USE ) { pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_ON ); } else { pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE ); } } // UNDONE: Send different USE codes for ON/OFF. Cache last ONOFF_USE object to send 'off' if you turn away else if ( (m_afButtonReleased & IN_USE) && (pUseEntity->ObjectCaps() & FCAP_ONOFF_USE) ) // BUGBUG This is an "off" use { pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_OFF ); } } else if ( m_afButtonPressed & IN_USE ) { PlayUseDenySound(); } #endif }