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 GetOutOfTheWater v0.1.0
GetOutOfTheWater.dll
Decompiled 2 hours agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("GetOutOfTheWater")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Press Jump while swimming to pull yourself onto nearby ledges, docks, ruins, and boats.")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+f8323569655b908c100cdcd250370728bbc335b1")] [assembly: AssemblyProduct("GetOutOfTheWater")] [assembly: AssemblyTitle("GetOutOfTheWater")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace GetOutOfTheWater { internal static class CharacterAccess { private static readonly FieldRef<Character, float> SwimTimer = AccessTools.FieldRefAccess<Character, float>("m_swimTimer"); private static readonly FieldRef<Character, float> LastGroundTouch = AccessTools.FieldRefAccess<Character, float>("m_lastGroundTouch"); private static readonly FieldRef<Character, float> MaxAirAltitude = AccessTools.FieldRefAccess<Character, float>("m_maxAirAltitude"); private static readonly FieldRef<Character, Vector3> CurrentVel = AccessTools.FieldRefAccess<Character, Vector3>("m_currentVel"); private static readonly FieldRef<Character, Vector3> LookDir = AccessTools.FieldRefAccess<Character, Vector3>("m_lookDir"); private static readonly FieldRef<int> GroundRayMask = AccessTools.StaticFieldRefAccess<int>(AccessTools.Field(typeof(Character), "s_groundRayMask")); internal static float GetSwimTimer(Character character) { return SwimTimer.Invoke(character); } internal static void SetSwimTimer(Character character, float value) { SwimTimer.Invoke(character) = value; } internal static void SetLastGroundTouch(Character character, float value) { LastGroundTouch.Invoke(character) = value; } internal static void SetMaxAirAltitude(Character character, float value) { MaxAirAltitude.Invoke(character) = value; } internal static void SetCurrentVel(Character character, Vector3 value) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) CurrentVel.Invoke(character) = value; } internal static Vector3 GetLookDir(Character character) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return LookDir.Invoke(character); } internal static int GetGroundRayMask() { int num = GroundRayMask.Invoke(); if (num != 0) { return num; } return LayerMask.GetMask(new string[7] { "Default", "static_solid", "Default_small", "piece", "terrain", "blocker", "vehicle" }); } } [BepInPlugin("hardwire99.getoutofthewater", "Get Out Of The Water", "0.1.0")] public sealed class GetOutOfTheWaterPlugin : BaseUnityPlugin { internal static ManualLogSource Log; private Harmony harmony; private void Awake() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); if (!ModConfig.Enabled.Value) { Log.LogInfo((object)"Get Out Of The Water 0.1.0 is disabled in config."); return; } harmony = new Harmony("hardwire99.getoutofthewater"); harmony.PatchAll(typeof(GetOutOfTheWaterPlugin).Assembly); Log.LogInfo((object)("Get Out Of The Water 0.1.0 loaded (lip-line, dll " + GetDllTimestamp() + ").")); } private void Update() { if (!ModConfig.Enabled.Value) { SwimExitLipLine.Hide(); } else { SwimExitLipLine.Tick(); } } private void OnDestroy() { SwimExitLipLine.Destroy(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private static string GetDllTimestamp() { string location = Assembly.GetExecutingAssembly().Location; if (!File.Exists(location)) { return "unknown"; } return File.GetLastWriteTime(location).ToString("yyyy-MM-dd HH:mm:ss"); } } internal static class ModConfig { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> DebugLogging; internal static ConfigEntry<float> BaseClimbHeight; internal static ConfigEntry<float> JumpClimbBonus; internal static ConfigEntry<float> ReachDistance; internal static ConfigEntry<float> MantleDuration; internal static ConfigEntry<float> StaminaCost; internal static ConfigEntry<bool> AllowBoats; internal static ConfigEntry<bool> ShowLipLine; internal static ConfigEntry<float> SurfaceMaxSubmersion; internal static ConfigEntry<float> CooldownSeconds; internal static void Bind(ConfigFile config) { Enabled = config.Bind<bool>("General", "Enabled", true, "Enable swim-exit on Jump. When false, no Harmony patches run."); DebugLogging = config.Bind<bool>("General", "DebugLogging", false, "Log ledge probes and mantle starts to BepInEx."); BaseClimbHeight = config.Bind<float>("Mantle", "BaseClimbHeight", 1f, "Pull-up height in meters above the waterline at Jump skill 0. Measured against water level at the instant you press Jump."); JumpClimbBonus = config.Bind<float>("Mantle", "JumpClimbBonus", 1f, "Extra meters of pull-up height at Jump skill 100. Scales linearly with Jump."); ReachDistance = config.Bind<float>("Mantle", "ReachDistance", 1.5f, "How far ahead to search for a wall or ledge while swimming."); MantleDuration = config.Bind<float>("Mantle", "MantleDuration", 0.2f, "Seconds to lerp onto the ledge. Keep short so swim physics cannot pull you back."); StaminaCost = config.Bind<float>("Mantle", "StaminaCost", -1f, "Stamina spent on a successful pull-up. Negative uses the vanilla jump stamina cost."); AllowBoats = config.Bind<bool>("Mantle", "AllowBoats", true, "Allow pulling onto ships and other vehicle colliders from the water."); ShowLipLine = config.Bind<bool>("Mantle", "ShowLipLine", true, "Draw a red/green line on a nearby ledge lip while swimming. Green means Jump would pull you up at the current waterline."); SurfaceMaxSubmersion = config.Bind<float>("Mantle", "SurfaceMaxSubmersion", 2.8f, "If water is deeper than this above your feet, Jump is left alone so diving mods can ascend. Also allows at least swimDepth + 0.75m."); CooldownSeconds = config.Bind<float>("Mantle", "CooldownSeconds", 0.4f, "Minimum seconds between swim-exit attempts."); } internal static void Log(string message) { if (DebugLogging.Value) { GetOutOfTheWaterPlugin.Log.LogInfo((object)message); } } } internal static class ModConstants { public const string ModGuid = "hardwire99.getoutofthewater"; public const string ModName = "Get Out Of The Water"; public const string ModVersion = "0.1.0"; public const string BuildLabel = "lip-line"; } internal static class SwimExitClimb { internal static float GetMaxHeight(Character character) { float num = 0f; if ((Object)(object)character != (Object)null) { num = Mathf.Clamp01(character.GetSkillFactor((SkillType)100)); } return ModConfig.BaseClimbHeight.Value + ModConfig.JumpClimbBonus.Value * num; } internal static void AwardJumpSkill(Character character) { character.RaiseSkill((SkillType)100, 1f); if (character is Player && (Object)(object)Game.instance != (Object)null) { Game.instance.IncrementPlayerStat((PlayerStatType)3, 1f); } } } internal static class SwimExitLipLine { private const float HalfWidth = 0.85f; private const float LineWidth = 0.07f; private const int SampleCount = 7; private static readonly Color Reachable = new Color(0.2f, 0.95f, 0.35f, 1f); private static readonly Color TooHigh = new Color(0.95f, 0.22f, 0.18f, 1f); private static readonly Vector3[] SamplePoints = (Vector3[])(object)new Vector3[7]; private static LineRenderer line; private static Material material; internal static void Tick() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.ShowLipLine.Value) { Hide(); return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || SwimExitMantle.IsActive((Character)(object)localPlayer) || !SwimExitMantle.IsEligible((Character)(object)localPlayer)) { Hide(); return; } if (!SwimExitProbe.TryFindLip((Character)(object)localPlayer, out var ledge)) { Hide(); return; } int num = BuildSamples((Character)(object)localPlayer, ledge); if (num < 2) { Hide(); return; } EnsureLine(); if (!((Object)(object)line == (Object)null)) { Color val = (ledge.InReach ? Reachable : TooHigh); line.startColor = val; line.endColor = val; if ((Object)(object)material != (Object)null) { material.color = val; } line.positionCount = num; for (int i = 0; i < num; i++) { line.SetPosition(i, SamplePoints[i]); } ((Renderer)line).enabled = true; } } internal static void Hide() { if ((Object)(object)line != (Object)null) { ((Renderer)line).enabled = false; } } internal static void Destroy() { if ((Object)(object)line != (Object)null) { Object.Destroy((Object)(object)((Component)line).gameObject); line = null; } if ((Object)(object)material != (Object)null) { Object.Destroy((Object)(object)material); material = null; } } private static int BuildSamples(Character character, SwimExitLedge ledge) { //IL_0000: 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_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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0068: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00da: 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_00e4: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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_0127: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.Cross(Vector3.up, ledge.Forward); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = ((Component)character).transform.right; } val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { return 0; } ((Vector3)(ref val)).Normalize(); int groundRayMask = CharacterAccess.GetGroundRayMask(); int result = 0; Vector3 val2 = Vector3.up * 0.04f - ledge.Forward * 0.04f; RaycastHit val5 = default(RaycastHit); for (int i = 0; i < 7; i++) { float num = (float)i / 6f * 2f - 1f; Vector3 val3 = ledge.StandPoint + val * (num * 0.85f) + Vector3.up * 0.45f; Vector3 val4 = ledge.StandPoint + val * (num * 0.85f); if (Physics.Raycast(val3, Vector3.down, ref val5, 0.9f, groundRayMask, (QueryTriggerInteraction)1) && Mathf.Abs(((RaycastHit)(ref val5)).point.y - ledge.StandPoint.y) < 0.35f) { val4 = ((RaycastHit)(ref val5)).point; } SamplePoints[result++] = val4 + val2; } return result; } private static void EnsureLine() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0068: 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_007f: Expected O, but got Unknown if (!((Object)(object)line != (Object)null)) { Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Hidden/Internal-Colored") ?? Shader.Find("Unlit/Color"); if ((Object)(object)val == (Object)null) { ModConfig.Log("Lip line shader not found."); return; } GameObject val2 = new GameObject("GetOutOfTheWater_LipLine"); Object.DontDestroyOnLoad((Object)val2); ((Object)val2).hideFlags = (HideFlags)61; material = new Material(val) { color = Reachable, hideFlags = (HideFlags)61 }; material.SetInt("_ZWrite", 0); material.renderQueue = 4000; line = val2.AddComponent<LineRenderer>(); ((Renderer)line).sharedMaterial = material; line.useWorldSpace = true; line.loop = false; line.positionCount = 0; line.widthMultiplier = 0.07f; line.numCapVertices = 2; line.numCornerVertices = 2; ((Renderer)line).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)line).receiveShadows = false; ((Renderer)line).allowOcclusionWhenDynamic = false; line.alignment = (LineAlignment)0; line.textureMode = (LineTextureMode)0; ((Renderer)line).enabled = false; } } } internal static class SwimExitMantle { private static Character active; private static Vector3 start; private static Vector3 end; private static Vector3 forward; private static float elapsed; private static float duration; private static float cooldownUntil; internal static bool IsCoolingDown => Time.time < cooldownUntil; internal static bool IsActive(Character character) { return (Object)(object)active == (Object)(object)character; } internal static bool IsEligible(Character character) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || (Object)(object)character != (Object)(object)Player.m_localPlayer) { return false; } if (!character.IsSwimming() || character.IsDead() || character.InDodge() || character.IsKnockedBack() || character.IsEncumbered()) { return false; } if (character.IsAttached() || character.IsAttachedToShip() || character.InBed()) { return false; } float num = character.GetLiquidLevel() - ((Component)character).transform.position.y; float num2 = Mathf.Max(ModConfig.SurfaceMaxSubmersion.Value, character.m_swimDepth + 0.75f); if (num > num2) { return false; } return true; } internal static bool TryBegin(Character character) { //IL_00a7: 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) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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) //IL_011c: 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) if (!IsEligible(character)) { return false; } if (IsActive(character) || IsCoolingDown) { return false; } if (!SwimExitProbe.TryFind(character, out var ledge) || !ledge.InReach) { return false; } float num = ModConfig.StaminaCost.Value; if (num < 0f) { num = character.m_jumpStaminaUsage; } if (num > 0f && !character.HaveStamina(num)) { if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.StaminaBarEmptyFlash(); } return false; } if (num > 0f) { character.UseStamina(num); } SwimExitClimb.AwardJumpSkill(character); Rigidbody component = ((Component)character).GetComponent<Rigidbody>(); start = (((Object)(object)component != (Object)null) ? component.position : ((Component)character).transform.position); end = ledge.StandPoint; forward = ledge.Forward; elapsed = 0f; duration = Mathf.Max(0.05f, ModConfig.MantleDuration.Value); active = character; cooldownUntil = Time.time + ModConfig.CooldownSeconds.Value; CharacterAccess.SetMaxAirAltitude(character, end.y); ModConfig.Log($"Mantle start {start} -> {end}"); return true; } internal static void Tick(Character character, float dt) { //IL_004b: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0075: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_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) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (IsActive(character)) { elapsed += dt; float num = ((duration <= 0f) ? 1f : Mathf.Clamp01(elapsed / duration)); num = num * num * (3f - 2f * num); Vector3 pos = Vector3.Lerp(start, end, num); ApplyPosition(character, pos, Vector3.zero); if (!(elapsed < duration)) { Vector3 val = forward * 1.6f + Vector3.up * 0.4f; ApplyPosition(character, end, val); CharacterAccess.SetSwimTimer(character, 1f); CharacterAccess.SetLastGroundTouch(character, 0f); CharacterAccess.SetMaxAirAltitude(character, end.y); CharacterAccess.SetCurrentVel(character, val); ModConfig.Log("Mantle complete."); active = null; } } } internal static void Cancel(Character character) { if (IsActive(character)) { active = null; } } private static void ApplyPosition(Character character, Vector3 pos, Vector3 velocity) { //IL_002a: 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_001e: Unknown result type (might be due to invalid IL or missing references) Rigidbody component = ((Component)character).GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.WakeUp(); component.position = pos; component.linearVelocity = velocity; } ((Component)character).transform.position = pos; } } internal readonly struct SwimExitLedge { internal Vector3 StandPoint { get; } internal Vector3 Forward { get; } internal bool InReach { get; } internal SwimExitLedge(Vector3 standPoint, Vector3 forward, bool inReach) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_0009: Unknown result type (might be due to invalid IL or missing references) StandPoint = standPoint; Forward = forward; InReach = inReach; } } internal static class SwimExitProbe { private const float MinStandNormalY = 0.45f; private const float CapsuleSkin = 0.08f; private const float CastBack = 0.55f; private static readonly float[] DownInsets = new float[4] { 0.18f, 0.35f, 0.55f, 0.8f }; private static readonly Collider[] OverlapBuffer = (Collider[])(object)new Collider[24]; private const float MarkerSearchHeight = 4f; internal static bool TryFind(Character character, out SwimExitLedge ledge) { return TryFindInternal(character, requireInReach: true, horizontalOnly: false, out ledge); } internal static bool TryFindLip(Character character, out SwimExitLedge ledge) { return TryFindInternal(character, requireInReach: false, horizontalOnly: true, out ledge); } private static bool TryFindInternal(Character character, bool requireInReach, bool horizontalOnly, out SwimExitLedge ledge) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0050: 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_0092: Unknown result type (might be due to invalid IL or missing references) ledge = default(SwimExitLedge); Vector3 val = Flatten(character.GetMoveDir()); Vector3 val2 = Flatten(character.GetLookDir()); Vector3 val3 = Flatten(((Component)character).transform.forward); if (!horizontalOnly && TryFindAlongLook(character, requireInReach, out ledge)) { return true; } if (((Vector3)(ref val)).sqrMagnitude > 0.05f && TryFindInDirection(character, ((Vector3)(ref val)).normalized, requireInReach, out ledge)) { return true; } if (((Vector3)(ref val2)).sqrMagnitude > 0.05f && TryFindInDirection(character, ((Vector3)(ref val2)).normalized, requireInReach, out ledge)) { return true; } if (((Vector3)(ref val3)).sqrMagnitude > 0.05f && TryFindInDirection(character, ((Vector3)(ref val3)).normalized, requireInReach, out ledge)) { return true; } if (requireInReach) { ModConfig.Log("Probe found no standable ledge."); } return false; } private static bool TryFindAlongLook(Character character, bool requireInReach, out SwimExitLedge ledge) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_006d: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) ledge = default(SwimExitLedge); Vector3 lookDir = character.GetLookDir(); if (((Vector3)(ref lookDir)).sqrMagnitude < 0.01f) { return false; } ((Vector3)(ref lookDir)).Normalize(); int num = BuildMask(); float num2 = ModConfig.ReachDistance.Value + 0.75f; Vector3[] array = (Vector3[])(object)new Vector3[2] { character.GetEyePoint() - lookDir * 0.15f, character.GetCenterPoint() - lookDir * 0.15f }; RaycastHit val = default(RaycastHit); for (int i = 0; i < array.Length; i++) { if (Physics.Raycast(array[i], lookDir, ref val, num2, num, (QueryTriggerInteraction)1)) { RaycastHit hit = val; Vector3 val2 = Flatten(lookDir); Vector3 fallbackDir; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.01f)) { fallbackDir = ((Component)character).transform.forward; } else { val2 = Flatten(lookDir); fallbackDir = ((Vector3)(ref val2)).normalized; } if (TryResolveHit(character, hit, fallbackDir, requireInReach, out ledge)) { return true; } } } return false; } private static bool TryFindInDirection(Character character, Vector3 dir, bool requireInReach, out SwimExitLedge ledge) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(0.35f, character.GetLiquidLevel() - ((Component)character).transform.position.y); float[] array = new float[5] { 0.45f, 0.9f, Mathf.Max(0.3f, num - 0.25f), num, num + 0.25f }; for (int i = 0; i < array.Length; i++) { if (TryCastAtHeight(character, dir, array[i], requireInReach, out ledge)) { return true; } } ledge = default(SwimExitLedge); return false; } private static bool TryCastAtHeight(Character character, Vector3 dir, float originHeight, bool requireInReach, out SwimExitLedge ledge) { //IL_0025: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_004b: 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) //IL_0068: 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) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) ledge = default(SwimExitLedge); int num = BuildMask(); float num2 = ModConfig.ReachDistance.Value + 0.55f; Vector3 val = ((Component)character).transform.position + Vector3.up * originHeight - dir * 0.55f; RaycastHit hit = default(RaycastHit); if (Physics.Raycast(val, dir, ref hit, num2, num, (QueryTriggerInteraction)1) && TryResolveHit(character, hit, dir, requireInReach, out ledge)) { return true; } RaycastHit hit2 = default(RaycastHit); if (Physics.SphereCast(val, 0.12f, dir, ref hit2, num2, num, (QueryTriggerInteraction)1) && TryResolveHit(character, hit2, dir, requireInReach, out ledge)) { return true; } return false; } private static bool TryResolveHit(Character character, RaycastHit hit, Vector3 fallbackDir, bool requireInReach, out SwimExitLedge ledge) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_012d: 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) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) ledge = default(SwimExitLedge); if (ShouldIgnore(character, ((RaycastHit)(ref hit)).collider)) { return false; } Vector3 val = Flatten(-((RaycastHit)(ref hit)).normal); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Flatten(fallbackDir); } if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Flatten(((Component)character).transform.forward); } if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { return false; } ((Vector3)(ref val)).Normalize(); if (((RaycastHit)(ref hit)).normal.y >= 0.45f && TryAcceptStand(character, ((RaycastHit)(ref hit)).point, ((RaycastHit)(ref hit)).normal, ((RaycastHit)(ref hit)).collider, ((RaycastHit)(ref hit)).collider, val, requireInReach, out ledge)) { return true; } int num = BuildMask(); float num2 = (requireInReach ? SwimExitClimb.GetMaxHeight(character) : 4f); float liquidLevel = character.GetLiquidLevel(); float num3 = Mathf.Max(((RaycastHit)(ref hit)).point.y, liquidLevel) + 0.05f; RaycastHit val2 = default(RaycastHit); for (int i = 0; i < DownInsets.Length; i++) { if (Physics.Raycast(new Vector3(((RaycastHit)(ref hit)).point.x, num3 + num2 + 0.2f, ((RaycastHit)(ref hit)).point.z) + val * DownInsets[i], Vector3.down, ref val2, num2 + 1.2f, num, (QueryTriggerInteraction)1) && !ShouldIgnore(character, ((RaycastHit)(ref val2)).collider) && TryAcceptStand(character, ((RaycastHit)(ref val2)).point, ((RaycastHit)(ref val2)).normal, ((RaycastHit)(ref val2)).collider, ((RaycastHit)(ref hit)).collider, val, requireInReach, out ledge)) { return true; } } ModConfig.Log("Probe hit " + ((Object)((RaycastHit)(ref hit)).collider).name + " but found no standable top."); return false; } private static bool TryAcceptStand(Character character, Vector3 point, Vector3 normal, Collider standCollider, Collider wallCollider, Vector3 forward, bool requireInReach, out SwimExitLedge ledge) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_007e: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) ledge = default(SwimExitLedge); if (normal.y < 0.45f) { return false; } if (ShouldIgnore(character, standCollider)) { return false; } float maxHeight = SwimExitClimb.GetMaxHeight(character); float liquidLevel = character.GetLiquidLevel(); float y = ((Component)character).transform.position.y; float num = point.y - liquidLevel; bool flag = num <= maxHeight; if (requireInReach && !flag) { ModConfig.Log($"Rejected {((Object)standCollider).name}: {num:F2}m above water (max {maxHeight:F2} at current waterline)."); return false; } if (point.y < y + 0.05f) { return false; } float num2 = Mathf.Max(0f, character.m_swimDepth - 0.4f); if (liquidLevel - point.y > num2) { ModConfig.Log("Rejected " + ((Object)standCollider).name + ": stand point still below swim depth."); return false; } Vector3 val = Flatten(forward); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Flatten(((Component)character).transform.forward); } if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.forward; } ((Vector3)(ref val)).Normalize(); Vector3 val2 = point + Vector3.up * 0.05f + val * 0.08f; if (!HasCapsuleClearance(character, val2, standCollider, wallCollider)) { if (requireInReach) { ModConfig.Log("Rejected " + ((Object)standCollider).name + ": capsule does not fit."); return false; } flag = false; } ledge = new SwimExitLedge(val2, val, flag); if (requireInReach) { ModConfig.Log($"Accepted ledge on {((Object)standCollider).name} at {val2} (above water {num:F2}m, jump max {maxHeight:F2}, inReach={flag})."); } return true; } private static bool HasCapsuleClearance(Character character, Vector3 standPoint, Collider standCollider, Collider wallCollider) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_0062: 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_006d: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) CapsuleCollider component = ((Component)character).GetComponent<CapsuleCollider>(); float num = (((Object)(object)component != (Object)null) ? (component.radius * 0.8f) : 0.25f); Vector3 val = standPoint + Vector3.up * (num + 0.08f); Vector3 val2 = standPoint + Vector3.up * (1.05f - num); if (val2.y <= val.y) { val2 = val + Vector3.up * 0.2f; } int num2 = Physics.OverlapCapsuleNonAlloc(val, val2, num, OverlapBuffer, BuildMask(), (QueryTriggerInteraction)1); for (int i = 0; i < num2; i++) { Collider val3 = OverlapBuffer[i]; if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3 == (Object)(object)standCollider) && !((Object)(object)val3 == (Object)(object)wallCollider) && !ShouldIgnore(character, val3) && !(val3.ClosestPoint(val).y < standPoint.y + 0.3f)) { return false; } } return true; } private static bool ShouldIgnore(Character character, Collider collider) { if ((Object)(object)collider == (Object)null) { return true; } if ((Object)(object)((Component)collider).transform == (Object)(object)((Component)character).transform || ((Component)collider).transform.IsChildOf(((Component)character).transform)) { return true; } if ((Object)(object)((Component)collider).GetComponentInParent<Character>() == (Object)(object)character) { return true; } if ((Object)(object)((Component)collider).GetComponentInParent<WaterVolume>() != (Object)null || (Object)(object)((Component)collider).GetComponentInParent<LiquidSurface>() != (Object)null) { return true; } if (!ModConfig.AllowBoats.Value && (Object)(object)((Component)collider).GetComponentInParent<Ship>() != (Object)null) { return true; } return false; } private static int BuildMask() { int groundRayMask = CharacterAccess.GetGroundRayMask(); groundRayMask |= LayerMask.GetMask(new string[8] { "Default", "static_solid", "Default_small", "piece", "terrain", "blocker", "vehicle", "viewblock" }); if (!ModConfig.AllowBoats.Value) { int num = LayerMask.NameToLayer("vehicle"); if (num >= 0) { groundRayMask &= ~(1 << num); } } return groundRayMask; } private static Vector3 Flatten(Vector3 value) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) value.y = 0f; return value; } } } namespace GetOutOfTheWater.Patches { [HarmonyPatch(typeof(Character), "Jump")] internal static class CharacterJumpPatch { [HarmonyPrefix] private static bool Prefix(Character __instance) { if (!ModConfig.Enabled.Value) { return true; } if (SwimExitMantle.TryBegin(__instance)) { return false; } return true; } } [HarmonyPatch(typeof(Character), "UpdateMotion")] internal static class CharacterUpdateMotionPatch { [HarmonyPrefix] private static bool Prefix(Character __instance, float dt) { if (!ModConfig.Enabled.Value || !SwimExitMantle.IsActive(__instance)) { return true; } if (__instance.IsDead()) { SwimExitMantle.Cancel(__instance); return true; } SwimExitMantle.Tick(__instance, dt); return false; } } }