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 Unhindered v0.3.0
Unhindered.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Unity.Collections; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Unhindered")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.3.0.0")] [assembly: AssemblyInformationalVersion("0.3.0+401075277446405148177f8c51d5dfe1cca810ca")] [assembly: AssemblyProduct("Unhindered")] [assembly: AssemblyTitle("Unhindered")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Unhindered { [HarmonyPatch] internal static class CharacterSlide { private const float Friction = 0.2f; private static readonly HashSet<int> s_characters = new HashSet<int>(); private static Collider s_playerCollider; private static int s_player; private static bool s_enabled; internal static void Init() { s_enabled = Plugin.CharacterSlideEnabled.Value; Physics.ContactModifyEvent += OnContactModify; } internal static void Shutdown() { Physics.ContactModifyEvent -= OnContactModify; SetEnabled(enabled: false); } internal static void SetEnabled(bool enabled) { s_enabled = enabled; if ((Object)(object)s_playerCollider != (Object)null) { s_playerCollider.hasModifiableContacts = enabled; } } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "Awake")] private static void Awake(Character __instance) { Track(__instance); } [HarmonyPostfix] [HarmonyPatch(typeof(Character), "CustomFixedUpdate")] private static void CustomFixedUpdate(Character __instance) { Track(__instance); } private static void Track(Character character) { if (!((Object)(object)character.m_collider == (Object)null)) { int instanceID = ((Object)character.m_collider).GetInstanceID(); if (character.IsTamed()) { s_characters.Remove(instanceID); } else { s_characters.Add(instanceID); } } } [HarmonyPrefix] [HarmonyPatch(typeof(Character), "OnDestroy")] private static void OnDestroy(Character __instance) { if ((Object)(object)__instance.m_collider != (Object)null) { int instanceID = ((Object)__instance.m_collider).GetInstanceID(); s_characters.Remove(instanceID); if (instanceID == s_player) { s_player = 0; s_playerCollider = null; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Player), "SetLocalPlayer")] private static void SetLocalPlayer(Player __instance) { if ((Object)(object)((Character)__instance).m_collider != (Object)null) { s_playerCollider = (Collider)(object)((Character)__instance).m_collider; s_player = ((Object)s_playerCollider).GetInstanceID(); s_playerCollider.hasModifiableContacts = s_enabled; } } private static void OnContactModify(PhysicsScene scene, NativeArray<ModifiableContactPair> pairs) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) int num = s_player; if (!s_enabled || num == 0) { return; } for (int i = 0; i < pairs.Length; i++) { ModifiableContactPair val = pairs[i]; int colliderInstanceID = ((ModifiableContactPair)(ref val)).colliderInstanceID; int otherColliderInstanceID = ((ModifiableContactPair)(ref val)).otherColliderInstanceID; if ((colliderInstanceID == num && s_characters.Contains(otherColliderInstanceID)) || (otherColliderInstanceID == num && s_characters.Contains(colliderInstanceID))) { for (int j = 0; j < ((ModifiableContactPair)(ref val)).contactCount; j++) { ((ModifiableContactPair)(ref val)).SetStaticFriction(j, Math.Min(((ModifiableContactPair)(ref val)).GetStaticFriction(j), 0.2f)); ((ModifiableContactPair)(ref val)).SetDynamicFriction(j, Math.Min(((ModifiableContactPair)(ref val)).GetDynamicFriction(j), 0.2f)); } } } } } [HarmonyPatch] internal static class ForgivingJump { private struct State { public bool Changed; public float LastGroundTouch; public Vector3 LastGroundNormal; } private const float AirborneAfter = 0.05f; private const float MaxHeight = 0.35f; private const float MinTimeSinceJump = 0.3f; private const float MinWalkableY = 0.5f; private static readonly RaycastHit[] s_hits = (RaycastHit[])(object)new RaycastHit[16]; private static float s_lastHitTime = float.NegativeInfinity; [HarmonyPatch(typeof(Character), "Jump")] [HarmonyPrefix] private static void JumpPrefix(Character __instance, out State __state) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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) __state = default(State); if (!Plugin.ForgivingJumpEnabled.Value || (object)__instance != Player.m_localPlayer) { return; } Player val = (Player)__instance; float lastGroundTouch = ((Character)val).m_lastGroundTouch; if (!(lastGroundTouch < 0.05f) && !((Character)val).m_body.IsSleeping() && !((Character)val).InLiquidSwimDepth() && !((Character)val).IsAttached() && !((Object)(object)GrapplingPoint.m_localGrappler != (Object)null)) { __state.Changed = true; __state.LastGroundTouch = lastGroundTouch; __state.LastGroundNormal = ((Character)val).m_lastGroundNormal; if (Time.time - s_lastHitTime <= lastGroundTouch) { ((Character)val).m_lastGroundTouch = 1f; return; } if (((Character)val).IsOnGround() || ((Character)val).m_jumpTimer < 0.3f || !NearGround(val, out var normal)) { __state.Changed = false; return; } ((Character)val).m_lastGroundTouch = 0f; ((Character)val).m_lastGroundNormal = normal; } } [HarmonyPatch(typeof(Character), "Jump")] [HarmonyPostfix] private static void JumpPostfix(Character __instance, State __state) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (__state.Changed && __instance.m_jumpTimer > 0f) { __instance.m_lastGroundTouch = __state.LastGroundTouch; __instance.m_lastGroundNormal = __state.LastGroundNormal; } } [HarmonyPatch(typeof(Character), "ApplyDamage")] [HarmonyPostfix] private static void ApplyDamagePostfix(Character __instance, HitData hit) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if ((object)__instance == Player.m_localPlayer && __instance.m_lastHit == hit && !IsOngoing(hit.m_hitType)) { s_lastHitTime = Time.time; } } private static bool IsOngoing(HitType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 //IL_0006: 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_000b: Invalid comparison between Unknown and I4 if (type - 3 <= 6 || type - 21 <= 1) { return true; } return false; } private static bool NearGround(Player player, out Vector3 normal) { //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_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) //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_0062: 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_00c0: 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_00f2: Unknown result type (might be due to invalid IL or missing references) normal = Vector3.up; CapsuleCollider collider = ((Character)player).m_collider; float num = collider.radius * 0.9f; Vector3 val = ((Component)collider).transform.TransformPoint(collider.center) - Vector3.up * (collider.height * 0.5f - collider.radius); float num2 = 0.35f + collider.radius - num; int num3 = Physics.SphereCastNonAlloc(val, num, Vector3.down, s_hits, num2, Character.s_groundRayMask, (QueryTriggerInteraction)1); int selfLayer = 1 << ((Component)collider).gameObject.layer; float num4 = float.MaxValue; for (int i = 0; i < num3; i++) { RaycastHit val2 = s_hits[i]; if (((RaycastHit)(ref val2)).distance > 0f && ((RaycastHit)(ref val2)).distance < num4 && ((RaycastHit)(ref val2)).normal.y >= 0.5f && StepUp.Blocks(((RaycastHit)(ref val2)).collider, selfLayer)) { num4 = ((RaycastHit)(ref val2)).distance; normal = ((RaycastHit)(ref val2)).normal; } } return num4 < float.MaxValue; } } [HarmonyPatch] internal static class HauledCart { [HarmonyPostfix] [HarmonyPatch(typeof(Vagon), "AttachTo")] private static void AttachTo(Vagon __instance, GameObject go) { if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)go == (Object)(object)((Component)Player.m_localPlayer).gameObject) { StepUp.s_hauledCart = __instance.m_body; } } [HarmonyPostfix] [HarmonyPatch(typeof(Vagon), "Detach")] private static void Detach(Vagon __instance) { if (StepUp.s_hauledCart == __instance.m_body) { StepUp.s_hauledCart = null; } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class PassThrough { private static int s_characterLayers; private static bool s_dirty; private static readonly HashSet<string> s_untouchable = new HashSet<string>(); private static readonly HashSet<string> s_checked = new HashSet<string>(); [HarmonyPriority(0)] private static void Postfix(ZNetScene __instance) { s_characterLayers = LayerMask.GetMask(new string[4] { "character", "character_net", "character_ghost", "character_noenv" }); foreach (GameObject item in AllPrefabs(__instance)) { if (s_checked.Add(((Object)item).name) && item.GetComponentsInChildren<Collider>(true).Any((Collider c) => (LayerMask.op_Implicit(c.excludeLayers) & s_characterLayers) != 0)) { s_untouchable.Add(((Object)item).name); } } s_dirty = false; Refresh(__instance, includeSpawned: false); } internal static void MarkDirty() { s_dirty = true; } internal static void RefreshIfDirty() { if (s_dirty && !((Object)(object)ZNetScene.instance == (Object)null)) { s_dirty = false; Refresh(ZNetScene.instance, includeSpawned: true); } } private static void Refresh(ZNetScene scene, bool includeSpawned) { bool value = Plugin.PassThroughEnabled.Value; string[] names = Split(Plugin.PassThroughNames.Value); string[] exclude = Split(Plugin.PassThroughExclude.Value); Dictionary<string, bool> dictionary = new Dictionary<string, bool>(); foreach (GameObject item in AllPrefabs(scene)) { if (!s_untouchable.Contains(((Object)item).name) && !dictionary.ContainsKey(((Object)item).name)) { bool flag = value && Matches(item, names, exclude); dictionary[((Object)item).name] = flag; Collider[] componentsInChildren = item.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Set(componentsInChildren[i], flag); } } } int num = (includeSpawned ? RefreshSpawned(dictionary) : 0); List<string> list = (from kv in dictionary where kv.Value select kv.Key).ToList(); Plugin.Log.LogInfo((object)(value ? ($"Pass-through applied to {list.Count} prefabs" + (includeSpawned ? $" ({num} spawned colliders updated)" : "")) : "Pass-through disabled")); if (value && Plugin.PassThroughLogMatches.Value) { list.Sort(StringComparer.OrdinalIgnoreCase); Plugin.Log.LogInfo((object)("Pass-through prefabs: " + string.Join(", ", list))); } } private static int RefreshSpawned(Dictionary<string, bool> passable) { int num = 0; Collider[] array = Object.FindObjectsByType<Collider>((FindObjectsSortMode)0); foreach (Collider val in array) { bool? flag = null; Transform val2 = ((Component)val).transform; while ((Object)(object)val2 != (Object)null) { if (passable.TryGetValue(Utils.GetPrefabName(((Component)val2).gameObject), out var value)) { flag = value; } val2 = val2.parent; } if (flag.HasValue && Set(val, flag.Value)) { num++; } } return num; } private static bool Set(Collider collider, bool pass) { //IL_000b: 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) if (collider.isTrigger) { return false; } int num = LayerMask.op_Implicit(collider.excludeLayers); int num2 = (pass ? (num | s_characterLayers) : (num & ~s_characterLayers)); if (num2 == num) { return false; } collider.excludeLayers = LayerMask.op_Implicit(num2); return true; } private static IEnumerable<GameObject> AllPrefabs(ZNetScene scene) { return from p in scene.m_prefabs.Concat(scene.m_nonNetViewPrefabs) where (Object)(object)p != (Object)null select p; } private static bool Matches(GameObject prefab, string[] names, string[] exclude) { string name = ((Object)prefab).name; if (ContainsAny(name, exclude)) { return false; } if ((!Plugin.PassThroughPickables.Value || !((Object)(object)prefab.GetComponent<Pickable>() != (Object)null)) && (!Plugin.PassThroughPlants.Value || !((Object)(object)prefab.GetComponent<Plant>() != (Object)null))) { return ContainsAny(name, names); } return true; } private static bool ContainsAny(string name, string[] parts) { foreach (string value in parts) { if (name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private static string[] Split(string list) { return (from s in list.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select s.Trim() into s where s.Length > 0 select s).ToArray(); } } [BepInPlugin("hvalch.Unhindered", "Unhindered", "0.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "hvalch.Unhindered"; public const string Name = "Unhindered"; public const string Version = "0.3.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> PassThroughEnabled; internal static ConfigEntry<bool> PassThroughPickables; internal static ConfigEntry<bool> PassThroughPlants; internal static ConfigEntry<string> PassThroughNames; internal static ConfigEntry<string> PassThroughExclude; internal static ConfigEntry<bool> PassThroughLogMatches; internal static ConfigEntry<bool> StepUpEnabled; internal static ConfigEntry<float> StepUpMaxHeightWalk; internal static ConfigEntry<float> StepUpMaxHeightJog; internal static ConfigEntry<float> StepUpMaxHeightSprint; internal static ConfigEntry<float> StepUpSpeed; internal static ConfigEntry<bool> StepUpOnTerrain; internal static ConfigEntry<bool> StepUpDebug; internal static ConfigEntry<bool> CharacterSlideEnabled; internal static ConfigEntry<bool> ForgivingJumpEnabled; private readonly Harmony _harmony = new Harmony("hvalch.Unhindered"); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; PassThroughEnabled = BindSynced("1 - Pass Through", "Enabled", value: true, "Let characters walk through small plants (bushes, mushrooms, berry bushes, crops...). They can still be picked, chopped and hit."); PassThroughPickables = BindSynced("1 - Pass Through", "Pickables", value: true, "Include every pickable object (mushrooms, berries, thistle, flax, stones, branches...)."); PassThroughPlants = BindSynced("1 - Pass Through", "Plants", value: true, "Include growing plants and saplings (crops, tree saplings)."); PassThroughNames = BindSynced("1 - Pass Through", "NameContains", "bush,shrub", "Comma-separated, case-insensitive. Any prefab whose name contains one of these is included (e.g. add 'FirTree_small,Beech_small' to walk through small trees)."); PassThroughExclude = BindSynced("1 - Pass Through", "Exclude", "", "Comma-separated, case-insensitive. Prefabs whose name contains one of these are never changed. Wins over everything above."); PassThroughLogMatches = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Pass Through", "LogMatches", false, "Log every prefab made pass-through (to tune the lists above). Local only, never synced."); StepUpEnabled = BindSynced("2 - Step Up", "Enabled", value: true, "Automatically step up onto low obstacles (logs, rocks, ledges) while moving, instead of having to jump."); StepUpMaxHeightWalk = BindSynced("2 - Step Up", "MaxHeightWalk", 0.7f, "Tallest obstacle (meters) you can step onto while walking, crouching or encumbered. 0 = never step up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f)); StepUpMaxHeightJog = BindSynced("2 - Step Up", "MaxHeightJog", 1.2f, "Tallest obstacle (meters) you can step onto at normal running speed. 0 = never step up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f)); StepUpMaxHeightSprint = BindSynced("2 - Step Up", "MaxHeightSprint", 1.5f, "Tallest obstacle (meters) you can step onto while sprinting. 0 = never step up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f)); StepUpSpeed = BindSynced("2 - Step Up", "Speed", 6f, "How fast you rise when stepping up (m/s). Higher is snappier; 20 is near-instant.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f)); StepUpOnTerrain = BindSynced("2 - Step Up", "StepOnTerrain", value: false, "Also step up terrain ledges (e.g. hoe-raised ground). Off by default so natural cliffs still need a jump."); StepUpDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Step Up", "DebugLog", false, "Log why each obstacle you walk into is or isn't stepped onto (to LogOutput.log). Local only, never synced."); CharacterSlideEnabled = BindSynced("3 - Character Slide", "Enabled", value: true, "Slide around enemies and other players you walk into, the way you slide around trees, instead of sticking to them."); ForgivingJumpEnabled = BindSynced("4 - Forgiving Jump", "Enabled", value: true, "Jump when running lifts you slightly off the ground, instead of the jump being ignored. Getting hit in the air cancels it until you land."); ((BaseUnityPlugin)this).Config.SettingChanged += delegate(object _, SettingChangedEventArgs e) { if (e.ChangedSetting.Definition.Section == "1 - Pass Through") { PassThrough.MarkDirty(); } CharacterSlide.SetEnabled(CharacterSlideEnabled.Value); }; CharacterSlide.Init(); _harmony.PatchAll(); Log.LogInfo((object)"Unhindered 0.3.0 loaded"); } private void Update() { PassThrough.RefreshIfDirty(); } private void OnDestroy() { CharacterSlide.Shutdown(); _harmony.UnpatchSelf(); } private ConfigEntry<T> BindSynced<T>(string section, string key, T value, string description, AcceptableValueBase range = null) { //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_0022: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown return ((BaseUnityPlugin)this).Config.Bind<T>(section, key, value, new ConfigDescription(description, range, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); } } [HarmonyPatch(typeof(Character), "UpdateWalking")] internal static class StepUp { private struct StepState { public bool Active; public Vector3 Start; public Vector3 Dir; public float TargetY; public float Travel; public float Timer; public Collider Obstacle; } private const float MinStep = 0.05f; private const float MinWalkableY = 0.788f; private static int s_mask; private static int s_maskWithTerrain; private static int s_characterLayers; private static readonly RaycastHit[] s_hits = (RaycastHit[])(object)new RaycastHit[16]; internal static Rigidbody s_hauledCart; private static string s_lastDebug; private static float s_lastDebugTime; private const float StepTimeout = 0.6f; private static StepState s_step; private const float Skin = 0.03f; private const float SweepBackoff = 0.15f; private const float SweepLookAhead = 0.15f; private const float ProbeStep = 0.05f; private const float ProbeBeyond = 0.6f; private static readonly Collider[] s_probeOverlaps = (Collider[])(object)new Collider[8]; private static void Postfix(Character __instance, float dt) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_018f: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.StepUpEnabled.Value || (object)__instance != Player.m_localPlayer) { return; } Player val = (Player)__instance; Rigidbody body = ((Character)val).m_body; Vector3 moveDir = ((Character)val).m_moveDir; moveDir.y = 0f; if (((Character)val).IsAttached() || ((Character)val).InDodge() || ((Character)val).IsStaggering() || ((Character)val).IsRiding() || !((Character)val).CanMove() || body.isKinematic || ((Vector3)(ref moveDir)).sqrMagnitude < 0.01f) { s_step.Active = false; return; } ((Vector3)(ref moveDir)).Normalize(); if ((!s_step.Active || !ContinueStep(val, body, moveDir, dt)) && ((Character)val).IsOnGround() && !(body.linearVelocity.y > 4f)) { if (s_mask == 0) { s_mask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "vehicle" }); s_maskWithTerrain = s_mask | LayerMask.GetMask(new string[1] { "terrain" }); s_characterLayers = LayerMask.GetMask(new string[4] { "character", "character_net", "character_ghost", "character_noenv" }); } int mask = (Plugin.StepUpOnTerrain.Value ? s_maskWithTerrain : s_mask); int selfLayer = 1 << ((Component)((Character)val).m_collider).gameObject.layer; float num = MaxStep(val); if (!(num < 0.05f)) { Sweep(val, body, moveDir, dt, num, mask, selfLayer); } } } private static float MaxStep(Player player) { if (((Character)player).m_running) { return Plugin.StepUpMaxHeightSprint.Value; } if (((Character)player).m_walking || ((Character)player).IsCrouching() || ((Character)player).IsEncumbered()) { return Plugin.StepUpMaxHeightWalk.Value; } return Plugin.StepUpMaxHeightJog.Value; } private static bool Raycast(Vector3 origin, Vector3 dir, float distance, int mask, int selfLayer, out RaycastHit best) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Nearest(Physics.RaycastNonAlloc(origin, dir, s_hits, distance, mask, (QueryTriggerInteraction)1), selfLayer, 1f, out best); } private static bool Nearest(int count, int selfLayer, float maxNormalY, out RaycastHit best) { //IL_0001: 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_001c: 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_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) best = default(RaycastHit); float num = float.MaxValue; for (int i = 0; i < count; i++) { RaycastHit val = s_hits[i]; if (((RaycastHit)(ref val)).distance > 0f && ((RaycastHit)(ref val)).distance < num && ((RaycastHit)(ref val)).normal.y <= maxNormalY && Blocks(((RaycastHit)(ref val)).collider, selfLayer)) { best = val; num = ((RaycastHit)(ref val)).distance; } } return num < float.MaxValue; } internal static bool Blocks(Collider collider, int selfLayer) { //IL_0008: 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) Rigidbody attachedRigidbody = collider.attachedRigidbody; if ((LayerMask.op_Implicit(collider.excludeLayers) & selfLayer) == 0) { if (!((Object)(object)attachedRigidbody == (Object)null)) { if (attachedRigidbody != s_hauledCart) { return (LayerMask.op_Implicit(attachedRigidbody.excludeLayers) & selfLayer) == 0; } return false; } return true; } return false; } private static void Debug(string what, Collider collider, string detail) { if (Plugin.StepUpDebug.Value) { string text = "Step-up " + what + ": " + ((Object)((Component)collider).transform.root).name + "/" + ((Object)collider).name + " layer=" + LayerMask.LayerToName(((Component)collider).gameObject.layer) + " " + detail; if (!(text == s_lastDebug) || !(Time.time - s_lastDebugTime < 1f)) { s_lastDebug = text; s_lastDebugTime = Time.time; Plugin.Log.LogInfo((object)text); } } } private static void DebugIgnoredLayer(Vector3 origin, Vector3 dir, float distance) { //IL_000c: 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_006d: Unknown result type (might be due to invalid IL or missing references) RaycastHit val = default(RaycastHit); if (Plugin.StepUpDebug.Value && Physics.Raycast(origin, dir, ref val, distance, ~s_characterLayers, (QueryTriggerInteraction)1)) { Debug((((Plugin.StepUpOnTerrain.Value ? s_maskWithTerrain : s_mask) & (1 << ((Component)((RaycastHit)(ref val)).collider).gameObject.layer)) != 0) ? "not blocking (walkable slope, or pass-through)" : "ignored: layer not stepped on", ((RaycastHit)(ref val)).collider, $"normalY={((RaycastHit)(ref val)).normal.y:0.00}"); } } private static void Sweep(Player player, Rigidbody body, Vector3 dir, float dt, float maxStep, int mask, int selfLayer) { //IL_0015: 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_0042: 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_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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_009c: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_00d9: 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_0103: 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_0114: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_019a: 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_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_0154: 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_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: 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_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024a: 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_0253: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_0327: 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_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) CapsuleCollider collider = ((Character)player).m_collider; Transform transform = ((Component)collider).transform; float num = collider.radius * Mathf.Max(Mathf.Abs(transform.lossyScale.x), Mathf.Abs(transform.lossyScale.z)); float num2 = Mathf.Max(collider.height * Mathf.Abs(transform.lossyScale.y), num * 2f); Vector3 val = body.position + (transform.TransformPoint(collider.center) - transform.position); Vector3 val2 = val - Vector3.up * (num2 * 0.5f - num); Vector3 val3 = val + Vector3.up * (num2 * 0.5f - num); Vector3 feet = val2 - Vector3.up * num; float num3 = num - 0.03f; Vector3 currentVel = ((Character)player).m_currentVel; currentVel.y = 0f; float num4 = Mathf.Max(((Vector3)(ref currentVel)).magnitude * dt * 2f, 0.15f); Vector3 val4 = -dir * 0.15f; if (!Nearest(Physics.CapsuleCastNonAlloc(val2 + val4, val3 + val4, num3, dir, s_hits, 0.15f + num4 + 0.03f, mask, (QueryTriggerInteraction)1), selfLayer, 0.788f, out var best)) { DebugIgnoredLayer(val2 - Vector3.up * (num - 0.1f), dir, num + num4); return; } float wallDistance = Mathf.Max(0f, ((RaycastHit)(ref best)).distance - 0.15f); float num5 = maxStep + 0.03f; if (Nearest(Physics.CapsuleCastNonAlloc(val2, val3, num3, Vector3.up, s_hits, num5, mask, (QueryTriggerInteraction)1), selfLayer, 1f, out var best2)) { num5 = ((RaycastHit)(ref best2)).distance - 0.03f; } if (num5 < 0.05f) { Debug("rejected: no headroom", ((RaycastHit)(ref best)).collider, "ceiling=" + ((Object)((RaycastHit)(ref best2)).collider).name); return; } if (!FindStandPoint(feet, dir, wallDistance, num, num5, maxStep, mask, selfLayer, out var distance, out var why)) { Debug(why, ((RaycastHit)(ref best)).collider, ""); return; } Vector3 val5 = Vector3.up * num5; if (Nearest(Physics.CapsuleCastNonAlloc(val2 + val5, val3 + val5, num3, dir, s_hits, distance, mask, (QueryTriggerInteraction)1), selfLayer, 0.788f, out var best3)) { Debug("rejected: taller than MaxHeight", ((RaycastHit)(ref best)).collider, $"blocked at raise={num5:0.00} by {((Object)((RaycastHit)(ref best3)).collider).name}"); return; } Vector3 val6 = val5 + dir * distance; RaycastHit best4; float num6 = (Nearest(Physics.CapsuleCastNonAlloc(val2 + val6, val3 + val6, num3, Vector3.down, s_hits, num5, mask, (QueryTriggerInteraction)1), selfLayer, 1f, out best4) ? (num5 - ((RaycastHit)(ref best4)).distance) : 0f); if (!(num6 < 0.05f)) { s_step = new StepState { Active = true, Start = body.position, Dir = dir, TargetY = body.position.y + num6 + 0.03f, Travel = distance, Obstacle = ((RaycastHit)(ref best)).collider }; Debug("STEP", ((RaycastHit)(ref best)).collider, $"rise={num6:0.00} travel={distance:0.00}"); ContinueStep(player, body, dir, dt); } } private static bool FindStandPoint(Vector3 feet, Vector3 dir, float wallDistance, float radius, float raise, float maxStep, int mask, int selfLayer, out float distance, out string why) { //IL_0023: 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_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) //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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) distance = 0f; float num = 0.05f; float num2 = wallDistance + radius + 0.6f; for (float num3 = 0.05f; num3 <= num2; num3 += 0.05f) { Vector3 val = feet + dir * num3 + Vector3.up * (raise + 0.03f); if (StartsInside(val, mask, selfLayer)) { why = "rejected: taller than MaxHeight"; return false; } if (!Raycast(val, Vector3.down, raise + 0.03f + 0.05f, mask, selfLayer, out var best)) { continue; } float num4 = ((RaycastHit)(ref best)).point.y - feet.y; if (num4 < 0.05f) { if (distance > 0f) { break; } continue; } if (num4 > maxStep) { why = "rejected: taller than MaxHeight"; return false; } if (num4 > num) { num = num4; distance = num3; } } why = ((distance > 0f) ? null : "rejected: no top found"); return distance > 0f; } private static bool StartsInside(Vector3 point, int mask, int selfLayer) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) int num = Physics.OverlapSphereNonAlloc(point, 0.01f, s_probeOverlaps, mask, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { if (Blocks(s_probeOverlaps[i], selfLayer)) { return true; } } return false; } private static bool ContinueStep(Player player, Rigidbody body, Vector3 dir, float dt) { //IL_0010: 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_0029: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0127: 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_011a: 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) s_step.Timer += dt; float num = Vector3.Dot(body.position - s_step.Start, s_step.Dir); if (num >= s_step.Travel || s_step.Timer > 0.6f || Vector3.Dot(dir, s_step.Dir) < 0.5f) { if (num < s_step.Travel && (Object)(object)s_step.Obstacle != (Object)null) { Debug("step abandoned", s_step.Obstacle, $"traveled={num:0.00}/{s_step.Travel:0.00} time={s_step.Timer:0.00}"); } s_step.Active = false; return false; } Vector3 position = body.position; if (position.y < s_step.TargetY) { position.y = Mathf.Min(s_step.TargetY, position.y + Plugin.StepUpSpeed.Value * dt); body.position = position; } Vector3 linearVelocity = body.linearVelocity; if (linearVelocity.y < 0f) { linearVelocity.y = 0f; body.linearVelocity = linearVelocity; } ((Character)player).m_lastGroundTouch = 0f; return true; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }