Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RealisticRunning v1.2.1
RealisticRunning.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("SurvivalMovementExertion")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SurvivalMovementExertion")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("21978fe2-ee63-49ee-aad5-3609c97f40b0")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace SurvivalMovementExertion; [BepInPlugin("com.marccunningham.survivalmovementexertion", "Realistic Running", "1.2.1")] [BepInProcess("valheim.exe")] public sealed class SurvivalMovementExertionPlugin : BaseUnityPlugin { public const string PluginGuid = "com.marccunningham.survivalmovementexertion"; public const string PluginName = "Realistic Running"; public const string PluginVersion = "1.2.1"; private const float MinimumInputMagnitude = 0.001f; private const float MinimumDuration = 0.01f; private const int TunnelTextureCount = 18; private const int TunnelTextureSize = 160; private const int DefaultWindStreakCount = 28; internal static SurvivalMovementExertionPlugin Instance; private ConfigEntry<bool> modEnabled; private ConfigEntry<KeyCode> diagnosticKey; private ConfigEntry<bool> showDiagnosticHud; private ConfigEntry<bool> enableInputSmoothing; private ConfigEntry<float> accelerationSeconds; private ConfigEntry<float> decelerationSeconds; private ConfigEntry<float> backwardSpeedMultiplier; private ConfigEntry<float> sidewaysSpeedMultiplier; private ConfigEntry<float> sprintBuildUpSeconds; private ConfigEntry<float> sprintStartSpeedFraction; private ConfigEntry<float> topSprintSpeedMultiplier; private ConfigEntry<float> sprintBuildRecoverySeconds; private ConfigEntry<float> baseRunStaminaDrainMultiplier; private ConfigEntry<float> maximumCombinedRunDrainMultiplier; private ConfigEntry<float> emergencySprintReleaseStaminaPercentage; private ConfigEntry<float> exertionGainPerSecond; private ConfigEntry<float> exertionRecoveryPerSecond; private ConfigEntry<float> stationaryRecoveryMultiplier; private ConfigEntry<float> highExertionStart; private ConfigEntry<float> highExertionRunSpeedMultiplier; private ConfigEntry<float> highExertionDrainMultiplier; private ConfigEntry<float> exhaustionTriggerStaminaPercentage; private ConfigEntry<float> exhaustedJogSeconds; private ConfigEntry<float> exhaustedJogSpeedMultiplier; private ConfigEntry<float> recoveryStaminaPercentage; private ConfigEntry<float> recoveryExertionPercentage; private ConfigEntry<bool> enableHillEffects; private ConfigEntry<float> hillGraceAngle; private ConfigEntry<float> hillFullPenaltyAngle; private ConfigEntry<float> uphillSpeedPenalty; private ConfigEntry<float> uphillDrainMultiplier; private ConfigEntry<float> uphillExertionMultiplier; private ConfigEntry<float> downhillSpeedBonus; private ConfigEntry<float> downhillDrainReduction; private ConfigEntry<bool> enableWeatherEffects; private ConfigEntry<float> wetSpeedMultiplier; private ConfigEntry<float> wetDrainMultiplier; private ConfigEntry<float> wetExertionMultiplier; private ConfigEntry<float> coldDrainMultiplier; private ConfigEntry<float> coldExertionMultiplier; private ConfigEntry<float> freezingSpeedMultiplier; private ConfigEntry<float> freezingDrainMultiplier; private ConfigEntry<float> freezingExertionMultiplier; private ConfigEntry<bool> enableInjuryCompatibility; private ConfigEntry<float> injuryExertionPenaltyStrength; private ConfigEntry<bool> applyInjurySpeedCompatibilityPenalty; private ConfigEntry<float> factorRefreshSeconds; private ConfigEntry<bool> enableTunnelVision; private ConfigEntry<float> tunnelVisionStartExertion; private ConfigEntry<float> tunnelVisionFullExertion; private ConfigEntry<float> maximumTunnelVisionAlpha; private ConfigEntry<float> tunnelVisionPulseStrength; private ConfigEntry<float> tunnelVisionClearRadiusAtExhaustion; private ConfigEntry<bool> enableWindRushStreaks; private ConfigEntry<int> windRushStreakCount; private ConfigEntry<float> windRushStartSprintBuild; private ConfigEntry<float> windRushMaximumAlpha; private ConfigEntry<float> windRushTravelSpeed; private ConfigEntry<bool> enableCameraSway; private ConfigEntry<bool> cameraSwayClosestZoomOnly; private ConfigEntry<float> closestZoomTolerance; private ConfigEntry<float> sprintBobVerticalMeters; private ConfigEntry<float> sprintBobSideMeters; private ConfigEntry<float> fatigueBreathSwayMeters; private ConfigEntry<float> sprintSwayFrequencyLow; private ConfigEntry<float> sprintSwayFrequencyHigh; private ConfigEntry<float> breathSwayFrequencyLow; private ConfigEntry<float> breathSwayFrequencyHigh; private ConfigEntry<float> cameraSwaySmoothingSeconds; private ConfigEntry<float> coolEdgeTintStrength; private ConfigEntry<bool> enableNativeDepthOfField; private ConfigEntry<bool> depthOfFieldClosestZoomOnly; private ConfigEntry<float> depthOfFieldStartVisualIntensity; private ConfigEntry<float> depthOfFieldMaximumBlurSize; private ConfigEntry<float> depthOfFieldFocalSizeAtExhaustion; private ConfigEntry<float> depthOfFieldFallbackFocusDistance; private ConfigEntry<float> depthOfFieldMaximumFocusDistance; private ConfigEntry<bool> enableSprintFovBoost; private ConfigEntry<float> sprintFovBoostDegrees; private ConfigEntry<float> sprintFovBoostSmoothingSeconds; private ConfigEntry<bool> enablePeripheralBlurOverlay; private ConfigEntry<float> peripheralBlurStartIntensity; private ConfigEntry<float> peripheralBlurMaximumAlpha; private ConfigEntry<float> peripheralBlurClearRadiusAtExhaustion; private ConfigEntry<bool> enableExhaustionHeartbeat; private ConfigEntry<float> heartbeatStartPressure; private ConfigEntry<float> heartbeatRecoveryBpm; private ConfigEntry<float> heartbeatMaximumBpm; private ConfigEntry<float> heartbeatMaximumVolume; private ConfigEntry<float> heartbeatIntensitySmoothingSeconds; private Harmony harmony; private bool setControlsPatchInstalled; private bool jogSpeedPatchInstalled; private bool runSpeedPatchInstalled; private bool checkRunPatchInstalled; private bool cameraPositionPatchInstalled; private bool depthOfFieldPatchInstalled; private int setControlsHookCalls; private int jogSpeedHookCalls; private int runSpeedHookCalls; private int checkRunHookCalls; private int cameraHookCalls; private int depthOfFieldHookCalls; private float smoothedInputMagnitude; private float sprintBuild; private float exertion; private float exhaustedJogRemaining; private bool fatigueRecoveryActive; private bool wasSprinting; private float lastRunDrainMultiplier = 1f; private float factorRefreshTimer = 999f; private float terrainSpeedMultiplier = 1f; private float terrainDrainMultiplier = 1f; private float terrainExertionMultiplier = 1f; private float weatherSpeedMultiplier = 1f; private float weatherDrainMultiplier = 1f; private float weatherExertionMultiplier = 1f; private float weatherRecoveryMultiplier = 1f; private float injurySpeedMultiplier = 1f; private float injuryExertionMultiplier = 1f; private float cachedSlopeAngle; private bool cachedWet; private bool cachedCold; private bool cachedFreezing; private float smoothedCameraSwayVertical; private float smoothedCameraSwaySide; private float cameraSwayVerticalVelocity; private float cameraSwaySideVelocity; private float latestCameraDistance = float.MaxValue; private float latestCameraMinimumDistance = float.MaxValue; private float baseCameraFieldOfView = -1f; private float smoothedSprintFovBoost; private float sprintFovBoostVelocity; private Component heartbeatAudioSource; private Object heartbeatClip; private MethodInfo heartbeatPlayOneShotMethod; private MethodInfo heartbeatStopMethod; private float heartbeatNextBeatTime; private float heartbeatCurrentPressure; private float heartbeatPressureVelocity; private float heartbeatCurrentBpm; private string heartbeatStatus = "not loaded"; private string heartbeatAssetPath = string.Empty; private FieldInfo cameraEffectsDofField; private FieldInfo cameraEffectsDofRayMaskField; private MemberInfo dofFocusDistanceMember; private MemberInfo dofFocalSizeMember; private MemberInfo dofMaxBlurSizeMember; private MemberInfo dofApertureMember; private bool depthOfFieldReflectionReady; private bool depthOfFieldAvailable; private string depthOfFieldStatus = "not resolved"; private Type injuryPluginType; private FieldInfo injuryInstanceField; private MethodInfo injuryIsActiveForMethod; private MethodInfo injuryRunSpeedMultiplierMethod; private bool injuryReflectionUsable; private Texture2D[] tunnelTextures; private Texture2D[] peripheralBlurTextures; private WindStreak[] windStreaks; private GUIStyle diagnosticStyle; private void Awake() { Instance = this; BindConfig(); MigratePerceptibilityDefaults(); MigrateEscapeSafetyDefaults(); InstallPatches(); TryLoadHeartbeatAudio(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Realistic Running 1.2.1 loaded. WindRushMaximumAlpha is now range-limited for a Configuration Manager slider, so wind-streak visibility can be tuned without rebuilding. Press F8 for diagnostics."); } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); } StopHeartbeatAudio(); if ((Object)(object)heartbeatAudioSource != (Object)null) { Object.Destroy((Object)(object)heartbeatAudioSource); heartbeatAudioSource = null; } if (heartbeatClip != (Object)null) { Object.Destroy(heartbeatClip); heartbeatClip = null; } DestroyTunnelTextures(); DestroyPeripheralBlurTextures(); windStreaks = null; if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void Update() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(diagnosticKey.Value)) { WriteDiagnostic(); } Player localPlayer = Player.m_localPlayer; if (!IsMovementEligible(localPlayer)) { ResetTransientMovementState(); return; } factorRefreshTimer += Time.deltaTime; if (factorRefreshTimer >= Mathf.Max(0.05f, factorRefreshSeconds.Value)) { factorRefreshTimer = 0f; RefreshWorldFactors(localPlayer); } UpdateExertion(localPlayer); UpdateVisualMotion(localPlayer); UpdateHeartbeatAudio(localPlayer); } private void OnGUI() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && modEnabled.Value) { DrawWindRush(localPlayer); DrawPeripheralBlur(localPlayer); DrawTunnelVision(localPlayer); DrawDiagnosticHud(localPlayer); } } private void BindConfig() { //IL_0803: Unknown result type (might be due to invalid IL or missing references) //IL_0826: Unknown result type (might be due to invalid IL or missing references) //IL_0830: Expected O, but got Unknown //IL_0830: Expected O, but got Unknown modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turns Realistic Running on or off without removing the DLL."); diagnosticKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "DiagnosticKey", (KeyCode)289, "Writes movement, exertion, terrain, weather and compatibility diagnostics to BepInEx/LogOutput.log."); showDiagnosticHud = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "ShowDiagnosticHud", false, "Shows a small top-left exertion readout for balancing. Leave off for normal play."); enableInputSmoothing = ((BaseUnityPlugin)this).Config.Bind<bool>("Movement", "EnableInputSmoothing", true, "Smooths input magnitude while preserving immediate turning direction. This creates acceleration and deceleration without steering lag."); accelerationSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "AccelerationSeconds", 0.28f, "Seconds for a stationary player to build toward full movement input. Higher values feel heavier."); decelerationSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "DecelerationSeconds", 0.18f, "Seconds for movement input to settle after keys are released. Higher values feel less abrupt."); backwardSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "BackwardSpeedMultiplier", 0.7f, "Speed while moving directly backward. Diagonal movement blends naturally between forward, sideways and backward values."); sidewaysSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "SidewaysSpeedMultiplier", 0.86f, "Speed while moving directly sideways."); sprintBuildUpSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Sprint", "SprintBuildUpSeconds", 1.35f, "Seconds for sprinting to build from the initial run into maximum speed."); sprintStartSpeedFraction = ((BaseUnityPlugin)this).Config.Bind<float>("Sprint", "SprintStartSpeedFraction", 0.72f, "Fraction of top sprint speed available the instant sprinting begins. It rises to full TopSprintSpeedMultiplier over SprintBuildUpSeconds. V1.1.1 starts close to normal run speed, then visibly builds into a faster sprint."); topSprintSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Sprint", "TopSprintSpeedMultiplier", 1.45f, "Maximum healthy forward sprint multiplier relative to Valheim's native running speed. V1.1.4 gives a clearly faster full sprint while retaining build-up, exertion and recovery."); sprintBuildRecoverySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Sprint", "SprintBuildRecoverySeconds", 0.6f, "Seconds for sprint build-up to fade after the player stops running."); baseRunStaminaDrainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Sprint", "BaseRunStaminaDrainMultiplier", 0.15f, "Multiplier applied to Valheim's native run stamina drain. 0.15 aims for roughly 45-60 seconds of healthy sustained running with the same stamina pool, before terrain and exertion are considered."); maximumCombinedRunDrainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "MaximumCombinedRunDrainMultiplier", 2.25f, "Safety cap for all combined run-drain effects from exertion, terrain, weather and compatible survival mods. It keeps a bad situation difficult without making every sprint attempt instantly empty the bar."); emergencySprintReleaseStaminaPercentage = ((BaseUnityPlugin)this).Config.Bind<float>("Safety", "EmergencySprintReleaseStaminaPercentage", 0.22f, "After the minimum exhausted-jog time ends, sprinting is allowed again once stamina reaches this fraction even while exertion recovery continues. This prevents a long no-sprint lock while keeping escape costly."); exertionGainPerSecond = ((BaseUnityPlugin)this).Config.Bind<float>("Exertion", "SprintExertionGainPerSecond", 1.5f, "Exertion gained per second while sprinting on neutral ground. A long hard run approaches high exertion."); exertionRecoveryPerSecond = ((BaseUnityPlugin)this).Config.Bind<float>("Exertion", "RecoveryPerSecond", 2.5f, "Exertion removed per second while walking or resting. Recovery is intentionally slower than the old version so hard running has a believable after-effect."); stationaryRecoveryMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Exertion", "StationaryRecoveryMultiplier", 1.75f, "Extra exertion recovery while standing still. Resting should recover you faster than walking onward."); highExertionStart = ((BaseUnityPlugin)this).Config.Bind<float>("Exertion", "HighExertionStart", 35f, "Exertion percentage where heavy breathing, tunnel vision and late-run penalties begin building. V1.1.1 starts the feedback earlier so the player can feel effort building before complete exhaustion."); highExertionRunSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Exertion", "HighExertionRunSpeedMultiplier", 0.84f, "Minimum late-run speed multiplier at 100 exertion. Exhaustion should feel heavy, not like walking through glue."); highExertionDrainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Exertion", "HighExertionDrainMultiplier", 1.9f, "Additional stamina-drain multiplier reached at maximum exertion. Sustained hard running becomes less efficient instead of ending abruptly."); exhaustionTriggerStaminaPercentage = ((BaseUnityPlugin)this).Config.Bind<float>("Fatigue Recovery", "ExhaustionTriggerStaminaPercentage", 0.08f, "Stamina percentage that triggers a hard fatigue recovery state after a hard run. This begins before literal zero so exhaustion is noticeable and reliable."); exhaustedJogSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Fatigue Recovery", "MinimumExhaustedJogSeconds", 5.5f, "Minimum number of seconds the player remains in a hard-jog recovery state after sprinting to near-zero stamina."); exhaustedJogSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Fatigue Recovery", "ExhaustedJogSpeedMultiplier", 0.88f, "Jog-speed multiplier during hard fatigue recovery."); recoveryStaminaPercentage = ((BaseUnityPlugin)this).Config.Bind<float>("Fatigue Recovery", "RecoveryStaminaPercentage", 0.28f, "Stamina percentage required before hard fatigue can end."); recoveryExertionPercentage = ((BaseUnityPlugin)this).Config.Bind<float>("Fatigue Recovery", "RecoveryExertionPercentage", 55f, "Exertion percentage required before hard fatigue can end. This gives exhaustion a believable recovery period after a long run."); enableHillEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Terrain", "EnableHillEffects", true, "Applies uphill and downhill movement/exertion effects using Valheim's real ground normal."); hillGraceAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "HillGraceAngle", 7f, "Slope angle in degrees before hill effects begin."); hillFullPenaltyAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "HillFullPenaltyAngle", 35f, "Slope angle in degrees where maximum hill effects apply."); uphillSpeedPenalty = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "MaxUphillSpeedPenalty", 0.22f, "Maximum speed reduction while moving directly uphill on a steep slope."); uphillDrainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "MaxUphillDrainMultiplier", 1.5f, "Maximum extra run stamina drain while moving directly uphill on a steep slope."); uphillExertionMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "MaxUphillExertionMultiplier", 1.65f, "Maximum extra exertion build while moving directly uphill on a steep slope."); downhillSpeedBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "MaxDownhillSpeedBonus", 0.04f, "Maximum small speed bonus while moving directly downhill. Kept low to avoid unsafe runaway movement."); downhillDrainReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Terrain", "MaxDownhillDrainReduction", 0.12f, "Maximum reduction in sprint stamina drain while moving directly downhill."); enableWeatherEffects = ((BaseUnityPlugin)this).Config.Bind<bool>("Weather", "EnableWeatherEffects", true, "Applies realistic movement and exertion effects for wet, cold and freezing conditions."); wetSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "WetSpeedMultiplier", 0.97f, "Movement multiplier while wet. Kept mild: wetness should make travel harder without feeling sticky."); wetDrainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "WetRunDrainMultiplier", 1.14f, "Sprint stamina-drain multiplier while wet."); wetExertionMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "WetExertionMultiplier", 1.16f, "Exertion-gain multiplier while wet."); coldDrainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "ColdRunDrainMultiplier", 1.08f, "Sprint stamina-drain multiplier in cold weather."); coldExertionMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "ColdExertionMultiplier", 1.1f, "Exertion-gain multiplier in cold weather."); freezingSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "FreezingSpeedMultiplier", 0.95f, "Movement multiplier in freezing conditions."); freezingDrainMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "FreezingRunDrainMultiplier", 1.25f, "Sprint stamina-drain multiplier in freezing conditions."); freezingExertionMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Weather", "FreezingExertionMultiplier", 1.28f, "Exertion-gain multiplier in freezing conditions."); enableInjuryCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "EnableYoureInjuredCompatibility", true, "Reads the installed You're Injured mod through safe reflection. It makes leg injuries build exertion faster and can apply its leg-speed penalty to Player overrides in current Valheim builds."); injuryExertionPenaltyStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Compatibility", "InjuryExertionPenaltyStrength", 0.85f, "How strongly leg injuries increase exertion. 0 disables the extra exertion link while preserving any direct injury speed effect."); applyInjurySpeedCompatibilityPenalty = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "ApplyYoureInjuredSpeedCompatibilityPenalty", true, "Applies the existing You're Injured leg-speed multiplier to Player movement. Leave true for current builds where the original injury speed patch targets Character instead of Player. Turn off only if a later You're Injured update already patches Player speed directly."); factorRefreshSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Compatibility", "FactorRefreshSeconds", 0.15f, "How often terrain, weather and optional-mod factors are refreshed. Lower values react faster; defaults are light on performance."); enableTunnelVision = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "EnableExhaustionTunnelVision", true, "Narrows peripheral vision progressively during sustained sprinting. The effect begins mild, then tightens and pulses more strongly as exertion builds toward exhaustion."); tunnelVisionStartExertion = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "TunnelVisionStartExertion", 8f, "Exertion percentage where a faint peripheral narrowing begins during a sustained run. The effect then builds continuously instead of appearing only at complete exhaustion."); tunnelVisionFullExertion = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "TunnelVisionFullExertion", 88f, "Exertion percentage where the tunnel effect reaches its intended maximum before hard exhaustion. Keep this below 100 so the player feels pressure before their stamina is empty."); maximumTunnelVisionAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "MaximumTunnelVisionAlpha", 0.68f, "Maximum edge opacity of the sprint-exhaustion tunnel vision. V1.1.4 narrows the clear centre more rather than simply making the whole screen darker."); tunnelVisionPulseStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "TunnelVisionPulseStrength", 0.3f, "How strongly the tunnel vision gently swells with heavy breathing. This only becomes noticeable as exertion rises."); tunnelVisionClearRadiusAtExhaustion = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "TunnelVisionClearRadiusAtExhaustion", 0.82f, "Size of the fully clear central view at heavy exhaustion. Lower values make the field of view feel more tightly narrowed; 0.82 keeps combat readable while making fatigue unmistakable."); enableWindRushStreaks = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "EnableWindRushStreaks", true, "Draws subtle pale wind streaks that burst outward from the centre toward all screen edges during a fresh full sprint. The centre remains clear for aiming and combat."); windRushStreakCount = ((BaseUnityPlugin)this).Config.Bind<int>("Visuals", "WindRushStreakCount", 28, "Number of radial wind streaks. Higher values create a fuller all-angle speed field but can feel visually busy."); windRushStartSprintBuild = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "WindRushStartSprintBuild", 0.52f, "Sprint build percentage at which wind streaks start. This keeps them out of normal jogging and the first moments of a run."); windRushMaximumAlpha = ((BaseUnityPlugin)this).Config.Bind<float>(new ConfigDefinition("Visuals", "WindRushMaximumAlpha"), 0.24f, new ConfigDescription("Brightness / visibility of individual wind streaks at full sprint. This is a slider in BepInEx Configuration Manager when that mod is installed. 0.24 is the current balanced default; try 0.32 for clearer streaks or 0.40 for a much stronger speed effect.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 0.65f), Array.Empty<object>())); windRushTravelSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "WindRushTravelSpeed", 1.35f, "How quickly radial wind streaks travel away from the screen centre at full sprint."); enableCameraSway = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "EnableCameraSway", true, "Adds subtle sprint bob and heavier breathing sway. It patches the final camera position so it layers after Survival View's Raised Head View."); cameraSwayClosestZoomOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "CameraSwayClosestZoomOnly", true, "When true, camera sway appears only at closest zoom / Survival View, avoiding unwanted third-person camera motion."); closestZoomTolerance = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "ClosestZoomToleranceMeters", 0.08f, "Tolerance used by CameraSwayClosestZoomOnly to recognise Valheim's closest normal third-person zoom."); sprintBobVerticalMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "SprintBobVerticalMeters", 0.013f, "Maximum vertical camera bob while sprinting at low exertion. This is deliberately noticeable in Survival View without becoming nauseating."); sprintBobSideMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "SprintBobSideMeters", 0.009f, "Maximum sideways camera bob while sprinting at low exertion."); fatigueBreathSwayMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "FatigueBreathSwayMeters", 0.02f, "Maximum slow breathing sway at high exertion or hard fatigue recovery. This is intentionally small so it feels heavy rather than jittery."); sprintSwayFrequencyLow = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "SprintSwayFrequencyLowHz", 1.45f, "Slow sprint gait frequency in cycles per second. Lower values feel steadier and less jittery."); sprintSwayFrequencyHigh = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "SprintSwayFrequencyHighHz", 2.15f, "Fast sprint gait frequency in cycles per second at full pace."); breathSwayFrequencyLow = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "BreathSwayFrequencyLowHz", 0.2f, "Slow breathing sway frequency at the beginning of visible exertion."); breathSwayFrequencyHigh = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "BreathSwayFrequencyHighHz", 0.48f, "Heavy breathing sway frequency near exhaustion. 0.48 Hz is about 29 breaths per minute."); cameraSwaySmoothingSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "CameraSwaySmoothingSeconds", 0.2f, "How gently camera sway eases toward its target. Higher values are smoother and reduce jitter."); coolEdgeTintStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "CoolEdgeTintStrength", 0.68f, "How much the peripheral haze shifts toward an airy blue-grey before deepening toward charcoal near exhaustion."); enableNativeDepthOfField = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "EnableNativeDepthOfField", true, "Uses Valheim's own CameraEffects depth-of-field component during heavy exertion. It focuses on the object in the centre of the view and applies only a mild depth blur."); depthOfFieldClosestZoomOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "DepthOfFieldClosestZoomOnly", true, "When true, exhaustion depth of field only runs at closest zoom / Survival View to keep normal third-person gameplay clear."); depthOfFieldStartVisualIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "DepthOfFieldStartVisualIntensity", 0.34f, "Visual-exhaustion intensity where mild focus blur begins. Tunnel tint can start earlier, but focus blur waits until exertion is meaningful."); depthOfFieldMaximumBlurSize = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "DepthOfFieldMaximumBlurSize", 0.55f, "Maximum native depth-of-field blur size near exhaustion. Kept deliberately modest so the screen centre remains usable in combat."); depthOfFieldFocalSizeAtExhaustion = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "DepthOfFieldFocalSizeAtExhaustion", 1.1f, "Focal range around the point you are looking at near exhaustion. Smaller values create a narrower, more focused view."); depthOfFieldFallbackFocusDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "DepthOfFieldFallbackFocusDistance", 18f, "Focus distance used when the centre camera ray does not hit terrain or an object."); depthOfFieldMaximumFocusDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "DepthOfFieldMaximumFocusDistance", 80f, "Maximum centre-view ray distance used for exhaustion focus."); enableSprintFovBoost = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "EnableSprintFovBoost", true, "Adds a very small field-of-view increase at a fresh full sprint. This stays subtle and fades as heavy exertion takes over."); sprintFovBoostDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "SprintFovBoostDegrees", 2.35f, "Maximum extra FOV at a fresh full sprint. Keep this around 2-3 degrees for a realistic speed feeling rather than an arcade effect."); sprintFovBoostSmoothingSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "SprintFovBoostSmoothingSeconds", 0.34f, "How smoothly the sprint FOV expands and relaxes. Slightly slower values feel more physical."); enablePeripheralBlurOverlay = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "EnablePeripheralBlurOverlay", true, "Adds a soft blue-grey focus-softening overlay around the outer edge as exertion builds. It complements Valheim's native depth of field without obscuring the centre."); peripheralBlurStartIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "PeripheralBlurStartIntensity", 0.22f, "Visual-exhaustion intensity where the subtle peripheral blur overlay begins to appear."); peripheralBlurMaximumAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "PeripheralBlurMaximumAlpha", 0.24f, "Maximum opacity of the soft peripheral blur overlay near heavy exhaustion."); peripheralBlurClearRadiusAtExhaustion = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "PeripheralBlurClearRadiusAtExhaustion", 0.92f, "Clear central radius that remains crisp when the peripheral blur overlay is at maximum strength. Lower values create more outer-edge focus loss."); enableExhaustionHeartbeat = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "EnableExhaustionHeartbeat", true, "Plays the supplied double-heartbeat sample as physical exhaustion builds, then spaces the beats out and fades them during recovery."); heartbeatStartPressure = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "HeartbeatStartPressure", 0.42f, "Exhaustion pressure where the heartbeat first becomes audible. It remains silent during ordinary jogging and light sprinting."); heartbeatRecoveryBpm = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "HeartbeatRecoveryBPM", 88f, "Slowest audible heartbeat rate during the tail end of recovery."); heartbeatMaximumBpm = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "HeartbeatMaximumBPM", 150f, "Fastest heartbeat rate at hard exhaustion. Values above 160 tend to feel artificial with this double-beat sample."); heartbeatMaximumVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "HeartbeatMaximumVolume", 0.3f, "Maximum heartbeat volume at hard exhaustion. Keep low enough that Valheim combat, rain and music still remain audible."); heartbeatIntensitySmoothingSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "HeartbeatIntensitySmoothingSeconds", 0.75f, "How gently the heartbeat rate responds to changing exhaustion. This prevents abrupt BPM jumps when you stop running."); } private void MigratePerceptibilityDefaults() { bool flag = false; if (Mathf.Abs(sprintStartSpeedFraction.Value - 0.78f) < 0.001f) { sprintStartSpeedFraction.Value = 0.72f; flag = true; } if (Mathf.Abs(topSprintSpeedMultiplier.Value - 1.2f) < 0.001f || Mathf.Abs(topSprintSpeedMultiplier.Value - 1.32f) < 0.001f) { topSprintSpeedMultiplier.Value = 1.45f; flag = true; } if (Mathf.Abs(highExertionStart.Value - 55f) < 0.001f) { highExertionStart.Value = 35f; flag = true; } if (Mathf.Abs(highExertionRunSpeedMultiplier.Value - 0.89f) < 0.001f) { highExertionRunSpeedMultiplier.Value = 0.84f; flag = true; } if (Mathf.Abs(exhaustionTriggerStaminaPercentage.Value - 0.02f) < 0.001f) { exhaustionTriggerStaminaPercentage.Value = 0.08f; flag = true; } if (Mathf.Abs(maximumTunnelVisionAlpha.Value - 0.42f) < 0.001f || Mathf.Abs(maximumTunnelVisionAlpha.Value - 0.58f) < 0.001f) { maximumTunnelVisionAlpha.Value = 0.78f; flag = true; } if (Mathf.Abs(sprintBobVerticalMeters.Value - 0.018f) < 0.001f) { sprintBobVerticalMeters.Value = 0.032f; flag = true; } if (Mathf.Abs(sprintBobSideMeters.Value - 0.012f) < 0.001f) { sprintBobSideMeters.Value = 0.022f; flag = true; } if (Mathf.Abs(fatigueBreathSwayMeters.Value - 0.032f) < 0.001f) { fatigueBreathSwayMeters.Value = 0.02f; flag = true; } if (Mathf.Abs(sprintBobVerticalMeters.Value - 0.032f) < 0.001f) { sprintBobVerticalMeters.Value = 0.013f; flag = true; } if (Mathf.Abs(sprintBobSideMeters.Value - 0.022f) < 0.001f) { sprintBobSideMeters.Value = 0.009f; flag = true; } if (Mathf.Abs(fatigueBreathSwayMeters.Value - 0.058f) < 0.001f) { fatigueBreathSwayMeters.Value = 0.02f; flag = true; } if (Mathf.Abs(maximumTunnelVisionAlpha.Value - 0.78f) < 0.001f || Mathf.Abs(maximumTunnelVisionAlpha.Value - 0.62f) < 0.001f) { maximumTunnelVisionAlpha.Value = 0.68f; flag = true; } if (Mathf.Abs(coolEdgeTintStrength.Value - 0.62f) < 0.001f) { coolEdgeTintStrength.Value = 0.68f; flag = true; } if (Mathf.Abs(depthOfFieldStartVisualIntensity.Value - 0.34f) < 0.001f) { depthOfFieldStartVisualIntensity.Value = 0.26f; flag = true; } if (Mathf.Abs(depthOfFieldMaximumBlurSize.Value - 0.55f) < 0.001f) { depthOfFieldMaximumBlurSize.Value = 0.7f; flag = true; } if (Mathf.Abs(depthOfFieldFocalSizeAtExhaustion.Value - 1.1f) < 0.001f) { depthOfFieldFocalSizeAtExhaustion.Value = 0.9f; flag = true; } if (windRushStreakCount.Value == 12) { windRushStreakCount.Value = 28; flag = true; } if (Mathf.Abs(windRushMaximumAlpha.Value - 0.2f) < 0.001f) { windRushMaximumAlpha.Value = 0.24f; flag = true; } if (flag) { ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Realistic Running: migrated untouched defaults to V1.1.8 slightly clearer radial wind-rush streaks."); } } private void MigrateEscapeSafetyDefaults() { if (Mathf.Abs(exhaustedJogSeconds.Value - 8f) < 0.001f && Mathf.Abs(exhaustedJogSpeedMultiplier.Value - 0.84f) < 0.001f && Mathf.Abs(recoveryStaminaPercentage.Value - 0.38f) < 0.001f && Mathf.Abs(recoveryExertionPercentage.Value - 45f) < 0.001f) { exhaustedJogSeconds.Value = 5.5f; exhaustedJogSpeedMultiplier.Value = 0.88f; recoveryStaminaPercentage.Value = 0.28f; recoveryExertionPercentage.Value = 55f; ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Realistic Running: migrated the exhausted-sprint recovery defaults to the ground-floor escape safety values."); } } private void InstallPatches() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_014f: Expected O, but got Unknown //IL_014f: Expected O, but got Unknown //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Expected O, but got Unknown //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Expected O, but got Unknown harmony = new Harmony("com.marccunningham.survivalmovementexertion"); setControlsPatchInstalled = TryPatch(FindMethod(typeof(Player), "SetControls", null), new HarmonyMethod(typeof(SurvivalMovementPatches), "PlayerSetControlsPrefix", (Type[])null), null, null, "Player.SetControls(...)"); jogSpeedPatchInstalled = TryPatch(FindMethod(typeof(Player), "GetJogSpeedFactor", Type.EmptyTypes), null, new HarmonyMethod(typeof(SurvivalMovementPatches), "PlayerGetJogSpeedFactorPostfix", (Type[])null), null, "Player.GetJogSpeedFactor()"); runSpeedPatchInstalled = TryPatch(FindMethod(typeof(Player), "GetRunSpeedFactor", Type.EmptyTypes), null, new HarmonyMethod(typeof(SurvivalMovementPatches), "PlayerGetRunSpeedFactorPostfix", (Type[])null), null, "Player.GetRunSpeedFactor()"); checkRunPatchInstalled = TryPatch(FindMethod(typeof(Player), "CheckRun", new Type[2] { typeof(Vector3), typeof(float) }), new HarmonyMethod(typeof(SurvivalMovementPatches), "PlayerCheckRunPrefix", (Type[])null), new HarmonyMethod(typeof(SurvivalMovementPatches), "PlayerCheckRunPostfix", (Type[])null), new HarmonyMethod(typeof(SurvivalMovementPatches), "PlayerCheckRunFinalizer", (Type[])null), "Player.CheckRun(Vector3, float)"); HarmonyMethod val = new HarmonyMethod(typeof(SurvivalMovementPatches), "GameCameraGetCameraPositionPostfix", (Type[])null); val.priority = 0; val.after = new string[1] { "com.marccunningham.survivalview" }; cameraPositionPatchInstalled = TryPatch(FindMethod(typeof(GameCamera), "GetCameraPosition", new Type[3] { typeof(float), typeof(Vector3).MakeByRefType(), typeof(Quaternion).MakeByRefType() }), null, val, null, "GameCamera.GetCameraPosition(float, out Vector3, out Quaternion)"); depthOfFieldPatchInstalled = TryPatch(FindMethod(typeof(CameraEffects), "UpdateDOF", Type.EmptyTypes), null, new HarmonyMethod(typeof(SurvivalMovementPatches), "CameraEffectsUpdateDofPostfix", (Type[])null), null, "CameraEffects.UpdateDOF()"); } private bool TryPatch(MethodInfo target, HarmonyMethod prefix, HarmonyMethod postfix, HarmonyMethod finalizer, string targetName) { if (target == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("Realistic Running: could not find " + targetName + ". That feature is disabled.")); return false; } try { harmony.Patch((MethodBase)target, prefix, postfix, (HarmonyMethod)null, finalizer, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Realistic Running: patched " + targetName + ".")); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Realistic Running: failed to patch " + targetName + ": " + ex)); return false; } } private static MethodInfo FindMethod(Type type, string methodName, Type[] parameterTypes) { if (parameterTypes != null) { return type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null); } MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); for (int i = 0; i < methods.Length; i++) { if (methods[i].Name == methodName) { return methods[i]; } } return null; } private bool IsMovementEligible(Player player) { return modEnabled.Value && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer && !((Character)player).IsDead() && !((Character)player).IsAttached() && !((Character)player).IsSwimming() && !((Character)player).IsFlying(); } private void ResetTransientMovementState() { smoothedInputMagnitude = Mathf.MoveTowards(smoothedInputMagnitude, 0f, Time.deltaTime * 5f); sprintBuild = Mathf.MoveTowards(sprintBuild, 0f, Time.deltaTime * 4f); exertion = Mathf.MoveTowards(exertion, 0f, Time.deltaTime * Mathf.Max(0f, exertionRecoveryPerSecond.Value)); exhaustedJogRemaining = 0f; fatigueRecoveryActive = false; wasSprinting = false; lastRunDrainMultiplier = 1f; smoothedCameraSwayVertical = 0f; smoothedCameraSwaySide = 0f; cameraSwayVerticalVelocity = 0f; cameraSwaySideVelocity = 0f; latestCameraDistance = float.MaxValue; latestCameraMinimumDistance = float.MaxValue; smoothedSprintFovBoost = 0f; sprintFovBoostVelocity = 0f; if ((Object)(object)Camera.main != (Object)null && baseCameraFieldOfView > 0f) { Camera.main.fieldOfView = baseCameraFieldOfView; } baseCameraFieldOfView = -1f; heartbeatCurrentPressure = 0f; heartbeatPressureVelocity = 0f; heartbeatCurrentBpm = 0f; heartbeatNextBeatTime = Time.unscaledTime + 0.1f; StopHeartbeatAudio(); ResetWorldFactors(); } private void ResetWorldFactors() { terrainSpeedMultiplier = 1f; terrainDrainMultiplier = 1f; terrainExertionMultiplier = 1f; weatherSpeedMultiplier = 1f; weatherDrainMultiplier = 1f; weatherExertionMultiplier = 1f; weatherRecoveryMultiplier = 1f; injurySpeedMultiplier = 1f; injuryExertionMultiplier = 1f; cachedSlopeAngle = 0f; cachedWet = false; cachedCold = false; cachedFreezing = false; } private void RefreshWorldFactors(Player player) { UpdateTerrainFactors(player); UpdateWeatherFactors(player); UpdateInjuryCompatibility(player); } private void UpdateTerrainFactors(Player player) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) terrainSpeedMultiplier = 1f; terrainDrainMultiplier = 1f; terrainExertionMultiplier = 1f; cachedSlopeAngle = 0f; if (!enableHillEffects.Value || !((Character)player).IsOnGround()) { return; } Vector3 moveDir = ((Character)player).GetMoveDir(); moveDir.y = 0f; if (((Vector3)(ref moveDir)).sqrMagnitude <= 1.0000001E-06f) { return; } Vector3 lastGroundNormal = ((Character)player).GetLastGroundNormal(); if (((Vector3)(ref lastGroundNormal)).sqrMagnitude <= 0.01f) { return; } ((Vector3)(ref lastGroundNormal)).Normalize(); cachedSlopeAngle = Vector3.Angle(lastGroundNormal, Vector3.up); float num = Mathf.Clamp(hillGraceAngle.Value, 0f, 60f); float num2 = Mathf.Max(num + 0.01f, hillFullPenaltyAngle.Value); float num3 = Mathf.Clamp01((cachedSlopeAngle - num) / (num2 - num)); if (num3 <= 0f) { return; } Vector3 val = Vector3.ProjectOnPlane(Vector3.up, lastGroundNormal); if (!(((Vector3)(ref val)).sqrMagnitude <= 0.0001f)) { ((Vector3)(ref val)).Normalize(); float num4 = Vector3.Dot(((Vector3)(ref moveDir)).normalized, val); if (num4 > 0f) { float num5 = num3 * Mathf.Clamp01(num4); terrainSpeedMultiplier = 1f - Mathf.Clamp01(uphillSpeedPenalty.Value) * num5; terrainDrainMultiplier = Mathf.Lerp(1f, Mathf.Max(1f, uphillDrainMultiplier.Value), num5); terrainExertionMultiplier = Mathf.Lerp(1f, Mathf.Max(1f, uphillExertionMultiplier.Value), num5); } else if (num4 < 0f) { float num6 = num3 * Mathf.Clamp01(0f - num4); terrainSpeedMultiplier = 1f + Mathf.Clamp(downhillSpeedBonus.Value, 0f, 0.15f) * num6; terrainDrainMultiplier = Mathf.Lerp(1f, Mathf.Clamp(1f - downhillDrainReduction.Value, 0.65f, 1f), num6); } } } private void UpdateWeatherFactors(Player player) { weatherSpeedMultiplier = 1f; weatherDrainMultiplier = 1f; weatherExertionMultiplier = 1f; weatherRecoveryMultiplier = 1f; cachedWet = false; cachedCold = false; cachedFreezing = false; if (enableWeatherEffects.Value) { SEMan sEMan = ((Character)player).GetSEMan(); bool flag = sEMan != null && sEMan.HaveStatusEffect(SEMan.s_statusEffectWet); cachedWet = flag || EnvMan.IsWet(); cachedFreezing = EnvMan.IsFreezing(); cachedCold = !cachedFreezing && EnvMan.IsCold(); if (cachedWet) { weatherSpeedMultiplier *= Mathf.Clamp(wetSpeedMultiplier.Value, 0.7f, 1f); weatherDrainMultiplier *= Mathf.Max(1f, wetDrainMultiplier.Value); weatherExertionMultiplier *= Mathf.Max(1f, wetExertionMultiplier.Value); weatherRecoveryMultiplier *= 0.85f; } if (cachedFreezing) { weatherSpeedMultiplier *= Mathf.Clamp(freezingSpeedMultiplier.Value, 0.7f, 1f); weatherDrainMultiplier *= Mathf.Max(1f, freezingDrainMultiplier.Value); weatherExertionMultiplier *= Mathf.Max(1f, freezingExertionMultiplier.Value); weatherRecoveryMultiplier *= 0.72f; } else if (cachedCold) { weatherDrainMultiplier *= Mathf.Max(1f, coldDrainMultiplier.Value); weatherExertionMultiplier *= Mathf.Max(1f, coldExertionMultiplier.Value); weatherRecoveryMultiplier *= 0.88f; } } } private void UpdateInjuryCompatibility(Player player) { injurySpeedMultiplier = 1f; injuryExertionMultiplier = 1f; if (!enableInjuryCompatibility.Value) { return; } ResolveInjuryReflection(); if (!injuryReflectionUsable) { return; } try { object value = injuryInstanceField.GetValue(null); if (value != null && (bool)injuryIsActiveForMethod.Invoke(value, new object[1] { player })) { float num = Mathf.Clamp((float)injuryRunSpeedMultiplierMethod.Invoke(value, null), 0.3f, 1f); if (applyInjurySpeedCompatibilityPenalty.Value) { injurySpeedMultiplier = num; } float num2 = 1f - num; injuryExertionMultiplier = 1f + num2 * Mathf.Max(0f, injuryExertionPenaltyStrength.Value); } } catch { injuryReflectionUsable = false; injurySpeedMultiplier = 1f; injuryExertionMultiplier = 1f; } } private void ResolveInjuryReflection() { if (injuryReflectionUsable) { return; } if (injuryPluginType == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("YoureInjured.YoureInjuredPlugin"); if (type != null) { injuryPluginType = type; break; } } } if (!(injuryPluginType == null)) { injuryInstanceField = injuryPluginType.GetField("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); injuryIsActiveForMethod = injuryPluginType.GetMethod("IsActiveFor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(Player) }, null); injuryRunSpeedMultiplierMethod = injuryPluginType.GetMethod("GetRunSpeedMultiplier", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); injuryReflectionUsable = injuryInstanceField != null && injuryIsActiveForMethod != null && injuryRunSpeedMultiplierMethod != null; } } private void TryLoadHeartbeatAudio() { if (!enableExhaustionHeartbeat.Value) { heartbeatStatus = "disabled in config"; return; } try { string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); if (string.IsNullOrEmpty(directoryName)) { heartbeatStatus = "plugin folder could not be resolved"; return; } string[] array = new string[4] { Path.Combine(directoryName, "assets", "heartbeat_double.wav"), Path.Combine(directoryName, "heartbeat_double.wav"), Path.Combine(directoryName, "assets", "untitled.wav"), Path.Combine(directoryName, "untitled.wav") }; string text = null; for (int i = 0; i < array.Length; i++) { if (File.Exists(array[i])) { text = array[i]; break; } } if (string.IsNullOrEmpty(text)) { heartbeatStatus = "missing assets/heartbeat_double.wav"; return; } if (!TryReadWaveFile(text, out var samples, out var channels, out var sampleRate, out var status)) { heartbeatStatus = "could not decode WAV: " + status; return; } Type type = FindLoadedType("UnityEngine.AudioClip"); Type type2 = FindLoadedType("UnityEngine.AudioSource"); if (type == null || type2 == null) { heartbeatStatus = "Unity audio types were unavailable"; return; } MethodInfo method = type.GetMethod("Create", BindingFlags.Static | BindingFlags.Public, null, new Type[5] { typeof(string), typeof(int), typeof(int), typeof(int), typeof(bool) }, null); MethodInfo method2 = type.GetMethod("SetData", BindingFlags.Instance | BindingFlags.Public, null, new Type[2] { typeof(float[]), typeof(int) }, null); if (method == null || method2 == null) { heartbeatStatus = "Unity AudioClip methods were unavailable"; return; } int num = samples.Length / Mathf.Max(1, channels); object obj = method.Invoke(null, new object[5] { "SurvivalMovementExertion_Heartbeat", num, channels, sampleRate, false }); if (obj == null) { heartbeatStatus = "Unity could not create the heartbeat clip"; return; } if (!(bool)method2.Invoke(obj, new object[2] { samples, 0 })) { Object.Destroy((Object)((obj is Object) ? obj : null)); heartbeatStatus = "Unity rejected the heartbeat sample data"; return; } Component val = ((Component)this).gameObject.AddComponent(type2); if ((Object)(object)val == (Object)null) { Object.Destroy((Object)((obj is Object) ? obj : null)); heartbeatStatus = "Unity could not create the heartbeat audio source"; return; } SetNumericProperty(type2, val, "spatialBlend", 0f); SetBooleanProperty(type2, val, "loop", value: false); SetBooleanProperty(type2, val, "playOnAwake", value: false); SetNumericProperty(type2, val, "volume", 1f); MethodInfo method3 = type2.GetMethod("PlayOneShot", BindingFlags.Instance | BindingFlags.Public, null, new Type[2] { type, typeof(float) }, null); MethodInfo method4 = type2.GetMethod("Stop", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); if (method3 == null) { Object.Destroy((Object)(object)val); Object.Destroy((Object)((obj is Object) ? obj : null)); heartbeatStatus = "Unity AudioSource.PlayOneShot was unavailable"; return; } heartbeatAudioSource = val; heartbeatClip = (Object)((obj is Object) ? obj : null); heartbeatPlayOneShotMethod = method3; heartbeatStopMethod = method4; heartbeatAssetPath = text; heartbeatNextBeatTime = Time.unscaledTime + 0.2f; heartbeatStatus = "ready " + sampleRate + " Hz, " + channels + " channel(s), " + num + " frames"; } catch (Exception ex) { heartbeatStatus = "load exception: " + ex.GetType().Name; } } private void UpdateHeartbeatAudio(Player player) { if (!enableExhaustionHeartbeat.Value || (Object)(object)heartbeatAudioSource == (Object)null || heartbeatClip == (Object)null || heartbeatPlayOneShotMethod == null) { return; } float heartbeatPressure = GetHeartbeatPressure(player); float num = Mathf.Max(0.05f, heartbeatIntensitySmoothingSeconds.Value); heartbeatCurrentPressure = Mathf.SmoothDamp(heartbeatCurrentPressure, heartbeatPressure, ref heartbeatPressureVelocity, num, float.PositiveInfinity, Time.deltaTime); if (heartbeatCurrentPressure <= 0.002f) { heartbeatCurrentBpm = 0f; heartbeatNextBeatTime = Time.unscaledTime + 0.1f; return; } float num2 = Mathf.Clamp(heartbeatRecoveryBpm.Value, 45f, 120f); float num3 = Mathf.Clamp(heartbeatMaximumBpm.Value, num2 + 1f, 180f); heartbeatCurrentBpm = Mathf.Lerp(num2, num3, SmoothStep01(heartbeatCurrentPressure)); float num4 = 60f / Mathf.Max(1f, heartbeatCurrentBpm); if (Time.unscaledTime < heartbeatNextBeatTime) { return; } float num5 = Mathf.Clamp01(heartbeatMaximumVolume.Value) * Mathf.Lerp(0.26f, 1f, heartbeatCurrentPressure); try { heartbeatPlayOneShotMethod.Invoke(heartbeatAudioSource, new object[2] { heartbeatClip, num5 }); heartbeatNextBeatTime = Time.unscaledTime + num4; } catch (Exception ex) { heartbeatStatus = "playback exception: " + ex.GetType().Name; heartbeatNextBeatTime = Time.unscaledTime + 1f; } } private float GetHeartbeatPressure(Player player) { if (!IsMovementEligible(player)) { return 0f; } float num = Mathf.Clamp(tunnelVisionStartExertion.Value, 0f, 95f); float num2 = Mathf.Clamp(tunnelVisionFullExertion.Value, num + 0.1f, 100f); float num3 = SmoothStep01(Mathf.InverseLerp(num, num2, exertion)); float num4 = Mathf.Clamp01(((Character)player).GetStaminaPercentage()); float num5 = 1f - Mathf.InverseLerp(0.08f, 0.52f, num4); float num6 = Mathf.Max(num3, num5 * 0.7f); if (fatigueRecoveryActive) { float num7 = Mathf.Max(0.1f, exhaustedJogSeconds.Value); float num8 = Mathf.Clamp01(exhaustedJogRemaining / num7); float num9 = Mathf.Lerp(0.34f, 1f, num8); num6 = Mathf.Max(num6, num9); } float num10 = Mathf.Clamp01(heartbeatStartPressure.Value); return SmoothStep01(Mathf.InverseLerp(num10, 1f, num6)); } private void StopHeartbeatAudio() { if ((Object)(object)heartbeatAudioSource == (Object)null || heartbeatStopMethod == null) { return; } try { heartbeatStopMethod.Invoke(heartbeatAudioSource, null); } catch { } } private static Type FindLoadedType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(fullName, throwOnError: false); if (type != null) { return type; } } return null; } private static void SetNumericProperty(Type type, object instance, string name, float value) { PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public); if (property != null && property.CanWrite) { property.SetValue(instance, value, null); } } private static void SetBooleanProperty(Type type, object instance, string name, bool value) { PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public); if (property != null && property.CanWrite) { property.SetValue(instance, value, null); } } private static bool TryReadWaveFile(string path, out float[] samples, out int channels, out int sampleRate, out string status) { samples = null; channels = 0; sampleRate = 0; status = "unknown error"; try { byte[] array = File.ReadAllBytes(path); if (array.Length < 44 || ReadAscii(array, 0, 4) != "RIFF" || ReadAscii(array, 8, 4) != "WAVE") { status = "not a RIFF/WAVE file"; return false; } int num = 0; int num2 = 0; int num3 = -1; int num4 = 0; int num5 = 12; while (num5 + 8 <= array.Length) { string text = ReadAscii(array, num5, 4); int num6 = ReadInt32LittleEndian(array, num5 + 4); int num7 = num5 + 8; if (num6 < 0 || num7 + num6 > array.Length) { status = "invalid WAV chunk length"; return false; } if (text == "fmt " && num6 >= 16) { num = ReadUInt16LittleEndian(array, num7); channels = ReadUInt16LittleEndian(array, num7 + 2); sampleRate = ReadInt32LittleEndian(array, num7 + 4); num2 = ReadUInt16LittleEndian(array, num7 + 14); } else if (text == "data") { num3 = num7; num4 = num6; } num5 = num7 + num6 + num6 % 2; } if (channels < 1 || channels > 2 || sampleRate < 8000 || num3 < 0 || num4 <= 0) { status = "missing supported WAV format or data chunk"; return false; } if (num != 1 && num != 3) { status = "unsupported WAV encoding " + num; return false; } int num8 = num2 / 8; if (num8 < 1 || num8 > 4 || num4 % (channels * num8) != 0) { status = "unsupported sample layout"; return false; } int num9 = num4 / num8; samples = new float[num9]; int num10 = num3; for (int i = 0; i < num9; i++) { if (num == 3 && num2 == 32) { samples[i] = BitConverter.ToSingle(array, num10); } else { switch (num2) { case 8: samples[i] = (float)(array[num10] - 128) / 128f; break; case 16: samples[i] = (float)(short)ReadUInt16LittleEndian(array, num10) / 32768f; break; case 24: { int num11 = array[num10] | (array[num10 + 1] << 8) | (array[num10 + 2] << 16); if ((num11 & 0x800000) != 0) { num11 |= -16777216; } samples[i] = (float)num11 / 8388608f; break; } case 32: samples[i] = (float)ReadInt32LittleEndian(array, num10) / 2.1474836E+09f; break; default: status = "unsupported bit depth " + num2; samples = null; return false; } } num10 += num8; } status = "decoded"; return true; } catch (Exception ex) { status = ex.GetType().Name; samples = null; return false; } } private static string ReadAscii(byte[] bytes, int start, int length) { char[] array = new char[length]; for (int i = 0; i < length; i++) { array[i] = (char)bytes[start + i]; } return new string(array); } private static int ReadInt32LittleEndian(byte[] bytes, int start) { return bytes[start] | (bytes[start + 1] << 8) | (bytes[start + 2] << 16) | (bytes[start + 3] << 24); } private static int ReadUInt16LittleEndian(byte[] bytes, int start) { return bytes[start] | (bytes[start + 1] << 8); } private void UpdateExertion(Player player) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) Vector3 moveDir = ((Character)player).GetMoveDir(); moveDir.y = 0f; bool flag = ((Vector3)(ref moveDir)).sqrMagnitude > 1.0000001E-06f; bool flag2 = ((Character)player).IsRunning() && flag && !ShouldForceExhaustedJog(player); float deltaTime = Time.deltaTime; if (flag2) { float exertionGainMultiplier = SurvivalMovementExertionBridge.GetExertionGainMultiplier(player); float num = terrainExertionMultiplier * weatherExertionMultiplier * injuryExertionMultiplier * exertionGainMultiplier; exertion = Mathf.Clamp(exertion + Mathf.Max(0f, exertionGainPerSecond.Value) * num * deltaTime, 0f, 100f); sprintBuild = Mathf.MoveTowards(sprintBuild, 1f, deltaTime / Mathf.Max(0.01f, sprintBuildUpSeconds.Value)); } else { float num2 = Mathf.Max(0f, exertionRecoveryPerSecond.Value) * weatherRecoveryMultiplier * SurvivalMovementExertionBridge.GetRecoveryMultiplier(player); if (!flag) { num2 *= Mathf.Max(1f, stationaryRecoveryMultiplier.Value); } exertion = Mathf.MoveTowards(exertion, 0f, num2 * deltaTime); sprintBuild = Mathf.MoveTowards(sprintBuild, 0f, deltaTime / Mathf.Max(0.01f, sprintBuildRecoverySeconds.Value)); } float num3 = Mathf.Clamp01(((Character)player).GetStaminaPercentage()); float num4 = Mathf.Clamp(exhaustionTriggerStaminaPercentage.Value, 0f, 0.25f); if ((flag2 || wasSprinting || sprintBuild > 0.2f) && num3 <= num4) { fatigueRecoveryActive = true; exhaustedJogRemaining = Mathf.Max(exhaustedJogRemaining, Mathf.Max(0f, exhaustedJogSeconds.Value)); } if (exhaustedJogRemaining > 0f) { exhaustedJogRemaining = Mathf.Max(0f, exhaustedJogRemaining - deltaTime); } if (fatigueRecoveryActive && exhaustedJogRemaining <= 0f) { float num5 = Mathf.Clamp(recoveryStaminaPercentage.Value, 0.05f, 1f); float num6 = Mathf.Clamp(recoveryExertionPercentage.Value, 0f, 100f); if (num3 >= num5 && exertion <= num6) { fatigueRecoveryActive = false; } } wasSprinting = flag2; } internal void RecordSetControlsHook() { setControlsHookCalls++; } internal void RecordJogSpeedHook() { jogSpeedHookCalls++; } internal void RecordRunSpeedHook() { runSpeedHookCalls++; } internal void RecordCheckRunHook() { checkRunHookCalls++; } internal void RecordCameraHook() { cameraHookCalls++; } internal Vector3 SmoothMoveInput(Player player, Vector3 rawMoveDirection) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (!IsMovementEligible(player) || !enableInputSmoothing.Value) { return rawMoveDirection; } float num = Mathf.Clamp01(((Vector3)(ref rawMoveDirection)).magnitude); float num2 = ((num > smoothedInputMagnitude) ? Mathf.Max(0.01f, accelerationSeconds.Value) : Mathf.Max(0.01f, decelerationSeconds.Value)); smoothedInputMagnitude = Mathf.MoveTowards(smoothedInputMagnitude, num, Time.deltaTime / num2); if (num <= 0.001f) { return Vector3.zero; } return ((Vector3)(ref rawMoveDirection)).normalized * Mathf.Clamp01(smoothedInputMagnitude); } internal float GetJogSpeedMultiplier(Player player) { if (!IsMovementEligible(player)) { return 1f; } float directionalSpeedMultiplier = GetDirectionalSpeedMultiplier(player); directionalSpeedMultiplier *= GetWorldMovementMultiplier(player); if (ShouldForceExhaustedJog(player)) { directionalSpeedMultiplier *= Mathf.Clamp(exhaustedJogSpeedMultiplier.Value, 0.35f, 1f); } return Mathf.Clamp(directionalSpeedMultiplier, 0.2f, 1.35f); } internal float GetRunSpeedMultiplier(Player player) { if (!IsMovementEligible(player)) { return 1f; } if (ShouldForceExhaustedJog(player)) { return GetJogSpeedMultiplier(player); } float num = Mathf.Clamp(topSprintSpeedMultiplier.Value, 0.8f, 1.65f); float num2 = Mathf.Clamp(sprintStartSpeedFraction.Value, 0.35f, 1f); float num3 = Mathf.Lerp(num * num2, num, Mathf.Clamp01(sprintBuild)); float num4 = Mathf.Lerp(1f, Mathf.Clamp(highExertionRunSpeedMultiplier.Value, 0.5f, 1f), GetHighExertionFraction()); float directionalSpeedMultiplier = GetDirectionalSpeedMultiplier(player); directionalSpeedMultiplier *= num3; directionalSpeedMultiplier *= num4; directionalSpeedMultiplier *= GetWorldMovementMultiplier(player); return Mathf.Clamp(directionalSpeedMultiplier, 0.2f, 1.65f); } private float GetWorldMovementMultiplier(Player player) { float num = terrainSpeedMultiplier * weatherSpeedMultiplier * injurySpeedMultiplier; num *= SurvivalMovementExertionBridge.GetMovementMultiplier(player); return Mathf.Clamp(num, 0.2f, 1.35f); } internal bool PrepareCheckRun(Player player, ref float nativeRunStaminaDrain, ref bool result, ref RunDrainPatchState state) { state = default(RunDrainPatchState); RecordCheckRunHook(); if (!IsMovementEligible(player)) { return true; } if (ShouldForceExhaustedJog(player)) { result = false; return false; } state.RestoreDrain = true; state.OriginalDrain = nativeRunStaminaDrain; nativeRunStaminaDrain *= GetRunStaminaDrainMultiplier(player); return true; } internal void RestoreCheckRunDrain(ref float nativeRunStaminaDrain, RunDrainPatchState state) { if (state.RestoreDrain) { nativeRunStaminaDrain = state.OriginalDrain; } } private float GetRunStaminaDrainMultiplier(Player player) { float num = Mathf.Clamp(baseRunStaminaDrainMultiplier.Value, 0.02f, 2f); float num2 = Mathf.Lerp(1f, Mathf.Clamp(highExertionDrainMultiplier.Value, 1f, 4f), GetHighExertionFraction()); float runDrainMultiplier = SurvivalMovementExertionBridge.GetRunDrainMultiplier(player); lastRunDrainMultiplier = num * num2 * terrainDrainMultiplier * weatherDrainMultiplier * runDrainMultiplier; float num3 = Mathf.Clamp(maximumCombinedRunDrainMultiplier.Value, 0.25f, 8f); return Mathf.Clamp(lastRunDrainMultiplier, 0.01f, num3); } private bool ShouldForceExhaustedJog(Player player) { if (!IsMovementEligible(player) || !fatigueRecoveryActive) { return false; } if (exhaustedJogRemaining > 0f) { return true; } float num = Mathf.Clamp(emergencySprintReleaseStaminaPercentage.Value, 0.05f, 0.6f); return ((Character)player).GetStaminaPercentage() < num; } private float GetDirectionalSpeedMultiplier(Player player) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) Vector3 moveDir = ((Character)player).GetMoveDir(); moveDir.y = 0f; if (((Vector3)(ref moveDir)).sqrMagnitude <= 1.0000001E-06f) { return 1f; } Vector3 val = ((Component)player).transform.InverseTransformDirection(((Vector3)(ref moveDir)).normalized); float num = Mathf.Max(0f, val.z); float num2 = Mathf.Max(0f, 0f - val.z); float num3 = Mathf.Abs(val.x); float num4 = num + num2 + num3; if (num4 <= 0.001f) { return 1f; } float num5 = Mathf.Clamp(backwardSpeedMultiplier.Value, 0.35f, 1f); float num6 = Mathf.Clamp(sidewaysSpeedMultiplier.Value, 0.35f, 1f); float num7 = num * 1f + num2 * num5 + num3 * num6; return num7 / num4; } private float GetHighExertionFraction() { float num = Mathf.Clamp(highExertionStart.Value, 1f, 99f); return Mathf.Clamp01((exertion - num) / (100f - num)); } private float GetVisualIntensity(Player player) { if (!IsMovementEligible(player)) { return 0f; } float num = Mathf.Clamp(tunnelVisionStartExertion.Value, 0f, 95f); float num2 = Mathf.Clamp(tunnelVisionFullExertion.Value, num + 0.1f, 100f); float value = Mathf.InverseLerp(num, num2, exertion); float num3 = SmoothStep01(value); float num4 = Mathf.Clamp01(((Character)player).GetStaminaPercentage()); float num5 = 1f - Mathf.InverseLerp(0.05f, 0.42f, num4); float num6 = (fatigueRecoveryActive ? 1f : 0f); return Mathf.Clamp01(Mathf.Max(new float[3] { num3, num5 * 0.6f, num6 * 0.96f })); } private static float SmoothStep01(float value) { value = Mathf.Clamp01(value); return value * value * (3f - 2f * value); } private void UpdateVisualMotion(Player player) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!enableCameraSway.Value || !IsMovementEligible(player)) { SmoothCameraSwayToward(0f, 0f); return; } Vector3 moveDir = ((Character)player).GetMoveDir(); moveDir.y = 0f; bool flag = ((Vector3)(ref moveDir)).sqrMagnitude > 1.0000001E-06f; float visualIntensity = GetVisualIntensity(player); Vector3 velocity = ((Character)player).GetVelocity(); velocity.y = 0f; float magnitude = ((Vector3)(ref velocity)).magnitude; float num = Mathf.Clamp01(magnitude / Mathf.Max(0.1f, 10f * Mathf.Max(1f, topSprintSpeedMultiplier.Value))); float num2 = ((((Character)player).IsRunning() && flag && !ShouldForceExhaustedJog(player)) ? Mathf.Clamp01(num * 0.65f + Mathf.Clamp01(sprintBuild) * 0.35f) : 0f); float num3 = Mathf.Lerp(Mathf.Clamp(sprintSwayFrequencyLow.Value, 0.2f, 4f), Mathf.Clamp(sprintSwayFrequencyHigh.Value, 0.2f, 4f), num2); float num4 = Mathf.Lerp(Mathf.Clamp(breathSwayFrequencyLow.Value, 0.05f, 1.5f), Mathf.Clamp(breathSwayFrequencyHigh.Value, 0.05f, 1.5f), visualIntensity); float num5 = Time.time * (float)Math.PI * 2f * num3; float num6 = Time.time * (float)Math.PI * 2f * num4; float num7 = Mathf.Sin(num5) * 0.66f + Mathf.Sin(num5 * 2f + 0.55f) * 0.09f; float num8 = Mathf.Sin(num5 * 0.5f + 0.35f); float num9 = Mathf.Sin(num6); float targetVertical = num7 * Mathf.Max(0f, sprintBobVerticalMeters.Value) * num2 + num9 * Mathf.Max(0f, fatigueBreathSwayMeters.Value) * visualIntensity; float targetSide = num8 * Mathf.Max(0f, sprintBobSideMeters.Value) * num2 * 0.85f; SmoothCameraSwayToward(targetVertical, targetSide); } private void SmoothCameraSwayToward(float targetVertical, float targetSide) { float num = Mathf.Max(0.03f, cameraSwaySmoothingSeconds.Value); smoothedCameraSwayVertical = Mathf.SmoothDamp(smoothedCameraSwayVertical, targetVertical, ref cameraSwayVerticalVelocity, num, float.PositiveInfinity, Time.deltaTime); smoothedCameraSwaySide = Mathf.SmoothDamp(smoothedCameraSwaySide, targetSide, ref cameraSwaySideVelocity, num, float.PositiveInfinity, Time.deltaTime); } internal void ApplyCameraSway(Player player, GameCamera camera, ref Vector3 position, float distance, float minimumDistance) { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) RecordCameraHook(); latestCameraDistance = distance; latestCameraMinimumDistance = minimumDistance; ApplySprintFov(player, camera, distance, minimumDistance); if (enableCameraSway.Value && IsMovementEligible(player) && !((Object)(object)camera == (Object)null) && (!cameraSwayClosestZoomOnly.Value || !(distance > minimumDistance + Mathf.Max(0f, closestZoomTolerance.Value))) && (!(Mathf.Abs(smoothedCameraSwayVertical) <= 1E-05f) || !(Mathf.Abs(smoothedCameraSwaySide) <= 1E-05f))) { position += ((Component)camera).transform.right * smoothedCameraSwaySide; position += Vector3.up * smoothedCameraSwayVertical; } } private void ApplySprintFov(Player player, GameCamera camera, float distance, float minimumDistance) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if (!((Object)(object)main == (Object)null)) { if (baseCameraFieldOfView <= 0f) { baseCameraFieldOfView = main.fieldOfView; } float num = 0f; bool flag = !cameraSwayClosestZoomOnly.Value || distance <= minimumDistance + Mathf.Max(0f, closestZoomTolerance.Value); if (enableSprintFovBoost.Value && IsMovementEligible(player) && flag) { Vector3 velocity = ((Character)player).GetVelocity(); velocity.y = 0f; float magnitude = ((Vector3)(ref velocity)).magnitude; float value = Mathf.Clamp01(magnitude / Mathf.Max(0.1f, 10f * Mathf.Max(1f, topSprintSpeedMultiplier.Value))); float num2 = Mathf.Clamp01(sprintBuild); float num3 = 1f - Mathf.Clamp01(GetHighExertionFraction() * 0.85f + (fatigueRecoveryActive ? 0.25f : 0f)); num = Mathf.Max(0f, sprintFovBoostDegrees.Value) * SmoothStep01(value) * Mathf.Lerp(0.45f, 1f, num2) * num3; } float num4 = Mathf.Max(0.05f, sprintFovBoostSmoothingSeconds.Value); smoothedSprintFovBoost = Mathf.SmoothDamp(smoothedSprintFovBoost, num, ref sprintFovBoostVelocity, num4, float.PositiveInfinity, Time.deltaTime); main.fieldOfView = baseCameraFieldOfView + smoothedSprintFovBoost; } } private void DrawWindRush(Player player) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) if (!enableWindRushStreaks.Value || !IsMovementEligible(player)) { return; } Vector3 moveDir = ((Character)player).GetMoveDir(); moveDir.y = 0f; if (!((Character)player).IsRunning() || ((Vector3)(ref moveDir)).sqrMagnitude <= 1.0000001E-06f || ShouldForceExhaustedJog(player)) { return; } float num = Mathf.Clamp(windRushStartSprintBuild.Value, 0f, 0.95f); float num2 = Mathf.InverseLerp(num, 1f, Mathf.Clamp01(sprintBuild)); if (num2 <= 0.005f) { return; } EnsureWindStreaks(); if (windStreaks == null || windStreaks.Length == 0) { return; } float num3 = Mathf.Lerp(1f, 0.66f, GetHighExertionFraction()); float num4 = Mathf.Clamp(windRushMaximumAlpha.Value, 0.05f, 0.65f) * num2 * num3; float num5 = Mathf.Max(0.1f, windRushTravelSpeed.Value); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor((float)Screen.width * 0.5f, (float)Screen.height * 0.5f); Matrix4x4 matrix = GUI.matrix; Color color = GUI.color; Vector2 val2 = default(Vector2); for (int i = 0; i < windStreaks.Length; i++) { WindStreak windStreak = windStreaks[i]; float num6 = Mathf.Repeat(Time.time * num5 * windStreak.Speed + windStreak.Phase, 1f); float num7 = SmoothStep01(num6); float num8 = SmoothStep01(Mathf.InverseLerp(0f, 0.13f, num6)); float num9 = 1f - SmoothStep01(Mathf.InverseLerp(0.68f, 1f, num6)); float num10 = num4 * windStreak.Alpha * num8 * num9; if (!(num10 <= 0.002f)) { float num11 = Mathf.Lerp(windStreak.InnerRadius, 1.18f, num7); ((Vector2)(ref val2))..ctor(Mathf.Cos(windStreak.AngleRadians), Mathf.Sin(windStreak.AngleRadians)); Vector2 val3 = val + new Vector2(val2.x * (float)Screen.width * 0.5f * num11, val2.y * (float)Screen.height * 0.5f * num11); float num12 = Mathf.Lerp(22f, (float)Mathf.Max(Screen.width, Screen.height) * windStreak.Length, num7); float num13 = Mathf.Lerp(0.8f, 2.2f, num7); float num14 = Mathf.Atan2(val2.y, val2.x) * 57.29578f; GUI.matrix = matrix; GUIUtility.RotateAroundPivot(num14, val3); GUI.color = new Color(0.7f, 0.84f, 0.96f, num10); GUI.DrawTexture(new Rect(val3.x, val3.y - num13 * 0.5f, num12, num13), (Texture)(object)Texture2D.whiteTexture); } } GUI.matrix = matrix; GUI.color = color; } private void EnsureWindStreaks() { int num = Mathf.Clamp(windRushStreakCount.Value, 4, 48); if (windStreaks == null || windStreaks.Length != num) { windStreaks = new WindStreak[num]; for (int i = 0; i < num; i++) { float num2 = PseudoRandom01(i + 11); float num3 = PseudoRandom01(i + 37); float phase = PseudoRandom01(i + 73); float num4 = PseudoRandom01(i + 101); float num5 = PseudoRandom01(i + 149); float num6 = (float)i / (float)num * (float)Math.PI * 2f; float angleRadians = num6 + Mathf.Lerp(-0.12f, 0.12f, num2); windStreaks[i] = new WindStreak(angleRadians, Mathf.Lerp(0.28f, 0.48f, num3), phase, Mathf.Lerp(0.72f, 1.4f, num4), Mathf.Lerp(0.055f, 0.16f, num5), Mathf.Lerp(0.4f, 1f, PseudoRandom01(i + 197))); } } } private static float PseudoRandom01(int value) { float num = Mathf.Sin((float)value * 12.9898f) * 43758.547f; return num - Mathf.Floor(num); } private void DrawPeripheralBlur(Player player) { //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) if (!enablePeripheralBlurOverlay.Value) { return; } float visualIntensity = GetVisualIntensity(player); float num = Mathf.Clamp01(peripheralBlurStartIntensity.Value); float value = Mathf.InverseLerp(num, 1f, visualIntensity); value = SmoothStep01(value); if (!(value <= 0.003f)) { EnsurePeripheralBlurTextures(); if (peripheralBlurTextures != null && peripheralBlurTextures.Length != 0) { int num2 = Mathf.Clamp(Mathf.RoundToInt(value * (float)(peripheralBlurTextures.Length - 1)), 0, peripheralBlurTextures.Length - 1); float num3 = Mathf.Clamp(peripheralBlurMaximumAlpha.Value, 0f, 0.45f) * Mathf.Lerp(0.12f, 1f, value); float num4 = Mathf.Lerp(0.18f, 0.42f, value); float num5 = 0.5f + 0.5f * Mathf.Sin(Time.time * (float)Math.PI * 2f * num4); num3 *= Mathf.Lerp(0.96f, 1.06f, num5); Color color = GUI.color; GUI.color = new Color(0.92f, 0.95f, 1f, Mathf.Clamp01(num3)); GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)peripheralBlurTextures[num2]); GUI.color = color; } } } private void DrawTunnelVision(Player player) { //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) if (!enableTunnelVision.Value) { return; } float visualIntensity = GetVisualIntensity(player); if (!(visualIntensity <= 0.005f)) { EnsureTunnelTextures(); if (tunnelTextures != null && tunnelTextures.Length != 0) { float num = Mathf.Clamp01(tunnelVisionPulseStrength.Value) * visualIntensity; float num2 = Mathf.Lerp(0.2f, 0.48f, visualIntensity); float num3 = 0.5f + 0.5f * Mathf.Sin(Time.time * (float)Math.PI * 2f * num2); float num4 = (num3 - 0.5f) * num * 0.16f; float num5 = Mathf.Clamp01(visualIntensity + num4); int num6 = Mathf.Clamp(Mathf.RoundToInt(num5 * (float)(tunnelTextures.Length - 1)), 0, tunnelTextures.Length - 1); float num7 = Mathf.Clamp(maximumTunnelVisionAlpha.Value, 0f, 0.82f); float num8 = num7 * Mathf.Lerp(0.08f, 1f, visualIntensity); num8 *= Mathf.Lerp(1f - num * 0.1f, 1f + num * 0.1f, num3); Color color = GUI.color; GUI.color = new Color(1f, 1f, 1f, Mathf.Clamp01(num8)); GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)tunnelTextures[num6]); GUI.color = color; } } } private void EnsurePeripheralBlurTextures() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) if (peripheralBlurTextures != null) { return; } peripheralBlurTextures = (Texture2D[])(object)new Texture2D[18]; Color val = default(Color); Color val2 = default(Color); for (int i = 0; i < 18; i++) { float value = (float)i / 17f; float num = SmoothStep01(value); float num2 = Mathf.Clamp(peripheralBlurClearRadiusAtExhaustion.Value, 0.72f, 1.1f); float num3 = Mathf.Lerp(1.22f, num2, num); float num4 = Mathf.Lerp(0.68f, 0.6f, num); float num5 = Mathf.Max(0f, num3 - num4); ((Color)(ref val))..ctor(0.82f, 0.89f, 0.97f, 1f); ((Color)(ref val2))..ctor(0.34f, 0.42f, 0.52f, 1f); Color val3 = Color.Lerp(val, val2, num * 0.55f); Color[] array = (Color[])(object)new Color[25600]; for (int j = 0; j < 160; j++) { for (int k = 0; k < 160; k++) { float num6 = ((float)k / 159f - 0.5f) * 2f; float num7 = ((float)j / 159f - 0.5f) * 2f; float num8 = Mathf.Sqrt(num6 * num6 + num7 * 0.84f * (num7 * 0.84f)); float value2 = Mathf.Clamp01((num8 - num5) / Mathf.Max(0.001f, num3 - num5)); value2 = SmoothStep01(value2); value2 *= Mathf.Lerp(0.1f, 0.82f, num); array[j * 160 + k] = new Color(val3.r, val3.g, val3.b, value2); } } Texture2D val4 = new Texture2D(160, 160, (TextureFormat)4, false); ((Texture)val4).wrapMode = (TextureWrapMode)1; ((Texture)val4).filterMode = (FilterMode)1; val4.SetPixels(array); val4.Apply(); peripheralBlurTextures[i] = val4; } } private void EnsureTunnelTextures() { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) if (tunnelTextures != null) { return; } tunnelTextures = (Texture2D[])(object)new Texture2D[18]; Color val = default(Color); Color val2 = default(Color); for (int i = 0; i < 18; i++) { float value = (float)i / 17f; float num = SmoothStep01(value); float num2 = Mathf.Clamp(tunnelVisionClearRadiusAtExhaustion.Value, 0.55f, 1.1f); float num3 = Mathf.Lerp(1.2f, num2, num); float num4 = Mathf.Lerp(0.64f, 0.56f, num); float num5 = Mathf.Max(0f, num3 - num4); float num6 = Mathf.Clamp01(coolEdgeTintStrength.Value) * Mathf.Lerp(0.95f, 0.38f, num); ((Color)(ref val))..ctor(0.13f, 0.23f, 0.34f, 1f); ((Color)(ref val2))..ctor(0.015f, 0.025f, 0.05f, 1f); Color val3 = Color.Lerp(val2, val, num6); Color[] array = (Color[])(object)new Color[25600]; for (int j = 0; j < 160; j++) { for (int k = 0; k < 160; k++) { float num7 = ((float)k / 159f - 0.5f) * 2f; float num8 = ((float)j / 159f - 0.5f) * 2f; float num9 = Mathf.Sqrt(num7 * num7 + num8 * 0.84f * (num8 * 0.84f)); float value2 = Mathf.Clamp01((num9 - num5) / Mathf.Max(0.001f, num3 - num5)); value2 = SmoothStep01(value2); array[j * 160 + k] = new Color(val3.r, val3.g, val3.b, value2); } } Texture2D val4 = new Texture2D(160, 160, (TextureFormat)4, false); ((Texture)val4).wrapMode = (TextureWrapMode)1; ((Texture)val4).filterMode = (FilterMode)1; val4.SetPixels(array); val4.Apply(); tunnelTextures[i] = val4; } } internal void ApplyExhaustionDepthOfField(CameraEffects cameraEffects) { depthOfFieldHookCalls++; if (!enableNativeDepthOfField.Value || (Object)(object)cameraEffects == (Object)null) { return; } Player localPlayer = Player.m_localPlayer; if (!IsMovementEligible(localPlayer) || (depthOfFieldClosestZoomOnly.Value && latestCameraDistance > latestCameraMinimumDistance + Mathf.Max(0f, closestZoomTolerance.Value))) { return; } float visualIntensity = GetVisualIntensity(localPlayer); float num = Mathf.Clamp(depthOfFieldStartVisualIntensity.Value, 0f, 0.95f); float value = Mathf.InverseLerp(num, 1f, visualIntensity); value = SmoothStep01(value); if (value <= 0.005f || !TryResolveDepthOfField(cameraEffects, out var dof)) { return; } Behaviour val = (Behaviour)((dof is Behaviour) ? dof : null); if ((Object)(object)val != (Object)null) { val.enabled = true; } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { depthOfFieldStatus = "native DOF found, Camera.main unavailable"; return; } float depthOfFieldFocusDistance = GetDepthOfFieldFocusDistance(main, cameraEffects); float value2 = Mathf.Lerp(3.5f, Mathf.Clamp(depthOfFieldFocalSizeAtExhaustion.Value, 0.35f, 8f), value); float value3 = Mathf.Lerp(0.1f, Mathf.Clamp(depthOfFieldMaximumBlurSize.Value, 0.1f, 1.25f), value); bool flag = false; flag |= TrySetNumericMember(dof, dofFocusDistanceMember, depthOfFieldFocusDistance); flag |= TrySetNumericMember(dof, dofFocalSizeMember, value2); flag |= TrySetNumericMember(dof, dofMaxBlurSizeMember, value3); if (dofApertureMember != null) { flag |= TrySetNumericMember(dof, dofApertureMember, Mathf.Lerp(4.2f, 2.6f, value)); } depthOfFieldStatus = (flag ? ("active " + dof.GetType().FullName) : "native DOF found but recognised focus members were unavailable"); } private bool TryResolveDepthOfField(CameraEffects cameraEffects, out object dof) { dof = null; if (cameraEffectsDofField == null) { cameraEffectsDofField = typeof(CameraEffects).GetField("m_dof", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); cameraEffectsDofRayMaskField = typeof(CameraEffects).GetField("m_dofRayMask", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (cameraEffectsDofField == null) { depthOfFieldStatus = "CameraEffects.m_dof not found"; return false; } dof = cameraEffectsDofField.GetValue(cameraEffects); if (dof == null) { depthOfFieldStatus = "CameraEffects.m_dof is null"; return false; } if (!depthOfFieldReflectionReady) { Type type = dof.GetType(); dofFocusDistanceMember = FindNumericMember(type, new string[3] { "focusDistance", "focalDistance", "objectFocus" }); dofFocalSizeMember = FindNumericMember(type, new string[2] { "focalSize", "focusRange" }); dofMaxBlurSizeMember = FindNumericMember(type, new string[2] { "maxBlurSize", "blurSize" }); dofApertureMember = FindNumericMember(type, new string[1] { "aperture" }); depthOfFieldReflectionReady = true; depthOfFieldAvailable = dofFocusDistanceMember != null || dofFocalSizeMember != null || dofMaxBlurSizeMember != null; depthOfFieldStatus = (depthOfFieldAvailable ? ("native DOF members resolved on " + type.FullName) : "native DOF component found but no supported members resolved"); } return depthOfFieldAvailable; } private static MemberInfo FindNumericMember(Type type, string[] candidateNames) { for (int i = 0; i < candidateNames.Length; i++) { FieldInfo field = type.GetField(candidateNames[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(float)) { return field; } PropertyInfo property = type.GetProperty(candidateNames[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite && property.PropertyType == typeof(float)) { return property; } } return null; } private static bool TrySetNumericMember(object target, MemberInfo member, float value) { if (target == null || member == null) { return false; } try { FieldInfo fieldInfo = member as FieldInfo; if (fieldInfo != null) { fieldInfo.SetValue(target, value); return true; } PropertyInfo propertyInfo = member as PropertyInfo; if (propertyInfo != null) { propertyInfo.SetValue(target, value, null); return true; } } catch { return false; } return false; } private float GetDepthOfFieldFocusDistance(Camera viewCamera, CameraEffects cameraEffects) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(1f, depthOfFieldMaximumFocusDistance.Value); float result = Mathf.Clamp(depthOfFieldFallbackFocusDistance.Value, 1f, num); int num2 = -1; if (cameraEffectsDofRayMaskField != null) { try { object value = cameraEffectsDofRayMaskField.GetValue(cameraEffects); if (value is LayerMask val) { num2 = ((LayerMask)(ref val)).value; } else if (value != null) { num2 = Convert.ToInt32(value); } } catch { num2 = -1; } } RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(((Component)viewCamera).transform.position, ((Component)viewCamera).transform.forward, ref val2, num, num2)) { return Mathf.Clamp(((RaycastHit)(ref val2)).distance, 1f, num); } return result; } private void DestroyTunnelTextures() { if (tunnelTextures == null) { return; } for (int i = 0; i < tunnelTextures.Length; i++) { if ((Object)(object)tunnelTextures[i] != (Object)null) { Object.Destroy((Object)(object)tunnelTextures[i]); } } tunnelTextures = null; } private void DestroyPeripheralBlurTextures() { if (peripheralBlurTextures == null) { return; } for (int i = 0; i < peripheralBlurTextures.Length; i++) { if ((Object)(object)peripheralBlurTextures[i] != (Object)null) { Object.Destroy((Object)(object)peripheralBlurTextures[i]); } } peripheralBlurTextures = null; } private void DrawDiagnosticHud(Player player) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (showDiagnosticHud.Value) { if (diagnosticStyle == null) { diagnosticStyle = new GUIStyle(GUI.skin.label); diagnosticStyle.fontSize = 15; diagnosticStyle.normal.textColor = Color.white; } GUI.Label(new Rect(12f, 12f, 840f, 44f), "EXERTION " + exertion.ToString("0") + "% | Sprint build " + sprintBuild.ToString("0.00") + " | Fatigue " + fatigueRecoveryActive + " | Slope " + cachedSlopeAngle.ToString("0") + "° | Wet " + cachedWet + " Cold " + cachedCold + " Freezing " + cachedFreezing + " | Run drain x" + lastRunDrainMultiplier.ToString("0.00"), diagnosticStyle); } } private void WriteDiagnostic() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Realistic Running: no local player is available yet."); return; } Vector3 val = ((Character)localPlayer).GetVelocity(); float magnitude = ((Vector3)(ref val)).magnitude; float directionalSpeedMultiplier = GetDirectionalSpeedMultiplier(localPlayer); float worldMovementMultiplier = GetWorldMovementMultiplier(localPlayer); float jogSpeedMultiplier = GetJogSpeedMultiplier(localPlayer); float runSpeedMultiplier = GetRunSpeedMultiplier(localPlayer); float visualIntensity = GetVisualIntensity(localPlayer); float highExertionFraction = GetHighExertionFraction(); ManualLogSource logger = ((BaseUnityPlugin)this).Logger; string[] array = new string[103]; array[0] = "Realistic Running diagnostic: enabled="; array[1] = modEnabled.Value.ToString(); array[2] = ", running="; array[3] = ((Character)localPlayer).IsRunning().ToString(); array[4] = ", moving="; val = ((Character)localPlayer).GetMoveDir(); array[5] = (((Vector3)(ref val)).sqrMagnitude > 1.0000001E-06f).ToString(); array[6] = ", stamina="; array[7] = ((Character)localPlayer).GetStaminaPercentage().ToString("0.000"); array[8] = ", exertion="; array[9] = exertion.ToString("0.0"); array[10] = ", visualIntensity="; array[11] = GetVisualIntensity(localPlayer).ToString("0.00"); array[12] = ", sprintBuild="; array[13] = sprintBuild.ToString("0.00"); array[14] = ", exhaustedJogRemaining="; array[15] = exhaustedJogRemaining.ToString("0.00"); array[16] = ", fatigueRecovery="; array[17] = fatigueRecoveryActive.ToString(); array[18] = ", runDrainMultiplier="; array[19] = lastRunDrainMultiplier.ToString("0.000"); array[20] = ", actualVelocity="; array[21] = magnitude.ToString("0.00"); array[22] = ", multipliers=[direction="; array[23] = directionalSpeedMultiplier.ToString("0.000"); array[24] = ", world="; array[25] = worldMovementMultiplier.ToString("0.000"); array[26] = ", jog="; array[27] = jogSpeedMultiplier.ToString("0.000"); array[28] = ", run="; array[29] = runSpeedMultiplier.ToString("0.000"); array[30] = "], visual=[intensity="; array[31] = visualIntensity.ToString("0.000"); array[32] = ", highExertion="; array[33] = highExertionFraction.ToString("0.000"); array[34] = ", swayVertical="; array[35] = smoothedCameraSwayVertical.ToString("0.0000"); array[36] = ", swaySide="; array[37] = smoothedCameraSwaySide.ToString("0.0000"); array[38] = ", fovBoost="; array[39] = smoothedSprintFovBoost.ToString("0.00"); array[40] = "], nativeDof=[available="; array[41] = depthOfFieldAvailable.ToString(); array[42] = ", status="; array[43] = depthOfFieldStatus; array[44] = "], heartbeat=[status="; array[45] = heartbeatStatus; array[46] = ", pressure="; array[47] = heartbeatCurrentPressure.ToString("0.00"); array[48] = ", bpm="; array[49] = heartbeatCurrentBpm.ToString("0"); array[50] = ", asset="; array[51] = heartbeatAssetPath; array[52] = "], slopeAngle="; array[53] = cachedSlopeAngle.ToString("0.0"); array[54] = ", terrain=[speed="; array[55] = terrainSpeedMultiplier.ToString("0.00"); array[56] = ", drain="; array[57] = terrainDrainMultiplier.ToString("0.00"); array[58] = ", exertion="; array[59] = terrainExertionMultiplier.ToString("0.00"); array[60] = "], weather=[wet="; array[61] = cachedWet.ToString(); array[62] = ", cold="; array[63] = cachedCold.ToString(); array[64] = ", freezing="; array[65] = cachedFreezing.ToString(); array[66] = ", speed="; array[67] = weatherSpeedMultiplier.ToString("0.00"); array[68] = ", drain="; array[69] = weatherDrainMultiplier.ToString("0.00"); array[70] = ", exertion="; array[71] = weatherExertionMultiplier.ToString("0.00"); array[72] = "], injury=[available="; array[73] = injuryReflectionUsable.ToString(); array[74] = ", speed="; array[75] = injurySpeedMultiplier.ToString("0.00"); array[76] = ", exertion="; array[77] = injuryExertionMultiplier.ToString("0.00"); array[78] = "], hookCalls=[controls="; array[79] = setControlsHookCalls.ToString(); array[80] = ", jog="; array[81] = jogSpeedHookCalls.ToString(); array[82] = ", run="; array[83] = runSpeedHookCalls.ToString(); array[84] = ", checkRun="; array[85] = checkRunHookCalls.ToString(); array[86] = ", camera="; array[87] = cameraHookCalls.ToString(); array[88] = ", dof="; array[89] = depthOfFieldHookCalls.ToString(); array[90] = "], patches=[controls="; array[91] = setControlsPatchInstalled.ToString(); array[92] = ", jog="; array[93] = jogSpeedPatchInstalled.ToString(); array[94] = ", run="; array[95] = runSpeedPatchInstalled.ToString(); array[96] = ", checkRun="; array[97] = checkRunPatchInstalled.ToString(); array[98] = ", camera="; array[99] = cameraPositionPatchInstalled.ToString(); array[100] = ", dof="; array[101] = depthOfFieldPatchInstalled.ToString(); array[102] = "]."; logger.LogInfo((object)string.Concat(array)); } } public static class SurvivalMovementExertionBridge { public static Func<Player, float> ExternalMovementMultiplier; public static Func<Player, float> ExternalRunDrainMultiplier; public static Func<Player, float> ExternalExertionGainMultiplier; public static Func<Player, float> ExternalRecoveryMultiplier; public static float GetMovementMultiplier(Player player) { return GetSafeMultiplier(ExternalMovementMultiplier, player, 0.2f, 1.35f); } public static float GetRunDrainMultiplier(Player player) { return GetSafeMultiplier(ExternalRunDrainMultiplier, player, 0.25f, 4f); } public static float GetExertionGainMultiplier(Player player) { return GetSafeMultiplier(ExternalExertionGainMultiplier, player, 0.25f, 4f); } public static float GetRecoveryMultiplier(Player player) { return GetSafeMultiplier(ExternalRecoveryMultiplier, player, 0.1f, 2f); } private static float GetSafeMultiplier(Func<Player, float> provider, Player player, float minimum, float maximum) { if (provider == null) { return 1f; } try { return Mathf.Clamp(provider(player), minimum, maximum); } catch { return 1f; } } } internal struct WindStreak { public readonly float AngleRadians; public readonly float InnerRadius; public readonly float Phase; public readonly float Speed; public readonly float Length; public readonly float Alpha; public WindStreak(float angleRadians, float innerRadius, float phase, float speed, float length, float alpha) { AngleRadians = angleRadians; InnerRadius = innerRadius; Phase = phase; S