void ScreenLayoutManager::UpdateHUDCanvasSize( void ) { const int renderWidth = gEnv->pRenderer->GetWidth(); const int renderHeight = gEnv->pRenderer->GetHeight(); RENDER_SCREEN_WIDTH = (float)renderWidth; RENDER_SCREEN_HEIGHT = (float)renderHeight; assert(RENDER_SCREEN_WIDTH>0.0f); assert(RENDER_SCREEN_HEIGHT>0.0f); INV_RENDER_SCREEN_WIDTH = 1.0f*__fres(RENDER_SCREEN_WIDTH); INV_RENDER_SCREEN_HEIGHT = 1.0f*__fres(RENDER_SCREEN_HEIGHT); // Force update of HUDAssets and other objects. const float pa = gEnv->pRenderer->GetPixelAspectRatio(); Vec2 curCanvasSize( RENDER_SCREEN_WIDTH*__fres(pa), RENDER_SCREEN_HEIGHT ); SHUDEvent resizeEvent(eHUDEvent_OnResolutionChange); resizeEvent.AddData(SHUDEventData(curCanvasSize.x)); resizeEvent.AddData(SHUDEventData(curCanvasSize.y)); resizeEvent.AddData(SHUDEventData(RENDER_SCREEN_WIDTH)); resizeEvent.AddData(SHUDEventData(RENDER_SCREEN_HEIGHT)); resizeEvent.AddData(SHUDEventData(int_round(RENDER_SCREEN_WIDTH))); resizeEvent.AddData(SHUDEventData(int_round(RENDER_SCREEN_HEIGHT))); //resizeEvent.AddData(SHUDEventData(pa)); CHUDEventDispatcher::CallEvent(resizeEvent); }
//------------------------------------------------------------------------ float CGameRulesCommonDamageHandling::GetVehicleForeignCollisionMultiplier( const IVehicle& vehicle, const SCollisionEntityInfo& colliderInfo, const CGameRules::SCollisionHitInfo& colHitInfo ) const { float result = 1.0f; //Vehicle to vehicle collision if (colliderInfo.pEntityVehicle) { const float vehicleMass = vehicle.GetMass(); const float vehicleColliderMass = colliderInfo.pEntityVehicle->GetMass(); const float targetSpeedSqr = colHitInfo.target_velocity.len2(); if ((vehicleMass > vehicleColliderMass * 1.5f) && (targetSpeedSqr > 0.01f)) { //Reduce damage for collisions with large mass ratios, to avoid instant-killing const float ratio = 1.0f + (0.35f * min(10.0f, vehicleMass * __fres(vehicleColliderMass))) * min(1.0f, targetSpeedSqr * 0.31623f); result = __fres(ratio); if (DebugCollisions()) { CryLog("Vehicle/Vehicle (%s <- %s), collision mult: %.2f", vehicle.GetEntity()->GetName(), colliderInfo.pEntity->GetName(), result); } } } return result; }
void CRecoil::PatchSpreadMod(const SSpreadModParams& spreadMod, const SSpreadParams& originalSpreadParams, float modMultiplier) { float oldSpreadMin = m_spreadParams.min; float oldSpreadMax = m_spreadParams.max; m_spreadParams.attack = CalculateParamModValue(originalSpreadParams.attack, spreadMod.attack_mod, modMultiplier); m_spreadParams.decay = CalculateParamModValue(originalSpreadParams.decay, spreadMod.decay_mod, modMultiplier); m_spreadParams.end_decay = CalculateParamModValue(originalSpreadParams.end_decay, spreadMod.end_decay_mod, modMultiplier); m_spreadParams.max = CalculateParamModValue(originalSpreadParams.max, spreadMod.max_mod, modMultiplier); m_spreadParams.min = CalculateParamModValue(originalSpreadParams.min, spreadMod.min_mod, modMultiplier); m_spreadParams.rotation_m = CalculateParamModValue(originalSpreadParams.rotation_m, spreadMod.rotation_m_mod, modMultiplier); m_spreadParams.speed_m = CalculateParamModValue(originalSpreadParams.speed_m, spreadMod.speed_m_mod, modMultiplier); m_spreadParams.speed_holdBreathActive_m = CalculateParamModValue(originalSpreadParams.speed_holdBreathActive_m, spreadMod.speed_holdBreathActive_m_mod, modMultiplier); m_spreadParams.spread_crouch_m = CalculateParamModValue(originalSpreadParams.spread_crouch_m, spreadMod.spread_crouch_m_mod, modMultiplier); m_spreadParams.spread_jump_m = CalculateParamModValue(originalSpreadParams.spread_jump_m, spreadMod.spread_jump_m_mod, modMultiplier); m_spreadParams.spread_slide_m = CalculateParamModValue(originalSpreadParams.spread_slide_m, spreadMod.spread_slide_m_mod, modMultiplier); m_spreadParams.spread_holdBreathActive_m = CalculateParamModValue(originalSpreadParams.spread_holdBreathActive_m, spreadMod.spread_holdBreathActive_m_mod, modMultiplier); float oldSpreadRange = oldSpreadMax-oldSpreadMin; if(oldSpreadRange) { float inverseOldSpreadRange = __fres(oldSpreadRange); float ratio = ((m_spread-oldSpreadMin) * inverseOldSpreadRange); m_spread = m_spreadParams.min + (m_spreadParams.max-m_spreadParams.min) * ratio; } else { m_spread = m_spreadParams.min; } m_useSpreadMultiplier = false; }
void CWeapon::EndVerificationSample(IActor * pActor, uint32 oldShotId) { if(m_fSampleNumShots > 1.0f) //This check needs to be here as some calls will call this directly { // without calling ShouldEndVerificationSample() const float fSampleStartTime = m_fSampleStartTime; const INetChannel* pNetChannel = gEnv->pGame->GetIGameFramework()->GetNetChannel(pActor->GetChannelId()); const float fNetLag = ((pActor->IsClient() || !pNetChannel) ? 0 : (pNetChannel->GetPing(true))); // GetPing() is the round journey but we're giving some leeway //work out how long the sample covered. //TODO: Work out if we need latency compensation here? const float kServerFrameTime = gEnv->pTimer->GetFrameTime(); const float kAdditionalFudge = (kServerFrameTime * 2.0f) + (fNetLag * 2.0f); //Generously assume that their ping could spike significantly const float fActualSampleLength = (m_fLastSampleTakenTime - fSampleStartTime) + kAdditionalFudge; const float fFireRate = m_fSampleNumShots / fActualSampleLength; const int kCurrentFireModeIdx = (oldShotId & CWeapon::GetShotIdFireModeMask()) >> CWeapon::GetShotIdFireModeOffset(); CFireMode * pFireMode = static_cast<CFireMode*>(GetFireMode(kCurrentFireModeIdx)); if(pFireMode) { //Fire rate is in shots per minute, convert to shots per second float fMaxFireRate = pFireMode->GetFireRate() * ( 1.0f / 60.0f ); if(pActor->IsPlayer()) { fMaxFireRate *= __fres(pFireMode->GetTimeBetweenShotsMultiplier(static_cast<CPlayer*>(pActor))); } if(fFireRate > fMaxFireRate) { g_pGame->GetAntiCheatManager()->FlagActivity(eCT_FireRate, pActor->GetChannelId(), fFireRate / fMaxFireRate, GetEntity()->GetName()); } } } }
//--------------------------------------------------------------- void CPlayerRotation::ProcessNormalRoll( float frameTime ) { //apply lean/roll float rollAngleGoal(0); const Vec3 velocity = m_player.GetActorPhysics().velocity; const float speed2( velocity.len2()); if ((speed2 > 0.01f) && m_player.m_stats.inAir) { const float maxSpeed = m_player.GetStanceMaxSpeed(STANCE_STAND); const float maxSpeedInverse = (float)__fsel(-maxSpeed, 1.0f, __fres(maxSpeed + FLT_EPSILON)); const Vec3 velVec = velocity * maxSpeedInverse; const float dotSide(m_viewQuat.GetColumn0() * velVec); rollAngleGoal -= DEG2RAD(dotSide * 1.5f);; } const float tempLean = m_leanAmount; const float leanAmountMultiplier = 3.0f; const float leanAmount = clamp_tpl(tempLean * leanAmountMultiplier, -1.0f, 1.0f); rollAngleGoal += DEG2RAD(leanAmount * m_player.m_params.leanAngle); Interpolate(m_viewRoll,rollAngleGoal,9.9f,frameTime); m_deltaAngles += m_angularImpulseDelta; }
void CPlayerRotation::ProcessForcedLookDirection( const Quat& lastViewQuat, float frameTime ) { const float forceLookLenSqr(m_forceLookVector.len2()); if (forceLookLenSqr < 0.001f) return; const float forceLookLen(sqrt_tpl(forceLookLenSqr)); Vec3 forceLook(m_forceLookVector); forceLook *= (float)__fres(forceLookLen); forceLook = lastViewQuat.GetInverted() * forceLook; const float smoothSpeed(6.6f * forceLookLen); float blendAmount = min(1.0f,frameTime*smoothSpeed); if(!m_bForcedLookAtBlendingEnabled) { blendAmount = 1.0f; } m_deltaAngles.x += asinf(forceLook.z) * blendAmount; m_deltaAngles.z += atan2_tpl(-forceLook.x,forceLook.y) * blendAmount; PR_CHECKQNAN_VEC(m_deltaAngles); }
float CGameRulesRSSpawning::GetScoreFromProximityToEnemies( SUsefulSpawnData& spawnData, TPositionList& EnemyPlayerPositions, const Vec3& potentialSpawnPosition ) { SpawnLogAlways("[SPAWN] > GetScoreFromProximityToEnemies()"); float fScoreFromEnemies = 0.0f; if(spawnData.numActiveEnemyPlayers > 0) { const float fScoreOnTopOfEnemy = 200.0f; const float fMultiplierForEnemyDistance = 1.7f; const float fDistanceScoreMultiplier = 200.0f; for(int i = EnemyPlayerPositions.size() - 1; i >= 0; i--) { Vec3 vDiffToEnemy = (EnemyPlayerPositions[i] - potentialSpawnPosition); vDiffToEnemy.z += max(2.0f * vDiffToEnemy.z, 6.0f); float fDistanceFromEnemy = vDiffToEnemy.len(); float fDistanceScoreFraction = __fres(max(fDistanceFromEnemy - 4.f, 0.001f)); float fScoreForThisEnemy = max(fScoreOnTopOfEnemy - (fDistanceFromEnemy * fMultiplierForEnemyDistance), 0.0f) + (fDistanceScoreFraction * fDistanceScoreMultiplier); SpawnLogAlways("[SPAWN] >>> Score from Enemy %d is %.6f at distance %.1f", i, fScoreForThisEnemy, fDistanceFromEnemy); fScoreFromEnemies = max(fScoreForThisEnemy, fScoreFromEnemies); } SpawnLogAlways("[SPAWN] >> Total Score from Enemies: %.6f", fScoreFromEnemies); } return fScoreFromEnemies; }
//////////////////////////////////////////////// // This is currently identical to the GetEnemyTeamCentre function, // but functionality will change in the future void CGameRulesRSSpawning::GetFriendlyTeamCentre( SUsefulSpawnData& spawnData, Vec3 * pOutCentre ) { int idx = 0; EntityId friendlyPlayerId = 0; float fNumFriendlies = 0.0f; Vec3 pureAveragePosition(0.0f, 0.0f, 0.0f); while( friendlyPlayerId = m_pGameRules->GetTeamActivePlayer(spawnData.playerTeamId, idx++)) { fNumFriendlies += 1.0f; const IEntity * pFriendlyPlayer = gEnv->pEntitySystem->GetEntity(friendlyPlayerId); Vec3 friendlyPosition = pFriendlyPlayer->GetPos(); float fInvNumFriendlies = __fres(fNumFriendlies); float fCurrentPositionWeighting = 1.0f - fInvNumFriendlies; //This is slightly more computationally expensive than adding them all up, but // avoids the potential for some float precision problems pureAveragePosition = (pureAveragePosition * fCurrentPositionWeighting) + (fInvNumFriendlies * friendlyPosition); } *pOutCentre = pureAveragePosition; }
void EntityEffects::CHeatController::AddHeatPulse( const float intensity, const float time ) { const float currentPulseHeat = (float)__fsel(-m_heatPulse.baseTime, 0.0f, clamp((1.0f - (m_heatPulse.runningTime * (float)__fres(m_heatPulse.baseTime + FLT_EPSILON))) * m_heatPulse.heat, 0.0f, 1.0f)); m_heatPulse.heat = clamp(currentPulseHeat + intensity, 0.0f, 1.0f - m_baseHeat); m_heatPulse.baseTime = clamp((m_heatPulse.baseTime - m_heatPulse.runningTime) + time, 0.0f, 4.5f); //Fixed to maximum of 4.5secs to cool down m_heatPulse.runningTime = 0.0f; }
void CPlayerStateJump::FinalizeVelocity( CPlayer& player, const Vec3& newVelocity ) { const float fNewSpeed = newVelocity.len(); const float fVelocityMultiplier = (float)__fsel(fNewSpeed - 22.0f, __fres(fNewSpeed+FLT_EPSILON) * 22.0f, 1.0f); // TODO: Maybe we should tell physics about this new velocity ? Or maybe SPlayerStats::velocity ? (stephenn). player.GetMoveRequest().velocity = newVelocity * fVelocityMultiplier; }
void Update(IEntity &entity, float timePassed) { if (m_invalid) return; QuatT applyingDelta(IDENTITY); const float newTime = min(m_lastTime + timePassed, m_targetTime); const float deltaTime = newTime - m_lastTime; if (deltaTime > 0.0f) { Quat totalDeltaRot, lastTotalDeltaRot; const float targetTimeInverse = (float)__fres(m_targetTime); const float dt = deltaTime * targetTimeInverse; const float t = newTime * targetTimeInverse; const float lastT = m_lastTime * targetTimeInverse; totalDeltaRot.SetSlerp(Quat(IDENTITY), m_deltaRot, t); lastTotalDeltaRot.SetSlerp(Quat(IDENTITY), m_deltaRot, lastT); applyingDelta.q = (!lastTotalDeltaRot * totalDeltaRot); applyingDelta.t = (m_delta * dt); m_lastTime = newTime; } else if (m_targetTime == 0.f) { applyingDelta.t = m_delta; applyingDelta.q = m_deltaRot; m_invalid = true; } //CryLog("Moving %s from (%f, %f, %f) to (%f, %f, %f) delta (%f, %f, %f) timeDelta: %f time: %f timeTgt: %f", // entity.GetName(), // entity.GetPos().x, entity.GetPos().y, entity.GetPos().z, // (entity.GetPos()+applyingDelta.t).x, (entity.GetPos()+applyingDelta.t).y, (entity.GetPos()+applyingDelta.t).z, // applyingDelta.t.x, applyingDelta.t.y, applyingDelta.t.z, // deltaTime, newTime, m_targetTime); if (m_pAnimatedCharacter) { m_pAnimatedCharacter->ForceMovement(applyingDelta); } else { if (IEntity* pParent = entity.GetParent()) applyingDelta.t = !pParent->GetRotation() * applyingDelta.t; entity.SetPosRotScale(entity.GetPos() + applyingDelta.t, entity.GetRotation() * applyingDelta.q, entity.GetScale()); } }
void CGameRulesRSSpawning::UpdateSpawnPointAverage(const EntityId spawnId, float& fNumSpawns, Vec3& averagePos) const { fNumSpawns += 1.0f; const IEntity *pSpawn = gEnv->pEntitySystem->GetEntity(spawnId); Vec3 spawnPosition = pSpawn->GetPos(); float fInvNumSpawns = __fres(fNumSpawns); float fScaleRemainder = 1.0f - fInvNumSpawns; averagePos = (spawnPosition * fInvNumSpawns) + (averagePos * fScaleRemainder); }
void CPlayerRotation::ProcessAngularImpulses( float frameTime ) { //update angular impulse if (m_angularImpulseTime>0.001f) { m_angularImpulse *= min(m_angularImpulseTime * __fres(m_angularImpulseTimeMax), 1.0f); m_angularImpulseTime -= frameTime; } else if (m_angularImpulseDeceleration>0.001f) { Interpolate(m_angularImpulse,ZERO,m_angularImpulseDeceleration, frameTime); } m_angularImpulseDelta -= m_angularImpulse; }
void CPlayerRotation::ProcessLeanAndPeek( const SActorFrameMovementParams& movement ) { const float leanAmt = (float)__fsel(0.01f - fabsf(movement.desiredLean), 0.0f, movement.desiredLean); m_leanAmount = leanAmt; //check if its possible if ((leanAmt*leanAmt) < 0.01f) { m_leanAndPeekInfo.Reset(); //Clear any previous result } else { const EStance stance = m_player.GetStance(); const float noLean(0.0f); const Vec3 playerPosition = m_player.GetEntity()->GetWorldPos(); const Vec3 headPos(playerPosition + m_baseQuat * m_player.GetStanceViewOffset(stance,&noLean)); const Vec3 newPos(playerPosition + m_baseQuat * m_player.GetStanceViewOffset(stance,&m_leanAmount)); /*gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(headPos, 0.05f, ColorB(0,0,255,255) ); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(newPos, 0.05f, ColorB(0,0,255,255) ); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(headPos, ColorB(0,0,255,255), newPos, ColorB(0,0,255,255));*/ const int rayFlags(rwi_stop_at_pierceable|rwi_colltype_any); IPhysicalEntity *pSkip(m_player.GetEntity()->GetPhysics()); const float distMult(3.0f); const float distMultInv(1.0f/distMult); const Vec3& limitPoint = m_leanAndPeekInfo.GetLeanLimit(headPos + m_viewQuat.GetColumn1() * 0.25f, (newPos - headPos)*distMult, ent_terrain|ent_static|ent_rigid|ent_sleeping_rigid, rayFlags, &pSkip, pSkip ? 1 : 0); const bool validHit = (!limitPoint.IsZero()); if (validHit) { const float dist((headPos - newPos).len2() * distMult); const float invDist = dist>0.f ? __fres(dist) : 0.f; m_leanAmount *= ((limitPoint - headPos).len2() * invDist * distMultInv); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(hit.pt, 0.05f, ColorB(0,255,0,255) ); } } // TODO(Márcio): Maybe do some checks here! m_peekOverAmount = movement.desiredPeekOver; }
void CDeferredExplosionEffect::TriggerRadialBlur( const Vec3& radialBlurCenter, float maxBlurDistance, float distance ) { CRY_ASSERT(maxBlurDistance > 0.0f); const float maxBlurDistanceInv = __fres(maxBlurDistance); if(CScreenEffects* pScreenFX = g_pGame->GetScreenEffects()) { const float blurRadius = (-maxBlurDistanceInv * distance) + 1.0f; pScreenFX->ProcessExplosionEffect(blurRadius, radialBlurCenter); } const float distAmp = 1.0f - (distance * maxBlurDistanceInv); IForceFeedbackSystem* pForceFeedback = g_pGame->GetIGameFramework()->GetIForceFeedbackSystem(); const ForceFeedbackFxId effectId = pForceFeedback->GetEffectIdByName("explosion"); SForceFeedbackRuntimeParams ffParams(distAmp * 3.0f, 0.0f); pForceFeedback->PlayForceFeedbackEffect(effectId, ffParams); }
float EntityEffects::CHeatController::UpdateHeat( const float frameTime ) { m_heatPulse.runningTime += frameTime; const float pulseFraction = clamp(m_heatPulse.runningTime * (float)__fres(m_heatPulse.baseTime), 0.0f, 1.0f); const bool pulseActive = (pulseFraction < 1.0f); float pulseHeat = 0.0f; if (pulseActive) { pulseHeat = (m_heatPulse.heat * (1.0f - pulseFraction)); } else { m_heatPulse.Reset(); } return clamp(m_baseHeat + pulseHeat, 0.0f, 1.0f); }
float CGameRulesRSSpawning::GetScoreFromProximityToEnemiesNoTeams( SUsefulSpawnData& spawnData, const Vec3& potentialSpawnPosition ) { SpawnLogAlways("[SPAWN] > GetScoreFromProximityToEnemiesNoTeams()"); float fScoreFromEnemies = 0.0f; CGameRules::TPlayers players; g_pGame->GetGameRules()->GetPlayers(players); if(players.size() > 1) { const float fScoreOnTopOfEnemy = 200.0f; const float fMultiplierForEnemyDistance = 1.7f; const float fDistanceScoreMultiplier = 200.0f; int i = -1; for(CGameRules::TPlayers::iterator it=players.begin();it!=players.end();++it) { i++; if(*it == spawnData.playerId) continue; const IEntity *pOther = gEnv->pEntitySystem->GetEntity(*it); Vec3 vDiffToEnemy = (pOther->GetWorldPos() - potentialSpawnPosition); vDiffToEnemy.z += max(2.0f * vDiffToEnemy.z, 6.0f); float fDistanceFromEnemy = vDiffToEnemy.len(); float fDistanceScoreFraction = __fres(max(fDistanceFromEnemy - 4.f, 0.001f)); float fScoreForThisEnemy = max(fScoreOnTopOfEnemy - (fDistanceFromEnemy * fMultiplierForEnemyDistance), 0.0f) + (fDistanceScoreFraction * fDistanceScoreMultiplier); SpawnLogAlways("[SPAWN] >>> Score from Enemy %d is %.6f at distance %.1f", i, fScoreForThisEnemy, fDistanceFromEnemy); fScoreFromEnemies = max(fScoreForThisEnemy, fScoreFromEnemies); } SpawnLogAlways("[SPAWN] >> Total Score from Enemies: %.6f", fScoreFromEnemies); } return fScoreFromEnemies; }
void CGameRulesRSSpawning::GetEnemyTeamCentre( SUsefulSpawnData& spawnData, Vec3 * pOutCentre ) { //This is now a blueprint for switching over the other functions to use the CActorManager. // They are not being switched over now because there are more significant changes in MPTrunk // that further changes would conflict with - Rich S int idx = 0; EntityId enemyPlayerId = 0; float fNumEnemies = 0.0f; Vec3 pureAveragePosition(0.0f, 0.0f, 0.0f); CActorManager * pActorManager = CActorManager::GetActorManager(); pActorManager->PrepareForIteration(); const int kNumActors = pActorManager->GetNumActors(); for(int i = 0; i < kNumActors; i++) { SActorData actorData; pActorManager->GetNthActorData(i, actorData); if(actorData.teamId == spawnData.enemyTeamId && actorData.spectatorMode == CActor::eASM_None) { fNumEnemies += 1.0f; float fInvNumEnemies = __fres(fNumEnemies); float fCurrentPositionWeighting = 1.0f - fInvNumEnemies; //This is slightly more computationally expensive than adding them all up, but // avoids the potential for some float precision problems pureAveragePosition = (pureAveragePosition * fCurrentPositionWeighting) + (fInvNumEnemies * actorData.position); } } *pOutCentre = pureAveragePosition; }
void CRecoil::UpdateRecoil(float recoilScale, float maxRecoil, bool weaponFired, bool weaponFiring, float frameTime) { if (m_recoil_time > 0.0f) { m_recoil_time -= frameTime; m_recoil += (m_attack * frameTime) / m_recoilParams.recoil_time; } const bool isFiring = m_singleShot ? weaponFired : weaponFiring; const float decay = isFiring ? m_recoilParams.decay : m_recoilParams.end_decay; const float frameDecay = (float)__fsel(-decay, 0.0f, frameTime * recoilScale * maxRecoil * __fres(decay+FLT_EPSILON)); m_recoil = clamp(m_recoil - frameDecay, 0.0f, maxRecoil); const float t = (float)__fsel(-maxRecoil, 0.0f, m_recoil * __fres(maxRecoil+FLT_EPSILON)); const Vec3 new_offset = Vec3( m_recoil_dir.x * sin_tpl(DEG2RAD(m_recoilParams.max.x)), m_recoil_dir.y * sin_tpl(DEG2RAD(m_recoilParams.max.y)), m_recoil_dir.z) * t; m_recoil_offset = (new_offset * 0.66f) + (m_recoil_offset * 0.33f); CRecoilDebugDraw::DebugRecoil(t, m_recoil_offset); }
CForceFeedBackSystem::SFFOutput CForceFeedBackSystem::SActiveEffect::Update( float frameTime ) { SFFOutput effectFF; bool canPlay = (runtimeParams.delay <= 0.0f); if (canPlay) { bool isLoopingEffect = (effectTime <= 0.0f); const float effectTimeInv = !isLoopingEffect ? (float)__fres(effectTime) : 1.0f; const float sampleTime = runningTime * effectTimeInv; const float sampleTimeAAtFreq = sampleTime * frequencyA; const float sampleTimeAAtFreqNorm = clamp_tpl(sampleTimeAAtFreq - floor_tpl(sampleTimeAAtFreq), 0.0f, 1.0f); const float sampleTimeBAtFreq = sampleTime * frequencyB; const float sampleTimeBAtFreqNorm = clamp_tpl(sampleTimeBAtFreq - floor_tpl(sampleTimeBAtFreq), 0.0f, 1.0f); effectFF.forceFeedbackA = m_patternA.SamplePattern(sampleTimeAAtFreqNorm) * m_envelopeA.SampleEnvelope(sampleTime) * runtimeParams.intensity; effectFF.forceFeedbackB = m_patternB.SamplePattern(sampleTimeBAtFreqNorm) * m_envelopeB.SampleEnvelope(sampleTime) * runtimeParams.intensity; runningTime += frameTime; //Re-start the loop if (isLoopingEffect) { runningTime = (float)__fsel(1.0f - runningTime, runningTime, 0.0f); } } else { runtimeParams.delay = clamp_tpl(runtimeParams.delay - frameTime, 0.0f, runtimeParams.delay); } return effectFF; }
//------------------------------------------------------------------------ void CRapid::Update(float frameTime, uint32 frameId) { FUNCTION_PROFILER( GetISystem(), PROFILE_GAME ); PlayStopRapidFireIfNeeded(); BaseClass::Update(frameTime, frameId); if (m_speed <= 0.0f && m_acceleration < 0.0001f) { FinishDeceleration(); return; } CActor* pOwnerActor = m_pWeapon->GetOwnerActor(); const bool isOwnerClient = pOwnerActor ? pOwnerActor->IsClient() : false; const bool isOwnerPlayer = pOwnerActor ? pOwnerActor->IsPlayer() : false; m_pWeapon->RequireUpdate(eIUS_FireMode); m_speed = m_speed + m_acceleration*frameTime; if (m_speed > m_fireParams->rapidparams.max_speed) { m_speed = m_fireParams->rapidparams.max_speed; m_rapidFlags &= ~eRapidFlag_accelerating; } if ((m_speed >= m_fireParams->rapidparams.min_speed) && !(m_rapidFlags & eRapidFlag_decelerating)) { float dt = 1.0f; if (cry_fabsf(m_speed)>0.001f && cry_fabsf(m_fireParams->rapidparams.max_speed)>0.001f) { dt = m_speed * (float)__fres(m_fireParams->rapidparams.max_speed); } CRY_ASSERT(m_fireParams->fireparams.rate > 0); m_next_shot_dt = 60.0f* (float)__fres((m_fireParams->fireparams.rate*dt)); if (CanFire(false)) { if (!OutOfAmmo()) { const bool firing = (m_rapidFlags & eRapidFlag_netShooting) || Shoot(true, m_fireParams->fireparams.autoReload); Firing(firing); } else { StopFire(); } } } else if (m_firing) { StopFire(); if (OutOfAmmo() && isOwnerPlayer) { m_pWeapon->Reload(); } } if ((m_speed < m_fireParams->rapidparams.min_speed) && (m_acceleration < 0.0f) && !(m_rapidFlags & eRapidFlag_decelerating)) Accelerate(m_fireParams->rapidparams.deceleration); UpdateRotation(frameTime); UpdateFiring(pOwnerActor, isOwnerClient, isOwnerPlayer, frameTime); }
void CPlayerStateUtil::ApplyFallDamage( CPlayer& player, const float startFallingHeight, const float fHeightofEntity ) { CRY_ASSERT(player.IsClient()); // Zero downwards impact velocity used for fall damage calculations if player was in water within the last 0.5 seconds. // Strength jumping straight up and down should theoretically land with a safe velocity, // but together with the water surface stickyness the velocity can sometimes go above the safe impact velocity threshold. // DEPRECATED: comment left for prosterity in case dedicated server problems re-appear (author cannot test it). // On dedicated server the player can still be flying this frame as well, // since synced pos from client is interpolated/smoothed and will not land immediately, // even though the velocity is set to zero. // Thus we need to use the velocity change instead of landing to identify impact. // DT: 12475: Falling a huge distance to a ledge grab results in no damage. // Now using the last velocity because when ledge grabbing the velocity is unchanged for this frame, thus zero damage is applied. // Assuming this a physics lag issue, using the last good velocity should be more-or-less ok. const float downwardsImpactSpeed = -(float)__fsel(-(player.m_playerStateSwim_WaterTestProxy.GetSwimmingTimer() + 0.5f), player.GetActorPhysics().velocityUnconstrainedLast.z, 0.0f); const SPlayerStats& stats = *player.GetActorStats(); CRY_ASSERT(NumberValid(downwardsImpactSpeed)); const float MIN_FALL_DAMAGE_DISTANCE = 3.0f; const float fallDist = startFallingHeight - fHeightofEntity; if ((downwardsImpactSpeed > 0.0f) && (fallDist > MIN_FALL_DAMAGE_DISTANCE)) { const SPlayerHealth& healthCVars = g_pGameCVars->pl_health; float velSafe = healthCVars.fallDamage_SpeedSafe; float velFatal = healthCVars.fallDamage_SpeedFatal; float velFraction = (float)__fsel(-(velFatal - velSafe), 1.0f , (downwardsImpactSpeed - velSafe) * (float)__fres(velFatal - velSafe)); CRY_ASSERT(NumberValid(velFraction)); if (velFraction > 0.0f) { //Stop crouching after taking falling damage if(player.GetStance() == STANCE_CROUCH) { static_cast<CPlayerInput*>(player.GetPlayerInput())->ClearCrouchAction(); } velFraction = powf(velFraction, gEnv->bMultiplayer ? healthCVars.fallDamage_CurveAttackMP : healthCVars.fallDamage_CurveAttack); const float maxHealth = player.GetMaxHealth(); const float currentHealth = player.GetHealth(); HitInfo hit; hit.dir.zero(); hit.type = CGameRules::EHitType::Fall; hit.shooterId = hit.targetId = hit.weaponId = player.GetEntityId(); const float maxDamage = (float)__fsel(velFraction - 1.0f, maxHealth, max(0.0f, (gEnv->bMultiplayer?maxHealth:currentHealth) - healthCVars.fallDamage_health_threshold)); hit.damage = velFraction * maxDamage; g_pGame->GetGameRules()->ClientHit(hit); #ifdef PLAYER_MOVEMENT_DEBUG_ENABLED player.GetMovementDebug().LogFallDamage(player.GetEntity(), velFraction, downwardsImpactSpeed, hit.damage); } else { player.GetMovementDebug().LogFallDamageNone(player.GetEntity(), downwardsImpactSpeed); } #else } #endif }
void CPlayerPlugin_InteractiveEntityMonitor::Update( const float dt ) { m_timeUntilRefresh -= dt; #ifndef _RELEASE //Verify entity integrity InteractiveEntityDebugMap::iterator mapIter = m_debugMap.begin(); InteractiveEntityDebugMap::iterator mapEnd = m_debugMap.end(); while(mapIter != mapEnd) { if(!gEnv->pEntitySystem->GetEntity(mapIter->first)) { CryLog("[ERROR] InteractiveEntityMonitor. About to crash. Registered entity no longer exists: '%s'. Tell Gary (Really this time).", mapIter->second.c_str()); DesignerWarning(false, "[ERROR] InteractiveEntityMonitor. About to crash. Registered entity no longer exists: '%s'. Tell Gary (Really this time).", mapIter->second.c_str()); } ++mapIter; } #endif //_RELEASE IEntitySystem* pEntitySys = gEnv->pEntitySystem; const Vec3& playerPos = GetOwnerPlayer()->GetEntity()->GetWorldTM().GetColumn3(); if(m_bEnabled && (m_timeUntilRefresh < 0.f || playerPos.GetSquaredDistance2D(m_playerPrevPos) > g_pGameCVars->g_highlightingMovementDistanceToUpdateSquared)) { for(InteractiveEntityList::iterator it = m_interactiveEntityList.begin(); it!=m_interactiveEntityList.end(); ) { const EntityId entityId = it->first; IEntity* pEntity = pEntitySys->GetEntity(entityId); if(!pEntity) { it=m_interactiveEntityList.erase(it); continue; } if (IEntityRenderProxy* pRenderProxy = static_cast<IEntityRenderProxy *>(pEntity->GetProxy(ENTITY_PROXY_RENDER))) { const Vec3& entityPos = pEntity->GetWorldTM().GetColumn3(); const float distSq = entityPos.GetSquaredDistance2D(playerPos); const bool withinHighlightDistance = distSq <= g_pGameCVars->g_highlightingMaxDistanceToHighlightSquared; if( withinHighlightDistance ) { // Apply intensity fade over outer half distance float alpha = distSq * 2.0f - g_pGameCVars->g_highlightingMaxDistanceToHighlightSquared; alpha *= __fres(g_pGameCVars->g_highlightingMaxDistanceToHighlightSquared); alpha = 1.0f - clamp(alpha, 0.0f, 1.0f); if( (it->second & EIES_ShootToInteract) == 0 ) { pRenderProxy->SetHUDSilhouettesParams(m_silhouetteInteractColor.r*alpha, m_silhouetteInteractColor.g*alpha, m_silhouetteInteractColor.b*alpha, m_silhouetteInteractColor.a*alpha); } else { pRenderProxy->SetHUDSilhouettesParams(m_silhouetteShootColor.r*alpha, m_silhouetteShootColor.g*alpha, m_silhouetteShootColor.b*alpha, m_silhouetteShootColor.a*alpha); } it->second |= EIES_Highlighted; } else if( it->second & EIES_Highlighted ) { pRenderProxy->SetHUDSilhouettesParams(0.f, 0.f, 0.f, 0.f); it->second &= ~EIES_Highlighted; } } ++it; } m_playerPrevPos = playerPos; m_timeUntilRefresh = g_pGameCVars->g_highlightingTimeBetweenForcedRefresh; } }
bool CXInputDevice::SetVibration(USHORT leftMotor, USHORT rightMotor, float timing, EFFEffectId effectId) { //if(g_bConnected[m_deviceNo]) if (m_connected) { USHORT desiredVibrationLeft = 0; USHORT desiredVibrationRight = 0; if (effectId == eFF_Rumble_Basic) { const float now = gEnv->pTimer->GetFrameStartTime().GetSeconds(); if (m_fVibrationTimer > 0.0f) { const float oldRumbleRatio = (float)__fsel(-timing, 1.0f, min(1.0f, (fabsf(m_fVibrationTimer - now) * (float)__fres((timing + FLT_EPSILON))))); //Store only 'basic', without frame part m_basicLeftMotorRumble = max(leftMotor, (USHORT)(m_basicLeftMotorRumble * oldRumbleRatio)); m_basicRightMotorRumble = max(rightMotor, (USHORT)(m_basicRightMotorRumble * oldRumbleRatio)); const float newLeftMotor = GetClampedLeftMotorAccumulatedVibration() * oldRumbleRatio; const float newRightMotor = GetClampedRightMotorAccumulatedVibration() * oldRumbleRatio; desiredVibrationLeft = max(leftMotor, (USHORT)newLeftMotor); desiredVibrationRight = max(rightMotor, (USHORT)newRightMotor); } else { m_basicLeftMotorRumble = leftMotor; m_basicRightMotorRumble = rightMotor; desiredVibrationLeft = max(leftMotor, (USHORT)GetClampedLeftMotorAccumulatedVibration() ); desiredVibrationRight = max(rightMotor, (USHORT)GetClampedRightMotorAccumulatedVibration()); } m_fVibrationTimer = (float)__fsel(-timing, 0.0f, now + timing); } else if (effectId == eFF_Rumble_Frame) { m_frameLeftMotorRumble = leftMotor; m_frameRightMotorRumble = rightMotor; desiredVibrationLeft = (USHORT)GetClampedLeftMotorAccumulatedVibration(); desiredVibrationRight = (USHORT)GetClampedRightMotorAccumulatedVibration(); } if( m_currentVibrationSettings.wLeftMotorSpeed != desiredVibrationLeft || m_currentVibrationSettings.wRightMotorSpeed != desiredVibrationRight ) { XINPUT_VIBRATION vibration; ZeroMemory( &vibration, sizeof(XINPUT_VIBRATION) ); vibration.wLeftMotorSpeed = desiredVibrationLeft; vibration.wRightMotorSpeed = desiredVibrationRight; DWORD error = XInputSetState( m_deviceNo, &vibration ); if(error == ERROR_SUCCESS) { m_currentVibrationSettings.wLeftMotorSpeed = desiredVibrationLeft; m_currentVibrationSettings.wRightMotorSpeed = desiredVibrationRight; } } return true; } return false; }
void CSmokeManager::UpdateSmokeInstance(SSmokeInstance& smokeInstance, float dt) { IEntity * pGrenade = gEnv->pEntitySystem->GetEntity(smokeInstance.grenadeId); CullOtherSmokeEffectsInProximityWhenGrenadeHasLanded(smokeInstance,pGrenade); if(pGrenade) { //Update the radius of the smoke according to the speed of movement, // it should reduce to nothing when moving fast enough, and should increase // when the grenade is stationary Vec3 vNewPosition = pGrenade->GetPos(); Vec3 vPositionDiff = vNewPosition - smokeInstance.vPositon; const float fDistanceTravelled = vPositionDiff.len(); const float fSpeed = fDistanceTravelled * __fres(dt); const float fNewRadius = smokeInstance.fCurrentRadius + (float)__fsel( smokeInstance.fTimer-kInitialDelay, ((kSmokeRadiusIncrease - fSpeed) * dt), 0.0f); smokeInstance.fCurrentRadius = clamp(fNewRadius, 0.0f, kMaxSmokeRadius); // If grenade on ground, then override its timer to be maximum of kMaxPhysicsSleepTime if((smokeInstance.state == eSIS_Active_PhysicsAsleep) && (smokeInstance.fTimer < kInitialDelay-kMaxPhysicsSleepTime)) { smokeInstance.fTimer = kInitialDelay-kMaxPhysicsSleepTime; } const float previousTimer = smokeInstance.fTimer; smokeInstance.fTimer = smokeInstance.fTimer + dt; if(previousTimer < kInitialDelay && smokeInstance.fTimer >= kInitialDelay) { // Spawn explosion particle effect if (m_pExplosionParticleEffect) { m_pExplosionParticleEffect->Spawn(false,IParticleEffect::ParticleLoc(vNewPosition)); } // Spawn smoke particle effect // Find a free slot on the grenade SEntitySlotInfo dummySlotInfo; int i=0; while (pGrenade->GetSlotInfo(i, dummySlotInfo)) { i++; } if (m_pOutsideSmokeParticleEffect) { pGrenade->LoadParticleEmitter(i, m_pOutsideSmokeParticleEffect); IParticleEmitter* pEmitter = pGrenade->GetParticleEmitter(i); if(pEmitter) { SpawnParams spawnParams; pEmitter->GetSpawnParams(spawnParams); pEmitter->SetSpawnParams(spawnParams); } } } //Update the smoke's position smokeInstance.vPositon = vNewPosition; if (smokeInstance.pObstructObject) { pe_params_pos pos; pos.scale = clamp(smokeInstance.fCurrentRadius * __fres(kMaxSmokeRadius), 0.1f, 1.0f); pos.pos = vNewPosition; smokeInstance.pObstructObject->SetParams(&pos); } } else { //The grenade entity has been deleted, so smoke has stopped being produced if(smokeInstance.fTimer > kSmokeEmitEndTime) { //The smoke has cleared, delete the SmokeInstance smokeInstance.state = eSIS_ForDeletion; } else { //Count down the remaining life, and reduce the radius smokeInstance.fTimer += dt; smokeInstance.fCurrentRadius = max(smokeInstance.fCurrentRadius - (dt * kMaxSmokeRadius / kSmokeLingerTime), 0.0f); if (smokeInstance.pObstructObject) { pe_params_pos pos; pos.scale = clamp(smokeInstance.fCurrentRadius * __fres(kMaxSmokeRadius), 0.1f, 1.0f); smokeInstance.pObstructObject->SetParams(&pos); } } } }
void CWeapon::NetUpdateFireMode(SEntityUpdateContext& ctx) { // CGunTurret and CVehicleWeapon overide NetAllowUpdate to perform their own checks. if(NetAllowUpdate(true)) { m_netNextShot -= ctx.fFrameTime; if(IsReloading()) return; // reloading, bail if((!m_isFiringStarted) && (m_isFiring || m_shootCounter > 0)) { m_isFiringStarted = true; m_netNextShot = 0.f; NetStartFire(); EnableUpdate(true, eIUS_FireMode); } if(m_fm) { if(m_shootCounter > 0 && m_netNextShot <= 0.0f) { // Aside from the prediction handle, needed for the server, NetShoot/Ex parameters // are no longer used, these will need removing when the client->server RMI's are tided up m_fm->NetShoot(Vec3(0.f, 0.f, 0.f), 0); m_shootCounter--; //if fireRate == 0.0f, set m_netNextShot to 0.0f, otherwise increment by 60.f / fireRate. // fres used to avoid microcoded instructions, fsel to avoid branching - Rich S const float fRawFireRate = m_fm->GetFireRate(); const float fFireRateSelect = -fabsf(fRawFireRate); const float fFireRateForDiv = (float)__fsel(fFireRateSelect, 1.0f, fRawFireRate); const float fNextShot = (float)__fsel(fFireRateSelect, 0.0f, m_netNextShot + (60.f * __fres(fFireRateForDiv))); m_netNextShot = fNextShot; } } if(m_isFiringStarted && !m_isFiring && m_shootCounter <= 0) { m_isFiringStarted = false; NetStopFire(); EnableUpdate(false, eIUS_FireMode); } // this needs to happen here, or NetStopFire interrupts the animation if(m_doMelee && m_melee) { m_melee->NetAttack(); m_doMelee= false; } } }
void CMountedGunController::Update(EntityId mountedGunID, float frameTime) { CRY_ASSERT_MESSAGE(m_pControlledPlayer, "Controlled player not initialized"); CItem* pMountedGun = static_cast<CItem*>(gEnv->pGame->GetIGameFramework()->GetIItemSystem()->GetItem(mountedGunID)); bool canUpdateMountedGun = (pMountedGun != NULL) && (pMountedGun->GetStats().mounted); if (canUpdateMountedGun) { IMovementController * pMovementController = m_pControlledPlayer->GetMovementController(); assert(pMovementController); SMovementState info; pMovementController->GetMovementState(info); IEntity* pMountedGunEntity = pMountedGun->GetEntity(); const Matrix34& lastMountedGunWorldTM = pMountedGunEntity->GetWorldTM(); Vec3 desiredAimDirection = info.aimDirection.GetNormalized(); // AI can switch directions too fast, prevent snapping if(!m_pControlledPlayer->IsPlayer()) { const Vec3 currentDir = lastMountedGunWorldTM.GetColumn1(); const float dot = clamp(currentDir.Dot(desiredAimDirection), -1.0f, 1.0f); const float reqAngle = cry_acosf(dot); const float maxRotSpeed = 2.0f; const float maxAngle = frameTime * maxRotSpeed; if(fabs(reqAngle) > maxAngle) { const Vec3 axis = currentDir.Cross(desiredAimDirection); if(axis.GetLengthSquared() > 0.001f) // current dir and new dir are enough different { desiredAimDirection = currentDir.GetRotated(axis.GetNormalized(),sgn(reqAngle)*maxAngle); } } } bool isUserClient = m_pControlledPlayer->IsClient(); IEntity* pMountedGunParentEntity = pMountedGunEntity->GetParent(); IVehicle *pVehicle = NULL; if(pMountedGunParentEntity && m_pControlledPlayer) pVehicle = m_pControlledPlayer->GetLinkedVehicle(); CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); //For client update always, for others only when there is notable change if (!pVehicle && (isUserClient || (!desiredAimDirection.IsEquivalent(lastMountedGunWorldTM.GetColumn1(), 0.003f)))) { Quat rotation = Quat::CreateRotationVDir(desiredAimDirection, 0.0f); pMountedGunEntity->SetRotation(rotation); if (isUserClient && pRecordingSystem) { // Only record the gun position if you're using the gun. pRecordingSystem->OnMountedGunRotate(pMountedGunEntity, rotation); } } const Vec3 vInitialAimDirection = GetMountDirection(pMountedGun, pMountedGunParentEntity); assert( vInitialAimDirection.IsUnit() ); //Adjust gunner position and animations UpdateGunnerLocation(pMountedGun, pMountedGunParentEntity, vInitialAimDirection); const float aimrad = Ang3::CreateRadZ(Vec2(vInitialAimDirection),Vec2(-desiredAimDirection)); const float pitchLimit = sin_tpl(DEG2RAD(30.0f)); const float animHeight = fabs_tpl(clamp(desiredAimDirection.z * (float)__fres(pitchLimit), -1.0f, 1.0f)); const float aimUp = (float)__fsel(-desiredAimDirection.z, 0.0f, animHeight); const float aimDown = (float)__fsel(desiredAimDirection.z, 0.0f, animHeight); if (pRecordingSystem) { pRecordingSystem->OnMountedGunUpdate(m_pControlledPlayer, aimrad, aimUp, aimDown); } if(!m_pControlledPlayer->IsThirdPerson()) { UpdateFirstPersonAnimations(pMountedGun, desiredAimDirection); } if(m_pMovementAction) { const float aimUpParam = aimUp; const float aimDownParam = aimDown; const float aimMovementParam = CalculateAnimationTime(aimrad); m_pMovementAction->SetParam(MountedGunCRCs.aimUpParam, aimUpParam); m_pMovementAction->SetParam(MountedGunCRCs.aimDownParam, aimDownParam); m_pMovementAction->SetParam(MountedGunCRCs.aimMovementParam, aimMovementParam); } UpdateIKMounted(pMountedGun); } }
void CPlayerStateGround::OnPrePhysicsUpdate( CPlayer& player, const SActorFrameMovementParams &movement, float frameTime, const bool isHeavyWeapon, const bool isPlayer ) { const Matrix34A baseMtx = Matrix34A(player.GetBaseQuat()); Matrix34A baseMtxZ(baseMtx * Matrix33::CreateScale(Vec3Constants<float>::fVec3_OneZ)); baseMtxZ.SetTranslation(Vec3Constants<float>::fVec3_Zero); const CAutoAimManager& autoAimManager = g_pGame->GetAutoAimManager(); const EntityId closeCombatTargetId = autoAimManager.GetCloseCombatSnapTarget(); const IActor* pCloseCombatTarget = isPlayer && closeCombatTargetId && player.IsClient() ? g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(closeCombatTargetId) : NULL; if (pCloseCombatTarget) { ProcessAlignToTarget(autoAimManager, player, pCloseCombatTarget); } else { // This is to restore inertia if the ProcessAlignToTarget set it previously. if( m_inertiaIsZero ) { CPlayerStateUtil::RestorePlayerPhysics( player ); m_inertiaIsZero = false; } //process movement const bool isRemote = isPlayer && !player.IsClient(); Vec3 move(ZERO); CPlayerStateUtil::CalculateGroundOrJumpMovement( player, movement, isHeavyWeapon, move ); player.GetMoveRequest().type = eCMT_Normal; //apply movement Vec3 desiredVel(ZERO); Vec3 entityPos = player.GetEntity()->GetWorldPos(); Vec3 entityRight(player.GetBaseQuat().GetColumn0()); hwvec3 xmDesiredVel = HWV3Zero(); hwmtx33 xmBaseMtxZ; HWMtx33LoadAligned(xmBaseMtxZ, baseMtxZ); hwmtx33 xmBaseMtxZOpt = HWMtx33GetOptimized(xmBaseMtxZ); hwvec3 xmMove = HWVLoadVecUnaligned(&move); simdf fGroundNormalZ; #ifdef STATE_DEBUG bool debugJumping = (g_pGameCVars->pl_debug_jumping != 0); #endif const SPlayerStats& stats = *player.GetActorStats(); { xmDesiredVel = xmMove; Vec3 groundNormal = player.GetActorPhysics().groundNormal; if(!gEnv->bMultiplayer) { if (player.IsAIControlled()) fGroundNormalZ = SIMDFLoadFloat(square(groundNormal.z)); else fGroundNormalZ = SIMDFLoadFloat(groundNormal.z); } else { //If the hill steepness is greater than our minimum threshold if(groundNormal.z > 1.f - cosf(g_pGameCVars->pl_movement.mp_slope_speed_multiplier_minHill)) { //Check if we are trying to move up or downhill groundNormal.z = 0.f; groundNormal.Normalize(); Vec3 moveDir = move; moveDir.z = 0.f; moveDir.Normalize(); float normalDotMove = groundNormal.Dot(moveDir); //Apply speed multiplier based on moving up/down hill and hill steepness float multiplier = normalDotMove < 0.f ? g_pGameCVars->pl_movement.mp_slope_speed_multiplier_uphill : g_pGameCVars->pl_movement.mp_slope_speed_multiplier_downhill; fGroundNormalZ = SIMDFLoadFloat(1.f - (1.f - player.GetActorPhysics().groundNormal.z) * multiplier); } else { fGroundNormalZ = SIMDFLoadFloat(1.0f); } } const float depthHi = g_pGameCVars->cl_shallowWaterDepthHi; const float depthLo = g_pGameCVars->cl_shallowWaterDepthLo; const float relativeBottomDepth = player.m_playerStateSwim_WaterTestProxy.GetRelativeBottomDepth(); if( relativeBottomDepth > depthLo ) { // Shallow water speed slowdown float shallowWaterMultiplier = 1.0f; shallowWaterMultiplier = isPlayer ? g_pGameCVars->cl_shallowWaterSpeedMulPlayer : g_pGameCVars->cl_shallowWaterSpeedMulAI; shallowWaterMultiplier = max(shallowWaterMultiplier, 0.1f); assert(shallowWaterMultiplier <= 1.0f); float shallowWaterDepthSpan = (depthHi - depthLo); shallowWaterDepthSpan = max(0.1f, shallowWaterDepthSpan); float slowdownFraction = (relativeBottomDepth - depthLo) / shallowWaterDepthSpan; slowdownFraction = clamp_tpl(slowdownFraction, 0.0f, 1.0f); shallowWaterMultiplier = LERP(1.0f, shallowWaterMultiplier, slowdownFraction); //avoid branch if m_stats.relativeBottomDepth <= 0.0f; shallowWaterMultiplier = (float)__fsel(-relativeBottomDepth, 1.0f, shallowWaterMultiplier); simdf vfShallowWaterMultiplier = SIMDFLoadFloat(shallowWaterMultiplier); xmDesiredVel = HWVMultiplySIMDF(xmDesiredVel, vfShallowWaterMultiplier); } } // Slow down on sloped terrain, simply proportional to the slope. xmDesiredVel = HWVMultiplySIMDF(xmDesiredVel, fGroundNormalZ); //be sure desired velocity is flat to the ground hwvec3 vDesiredVelVert = HWMtx33RotateVecOpt(xmBaseMtxZOpt, xmDesiredVel); xmDesiredVel = HWVSub(xmDesiredVel, vDesiredVelVert); HWVSaveVecUnaligned(&desiredVel, xmDesiredVel); if (isPlayer) { Vec3 modifiedSlopeNormal = player.GetActorPhysics().groundNormal; float h = Vec2(modifiedSlopeNormal.x, modifiedSlopeNormal.y).GetLength(); // TODO: OPT: sqrt(x*x+y*y) float v = modifiedSlopeNormal.z; float slopeAngleCur = RAD2DEG(atan2_tpl(h, v)); const float divisorH = (float)__fsel(-h, 1.0f, h); const float divisorV = (float)__fsel(-v, 1.0f, v); const float invV = __fres(divisorV); const float invH = __fres(divisorH); const float slopeAngleHor = 10.0f; const float slopeAngleVer = 50.0f; float slopeAngleFraction = clamp_tpl((slopeAngleCur - slopeAngleHor) * __fres(slopeAngleVer - slopeAngleHor), 0.0f, 1.0f); slopeAngleFraction = slopeAngleFraction * slopeAngleFraction * slopeAngleFraction; float slopeAngleMod = LERP(0.0f, 90.0f, slopeAngleFraction); float s, c; sincos_tpl(DEG2RAD(slopeAngleMod), &s, &c); const float hMultiplier = (float)__fsel(-h, 1.0f, s * invH); const float vMultiplier = (float)__fsel(-v, 1.0f, c * invV); modifiedSlopeNormal.x *= hMultiplier; modifiedSlopeNormal.y *= hMultiplier; modifiedSlopeNormal.z *= vMultiplier; //Normalize the slope normal if possible const float fSlopeNormalLength = modifiedSlopeNormal.len(); const float fSlopeNormalLengthSafe = (float)__fsel(fSlopeNormalLength - 0.000001f, fSlopeNormalLength, 1.0f); modifiedSlopeNormal = modifiedSlopeNormal * __fres(fSlopeNormalLengthSafe); float alignment = min(modifiedSlopeNormal * desiredVel, 0.0f); // Also affect air control (but not as much), to prevent jumping up against steep slopes. alignment *= (float)__fsel(-fabsf(stats.onGround), LERP(0.7f, 1.0f, 1.0f - clamp_tpl(modifiedSlopeNormal.z * 100.0f, 0.0f, 1.0f)), 1.0f); modifiedSlopeNormal.z = modifiedSlopeNormal.z; desiredVel -= modifiedSlopeNormal * alignment; #ifdef STATE_DEBUG if (debugJumping) { player.DebugGraph_AddValue("GroundSlope", slopeAngleCur); player.DebugGraph_AddValue("GroundSlopeMod", slopeAngleMod); } #endif } Vec3 newVelocity = desiredVel; const float fNewSpeed = newVelocity.len(); const float fVelocityMultiplier = (float)__fsel(fNewSpeed - 22.0f, __fres(fNewSpeed+FLT_EPSILON) * 22.0f, 1.0f); // TODO: Maybe we should tell physics about this new velocity ? Or maybe SPlayerStats::velocity ? (stephenn). player.GetMoveRequest().velocity = newVelocity * (stats.flashBangStunMult * fVelocityMultiplier); #ifdef STATE_DEBUG if(g_pGameCVars->pl_debug_movement > 0) { const char* filter = g_pGameCVars->pl_debug_filter->GetString(); const char* name = player.GetEntity()->GetName(); if ((strcmp(filter, "0") == 0) || (strcmp(filter, name) == 0)) { float white[] = {1.0f,1.0f,1.0f,1.0f}; gEnv->pRenderer->Draw2dLabel(20, 450, 2.0f, white, false, "Speed: %.3f m/s", player.GetMoveRequest().velocity.len()); if(g_pGameCVars->pl_debug_movement > 1) { gEnv->pRenderer->Draw2dLabel(35, 470, 1.8f, white, false, "Stance Speed: %.3f m/s - (%sSprinting)", player.GetStanceMaxSpeed(player.GetStance()), player.IsSprinting() ? "" : "Not "); } } } #endif } if( isPlayer ) { CheckForVaultTrigger(player, frameTime); } }
bool CSmokeManager::IsPointInSmoke(const Vec3& vPos, float& outInsideFactor) const { const int kNumActiveSmokeInstances = m_numActiveSmokeInstances; PrefetchLine(m_smokeInstances, 0); PrefetchLine(m_smokeInstances, 128); outInsideFactor = 0.0f; for(int i = 0; i < kNumActiveSmokeInstances; i++) { const SSmokeInstance& smokeInstance = m_smokeInstances[i]; PrefetchLine(&smokeInstance, 128); const float fDistanceSq = Distance::Point_PointSq(vPos, smokeInstance.vPositon); const float fCurrentRadiusSq = sqr(smokeInstance.fCurrentRadius); if(fDistanceSq < fCurrentRadiusSq) { outInsideFactor = 1.0f - ((float)cry_sqrtf_fast(fDistanceSq) * (float)__fres(cry_sqrtf_fast(fCurrentRadiusSq))); return true; } } return false; }
void CRecoil::UpdateSpread(bool weaponFired, bool weaponFiring, float frameTime) { const bool isFiring = m_singleShot ? weaponFired : weaponFiring; const float decay = isFiring ? m_spreadParams.decay : m_spreadParams.end_decay; const float frameDecay = (float)__fsel(-decay, 0.0f, ((m_spreadParams.max - m_spreadParams.min) * __fres(decay + FLT_EPSILON)) * frameTime); float newSpread = clamp(m_spread - frameDecay, m_spreadParams.min, (m_spreadParams.max * m_maxSpreadMultiplier)); if(newSpread < m_spreadParams.max) { m_maxSpreadMultiplier = 1.f; } m_spread = newSpread; CRecoilDebugDraw::DebugSpread(GetSpread()); }