//----------------------------------------------------------------------------- // Purpose: Allow pre-frame adjustments on the player //----------------------------------------------------------------------------- void CHL1_Player::PreThink(void) { CheckExplosionEffects(); if ( player_showpredictedposition.GetBool() ) { Vector predPos; UTIL_PredictedPosition( this, player_showpredictedposition_timestep.GetFloat(), &predPos ); NDebugOverlay::Box( predPos, NAI_Hull::Mins( GetHullType() ), NAI_Hull::Maxs( GetHullType() ), 0, 255, 0, 0, 0.01f ); NDebugOverlay::Line( GetAbsOrigin(), predPos, 0, 255, 0, 0, 0.01f ); } int buttonsChanged; buttonsChanged = m_afButtonPressed | m_afButtonReleased; g_pGameRules->PlayerThink( this ); if ( g_fGameOver || IsPlayerLockedInPlace() ) return; // intermission or finale ItemPreFrame( ); WaterMove(); if ( g_pGameRules && g_pGameRules->FAllowFlashlight() ) m_Local.m_iHideHUD &= ~HIDEHUD_FLASHLIGHT; else m_Local.m_iHideHUD |= HIDEHUD_FLASHLIGHT; // checks if new client data (for HUD and view control) needs to be sent to the client UpdateClientData(); CheckTimeBasedDamage(); CheckSuitUpdate(); if (m_lifeState >= LIFE_DYING) { PlayerDeathThink(); return; } // So the correct flags get sent to client asap. // if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) AddFlag( FL_ONTRAIN ); else RemoveFlag( FL_ONTRAIN ); // Train speed control if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) { CBaseEntity *pTrain = GetGroundEntity(); float vel; if ( pTrain ) { if ( !(pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) ) pTrain = NULL; } if ( !pTrain ) { if ( GetActiveWeapon() && (GetActiveWeapon()->ObjectCaps() & FCAP_DIRECTIONAL_USE) ) { m_iTrain = TRAIN_ACTIVE | TRAIN_NEW; if ( m_nButtons & IN_FORWARD ) { m_iTrain |= TRAIN_FAST; } else if ( m_nButtons & IN_BACK ) { m_iTrain |= TRAIN_BACK; } else { m_iTrain |= TRAIN_NEUTRAL; } return; } else { trace_t trainTrace; // Maybe this is on the other side of a level transition UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,-38), MASK_PLAYERSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trainTrace ); if ( trainTrace.fraction != 1.0 && trainTrace.m_pEnt ) pTrain = trainTrace.m_pEnt; if ( !pTrain || !(pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) || !pTrain->OnControls(GetContainingEntity(pev)) ) { // Warning( "In train mode with no train!\n" ); m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; m_iTrain = TRAIN_NEW|TRAIN_OFF; return; } } } else if ( !( GetFlags() & FL_ONGROUND ) || pTrain->HasSpawnFlags( SF_TRACKTRAIN_NOCONTROL ) || (m_nButtons & (IN_MOVELEFT|IN_MOVERIGHT) ) ) { // Turn off the train if you jump, strafe, or the train controls go dead m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; m_iTrain = TRAIN_NEW|TRAIN_OFF; return; } SetAbsVelocity( vec3_origin ); 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->m_flSpeed, ((CFuncTrackTrain*)pTrain)->GetMaxSpeed()); m_iTrain |= TRAIN_ACTIVE|TRAIN_NEW; } } else if (m_iTrain & TRAIN_ACTIVE) { m_iTrain = TRAIN_NEW; // turn off train } // THIS CODE DOESN'T SEEM TO DO ANYTHING!!! // WHY IS IT STILL HERE? (sjb) if (m_nButtons & 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 ((m_nButtons & IN_DUCK) || (GetFlags() & FL_DUCKING) || (m_afPhysicsFlags & PFLAG_DUCKING) ) Duck(); // // If we're not on the ground, we're falling. Update our falling velocity. // if ( !( GetFlags() & FL_ONGROUND ) ) { m_Local.m_flFallVelocity = -GetAbsVelocity().z; } if ( m_afPhysicsFlags & PFLAG_ONBARNACLE ) { SetAbsVelocity( vec3_origin ); } // StudioFrameAdvance( );//!!!HACKHACK!!! Can't be hit by traceline when not animating? //Find targets for NPC to shoot if they decide to miss us FindMissTargets(); }
//----------------------------------------------------------------------------- // 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 }
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 ); } }