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.9
Physics.dll
Decompiled 2 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.9")] [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> MountFooting; internal static ConfigEntry<bool> CreatureDeckHold; internal static ConfigEntry<bool> CreatureStayAboard; internal static ConfigEntry<bool> ClaimAboard; 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; internal static bool ShipCreatureReady; 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_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023a: 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. Players only; 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, carry the character model along the line of the treads and step its feet from tread to tread. Visual only."); RampClearance = Bind("Stairs", "RampGap", 0.05f, 0.03f, 0.1f, "Gap between the invisible ramp and the tread noses, in meters. The body must not touch the noses: closer than 0.03 the character snags on them at low speed. The model and feet are placed on the real treads regardless of this value."); 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."); CreatureDeckHold = Bind("Ship creatures", "CreatureDeckHold", value: true, "Tamed creatures and mounts (ridden or not) standing still on a ship stay locked to their deck spot, also on the ship owner's machine. Vanilla only does this for passengers."); CreatureStayAboard = Bind("Ship creatures", "CreatureStayAboard", value: true, "Tamed creatures with no one to follow stop wandering while standing on a ship, and a 'stay' order moves along with the ship instead of pointing at a fixed spot in the sea."); ClaimAboard = Bind("Ship creatures", "ClaimAboard", value: true, "While you are aboard, your game takes over (network ownership) the tamed creatures standing on your ship that nobody rides, so these fixes also cover animals run by players without this mod. Creatures already run by another player with this mod are left alone."); 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); } try { ShipCreatures.Init(); ShipCreatureReady = true; harmony.PatchAll(typeof(CreatureDeckPatch)); harmony.PatchAll(typeof(CreatureIdlePatch)); } catch (Exception ex5) { Fail(ref ShipCreatureReady, "ship creatures initialization", ex5); } EnabledMod.SettingChanged += Reset; PlayersOnly.SettingChanged += Reset; SmoothStairClimb.SettingChanged += Reset; RampClearance.SettingChanged += Reset; StairFeet.SettingChanged += Reset; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Physics 1.0.9: boat=" + BoatReady + ", stairs=" + StairReady + ", camera=" + CameraReady + ", mount=" + MountReady + ", shipCreatures=" + ShipCreatureReady)); } private void Update() { if (StairReady) { LadderRamp.Tick(); } if (ShipCreatureReady) { try { ShipCreatures.Tick(); } catch (Exception ex) { ShipCreatures.Clear(); Fail(ref ShipCreatureReady, "ship creatures", ex); } } } 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(); ShipCreatures.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; } 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00c2: 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_00e7: 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) //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_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013f: 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_0145: Unknown result type (might be due to invalid IL or missing references) //IL_019e: 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_005d: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_00c9: 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) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) if (!PhysicsPlugin.DeckGrip.Value || !c.IsPlayer() || ((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_0039: 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_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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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) 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_0102: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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_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_0123: 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_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: 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_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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) __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_003b: 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_004d: 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_0053: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) 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; private static Collider playerCollider; private static Player playerOf; 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_00f4: 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_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Expected O, but got Unknown //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_032c: 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) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0374: 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>(); List<Tread> list3 = new List<Tread>(); 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, out var far, out var halfWidth)) { list.Add(along); list2.Add(top); num += side; list3.Add(new Tread { Near = along, Far = far, Top = top, Side = side, Half = halfWidth }); } } float clearance = PhysicsPlugin.Value(PhysicsPlugin.RampClearance, 0.05f, 0.03f, 0.1f); if (!Safety.TryNoseRamp(list.ToArray(), list2.ToArray(), ((Component)ladder).transform.position.y, clearance, out var slope, out var intercept, out var start, out var end, out var startHeight, out var topHeight)) { return Reject(instanceID); } float num2 = num / (float)list.Count; float num3 = 0f; foreach (Tread item in list3) { num3 = Mathf.Max(num3, item.Half * 2f); } num3 = Mathf.Clamp(num3, 0.8f, 1.3f); float halfTread = num3 * 0.5f; num3 = 1.3f; 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 num4 = Mathf.Sqrt((end - start) * (end - start) + (topHeight - startHeight) * (topHeight - startHeight)); GameObject val4 = new GameObject("Razaotium_Physics_LadderRamp"); ((Object)val4).hideFlags = (HideFlags)61; int num5 = LayerMask.NameToLayer("blocker"); val4.layer = ((num5 >= 0) ? num5 : ((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(num3, 0.08f, num4); RampData rampData = val4.AddComponent<RampData>(); rampData.Forward = val; rampData.Right = normalized; rampData.Side = num2; rampData.HalfTread = halfTread; rampData.Slope = slope; rampData.Intercept = intercept; rampData.Treads = list3; 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, out float far, out float halfWidth) { //IL_0058: 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_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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: 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_010d: 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_012e: 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_0138: 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_0142: 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_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) along = (top = (side = (far = (halfWidth = 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; far = float.MinValue; top = float.MinValue; float num4 = float.MaxValue; float num5 = 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)); far = Mathf.Max(far, Vector3.Dot(val, forward)); top = Mathf.Max(top, val.y); num4 = Mathf.Min(num4, Vector3.Dot(val, right)); num5 = Mathf.Max(num5, Vector3.Dot(val, right)); } } side = Vector3.Dot(transform.TransformPoint(box.center), right); halfWidth = (num5 - num4) * 0.5f; 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; } private static void OneWay() { //IL_004c: 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) //IL_005b: 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_0096: 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_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_00cc: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return; } if ((Object)(object)localPlayer != (Object)(object)playerOf || !Object.op_Implicit((Object)(object)playerCollider)) { playerOf = localPlayer; playerCollider = (Collider)(object)((Component)localPlayer).GetComponent<CapsuleCollider>(); } if (!Object.op_Implicit((Object)(object)playerCollider)) { return; } Vector3 val = ((Component)localPlayer).transform.position + Vector3.up * 0.25f; foreach (GameObject value in ramps.Values) { if (!Object.op_Implicit((Object)(object)value)) { continue; } Transform transform = value.transform; Vector3 val2 = val - transform.position; if (((Vector3)(ref val2)).sqrMagnitude > 36f) { continue; } Collider component = value.GetComponent<Collider>(); if (Object.op_Implicit((Object)(object)component)) { RampData component2 = value.GetComponent<RampData>(); bool flag = Vector3.Dot(val2, transform.up) < -0.15f; if (Object.op_Implicit((Object)(object)component2) && Mathf.Abs(Vector3.Dot(val, component2.Right) - component2.Side) > component2.HalfTread + 0.15f) { flag = true; } Physics.IgnoreCollision(playerCollider, component, flag); } } } internal static void Tick() { if (!PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.SmoothStairClimb.Value) { DestroyAll(); return; } OneWay(); 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_006b: 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 int rampMask; private static bool OnRamp(Character c) { if (c.IsOnGround() && LadderRamp.IsRampCollider(c.GetLastGroundCollider()) && !c.IsDead() && !c.IsAttached() && !c.InDodge() && !c.IsKnockedBack()) { return !c.IsStaggering(); } return false; } private static void HugDescent(Character c) { //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_0058: 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_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_0097: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) Vector3 moveDir = c.GetMoveDir(); if (!(((Vector3)(ref moveDir)).sqrMagnitude >= 0.01f) || c.IsDead() || c.IsAttached() || c.InDodge() || c.IsKnockedBack() || c.IsStaggering()) { return; } Rigidbody component = ((Component)c).GetComponent<Rigidbody>(); if (!Object.op_Implicit((Object)(object)component) || component.isKinematic) { return; } Vector3 linearVelocity = component.linearVelocity; if (linearVelocity.y > 0.5f) { return; } if (rampMask == 0) { rampMask = LayerMask.GetMask(new string[1] { "blocker" }); } Vector3 position = ((Component)c).transform.position; RaycastHit val = default(RaycastHit); if (!Physics.Raycast(position + Vector3.up * 0.6f, Vector3.down, ref val, 1.3f, rampMask, (QueryTriggerInteraction)1) || ((RaycastHit)(ref val)).point.y > position.y + 0.02f || !LadderRamp.IsRampCollider(((RaycastHit)(ref val)).collider)) { return; } RampData component2 = ((Component)((RaycastHit)(ref val)).collider).GetComponent<RampData>(); if (Object.op_Implicit((Object)(object)component2)) { float num = Vector3.Dot(linearVelocity, component2.Forward); if (num < -0.3f && linearVelocity.y > num * component2.Slope) { linearVelocity.y = num * component2.Slope; component.linearVelocity = linearVelocity; } } } private static void Prefix(Character __instance) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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.StairReady || !PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.SmoothStairClimb.Value || (object)__instance != Player.m_localPlayer) { return; } try { if (OnRamp(__instance)) { Vector3 moveDir = __instance.GetMoveDir(); if (!(((Vector3)(ref moveDir)).sqrMagnitude >= 0.01f)) { Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>(); if (Object.op_Implicit((Object)(object)component) && !component.isKinematic) { component.linearVelocity = Vector3.zero; } return; } } HugDescent(__instance); } catch (Exception ex) { LadderRamp.DestroyAll(); PhysicsPlugin.Fail(ref PhysicsPlugin.StairReady, "stairs", ex); } } private static void Postfix(Character __instance) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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 (!OnRamp(__instance)) { return; } Vector3 moveDir = __instance.GetMoveDir(); if (!(((Vector3)(ref moveDir)).sqrMagnitude >= 0.01f)) { Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>(); if (Object.op_Implicit((Object)(object)component) && !component.isKinematic) { component.useGravity = false; } } } catch (Exception ex) { LadderRamp.DestroyAll(); PhysicsPlugin.Fail(ref PhysicsPlugin.StairReady, "stairs", ex); } } } internal sealed class Tread { internal float Near; internal float Far; internal float Top; internal float Side; internal float Half; internal float Center => (Near + Far) * 0.5f; } internal sealed class RampData : MonoBehaviour { internal Vector3 Forward; internal Vector3 Right; internal float Side; internal float HalfTread; internal float Slope; internal float Intercept; internal List<Tread> Treads; } internal static class StairStride { private sealed class Foot { internal Vector3 Pos; internal float Lift; internal float Weight; internal float Stance; internal bool HasTread; internal float TreadTop; internal float Level; internal float Shift; internal float ShiftTarget; internal bool Pulled; internal Quaternion Rotation; } private sealed class Stride { internal Character Character; internal Transform Visual; internal Vector3 Baseline; internal Animator Animator; internal AnimatorUpdateMode OldMode; internal float Offset; internal float OffsetVelocity; internal float Target; internal float LastContact; internal float LastTime; internal float Weight; internal float Velocity; internal float LastAlong; internal float NextChain; internal float FootHeight; internal float DownMax; internal float Speed; internal readonly Vector3[] Trail = (Vector3[])(object)new Vector3[16]; internal readonly float[] TrailTime = new float[16]; internal int TrailNext; internal int TrailCount; internal bool Still; internal bool Active; internal bool HasAlong; internal bool Placed; internal RampData Ramp; internal List<Tread> Chain; internal float LineDrop; 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.2f; private const float RampProbe = 0.6f; private const float RampReach = 1f; private const float ContactGrace = 0.25f; private const float Airborne = 0.45f; private const float BehindLimit = 0.1f; private const float AheadLimit = 0.72f; private const float TreadRun = 0.66f; private const float Stance = 0.11f; private const float AnkleBack = 0.06f; private const float TreadInset = 0.13f; private const float TurnLimit = 55f; private const float SideLimit = 0.25f; private const float SwingMin = 0.14f; private const float SwingMax = 0.45f; private const float SwingArc = 0.16f; private const float ShuffleArc = 0.05f; private static readonly Dictionary<CharacterAnimEvent, Stride> strides = new Dictionary<CharacterAnimEvent, Stride>(); private static readonly List<CharacterAnimEvent> finished = new List<CharacterAnimEvent>(); private static readonly Collider[] nearby = (Collider[])(object)new Collider[16]; 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() { foreach (KeyValuePair<CharacterAnimEvent, Stride> stride in strides) { Restore(stride.Value); } strides.Clear(); } private static void Restore(Stride s) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)s.Visual)) { s.Visual.localPosition = s.Baseline; } if (Object.op_Implicit((Object)(object)s.Animator)) { s.Animator.updateMode = s.OldMode; } } internal static void Step(float dt) { if (strides.Count == 0) { return; } finished.Clear(); float time = Time.time; foreach (KeyValuePair<CharacterAnimEvent, Stride> stride in strides) { if (!Object.op_Implicit((Object)(object)stride.Key) || !Object.op_Implicit((Object)(object)stride.Value.Visual) || time - stride.Value.LastTime > 0.5f || !Enabled) { Restore(stride.Value); finished.Add(stride.Key); } } 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_0155: 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_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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Unknown result type (might be due to invalid IL or missing references) //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: 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 time = Time.time; 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); RampData rampData = (flag ? ((Component)((RaycastHit)(ref val3)).collider).GetComponent<RampData>() : null); flag = flag && Object.op_Implicit((Object)(object)rampData); if (!strides.TryGetValue(e, out var value)) { if (!flag) { return; } value = new Stride { Character = val, Visual = ((Component)e).transform, Baseline = ((Component)e).transform.localPosition, Animator = val2, OldMode = val2.updateMode, LastContact = time, LastTime = time }; val2.updateMode = (AnimatorUpdateMode)0; strides[e] = value; } value.FootHeight = e.m_footOffset; value.DownMax = e.m_footDownMax; value.Trail[value.TrailNext] = position; value.TrailTime[value.TrailNext] = time; value.TrailNext = (value.TrailNext + 1) % 16; value.TrailCount = Mathf.Min(value.TrailCount + 1, 16); value.Speed = 0f; for (int i = 0; i < value.TrailCount; i++) { float num = time - value.TrailTime[i]; if (num >= 0.2f && num <= 0.6f) { value.Speed = Mathf.Max(value.Speed, Vector3.Distance(position, value.Trail[i]) / num); } } value.Still = (value.Still ? (value.Speed < 0.5f) : (value.Speed < 0.25f)); if (flag) { value.LastContact = time; if ((Object)(object)rampData != (Object)(object)value.Ramp || time >= value.NextChain) { value.Ramp = rampData; value.Chain = Chain(rampData, position, out value.LineDrop); value.NextChain = time + 1f; } } value.Active = time - value.LastContact <= 0.25f && Object.op_Implicit((Object)(object)value.Ramp); float num2 = time - value.LastTime; if (num2 <= 0f) { return; } value.LastTime = time; Collider lastGroundCollider = val.GetLastGroundCollider(); bool flag2 = val.IsOnGround() && LadderRamp.IsRampCollider(lastGroundCollider); bool flag3 = !value.Active || !val.IsOnGround() || (!flag2 && Object.op_Implicit((Object)(object)lastGroundCollider)) || (flag && position.y - ((RaycastHit)(ref val3)).point.y > 0.45f) || val.InDodge() || val.IsSitting() || val.IsAttached() || val.IsDead(); value.Weight = Mathf.MoveTowards(value.Weight, flag3 ? 0f : 1f, num2 * (flag3 ? 10f : 6f)); if (flag3) { value.Target = 0f; value.Offset = Mathf.SmoothDamp(value.Offset, 0f, ref value.OffsetVelocity, 0.1f, 8f, num2); value.Visual.localPosition = value.Baseline + Vector3.up * value.Offset; value.Left.Lift = (value.Right.Lift = 0f); value.Left.Weight = (value.Right.Weight = 0f); value.Left.Shift = (value.Right.Shift = 0f); if (!value.Active && value.Weight <= 0f && Mathf.Abs(value.Offset) < 0.002f) { Restore(value); strides.Remove(e); } } else { Walk(value, val2, position, num2); } } private static List<Tread> Chain(RampData ramp, Vector3 position, out float lineDrop) { //IL_000c: 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: Unknown result type (might be due to invalid IL or missing references) List<Tread> list = new List<Tread>(ramp.Treads); int num = Physics.OverlapSphereNonAlloc(position, 7f, nearby, rampMask, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { RampData component = ((Component)nearby[i]).GetComponent<RampData>(); if (!Object.op_Implicit((Object)(object)component) || (Object)(object)component == (Object)(object)ramp || Vector3.Dot(component.Forward, ramp.Forward) < 0.995f || Mathf.Abs(component.Side - ramp.Side) > 0.3f || Mathf.Abs(component.Intercept - ramp.Intercept) > 0.3f) { continue; } foreach (Tread tread in component.Treads) { bool flag = false; foreach (Tread item in list) { if (Mathf.Abs(item.Near - tread.Near) < 0.1f && Mathf.Abs(item.Top - tread.Top) < 0.1f) { flag = true; } } if (!flag) { list.Add(tread); } } } list.Sort((Tread a, Tread b) => a.Near.CompareTo(b.Near)); List<float> list2 = new List<float>(); foreach (Tread item2 in list) { list2.Add(ramp.Slope * item2.Center + ramp.Intercept - item2.Top); } list2.Sort(); lineDrop = ((list2.Count > 0) ? list2[list2.Count / 2] : 0f); return list; } private static void Walk(Stride s, Animator animator, Vector3 position, float dt) { //IL_0137: 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) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) RampData ramp = s.Ramp; if (s.Chain.Count == 0) { return; } Transform visual = s.Visual; float footHeight = s.FootHeight; float downMax = s.DownMax; Sample(s, s.Left, animator, (AvatarIKGoal)0, visual, footHeight, downMax, dt); Sample(s, s.Right, animator, (AvatarIKGoal)1, visual, footHeight, downMax, dt); float num = float.MaxValue; bool flag = false; Foot[] array = new Foot[2] { s.Left, s.Right }; foreach (Foot foot in array) { if (foot.HasTread && foot.Stance >= 0.6f) { num = Mathf.Min(num, foot.TreadTop + footHeight - (foot.Pos.y - s.Offset)); flag = true; } } if (flag) { s.Target = Mathf.Clamp(Mathf.Min(num, 0f), s.Still ? (-0.4f) : (-0.75f), 0.2f); } float offset = s.Offset; s.Offset = Mathf.SmoothDamp(s.Offset, s.Target, ref s.OffsetVelocity, 0.1f, 8f, dt); s.Visual.localPosition = s.Baseline + Vector3.up * s.Offset; float bodyShift = s.Offset - offset; Lift(s.Left, footHeight, bodyShift, dt, ramp.Forward); Lift(s.Right, footHeight, bodyShift, dt, ramp.Forward); } private static void Sample(Stride s, Foot foot, Animator animator, AvatarIKGoal goal, Transform visual, float footOffset, float downMax, float dt) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_001d: 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_002b: 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_0082: 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_0094: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) foot.Pos = animator.GetIKPosition(goal); foot.Rotation = animator.GetIKRotation(goal); float y = visual.InverseTransformPoint(foot.Pos - visual.up * footOffset).y; float num = ((downMax > 0f) ? (1f - Mathf.Clamp01(y / downMax)) : 0f); foot.Stance = Mathf.MoveTowards(foot.Stance, num, dt * 10f); RampData ramp = s.Ramp; float num2 = Vector3.Dot(foot.Pos, ramp.Forward); float num3 = Vector3.Dot(foot.Pos, ramp.Right); float num4 = Vector3.Dot(foot.Rotation * Vector3.forward, ramp.Forward); float num5 = num2 + ((num4 >= 0f) ? (-0.08f) : (-0.22f)) * Mathf.Abs(num4) - 0.08f * (1f - Mathf.Abs(num4)); float num6 = num2 + ((num4 >= 0f) ? 0.22f : 0.08f) * Mathf.Abs(num4) + 0.08f * (1f - Mathf.Abs(num4)); float num7 = float.MinValue; foreach (Tread item in s.Chain) { if (num6 >= item.Near && num5 <= item.Far && Mathf.Abs(num3 - item.Side) <= item.Half + 0.1f && item.Top <= foot.Pos.y + 0.45f && item.Top > num7) { num7 = item.Top; } } RaycastHit val = default(RaycastHit); if (num7 > float.MinValue && Physics.Raycast(new Vector3(foot.Pos.x, foot.Pos.y + 1f, foot.Pos.z), Vector3.down, ref val, 2f, groundMask, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val)).point.y > num7 + 0.03f) { num7 = float.MinValue; } foot.ShiftTarget = 0f; float num8 = num7 + footOffset - (foot.Pos.y - s.Offset); bool num9 = num7 > float.MinValue && s.Still && num8 < (foot.Pulled ? (-0.2f) : (-0.4f)); foot.Pulled = false; if (num9) { float num10 = float.MinValue; float shiftTarget = 0f; foreach (Tread item2 in s.Chain) { if (!(item2.Top <= num7) && !(item2.Top > foot.Pos.y + 0.45f) && !(Mathf.Abs(num3 - item2.Side) > item2.Half + 0.1f)) { float num11 = ((num2 < item2.Near) ? (item2.Near + 0.1f) : ((num2 > item2.Far) ? (item2.Far - 0.1f) : num2)) - num2; if (Mathf.Abs(num11) <= 0.3f && item2.Top > num10) { num10 = item2.Top; shiftTarget = num11; } } } if (num10 > float.MinValue) { num7 = num10; foot.ShiftTarget = shiftTarget; foot.Pulled = true; } } foot.HasTread = num7 > float.MinValue; foot.TreadTop = num7; } private static void Lift(Foot foot, float footOffset, float bodyShift, float dt, Vector3 forward) { //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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) foot.Shift = Mathf.MoveTowards(foot.Shift, foot.ShiftTarget, dt * 1.5f); foot.Pos += forward * foot.Shift; float num = foot.Pos.y + bodyShift; float num2 = (foot.HasTread ? Mathf.Max(0f, foot.TreadTop + footOffset - num) : 0f); foot.Lift = Mathf.MoveTowards(foot.Lift, num2, dt * ((num2 > foot.Lift) ? 12f : 6f)); foot.Pos.y = num + foot.Lift; foot.Weight = Mathf.MoveTowards(foot.Weight, (foot.Lift > 0.005f || Mathf.Abs(foot.Shift) > 0.005f) ? 1f : 0f, dt * 10f); foot.Level = Mathf.MoveTowards(foot.Level, (foot.HasTread && foot.Stance >= 0.5f && foot.TreadTop + footOffset >= num - 0.03f) ? 1f : 0f, dt * 8f); } internal static void AfterIK(CharacterAnimEvent e) { if (Enabled && Object.op_Implicit((Object)(object)e) && strides.TryGetValue(e, out var value) && value.Weight > 0f) { Animator val = animatorOf.Invoke(e); if (Object.op_Implicit((Object)(object)val)) { Apply(val, (AvatarIKGoal)0, value.Left, value.Weight); Apply(val, (AvatarIKGoal)1, value.Right, value.Weight); } } } private static void Apply(Animator animator, AvatarIKGoal goal, Foot foot, float weight) { //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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0058: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_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_0094: Unknown result type (might be due to invalid IL or missing references) float num = foot.Weight * weight; if (num > 0f) { animator.SetIKPositionWeight(goal, Mathf.Max(animator.GetIKPositionWeight(goal), num)); animator.SetIKPosition(goal, foot.Pos); } float num2 = foot.Level * weight; if (num2 > 0f) { Vector3 val = Vector3.ProjectOnPlane(foot.Rotation * Vector3.forward, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude > 0.001f) { animator.SetIKRotationWeight(goal, Mathf.Max(animator.GetIKRotationWeight(goal), num2)); animator.SetIKRotation(goal, Quaternion.Slerp(foot.Rotation, Quaternion.LookRotation(val, Vector3.up), num2)); } } } } [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); } } } internal static class ShipCreatures { private const float PatrolFollowInterval = 1f; private const float PatrolFollowDistance = 1f; internal static FieldRef<Character, Rigidbody> GroundBody; private static readonly Dictionary<int, float> patrolUpdate = new Dictionary<int, float>(); private const string AboardOwnerKey = "razaotium.physics.aboardOwner"; private const string AboardStampKey = "razaotium.physics.aboardStamp"; private static float nextClaim; private static readonly RaycastHit[] deckHits = (RaycastHit[])(object)new RaycastHit[16]; internal static void Init() { GroundBody = AccessTools.FieldRefAccess<Character, Rigidbody>("m_lastGroundBody"); if (AccessTools.Method(typeof(BaseAI), "IdleMovement", (Type[])null, (Type[])null) == null) { throw new MissingMethodException("BaseAI.IdleMovement"); } } internal static bool OnDeck(Character c, Ship ship) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)c).transform.position; if (!PhysicsPlugin.Finite(position)) { return false; } int num = Physics.RaycastNonAlloc(new Ray(position + Vector3.up * 0.5f, Vector3.down), deckHits, 1.5f, -5, (QueryTriggerInteraction)1); for (int i = 0; i < num && i < deckHits.Length; i++) { Rigidbody val = (Object.op_Implicit((Object)(object)((RaycastHit)(ref deckHits[i])).collider) ? ((RaycastHit)(ref deckHits[i])).collider.attachedRigidbody : null); if (Object.op_Implicit((Object)(object)val) && (Object)(object)((Component)val).GetComponent<Ship>() == (Object)(object)ship) { return true; } } return false; } internal static void Clear() { patrolUpdate.Clear(); nextClaim = 0f; } internal static void Tick() { if (Time.time < nextClaim) { return; } nextClaim = Time.time + Random.Range(1f, 1.5f); if (!PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.ClaimAboard.Value || (Object)(object)ZNet.instance == (Object)null || ZDOMan.instance == null) { return; } Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).IsTeleporting()) { return; } Ship localShip = Ship.GetLocalShip(); if (!Object.op_Implicit((Object)(object)localShip) || !localShip.IsPlayerInBoat(localPlayer)) { return; } long sessionID = ZDOMan.GetSessionID(); foreach (Character allCharacter in Character.GetAllCharacters()) { if (!Kept(allCharacter) || allCharacter.HaveRider() || !OnDeck(allCharacter, localShip)) { continue; } ZNetView val = Access.View.Invoke(allCharacter); ZDO val2 = ((Object.op_Implicit((Object)(object)val) && val.IsValid()) ? val.GetZDO() : null); if (val2 == null) { continue; } if (val.IsOwner()) { if (val2.GetLong("razaotium.physics.aboardOwner", 0L) != sessionID) { val2.Set("razaotium.physics.aboardOwner", sessionID); } continue; } long owner = val2.GetOwner(); if (owner == 0L || val2.GetLong("razaotium.physics.aboardOwner", 0L) != owner) { BaseAI baseAI = allCharacter.GetBaseAI(); if (!allCharacter.InAttack() && (!Object.op_Implicit((Object)(object)baseAI) || !baseAI.IsAlerted())) { val.ClaimOwnership(); val2.Set("razaotium.physics.aboardOwner", sessionID); val2.Set("razaotium.physics.aboardStamp", val2.GetInt("razaotium.physics.aboardStamp", 0) + 1); } } } } internal static bool Kept(Character c) { if (Object.op_Implicit((Object)(object)c) && !c.IsPlayer() && !c.IsDead()) { if (!c.IsTamed()) { return c.HaveRider(); } return true; } return false; } internal static bool Owned(Character c, out Rigidbody body) { body = Access.Body.Invoke(c); ZNetView val = Access.View.Invoke(c); if (Object.op_Implicit((Object)(object)val) && val.IsValid() && val.IsOwner() && Object.op_Implicit((Object)(object)body)) { return !body.isKinematic; } return false; } internal static void FollowPatrol(BaseAI ai, ZNetView view) { //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_0060: 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_0066: 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_006a: 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_007e: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = view.GetZDO(); if (zDO == null || !zDO.GetBool(ZDOVars.s_patrol, false)) { return; } int instanceID = ((Object)ai).GetInstanceID(); if (!patrolUpdate.TryGetValue(instanceID, out var value) || !(Time.time - value < 1f)) { patrolUpdate[instanceID] = Time.time; Vector3 position = ((Component)ai).transform.position; Vector3 vec = zDO.GetVec3(ZDOVars.s_patrolPoint, position); if (Utils.DistanceXZ(vec, position) > 1f || Mathf.Abs(vec.y - position.y) > 2f) { ai.SetPatrolPoint(); } } } } [HarmonyPatch(typeof(Character), "ApplyGroundForce")] internal static class CreatureDeckPatch { [HarmonyPriority(600)] private static void Prefix(Character __instance, Vector3 targetVel) { //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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_00d4: 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_00db: 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_00fa: Unknown result type (might be due to invalid IL or missing references) if (!PhysicsPlugin.ShipCreatureReady || !PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.CreatureDeckHold.Value) { return; } try { if (!Object.op_Implicit((Object)(object)__instance) || __instance.InNumShipVolumes <= 0 || ((Vector3)(ref targetVel)).magnitude > 0.01f || !ShipCreatures.Kept(__instance) || !ShipCreatures.Owned(__instance, out var body)) { return; } Ship standingOnShip = __instance.GetStandingOnShip(); if (!Object.op_Implicit((Object)(object)standingOnShip) || !standingOnShip.IsOwner()) { return; } Rigidbody val = Access.AttachBody.Invoke(__instance); if (!Object.op_Implicit((Object)(object)val) || (Object)(object)val != (Object)(object)ShipCreatures.GroundBody.Invoke(__instance)) { return; } Vector3 val2 = ((Component)val).transform.TransformPoint(Access.AttachPos.Invoke(__instance)); Vector3 position = body.position; if (PhysicsPlugin.Finite(val2) && PhysicsPlugin.Finite(position)) { Vector3 val3 = val2 - position; if (!(((Vector3)(ref val3)).magnitude >= 4f)) { val2.y = position.y; body.position = val2; } } } catch (Exception ex) { PhysicsPlugin.Fail(ref PhysicsPlugin.ShipCreatureReady, "ship creatures", ex); } } } [HarmonyPatch(typeof(BaseAI), "IdleMovement")] internal static class CreatureIdlePatch { private static bool Prefix(BaseAI __instance, Character ___m_character, ZNetView ___m_nview) { if (!PhysicsPlugin.ShipCreatureReady || !PhysicsPlugin.EnabledMod.Value || !PhysicsPlugin.CreatureStayAboard.Value) { return true; } try { if (!Object.op_Implicit((Object)(object)___m_character) || ___m_character.InNumShipVolumes <= 0 || !___m_character.IsTamed() || ___m_character.IsPlayer() || ___m_character.HaveRider() || ___m_character.IsSwimming() || ___m_character.IsFlying()) { return true; } if (!Object.op_Implicit((Object)(object)___m_nview) || !___m_nview.IsValid() || !___m_nview.IsOwner()) { return true; } if (___m_character.IsOnGround() && !Object.op_Implicit((Object)(object)___m_character.GetStandingOnShip())) { return true; } ShipCreatures.FollowPatrol(__instance, ___m_nview); __instance.StopMoving(); return false; } catch (Exception ex) { PhysicsPlugin.Fail(ref PhysicsPlugin.ShipCreatureReady, "ship creatures", ex); return true; } } } [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 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_45": case "piece_woodstepladder": case "grausten_ladder": case "wood_stepladder": case "piece_wood_ladder": case "piece_grausten_stoneladder": case "piece_grausten_stone_ladder": case "wood_ladder": case "woodstepladder": return true; } } } }