Please disclose if your mod was created primarily 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 ValheimClimbingMod v1.0.0
plugins/Valheim-Climbing-Mod.dll
Decompiled 4 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Animations; using UnityEngine.Playables; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 Valheim_Climbing_Mod { public static class ClimbAnimationController { private enum ClipDirection { Up, Down } private class PlayerAnimationState { public Animator Animator; public PlayableGraph Graph; public AnimationClipPlayable UpPlayable; public AnimationClipPlayable DownPlayable; public AnimationMixerPlayable Mixer; public ClipDirection CurrentDirection; } private static readonly Dictionary<Player, PlayerAnimationState> ActiveStates = new Dictionary<Player, PlayerAnimationState>(); private static ManualLogSource _logger; private static AnimationClip _upClip; private static AnimationClip _downClip; private static bool _initialized; private static readonly FieldInfo AnimatorField = AccessTools.Field(typeof(Character), "m_animator"); public static void Initialize(ManualLogSource logger) { if (_initialized) { return; } _initialized = true; _logger = logger; _upClip = LoadClip("climbingup"); _downClip = LoadClip("climbingdown"); if ((Object)(object)_upClip == (Object)null || (Object)(object)_downClip == (Object)null) { ManualLogSource logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)"Climbing animation clips were not loaded. Default animations will be used instead."); } } } private static AnimationClip LoadClip(string bundleName) { try { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (string.IsNullOrEmpty(directoryName)) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)("Unable to determine plugin directory while loading '" + bundleName + "'.")); } return null; } string text = Path.Combine(directoryName, bundleName); if (!File.Exists(text)) { ManualLogSource logger2 = _logger; if (logger2 != null) { logger2.LogWarning((object)("Animation asset bundle '" + text + "' was not found.")); } return null; } AssetBundle val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { ManualLogSource logger3 = _logger; if (logger3 != null) { logger3.LogWarning((object)("Failed to load AssetBundle from '" + text + "'.")); } return null; } try { AnimationClip val2 = val.LoadAsset<AnimationClip>(bundleName); if ((Object)(object)val2 == (Object)null) { AnimationClip[] array = val.LoadAllAssets<AnimationClip>(); if (array.Length != 0) { val2 = array[0]; } } if ((Object)(object)val2 == (Object)null) { ManualLogSource logger4 = _logger; if (logger4 != null) { logger4.LogWarning((object)("No AnimationClip found inside '" + bundleName + "'.")); } } return val2; } finally { val.Unload(false); } } catch (Exception arg) { ManualLogSource logger5 = _logger; if (logger5 != null) { logger5.LogError((object)$"Failed to load animation clip '{bundleName}': {arg}"); } return null; } } private static Animator GetAnimator(Player player) { if (AnimatorField != null) { object? value = AnimatorField.GetValue(player); Animator val = (Animator)((value is Animator) ? value : null); if (val != null && (Object)(object)val != (Object)null) { return val; } } return ((Component)player).GetComponentInChildren<Animator>(); } public static void Begin(Player player) { //IL_0063: 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_0071: 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_0085: 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) //IL_0090: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00d6: 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_00e2: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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_0111: 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_0118: 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) if ((Object)(object)_upClip == (Object)null || (Object)(object)_downClip == (Object)null || ActiveStates.ContainsKey(player)) { return; } Animator animator = GetAnimator(player); if ((Object)(object)animator == (Object)null) { ManualLogSource logger = _logger; if (logger != null) { logger.LogWarning((object)"Unable to locate player Animator component for climbing animations."); } return; } PlayableGraph val = PlayableGraph.Create($"ClimbGraph_{player.GetPlayerID()}"); ((PlayableGraph)(ref val)).SetTimeUpdateMode((DirectorUpdateMode)1); AnimationClipPlayable val2 = AnimationClipPlayable.Create(val, _upClip); ((AnimationClipPlayable)(ref val2)).SetApplyFootIK(true); AnimationClipPlayable val3 = AnimationClipPlayable.Create(val, _downClip); ((AnimationClipPlayable)(ref val3)).SetApplyFootIK(true); AnimationMixerPlayable val4 = AnimationMixerPlayable.Create(val, 2); ((PlayableGraph)(ref val)).Connect<AnimationClipPlayable, AnimationMixerPlayable>(val2, 0, val4, 0); ((PlayableGraph)(ref val)).Connect<AnimationClipPlayable, AnimationMixerPlayable>(val3, 0, val4, 1); PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(val4, 0, 1f); PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(val4, 1, 0f); PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationMixerPlayable>(AnimationPlayableOutput.Create(val, "ClimbOutput", animator), val4); ((PlayableGraph)(ref val)).Play(); ActiveStates[player] = new PlayerAnimationState { Animator = animator, Graph = val, UpPlayable = val2, DownPlayable = val3, Mixer = val4, CurrentDirection = ClipDirection.Up }; } public static void Update(Player player, float verticalInput, float animationSpeedMultiplier = 0.9f) { if (ActiveStates.TryGetValue(player, out var value)) { if (Mathf.Abs(verticalInput) <= 0.05f) { Pause(value); } else if (verticalInput > 0f) { SwitchClip(value, ClipDirection.Up, Mathf.Abs(verticalInput), animationSpeedMultiplier); } else { SwitchClip(value, ClipDirection.Down, Mathf.Abs(verticalInput), animationSpeedMultiplier); } } } private static void Pause(PlayerAnimationState state) { //IL_0001: 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) PlayableExtensions.SetSpeed<AnimationClipPlayable>(state.UpPlayable, 0.0); PlayableExtensions.SetSpeed<AnimationClipPlayable>(state.DownPlayable, 0.0); } private static void SwitchClip(PlayerAnimationState state, ClipDirection direction, float speed, float animationSpeedMultiplier) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_0086: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) float num = Mathf.Max(speed * Mathf.Max(animationSpeedMultiplier, 0.01f), 0.25f); if (direction == ClipDirection.Up) { if (state.CurrentDirection != 0) { PlayableExtensions.SetTime<AnimationClipPlayable>(state.UpPlayable, 0.0); } PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(state.Mixer, 0, 1f); PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(state.Mixer, 1, 0f); PlayableExtensions.SetSpeed<AnimationClipPlayable>(state.UpPlayable, (double)num); PlayableExtensions.SetSpeed<AnimationClipPlayable>(state.DownPlayable, 0.0); } else { if (state.CurrentDirection != ClipDirection.Down) { PlayableExtensions.SetTime<AnimationClipPlayable>(state.DownPlayable, 0.0); } PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(state.Mixer, 0, 0f); PlayableExtensions.SetInputWeight<AnimationMixerPlayable>(state.Mixer, 1, 1f); PlayableExtensions.SetSpeed<AnimationClipPlayable>(state.DownPlayable, (double)num); PlayableExtensions.SetSpeed<AnimationClipPlayable>(state.UpPlayable, 0.0); } state.CurrentDirection = direction; if (!((PlayableGraph)(ref state.Graph)).IsPlaying()) { ((PlayableGraph)(ref state.Graph)).Play(); } } public static void End(Player player) { if (ActiveStates.TryGetValue(player, out var value)) { if (((PlayableGraph)(ref value.Graph)).IsValid()) { ((PlayableGraph)(ref value.Graph)).Destroy(); } ActiveStates.Remove(player); } } public static void Cleanup(Player player) { End(player); } public static bool IsActive(Player player) { return ActiveStates.ContainsKey(player); } } public static class ClimbingConfig { public const float DETECTION_DISTANCE = 0.6f; public const float MIN_SURFACE_ANGLE = 10f; public const float MAX_SURFACE_ANGLE = 240f; public const float STICK_FORCE = 0.5f; public const float SURFACE_TARGET_DISTANCE = 0.18f; public const float SURFACE_REPEL_FORCE = 0.15f; public const float FACE_SURFACE_TURN_SPEED = 10f; public const float STEEP_SURFACE_ANGLE = 90f; public const float SHALLOW_SURFACE_ANGLE = 10f; public const float STEEP_SURFACE_SPEED_FACTOR = 1f; public const float SHALLOW_SURFACE_SPEED_FACTOR = 1.6f; public const float REPEL_DISABLE_SURFACE_ANGLE = 25f; public const float REPEL_FULL_STRENGTH_SURFACE_ANGLE = 60f; public static float CLIMB_SPEED_UP => ClimbingModPlugin.ClimbSpeedUp?.Value ?? 1f; public static float CLIMB_SPEED_DOWN => ClimbingModPlugin.ClimbSpeedDown?.Value ?? 1f; public static float STAMINA_DRAIN_PER_SECOND => ClimbingModPlugin.StaminaDrainPerSecond?.Value ?? 3f; } [BepInPlugin("com.rotceh.valheimclimbingmod", "Valheim Climbing Mod", "1.0.0")] public class ClimbingModPlugin : BaseUnityPlugin { public static ConfigEntry<KeyCode> ClimbKey; public static ConfigEntry<float> ClimbSpeedUp; public static ConfigEntry<float> ClimbSpeedDown; public static ConfigEntry<float> StaminaDrainPerSecond; public static ConfigEntry<bool> ToggleClimbKey; private void Awake() { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) ClimbKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ClimbKey", (KeyCode)308, "Key to trigger climbing (default: LeftAlt)"); ToggleClimbKey = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ToggleClimbKey", false, "When enabled, pressing the climb key toggles climbing instead of requiring the key to be held."); ClimbSpeedUp = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "ClimbSpeedUp", 1f, "Base climb speed when moving upward (W)."); ClimbSpeedDown = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "ClimbSpeedDown", 1f, "Base climb speed when moving downward or sideways (S/A/D)."); StaminaDrainPerSecond = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "StaminaDrainPerSecond", 2f, "Stamina drained per second while climbing (scaled by movement)."); new Harmony("com.rotceh.valheimclimbingmod").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Valheim Climbing Mod loaded. Climb key: {ClimbKey.Value}"); ClimbAnimationController.Initialize(((BaseUnityPlugin)this).Logger); } } [HarmonyPatch(typeof(Player), "FixedUpdate")] public class Player_FixedUpdate_Patch { [CompilerGenerated] private sealed class <EnumerateProbeDirections>d__12 : IEnumerable<Vector3>, IEnumerable, IEnumerator<Vector3>, IDisposable, IEnumerator { private int <>1__state; private Vector3 <>2__current; private int <>l__initialThreadId; private Vector3 preferredNormal; public Vector3 <>3__preferredNormal; private Player player; public Player <>3__player; private Transform <t>5__2; private Vector3[] <>7__wrap2; private int <>7__wrap3; Vector3 IEnumerator<Vector3>.Current { [DebuggerHidden] get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return <>2__current; } } [DebuggerHidden] public <EnumerateProbeDirections>d__12(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <t>5__2 = null; <>7__wrap2 = null; <>1__state = -2; } private bool MoveNext() { //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_00ab: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: 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_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (preferredNormal != Vector3.zero) { <>2__current = -((Vector3)(ref preferredNormal)).normalized; <>1__state = 1; return true; } goto IL_0072; case 1: <>1__state = -1; goto IL_0072; case 2: <>1__state = -1; <>2__current = -<t>5__2.forward; <>1__state = 3; return true; case 3: <>1__state = -1; <>2__current = <t>5__2.up; <>1__state = 4; return true; case 4: <>1__state = -1; <>2__current = -<t>5__2.up; <>1__state = 5; return true; case 5: <>1__state = -1; <>2__current = <t>5__2.right; <>1__state = 6; return true; case 6: <>1__state = -1; <>2__current = -<t>5__2.right; <>1__state = 7; return true; case 7: <>1__state = -1; <>7__wrap2 = WorldProbeDirections; <>7__wrap3 = 0; break; case 8: { <>1__state = -1; <>7__wrap3++; break; } IL_0072: <t>5__2 = ((Component)player).transform; <>2__current = <t>5__2.forward; <>1__state = 2; return true; } if (<>7__wrap3 < <>7__wrap2.Length) { Vector3 val = <>7__wrap2[<>7__wrap3]; <>2__current = val; <>1__state = 8; return true; } <>7__wrap2 = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<Vector3> IEnumerable<Vector3>.GetEnumerator() { //IL_0037: 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) <EnumerateProbeDirections>d__12 <EnumerateProbeDirections>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <EnumerateProbeDirections>d__ = this; } else { <EnumerateProbeDirections>d__ = new <EnumerateProbeDirections>d__12(0); } <EnumerateProbeDirections>d__.player = <>3__player; <EnumerateProbeDirections>d__.preferredNormal = <>3__preferredNormal; return <EnumerateProbeDirections>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<Vector3>)this).GetEnumerator(); } } private static readonly int SurfaceLayerMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "terrain", "piece", "Default_small" }); private static readonly float[] ProbeHeights = new float[3] { 1.2f, 0.7f, 0.2f }; private static readonly Vector3[] WorldProbeDirections = (Vector3[])(object)new Vector3[6] { Vector3.up, Vector3.down, Vector3.right, Vector3.left, Vector3.forward, Vector3.back }; private static MethodInfo _takeInputMethod; private static bool CallTakeInput(Player player) { if (_takeInputMethod == null) { _takeInputMethod = typeof(Player).GetMethod("TakeInput", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (_takeInputMethod != null) { return (bool)_takeInputMethod.Invoke(player, null); } return true; } private static void Postfix(Player __instance) { //IL_00a2: 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_00f2: 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_0100: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return; } if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { HandleRemotePlayer(__instance); } else { if (((Character)__instance).IsDead() || ((Character)__instance).InCutscene() || ((Character)__instance).IsTeleporting()) { return; } ClimbingState.ClimbingData orCreate = ClimbingState.GetOrCreate(__instance); bool flag = ClimbingModPlugin.ToggleClimbKey?.Value ?? false; bool flag2 = false; if (CallTakeInput(__instance)) { if (flag) { if (Input.GetKeyDown(ClimbingModPlugin.ClimbKey.Value)) { orCreate.toggleActive = !orCreate.toggleActive; if (!orCreate.toggleActive && orCreate.isClimbing) { StopClimbing(__instance, orCreate); } } flag2 = orCreate.toggleActive; } else { flag2 = Input.GetKey(ClimbingModPlugin.ClimbKey.Value); if (!flag2) { orCreate.toggleActive = false; } } } else { flag2 = orCreate.toggleActive; } Vector3 normal; if (!orCreate.isClimbing) { if (flag2) { TryStartClimbing(__instance, orCreate); } } else if (!flag2) { StopClimbing(__instance, orCreate); } else if (!PlayerHasClimbStamina(__instance)) { StopClimbing(__instance, orCreate); } else if (TryGetSurfaceNormal(__instance, out normal, orCreate.surfaceNormal)) { orCreate.surfaceNormal = normal; } else { StopClimbing(__instance, orCreate); } } } private static void HandleRemotePlayer(Player player) { ZNetView component = ((Component)player).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid()) { bool @bool = component.GetZDO().GetBool("IsClimbing", false); bool flag = ClimbAnimationController.IsActive(player); if (@bool && !flag) { ClimbAnimationController.Begin(player); } else if (!@bool && flag) { ClimbAnimationController.End(player); } if (@bool) { ClimbAnimationController.Update(player, 0f, 1f); } } } private static void TryStartClimbing(Player player, ClimbingState.ClimbingData climbData) { //IL_000e: 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_001e: Unknown result type (might be due to invalid IL or missing references) if (PlayerHasClimbStamina(player) && TryGetSurfaceNormal(player, out var normal)) { StartClimbing(player, climbData, normal); } } private static bool PlayerHasClimbStamina(Player player) { return player.GetStamina() > 0.25f; } private static void StartClimbing(Player player, ClimbingState.ClimbingData climbData, Vector3 surfaceNormal) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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) climbData.isClimbing = true; climbData.surfaceNormal = surfaceNormal; ZNetView component = ((Component)player).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.GetZDO().Set("IsClimbing", true); } Rigidbody component2 = ((Component)player).GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { climbData.wasGravityEnabled = component2.useGravity; component2.useGravity = false; component2.linearVelocity = Vector3.zero; component2.angularVelocity = Vector3.zero; } ClimbAnimationController.Begin(player); } public static void StopClimbing(Player player, ClimbingState.ClimbingData climbData) { climbData.isClimbing = false; ZNetView component = ((Component)player).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.GetZDO().Set("IsClimbing", false); } Rigidbody component2 = ((Component)player).GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { component2.useGravity = climbData.wasGravityEnabled; } ClimbAnimationController.End(player); } private static bool TryGetSurfaceNormal(Player player, out Vector3 normal, Vector3 preferredNormal = default(Vector3)) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_0065: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) float num = 1.35f; float[] probeHeights = ProbeHeights; RaycastHit val2 = default(RaycastHit); foreach (float num2 in probeHeights) { Vector3 val = ((Component)player).transform.position + Vector3.up * num2; foreach (Vector3 item in EnumerateProbeDirections(player, preferredNormal)) { if (Physics.SphereCast(val, 0.4f, item, ref val2, num, SurfaceLayerMask)) { float num3 = Vector3.Angle(Vector3.up, ((RaycastHit)(ref val2)).normal); if (num3 >= 10f && num3 <= 240f) { normal = ((RaycastHit)(ref val2)).normal; return true; } } } } normal = Vector3.zero; return false; } [IteratorStateMachine(typeof(<EnumerateProbeDirections>d__12))] private static IEnumerable<Vector3> EnumerateProbeDirections(Player player, Vector3 preferredNormal) { //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) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <EnumerateProbeDirections>d__12(-2) { <>3__player = player, <>3__preferredNormal = preferredNormal }; } } [HarmonyPatch(typeof(Character), "UpdateMotion")] internal class Character_UpdateMotion_Patch { private static readonly int SurfaceLayerMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "terrain", "piece", "Default_small" }); private static bool Prefix(Character __instance) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && ClimbingState.IsClimbing(val)) { HandleClimbingMovement(val); return false; } return true; } private static void HandleClimbingMovement(Player player) { //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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_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_0073: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_0122: 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_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_0135: 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_0147: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_00bf: 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_00c9: 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) Rigidbody component = ((Component)player).GetComponent<Rigidbody>(); if (!((Object)(object)component == (Object)null)) { component.useGravity = false; float axis = Input.GetAxis("Vertical"); float axis2 = Input.GetAxis("Horizontal"); Vector3 val = Vector3.zero; ClimbingState.ClimbingData orCreate = ClimbingState.GetOrCreate(player); Vector3 val2 = ((orCreate.surfaceNormal != Vector3.zero) ? orCreate.surfaceNormal : (-((Component)player).transform.forward)); float num = CalculateSlopeSpeedFactor(val2); Vector3 val3 = ResolveClimbDirection(val2, ((Component)player).transform); Vector3 val4 = ResolveLateralDirection(val2, val3); if (Mathf.Abs(axis) > 0.1f && ((Vector3)(ref val3)).sqrMagnitude > 0.01f) { float num2 = ((axis > 0f) ? ClimbingConfig.CLIMB_SPEED_UP : ClimbingConfig.CLIMB_SPEED_DOWN); val += val3 * num2 * axis * num; } if (Mathf.Abs(axis2) > 0.1f && ((Vector3)(ref val4)).sqrMagnitude > 0.01f) { val += val4 * ClimbingConfig.CLIMB_SPEED_DOWN * axis2; } Vector3 val5 = -val2; Vector3 normalized = ((Vector3)(ref val5)).normalized; val += normalized * 0.5f; ApplySurfaceRepulsion(player, val2, ref val); AlignWithSurface(player, val2); component.linearVelocity = val; float verticalInput = ResolveAnimationInput(axis, axis2); ClimbAnimationController.Update(player, verticalInput, num); ApplyClimbStaminaDrain(player, axis, axis2); } } private static float CalculateSlopeSpeedFactor(Vector3 surfaceNormal) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) float num = Vector3.Angle(Vector3.up, surfaceNormal); float num2 = Mathf.InverseLerp(90f, 10f, num); return Mathf.Clamp(Mathf.Lerp(1f, 1.6f, num2), 0.1f, 3f); } private static Vector3 ResolveClimbDirection(Vector3 surfaceNormal, Transform transform) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0035: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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) Vector3 val = Vector3.ProjectOnPlane(Vector3.up, surfaceNormal); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.ProjectOnPlane(transform.forward, surfaceNormal); } if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.Cross(surfaceNormal, transform.right); } if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f)) { return Vector3.forward; } return ((Vector3)(ref val)).normalized; } private static Vector3 ResolveLateralDirection(Vector3 surfaceNormal, Vector3 climbDirection) { //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) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_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_001c: 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_0038: 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 val = Vector3.Cross(surfaceNormal, climbDirection); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.Cross(surfaceNormal, Vector3.up); } if (!(((Vector3)(ref val)).sqrMagnitude > 0.01f)) { return Vector3.zero; } return ((Vector3)(ref val)).normalized; } private static float ResolveAnimationInput(float forwardInput, float rightInput) { if (Mathf.Abs(forwardInput) > 0.05f) { return forwardInput; } if (!(Mathf.Abs(rightInput) > 0.1f)) { return 0f; } return Mathf.Abs(rightInput); } private static void ApplyClimbStaminaDrain(Player player, float forwardInput, float rightInput) { float sTAMINA_DRAIN_PER_SECOND = ClimbingConfig.STAMINA_DRAIN_PER_SECOND; if (!(sTAMINA_DRAIN_PER_SECOND <= 0f)) { float num = Mathf.Clamp01(Mathf.Max(Mathf.Abs(forwardInput), Mathf.Abs(rightInput))); float num2 = ((num <= 0.05f) ? 0.1f : Mathf.Lerp(0.5f, 1f, num)); ((Character)player).UseStamina(num2 * sTAMINA_DRAIN_PER_SECOND * Time.deltaTime); } } private static void ApplySurfaceRepulsion(Player player, Vector3 surfaceNormal, ref Vector3 climbVelocity) { //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) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_00a5: 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) if (surfaceNormal == Vector3.zero) { return; } Vector3 val = ((Component)player).transform.position + Vector3.up * 1f; float num = 0.93f; float num2 = Vector3.Angle(Vector3.up, surfaceNormal); float num3 = Mathf.Clamp01(Mathf.InverseLerp(25f, 60f, num2)); RaycastHit val2 = default(RaycastHit); if (!(num3 <= 0.001f) && Physics.Raycast(val, -surfaceNormal, ref val2, num, SurfaceLayerMask)) { float num4 = 0.18f - ((RaycastHit)(ref val2)).distance; if (num4 > 0f) { climbVelocity += ((Vector3)(ref surfaceNormal)).normalized * (0.15f * num4 * num3); } } } private static void AlignWithSurface(Player player, Vector3 surfaceNormal) { //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) //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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0062: 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) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_008a: Unknown result type (might be due to invalid IL or missing references) if (!(surfaceNormal == Vector3.zero)) { Vector3 val = -((Vector3)(ref surfaceNormal)).normalized; Vector3 val2 = ((Mathf.Abs(Vector3.Dot(val, Vector3.up)) > 0.95f) ? Vector3.forward : Vector3.up); Vector3 val3 = Vector3.Cross(val2, val); if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val2 = Vector3.right; val3 = Vector3.Cross(val2, val); } ((Vector3)(ref val3)).Normalize(); Vector3 val4 = Vector3.Cross(val, val3); Vector3 val5 = ((Vector3)(ref val4)).normalized; if (((Vector3)(ref val5)).sqrMagnitude < 0.0001f) { val5 = val2; } Quaternion val6 = Quaternion.LookRotation(val, val5); ((Component)player).transform.rotation = Quaternion.Slerp(((Component)player).transform.rotation, val6, Time.deltaTime * 10f); } } } [HarmonyPatch(typeof(Character), "ApplySlide")] internal class Character_ApplySlide_Patch { private static bool Prefix(Character __instance) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && ClimbingState.IsClimbing(val)) { return false; } return true; } } [HarmonyPatch(typeof(Player), "OnDestroy")] internal class Player_OnDestroy_Patch { private static void Postfix(Player __instance) { ClimbingState.Cleanup(__instance); ClimbAnimationController.Cleanup(__instance); } } [HarmonyPatch(typeof(Humanoid), "StartAttack")] internal class Humanoid_StartAttack_Patch { private static bool Prefix(Humanoid __instance) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && ClimbingState.IsClimbing(val)) { return false; } return true; } } [HarmonyPatch(typeof(Character), "Damage")] internal class Character_Damage_Patch { private static void Prefix(Character __instance, ref HitData hit) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (hit == null) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null && ClimbingState.IsClimbing(val)) { if ((int)hit.m_hitType == 3) { hit.m_damage = default(DamageTypes); hit.m_pushForce = 0f; } else if (hit.m_pushForce > 5f) { ClimbingState.ClimbingData orCreate = ClimbingState.GetOrCreate(val); Player_FixedUpdate_Patch.StopClimbing(val, orCreate); } } } } public static class ClimbingState { public class ClimbingData { public bool isClimbing; public Vector3 surfaceNormal = Vector3.zero; public bool wasGravityEnabled = true; public bool toggleActive; } private static Dictionary<Player, ClimbingData> climbingPlayers = new Dictionary<Player, ClimbingData>(); public static ClimbingData GetOrCreate(Player player) { if (!climbingPlayers.ContainsKey(player)) { climbingPlayers[player] = new ClimbingData(); } return climbingPlayers[player]; } public static bool IsClimbing(Player player) { if (climbingPlayers.ContainsKey(player)) { return climbingPlayers[player].isClimbing; } return false; } public static void Cleanup(Player player) { climbingPlayers.Remove(player); } } }