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 Physics v1.0.6
Physics.dll
Decompiled 4 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [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 ValheimPhysics { [BepInPlugin("com.razaotium.physics", "Physics", "1.0.6")] [BepInProcess("valheim.exe")] public sealed class PhysicsPlugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry<bool> EnabledMod; internal static ConfigEntry<bool> PlayersOnly; internal static ConfigEntry<bool> ShipCameraFix; internal static ConfigEntry<bool> DeckGrip; internal static ConfigEntry<bool> DeckJump; internal static ConfigEntry<bool> SmoothStairClimb; internal static ConfigEntry<bool> StairFeet; internal static ConfigEntry<bool> FootMagnet; internal static ConfigEntry<bool> MountFooting; internal static ConfigEntry<float> Strength; internal static ConfigEntry<float> DeckGripLimit; internal static ConfigEntry<float> MaxAirSeconds; internal static ConfigEntry<float> FadeSeconds; internal static ConfigEntry<float> MountSlideAngle; internal static ConfigEntry<float> RampClearance; internal static bool BoatReady; internal static bool StairReady; internal static bool CameraReady; internal static bool MountReady; private Harmony harmony; private ConfigEntry<bool> Bind(string section, string name, bool value, string description) { return ((BaseUnityPlugin)this).Config.Bind<bool>(section, name, value, description); } private ConfigEntry<float> Bind(string section, string name, float value, float min, float max, string description) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<float>(section, name, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>())); } private void Awake() { //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; EnabledMod = Bind("General", "Enabled", value: true, "Enable corrections. No hotkeys or wall climbing."); PlayersOnly = Bind("General", "PlayersOnly", value: false, "Limit ship inertia correction to players."); ShipCameraFix = Bind("General", "ShipCameraFix", value: true, "Follow the player's actual position while jumping above a ship, instead of vanilla's lagging camera."); Strength = Bind("Tuning", "Strength", 1f, 0f, 1f, "Fraction of ship-frame velocity changes carried into airborne movement."); DeckGrip = Bind("Tuning", "DeckGrip", value: true, "Cap the idle deck spring of the ship owner. Passengers keep vanilla repositioning."); DeckGripLimit = Bind("Tuning", "DeckGripLimit", 2f, 0.5f, 40f, "Maximum idle deck spring speed for the ship owner, in m/s. Vanilla pulls at 10 m/s per meter of offset."); DeckJump = Bind("Tuning", "DeckJump", value: true, "Jump relative to the deck, so ship speed, deck tilt and waves do not change jump height."); MaxAirSeconds = Bind("Tuning", "MaxAirSeconds", 3f, 0.5f, 3f, "Airborne carry duration before fading, in seconds."); FadeSeconds = Bind("Tuning", "FadeSeconds", 1f, 0f, 1f, "Airborne carry fade after MaxAirSeconds, in seconds."); SmoothStairClimb = Bind("Stairs", "SmoothStairClimb", value: true, "Cover supported vanilla ladders with an invisible walking ramp laid just over their tread noses, and hold the player still on it when idle."); StairFeet = Bind("Stairs", "StairFeet", value: true, "On the ramps, move the character model to the tread under its standing foot and place each foot on the real tread beneath it. Visual only."); FootMagnet = Bind("Stairs", "FootMagnet", value: false, "With StairFeet: hold each planted foot on the tread spot under it until the animation lifts it. Visual only."); RampClearance = Bind("Stairs", "RampClearance", 0.01f, -0.05f, 0.1f, "Gap between the invisible ramp and the tread noses, in meters. Lower brings the feet closer to the treads; below 0 the noses poke through the ramp and every tread becomes a small bump."); MountFooting = Bind("Mounts", "MountFooting", value: true, "Use configured slide threshold for ridden creatures."); MountSlideAngle = Bind("Mounts", "MountSlideAngle", 85f, 38f, 90f, "Ridden slide threshold. Gameplay setting, not a guarantee of collision or dismount safety on steep terrain. Vanilla is 45."); harmony = new Harmony("com.razaotium.physics"); try { Access.Init(); BoatReady = true; harmony.PatchAll(typeof(BoatPatch)); harmony.PatchAll(typeof(BoatAirPatch)); harmony.PatchAll(typeof(BoatJumpPatch)); } catch (Exception ex) { Fail(ref BoatReady, "boat initialization", ex); } try { StairReady = true; harmony.PatchAll(typeof(StairTriggerPatch)); harmony.PatchAll(typeof(StairPiecePatch)); harmony.PatchAll(typeof(StairSlidePatch)); harmony.PatchAll(typeof(StairHoldPatch)); StairStride.Init(); harmony.PatchAll(typeof(StairStrideIKPatch)); harmony.PatchAll(typeof(StairStrideCameraPatch)); harmony.PatchAll(typeof(StairStrideCollisionPatch)); } catch (Exception ex2) { Fail(ref StairReady, "stairs initialization", ex2); } try { if (!BoatReady) { throw new InvalidOperationException("Character access unavailable"); } CameraPatch.Init(); CameraReady = true; harmony.PatchAll(typeof(CameraPatch)); } catch (Exception ex3) { Fail(ref CameraReady, "camera initialization", ex3); } try { MountReady = true; harmony.PatchAll(typeof(MountPatch)); } catch (Exception ex4) { Fail(ref MountReady, "mount initialization", ex4); } EnabledMod.SettingChanged += Reset; PlayersOnly.SettingChanged += Reset; SmoothStairClimb.SettingChanged += Reset; RampClearance.SettingChanged += Reset; StairFeet.SettingChanged += Reset; FootMagnet.SettingChanged += Reset; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Physics 1.0.6: boat=" + BoatReady + ", stairs=" + StairReady + ", camera=" + CameraReady + ", mount=" + MountReady)); } private void Update() { if (StairReady) { LadderRamp.Tick(); } } private void FixedUpdate() { if (!StairReady) { return; } try { StairStride.Step(Time.fixedDeltaTime); } catch (Exception ex) { StairStride.Clear(); Fail(ref StairReady, "stair feet", ex); } } private void Reset(object sender, EventArgs args) { BoatPatch.Clear(); LadderRamp.DestroyAll(); StairStride.Clear(); } private void OnDestroy() { if (EnabledMod != null) { EnabledMod.SettingChanged -= Reset; } if (PlayersOnly != null) { PlayersOnly.SettingChanged -= Reset; } if (SmoothStairClimb != null) { SmoothStairClimb.SettingChanged -= Reset; } if (RampClearance != null) { RampClearance.SettingChanged -= Reset; } if (StairFeet != null) { StairFeet.SettingChanged -= Reset; } if (FootMagnet != null) { FootMagnet.SettingChanged -= Reset; } Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } Reset(null, null); } internal static void Fail(ref bool ready, string feature, Exception ex) { ready = false; Log.LogError((object)("Physics disabled " + feature + " for this session; vanilla fallback. " + ex.GetType().Name + ": " + ex.Message)); } internal static float Value(ConfigEntry<float> setting, float fallback, float min, float max) { return Safety.Bounded(setting.Value, fallback, min, max); } internal static bool Finite(Vector3 v) { //IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references) if (Safety.Finite(v.x) && Safety.Finite(v.y)) { return Safety.Finite(v.z); } return false; } } internal static class Access { internal static FieldRef<Character, Rigidbody> Body; internal static FieldRef<Character, Rigidbody> AttachBody; internal static FieldRef<Character, ZNetView> View; internal static FieldRef<Character, Vector3> AttachPos; internal static FieldRef<Character, float> GroundTouch; internal static FieldRef<Character, float> GroundTimer; internal static Func<Character, bool> SwimDepth; internal static void Init() { Body = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body"); AttachBody = AccessTools.FieldRefAccess<Character, Rigidbody>("m_lastAttachBody"); View = AccessTools.FieldRefAccess<Character, ZNetView>("m_nview"); AttachPos = AccessTools.FieldRefAccess<Character, Vector3>("m_lastAttachPos"); GroundTouch = AccessTools.FieldRefAccess<Character, float>("m_lastGroundTouch"); GroundTimer = AccessTools.FieldRefAccess<Character, float>("m_groundForceTimer"); SwimDepth = AccessTools.MethodDelegate<Func<Character, bool>>(AccessTools.Method(typeof(Character), "InLiquidSwimDepth", (Type[])null, (Type[])null), (object)null, true); } internal static bool Valid(Character c) { if (!Object.op_Implicit((Object)(object)c) || !PhysicsPlugin.EnabledMod.Value || c.IsDead() || c.IsTeleporting() || c.IsAttached() || c.IsSwimming() || SwimDepth(c) || c.IsDebugFlying() || c.InIntro()) { return false; } ZNetView val = View.Invoke(c); if (Object.op_Implicit((Object)(object)val) && val.IsValid() && val.IsOwner() && Object.op_Implicit((Object)(object)Body.Invoke(c))) { return !Body.Invoke(c).isKinematic; } return false; } } internal sealed class DeckState { internal Ship Ship; internal Rigidbody Body; internal Collider Deck; internal ZNetView ShipView; internal long Owner; internal Vector3 FrameVelocity; internal Vector3 CarriedVelocity; internal Vector3 LocalPoint; internal float ContactTime; } [HarmonyPatch(typeof(Character), "ApplyGroundForce")] internal static class BoatPatch { private const float MaxDeckHeave = 4f; private static ConditionalWeakTable<Character, DeckState> states = new ConditionalWeakTable<Character, DeckState>(); private static readonly RaycastHit[] deckHits = (RaycastHit[])(object)new RaycastHit[32]; internal static void Clear() { states = new ConditionalWeakTable<Character, DeckState>(); } internal static bool Nearby(Character c) { if (!Object.op_Implicit((Object)(object)c)) { return false; } if (c.IsPlayer() || c.InNumShipVolumes > 0) { return true; } states.Remove(c); return false; } internal static bool Eligible(Character c) { if (Access.Valid(c) && (!PhysicsPlugin.PlayersOnly.Value || c.IsPlayer())) { return !c.IsKnockedBack(); } return false; } private static void Prefix(Character __instance, Vector3 targetVel) { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00c1: 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_00d4: 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012e: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) if (!PhysicsPlugin.BoatReady || !Nearby(__instance)) { return; } try { if (!Eligible(__instance)) { states.Remove(__instance); return; } Ship standingOnShip = __instance.GetStandingOnShip(); if (!__instance.IsOnGround()) { return; } if (!Object.op_Implicit((Object)(object)standingOnShip)) { states.Remove(__instance); } else { if (Access.GroundTouch.Invoke(__instance) > 0.001f) { return; } Collider lastGroundCollider = __instance.GetLastGroundCollider(); Rigidbody val = (Object.op_Implicit((Object)(object)lastGroundCollider) ? lastGroundCollider.attachedRigidbody : null); if (!Object.op_Implicit((Object)(object)val) || (Object)(object)((Component)val).GetComponent<Ship>() != (Object)(object)standingOnShip) { states.Remove(__instance); return; } Vector3 position = ((Component)__instance).transform.position; Vector3 pointVelocity = val.GetPointVelocity(position); pointVelocity.y = 0f; if (!PhysicsPlugin.Finite(pointVelocity) || ((Vector3)(ref pointVelocity)).magnitude > 20f || !PhysicsPlugin.Finite(position)) { states.Remove(__instance); return; } DeckState orCreateValue = states.GetOrCreateValue(__instance); orCreateValue.Ship = standingOnShip; orCreateValue.Body = val; orCreateValue.Deck = lastGroundCollider; orCreateValue.FrameVelocity = pointVelocity; orCreateValue.CarriedVelocity = pointVelocity; orCreateValue.LocalPoint = ((Component)val).transform.InverseTransformPoint(position); orCreateValue.ContactTime = Time.time; orCreateValue.ShipView = ((Component)standingOnShip).GetComponent<ZNetView>(); orCreateValue.Owner = ((Object.op_Implicit((Object)(object)orCreateValue.ShipView) && orCreateValue.ShipView.IsValid()) ? orCreateValue.ShipView.GetZDO().GetOwner() : 0); GripDeck(__instance, standingOnShip, val, targetVel); } } catch (Exception ex) { Clear(); PhysicsPlugin.Fail(ref PhysicsPlugin.BoatReady, "boat", ex); } } private static void GripDeck(Character c, Ship ship, Rigidbody body, Vector3 targetVel) { //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_005f: 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) //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_006c: 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_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_00c7: 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_00d5: 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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if (!PhysicsPlugin.DeckGrip.Value || ((Vector3)(ref targetVel)).magnitude > 0.01f || (Object)(object)Access.AttachBody.Invoke(c) != (Object)(object)body || !ship.IsOwner()) { return; } Rigidbody val = Access.Body.Invoke(c); Vector3 val2 = ((Component)body).transform.TransformPoint(Access.AttachPos.Invoke(c)); Vector3 val3 = val2 - val.position; if (PhysicsPlugin.Finite(val3) && !(((Vector3)(ref val3)).magnitude >= 4f)) { val3.y = 0f; float num = Safety.GripScale(((Vector3)(ref val3)).magnitude, PhysicsPlugin.Value(PhysicsPlugin.DeckGripLimit, 2f, 0.5f, 40f)); if (!(num >= 1f)) { Vector3 val4 = val.position + val3 * num; val4.y = val2.y; Access.AttachPos.Invoke(c) = ((Component)body).transform.InverseTransformPoint(val4); } } } private static void Postfix(Character __instance, ref Vector3 vel) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_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) if (!PhysicsPlugin.BoatReady || !Nearby(__instance)) { return; } try { if (GetAirState(__instance, out var s, out var fade) && !__instance.IsOnGround() && !(Access.GroundTimer.Invoke(__instance) > 0f)) { Vector3 val = vel + s.CarriedVelocity * fade; if (PhysicsPlugin.Finite(val)) { vel = val; } } } catch (Exception ex) { Clear(); PhysicsPlugin.Fail(ref PhysicsPlugin.BoatReady, "boat", ex); } } internal static bool GetAirState(Character c, out DeckState s, out float fade) { //IL_00c1: 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_0103: 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_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_013c: Unknown result type (might be due to invalid IL or missing references) fade = 0f; s = null; if (!PhysicsPlugin.BoatReady || !Eligible(c)) { if (Object.op_Implicit((Object)(object)c)) { states.Remove(c); } return false; } if (!states.TryGetValue(c, out s)) { return false; } float age = Time.time - s.ContactTime; bool flag = Object.op_Implicit((Object)(object)s.ShipView) && s.ShipView.IsValid() && s.ShipView.GetZDO().GetOwner() == s.Owner; float keep = PhysicsPlugin.Value(PhysicsPlugin.MaxAirSeconds, 3f, 0.5f, 3f); float fade2 = PhysicsPlugin.Value(PhysicsPlugin.FadeSeconds, 1f, 0f, 1f); Vector3 position = ((Component)c).transform.position; if (!Object.op_Implicit((Object)(object)s.Ship) || !Object.op_Implicit((Object)(object)s.Body) || !Object.op_Implicit((Object)(object)s.Deck) || !s.Deck.enabled || !flag || !PhysicsPlugin.Finite(position)) { states.Remove(c); s = null; return false; } Vector3 val = ((Component)s.Body).transform.TransformPoint(s.LocalPoint); if (!Safety.AirValid(age, keep, fade2, Vector3.Distance(position, val))) { states.Remove(c); s = null; return false; } if (c.IsOnGround() && (Object)(object)c.GetStandingOnShip() != (Object)(object)s.Ship) { states.Remove(c); s = null; return false; } fade = Safety.Fade(age, keep, fade2); return fade > 0f; } internal static void CarryAirborne(Character c) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_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_0052: 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_007b: 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_0085: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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_0124: 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_0138: 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_0142: Unknown result type (might be due to invalid IL or missing references) if (!PhysicsPlugin.BoatReady || !Nearby(c)) { return; } try { if (!GetAirState(c, out var s, out var fade)) { return; } Vector3 val = ((Component)s.Body).transform.TransformPoint(s.LocalPoint); Vector3 pointVelocity = s.Body.GetPointVelocity(val); pointVelocity.y = 0f; if (!PhysicsPlugin.Finite(pointVelocity) || ((Vector3)(ref pointVelocity)).magnitude > 20f) { states.Remove(c); return; } Vector3 val2 = pointVelocity - s.FrameVelocity; s.FrameVelocity = pointVelocity; if (!c.IsOnGround() && !(Access.GroundTimer.Invoke(c) > 0f) && PhysicsPlugin.Finite(val2) && !(((Vector3)(ref val2)).magnitude > 5f) && OverDeck(c, s)) { Rigidbody val3 = Access.Body.Invoke(c); Vector3 val4 = val2 * (PhysicsPlugin.Value(PhysicsPlugin.Strength, 1f, 0f, 1f) * fade); Vector3 val5 = val3.linearVelocity + val4; Vector3 val6 = s.CarriedVelocity + val4; if (PhysicsPlugin.Finite(val5) && PhysicsPlugin.Finite(val6)) { val3.linearVelocity = val5; s.CarriedVelocity = val6; } } } catch (Exception ex) { Clear(); PhysicsPlugin.Fail(ref PhysicsPlugin.BoatReady, "boat", ex); } } internal static bool OverDeck(Character c, DeckState s) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) int num = Physics.RaycastNonAlloc(new Ray(((Component)c).transform.position + Vector3.up * 0.3f, Vector3.down), deckHits, 8.3f, -5, (QueryTriggerInteraction)1); for (int i = 0; i < num && i < deckHits.Length; i++) { Collider collider = ((RaycastHit)(ref deckHits[i])).collider; if (Object.op_Implicit((Object)(object)collider) && (Object)(object)collider.attachedRigidbody == (Object)(object)s.Body) { return true; } } return false; } internal static bool CameraOnDeck(Player p, out DeckState s) { if (GetAirState((Character)(object)p, out s, out var _)) { return OverDeck((Character)(object)p, s); } return false; } internal static bool DeckJumpFrame(Character c, bool force, out Vector3 velocity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_00f1: 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) velocity = Vector3.zero; if (!Nearby(c) || !Eligible(c) || !c.IsOnGround() || (!force && c.InAttack()) || Access.GroundTimer.Invoke(c) > 0f) { return false; } Ship standingOnShip = c.GetStandingOnShip(); Collider lastGroundCollider = c.GetLastGroundCollider(); Rigidbody val = (Object.op_Implicit((Object)(object)lastGroundCollider) ? lastGroundCollider.attachedRigidbody : null); if (!Object.op_Implicit((Object)(object)standingOnShip) || !Object.op_Implicit((Object)(object)val) || (Object)(object)((Component)val).GetComponent<Ship>() != (Object)(object)standingOnShip) { return false; } Vector3 position = ((Component)c).transform.position; Vector3 pointVelocity = val.GetPointVelocity(position); if (PhysicsPlugin.Finite(position) && PhysicsPlugin.Finite(pointVelocity)) { Vector3 val2 = new Vector3(pointVelocity.x, 0f, pointVelocity.z); if (!(((Vector3)(ref val2)).magnitude > 20f)) { pointVelocity.y = Mathf.Clamp(pointVelocity.y, -4f, 4f); velocity = pointVelocity; return true; } } return false; } } [HarmonyPatch(typeof(Character), "UpdateWalking")] internal static class BoatAirPatch { private static void Postfix(Character __instance) { BoatPatch.CarryAirborne(__instance); } } internal struct JumpFrame { internal Rigidbody Body; internal Vector3 Velocity; } [HarmonyPatch(typeof(Character), "Jump")] internal static class BoatJumpPatch { private static void Prefix(Character __instance, bool force, out JumpFrame __state) { //IL_0038: 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_003e: 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_0051: Unknown result type (might be due to invalid IL or missing references) __state = default(JumpFrame); if (!PhysicsPlugin.BoatReady || !PhysicsPlugin.DeckJump.Value) { return; } try { if (BoatPatch.DeckJumpFrame(__instance, force, out var velocity)) { Rigidbody val = Access.Body.Invoke(__instance); val.linearVelocity -= velocity; __state.Body = val; __state.Velocity = velocity; } } catch (Exception ex) { BoatPatch.Clear(); PhysicsPlugin.Fail(ref PhysicsPlugin.BoatReady, "boat", ex); } } private static void Finalizer(JumpFrame __state) { //IL_001b: 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_0026: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)__state.Body)) { return; } try { __state.Body.linearVelocity = __state.Body.linearVelocity + __state.Velocity; } catch (Exception ex) { PhysicsPlugin.Fail(ref PhysicsPlugin.BoatReady, "boat", ex); } } } [HarmonyPatch(typeof(GameCamera), "UpdateBaseOffset")] internal static class CameraPatch { private static FieldRef<GameCamera, Vector3> pos; private static FieldRef<GameCamera, Vector3> vel; internal static void Init() { pos = AccessTools.FieldRefAccess<GameCamera, Vector3>("m_playerPos"); vel = AccessTools.FieldRefAccess<GameCamera, Vector3>("m_playerVel"); } private static void Postfix(GameCamera __instance, Player player) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_0054: 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_005d: 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_0083: 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) if (!PhysicsPlugin.CameraReady || !PhysicsPlugin.ShipCameraFix.Value) { return; } try { if (Object.op_Implicit((Object)(object)player) && !((Object)(object)((Character)player).GetStandingOnShip() != (Object)null) && BoatPatch.CameraOnDeck(player, out var _)) { Vector3 position = ((Component)player).transform.position; Vector3 linearVelocity = Access.Body.Invoke((Character)(object)player).linearVelocity; if (PhysicsPlugin.Finite(position) && PhysicsPlugin.Finite(linearVelocity)) { pos.Invoke(__instance) = position; vel.Invoke(__instance) = linearVelocity; } } } catch (Exception ex) { PhysicsPlugin.Fail(ref PhysicsPlugin.CameraReady, "camera", ex); } } } internal static class LadderRamp { private const string ObjectName = "Razaotium_Physics_LadderRamp"; private const float Width = 1.3f; private const float MaxTreadHeight = 1f; private const float Thickness = 0.08f; private static readonly Dictionary<int, GameObject> ramps = new Dictionary<int, GameObject>(); private static readonly Dictionary<int, float> rejectedUntil = new Dictionary<int, float>(); private static readonly List<int> stale = new List<int>(); private static float nextCleanup; internal static bool Ensure(Piece ladder, Vector3 ladderForward) { //IL_0078: 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_00aa: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_00ed: 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_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0186: 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_0193: 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) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: 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_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Expected O, but got Unknown //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)ladder) || !PhysicsPlugin.StairReady || !PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.SmoothStairClimb.Value) { return false; } int instanceID = ((Object)ladder).GetInstanceID(); if (ramps.TryGetValue(instanceID, out var value) && Object.op_Implicit((Object)(object)value)) { return true; } if (rejectedUntil.TryGetValue(instanceID, out var value2) && Time.unscaledTime < value2) { return false; } if (!Safety.KnownStair(Utils.GetPrefabName(((Component)ladder).gameObject))) { return false; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(ladderForward.x, 0f, ladderForward.z); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { return Reject(instanceID); } ((Vector3)(ref val)).Normalize(); Vector3 val2 = Vector3.Cross(Vector3.up, val); Vector3 normalized = ((Vector3)(ref val2)).normalized; List<float> list = new List<float>(); List<float> list2 = new List<float>(); float num = 0f; Collider[] componentsInChildren = ((Component)ladder).GetComponentsInChildren<Collider>(true); foreach (Collider obj in componentsInChildren) { if (TreadNose((BoxCollider)(object)((obj is BoxCollider) ? obj : null), val, normalized, out var along, out var top, out var side)) { list.Add(along); list2.Add(top); num += side; } } float clearance = PhysicsPlugin.Value(PhysicsPlugin.RampClearance, 0.01f, -0.05f, 0.1f); if (!Safety.TryNoseRamp(list.ToArray(), list2.ToArray(), ((Component)ladder).transform.position.y, clearance, out var slope, out var _, out var start, out var end, out var startHeight, out var topHeight)) { return Reject(instanceID); } float num2 = num / (float)list.Count; val2 = val + Vector3.up * slope; Vector3 normalized2 = ((Vector3)(ref val2)).normalized; val2 = Vector3.up - val * slope; Vector3 normalized3 = ((Vector3)(ref val2)).normalized; Vector3 val3 = val * ((start + end) * 0.5f) + normalized * num2 + Vector3.up * ((startHeight + topHeight) * 0.5f); float num3 = Mathf.Sqrt((end - start) * (end - start) + (topHeight - startHeight) * (topHeight - startHeight)); GameObject val4 = new GameObject("Razaotium_Physics_LadderRamp"); ((Object)val4).hideFlags = (HideFlags)61; int num4 = LayerMask.NameToLayer("blocker"); val4.layer = ((num4 >= 0) ? num4 : ((Component)ladder).gameObject.layer); val4.transform.position = val3 - normalized3 * 0.04f; val4.transform.rotation = Quaternion.LookRotation(normalized2, normalized3); val4.transform.SetParent(((Component)ladder).transform, true); val4.AddComponent<BoxCollider>().size = new Vector3(1.3f, 0.08f, num3); ramps[instanceID] = val4; rejectedUntil.Remove(instanceID); return true; } private static bool TreadNose(BoxCollider box, Vector3 forward, Vector3 right, out float along, out float top, out float side) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: 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_00d2: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0118: 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) along = (top = (side = 0f)); if (!Object.op_Implicit((Object)(object)box) || ((Collider)box).isTrigger || ((Object)((Component)box).gameObject).name == "Razaotium_Physics_LadderRamp") { return false; } Transform transform = ((Component)box).transform; float num = Vector3.Dot(transform.up, Vector3.up); if (Mathf.Abs(num) < 0.995f) { return false; } float num2 = Mathf.Abs(box.size.y * transform.lossyScale.y); if (num2 < 0.02f || num2 > 1f) { return false; } float num3 = ((num > 0f) ? 0.5f : (-0.5f)) * box.size.y; along = float.MaxValue; top = float.MinValue; for (int i = -1; i <= 1; i += 2) { for (int j = -1; j <= 1; j += 2) { Vector3 val = transform.TransformPoint(box.center + new Vector3((float)i * 0.5f * box.size.x, num3, (float)j * 0.5f * box.size.z)); along = Mathf.Min(along, Vector3.Dot(val, forward)); top = Mathf.Max(top, val.y); } } side = Vector3.Dot(transform.TransformPoint(box.center), right); if (Safety.Finite(along) && Safety.Finite(top)) { return Safety.Finite(side); } return false; } private static bool Reject(int id) { rejectedUntil[id] = Time.unscaledTime + 2f; return false; } internal static bool IsRampCollider(Collider collider) { if (Object.op_Implicit((Object)(object)collider)) { return ((Object)((Component)collider).gameObject).name == "Razaotium_Physics_LadderRamp"; } return false; } internal static void Tick() { if (!PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.SmoothStairClimb.Value) { DestroyAll(); } else { if (Time.unscaledTime < nextCleanup) { return; } nextCleanup = Time.unscaledTime + 1f; stale.Clear(); foreach (KeyValuePair<int, GameObject> ramp in ramps) { if (!Object.op_Implicit((Object)(object)ramp.Value)) { stale.Add(ramp.Key); } } foreach (int item in stale) { ramps.Remove(item); } } } internal static void DestroyAll() { foreach (GameObject value in ramps.Values) { if (Object.op_Implicit((Object)(object)value)) { value.SetActive(false); Object.Destroy((Object)(object)value); } } ramps.Clear(); rejectedUntil.Clear(); stale.Clear(); nextCleanup = 0f; } } [HarmonyPatch(typeof(AutoJumpLedge), "OnTriggerStay")] internal static class StairTriggerPatch { private static bool Prefix(AutoJumpLedge __instance, Collider __0) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (!PhysicsPlugin.StairReady || !PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.SmoothStairClimb.Value) { return true; } try { Character val = (Object.op_Implicit((Object)(object)__0) ? ((Component)__0).GetComponent<Character>() : null); if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val != (Object)(object)Player.m_localPlayer) { return true; } Piece componentInParent = ((Component)__instance).GetComponentInParent<Piece>(); if (!Object.op_Implicit((Object)(object)componentInParent) || !Safety.KnownStair(Utils.GetPrefabName(((Component)componentInParent).gameObject))) { return true; } return !LadderRamp.Ensure(componentInParent, ((Component)__instance).transform.forward); } catch (Exception ex) { LadderRamp.DestroyAll(); PhysicsPlugin.Fail(ref PhysicsPlugin.StairReady, "stairs", ex); return true; } } } [HarmonyPatch(typeof(Piece), "Awake")] internal static class StairPiecePatch { private static void Postfix(Piece __instance) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (!PhysicsPlugin.StairReady || !PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.SmoothStairClimb.Value || !Object.op_Implicit((Object)(object)__instance)) { return; } try { if (!Safety.KnownStair(Utils.GetPrefabName(((Component)__instance).gameObject))) { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component) && component.IsValid()) { AutoJumpLedge componentInChildren = ((Component)__instance).GetComponentInChildren<AutoJumpLedge>(true); if (Object.op_Implicit((Object)(object)componentInChildren)) { LadderRamp.Ensure(__instance, ((Component)componentInChildren).transform.forward); } } } catch (Exception ex) { LadderRamp.DestroyAll(); PhysicsPlugin.Fail(ref PhysicsPlugin.StairReady, "stairs", ex); } } } [HarmonyPatch(typeof(Character), "GetSlideAngle")] internal static class StairSlidePatch { private static void Postfix(Character __instance, ref float __result) { if (PhysicsPlugin.StairReady && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && LadderRamp.IsRampCollider(__instance.GetLastGroundCollider())) { __result = Mathf.Max(__result, 55f); } } } [HarmonyPatch(typeof(Character), "UpdateWalking")] internal static class StairHoldPatch { private static void Postfix(Character __instance) { //IL_0034: 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_00a3: Unknown result type (might be due to invalid IL or missing references) if (!PhysicsPlugin.StairReady || !PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.SmoothStairClimb.Value || (object)__instance != Player.m_localPlayer) { return; } try { if (!__instance.IsOnGround()) { return; } Vector3 moveDir = __instance.GetMoveDir(); if (!(((Vector3)(ref moveDir)).sqrMagnitude >= 0.01f) && LadderRamp.IsRampCollider(__instance.GetLastGroundCollider()) && !__instance.IsDead() && !__instance.IsAttached() && !__instance.InAttack() && !__instance.InDodge() && !__instance.IsKnockedBack() && !__instance.IsStaggering()) { Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>(); if (Object.op_Implicit((Object)(object)component) && !component.isKinematic) { component.linearVelocity = Vector3.zero; component.useGravity = false; } } } catch (Exception ex) { LadderRamp.DestroyAll(); PhysicsPlugin.Fail(ref PhysicsPlugin.StairReady, "stairs", ex); } } } internal static class StairStride { private sealed class Foot { internal float Stance; internal float Ik; internal float Support; internal float Lift; internal float PlantBlend; internal float Drift; internal float LastHit; internal float HitX; internal float HitZ; internal float TreadX; internal float TreadZ; internal float Stand; internal bool Planted; internal bool Spent; internal bool Hit; internal bool Valid; internal bool Seen; internal bool HasStand; internal Vector3 Position; internal Vector3 Normal = Vector3.up; internal Vector3 PlantPos; internal Vector3 PlantNormal = Vector3.up; internal Quaternion Rotation; } private sealed class Stride { internal Character Character; internal Transform Visual; internal Vector3 Baseline; internal float Offset; internal float OffsetVelocity; internal float Target; internal float LastContact; internal float Speed; internal bool Active; internal bool Still; internal bool HasPivot; internal Vector3 LastPivot; internal readonly Foot Left = new Foot(); internal readonly Foot Right = new Foot(); } private const float Smooth = 0.08f; private const float MaxDown = 1f; private const float MaxUp = 0.8f; private const float RampProbe = 0.6f; private const float RampReach = 1f; private const float ProbeAbove = 1.3f; private const float ProbeDepth = 2.8f; private const float MaxDrift = 0.3f; private const float ContactGrace = 0.25f; private const float MissHold = 0.25f; private const float HoldRadius = 0.12f; private const float EdgeMargin = 0.05f; private const float SameTread = 0.3f; private const float StillEnter = 0.5f; private const float StillExit = 1f; private static readonly Dictionary<CharacterAnimEvent, Stride> strides = new Dictionary<CharacterAnimEvent, Stride>(); private static readonly List<CharacterAnimEvent> finished = new List<CharacterAnimEvent>(); private static FieldRef<CharacterAnimEvent, Character> characterOf; private static FieldRef<CharacterAnimEvent, Animator> animatorOf; private static int groundMask; private static int rampMask; private static bool Enabled { get { if (PhysicsPlugin.StairReady && PhysicsPlugin.EnabledMod.Value && PhysicsPlugin.SmoothStairClimb.Value) { return PhysicsPlugin.StairFeet.Value; } return false; } } internal static void Init() { characterOf = AccessTools.FieldRefAccess<CharacterAnimEvent, Character>("m_character"); animatorOf = AccessTools.FieldRefAccess<CharacterAnimEvent, Animator>("m_animator"); groundMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" }); rampMask = LayerMask.GetMask(new string[1] { "blocker" }); } internal static void Clear() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<CharacterAnimEvent, Stride> stride in strides) { if (Object.op_Implicit((Object)(object)stride.Key) && Object.op_Implicit((Object)(object)stride.Value.Visual)) { stride.Value.Visual.localPosition = stride.Value.Baseline; } } strides.Clear(); } internal static void Step(float dt) { //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) if (strides.Count == 0) { return; } finished.Clear(); float fixedTime = Time.fixedTime; foreach (KeyValuePair<CharacterAnimEvent, Stride> stride in strides) { Stride value = stride.Value; if (!Object.op_Implicit((Object)(object)stride.Key) || !Object.op_Implicit((Object)(object)value.Visual)) { finished.Add(stride.Key); continue; } value.Active = Enabled && fixedTime - value.LastContact <= 0.25f; value.Offset = Mathf.SmoothDamp(value.Offset, value.Active ? value.Target : 0f, ref value.OffsetVelocity, 0.08f, 20f, dt); if (!value.Active && Mathf.Abs(value.Offset) < 0.002f) { value.Visual.localPosition = value.Baseline; finished.Add(stride.Key); } else { value.Visual.localPosition = value.Baseline + Vector3.up * value.Offset; } } foreach (CharacterAnimEvent item in finished) { strides.Remove(item); } } internal static float OffsetOf(Character c) { foreach (Stride value in strides.Values) { if (value.Character == c) { return value.Offset; } } return 0f; } internal static void BeforeIK(CharacterAnimEvent e) { //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_0055: 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_0060: 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) //IL_00c7: 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_017e: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: 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_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !Object.op_Implicit((Object)(object)e) || !e.m_footIK) { return; } Character val = characterOf.Invoke(e); Animator val2 = animatorOf.Invoke(e); if (!(val is Player) || !Object.op_Implicit((Object)(object)val2)) { return; } Vector3 position = ((Component)val).transform.position; float fixedTime = Time.fixedTime; RaycastHit val3 = default(RaycastHit); bool flag = Physics.Raycast(position + Vector3.up * 0.6f, Vector3.down, ref val3, 1f, rampMask, (QueryTriggerInteraction)1) && LadderRamp.IsRampCollider(((RaycastHit)(ref val3)).collider); if (!strides.TryGetValue(e, out var value)) { if (!flag) { return; } value = new Stride { Character = val, Visual = ((Component)e).transform, Baseline = ((Component)e).transform.localPosition, LastContact = fixedTime }; strides[e] = value; } if (flag) { value.LastContact = fixedTime; } value.Active = fixedTime - value.LastContact <= 0.25f; if (!value.Active) { Release(value.Left); Release(value.Right); return; } float deltaTime = Time.deltaTime; if (value.HasPivot && deltaTime > 0f) { value.Speed += (Vector3.Distance(position, value.LastPivot) / deltaTime - value.Speed) * Mathf.Clamp01(deltaTime * 10f); } value.LastPivot = position; value.HasPivot = true; value.Still = Safety.StillBody(value.Still, value.Speed, 0.5f, 1f); Sample(e, val2, (AvatarIKGoal)0, position, fixedTime, deltaTime, value.Left); Sample(e, val2, (AvatarIKGoal)1, position, fixedTime, deltaTime, value.Right); float num = ((!value.Still || !value.Left.HasStand || !value.Right.HasStand) ? Safety.StanceSupport(Deciding(value.Left), Tread(value.Left), Deciding(value.Right), Tread(value.Right), position.y + value.Target) : Mathf.Min(value.Left.Stand, value.Right.Stand)); value.Target = Mathf.Clamp(num - position.y, -1f, 0.8f); } private static void Release(Foot foot) { foot.Planted = (foot.Spent = (foot.Seen = (foot.Valid = (foot.HasStand = false)))); foot.PlantBlend = 0f; } private static float Horizontal(float x, float z) { return Mathf.Sqrt(x * x + z * z); } private static bool Supported(Foot foot) { if (!foot.Valid) { return foot.Planted; } return true; } private static float Standing(Foot foot) { return Mathf.Max(foot.Stance, foot.PlantBlend); } private static float Deciding(Foot foot) { if (!Supported(foot)) { return 0f; } return Standing(foot); } private static float Tread(Foot foot) { return Mathf.Lerp(foot.Support, foot.PlantPos.y, foot.PlantBlend); } private static void Sample(CharacterAnimEvent e, Animator animator, AvatarIKGoal goal, Vector3 pivot, float now, float dt, Foot foot) { //IL_0003: 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_0009: 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_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_0024: 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_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_0044: 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_0080: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) foot.Position = animator.GetIKPosition(goal); foot.Rotation = animator.GetIKRotation(goal); float num = Safety.StanceWeight(((Component)e).transform.InverseTransformPoint(foot.Position - ((Component)e).transform.up * e.m_footOffset).y, e.m_footDownMax); RaycastHit val = default(RaycastHit); foot.Hit = Physics.Raycast(new Vector3(foot.Position.x, pivot.y + 1.3f, foot.Position.z), Vector3.down, ref val, 2.8f, groundMask, (QueryTriggerInteraction)1); if (foot.Hit) { float moved = Horizontal(foot.Position.x - foot.TreadX, foot.Position.z - foot.TreadZ); if (Safety.TakeTread(foot.Seen, foot.Support, ((RaycastHit)(ref val)).point.y, moved, 0.3f, 0.05f)) { foot.Support = ((RaycastHit)(ref val)).point.y; foot.Normal = ((RaycastHit)(ref val)).normal; foot.TreadX = foot.Position.x; foot.TreadZ = foot.Position.z; } foot.LastHit = now; foot.HitX = foot.Position.x; foot.HitZ = foot.Position.z; foot.Seen = true; } foot.Valid = foot.Hit || (foot.Seen && (now - foot.LastHit <= 0.25f || Horizontal(foot.Position.x - foot.HitX, foot.Position.z - foot.HitZ) <= 0.12f)); if (foot.Valid && num >= 0.9f) { foot.Stand = foot.Support; foot.HasStand = true; } foot.Stance = Mathf.MoveTowards(foot.Stance, num, dt * 10f); float num2 = (foot.Valid ? Mathf.Max(0f, foot.Support - ((Component)e).transform.position.y) : 0f); foot.Lift = Mathf.MoveTowards(foot.Lift, num2, dt * 8f); float num3 = foot.Position.x - foot.PlantPos.x; float num4 = foot.Position.z - foot.PlantPos.z; foot.Drift = (foot.Planted ? Mathf.Sqrt(num3 * num3 + num4 * num4) : 0f); if (!PhysicsPlugin.FootMagnet.Value || num < 0.4f) { foot.Planted = (foot.Spent = false); } else if (foot.Planted) { if (foot.Drift > 0.3f) { foot.Planted = false; } } else if (!foot.Spent && num >= 0.9f && foot.Hit) { foot.PlantPos = ((RaycastHit)(ref val)).point; foot.PlantNormal = ((RaycastHit)(ref val)).normal; foot.Planted = (foot.Spent = true); } foot.PlantBlend = Mathf.MoveTowards(foot.PlantBlend, (float)(foot.Planted ? 1 : 0), dt * 12f); if (Supported(foot)) { foot.Ik = Mathf.MoveTowards(foot.Ik, Mathf.Max((foot.Lift > 0.02f) ? 1f : num, foot.PlantBlend), dt * 10f); } else { foot.Ik = Mathf.MoveTowards(foot.Ik, 0f, dt * 4f); } } internal static void AfterIK(CharacterAnimEvent e) { if (Enabled && Object.op_Implicit((Object)(object)e) && strides.TryGetValue(e, out var value) && value.Active) { Animator val = animatorOf.Invoke(e); if (Object.op_Implicit((Object)(object)val)) { Place(val, (AvatarIKGoal)0, value.Left, e.m_footOffset); Place(val, (AvatarIKGoal)1, value.Right, e.m_footOffset); } } } private static void Place(Animator animator, AvatarIKGoal goal, Foot foot, float footOffset) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_00a4: 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_00b4: 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_00c3: 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_00d2: 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_00da: 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_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_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_00f2: Unknown result type (might be due to invalid IL or missing references) float num = (foot.Seen ? foot.Ik : 0f); animator.SetIKPositionWeight(goal, num); animator.SetIKRotationWeight(goal, Mathf.Min(Standing(foot), num) * 0.5f); if (!(num <= 0f)) { float num2 = ((foot.Lift > 0.02f) ? Mathf.Max(foot.Position.y + foot.Lift, foot.Support + footOffset) : (foot.Support + footOffset)); Vector3 val = Vector3.Lerp(new Vector3(foot.Position.x, num2, foot.Position.z), foot.PlantPos + Vector3.up * footOffset, foot.PlantBlend); Vector3 val2 = ((foot.PlantBlend > 0.5f) ? foot.PlantNormal : foot.Normal); animator.SetIKPosition(goal, val); animator.SetIKRotation(goal, Quaternion.LookRotation(Vector3.Cross(foot.Rotation * Vector3.right, val2), val2)); } } } [HarmonyPatch(typeof(CharacterAnimEvent), "OnAnimatorIK")] internal static class StairStrideIKPatch { private static void Prefix(CharacterAnimEvent __instance) { if (!PhysicsPlugin.StairReady) { return; } try { StairStride.BeforeIK(__instance); } catch (Exception ex) { StairStride.Clear(); PhysicsPlugin.Fail(ref PhysicsPlugin.StairReady, "stair feet", ex); } } private static void Postfix(CharacterAnimEvent __instance) { if (!PhysicsPlugin.StairReady) { return; } try { StairStride.AfterIK(__instance); } catch (Exception ex) { StairStride.Clear(); PhysicsPlugin.Fail(ref PhysicsPlugin.StairReady, "stair feet", ex); } } } [HarmonyPatch(typeof(GameCamera), "GetCameraBaseOffset")] internal static class StairStrideCameraPatch { private static void Postfix(Player player, ref Vector3 __result) { if (!PhysicsPlugin.StairReady || !Object.op_Implicit((Object)(object)player) || ((Character)player).InBed() || ((Character)player).IsAttached() || ((Character)player).IsSitting()) { return; } try { __result.y -= StairStride.OffsetOf((Character)(object)player); } catch (Exception ex) { StairStride.Clear(); PhysicsPlugin.Fail(ref PhysicsPlugin.StairReady, "stair feet", ex); } } } [HarmonyPatch(typeof(GameCamera), "CollideRay2")] internal static class StairStrideCollisionPatch { private static void Prefix(ref Vector3 eyePos) { if (!PhysicsPlugin.StairReady) { return; } try { eyePos.y -= StairStride.OffsetOf((Character)(object)Player.m_localPlayer); } catch (Exception ex) { StairStride.Clear(); PhysicsPlugin.Fail(ref PhysicsPlugin.StairReady, "stair feet", ex); } } } [HarmonyPatch(typeof(Character), "GetSlideAngle")] internal static class MountPatch { private static void Postfix(Character __instance, ref float __result) { if (!PhysicsPlugin.MountReady || !PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.MountFooting.Value) { return; } try { if (Object.op_Implicit((Object)(object)__instance) && !__instance.IsPlayer() && __instance.HaveRider()) { __result = PhysicsPlugin.Value(PhysicsPlugin.MountSlideAngle, 85f, 38f, 90f); } } catch (Exception ex) { PhysicsPlugin.Fail(ref PhysicsPlugin.MountReady, "mount", ex); } } } internal static class Safety { internal const float MaxCarryDistance = 8f; internal static bool Finite(float v) { if (!float.IsNaN(v)) { return !float.IsInfinity(v); } return false; } internal static float Bounded(float v, float fallback, float min, float max) { if (!Finite(v)) { return fallback; } return Math.Max(min, Math.Min(max, v)); } internal static float Fade(float age, float keep, float fade) { if (!(age < 0f)) { if (!(age <= keep)) { if (!(fade <= 0f)) { return Math.Max(0f, 1f - (age - keep) / fade); } return 0f; } return 1f; } return 0f; } internal static bool AirValid(float age, float keep, float fade, float displacement) { if (Finite(age) && age >= 0f && age <= keep + fade && Finite(displacement)) { return displacement <= 8f; } return false; } internal static float GripScale(float offset, float limitSpeed) { if (!Finite(offset) || !Finite(limitSpeed) || offset <= 0f || limitSpeed <= 0f) { return 1f; } float num = limitSpeed / 10f; if (!(offset <= num)) { return num / offset; } return 1f; } internal static bool StairVelocity(float y, float speed) { if (Finite(y) && y >= -1f) { return y <= speed + 0.25f; } return false; } internal static bool StairGrace(float age) { if (Finite(age) && age >= 0f) { return age <= 0.25f; } return false; } internal static bool StairContact(bool grounded, bool sameStair, float age) { if (!grounded) { if (sameStair) { return StairGrace(age); } return false; } return true; } internal static bool CeilingNormal(float y) { if (Finite(y)) { return y < -0.5f; } return false; } internal static bool StepSurface(float width, float height, float depth) { if (!Finite(width) || !Finite(height) || !Finite(depth) || width <= 0f || height <= 0f || depth <= 0f) { return false; } if (height <= 0.35f) { return height <= Math.Max(width, depth) * 0.5f; } return false; } internal static bool TryNoseRamp(float[] along, float[] top, float baseHeight, float clearance, out float slope, out float intercept, out float start, out float end, out float startHeight, out float topHeight) { slope = (intercept = (start = (end = (startHeight = (topHeight = 0f))))); if (along == null || top == null || along.Length != top.Length || along.Length < 2 || !Finite(baseHeight) || !Finite(clearance) || clearance < -0.1f || clearance > 0.5f) { return false; } int num = along.Length; int[] array = new int[num]; for (int i = 0; i < num; i++) { if (!Finite(along[i]) || !Finite(top[i])) { return false; } array[i] = i; } Array.Sort((float[])along.Clone(), array); List<float> list = new List<float>(); for (int j = 1; j < num; j++) { float num2 = along[array[j]] - along[array[j - 1]]; float num3 = top[array[j]] - top[array[j - 1]]; if (num2 > 0.05f && num3 > 0.05f) { list.Add(num3 / num2); } } if (list.Count == 0) { return false; } list.Sort(); int num4 = list.Count / 2; float num5 = ((list.Count % 2 == 1) ? list[num4] : ((list[num4 - 1] + list[num4]) * 0.5f)); if (!Finite(num5) || num5 < 0.4f || num5 > 2.5f) { return false; } slope = Math.Min(num5, 1.35f); float num6 = float.MinValue; float num7 = float.MaxValue; topHeight = float.MinValue; for (int k = 0; k < num; k++) { num6 = Math.Max(num6, top[k] - slope * along[k]); topHeight = Math.Max(topHeight, top[k]); num7 = Math.Min(num7, top[k]); } intercept = num6 + clearance * (float)Math.Sqrt(1f + slope * slope); startHeight = Math.Min(baseHeight, num7); start = (startHeight - intercept) / slope; end = (topHeight - intercept) / slope; if (Finite(intercept) && Finite(start) && Finite(end) && end - start > 0.25f) { return end - start < 12f; } return false; } internal static float StanceWeight(float lifted, float downMax) { if (!Finite(lifted) || !Finite(downMax) || downMax <= 0f) { return 0f; } return 1f - Math.Max(0f, Math.Min(1f, lifted / downMax)); } internal static float StanceSupport(float leftWeight, float leftSupport, float rightWeight, float rightSupport, float previous) { if (!Finite(leftWeight) || !Finite(rightWeight) || !Finite(leftSupport) || !Finite(rightSupport)) { return previous; } float num = Math.Max(0f, Math.Min(1f, leftWeight)); float num2 = Math.Max(0f, Math.Min(1f, rightWeight)); if (num + num2 < 0.05f) { return previous; } float num3 = ((leftSupport <= rightSupport) ? num : num2); float num4 = ((leftSupport <= rightSupport) ? num2 : num); float num5 = Math.Min(leftSupport, rightSupport); float num6 = Math.Max(leftSupport, rightSupport); if (num3 < 0.05f && num4 < 0.05f) { return previous; } return num5 + (num6 - num5) * num4 * (1f - num3); } internal static bool StillBody(bool still, float speed, float enter, float exit) { if (!Finite(speed)) { return still; } if (!still) { return speed < enter; } return speed <= exit; } internal static bool TakeTread(bool known, float tread, float hitHeight, float moved, float sameTread, float margin) { if (!Finite(hitHeight)) { return false; } if (!known || !Finite(tread) || Math.Abs(hitHeight - tread) < sameTread) { return true; } if (Finite(moved)) { return moved > margin; } return false; } internal static bool TryEndpointRamp(float lowerAlong, float lowerTop, float upperAlong, float upperTop, out float slope, out float surfaceLength) { slope = 0f; surfaceLength = 0f; if (!Finite(lowerAlong) || !Finite(lowerTop) || !Finite(upperAlong) || !Finite(upperTop)) { return false; } float num = upperAlong - lowerAlong; float num2 = upperTop - lowerTop; if (num < 0.25f || num2 < 0.1f) { return false; } float num3 = num2 / num; if (!Finite(num3) || num3 < 0.4f || num3 > 2.5f) { return false; } slope = Math.Min(num3, 1.35f); surfaceLength = num * (float)Math.Sqrt(1f + slope * slope); if (Finite(surfaceLength)) { return surfaceLength > 0f; } return false; } internal static bool TryCappedRamp(float centerAlong, float centerHeight, float slope, float requestedLength, float topHeight, out float start, out float startHeight, out float end, out float endHeight, out float landingEnd) { start = (startHeight = (end = (endHeight = (landingEnd = 0f)))); if (!Finite(centerAlong) || !Finite(centerHeight) || !Finite(slope) || !Finite(requestedLength) || !Finite(topHeight) || slope <= 0f || requestedLength <= 0f) { return false; } float num = requestedLength / (2f * (float)Math.Sqrt(1f + slope * slope)); float num2 = num * slope; start = centerAlong - num; startHeight = centerHeight - num2; endHeight = Math.Min(centerHeight + num2, topHeight + 0.02f); if (endHeight - startHeight < 0.01f) { return false; } end = start + (endHeight - startHeight) / slope; landingEnd = Math.Max(end, centerAlong + num); if (Finite(start) && Finite(startHeight) && Finite(end) && Finite(endHeight)) { return Finite(landingEnd); } return false; } internal static bool KnownStair(string name) { if (string.IsNullOrEmpty(name)) { return false; } int num = name.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase); if (num >= 0) { name = name.Substring(0, num); } name = name.Trim().ToLowerInvariant(); switch (name) { default: return name == "grausten_stone_ladder"; case "piece_wood_ladder": case "piece_wood_ladder_45": case "piece_woodstepladder": case "piece_grausten_stoneladder": case "piece_grausten_stone_ladder": case "wood_ladder": case "wood_stepladder": case "woodstepladder": case "grausten_ladder": return true; } } } }