using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Extensions; using Jotunn.Utils; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("HardheimDiving")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HardheimDiving")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("24fb0f19-a1c4-450f-90e2-e32044a5031d")] [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 Hardheim.Diving; [BepInPlugin("hardheim.diving", "Hardheim Diving", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class HardheimDivingPlugin : BaseUnityPlugin { [CompilerGenerated] private sealed class d__24 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public HardheimDivingPlugin <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__24(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; ((Component)<>4__this).gameObject.AddComponent(); LogInfo("Oxygen HUD initialized."); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "hardheim.diving"; public const string PluginName = "Hardheim Diving"; public const string PluginVersion = "1.0.1"; internal static HardheimDivingPlugin Instance; internal ConfigEntry RequiredSwimmingSkill; internal ConfigEntry UseEquipInWater; internal ConfigEntry RestingStaminaRegenDelay; internal ConfigEntry RestingStaminaRegenRate; internal ConfigEntry UnderwaterRestingStaminaDrainRate; internal ConfigEntry MaxSwimSpeed; internal ConfigEntry ColorDarknessFactor; internal ConfigEntry FogDensityFactor; internal ConfigEntry MinFogDensity; internal ConfigEntry MaxFogDensity; internal ConfigEntry DebugLogging; internal ConfigEntry MaxOxygen; internal ConfigEntry OxygenDrainPerSecond; internal ConfigEntry OxygenRegenPerSecond; internal ConfigEntry OxygenDamageInterval; internal ConfigEntry OxygenDamageAmount; private static float currentOxygen; private static float oxygenDamageTimer; private Harmony harmony; private void Awake() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown Instance = this; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; BindConfigs(); currentOxygen = MaxOxygen.Value; ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; harmony = new Harmony("hardheim.diving"); harmony.PatchAll(); ((MonoBehaviour)this).StartCoroutine(InitHudDelayed()); Game.isModded = true; LogInfo("Hardheim Diving 1.0.1 loaded."); } [IteratorStateMachine(typeof(d__24))] private IEnumerator InitHudDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__24(0) { <>4__this = this }; } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } ((BaseUnityPlugin)this).Config.Save(); } private void BindConfigs() { RequiredSwimmingSkill = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Hardheim", "Szükséges úszás szint", 20f, "Minimum úszás skill, ami szükséges a merülés használatához. Ez alatt a játékos csak vanilla módon úszik.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); UseEquipInWater = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Általános", "Eszközhasználat vízben", true, "Engedélyezi, hogy a játékos vízben is használhasson eszközöket és fegyvereket.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); RestingStaminaRegenDelay = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Stamina", "Pihenő stamina visszatöltés késleltetése", 2f, "Mennyi idő után kezdjen visszatöltődni a stamina vízben lebegés közben. A vanilla késleltetés szorzója.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); RestingStaminaRegenRate = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Stamina", "Pihenő stamina visszatöltés mértéke", 0.5f, "Milyen gyorsan töltődjön vissza a stamina vízben lebegés közben. A vanilla visszatöltés szorzója.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); UnderwaterRestingStaminaDrainRate = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Stamina", "Víz alatti stamina fogyás", 0.5f, "Milyen gyorsan fogyjon a stamina víz alatt lebegés közben. A vanilla úszás stamina fogyás szorzója.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); MaxSwimSpeed = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Mozgás", "Maximális úszási sebesség", 3f, "Maximális úszási sebesség sprintelés közben.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); ColorDarknessFactor = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Vizuális", "Sötétedés mértéke", 0.08298756f, "Milyen gyorsan sötétedjen a látvány, ahogy a játékos mélyebbre merül.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); FogDensityFactor = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Vizuális", "Köd sűrűsödés mértéke", 0f, "Milyen gyorsan sűrűsödjön a köd, ahogy a játékos mélyebbre merül.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); MinFogDensity = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Vizuális", "Minimum köd sűrűség", 0.06452283f, "A víz alatti köd minimum sűrűsége.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); MaxFogDensity = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Vizuális", "Maximum köd sűrűség", 1.518672f, "A víz alatti köd maximum sűrűsége.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); DebugLogging = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Debug", "Részletes logolás", false, "Részletes debug logok bekapcsolása hibakereséshez. Normál használat mellett maradjon kikapcsolva.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); MaxOxygen = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Oxigén", "Maximális oxigén", 100f, "A játékos maximális oxigén mennyisége víz alatt.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); OxygenDrainPerSecond = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Oxigén", "Oxigén fogyás másodpercenként", 1f, "Ennyi oxigén fogy másodpercenként, amikor a játékos víz alatt van.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); OxygenRegenPerSecond = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Oxigén", "Oxigén visszatöltés másodpercenként", 10f, "Ennyi oxigén töltődik vissza másodpercenként, amikor a játékos nincs víz alatt.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); OxygenDamageInterval = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Oxigén", "Fulladás sebzés időköze", 1f, "Másodpercben megadva, milyen gyakran kap sebzést a játékos, ha elfogyott az oxigénje.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); OxygenDamageAmount = ConfigFileExtensions.BindConfig(((BaseUnityPlugin)this).Config, "Oxigén", "Fulladás sebzés mértéke", 5f, "Ennyi sebzést kap a játékos minden fulladás sebzésnél.", true, (int?)null, (AcceptableValueBase)null, (Action)null, (ConfigurationManagerAttributes)null); } internal bool IsEnvAllowed() { if ((Object)(object)EnvMan.instance == (Object)null) { return true; } EnvSetup currentEnvironment = EnvMan.instance.GetCurrentEnvironment(); return currentEnvironment == null || currentEnvironment.m_name != "SunkenCrypt"; } internal static bool HasRequiredSwimmingSkill(Player player) { if ((Object)(object)player == (Object)null || (Object)(object)Instance == (Object)null) { return false; } return ((Character)player).GetSkillLevel((SkillType)103) >= Instance.RequiredSwimmingSkill.Value; } internal static float GetOxygen01() { if ((Object)(object)Instance == (Object)null || Instance.MaxOxygen.Value <= 0f) { return 1f; } return Mathf.Clamp01(currentOxygen / Instance.MaxOxygen.Value); } internal static bool ShouldShowOxygenHud() { if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } if (!DivingUtils.TryGetDiver(Player.m_localPlayer, out var diver)) { return false; } return ((Character)Player.m_localPlayer).InWater() && diver.HasRequiredSwimmingSkill(); } internal static void HandleOxygen(Player player, Diver diver, float dt) { //IL_00cc: 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: Expected O, but got Unknown //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Instance == (Object)null || (Object)(object)player == (Object)null || (Object)(object)diver == (Object)null) { return; } float num = Mathf.Max(1f, Instance.MaxOxygen.Value); if (currentOxygen > num) { currentOxygen = num; } if (currentOxygen < 0f) { currentOxygen = 0f; } bool flag = diver.HasRequiredSwimmingSkill(); bool flag2 = ((Character)player).InWater(); bool flag3 = ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch"); bool flag4 = ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump"); float liquidLevel = ((Character)player).GetLiquidLevel(); float num2 = ((Component)player).transform.position.y + 1.55f; bool flag5 = num2 < liquidLevel - 0.05f; if (flag2 && flag && flag5 && (flag3 || flag4 || diver.IsUnderSurface() || diver.IsInsideLiquid())) { currentOxygen = Mathf.MoveTowards(currentOxygen, 0f, Instance.OxygenDrainPerSecond.Value * dt); if (currentOxygen <= 0f) { oxygenDamageTimer += dt; if (oxygenDamageTimer >= Instance.OxygenDamageInterval.Value) { oxygenDamageTimer = 0f; HitData val = new HitData(); val.m_damage.m_damage = Instance.OxygenDamageAmount.Value; val.m_point = ((Component)player).transform.position; val.m_dir = Vector3.up; val.m_hitType = (HitType)4; ((Character)player).Damage(val); } } else { oxygenDamageTimer = 0f; } } else { currentOxygen = Mathf.MoveTowards(currentOxygen, num, Instance.OxygenRegenPerSecond.Value * dt); oxygenDamageTimer = 0f; } } internal static void LogInfo(string msg) { HardheimDivingPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)msg); } } internal static void LogDebug(string msg) { if ((Object)(object)Instance != (Object)null && Instance.DebugLogging.Value) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("[DEBUG] " + msg)); } } internal static void LogWarning(string msg) { HardheimDivingPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)msg); } } } internal class OxygenHud : MonoBehaviour { private GameObject oxygenRoot; private GuiBar oxygenBar; private float retryTimer; private float displayedOxygen01 = 1f; private void Update() { if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)HardheimDivingPlugin.Instance == (Object)null) { SetVisible(visible: false); return; } if ((Object)(object)oxygenRoot == (Object)null || (Object)(object)oxygenBar == (Object)null) { retryTimer -= Time.deltaTime; if (retryTimer <= 0f) { retryTimer = 1f; TryCreateFromStaminaBar(); } return; } bool flag = HardheimDivingPlugin.ShouldShowOxygenHud(); SetVisible(flag); if (flag) { float value = HardheimDivingPlugin.Instance.MaxOxygen.Value; float oxygen = HardheimDivingPlugin.GetOxygen01(); displayedOxygen01 = Mathf.MoveTowards(displayedOxygen01, oxygen, Time.deltaTime * 0.75f); float value2 = Mathf.Clamp(displayedOxygen01 * value, 0f, value); oxygenBar.SetMaxValue(value); oxygenBar.SetValue(value2); } } private void TryCreateFromStaminaBar() { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Hud.instance == (Object)null) { return; } GuiBar val = FindStaminaBar(); if ((Object)(object)val == (Object)null) { HardheimDivingPlugin.LogInfo("Oxygen HUD: nem találtam stamina GuiBar-t."); return; } oxygenRoot = Object.Instantiate(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)oxygenRoot).name = "Hardheim_OxygenBar"; oxygenRoot.SetActive(true); oxygenBar = oxygenRoot.GetComponent(); RectTransform component = oxygenRoot.GetComponent(); RectTransform component2 = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { component.anchorMin = component2.anchorMin; component.anchorMax = component2.anchorMax; component.pivot = component2.pivot; component.anchoredPosition = component2.anchoredPosition + new Vector2(45f, 38f); ((Transform)component).localScale = Vector3.one; ((Transform)component).SetAsLastSibling(); component.sizeDelta = new Vector2(158f, 16f); RectTransform[] componentsInChildren = oxygenRoot.GetComponentsInChildren(true); foreach (RectTransform val2 in componentsInChildren) { val2.SetSizeWithCurrentAnchors((Axis)0, 158f); } } Image[] componentsInChildren2 = oxygenRoot.GetComponentsInChildren(true); foreach (Image val3 in componentsInChildren2) { if (!((Object)(object)val3 == (Object)null)) { string text = ((Object)val3).name.ToLowerInvariant(); if (!text.Contains("background") && !text.Contains("bg") && !text.Contains("border")) { ((Graphic)val3).color = new Color(0.05f, 0.55f, 1f, ((Graphic)val3).color.a); } } } if ((Object)(object)oxygenBar != (Object)null) { oxygenBar.SetMaxValue(HardheimDivingPlugin.Instance.MaxOxygen.Value); oxygenBar.SetValue(HardheimDivingPlugin.Instance.MaxOxygen.Value); } SetVisible(visible: false); HardheimDivingPlugin.LogInfo("Hardheim oxigén HUD létrehozva teljes stamina panel klónból."); } private GuiBar FindStaminaBar() { //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //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) GuiBar[] componentsInChildren = ((Component)Hud.instance).GetComponentsInChildren(true); GuiBar val = null; GuiBar[] array = componentsInChildren; foreach (GuiBar val2 in array) { if ((Object)(object)val2 == (Object)null) { continue; } string text = GetPath(((Component)val2).transform).ToLowerInvariant(); if (!text.Contains("hardheim_oxygenbar") && !text.Contains("mounthud") && !text.Contains("mountpanel") && !text.Contains("eitr") && !text.Contains("adrenaline") && text.Contains("hudroot/staminapanel/stamina") && text.EndsWith("stamina_fast")) { RectTransform component = ((Component)val2).GetComponent(); float num; Rect rect; if (!((Object)(object)component != (Object)null)) { num = 0f; } else { rect = component.rect; num = ((Rect)(ref rect)).width; } float num2 = num; float num3; if (!((Object)(object)component != (Object)null)) { num3 = 0f; } else { rect = component.rect; num3 = ((Rect)(ref rect)).height; } float num4 = num3; HardheimDivingPlugin.LogInfo("Player stamina GuiBar candidate: " + text + " activeInHierarchy=" + ((Component)val2).gameObject.activeInHierarchy + " width=" + num2 + " height=" + num4); val = val2; break; } } if ((Object)(object)val != (Object)null) { HardheimDivingPlugin.LogInfo("Oxygen HUD PLAYER stamina source: " + GetPath(((Component)val).transform)); } return val; } private void SetVisible(bool visible) { if (!((Object)(object)oxygenRoot == (Object)null)) { oxygenRoot.SetActive(visible); } } private string GetPath(Transform t) { if ((Object)(object)t == (Object)null) { return ""; } string text = ((Object)t).name; while ((Object)(object)t.parent != (Object)null) { t = t.parent; text = ((Object)t).name + "/" + text; } return text; } } internal static class ReflectionFields { internal static readonly FieldInfo MoveDir = AccessTools.Field(typeof(Character), "m_moveDir"); internal static readonly FieldInfo CurrentVel = AccessTools.Field(typeof(Character), "m_currentVel"); internal static readonly FieldInfo LastGroundTouch = AccessTools.Field(typeof(Character), "m_lastGroundTouch"); internal static readonly FieldInfo SwimTimer = AccessTools.Field(typeof(Character), "m_swimTimer"); internal static readonly FieldInfo SwimDepth = AccessTools.Field(typeof(Player), "m_swimDepth"); internal static readonly FieldInfo SwimSpeed = AccessTools.Field(typeof(Player), "m_swimSpeed"); internal static readonly FieldInfo SwimAcceleration = AccessTools.Field(typeof(Player), "m_swimAcceleration"); internal static readonly FieldInfo SwimSkillImproveTimer = AccessTools.Field(typeof(Player), "m_swimSkillImproveTimer"); internal static readonly FieldInfo Stamina = AccessTools.Field(typeof(Player), "m_stamina"); internal static readonly FieldInfo StaminaRegenTimer = AccessTools.Field(typeof(Player), "m_staminaRegenTimer"); internal static readonly FieldInfo StaminaRegen = AccessTools.Field(typeof(Player), "m_staminaRegen"); internal static readonly FieldInfo StaminaRegenDelay = AccessTools.Field(typeof(Player), "m_staminaRegenDelay"); internal static readonly FieldInfo SwimStaminaDrainMinSkill = AccessTools.Field(typeof(Player), "m_swimStaminaDrainMinSkill"); internal static readonly FieldInfo SwimStaminaDrainMaxSkill = AccessTools.Field(typeof(Player), "m_swimStaminaDrainMaxSkill"); internal static readonly FieldInfo GameCameraMinWaterDistance = AccessTools.Field(typeof(GameCamera), "m_minWaterDistance"); internal static T Get(FieldInfo field, object instance, T fallback = default(T)) { if (field == null || instance == null) { return fallback; } try { object value = field.GetValue(instance); if (value is T) { T result = (T)value; if (true) { return result; } } } catch { } return fallback; } internal static void Set(FieldInfo field, object instance, T value) { if (field == null || instance == null) { return; } try { field.SetValue(instance, value); } catch { } } } internal class Diver : MonoBehaviour { private const float DefaultSwimDepth = 1.4f; private const float DivingSwimDepth = 2.5f; private static readonly Dictionary Divers = new Dictionary(); public Player player; public float BaseSwimSpeed { get; private set; } public float RestingStaminaRegenDelay { get { float num = ReflectionFields.Get(ReflectionFields.StaminaRegenDelay, player, 1f); return (0f - HardheimDivingPlugin.Instance.RestingStaminaRegenDelay.Value) * num; } } public float RestingStaminaRegenRate { get { float num = ReflectionFields.Get(ReflectionFields.StaminaRegen, player, 1f); return HardheimDivingPlugin.Instance.RestingStaminaRegenRate.Value * num; } } private void Awake() { player = ((Component)this).GetComponent(); if (!((Object)(object)player == (Object)null)) { SetSwimDepth(1.4f); BaseSwimSpeed = GetSwimSpeed(); if (!Divers.ContainsKey(player)) { Divers.Add(player, this); } } } private void OnDestroy() { if ((Object)(object)player != (Object)null && Divers.ContainsKey(player)) { Divers.Remove(player); } } public bool HasRequiredSwimmingSkill() { return HardheimDivingPlugin.HasRequiredSwimmingSkill(player); } public void ResetSwimDepthIfNotInWater() { if ((Object)(object)player == (Object)null || !((Character)player).InWater()) { ResetSwimDepthToDefault(); } } public void ResetSwimDepthToDefault() { SetSwimDepth(1.4f); } public bool CanDive() { if ((Object)(object)player == (Object)null) { return false; } if (!HasRequiredSwimmingSkill()) { return false; } return ((Character)player).InWater() && !((Character)player).IsOnGround() && ((Character)player).IsSwimming(); } public bool IsInsideLiquid() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return false; } return Mathf.Max(0f, ((Character)player).GetLiquidLevel() - ((Component)player).transform.position.y) > 1.4f; } public bool IsUnderSurface() { return GetSwimDepth() > 1.4f; } public bool IsDiving() { return GetSwimDepth() > 2.5f; } public bool IsSurfacing() { return !IsDiving() && IsUnderSurface(); } public bool IsRestingInWater() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) int result; if ((Object)(object)player != (Object)null && !IsDiving() && ((Character)player).IsSwimming()) { Vector3 velocity = ((Character)player).GetVelocity(); result = ((((Vector3)(ref velocity)).magnitude < 1f) ? 1 : 0); } else { result = 0; } return (byte)result != 0; } public void RegenRestingStamina(float dt) { if (!((Object)(object)player == (Object)null)) { float num = ReflectionFields.Get(ReflectionFields.StaminaRegenTimer, player, 0f); num -= dt; ReflectionFields.Set(ReflectionFields.StaminaRegenTimer, player, num); if (player.GetStamina() < ((Character)player).GetMaxStamina() && num <= RestingStaminaRegenDelay) { float skillFactor = ((Character)player).GetSkillFactor((SkillType)103); float num2 = (1f + skillFactor) * RestingStaminaRegenRate; float num3 = ReflectionFields.Get(ReflectionFields.Stamina, player, player.GetStamina()); num3 = Mathf.Min(((Character)player).GetMaxStamina(), num3 + num2 * dt * Game.m_staminaRegenRate); ReflectionFields.Set(ReflectionFields.Stamina, player, num3); } } } public void DrainDivingStamina(float dt) { } public void UpdateSwimSkill(float dt) { if (!((Object)(object)player == (Object)null)) { float num = ReflectionFields.Get(ReflectionFields.SwimSkillImproveTimer, player, 0f); num += dt; if (num > 1f) { num = 0f; ((Character)player).RaiseSkill((SkillType)103, 1f); } ReflectionFields.Set(ReflectionFields.SwimSkillImproveTimer, player, num); } } public void UpdateSwimSpeed(float dt) { if (!((Object)(object)player == (Object)null)) { float num = ((ZInput.GetButton("Run") || ZInput.GetButton("JoyRun")) ? dt : (0f - dt)); float num2 = ReflectionFields.Get(ReflectionFields.SwimAcceleration, player, 1f); float num3 = GetSwimSpeed() + num2 * num; num3 = Mathf.Clamp(num3, BaseSwimSpeed, HardheimDivingPlugin.Instance.MaxSwimSpeed.Value); SetSwimSpeed(num3); } } public void Dive(float dt, bool ascend, out Vector3? defaultMoveDir) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) defaultMoveDir = GetMoveDir(); Vector3 diveDirection = GetDiveDirection(ascend); SetMoveDir(diveDirection); Vector3 val = CalculateSwimVelocity(); float num = GetSwimDepth() - val.y * dt; SetSwimDepth(Mathf.Max(num, 1.4f)); } public Vector3 GetDiveDirection(bool ascend) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (ascend ? Vector3.up : Vector3.down); Vector3 val2 = GetMoveDir(); if (((Vector3)(ref val2)).magnitude < 0.1f) { float scale = ((ascend && IsSurfacing()) ? 0.6f : 0.05f); val2 = GetHorizontalLookDir(scale); } Vector3 result = val2 + val; ((Vector3)(ref result)).Normalize(); return result; } private Vector3 GetHorizontalLookDir(float scale) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //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_0030: Unknown result type (might be due to invalid IL or missing references) Vector3 forward = ((Component)player).transform.forward; forward.y = 0f; ((Vector3)(ref forward)).Normalize(); return forward * scale; } public Vector3 CalculateSwimVelocity() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) float num = GetSwimSpeed(); if (((Character)player).InMinorActionSlowdown()) { num = 0f; } Vector3 moveDir = GetMoveDir(); Vector3 val = moveDir * num; Vector3 val2 = ReflectionFields.Get(ReflectionFields.CurrentVel, player, ((Character)player).GetVelocity()); float num2 = ReflectionFields.Get(ReflectionFields.SwimAcceleration, player, 1f); Vector3 result = Vector3.Lerp(val2, val, num2); try { } catch { } return result; } public float GetSwimDepth() { return ReflectionFields.Get(ReflectionFields.SwimDepth, player, 1.4f); } private void SetSwimDepth(float value) { ReflectionFields.Set(ReflectionFields.SwimDepth, player, value); } private float GetSwimSpeed() { return ReflectionFields.Get(ReflectionFields.SwimSpeed, player, 2f); } private void SetSwimSpeed(float value) { ReflectionFields.Set(ReflectionFields.SwimSpeed, player, value); } public Vector3 GetMoveDir() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) return ReflectionFields.Get(ReflectionFields.MoveDir, player, Vector3.zero); } public void SetMoveDir(Vector3 value) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) ReflectionFields.Set(ReflectionFields.MoveDir, player, value); } } internal static class DivingUtils { public static bool TryGetDiver(Character character, out Diver diver) { if (!IsValidLocalPlayer(character, out var player)) { diver = null; return false; } return ((Component)player).TryGetComponent(ref diver); } public static bool TryGetDiver(Player player, out Diver diver) { if (!IsValidLocalPlayer(player)) { diver = null; return false; } return ((Component)player).TryGetComponent(ref diver); } public static bool IsValidLocalPlayer(Character character, out Player player) { if ((Object)(object)character != (Object)null && character.IsPlayer() && (Object)(object)character == (Object)(object)Player.m_localPlayer) { player = Player.m_localPlayer; return true; } player = null; return false; } public static bool IsValidLocalPlayer(Player player) { return (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer; } } [HarmonyPatch] internal static class DivingPatches { private static bool InUpdateSwimming; [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Awake")] private static void Player_Awake_Postfix(Player __instance) { Diver diver = default(Diver); if (!((Object)(object)__instance == (Object)null) && !((Component)__instance).TryGetComponent(ref diver)) { ((Component)__instance).gameObject.AddComponent(); } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "UpdateMotion")] private static void Character_UpdateMotion_Prefix(Character __instance) { if (!DivingUtils.TryGetDiver(__instance, out var diver) || (Object)(object)HardheimDivingPlugin.Instance == (Object)null || !HardheimDivingPlugin.Instance.IsEnvAllowed()) { return; } if (!diver.HasRequiredSwimmingSkill()) { diver.ResetSwimDepthToDefault(); return; } diver.ResetSwimDepthIfNotInWater(); if (diver.IsUnderSurface() && diver.IsInsideLiquid()) { ReflectionFields.Set(ReflectionFields.LastGroundTouch, diver.player, 0.3f); ReflectionFields.Set(ReflectionFields.SwimTimer, diver.player, 0f); } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "UpdateSwimming")] public static void UpdateSwimming_Prefix(Character __instance, float dt, out Vector3? __state) { InUpdateSwimming = true; __state = null; if (!DivingUtils.TryGetDiver(__instance, out var diver)) { return; } if (!diver.HasRequiredSwimmingSkill()) { diver.ResetSwimDepthToDefault(); return; } diver.UpdateSwimSpeed(dt); if ((ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump")) && diver.IsUnderSurface()) { diver.Dive(dt, ascend: true, out __state); } else if ((ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch")) && diver.CanDive()) { diver.Dive(dt, ascend: false, out __state); } else if ((__instance.IsOnGround() || !diver.IsDiving()) && !diver.IsRestingInWater()) { diver.ResetSwimDepthToDefault(); } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "UpdateSwimming")] public static void UpdateSwimming_Postfix(Character __instance, float dt, ref Vector3? __state) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) InUpdateSwimming = false; if (__state.HasValue) { ReflectionFields.Set(ReflectionFields.MoveDir, __instance, __state.Value); __state = null; } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "UpdateRotation")] public static void UpdateRotation_Prefix(Character __instance, out Quaternion? __state) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (InUpdateSwimming) { __state = ((Component)__instance).transform.rotation; } else { __state = null; } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "UpdateRotation")] public static void UpdateRotation_Postfix(Character __instance, float turnSpeed, float dt, ref Quaternion? __state) { //IL_002c: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if (InUpdateSwimming && __state.HasValue && !((Object)(object)__instance == (Object)null) && !(((Component)__instance).transform.rotation != __state.Value) && DivingUtils.TryGetDiver(__instance, out var diver) && diver.IsUnderSurface()) { Player player = diver.player; Vector3 moveDir = diver.GetMoveDir(); Quaternion val = ((moveDir == Vector3.zero) ? ((Component)player).transform.rotation : Quaternion.LookRotation(moveDir)); ((Component)player).transform.rotation = Quaternion.RotateTowards(((Component)player).transform.rotation, val, turnSpeed * dt); } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "OnSwimming")] public static void Player_OnSwimming_Prefix(Player __instance, Vector3 targetVel, float dt) { if (!(((Vector3)(ref targetVel)).magnitude >= 0.1f) && DivingUtils.TryGetDiver(__instance, out var diver) && diver.HasRequiredSwimmingSkill()) { if (diver.IsDiving()) { diver.DrainDivingStamina(dt); diver.UpdateSwimSkill(dt); } else if (diver.IsRestingInWater()) { diver.RegenRestingStamina(dt); } } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "Update")] private static void Player_Update_Postfix(Player __instance) { if (DivingUtils.TryGetDiver(__instance, out var diver)) { HardheimDivingPlugin.HandleOxygen(__instance, diver, Time.deltaTime); } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "UseStamina")] private static bool Player_UseStamina_Prefix(Player __instance) { if (!DivingUtils.TryGetDiver(__instance, out var diver)) { return true; } if (!diver.HasRequiredSwimmingSkill()) { return true; } if (((Character)__instance).InWater() && diver.IsUnderSurface()) { HardheimDivingPlugin.LogDebug("Stamina használat blokkolva víz alatt. Oxigén fogy helyette."); return false; } return true; } } [HarmonyPatch] internal static class WaterCameraPatches { private static float WaterLevelCamera; private static bool ShouldResetCamera; private static float? CachedMinWaterDistance; private const float UnderWaterCameraMinWaterDistance = -1000f; [HarmonyPrefix] [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] private static void GameCamera_UpdateCamera_Prefix(GameCamera __instance) { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0149: 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_014e: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !DivingUtils.TryGetDiver(Player.m_localPlayer, out var diver)) { ResetMinWaterDistance(__instance); return; } if (!diver.HasRequiredSwimmingSkill() || (Object)(object)HardheimDivingPlugin.Instance == (Object)null || !HardheimDivingPlugin.Instance.IsEnvAllowed()) { ResetMinWaterDistance(__instance); return; } bool flag = diver.IsUnderSurface() && ((Character)Player.m_localPlayer).IsSwimming(); if (flag && !diver.IsRestingInWater()) { SetMinWaterDistanceUnderWater(__instance); } else { ResetMinWaterDistance(__instance); } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return; } if (((Component)main).gameObject.transform.position.y < WaterLevelCamera && flag && HardheimDivingPlugin.Instance.IsEnvAllowed()) { SetMinWaterDistanceUnderWater(__instance); if ((Object)(object)EnvMan.instance != (Object)null) { EnvSetup currentEnvironment = EnvMan.instance.GetCurrentEnvironment(); if (currentEnvironment != null) { Color color = ((!EnvMan.IsNight()) ? currentEnvironment.m_fogColorDay : currentEnvironment.m_fogColorNight); color.a = 1f; color = ChangeColorBrightness(color, diver.GetSwimDepth() * (0f - HardheimDivingPlugin.Instance.ColorDarknessFactor.Value)); RenderSettings.fogColor = color; RenderSettings.fogDensity = Mathf.Clamp(RenderSettings.fogDensity + diver.GetSwimDepth() * HardheimDivingPlugin.Instance.FogDensityFactor.Value, HardheimDivingPlugin.Instance.MinFogDensity.Value, HardheimDivingPlugin.Instance.MaxFogDensity.Value); ShouldResetCamera = true; } } } else if (ShouldResetCamera && ((Component)main).gameObject.transform.position.y > WaterLevelCamera && (Object)(object)EnvMan.instance != (Object)null) { EnvSetup currentEnvironment2 = EnvMan.instance.GetCurrentEnvironment(); if (currentEnvironment2 != null) { EnvMan.instance.SetForceEnvironment(currentEnvironment2.m_name); EnvMan.instance.SetForceEnvironment(string.Empty); } ShouldResetCamera = false; } } [HarmonyPrefix] [HarmonyPatch(typeof(WaterVolume), "UpdateMaterials")] private static void WaterVolume_UpdateMaterials_Prefix(WaterVolume __instance) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && Object.op_Implicit((Object)(object)GameCamera.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && DivingUtils.TryGetDiver(Player.m_localPlayer, out var diver) && diver.HasRequiredSwimmingSkill()) { WaterLevelCamera = __instance.GetWaterSurface(((Component)GameCamera.instance).transform.position, 1f); } } private static void SetMinWaterDistanceUnderWater(GameCamera camera) { if (!((Object)(object)camera == (Object)null) && !(ReflectionFields.GameCameraMinWaterDistance == null)) { if (!CachedMinWaterDistance.HasValue) { CachedMinWaterDistance = ReflectionFields.Get(ReflectionFields.GameCameraMinWaterDistance, camera, 0.4f); } ReflectionFields.Set(ReflectionFields.GameCameraMinWaterDistance, camera, -1000f); } } private static void ResetMinWaterDistance(GameCamera camera) { if (!((Object)(object)camera == (Object)null) && !(ReflectionFields.GameCameraMinWaterDistance == null) && CachedMinWaterDistance.HasValue) { ReflectionFields.Set(ReflectionFields.GameCameraMinWaterDistance, camera, CachedMinWaterDistance.Value); } } private static Color ChangeColorBrightness(Color color, float correctionFactor) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) float r = color.r; float g = color.g; float b = color.b; if (correctionFactor >= 0f) { return new Color(r, g, b, color.a); } correctionFactor *= -1f; r -= r * correctionFactor; g -= g * correctionFactor; b -= b * correctionFactor; if (r < 0f) { r = 0f; } if (g < 0f) { g = 0f; } if (b < 0f) { b = 0f; } return new Color(r, g, b, color.a); } } [HarmonyPatch] internal static class UseEquipPatches { private static readonly CodeMatch[] CodeMatches = (CodeMatch[])(object)new CodeMatch[5] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Character), "IsSwimming", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Brfalse, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Character), "IsOnGround", (Type[])null, (Type[])null), (string)null) }; private static readonly int InstructionMatchCount = CodeMatches.Length + 1; private static bool ShouldHideItem() { return (Object)(object)HardheimDivingPlugin.Instance != (Object)null && !HardheimDivingPlugin.Instance.UseEquipInWater.Value; } [HarmonyTranspiler] [HarmonyPatch(typeof(Humanoid), "UpdateEquipment")] private static IEnumerable UpdateEquipment_Transpiler(IEnumerable instructions) { return PatchSwimmingEquipmentCheck(instructions, "Humanoid.UpdateEquipment"); } [HarmonyTranspiler] [HarmonyPatch(typeof(Humanoid), "EquipItem")] private static IEnumerable EquipItem_Transpiler(IEnumerable instructions) { return PatchSwimmingEquipmentCheck(instructions, "Humanoid.EquipItem"); } [HarmonyTranspiler] [HarmonyPatch(typeof(Player), "Update")] private static IEnumerable UpdatePlayer_Transpiler(IEnumerable instructions) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward(CodeMatches); if (!val.IsValid) { HardheimDivingPlugin.LogWarning("Failed to patch Player.Update equipment swimming check."); return instructions; } val.Advance(1); val.RemoveInstructions(InstructionMatchCount); return val.InstructionEnumeration(); } private static IEnumerable PatchSwimmingEquipmentCheck(IEnumerable instructions, string methodName) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward(CodeMatches); if (!val.IsValid) { HardheimDivingPlugin.LogWarning("Failed to patch " + methodName + " equipment swimming check."); return instructions; } val.Advance(InstructionMatchCount); val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { Transpilers.EmitDelegate>((Func)ShouldHideItem), new CodeInstruction(OpCodes.Brfalse, val.InstructionAt(-1).operand) }); return val.InstructionEnumeration(); } }