void CCannonBall::HandlePierceableSurface( const EventPhysCollision* pCollision, IEntity* pHitTarget, const Vec3& hitDirection, bool bProcessedCollisionEvent ) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); const SPierceabilityParams& pierceabilityParams = m_pAmmoParams->pierceabilityParams; const int maxPenetrationCount = 4; const float entryAngleDot = pCollision->n.Dot(hitDirection); bool backFace = (entryAngleDot >= 0); #ifdef DEBUG_CannonBall_PENETRATION bool debugCannonBallPenetration = (g_pGameCVars->g_bulletPenetrationDebug != 0); #endif if (backFace == false) { //Front face hit, accumulate damage falloff after penetration float bouncy, friction; uint32 pierceabilityMat; gEnv->pPhysicalWorld->GetSurfaceParameters(pCollision->idmat[1], bouncy, friction, pierceabilityMat); pierceabilityMat &= sf_pierceable_mask; #ifdef DEBUG_CannonBall_PENETRATION const float damageBeforePenetration = GetDamageAfterPenetrationFallOff(); #endif m_penetrationCount++; //1- Check if collided surface might stop the Cannon Ball const bool collisionStopsCannonBall = (!bProcessedCollisionEvent) || (pCollision->idCollider == -1) || ((int16)pierceabilityMat <= GetCannonBallPierceability()) || (m_penetrationCount >= maxPenetrationCount); if (collisionStopsCannonBall) { #ifdef DEBUG_CannonBall_PENETRATION if (debugCannonBallPenetration) { s_debugCannonBallPenetration.AddCannonBallHit(pCollision->pt, hitDirection, damageBeforePenetration, (pCollision->idCollider == -1) ? -1 : pierceabilityMat, false, true, false); } #endif m_accumulatedDamageFallOffAfterPenetration += (float)m_damage; return; } //2- If not stopped, add fall off damage, and see if can still penetrate m_accumulatedDamageFallOffAfterPenetration += (float)m_damage * (pierceabilityParams.GetDamageFallOffForPierceability(pierceabilityMat) * 0.01f); bool needsBackFaceCheck = (GetDamageAfterPenetrationFallOff() > 0.0f) && pierceabilityParams.SurfaceRequiresBackFaceCheck(pierceabilityMat); #ifdef DEBUG_CannonBall_PENETRATION if (debugCannonBallPenetration) { if (ShouldDestroyCannonBall()) { s_debugCannonBallPenetration.AddCannonBallHit(pCollision->pt, hitDirection, damageBeforePenetration, pierceabilityMat, false, true, false); } } #endif if (needsBackFaceCheck) { //3- Raytrace backwards, to check thickness & exit point if any const float angleFactor = 1.0f/max(0.2f, -entryAngleDot); const float distCheck = pierceabilityParams.maxPenetrationThickness * angleFactor; SBackHitInfo hit; bool exitPointFound = RayTraceGeometry(pCollision, pCollision->pt + (hitDirection * (distCheck + 0.035f)), -hitDirection * distCheck ,&hit); if (exitPointFound) { //Exit point found if(ShouldSpawnBackSideEffect(pHitTarget)) { //Spawn effect IMaterialEffects* pMaterialEffects = g_pGame->GetIGameFramework()->GetIMaterialEffects(); TMFXEffectId effectId = pMaterialEffects->GetEffectId(GetEntity()->GetClass(), pCollision->idmat[1]); if (effectId != InvalidEffectId) { SMFXRunTimeEffectParams params; params.src = GetEntityId(); params.trg = pHitTarget ? pHitTarget->GetId() : 0; params.srcSurfaceId = pCollision->idmat[0]; params.trgSurfaceId = pCollision->idmat[1]; params.soundSemantic = eSoundSemantic_Physics_Collision; params.srcRenderNode = (pCollision->iForeignData[0] == PHYS_FOREIGN_ID_STATIC) ? (IRenderNode*)pCollision->pForeignData[0] : NULL; params.trgRenderNode = (pCollision->iForeignData[1] == PHYS_FOREIGN_ID_STATIC) ? (IRenderNode*)pCollision->pForeignData[1] : NULL; params.pos = hit.pt; params.normal = hitDirection; //Use Cannon direction, more readable for exits than normal params.partID = pCollision->partid[1]; params.dir[0] = -hitDirection; params.playflags = MFX_PLAY_ALL&(~MFX_PLAY_SOUND); //Do not play the sound on backface params.playflags &= ~MFX_PLAY_DECAL; //We disable also decals, since hit.pt is not refined with render mesh params.fDecalPlacementTestMaxSize = pCollision->fDecalPlacementTestMaxSize; pMaterialEffects->ExecuteEffect(effectId, params); } } #ifdef DEBUG_CannonBall_PENETRATION if (debugCannonBallPenetration) { s_debugCannonBallPenetration.AddCannonBallHit(pCollision->pt, hitDirection, damageBeforePenetration, pierceabilityMat, false, false, false); s_debugCannonBallPenetration.AddCannonBallHit(hit.pt, hitDirection, GetDamageAfterPenetrationFallOff(), pierceabilityMat, true, false, false); } #endif } else { #ifdef DEBUG_CannonBall_PENETRATION if (debugCannonBallPenetration) { s_debugCannonBallPenetration.AddCannonBallHit(pCollision->pt, hitDirection, damageBeforePenetration, pierceabilityMat, false, true, true); } #endif //Surface must be too thick, add enough fall off to destroy the Cannon Ball m_accumulatedDamageFallOffAfterPenetration += (float)m_damage; } } } }
void CPlayerRotation::Process(IItem* pCurrentItem, const SActorFrameMovementParams& movement, const SAimAccelerationParams& verticalAcceleration, float frameTime) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); // reset to the new impulse. m_angularImpulseDelta = m_angularImpulse; m_deltaAngles = movement.deltaAngles; PR_CHECKQNAN_FLT(m_deltaAngles); // Store the previous rotation to get the correct rotation for linked actors. const Quat previousBaseQuat = m_baseQuat; const Quat previousViewQuat = m_viewQuat; ProcessForcedLookDirection(m_viewQuatFinal, frameTime); ProcessAngularImpulses( frameTime ); ProcessLeanAndPeek( movement ); ProcessNormalRoll( frameTime ); bool shouldProcessTargetAssistance = ShouldProcessTargetAssistance(); if (shouldProcessTargetAssistance) { ProcessTargetAssistance( pCurrentItem ); } #if TALOS if(stricmp(g_pGameCVars->pl_talos->GetString(), m_player.GetEntity()->GetName()) == 0) { IMovementController* pMovementController = m_player.GetMovementController(); CRY_ASSERT(pMovementController); SMovementState moveState; pMovementController->GetMovementState(moveState); Vec3 playerView[4] = { m_viewQuat.GetColumn0(), // Right m_viewQuat.GetColumn1(), // Forward m_viewQuat.GetColumn2(), // Up moveState.eyePosition // Pos }; GetTalosInput(this, m_player, m_deltaAngles.x, m_deltaAngles.z, playerView, frameTime); } #endif float minAngle,maxAngle; GetStanceAngleLimits(verticalAcceleration, pCurrentItem, minAngle, maxAngle); ClampAngles( minAngle, maxAngle ); ProcessNormal( frameTime ); if(shouldProcessTargetAssistance) { IVehicle* pVehicle = m_player.GetLinkedVehicle(); if (pVehicle && GetCurrentItem(true)) { if (m_deltaAngles.x!=0.f) pVehicle->OnAction(eVAI_RotatePitchAimAssist, eAAM_Always, m_deltaAngles.x, m_player.GetEntity()->GetId()); if (m_deltaAngles.z!=0.f) pVehicle->OnAction(eVAI_RotateYawAimAssist, eAAM_Always, m_deltaAngles.z, m_player.GetEntity()->GetId()); } } //update freelook when linked to an entity ProcessLinkedState(m_player.m_linkStats, previousBaseQuat, previousViewQuat); //Recoil/Zoom sway offset for local player ProcessFinalViewEffects( minAngle, maxAngle ); m_frameViewAnglesOffset.Set(0.0f, 0.0f, 0.0f); m_forceLookVector.zero(); m_externalAngles.Set(0.f, 0.f, 0.f); NormalizeQuats(); }
bool CDevMode::OnInputEvent( const SInputEvent& evt ) { FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION); bool handled = false; bool canCheat = CCryAction::GetCryAction()->CanCheat(); IActor* pActor = CCryAction::GetCryAction()->GetClientActor(); if (!pActor) return false; IEntity* pEntity = pActor->GetEntity(); if (!pEntity) return false; // tag-point functionality is provided by the editor already, so we should ignore it // when running in the editor if (!gEnv->IsEditor()) { if ((evt.state == eIS_Pressed) && canCheat) { if ((evt.modifiers & eMM_Shift)!=0 && (evt.modifiers & eMM_Alt) == 0) // Shift ONLY { if (handled = (evt.keyId == eKI_F1)) GotoTagPoint(0); if (handled = (evt.keyId == eKI_F2)) GotoTagPoint(1); if (handled = (evt.keyId == eKI_F3)) GotoTagPoint(2); if (handled = (evt.keyId == eKI_F4)) GotoTagPoint(3); if (handled = (evt.keyId == eKI_F5)) GotoTagPoint(4); if (handled = (evt.keyId == eKI_F6)) GotoTagPoint(5); if (handled = (evt.keyId == eKI_F7)) GotoTagPoint(6); if (handled = (evt.keyId == eKI_F8)) GotoTagPoint(7); if (handled = (evt.keyId == eKI_F9)) GotoTagPoint(8); if (handled = (evt.keyId == eKI_F10)) GotoTagPoint(9); if (handled = (evt.keyId == eKI_F11)) GotoTagPoint(10); if (handled = (evt.keyId == eKI_F12)) GotoTagPoint(11); } else if ((evt.modifiers & eMM_Shift) == 0 && ((evt.modifiers & eMM_Alt)!=0 || (evt.modifiers & eMM_Ctrl)!=0)) // Alt or Ctrl and NO Shift { if (handled = (evt.keyId == eKI_F1)) SaveTagPoint(0); if (handled = (evt.keyId == eKI_F2)) SaveTagPoint(1); if (handled = (evt.keyId == eKI_F3)) SaveTagPoint(2); if (handled = (evt.keyId == eKI_F4)) SaveTagPoint(3); if (handled = (evt.keyId == eKI_F5)) SaveTagPoint(4); if (handled = (evt.keyId == eKI_F6)) SaveTagPoint(5); if (handled = (evt.keyId == eKI_F7)) SaveTagPoint(6); if (handled = (evt.keyId == eKI_F8)) SaveTagPoint(7); if (handled = (evt.keyId == eKI_F9)) SaveTagPoint(8); if (handled = (evt.keyId == eKI_F10)) SaveTagPoint(9); if (handled = (evt.keyId == eKI_F11)) SaveTagPoint(10); if (handled = (evt.keyId == eKI_F12)) SaveTagPoint(11); } } } else { // place commands which should only be dealt with in game mode here } // shared commands if (canCheat) { if (!handled && (evt.state == eIS_Pressed) && (evt.modifiers & eMM_Shift) != 0 && (evt.modifiers & eMM_Alt) != 0) { if (handled = (evt.keyId == eKI_NP_1)) GotoSpecialSpawnPoint(1); if (handled = (evt.keyId == eKI_NP_2)) GotoSpecialSpawnPoint(2); if (handled = (evt.keyId == eKI_NP_3)) GotoSpecialSpawnPoint(3); if (handled = (evt.keyId == eKI_NP_4)) GotoSpecialSpawnPoint(4); if (handled = (evt.keyId == eKI_NP_5)) GotoSpecialSpawnPoint(5); if (handled = (evt.keyId == eKI_NP_6)) GotoSpecialSpawnPoint(6); if (handled = (evt.keyId == eKI_NP_7)) GotoSpecialSpawnPoint(7); if (handled = (evt.keyId == eKI_NP_8)) GotoSpecialSpawnPoint(8); if (handled = (evt.keyId == eKI_NP_9)) GotoSpecialSpawnPoint(9); } else if (!handled && (evt.state == eIS_Pressed) && !(evt.modifiers & eMM_Modifiers)) { if (handled = (evt.keyId == eKI_NP_1) && !gEnv->bMultiplayer) // give all items { CCryAction::GetCryAction()->GetIItemSystem()->GetIEquipmentManager()->GiveEquipmentPack(pActor, "Player_Default", true, true); } else if (handled = (evt.keyId == eKI_F2)) // go to next spawnpoint { Vec3 oldPos = pEntity->GetWorldPos(); if (gEnv->pScriptSystem->BeginCall("BasicActor", "OnNextSpawnPoint")) { gEnv->pScriptSystem->PushFuncParam(pEntity->GetScriptTable()); gEnv->pScriptSystem->EndCall(); if (gEnv->pStatoscope) { char buffer[100]; Vec3 pos = pEntity->GetWorldPos(); sprintf(buffer, "Teleported from (%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f)", oldPos.x, oldPos.y, oldPos.z, pos.x, pos.y, pos.z); gEnv->pStatoscope->AddUserMarker("Player", buffer); } } } } } if (handled == false && evt.state == eIS_Pressed && (evt.modifiers & eMM_Alt)!=0) { if(evt.keyId == eKI_F7) SwitchSlowDownGameSpeed(); else if(evt.keyId==eKI_F8) SwitchHUD(); } // AlexL: don't mark commands as handled for now. Would stop processing/propagating to other // listeners. especially for non-modifier keys like f7,f8,f9 problematic return false; // handled; }
//------------------------------------------------------------------------ void CCannonBall::HandleEvent(const SGameObjectEvent &event) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); BaseClass::HandleEvent(event); if (event.event == eGFE_OnCollision) { if (CheckAnyProjectileFlags(ePFlag_destroying)) return; EventPhysCollision *pCollision = reinterpret_cast<EventPhysCollision *>(event.ptr); if (!pCollision) return; float finalDamage = GetFinalDamage(pCollision->pt); if (finalDamage <= 0.0f) m_alive = false; IEntity *pTarget = pCollision->iForeignData[1]==PHYS_FOREIGN_ID_ENTITY ? (IEntity*)pCollision->pForeignData[1]:0; CGameRules *pGameRules = g_pGame->GetGameRules(); const int hitMatId = pCollision->idmat[1]; Vec3 hitDir(ZERO); if (pCollision->vloc[0].GetLengthSquared() > 1e-6f) { hitDir = pCollision->vloc[0].GetNormalized(); } const bool bProcessCollisionEvent = ProcessCollisionEvent(pTarget); if (bProcessCollisionEvent) { //================================= Process Hit ===================================== //Only process hits that have a target if(pTarget) { if(FilterFriendlyAIHit(pTarget) == false) { ProcessHit(*pGameRules, *pCollision, *pTarget, finalDamage, hitMatId, hitDir); } } //====================================~ Process Hit ====================================== //==================================== Notify AI ====================================== if (gEnv->pAISystem) { if (gEnv->pEntitySystem->GetEntity(m_ownerId)) { ISurfaceType *pSurfaceType = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceType(hitMatId); const ISurfaceType::SSurfaceTypeAIParams* pParams = pSurfaceType ? pSurfaceType->GetAIParams() : 0; const float radius = pParams ? pParams->fImpactRadius : 2.5f; const float soundRadius = pParams ? pParams->fImpactSoundRadius : 20.0f; SAIStimulus stim(AISTIM_BULLET_HIT, 0, m_ownerId, pTarget ? pTarget->GetId() : 0, pCollision->pt, pCollision->vloc[0].GetNormalizedSafe(ZERO), radius); gEnv->pAISystem->RegisterStimulus(stim); SAIStimulus stimSound(AISTIM_SOUND, AISTIM_BULLET_HIT, m_ownerId, 0, pCollision->pt, ZERO, soundRadius); gEnv->pAISystem->RegisterStimulus(stim); } } //=========================================~ Notify AI =============================== } //========================================= Surface Pierceability ============================== if (pCollision->pEntity[0]->GetType() == PE_PARTICLE) { const SPierceabilityParams& pierceabilityParams = m_pAmmoParams->pierceabilityParams; //If collided water if( s_materialLookup.IsMaterial( pCollision->idmat[1], CProjectile::SMaterialLookUp::eType_Water ) ) { if(pierceabilityParams.DestroyOnWaterImpact()) { DestroyAtHitPosition(pCollision->pt); } else { EmitUnderwaterTracer(pCollision->pt, pCollision->pt + (pCollision->vloc[0].GetNormalizedSafe() * 100.0f)); } } else if (m_pAmmoParams->bounceableBullet == 0) { float bouncy, friction; uint32 pierceabilityMat; gEnv->pPhysicalWorld->GetSurfaceParameters(pCollision->idmat[1], bouncy, friction, pierceabilityMat); pierceabilityMat &= sf_pierceable_mask; const bool terrainHit = (pCollision->idCollider == -1); bool thouShallNotPass = terrainHit; if (!CheckAnyProjectileFlags(ePFlag_ownerIsPlayer)) thouShallNotPass = thouShallNotPass || pierceabilityParams.DestroyOnImpact(pierceabilityMat); if (!thouShallNotPass) HandlePierceableSurface(pCollision, pTarget, hitDir, bProcessCollisionEvent); const bool destroy = thouShallNotPass || ShouldDestroyCannonBall(); if (destroy) { DestroyAtHitPosition(pCollision->pt); } } } } }
//------------------------------------------------------------------------ void CVehicleMovementVTOL::ProcessActions(const float deltaTime) { FUNCTION_PROFILER( GetISystem(), PROFILE_GAME ); UpdateDamages(deltaTime); UpdateEngine(deltaTime); m_velDamp = 0.25f; m_playerControls.ProcessActions(deltaTime); Limit(m_forwardAction, -1.0f, 1.0f); Limit(m_strafeAction, -1.0f, 1.0f); m_actionYaw = 0.0f; Vec3 worldPos = m_pEntity->GetWorldPos(); IPhysicalEntity *pPhysics = GetPhysics(); // get the current state // roll pitch + yaw Matrix34 worldTM = m_pRotorPart ? m_pRotorPart->GetWorldTM() : m_pEntity->GetWorldTM(); // if (m_pRotorPart) // worldTM = m_pRotorPart->GetWorldTM(); // else // worldTM = m_pEntity->GetWorldTM(); Vec3 specialPos = worldTM.GetTranslation(); Ang3 angles = Ang3::GetAnglesXYZ(Matrix33(worldTM)); Matrix33 tm; tm.SetRotationXYZ((angles)); // +ve pitch means nose up const float ¤tPitch = angles.x; // +ve roll means to the left const float ¤tRoll = angles.y; // +ve direction mean rotation anti-clockwise about the z axis - 0 means along y float currentDir = angles.z; const float maxPitchAngle = 60.0f; float pitchDeg = RAD2DEG(currentPitch); if (pitchDeg >= (maxPitchAngle * 0.75f)) { float mult = pitchDeg / (maxPitchAngle); if (mult > 1.0f && m_desiredPitch < 0.0f) { m_desiredPitch *= 0.0f; m_actionPitch *= 0.0f; m_desiredPitch += 0.2f * mult; } else if (m_desiredPitch < 0.0f) { m_desiredPitch *= (1.0f - mult); m_desiredPitch += 0.05f; } } else if (pitchDeg <= (-maxPitchAngle * 0.75f)) { float mult = abs(pitchDeg) / (maxPitchAngle); if (mult > 1.0f && m_desiredPitch > 0.0f) { m_desiredPitch *= 0.0f; m_actionPitch *= 0.0f; m_desiredPitch += 0.2f * mult; } else if (m_desiredPitch > 0.0f) { m_desiredPitch *= (1.0f - mult); m_desiredPitch -= 0.05f; } } if (currentRoll >= DEG2RAD(m_maxRollAngle * 0.7f) && m_desiredRoll > 0.001f) { float r = currentRoll / DEG2RAD(m_maxRollAngle); r = min(1.0f, r * 1.0f); r = 1.0f - r; m_desiredRoll *= r; m_desiredRoll = min(1.0f, m_desiredRoll); } else if (currentRoll <= DEG2RAD(-m_maxRollAngle * 0.7f) && m_desiredRoll < 0.001f) { float r = abs(currentRoll) / DEG2RAD(m_maxRollAngle); r = min(1.0f, r * 1.0f); r = 1.0f - r; m_desiredRoll *= r; m_desiredRoll = max(-1.0f, m_desiredRoll); } Vec3 currentFwdDir2D = m_currentFwdDir; currentFwdDir2D.z = 0.0f; currentFwdDir2D.NormalizeSafe(); Vec3 currentLeftDir2D(-currentFwdDir2D.y, currentFwdDir2D.x, 0.0f); Vec3 currentVel = m_PhysDyn.v; Vec3 currentVel2D = currentVel; currentVel2D.z = 0.0f; float currentHeight = worldPos.z; float currentFwdSpeed = currentVel.Dot(currentFwdDir2D); ProcessActions_AdjustActions(deltaTime); float inputMult = m_basicSpeedFraction; // desired things float turnDecreaseScale = m_yawDecreaseWithSpeed / (m_yawDecreaseWithSpeed + fabs(currentFwdSpeed)); Vec3 desired_vel2D = currentFwdDir2D * m_forwardAction * m_maxFwdSpeed * inputMult + currentLeftDir2D * m_strafeAction * m_maxLeftSpeed * inputMult; // calculate the angle changes Vec3 desiredVelChange2D = desired_vel2D - currentVel2D; float desiredTiltAngle = m_tiltPerVelDifference * desiredVelChange2D.GetLength(); Limit(desiredTiltAngle, -m_maxTiltAngle, m_maxTiltAngle); float goal = abs(m_desiredPitch) + abs(m_desiredRoll); goal *= 1.5f; Interpolate(m_playerAcceleration, goal, 0.25f, deltaTime); Limit(m_playerAcceleration, 0.0f, 5.0f); //static float g_angleLift = 4.0f; if (abs(m_liftAction) > 0.001f && abs(m_forwardAction) < 0.001) { // float pitch = RAD2DEG(currentPitch); if (m_liftPitchAngle < 0.0f && m_liftAction > 0.0f) { m_liftPitchAngle = 0.0f; } else if (m_liftPitchAngle > 0.0f && m_liftAction < 0.0f) { m_liftPitchAngle = 0.0f; } Interpolate(m_liftPitchAngle, 1.25f * m_liftAction, 0.75f, deltaTime); if (m_liftPitchAngle < 1.0f && m_liftPitchAngle > -1.0f) { m_desiredPitch += 0.05f * m_liftAction; } } else if (m_liftAction < 0.001f && abs(m_liftPitchAngle) > 0.001) { Interpolate(m_liftPitchAngle, 0.0f, 1.0f, deltaTime); m_desiredPitch += 0.05f * -m_liftPitchAngle; } /* todo else if (m_liftAction < -0.001f) { m_desiredPitch += min(0.0f, (DEG2RAD(-5.0f) - currentPitch)) * 0.5f * m_liftAction; }*/ if (!iszero(m_desiredPitch)) { m_actionPitch -= m_desiredPitch * m_pitchInputConst; Limit(m_actionPitch, -m_maxYawRate, m_maxYawRate); } float rollAccel = 1.0f; if (abs(currentRoll + m_desiredRoll) < abs(currentRoll)) { rollAccel *= 1.25f; } m_actionRoll += m_pitchActionPerTilt * m_desiredRoll * rollAccel * (m_playerAcceleration + 1.0f); Limit(m_actionRoll, -10.0f, 10.0f); Limit(m_actionPitch, -10.0f, 10.0f); // roll as we turn if (!m_strafeAction) { m_actionYaw += m_yawPerRoll * currentRoll; } if (abs(m_strafeAction) > 0.001f) { float side = 0.0f; side = min(1.0f, max(-1.0f, m_strafeAction)); float roll = DEG2RAD(m_extraRollForTurn * 0.25f * side) - (currentRoll); m_actionRoll += max(0.0f, abs(roll)) * side * 1.0f; } float relaxRollTolerance = 0.0f; if (abs(m_turnAction) > 0.01f || abs(m_PhysDyn.w.z) > DEG2RAD(3.0f)) { m_actionYaw += -m_turnAction * m_yawInputConst * GetDamageMult(); float side = 0.0f; if (abs(m_turnAction) > 0.01f) { side = min(1.0f, max(-1.0f, m_turnAction)); } float roll = DEG2RAD(m_extraRollForTurn * side) - (currentRoll); m_actionRoll += max(0.0f, abs(roll)) * side * m_rollForTurnForce; roll *= max(1.0f, abs(m_PhysDyn.w.z)); m_actionRoll += roll; Limit(m_actionYaw, -m_maxYawRate, m_maxYawRate); } m_desiredDir = currentDir; m_lastDir = currentDir; float boost = Boosting() ? m_boostMult : 1.0f; float liftActionMax = 1.0f; if (m_pAltitudeLimitVar) { float altitudeLimit = m_pAltitudeLimitVar->GetFVal(); if (!iszero(altitudeLimit)) { float altitudeLowerOffset; if (m_pAltitudeLimitLowerOffsetVar) { float r = 1.0f - min(1.0f, max(0.0f, m_pAltitudeLimitLowerOffsetVar->GetFVal())); altitudeLowerOffset = r * altitudeLimit; } else { altitudeLowerOffset = altitudeLimit; } float mult = 1.0f; if (currentHeight >= altitudeLimit) { if (m_liftAction > 0.f) { mult = 0.0f; } } else if (currentHeight >= altitudeLowerOffset) { float zone = altitudeLimit - altitudeLowerOffset; mult = (altitudeLimit - currentHeight) / (zone); } m_liftAction *= mult; if (currentPitch > DEG2RAD(0.0f)) { if (m_forwardAction > 0.0f) { m_forwardAction *= mult; } if (m_actionPitch > 0.0f) { m_actionPitch *= mult; m_actionPitch += -currentPitch; } } m_desiredHeight = min(altitudeLowerOffset, currentHeight); } } else { m_desiredHeight = currentHeight; } if (abs(m_liftAction) > 0.001f) { m_liftAction = min(liftActionMax, max(-0.2f, m_liftAction)); m_hoveringPower = (m_powerInputConst * m_liftAction) * boost; m_noHoveringTimer = 0.0f; } else if (!m_isTouchingGround) { if (m_noHoveringTimer <= 0.0f) { float gravity; pe_simulation_params paramsSim; if (pPhysics->GetParams(¶msSim)) { gravity = abs(paramsSim.gravity.z); } else { gravity = 9.2f; } float upDirZ = m_workingUpDir.z; if (abs(m_forwardAction) > 0.01 && upDirZ > 0.0f) { upDirZ = 1.0f; } else if (upDirZ > 0.8f) { upDirZ = 1.0f; } float upPower = upDirZ; upPower -= min(1.0f, abs(m_forwardAction) * abs(angles.x)); float turbulenceMult = 1.0f - min(m_turbulenceMultMax, m_turbulence); Vec3 &impulse = m_control.impulse; impulse += Vec3(0.0f, 0.0f, upPower) * gravity * turbulenceMult * GetDamageMult(); impulse.z -= m_PhysDyn.v.z * turbulenceMult; } else { m_noHoveringTimer -= deltaTime; } } if (m_pStabilizeVTOL) { float stabilizeTime = m_pStabilizeVTOL->GetFVal(); if (stabilizeTime > 0.0f) { if (m_relaxTimer < 6.0f) { m_relaxTimer += deltaTime; } else { float r = currentRoll - relaxRollTolerance; r = min(1.0f, max(-1.0f, r)); m_actionRoll += -r * m_relaxForce * (m_relaxTimer / 6.0f); } } } if (m_netActionSync.PublishActions( CNetworkMovementHelicopter(this) )) { m_pVehicle->GetGameObject()->ChangedNetworkState(eEA_GameClientDynamic); } }
//------------------------------------------------------------------ void CLam::UpdateTPLaser(float frameTime, CItem* parent) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); const int frameId = gEnv->pRenderer->GetFrameID(); if (s_lastUpdateFrameId != frameId) { // Check how many LAMs to update this frame. float dt = frameTime; // + s_laserUpdateTimeError; const int n = s_lasers.size(); int nActive = 0; for (int i = 0; i < n; ++i) { if (!s_lasers[i]->IsLaserActivated() && !s_lasers[i]->IsLightActivated()) continue; nActive++; } float updatedPerSecond = (nActive / LASER_UPDATE_TIME) + s_laserUpdateTimeError; int updateCount = (int)floorf(updatedPerSecond * dt); if(dt==0.0f) s_laserUpdateTimeError = 0.0f; else s_laserUpdateTimeError = updatedPerSecond - updateCount/dt; s_curLaser %= n; for (int i = 0, j = 0; i < n && j < updateCount ; ++i) { s_curLaser = (s_curLaser + 1) % n; if (!s_lasers[s_curLaser]->IsLaserActivated() && !s_lasers[s_curLaser]->IsLightActivated()) continue; s_lasers[s_curLaser]->SetAllowUpdate(); ++j; } s_lastUpdateFrameId = frameId; } IEntity* pRootEnt = GetEntity(); if (!pRootEnt) return; IEntity *pLaserEntity = m_pEntitySystem->GetEntity(m_pLaserEntityId); // if(!pLaserEntity) // return; const CCamera& camera = gEnv->pRenderer->GetCamera(); Vec3 lamPos = pRootEnt->GetWorldPos(); //pLaserEntity->GetParent()->GetWorldPos(); Vec3 dir = pRootEnt->GetWorldRotation().GetColumn1(); //pLaserEntity->GetParent()->GetWorldRotation().GetColumn1(); bool charNotVisible = false; float dsg1Scale = 1.0f; //If character not visible, laser is not correctly updated if(parent) { if(CActor* pOwner = parent->GetOwnerActor()) { ICharacterInstance* pCharacter = pOwner->GetEntity()->GetCharacter(0); if(pCharacter && !pCharacter->IsCharacterVisible()) charNotVisible = true; } if(parent->GetEntity()->GetClass()==CItem::sDSG1Class) dsg1Scale = 3.0f; } // if (!pLaserEntity->GetParent()) // return; Vec3 hitPos(0,0,0); float laserLength = 0.0f; // HACK??: Use player movement controller locations, or else the laser // pops all over the place when character out of the screen. CActor *pActor = parent->GetOwnerActor(); if (pActor && (!pActor->IsPlayer() || charNotVisible)) { if (IMovementController* pMC = pActor->GetMovementController()) { SMovementState state; pMC->GetMovementState(state); if(!charNotVisible) lamPos = state.weaponPosition; else { float oldZPos = lamPos.z; lamPos = state.weaponPosition; if(m_lastZPos>0.0f) lamPos.z = m_lastZPos; //Stabilize somehow z position (even if not accurate) else lamPos.z = oldZPos; } const float angleMin = DEG2RAD(3.0f); const float angleMax = DEG2RAD(7.0f); const float thr = cosf(angleMax); float dot = dir.Dot(state.aimDirection); if (dot > thr) { float a = acos_tpl(dot); float u = 1.0f - clamp((a - angleMin) / (angleMax - angleMin), 0.0f, 1.0f); dir = dir + u * (state.aimDirection - dir); dir.Normalize(); } } } if(!charNotVisible) m_lastZPos = lamPos.z; lamPos += (dir*0.10f); if (m_allowUpdate) { m_allowUpdate = false; IPhysicalEntity* pSkipEntity = NULL; if(parent->GetOwner()) pSkipEntity = parent->GetOwner()->GetPhysics(); const float range = m_lamparams.laser_range[eIGS_ThirdPerson]*dsg1Scale; // Use the same flags as the AI system uses for visbility. const int objects = ent_terrain|ent_static|ent_rigid|ent_sleeping_rigid|ent_independent; //ent_living; const int flags = (geom_colltype_ray << rwi_colltype_bit) | rwi_colltype_any | (10 & rwi_pierceability_mask) | (geom_colltype14 << rwi_colltype_bit); ray_hit hit; if (gEnv->pPhysicalWorld->RayWorldIntersection(lamPos, dir*range, objects, flags, &hit, 1, &pSkipEntity, pSkipEntity ? 1 : 0)) { laserLength = hit.dist; m_lastLaserHitPt = hit.pt; m_lastLaserHitSolid = true; } else { m_lastLaserHitSolid = false; m_lastLaserHitPt = lamPos + dir * range; laserLength = range + 0.1f; } // Hit near plane if (dir.Dot(camera.GetViewdir()) < 0.0f) { Plane nearPlane; nearPlane.SetPlane(camera.GetViewdir(), camera.GetPosition()); nearPlane.d -= camera.GetNearPlane()+0.15f; Ray ray(lamPos, dir); Vec3 out; m_lastLaserHitViewPlane = false; if (Intersect::Ray_Plane(ray, nearPlane, out)) { float dist = Distance::Point_Point(lamPos, out); if (dist < laserLength) { laserLength = dist; m_lastLaserHitPt = out; m_lastLaserHitSolid = true; m_lastLaserHitViewPlane = true; } } } hitPos = m_lastLaserHitPt; } else { laserLength = Distance::Point_Point(m_lastLaserHitPt, lamPos); hitPos = lamPos + dir * laserLength; } if (m_smoothLaserLength < 0.0f) m_smoothLaserLength = laserLength; else { if (laserLength < m_smoothLaserLength) m_smoothLaserLength = laserLength; else m_smoothLaserLength += (laserLength - m_smoothLaserLength) * min(1.0f, 10.0f * frameTime); } float laserAIRange = 0.0f; if (m_laserActivated && pLaserEntity) { // Orient the laser towards the point point. Matrix34 parentTMInv; parentTMInv = pRootEnt->GetWorldTM().GetInverted(); Vec3 localDir = parentTMInv.TransformPoint(hitPos); float finalLaserLen = localDir.NormalizeSafe(); Matrix33 rot; rot.SetIdentity(); rot.SetRotationVDir(localDir); pLaserEntity->SetLocalTM(rot); laserAIRange = finalLaserLen; const float assetLength = 2.0f; finalLaserLen = CLAMP(finalLaserLen,0.01f,m_lamparams.laser_max_len*dsg1Scale); float scale = finalLaserLen / assetLength; // Scale the laser based on the distance. if (m_laserEffectSlot >= 0) { Matrix33 scl; scl.SetIdentity(); scl.SetScale(Vec3(1,scale,1)); pLaserEntity->SetSlotLocalTM(m_laserEffectSlot, scl); } if (m_dotEffectSlot >= 0) { if (m_lastLaserHitSolid) { Matrix34 mt = Matrix34::CreateTranslationMat(Vec3(0,finalLaserLen,0)); if(m_lastLaserHitViewPlane) mt.Scale(Vec3(0.2f,0.2f,0.2f)); pLaserEntity->SetSlotLocalTM(m_dotEffectSlot, mt); } else { Matrix34 scaleMatrix; scaleMatrix.SetIdentity(); scaleMatrix.SetScale(Vec3(0.001f,0.001f,0.001f)); pLaserEntity->SetSlotLocalTM(m_dotEffectSlot, scaleMatrix); } } } float lightAIRange = 0.0f; if (m_lightActivated) { float range = clamp(m_smoothLaserLength, 0.5f, m_lamparams.light_range[eIGS_ThirdPerson]); lightAIRange = range * 1.5f; if (m_lightID[eIGS_ThirdPerson] && m_smoothLaserLength > 0.0f) { CItem* pLightEffect = this; if (IItem *pOwnerItem = m_pItemSystem->GetItem(GetParentId())) pLightEffect = (CItem *)pOwnerItem; pLightEffect->SetLightRadius(range, m_lightID[eIGS_ThirdPerson]); } } if (laserAIRange > 0.0001f || lightAIRange > 0.0001f) UpdateAILightAndLaser(lamPos, dir, lightAIRange, m_lamparams.light_fov[eIGS_ThirdPerson], laserAIRange); }
////////////////////////////////////////////////////////////////////////// // NOTE: This function must be thread-safe. Before adding stuff contact MarcoC. void CVehicleMovementStdBoat::ProcessAI(const float deltaTime) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); float dt = max(deltaTime, 0.005f); // It is copyed from CVehicleMoventTank::ProcessAI m_movementAction.brake = false; m_movementAction.rotateYaw = 0.0f; m_movementAction.power = 0.0f; float inputSpeed = 0.0f; { if(m_aiRequest.HasDesiredSpeed()) inputSpeed = m_aiRequest.GetDesiredSpeed(); Limit(inputSpeed, -m_maxSpeed, m_maxSpeed); } Vec3 vMove(ZERO); { if(m_aiRequest.HasMoveTarget()) vMove = (m_aiRequest.GetMoveTarget() - m_pEntity->GetWorldPos()).GetNormalizedSafe(); } //start calculation if(fabsf(inputSpeed) < 0.0001f) { m_movementAction.brake = true; if(m_PhysDyn.v.GetLength() > 1.0f) { m_movementAction.power =-1.0f; } } else { Matrix33 entRotMatInvert(m_PhysPos.q); entRotMatInvert.Invert(); float currentAngleSpeed = RAD2DEG(-m_PhysDyn.w.z); const static float maxSteer = RAD2DEG(gf_PI/4.f); // fix maxsteer, shouldn't change Vec3 vVel = m_PhysDyn.v; Vec3 vVelR = entRotMatInvert * vVel; float currentSpeed =vVel.GetLength(); vVelR.NormalizeSafe(); if(vVelR.Dot(FORWARD_DIRECTION) < 0) currentSpeed *= -1.0f; // calculate pedal static float accScale = 0.5f; m_movementAction.power = (inputSpeed - currentSpeed) * accScale; Limit(m_movementAction.power, -1.0f, 1.0f); // calculate angles Vec3 vMoveR = entRotMatInvert * vMove; Vec3 vFwd = FORWARD_DIRECTION; vMoveR.z =0.0f; vMoveR.NormalizeSafe(); if(inputSpeed < 0.0f) // when going back { vFwd *= -1.0f; vMoveR *= -1.0f; currentAngleSpeed *=-1.0f; } float cosAngle = vFwd.Dot(vMoveR); float angle = RAD2DEG(acos_tpl(cosAngle)); if(vMoveR.Dot(Vec3(1.0f,0.0f,0.0f))< 0) angle = -angle; //int step =0; m_movementAction.rotateYaw = angle * 1.75f/ maxSteer; // implementation 1. if there is enough angle speed, we don't need to steer more if(fabsf(currentAngleSpeed) > fabsf(angle) && angle*currentAngleSpeed > 0.0f) { m_movementAction.rotateYaw = m_movementAction.rotateYaw*0.995f; //step =1; } // implementation 2. if we can guess we reach the distination angle soon, start counter steer. float predictDelta = inputSpeed < 0.0f ? 0.1f : 0.1f; float dict = angle + predictDelta * (angle - m_prevAngle) / dt ; if(dict*currentAngleSpeed<0.0f) { if(fabsf(angle) < 2.0f) { m_movementAction.rotateYaw = angle* 1.75f/ maxSteer;// ; step =3; } else { m_movementAction.rotateYaw = currentAngleSpeed < 0.0f ? 1.0f : -1.0f;// step =2; } } if(fabsf(angle) > 20.0f && currentSpeed > 3.0f) { m_movementAction.power = 0.1f ; //step =4; } m_prevAngle = angle; //CryLog("steering %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %d", deltaTime,inputSpeed - currentSpeed,angle,currentAngleSpeed, m_movementAction.rotateYaw,currentAngleSpeed-m_prevAngle,step); } }
//------------------------------------------------------------------------ void CMelee::Update(float frameTime, uint32 frameId) { FUNCTION_PROFILER( GetISystem(), PROFILE_GAME ); bool remote = false; bool doMelee = false; bool requireUpdate = false; Vec3 dirToTarget(ZERO); if(m_pMeleeAction && s_meleeSnapTargetId && g_pGameCVars->pl_melee.mp_melee_system_camera_lock_and_turn) { m_attackTime += frameTime; CActor* pOwner = m_pWeapon->GetOwnerActor(); IEntity* pTarget = gEnv->pEntitySystem->GetEntity(s_meleeSnapTargetId); if(pOwner && pTarget) { Vec3 targetPos = pTarget->GetWorldPos(); if(s_bMeleeSnapTargetCrouched) { targetPos.z -= g_pGameCVars->pl_melee.mp_melee_system_camera_lock_crouch_height_offset; } dirToTarget = targetPos - pOwner->GetEntity()->GetWorldPos(); dirToTarget.Normalize(); static const float smooth_time = 0.1f; SmoothCD(m_attackTurnAmount, m_attackTurnAmountSmoothRate, frameTime, 1.f, smooth_time); Quat newViewRotation; newViewRotation.SetSlerp(pOwner->GetViewRotation(), Quat::CreateRotationVDir(dirToTarget), m_attackTurnAmount); Ang3 newAngles(newViewRotation); newAngles.y = 0.f; //No head tilting newViewRotation = Quat(newAngles); pOwner->SetViewRotation( newViewRotation ); } if(m_attackTime >= g_pGameCVars->pl_melee.mp_melee_system_camera_lock_time && pOwner && pOwner->IsClient()) { pOwner->GetActorParams().viewLimits.ClearViewLimit(SViewLimitParams::eVLS_Item); } } if (m_attacking) { MeleeDebugLog ("CMelee<%p> Update while attacking: m_attacked=%d, delay=%f", this, m_attacked, m_delayTimer); requireUpdate = true; if (m_delayTimer>0.0f) { RequestAlignmentToNearestTarget(); m_delayTimer-=frameTime; if (m_delayTimer<=0.0f) { m_delayTimer=0.0f; } } else if (m_netAttacking) { remote = true; doMelee = true; m_attacking = false; m_slideKick = false; m_netAttacking = false; m_pWeapon->SetBusy(false); } else if (!m_attacked) { doMelee = true; m_attacked = true; } if ( !m_collisionHelper.IsBlocked() && doMelee) { if (CActor *pActor = m_pWeapon->GetOwnerActor()) { if (IMovementController * pMC = pActor->GetMovementController()) { SMovementState info; pMC->GetMovementState(info); if(!dirToTarget.IsZeroFast()) { PerformMelee(info.weaponPosition, dirToTarget, remote); //We know where we will be facing at the point of impact - using our current fire direction is not accurate enough } else { PerformMelee(info.weaponPosition, info.fireDirection, remote); } } } } if( (m_useMeleeWeaponDelay <= 0.0f && m_useMeleeWeaponDelay > -1.0f) ) { m_useMeleeWeaponDelay = -1.0f; // Switch to the MELEE WEAPON. SwitchToMeleeWeaponAndAttack(); m_attacking = false; } m_useMeleeWeaponDelay -= frameTime; } if (requireUpdate) m_pWeapon->RequireUpdate(eIUS_FireMode); }
CGame::CGame() : m_pGameFramework(nullptr) { GetISystem()->SetIGame(this); }
//------------------------------------------------------------------------ void CVehicleMovementStdBoat::UpdateSurfaceEffects(const float deltaTime) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); if(0 == g_pGameCVars->v_pa_surface) { ResetParticles(); return; } IEntity *pEntity = m_pVehicle->GetEntity(); const Matrix34 &worldTM = pEntity->GetWorldTM(); float distSq = worldTM.GetTranslation().GetSquaredDistance(gEnv->pRenderer->GetCamera().GetPosition()); if(distSq > sqr(300.f) || (distSq > sqr(50.f) && !m_pVehicle->GetGameObject()->IsProbablyVisible())) return; Matrix34 worldTMInv = worldTM.GetInverted(); const SVehicleStatus &status = m_pVehicle->GetStatus(); float velDot = status.vel * worldTM.GetColumn1(); float powerNorm = min(abs(m_movementAction.power), 1.f); SEnvironmentParticles *envParams = m_pPaParams->GetEnvironmentParticles(); SEnvParticleStatus::TEnvEmitters::iterator end = m_paStats.envStats.emitters.end(); for(SEnvParticleStatus::TEnvEmitters::iterator emitterIt = m_paStats.envStats.emitters.begin(); emitterIt!=end; ++emitterIt) { if(emitterIt->layer < 0) { assert(0); continue; } const SEnvironmentLayer &layer = envParams->GetLayer(emitterIt->layer); SEntitySlotInfo info; info.pParticleEmitter = 0; pEntity->GetSlotInfo(emitterIt->slot, info); float countScale = 1.f; float sizeScale = 1.f; float speedScale = 1.f; float speed = 0.f; // check if helper position is beneath water level Vec3 emitterWorldPos = worldTM * emitterIt->quatT.t; float waterLevel = gEnv->p3DEngine->GetWaterLevel(&emitterWorldPos); int matId = 0; if(emitterWorldPos.z <= waterLevel+0.1f && m_statusDyn.submergedFraction<0.999f) { matId = gEnv->pPhysicalWorld->GetWaterMat(); speed = status.speed; bool spray = !strcmp(layer.GetName(), "spray"); if(spray) { // slip based speed -= abs(velDot); } GetParticleScale(layer, speed, powerNorm, countScale, sizeScale, speedScale); } else { countScale = 0.f; } if(matId && matId != emitterIt->matId) { // change effect IParticleEffect *pEff = 0; const char *effect = GetEffectByIndex(matId, layer.GetName()); if(effect && (pEff = gEnv->pParticleManager->FindEffect(effect))) { #if ENABLE_VEHICLE_DEBUG if(DebugParticles()) CryLog("%s changes water sfx to %s (slot %i)", pEntity->GetName(), effect, emitterIt->slot); #endif if(info.pParticleEmitter) { info.pParticleEmitter->Activate(false); pEntity->FreeSlot(emitterIt->slot); } emitterIt->slot = pEntity->LoadParticleEmitter(emitterIt->slot, pEff); if(emitterIt->slot != -1) pEntity->SetSlotLocalTM(emitterIt->slot, Matrix34(emitterIt->quatT)); info.pParticleEmitter = 0; pEntity->GetSlotInfo(emitterIt->slot, info); } else countScale = 0.f; } if(matId) emitterIt->matId = matId; if(info.pParticleEmitter) { SpawnParams sp; sp.fSizeScale = sizeScale; sp.fCountScale = countScale; sp.fSpeedScale = speedScale; info.pParticleEmitter->SetSpawnParams(sp); if(layer.alignToWater && countScale > 0.f) { Vec3 worldPos(emitterWorldPos.x, emitterWorldPos.y, waterLevel+0.05f); Matrix34 localTM(emitterIt->quatT); localTM.SetTranslation(worldTMInv * worldPos); pEntity->SetSlotLocalTM(emitterIt->slot, localTM); } } #if ENABLE_VEHICLE_DEBUG if(DebugParticles() && m_pVehicle->IsPlayerDriving()) { float color[] = {1,1,1,1}; ColorB red(255,0,0,255); IRenderAuxGeom *pAuxGeom = gEnv->pRenderer->GetIRenderAuxGeom(); const char *effect = info.pParticleEmitter ? info.pParticleEmitter->GetName() : ""; const Matrix34 &slotTM = m_pEntity->GetSlotWorldTM(emitterIt->slot); Vec3 ppos = slotTM.GetTranslation(); pAuxGeom->DrawSphere(ppos, 0.2f, red); pAuxGeom->DrawCone(ppos, slotTM.GetColumn1(), 0.1f, 0.5f, red); gEnv->pRenderer->Draw2dLabel(50.f, (float)(400+10*emitterIt->slot), 1.2f, color, false, "<%s> water fx: slot %i [%s], speed %.1f, sizeScale %.2f, countScale %.2f (pos %.0f,%0.f,%0.f)", pEntity->GetName(), emitterIt->slot, effect, speed, sizeScale, countScale, ppos.x, ppos.y, ppos.z); } #endif } // generate water splashes Vec3 wakePos; if(m_pSplashPos) { wakePos = m_pSplashPos->GetWorldSpaceTranslation(); } else { wakePos = worldTM.GetTranslation(); } float wakeWaterLevel = gEnv->p3DEngine->GetWaterLevel(&wakePos); Vec3 localW = worldTMInv.TransformVector(m_statusDyn.w); if(localW.x >= 0.f) m_diving = false; if(!m_diving && localW.x < -0.03f && status.speed > 10.f && wakePos.z < m_lastWakePos.z && wakeWaterLevel+0.1f >= wakePos.z) { float speedRatio = min(1.f, status.speed/m_maxSpeed); m_diving = true; if(m_pWaveEffect) { if(IParticleEmitter *pEmitter = pEntity->GetParticleEmitter(m_wakeSlot)) { pEmitter->Activate(false); pEntity->FreeSlot(m_wakeSlot); m_wakeSlot = -1; } SpawnParams spawnParams; spawnParams.fSizeScale = spawnParams.fCountScale = 0.5f + 0.25f*speedRatio; spawnParams.fSizeScale += 0.4f*m_waveRandomMult; spawnParams.fCountScale += 0.4f*Random(); m_wakeSlot = pEntity->LoadParticleEmitter(m_wakeSlot, m_pWaveEffect, &spawnParams); } // handle splash sound PlaySound(eSID_Splash, 0.f, Vec3(0,5,1)); SetSoundParam(eSID_Splash, "intensity", 0.2f*speedRatio + 0.5f*m_waveRandomMult); if(m_rpmPitchDir == 0) { m_rpmPitchDir = -1; m_waveSoundPitch = 0.f; m_waveSoundAmount = 0.02f + m_waveRandomMult*0.08f; } } if(m_wakeSlot != -1) { // update emitter local pos to short above waterlevel Matrix34 tm; if(m_pSplashPos) m_pSplashPos->GetVehicleTM(tm); else tm.SetIdentity(); Vec3 pos = tm.GetTranslation(); pos.z = worldTMInv.TransformPoint(Vec3(wakePos.x,wakePos.y,wakeWaterLevel)).z + 0.2f; tm.SetTranslation(pos); pEntity->SetSlotLocalTM(m_wakeSlot, tm); #if ENABLE_VEHICLE_DEBUG if(IsProfilingMovement()) { Vec3 wPos = worldTM * tm.GetTranslation(); ColorB col(128, 128, 0, 200); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(wPos, 0.4f, col); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(wPos, col, wPos+Vec3(0,0,1.5f), col); } #endif } m_lastWakePos = wakePos; }
//------------------------------------------------------------------------ void CVehicleMovementVTOL::Update(const float deltaTime) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); CVehicleMovementHelicopter::Update(deltaTime); CryAutoCriticalSection lk(m_lock); if(m_pWingsAnimation) { m_pWingsAnimation->SetTime(m_wingsAnimTime); } IActorSystem *pActorSystem = g_pGame->GetIGameFramework()->GetIActorSystem(); assert(pActorSystem); IActor *pActor = pActorSystem->GetActor(m_actorId); if(pActor && pActor->IsClient()) { float turbulence = m_turbulence; if(m_pAltitudeLimitVar) { float altitudeLimit = m_pAltitudeLimitVar->GetFVal(); float currentHeight = m_pEntity->GetWorldPos().z; if(!iszero(altitudeLimit)) { float altitudeLowerOffset; if(m_pAltitudeLimitLowerOffsetVar) { float r = 1.0f - min(1.0f, max(0.0f, m_pAltitudeLimitLowerOffsetVar->GetFVal())); altitudeLowerOffset = r * altitudeLimit; if(currentHeight >= altitudeLowerOffset) { if(currentHeight > altitudeLowerOffset) { float zone = altitudeLimit - altitudeLowerOffset; turbulence += (currentHeight - altitudeLowerOffset) / (zone); } } } } } if(turbulence > 0.0f) { static_cast<CActor *>(pActor)->CameraShake(0.50f * turbulence, 0.0f, 0.05f, 0.04f, Vec3(0.0f, 0.0f, 0.0f), 10, "VTOL_Update_Turbulence"); } float enginePowerRatio = m_enginePower / m_enginePowerMax; if(enginePowerRatio > 0.0f) { float rpmScaleDesired = 0.2f; rpmScaleDesired += abs(m_forwardAction) * 0.8f; rpmScaleDesired += abs(m_strafeAction) * 0.4f; rpmScaleDesired += abs(m_turnAction) * 0.25f; rpmScaleDesired = min(1.0f, rpmScaleDesired); Interpolate(m_rpmScale, rpmScaleDesired, 1.0f, deltaTime); } float turnParamGoal = min(1.0f, abs(m_turnAction)) * 0.6f; turnParamGoal *= (min(1.0f, max(0.0f, m_speedRatio)) + 1.0f) * 0.50f; turnParamGoal += turnParamGoal * m_boost * 0.25f; Interpolate(m_soundParamTurn, turnParamGoal, 0.5f, deltaTime); SetSoundParam(eSID_Run, "turn", m_soundParamTurn); float damage = GetSoundDamage(); if(damage > 0.1f) { //if (ISound* pSound = GetOrPlaySound(eSID_Damage, 5.f, m_enginePos)) //SetSoundParam(pSound, "damage", damage); } } }
bool CScriptSurfaceType::Load( int nId ) { m_nId = nId; IScriptSystem *pScriptSystem = gEnv->pScriptSystem; SmartScriptTable mtlTable; if (!pScriptSystem->GetGlobalValue("Materials", mtlTable)) { return false; } ////////////////////////////////////////////////////////////////////////// if (!pScriptSystem->ExecuteFile( m_script,true )) { GetISystem()->Warning( VALIDATOR_MODULE_3DENGINE,VALIDATOR_WARNING, VALIDATOR_FLAG_FILE|VALIDATOR_FLAG_SCRIPT, m_script.c_str(), "'%s' failed to load surface type definition script",m_name.c_str() ); return false; } if (!mtlTable->GetValue( m_name,m_pScriptTable )) return false; XmlNodeRef matNode = m_root->newChild("SurfaceType"); matNode->setAttr( "name",m_name ); // Load physics params. SmartScriptTable pPhysicsTable,props; float fBouncyness = 0.0f; float fFriction = 1.0f; int iPiercingResistence = sf_max_pierceable; // physics traces range 0-15 int imatBreakable = -1, bManuallyBreakable=0; m_iBreakability=0; m_nHitpoints=0; m_breakEnergy=0; if (m_pScriptTable->GetValue("physics",pPhysicsTable)) { pPhysicsTable->GetValue("friction",fFriction); pPhysicsTable->GetValue("bouncyness",fBouncyness); pPhysicsTable->GetValue("breakable_id",imatBreakable); if (pPhysicsTable->GetValue("pierceability",iPiercingResistence)) { if(iPiercingResistence>sf_max_pierceable) iPiercingResistence = sf_max_pierceable; } int nBreakable2d = 0; int bNoCollide = 0; pPhysicsTable->GetValue("no_collide", bNoCollide); if (pPhysicsTable->GetValue("break_energy",m_breakEnergy)) { bManuallyBreakable = sf_manually_breakable; m_iBreakability = 2; pPhysicsTable->GetValue("hit_points",m_nHitpoints); } else if (m_pScriptTable->GetValue("breakable_2d",props)) { nBreakable2d = 1; bManuallyBreakable = sf_manually_breakable; m_iBreakability = 1; props->GetValue("break_energy",m_breakEnergy); props->GetValue("hit_points",m_nHitpoints); } m_nFlags &= ~SURFACE_TYPE_NO_COLLIDE; if (bNoCollide) m_nFlags |= SURFACE_TYPE_NO_COLLIDE; XmlNodeRef physNode = matNode->newChild("Physics"); physNode->setAttr( "friction",fFriction ); physNode->setAttr( "elasticity",fBouncyness ); physNode->setAttr( "breakable_id",imatBreakable ); physNode->setAttr( "pierceability",iPiercingResistence ); physNode->setAttr( "no_collide",bNoCollide ); physNode->setAttr( "break_energy",m_breakEnergy ); physNode->setAttr( "hit_points",m_nHitpoints ); physNode->setAttr( "breakable_2d",nBreakable2d ); } SmartScriptTable pAITable; if (m_pScriptTable->GetValue("AI",pAITable)) { XmlNodeRef aiNode = matNode->newChild("AI"); float fImpactRadius = 1; float fFootStepRadius = 1; float proneMult = 1; float crouchMult = 1; float movingMult = 1; pAITable->GetValue( "fImpactRadius",fImpactRadius ); pAITable->GetValue( "fFootStepRadius",fFootStepRadius ); pAITable->GetValue( "proneMult",proneMult ); pAITable->GetValue( "crouchMult",crouchMult ); pAITable->GetValue( "movingMult",movingMult ); aiNode->setAttr( "fImpactRadius",fImpactRadius ); aiNode->setAttr( "fFootStepRadius",fFootStepRadius ); aiNode->setAttr( "proneMult",proneMult ); aiNode->setAttr( "crouchMult",crouchMult ); aiNode->setAttr( "movingMult",movingMult ); } gEnv->pPhysicalWorld->SetSurfaceParameters(m_nId,fBouncyness,fFriction, (uint32)(sf_pierceability(iPiercingResistence) | sf_matbreakable(imatBreakable) | bManuallyBreakable)); return true; }
bool CScriptSurfaceTypesLoader::LoadSurfaceTypes( const char *sFolder,bool bReload ) { { if (!gEnv->p3DEngine) return false; I3DEngine *pEngine = gEnv->p3DEngine; ISurfaceTypeEnumerator *pEnum = pEngine->GetMaterialManager()->GetSurfaceTypeManager()->GetEnumerator(); if (pEnum) { for (ISurfaceType *pSurfaceType = pEnum->GetFirst(); pSurfaceType; pSurfaceType = pEnum->GetNext()) { SmartScriptTable mtlTable(gEnv->pScriptSystem); gEnv->pScriptSystem->SetGlobalValue( pSurfaceType->GetName(),mtlTable ); SmartScriptTable aiTable(gEnv->pScriptSystem); mtlTable->SetValue("AI",aiTable); aiTable->SetValue( "fImpactRadius",5.0f ); aiTable->SetValue( "fFootStepRadius",15.0f ); aiTable->SetValue( "proneMult",0.2f ); aiTable->SetValue( "crouchMult",0.5f ); aiTable->SetValue( "movingMult",2.5f ); } pEnum->Release(); } } return true; // Do not load surface types from script anymore. m_root = GetISystem()->CreateXmlNode("SurfaceTypes"); IScriptSystem *pScriptSystem = gEnv->pScriptSystem; ////////////////////////////////////////////////////////////////////////// // Make sure Materials table exist. ////////////////////////////////////////////////////////////////////////// SmartScriptTable mtlTable; if (!pScriptSystem->GetGlobalValue("Materials", mtlTable) || bReload) { mtlTable = pScriptSystem->CreateTable(); pScriptSystem->SetGlobalValue("Materials", mtlTable); } ICryPak *pIPak = gEnv->pCryPak; ISurfaceTypeManager *pSurfaceManager = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager(); if (!bReload) stl::push_back_unique( m_folders,sFolder ); string searchFolder = string(sFolder) + "/";; string searchFilter = searchFolder + "mat_*.lua"; gEnv->pScriptSystem->ExecuteFile(searchFolder+"common.lua", false, bReload); _finddata_t fd; intptr_t fhandle; fhandle = pIPak->FindFirst( searchFilter,&fd ); if (fhandle != -1) { do { // Skip back folders. if (fd.attrib & _A_SUBDIR) // skip if directory. continue; char name[_MAX_PATH]; _splitpath( fd.name,NULL,NULL,name,NULL ); if (strlen(name) == 0) continue; if (bReload) { ISurfaceType *pSurfaceType = pSurfaceManager->GetSurfaceTypeByName(name); if (pSurfaceType) { pSurfaceType->Load( pSurfaceType->GetId() ); continue; } } ISurfaceType *pSurfaceType = new CScriptSurfaceType( this,name,searchFolder+fd.name,0 ); if (pSurfaceManager->RegisterSurfaceType( pSurfaceType )) m_surfaceTypes.push_back(pSurfaceType); else pSurfaceType->Release(); } while (pIPak->FindNext( fhandle,&fd ) == 0); pIPak->FindClose(fhandle); } if (m_root) { m_root->saveToFile( "SurfaceTypes.xml" ); } return true; }
void CPlayerRotation::TargetAimAssistance(CWeapon* pWeapon, float& followH, float& followV, float& scale, float& _fZoomAmount, const Vec3 playerView[4]) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); CRY_ASSERT(m_player.IsClient()); followH = 0.0f; followV = 0.0f; scale = 1.0f; float bestScale = 1.0f; const Vec3 playerFwd = playerView[1]; const Vec3 playerRgt = playerView[0]; const Vec3 playerUp = playerView[2]; const Vec3 playerPos = playerView[3]; Vec3 follow_target_pos(ZERO); float follow_vote_leader = 0.0f; float snap_vote_leader = 0.0f; Vec3 follow_target_dir(ZERO); Vec3 snap_target_dir(ZERO); EntityId follow_target_id = 0; EntityId snap_target_id = 0; CGameRules * pGameRules = g_pGame->GetGameRules(); float distance_follow_threshold_near = max(0.0f, g_pGameCVars->aim_assistMinDistance); float distance_follow_threshold_far = max(20.0f, g_pGameCVars->aim_assistMaxDistance); int playerTeam = pGameRules->GetTeam(m_player.GetEntity()->GetId()); float cloakedPlayerMultiplier = g_pGameCVars->pl_aim_cloaked_multiplier; const bool multipleTeams = pGameRules->GetTeamCount() > 0; const float fFollowFalloffDist = g_pGameCVars->aim_assistFalloffDistance + FLT_EPSILON*g_pGameCVars->aim_assistFalloffDistance; const bool playerIsScoped = m_player.GetActorStats()->isScoped; float minTurnScale, fAimAssistStrength, fMaxDistMult; if(pWeapon) { const float fZoomAmount = pWeapon->GetZoomTransition(); _fZoomAmount = fZoomAmount; const float fStrength = g_pGameCVars->aim_assistStrength; const float fStrengthIronSight = playerIsScoped ? g_pGameCVars->aim_assistStrength_SniperScope : g_pGameCVars->aim_assistStrength_IronSight; const float fDiff = fStrengthIronSight - fStrength; fAimAssistStrength = fStrength + (fZoomAmount * fDiff); const float fMinTurn = g_pGameCVars->aim_assistMinTurnScale; const float fMinTurnIronSight = playerIsScoped ? g_pGameCVars->aim_assistMinTurnScale_SniperScope : g_pGameCVars->aim_assistMinTurnScale_IronSight; const float fMinTurnDiff = fMinTurnIronSight - fMinTurn; minTurnScale = fMinTurn + (fZoomAmount * fMinTurnDiff); const float fMaxAssistDist = g_pGameCVars->aim_assistMaxDistance; const float fMaxAssistDist_Iron = playerIsScoped ? g_pGameCVars->aim_assistMaxDistance_SniperScope : g_pGameCVars->aim_assistMaxDistance_IronSight; const float fMaxAssistDistDiff = (fMaxAssistDist_Iron - fMaxAssistDist) * fZoomAmount; fMaxDistMult = (fMaxAssistDist + fMaxAssistDistDiff) * __fres(fMaxAssistDist); } else { _fZoomAmount = 0.0f; fMaxDistMult = 1.0f; fAimAssistStrength = g_pGameCVars->aim_assistStrength; minTurnScale = g_pGameCVars->aim_assistMinTurnScale; } const float falloffStartDistance = g_pGameCVars->aim_assistSlowFalloffStartDistance; const float falloffPerMeter = 1.0f / (g_pGameCVars->aim_assistSlowDisableDistance - falloffStartDistance); const TAutoaimTargets& aaTargets = g_pGame->GetAutoAimManager().GetAutoAimTargets(); const int targetCount = aaTargets.size(); float fBestTargetDistance = FLT_MAX; #if DBG_AUTO_AIM SAuxGeomRenderFlags oldFlags = gEnv->pRenderer->GetIRenderAuxGeom()->GetRenderFlags(); SAuxGeomRenderFlags newFlags = e_Def3DPublicRenderflags; newFlags.SetAlphaBlendMode(e_AlphaBlended); newFlags.SetDepthTestFlag(e_DepthTestOff); newFlags.SetCullMode(e_CullModeNone); gEnv->pRenderer->GetIRenderAuxGeom()->SetRenderFlags(newFlags); #endif for (int i = 0; i < targetCount; ++i) { const SAutoaimTarget& target = aaTargets[i]; CRY_ASSERT(target.entityId != m_player.GetEntityId()); //Skip friendly ai if(gEnv->bMultiplayer) { if(multipleTeams && (pGameRules->GetTeam(target.entityId) == playerTeam)) { continue; } } else { if (target.HasFlagSet(eAATF_AIHostile) == false) continue; distance_follow_threshold_far = fMaxDistMult * (target.HasFlagSet(eAATF_AIRadarTagged) ? g_pGameCVars->aim_assistMaxDistanceTagged : g_pGameCVars->aim_assistMaxDistance); } Vec3 targetPos = target.primaryAimPosition; Vec3 targetDistVec = (targetPos - playerPos); float distance = targetDistVec.GetLength(); if (distance <= 0.1f) continue; Vec3 dirToTarget = targetDistVec / distance; // fast reject everything behind player, too far away or too near from line of view // sort rest by angle to crosshair and distance from player float alignment = playerFwd * dirToTarget; if (alignment <= 0.0f) continue; if ((distance < distance_follow_threshold_near) || (distance > distance_follow_threshold_far)) continue; const int kAutoaimVisibilityLatency = 2; CPlayerVisTable::SVisibilityParams visParams(target.entityId); visParams.queryParams = eVQP_IgnoreGlass; if (!g_pGame->GetPlayerVisTable()->CanLocalPlayerSee(visParams, kAutoaimVisibilityLatency)) { // Since both player and target entities are ignored, and the ray still intersected something, there's something in the way. // Need to profile this and see if it's faster to do the below checks before doing the linetest. It's fairly expensive but // linetests generally are as well... - Richard continue; } #if DBG_AUTO_AIM const ColorB green(0,255,0,255); const ColorB darkgreen(0,155,0,225); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine( playerPos, darkgreen, targetPos, green); #endif const float angleDot = dirToTarget.dot(-playerRgt); const float angle = (RAD2DEG(cry_acosf(angleDot)) - 90.f); const float absAngle = fabsf(angle); const float angleDotV = playerUp.dot(dirToTarget); const float angleToTargetV = (RAD2DEG(cry_acosf(angleDotV)) - 90.f); const float absAngleV = fabsf(angleToTargetV); const float slowModifiedDistance = distance * g_pGameCVars->aim_assistSlowDistanceModifier; const float radius_slow_threshold_inner = 0.5f; const float radius_slow_threshold_outer = g_pGameCVars->aim_assistSlowThresholdOuter; const float angle_slow_threshold_inner = RAD2DEG(cry_atanf(radius_slow_threshold_inner / slowModifiedDistance)); const float angle_slow_threshold_outer = RAD2DEG(cry_atanf(radius_slow_threshold_outer / slowModifiedDistance)); float angle_slow_fractionH = clamp((absAngle - angle_slow_threshold_inner) / (angle_slow_threshold_outer - angle_slow_threshold_inner), 0.0f, 1.0f); float angle_slow_fractionV = clamp((absAngleV - angle_slow_threshold_inner) / (angle_slow_threshold_outer - angle_slow_threshold_inner), 0.0f, 1.0f); float angle_slow_fraction = max(angle_slow_fractionH, angle_slow_fractionV); const float distance_follow_fraction = clamp((distance - fFollowFalloffDist) / (distance_follow_threshold_far - fFollowFalloffDist), 0.0f, 1.0f); const float radius_follow_threshold_inner = target.innerRadius; const float radius_follow_threshold_outer = target.outerRadius; const float radius_snap = target.HasFlagSet(eAATF_AIRadarTagged) ? target.snapRadiusTagged * g_pGameCVars->aim_assistSnapRadiusTaggedScale : target.snapRadius * g_pGameCVars->aim_assistSnapRadiusScale; const float angle_follow_threshold_inner = RAD2DEG(cry_atanf(radius_follow_threshold_inner / distance)); const float angle_follow_threshold_outer = RAD2DEG(cry_atanf(radius_follow_threshold_outer / distance)); const float angle_follow_fraction = clamp((absAngle - angle_follow_threshold_inner) / (angle_follow_threshold_outer - angle_follow_threshold_inner), 0.0f, 1.0f); const float angle_follow_fractionV = clamp((absAngleV - angle_follow_threshold_inner) / (angle_follow_threshold_outer - angle_follow_threshold_inner), 0.0f, 1.0f); const float worst_follow_fraction = (float)__fsel(angle_follow_fraction - angle_follow_fractionV, angle_follow_fraction, angle_follow_fractionV); float follow_fraction = ((1.0f - worst_follow_fraction) * (1.0f - distance_follow_fraction)); float follow_vote = follow_fraction; //clamp the lower bound of the distance_slow_modifier so it can't be lower than the angle slow fraction // which prevents close but off-centre targets slowing us too much const float distance_slow_modifier = clamp( 1.0f - ((distance - falloffStartDistance) * falloffPerMeter), angle_slow_fraction, 1.0f); const float fCombinedModifier = angle_slow_fraction * distance_slow_modifier; fBestTargetDistance = (float)__fsel(fCombinedModifier - bestScale, fBestTargetDistance, distance); bestScale = min(fCombinedModifier, bestScale); if (follow_vote > follow_vote_leader) { follow_vote_leader = follow_vote; //m_follow_target_id only gets set after the loop -> this won't get hit when a target is selected // as a follow target for the first time. This doesn't need to be in the loop. if ( m_follow_target_id == target.entityId) { const Vec3 follow_target_dir_local = m_follow_target_dir; Vec3 target_rgt = playerRgt; Vec3 target_up = target_rgt.cross(follow_target_dir_local); target_rgt = follow_target_dir_local.cross(target_up); target_rgt.Normalize(); target_up.Normalize(); float alignH = dirToTarget * -target_rgt; float alignV = dirToTarget.z - follow_target_dir_local.z; float angleH = min(fabsf(alignH * fAimAssistStrength), fabsf(angleDot)); float angleV = min(fabsf(alignV * fAimAssistStrength), fabsf(angleDotV)); followH = follow_fraction * (float)__fsel(angleDot, angleH, -angleH); followV = follow_fraction * (float)__fsel(angleDotV, angleV, -angleV); follow_vote_leader += 0.05f; // anti oscillation between different targets follow_target_pos = targetPos; } follow_target_id = target.entityId; snap_target_id = target.entityId; follow_target_dir = dirToTarget; snap_target_dir = PickBestSnapDirection(playerPos, playerFwd, target); } else if (!follow_target_id && (radius_snap > 0.0f)) { Lineseg lineSegment; lineSegment.start = playerPos; lineSegment.end = playerPos + (playerFwd * (distance + radius_snap)); Sphere sphere; sphere.center = targetPos; sphere.radius = radius_snap; Vec3 intersectionPoint; if (Intersect::Lineseg_SphereFirst(lineSegment, sphere, intersectionPoint)) { float t = 0.0f; const float snap_fraction = 1.0f - (Distance::Point_Lineseg(targetPos, lineSegment, t) * (float)__fres(radius_snap)); if (snap_fraction > snap_vote_leader) { snap_vote_leader = snap_fraction; snap_target_id = target.entityId; snap_target_dir = PickBestSnapDirection(playerPos, playerFwd, target); } } } } #if DBG_AUTO_AIM if ((!follow_target_pos.IsZeroFast()) && (g_pGameCVars->pl_targeting_debug != 0)) { float radius_inner = 0.30f; float radius_outer = 0.33f; ColorB colorInner(255,255,0,0x40); ColorB colorOuter(255,255,0,0x40); DrawDisc(follow_target_pos, follow_target_dir, radius_inner, radius_outer, colorInner, colorOuter); } gEnv->pRenderer->GetIRenderAuxGeom()->SetRenderFlags(oldFlags); #endif m_follow_target_id = follow_target_id; m_follow_target_dir = follow_target_dir; //IMPORTANT: Apply the minimum-distance scaling of the slowdown _after_ calculating the slowdown for the best target // as we want to help the player aim at the nearest target, and modifying the slowdown multiplier prior to this // could result in a different target being selected const float fSlowDownProximityFadeInBand = (g_pGameCVars->aim_assistSlowStopFadeinDistance - g_pGameCVars->aim_assistSlowStartFadeinDistance) + FLT_EPSILON; float fSlowDownProximityScale = (fBestTargetDistance - g_pGameCVars->aim_assistSlowStartFadeinDistance) / fSlowDownProximityFadeInBand; Limit(fSlowDownProximityScale, 0.0f, 1.0f); float fInvBestScale = (1.0f - bestScale) * fSlowDownProximityScale; bestScale = 1.0f - fInvBestScale; scale = minTurnScale + ((1.0f - minTurnScale) * bestScale); UpdateCurrentSnapTarget(snap_target_id, snap_target_dir); }
////////////////////////////////////////////////////////////////////////// // NOTE: This function must be thread-safe. Before adding stuff contact MarcoC. void CVehicleMovementStdBoat::ProcessMovement(const float deltaTime) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); static const float fWaterLevelMaxDiff = 0.15f; // max allowed height difference between propeller center and water level static const float fSubmergedMin = 0.01f; static const float fMinSpeedForTurn = 0.5f; // min speed so that turning becomes possible if(m_bNetSync) m_netActionSync.UpdateObject(this); CryAutoCriticalSection lk(m_lock); CVehicleMovementBase::ProcessMovement(deltaTime); IEntity *pEntity = m_pVehicle->GetEntity(); IPhysicalEntity *pPhysics = pEntity->GetPhysics(); assert(pPhysics); float frameTime = min(deltaTime, 0.1f); if(abs(m_movementAction.power) < 0.001f) m_movementAction.power = 0.f; if(abs(m_movementAction.rotateYaw) < 0.001f) m_movementAction.rotateYaw = 0.f; Matrix34 wTM(m_PhysPos.q); wTM.AddTranslation(m_PhysPos.pos); Matrix34 wTMInv = wTM.GetInvertedFast(); Vec3 localVel = wTMInv.TransformVector(m_PhysDyn.v); Vec3 localW = wTMInv.TransformVector(m_PhysDyn.w); const Vec3 xAxis = wTM.GetColumn0(); const Vec3 yAxis = wTM.GetColumn1(); const Vec3 zAxis = wTM.GetColumn2(); // check if propeller is in water Vec3 worldPropPos = wTM * m_pushOffset; float waterLevelWorld = gEnv->p3DEngine->GetWaterLevel(&worldPropPos); float fWaterLevelDiff = worldPropPos.z - waterLevelWorld; bool submerged = m_PhysDyn.submergedFraction > fSubmergedMin; m_inWater = submerged && fWaterLevelDiff < fWaterLevelMaxDiff; float speed = m_PhysDyn.v.len2() > 0.001f ? m_PhysDyn.v.len() : 0.f; float speedRatio = min(1.f, speed/m_maxSpeed); float absPedal = abs(m_movementAction.power); float absSteer = abs(m_movementAction.rotateYaw); // wave stuff float waveFreq = 1.f; waveFreq += 3.f*speedRatio; float waveTimerPrev = m_waveTimer; m_waveTimer += frameTime*waveFreq; // new randomized amount for this oscillation if(m_waveTimer >= gf_PI && waveTimerPrev < gf_PI) m_waveRandomMult = Random(); if(m_waveTimer >= 2*gf_PI) m_waveTimer -= 2*gf_PI; float kx = m_waveIdleStrength.x*(m_waveRandomMult+0.3f) * (1.f-speedRatio + m_waveSpeedMult*speedRatio); float ky = m_waveIdleStrength.y * (1.f - 0.5f*absPedal - 0.5f*absSteer); Vec3 waveLoc = m_massOffset; waveLoc.y += speedRatio*min(0.f, m_pushOffset.y-m_massOffset.y); waveLoc = wTM * waveLoc; bool visible = m_pVehicle->GetGameObject()->IsProbablyVisible(); bool doWave = visible && submerged && m_PhysDyn.submergedFraction < 0.99f; if(doWave && !m_isEnginePowered) m_pVehicle->NeedsUpdate(IVehicle::eVUF_AwakePhysics, true); if(m_isEnginePowered || (visible && !m_pVehicle->IsProbablyDistant())) { if(doWave && (m_isEnginePowered || g_pGameCVars->v_rockBoats)) { pe_action_impulse waveImp; waveImp.angImpulse.x = Boosting() ? 0.f : sinf(m_waveTimer) * frameTime * m_Inertia.x * kx; if(isneg(waveImp.angImpulse.x)) waveImp.angImpulse.x *= (1.f - min(1.f, 2.f*speedRatio)); // less amplitude for negative impulse waveImp.angImpulse.y = sinf(m_waveTimer-0.5f*gf_PI) * frameTime * m_Inertia.y * ky; waveImp.angImpulse.z = 0.f; waveImp.angImpulse = wTM.TransformVector(waveImp.angImpulse); waveImp.point = waveLoc; if(!m_movementAction.isAI) pPhysics->Action(&waveImp, 1); } } // ~wave stuff if(!m_isEnginePowered) return; pe_action_impulse linearImp, angularImp, dampImp, liftImp; float turnAccel = 0, turnAccelNorm = 0; if(m_inWater) { // Lateral damping if(m_lateralDamping>0.f) { pe_action_impulse impulse; impulse.impulse = - m_PhysDyn.mass * xAxis * (localVel.x * (frameTime * m_lateralDamping)/(1.f + frameTime*m_lateralDamping)); pPhysics->Action(&impulse, 1); } // optional lifting (catamarans) if(m_velLift > 0.f) { if(localVel.y > m_velLift && !IsLifted()) Lift(true); else if(localVel.y < m_velLift && IsLifted()) Lift(false); } if(Boosting() && IsLifted()) { // additional lift force liftImp.impulse = Vec3(0,0,m_PhysDyn.mass*frameTime*(localVel.y/m_velMax)*3.f); liftImp.point = wTM * m_massOffset; pPhysics->Action(&liftImp, 1); } // apply driving force float a = m_movementAction.power; if(sgn(a)*sgn(localVel.y) > 0) { // reduce acceleration with increasing speed float ratio = (localVel.y > 0.f) ? localVel.y/m_velMax : -localVel.y/m_velMaxReverse; a = (ratio>1.f) ? 0.f : sgn(a)*min(abs(a), 1.f-((1.f-m_accelVelMax)*sqr(ratio))); } if(a != 0) { if(sgn(a) * sgn(localVel.y) < 0) // "braking" a *= m_accelCoeff; else a = max(a, -m_pedalLimitReverse); Vec3 pushDir(FORWARD_DIRECTION); // apply force downwards a bit for more realistic response if(a > 0) pushDir = Quat_tpl<float>::CreateRotationAA(DEG2RAD(m_pushTilt), Vec3(-1,0,0)) * pushDir; pushDir = wTM.TransformVector(pushDir); linearImp.impulse = pushDir * m_PhysDyn.mass * a * m_accel * frameTime; linearImp.point = m_pushOffset; linearImp.point.x = m_massOffset.x; linearImp.point = wTM * linearImp.point; pPhysics->Action(&linearImp, 1); } float roll = (float)__fsel(zAxis.z - 0.2f, xAxis.z / (frameTime + frameTime*frameTime), 0.f); // Roll damping (with a exp. time constant of 1 sec) // apply steering if(m_movementAction.rotateYaw != 0) { if(abs(localVel.y) < fMinSpeedForTurn) // if forward speed too small, no turning possible { turnAccel = 0; } else { int iDir = m_movementAction.power != 0.f ? sgn(m_movementAction.power) : sgn(localVel.y); turnAccelNorm = m_movementAction.rotateYaw * iDir * max(1.f, m_turnVelocityMult * speedRatio); // steering and current w in same direction? int sgnSteerW = sgn(m_movementAction.rotateYaw) * iDir * sgn(-localW.z); if(sgnSteerW < 0) { // "braking" turnAccelNorm *= m_turnAccelCoeff; } else { // reduce turn vel towards max float maxRatio = 1.f - 0.15f*min(1.f, abs(localW.z)/m_turnRateMax); turnAccelNorm = sgn(turnAccelNorm) * min(abs(turnAccelNorm), maxRatio); } turnAccel = turnAccelNorm * m_turnAccel; //roll = 0.2f * turnAccel; // slight roll } } // Use the centripetal acceleration to determine the amount of roll float centripetalAccel = clamp(speed * localW.z, -10.f, +10.f); roll -= (1.f - 2.f*fabsf(xAxis.z)) * m_rollAccel * centripetalAccel; // Always damp rotation! turnAccel += localW.z * m_turnDamping; if(turnAccel != 0) { Vec3 &angImp = angularImp.angImpulse; angImp.x = 0.f; angImp.y = roll * frameTime * m_Inertia.y; angImp.z = -turnAccel * frameTime * m_Inertia.z; angImp = wTM.TransformVector(angImp); pPhysics->Action(&angularImp, 1); } if(abs(localVel.x) > 0.01f) { // lateral force Vec3 &cornerForce = dampImp.impulse; cornerForce.x = -localVel.x * m_cornerForceCoeff * m_PhysDyn.mass * frameTime; cornerForce.y = 0.f; cornerForce.z = 0.f; if(m_cornerTilt != 0) cornerForce = Quat_tpl<float>::CreateRotationAA(sgn(localVel.x)*DEG2RAD(m_cornerTilt), Vec3(0,1,0)) * cornerForce; dampImp.impulse = wTM.TransformVector(cornerForce); dampImp.point = m_cornerOffset; dampImp.point.x = m_massOffset.x; dampImp.point = wTM.TransformPoint(dampImp.point); pPhysics->Action(&dampImp, 1); } } EjectionTest(deltaTime); if(m_bNetSync && m_netActionSync.PublishActions(CNetworkMovementStdBoat(this))) CHANGED_NETWORK_STATE(m_pVehicle, eEA_GameClientDynamic); }
//------------------------------------------------------------------------ void CWeapon::OnPickedUp(EntityId actorId, bool destroyed) { BROADCAST_WEAPON_EVENT(OnPickedUp, (this, actorId, destroyed)); BaseClass::OnPickedUp(actorId, destroyed); GetEntity()->SetFlags(GetEntity()->GetFlags() | ENTITY_FLAG_NO_PROXIMITY); // bonus ammo is always put in the actor's inv if (!m_bonusammo.empty()) { for (TAmmoVector::iterator it = m_bonusammo.begin(); it != m_bonusammo.end(); ++it) { const SWeaponAmmo& currentBonusAmmo = *it; SetInventoryAmmoCount(currentBonusAmmo.pAmmoClass, GetInventoryAmmoCount(currentBonusAmmo.pAmmoClass)+currentBonusAmmo.count); } m_bonusammo.clear(); } if(GetISystem()->IsSerializingFile() == 1) return; CActor *pActor = GetActor(actorId); if (!pActor) return; // current ammo is only added to actor's inv, if we already have this weapon if (destroyed && m_sharedparams->params.unique) { for (TAmmoVector::iterator it = m_ammo.begin(); it!=m_ammo.end(); ++it) { //Only add ammo to inventory, if not accessory ammo (accessories give ammo already) const SWeaponAmmo& currentAmmo = *it; const SWeaponAmmo* pAccessoryAmmo = SWeaponAmmoUtils::FindAmmo(m_weaponsharedparams->ammoParams.accessoryAmmo, currentAmmo.pAmmoClass); if(pAccessoryAmmo != NULL) { SetInventoryAmmoCount(currentAmmo.pAmmoClass, GetInventoryAmmoCount(currentAmmo.pAmmoClass)+currentAmmo.count); } } } TestClipAmmoCountIsValid(); if (!gEnv->bServer && pActor->IsPlayer()) { IEntityClass* pCurrentAmmoClass = m_fm ? m_fm->GetAmmoType() : NULL; if (pCurrentAmmoClass) { //server has serialised the inventory count already if(IInventory* pInventory = GetActorInventory(GetOwnerActor())) { if(m_lastRecvInventoryAmmo > pInventory->GetAmmoCapacity(pCurrentAmmoClass)) { pInventory->SetAmmoCapacity(pCurrentAmmoClass, m_lastRecvInventoryAmmo); } SetInventoryAmmoCountInternal(pInventory, pCurrentAmmoClass, m_lastRecvInventoryAmmo); } } } if(gEnv->bMultiplayer) { HighlightWeapon(false); } m_expended_ammo = 0; }
int CFlowConvoyNode::OnPhysicsPostStep(const EventPhys * pEvent) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); if(m_bFirstUpdate) return 0; //after QuickLoad OnPhysicsPostStep called before ProcessEvent const EventPhysPostStep *pPhysPostStepEvent = (const EventPhysPostStep *)pEvent; IPhysicalEntity *pEventPhysEnt = pPhysPostStepEvent->pEntity; Vec3 posBack, posFront, posCenter; for (size_t i = 0; i < m_coaches.size(); ++i) { IPhysicalEntity *pPhysEnt = m_coaches[i].m_pEntity->GetPhysics(); if (pEventPhysEnt == pPhysEnt) { if (m_ShiftTime > 0.0f) { m_speed = m_speed * (1.0f - breakValue * pPhysPostStepEvent->dt / m_MaxShiftTime); m_ShiftTime -= pPhysPostStepEvent->dt; } else { m_speed = m_speed + min(1.0f, (pPhysPostStepEvent->dt / 5.0f)) * (m_desiredSpeed - m_speed); } float speed = (m_splitCoachIndex > 0 && (int)i >= m_splitCoachIndex) ? m_splitSpeed : m_speed; float distance = (m_coaches[i].m_distanceOnPath += pPhysPostStepEvent->dt * speed); if(m_splitCoachIndex>0) {//train splitted if(i==m_splitCoachIndex-1) // update m_distanceOnPath for serialization m_distanceOnPath=distance-m_coaches[i].m_coachOffset; else if(i==m_coaches.size()-1) // update m_splitDistanceOnPath for serialization m_splitDistanceOnPath=distance-m_coaches[i].m_coachOffset; } else {//train in one piece if(i==m_coaches.size()-1)// update m_distanceOnPath for serialization m_distanceOnPath=distance-m_coaches[i].m_coachOffset; } posBack = m_path.GetPointAlongPath(distance - m_coaches[i].m_wheelDistance, m_coaches[i].m_backWheelIterator[0]); posFront = m_path.GetPointAlongPath(distance + m_coaches[i].m_wheelDistance, m_coaches[i].m_frontWheelIterator[0]); posCenter = (posBack+posFront)*0.5f; Vec3 posDiff = posFront - posBack; float magnitude = posDiff.GetLength(); if (magnitude > FLT_EPSILON) { posDiff *= 1.0f / magnitude; pe_params_pos ppos; ppos.pos = posCenter; ppos.q = Quat::CreateRotationVDir(posDiff); if (m_bXAxisFwd) ppos.q *= Quat::CreateRotationZ(gf_PI*-0.5f); pPhysEnt->SetParams(&ppos, 0 /* bThreadSafe=0 */); // as we are calling from the physics thread Vec3 futurePositionBack, futurePositionFront; futurePositionBack = m_path.GetPointAlongPath(distance + PATH_DERIVATION_TIME * speed - m_coaches[i].m_wheelDistance, m_coaches[i].m_backWheelIterator[1]); futurePositionFront = m_path.GetPointAlongPath(distance + PATH_DERIVATION_TIME * speed + m_coaches[i].m_wheelDistance, m_coaches[i].m_frontWheelIterator[1]); Vec3 futurePosDiff = futurePositionFront - futurePositionBack; magnitude = futurePosDiff.GetLength(); if (magnitude > FLT_EPSILON) { futurePosDiff *= 1.0f / magnitude; pe_action_set_velocity setVel; setVel.v = ((futurePositionBack+ futurePositionFront)*0.5f - posCenter) * (1.0f/PATH_DERIVATION_TIME); //Vec3 dir=(posFront-posBack).GetNormalized(); //Vec3 future_dir=(futurePositionFront-futurePositionBack).GetNormalized(); Vec3 w=posDiff.Cross(futurePosDiff); float angle=cry_asinf(w.GetLength()); setVel.w=(angle/PATH_DERIVATION_TIME)*w.GetNormalized(); pPhysEnt->Action(&setVel, 0 /* bThreadSafe=0 */); // as we are calling from the physics thread break; } } } } // Done processing once we reach end of path if (m_atEndOfPath) m_processNode = false; return 0; }
//------------------------------------------------------------------------ void CWeapon::OnPickedUp(EntityId actorId, bool destroyed) { BROADCAST_WEAPON_EVENT(OnPickedUp, (this, actorId, destroyed)); CItem::OnPickedUp(actorId, destroyed); GetEntity()->SetFlags(GetEntity()->GetFlags() | ENTITY_FLAG_NO_PROXIMITY); GetEntity()->SetFlags(GetEntity()->GetFlags() & ~ENTITY_FLAG_ON_RADAR); if(GetISystem()->IsSerializingFile() == 1) return; if (!IsServer()) return; CActor *pActor=GetActor(actorId); if (!pActor) return; // bonus ammo is always put in the actor's inv if (!m_bonusammo.empty()) { for (TAmmoMap::iterator it=m_bonusammo.begin(); it!=m_bonusammo.end(); ++it) { int count=it->second; SetInventoryAmmoCount(it->first, GetInventoryAmmoCount(it->first)+count); } m_bonusammo.clear(); } if (!m_ammoCapacity.empty()) { IInventory* pInventory = GetActorInventory(GetOwnerActor()); if (pInventory) { for (TAmmoMap::iterator it=m_ammoCapacity.begin(); it!=m_ammoCapacity.end(); ++it) pInventory->SetAmmoCapacity(it->first, it->second); } m_ammoCapacity.clear(); } // current ammo is only added to actor's inv, if we already have this weapon if (destroyed && m_sharedparams->params.unique) { for (TAmmoMap::iterator it=m_ammo.begin(); it!=m_ammo.end(); ++it) { //Only add ammo to inventory, if not accessory ammo (accessories give ammo already) if(m_accessoryAmmo.find(it->first)==m_accessoryAmmo.end()) { int count=it->second; SetInventoryAmmoCount(it->first, GetInventoryAmmoCount(it->first)+count); } } } if(!gEnv->bMultiplayer && !m_initialSetup.empty() && pActor->IsClient()) { for (TAccessoryMap::iterator it=m_accessories.begin(); it!=m_accessories.end(); ++it) FixAccessories(GetAccessoryParams(it->first), true); } m_expended_ammo = 0; }
CHUDObituary::CHUDObituary() : m_deathHead(0), m_empty(true) { m_pDefaultFont = GetISystem()->GetICryFont()->GetFont("default"); CRY_ASSERT(m_pDefaultFont); }
////////////////////////////////////////////////////////////////////////// // NOTE: This function must be thread-safe. Before adding stuff contact MarcoC. void CVehicleMovementVTOL::ProcessAI(const float deltaTime) { FUNCTION_PROFILER( GetISystem(), PROFILE_GAME ); if (!m_isVTOLMovement) { CVehicleMovementHelicopter::ProcessAI(deltaTime); return; } m_velDamp = 0.15f; const float maxDirChange = 15.0f; // it's useless to progress further if the engine has yet to be turned on if (!m_isEnginePowered) { return; } m_movementAction.Clear(); m_movementAction.isAI = true; ResetActions(); // Our current state const Vec3 worldPos = m_PhysPos.pos; const Matrix33 worldMat( m_PhysPos.q); Ang3 worldAngles = Ang3::GetAnglesXYZ(worldMat); const Vec3 currentVel = m_PhysDyn.v; const Vec3 currentVel2D(currentVel.x, currentVel.y, 0.0f); // +ve direction mean rotation anti-clocwise about the z axis - 0 means along y float currentDir = worldAngles.z; // to avoid singularity const Vec3 vWorldDir = worldMat * FORWARD_DIRECTION; const Vec3 vWorldDir2D = Vec3( vWorldDir.x, vWorldDir.y, 0.0f ).GetNormalizedSafe(); // Our inputs const float desiredSpeed = m_aiRequest.HasDesiredSpeed() ? m_aiRequest.GetDesiredSpeed() : 0.0f; const Vec3 desiredMoveDir = m_aiRequest.HasMoveTarget() ? (m_aiRequest.GetMoveTarget() - worldPos).GetNormalizedSafe() : vWorldDir; const Vec3 desiredMoveDir2D = Vec3(desiredMoveDir.x, desiredMoveDir.y, 0.0f).GetNormalizedSafe(vWorldDir2D); const Vec3 desiredVel = desiredMoveDir * desiredSpeed; const Vec3 desiredVel2D(desiredVel.x, desiredVel.y, 0.0f); const Vec3 desiredLookDir = m_aiRequest.HasLookTarget() ? (m_aiRequest.GetLookTarget() - worldPos).GetNormalizedSafe() : desiredMoveDir; const Vec3 desiredLookDir2D = Vec3(desiredLookDir.x, desiredLookDir.y, 0.0f).GetNormalizedSafe(vWorldDir2D); // Calculate the desired 2D velocity change Vec3 desiredVelChange2D = desiredVel2D - currentVel2D; float velChangeLength = desiredVelChange2D.GetLength2D(); bool isLandingMode = false; if (m_pLandingGears && m_pLandingGears->AreLandingGearsOpen()) { isLandingMode = true; } bool isHorizontal = (desiredSpeed >= 5.0f) && (desiredMoveDir.GetLength2D() > desiredMoveDir.z); float desiredPitch = 0.0f; float desiredRoll = 0.0f; float desiredDir = atan2f(-desiredLookDir2D.x, desiredLookDir2D.y); while (currentDir < desiredDir - gf_PI) { currentDir += 2.0f * gf_PI; } while (currentDir > desiredDir + gf_PI) { currentDir -= 2.0f * gf_PI; } float diffDir = (desiredDir - currentDir); m_actionYaw = diffDir * m_yawInputConst; m_actionYaw += m_yawInputDamping * (currentDir - m_lastDir) / deltaTime; m_lastDir = currentDir; if (isHorizontal && !isLandingMode) { float desiredFwdSpeed = desiredVelChange2D.GetLength(); desiredFwdSpeed *= min(1.0f, diffDir / DEG2RAD(maxDirChange)); if (!iszero(desiredFwdSpeed)) { const Vec3 desiredWorldTiltAxis = Vec3(-desiredVelChange2D.y, desiredVelChange2D.x, 0.0f); const Vec3 desiredLocalTiltAxis = worldMat.GetTransposed() * desiredWorldTiltAxis; m_forwardAction = m_fwdPID.Update(currentVel.y, desiredLocalTiltAxis.GetLength(), -1.0f, 1.0f); float desiredTiltAngle = m_tiltPerVelDifference * desiredVelChange2D.GetLength(); Limit(desiredTiltAngle, -m_maxTiltAngle, m_maxTiltAngle); if (desiredTiltAngle > 0.0001f) { const Vec3 desiredWorldTiltAxis2 = Vec3(-desiredVelChange2D.y, desiredVelChange2D.x, 0.0f).GetNormalizedSafe(); const Vec3 desiredLocalTiltAxis2 = worldMat.GetTransposed() * desiredWorldTiltAxis2; Vec3 vVelLocal = worldMat.GetTransposed() * desiredVel; vVelLocal.NormalizeSafe(); float dotup = vVelLocal.Dot(Vec3( 0.0f, 0.0f, 1.0f ) ); float currentSpeed = currentVel.GetLength(); desiredPitch = dotup * currentSpeed / 100.0f; desiredRoll = desiredTiltAngle * desiredLocalTiltAxis2.y * currentSpeed / 30.0f; } } } else { float desiredTiltAngle = m_tiltPerVelDifference * desiredVelChange2D.GetLength(); Limit(desiredTiltAngle, -m_maxTiltAngle, m_maxTiltAngle); if (desiredTiltAngle > 0.0001f) { const Vec3 desiredWorldTiltAxis = Vec3(-desiredVelChange2D.y, desiredVelChange2D.x, 0.0f).GetNormalizedSafe(); const Vec3 desiredLocalTiltAxis = worldMat.GetTransposed() * desiredWorldTiltAxis; desiredPitch = desiredTiltAngle * desiredLocalTiltAxis.x; desiredRoll = desiredTiltAngle * desiredLocalTiltAxis.y; } } float currentHeight = m_PhysPos.pos.z; if ( m_aiRequest.HasMoveTarget() ) { m_hoveringPower = m_powerPID.Update(currentVel.z, desiredVel.z, -1.0f, 4.0f); //m_hoveringPower = (m_desiredHeight - currentHeight) * m_powerInputConst; //m_hoveringPower += m_powerInputDamping * (currentHeight - m_lastHeight) / deltaTime; if (isHorizontal) { if (desiredMoveDir.z > 0.6f || desiredMoveDir.z < -0.85f) { desiredPitch = max(-0.5f, min(0.5f, desiredMoveDir.z)) * DEG2RAD(35.0f); m_forwardAction += abs(desiredMoveDir.z); } m_liftAction = min(2.0f, max(m_liftAction, m_hoveringPower * 2.0f)); } else { m_liftAction = 0.0f; } } else { // to keep hovering at the same place m_hoveringPower = m_powerPID.Update(currentVel.z, m_desiredHeight - currentHeight, -1.0f, 1.0f); m_liftAction = 0.0f; if (m_pVehicle->GetAltitude() > 10.0f) //TODO: this line is not MTSafe { m_liftAction = m_forwardAction; } } m_actionPitch += m_pitchActionPerTilt * (desiredPitch - worldAngles.x); m_actionRoll += m_pitchActionPerTilt * (desiredRoll - worldAngles.y); Limit(m_actionPitch, -1.0f, 1.0f); Limit(m_actionRoll, -1.0f, 1.0f); Limit(m_actionYaw, -1.0f, 1.0f); if (m_horizontal > 0.0001f) { m_desiredHeight = m_PhysPos.pos.z; } Limit(m_forwardAction, -1.0f, 1.0f); }
//------------------------------------------------------------------------ void CViewSystem::Update(float frameTime) { FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION); if (gEnv->IsDedicated()) return; CView* const __restrict pActiveView = static_cast<CView*>(GetActiveView()); TViewMap::const_iterator Iter(m_views.begin()); TViewMap::const_iterator const IterEnd(m_views.end()); for (; Iter != IterEnd; ++Iter) { CView* const __restrict pView = Iter->second; bool const bIsActive = (pView == pActiveView); pView->Update(frameTime, bIsActive); if (bIsActive) { CCamera &rCamera = pView->GetCamera(); pView->UpdateAudioListener(rCamera.GetMatrix()); SViewParams currentParams = *(pView->GetCurrentParams()); rCamera.SetJustActivated(currentParams.justActivated); currentParams.justActivated = false; pView->SetCurrentParams(currentParams); if (m_bOverridenCameraRotation) { // When camera rotation is overridden. Vec3 pos = rCamera.GetMatrix().GetTranslation(); Matrix34 camTM(m_overridenCameraRotation); camTM.SetTranslation(pos); rCamera.SetMatrix(camTM); } else { // Normal setting of the camera if (m_fCameraNoise > 0) { Matrix33 m = Matrix33(rCamera.GetMatrix()); m.OrthonormalizeFast(); Ang3 aAng1 = Ang3::GetAnglesXYZ(m); //Ang3 aAng2 = RAD2DEG(aAng1); Matrix34 camTM = rCamera.GetMatrix(); Vec3 pos = camTM.GetTranslation(); camTM.SetIdentity(); const float fScale = 0.1f; CPNoise3* pNoise = m_pSystem->GetNoiseGen(); float fRes = pNoise->Noise1D(gEnv->pTimer->GetCurrTime() * m_fCameraNoiseFrequency); aAng1.x += fRes * m_fCameraNoise * fScale; pos.z -= fRes * m_fCameraNoise * fScale; fRes = pNoise->Noise1D(17 + gEnv->pTimer->GetCurrTime() * m_fCameraNoiseFrequency); aAng1.y -= fRes * m_fCameraNoise * fScale; //aAng1.z+=fRes*0.025f; // left / right movement should be much less visible camTM.SetRotationXYZ(aAng1); camTM.SetTranslation(pos); rCamera.SetMatrix(camTM); } } m_pSystem->SetViewCamera(rCamera); } } // Display debug info on screen if (m_nViewSystemDebug) { DebugDraw(); } // perform dynamic color grading // Beni - Commented for console demo stuff /****************************************************************************************** if (!IsPlayingCutScene() && gEnv->pAISystem) { SAIDetectionLevels detection; gEnv->pAISystem->GetDetectionLevels(nullptr, detection); float factor = detection.puppetThreat; // marcok: magic numbers taken from Maciej's tweaked values (final - initial) { float percentage = (0.0851411f - 0.0509998f)/0.0509998f * factor; float amount = 0.0f; gEnv->p3DEngine->GetPostEffectParam("ColorGrading_GrainAmount", amount); gEnv->p3DEngine->SetPostEffectParam("ColorGrading_GrainAmount_Offset", amount*percentage); } { float percentage = (0.405521f - 0.256739f)/0.256739f * factor; float amount = 0.0f; gEnv->p3DEngine->GetPostEffectParam("ColorGrading_SharpenAmount", amount); //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_SharpenAmount_Offset", amount*percentage); } { float percentage = (0.14f - 0.11f)/0.11f * factor; float amount = 0.0f; gEnv->p3DEngine->GetPostEffectParam("ColorGrading_PhotoFilterColorDensity", amount); gEnv->p3DEngine->SetPostEffectParam("ColorGrading_PhotoFilterColorDensity_Offset", amount*percentage); } { float percentage = (234.984f - 244.983f)/244.983f * factor; float amount = 0.0f; gEnv->p3DEngine->GetPostEffectParam("ColorGrading_maxInput", amount); //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_maxInput_Offset", amount*percentage); } { float percentage = (239.984f - 247.209f)/247.209f * factor; float amount = 0.0f; gEnv->p3DEngine->GetPostEffectParam("ColorGrading_maxOutput", amount); //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_maxOutput_Offset", amount*percentage); } { Vec4 dest(0.0f/255.0f, 22.0f/255.0f, 33.0f/255.0f, 1.0f); Vec4 initial(2.0f/255.0f, 154.0f/255.0f, 226.0f/255.0f, 1.0f); Vec4 percentage = (dest - initial)/initial * factor; Vec4 amount; gEnv->p3DEngine->GetPostEffectParamVec4("clr_ColorGrading_SelectiveColor", amount); //gEnv->p3DEngine->SetPostEffectParamVec4("clr_ColorGrading_SelectiveColor_Offset", amount*percentage); } { float percentage = (-5.0083 - -1.99999)/-1.99999 * factor; float amount = 0.0f; gEnv->p3DEngine->GetPostEffectParam("ColorGrading_SelectiveColorCyans", amount); //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_SelectiveColorCyans_Offset", amount*percentage); } { float percentage = (10.0166 - -5.99999)/-5.99999 * factor; float amount = 0.0f; gEnv->p3DEngine->GetPostEffectParam("ColorGrading_SelectiveColorMagentas", amount); //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_SelectiveColorMagentas_Offset", amount*percentage); } { float percentage = (10.0166 - 1.99999)/1.99999 * factor; float amount = 0.0f; gEnv->p3DEngine->GetPostEffectParam("ColorGrading_SelectiveColorYellows", amount); //gEnv->p3DEngine->SetPostEffectParam("ColorGrading_SelectiveColorYellows_Offset", amount*percentage); } } ********************************************************************************************/ }