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 PotatoRider v1.0.2
plugins/PotatoRider.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; using UnityEngine.Audio; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace PotatoRider; internal static class Calling { [HarmonyPatch(typeof(Player), "StartDoodadControl")] internal static class Remember { private static void Postfix(Player __instance, IDoodadController shipControl) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Sadle val = (Sadle)(object)((shipControl is Sadle) ? shipControl : null); if (val == null || !Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.GetCharacter())) { return; } Character character = val.GetCharacter(); ZNetView component = ((Component)character).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid()) { return; } ZDO zDO = component.GetZDO(); string text = zDO.GetString(MountIdKey, ""); if (string.IsNullOrEmpty(text)) { text = Guid.NewGuid().ToString("N"); if (!component.IsOwner()) { component.ClaimOwnership(); } zDO.Set(MountIdKey, text); } __instance.m_customData["PotatoRider_LastMount"] = text; Tameable component2 = ((Component)character).GetComponent<Tameable>(); __instance.m_customData["PotatoRider_LastMountName"] = (Object.op_Implicit((Object)(object)component2) ? component2.GetHoverName() : Localization.instance.Localize(character.m_name)); } } [HarmonyPatch(typeof(Player), "StopDoodadControl")] internal static class Stay { private static void Prefix(Player __instance) { if (!StayOn.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } IDoodadController doodadController = __instance.GetDoodadController(); Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null); if (val == null || !Object.op_Implicit((Object)(object)val)) { return; } Character character = val.GetCharacter(); MonsterAI val2 = (Object.op_Implicit((Object)(object)character) ? ((Component)character).GetComponent<MonsterAI>() : null); ZNetView val3 = (Object.op_Implicit((Object)(object)character) ? ((Component)character).GetComponent<ZNetView>() : null); if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val3) || !val3.IsValid() || character.IsDead()) { return; } if (val3.IsOwner()) { val2.SetFollowTarget((GameObject)null); ((BaseAI)val2).SetPatrolPoint(); val3.GetZDO().Set(ZDOVars.s_follow, ""); } else if (!string.IsNullOrEmpty(val3.GetZDO().GetString(ZDOVars.s_follow, ""))) { Tameable component = ((Component)character).GetComponent<Tameable>(); if (component != null) { component.Command((Humanoid)(object)__instance, false); } } } } [HarmonyPatch(typeof(Player), "Update")] internal static class CallKeyPress { private static void Postfix(Player __instance) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (CallOn.Value && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Input.GetKeyDown(CallKey.Value) && TakeInput(__instance) && !((Character)__instance).IsDead()) { Call(__instance); } } } internal static ConfigEntry<bool> CallOn; internal static ConfigEntry<bool> StayOn; internal static ConfigEntry<KeyCode> CallKey; internal static ConfigEntry<int> WhistleVolume; private const string LastMount = "PotatoRider_LastMount"; private const string LastMountName = "PotatoRider_LastMountName"; private static readonly Func<Player, bool> TakeInput = AccessTools.MethodDelegate<Func<Player, bool>>(AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null), (object)null, true); private static readonly int MountIdKey = StringExtensionMethods.GetStableHashCode("PotatoRider_MountId"); private static AudioClip whistle; private static AudioMixerGroup mixer; private static bool mixerLooked; internal static void Bind(ConfigFile config) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown StayOn = config.Bind<bool>("1 - Riding", "Stays where you get off", true, "A mount you get off stays on that spot, like telling a tame to stay, instead of wandering off or trailing after you."); CallOn = config.Bind<bool>("1 - Riding", "Call your mount", true, "The call key whistles for the tame you last rode, and it comes to you, as long as it's close enough to hear (in the area the game has loaded around you)."); CallKey = config.Bind<KeyCode>("1 - Riding", "Call key", (KeyCode)106, "The key that whistles for your mount."); WhistleVolume = config.Bind<int>("1 - Riding", "Whistle volume", 60, new ConfigDescription("How loud the whistle is, in percent, on top of your sound effects volume. 0 is silent.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>())); } private static Character Find(string tag) { foreach (Character allCharacter in Character.GetAllCharacters()) { if (Object.op_Implicit((Object)(object)allCharacter) && !allCharacter.IsPlayer()) { ZNetView component = ((Component)allCharacter).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.GetZDO().GetString(MountIdKey, "") == tag) { return allCharacter; } } } return null; } private static void Call(Player player) { //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0182: 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) if (WhistleVolume.Value > 0) { Whistle(player); } if (!player.m_customData.TryGetValue("PotatoRider_LastMount", out var value) || string.IsNullOrEmpty(value)) { Say(player, "You haven't ridden anything yet", "nothing remembered"); return; } Character val = Find(value); if (!Object.op_Implicit((Object)(object)val)) { player.m_customData.TryGetValue("PotatoRider_LastMountName", out var value2); Say(player, (string.IsNullOrEmpty(value2) ? "Your mount" : value2) + " is out of earshot", "not loaded"); return; } GameObject gameObject = ((Component)val).gameObject; Tameable component = gameObject.GetComponent<Tameable>(); ZNetView component2 = gameObject.GetComponent<ZNetView>(); if (val.IsDead() || !Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2) || !component2.IsValid() || !val.IsTamed()) { Say(player, "Your mount can't come", "not a living tame"); return; } IDoodadController doodadController = player.GetDoodadController(); Sadle val2 = (Sadle)(object)((doodadController is Sadle) ? doodadController : null); if (val2 != null && Object.op_Implicit((Object)(object)val2) && (Object)(object)val2.GetCharacter() == (Object)(object)val) { return; } string text = component2.GetZDO().GetString(ZDOVars.s_follow, ""); if (text != player.GetPlayerName()) { if (!string.IsNullOrEmpty(text)) { component.Command((Humanoid)(object)player, false); } component.Command((Humanoid)(object)player, false); } BaseAI component3 = gameObject.GetComponent<BaseAI>(); if ((Object)(object)component3 != (Object)null) { component3.m_alertedEffects.Create(gameObject.transform.position, gameObject.transform.rotation, gameObject.transform, 1f, -1, default(ZDOID)); } Say(player, component.GetHoverName() + " is coming", "following was '" + text + "'"); } private static void Say(Player player, string text, string why) { ((Character)player).Message((MessageType)2, text, 0, (Sprite)null, false); Plugin.Log.LogInfo((object)("Call: " + text + " (" + why + ")")); } private static void Whistle(Player player) { //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_00bc: 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_013b: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)whistle)) { whistle = MakeWhistle(); } if (!mixerLooked && Object.op_Implicit((Object)(object)ZNetScene.instance)) { mixerLooked = true; string[] array = new string[3] { "sfx_wolf_alerted", "sfx_lox_alerted", "sfx_boar_alerted" }; foreach (string text in array) { GameObject prefab = ZNetScene.instance.GetPrefab(text); AudioSource val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponentInChildren<AudioSource>(true) : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.outputAudioMixerGroup)) { mixer = val.outputAudioMixerGroup; break; } } } GameObject val2 = new GameObject("PotatoRider_Whistle"); val2.transform.position = ((Character)player).GetHeadPoint(); AudioSource obj = val2.AddComponent<AudioSource>(); obj.clip = whistle; obj.outputAudioMixerGroup = mixer; obj.spatialBlend = 0.5f; float num = 0.55f * (float)WhistleVolume.Value / 100f; obj.volume = (Object.op_Implicit((Object)(object)mixer) ? num : (num * AudioMan.GetSFXVolume())); obj.Play(); Object.Destroy((Object)val2, whistle.length + 0.2f); } private static AudioClip MakeWhistle() { (float, float, float, float, float)[] obj = new(float, float, float, float, float)[2] { (0f, 0.13f, 2250f, 2700f, 0f), (0.19f, 0.32f, 2450f, 3150f, 22f) }; float num = 0.55f; float[] array = new float[(int)(44100f * num)]; Random random = new Random(7); float num2 = 0f; (float, float, float, float, float)[] array2 = obj; for (int i = 0; i < array2.Length; i++) { (float, float, float, float, float) tuple = array2[i]; double num3 = 0.0; int num4 = (int)(tuple.Item1 * 44100f); int num5 = (int)(tuple.Item2 * 44100f); for (int j = 0; j < num5 && num4 + j < array.Length; j++) { float num6 = (float)j / 44100f; float num7 = (float)j / (float)num5; float num8 = tuple.Item3 + (tuple.Item4 - tuple.Item3) * Mathf.SmoothStep(0f, 1f, Mathf.Min(1f, num7 * 1.6f)) - ((num7 > 0.8f) ? ((num7 - 0.8f) * 900f) : 0f); num8 += tuple.Item5 * Mathf.Sin((float)Math.PI * 12f * num6); num3 += Math.PI * 2.0 * (double)num8 / 44100.0; float num9 = Mathf.Min(1f, num6 / 0.015f) * Mathf.Min(1f, (tuple.Item2 - num6) / 0.04f); num2 = num2 * 0.85f + (float)(random.NextDouble() * 2.0 - 1.0) * 0.15f; array[num4 + j] += num9 * (0.5f * (float)Math.Sin(num3) + 0.04f * num2); } } AudioClip obj2 = AudioClip.Create("PotatoRider_Whistle", array.Length, 1, 44100, false); obj2.SetData(array, 0); return obj2; } } internal static class MountedCameraRoll { [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] internal static class EyeLevel { private static void Prefix() { Player localPlayer = Player.m_localPlayer; if (Mounted(localPlayer)) { LevelEye(localPlayer); } } } [HarmonyPatch(typeof(GameCamera), "ApplyCameraTilt")] internal static class TrueUp { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { return Transpilers.CallInstead(instructions, (CodeInstruction x) => CodeInstructionExtensions.Calls(x, AccessTools.Method(typeof(Character), "GetVisual", (Type[])null, (Type[])null)), AccessTools.Method(typeof(TrueUp), "UpFrom", (Type[])null, (Type[])null), 1, "Valheim's camera tilt changed."); } private static GameObject UpFrom(Character character) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown Player val = (Player)(object)((character is Player) ? character : null); if (val != null && Mounted(val)) { if (!Object.op_Implicit((Object)(object)level)) { level = new GameObject("PotatoTweaks_Level"); Object.DontDestroyOnLoad((Object)(object)level); } return level; } return character.GetVisual(); } } private static readonly Action<Player> LevelEye = AccessTools.MethodDelegate<Action<Player>>(AccessTools.Method(typeof(Player), "UpdateEyeRotation", (Type[])null, (Type[])null), (object)null, true); private static GameObject level; private static bool Mounted(Player player) { if (Object.op_Implicit((Object)(object)player) && ((Character)player).IsAttached()) { return !((Character)player).IsAttachedToShip(); } return false; } } internal static class Transpilers { internal static List<CodeInstruction> CallInstead(IEnumerable<CodeInstruction> instructions, Func<CodeInstruction, bool> match, MethodInfo replacement, int expected, string changed) { List<CodeInstruction> list = instructions.ToList(); List<CodeInstruction> list2 = list.Where(match).ToList(); if (list2.Count != expected) { throw new InvalidOperationException(changed); } foreach (CodeInstruction item in list2) { item.opcode = OpCodes.Call; item.operand = replacement; } return list; } } internal static class ConfigMove { internal static Dictionary<string, string> Read(string path) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); try { if (!File.Exists(path)) { return dictionary; } string text = ""; string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length == 0 || text2.StartsWith("#")) { continue; } if (text2.StartsWith("[") && text2.EndsWith("]")) { text = text2.Substring(1, text2.Length - 2); continue; } int num = text2.IndexOf('='); if (num > 0) { dictionary[text + "|" + text2.Substring(0, num).Trim()] = text2.Substring(num + 1).Trim(); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't read " + Path.GetFileName(path) + ": " + ex.Message)); } return dictionary; } internal static void Apply(ConfigFile config, Dictionary<string, string> before, Dictionary<string, ConfigEntryBase> moves) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown try { Dictionary<ConfigDefinition, string> dictionary = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(config) as Dictionary<ConfigDefinition, string>; int num = 0; foreach (KeyValuePair<string, ConfigEntryBase> move in moves) { ConfigEntryBase value = move.Value; int num2 = move.Key.IndexOf('|'); ConfigDefinition key = new ConfigDefinition(move.Key.Substring(0, num2), move.Key.Substring(num2 + 1)); if (before.TryGetValue(move.Key, out var value2) && !before.ContainsKey(value.Definition.Section + "|" + value.Definition.Key)) { try { value.BoxedValue = TomlTypeConverter.ConvertToValue(value2, value.SettingType); num++; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't copy '" + value2 + "' into " + value.Definition.Key + ": " + ex.Message)); } } dictionary?.Remove(key); } HashSet<string> hashSet = new HashSet<string>(); foreach (string key2 in moves.Keys) { hashSet.Add(key2.Substring(0, key2.IndexOf('|'))); } if (dictionary != null) { foreach (ConfigDefinition item in new List<ConfigDefinition>(dictionary.Keys)) { if (hashSet.Contains(item.Section)) { dictionary.Remove(item); } } } if (num > 0) { Plugin.Log.LogInfo((object)$"Settings regrouped: {num} values carried over to their new places."); } config.Save(); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("Couldn't carry the old settings over: " + ex2.Message)); } } } internal static class Leap { private sealed class Pose { public Quaternion[] Rotation; public Vector3[] Position; } private static readonly Dictionary<string, string> RunClipOf = new Dictionary<string, string> { { "Wolf", "C_Run" } }; private static readonly FieldRef<Character, Animator> AnimatorOf = AccessTools.FieldRefAccess<Character, Animator>("m_animator"); private static bool broken; private const float BlendSeconds = 0.25f; private static readonly Dictionary<string, Pose> poseOf = new Dictionary<string, Pose>(); private static Animator bonesFor; private static Transform[] bones; private static float blend; internal static void Frame() { //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: 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_0209: Unknown result type (might be due to invalid IL or missing references) if (broken) { return; } try { Player localPlayer = Player.m_localPlayer; object obj; if (Object.op_Implicit((Object)(object)localPlayer)) { IDoodadController doodadController = localPlayer.GetDoodadController(); Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null); if (val != null && Object.op_Implicit((Object)(object)val)) { obj = val.GetCharacter(); goto IL_0037; } } obj = null; goto IL_0037; IL_0037: Character val2 = (Character)obj; string text = (Object.op_Implicit((Object)(object)val2) ? Utils.GetPrefabName(((Component)val2).gameObject) : null); if (!Object.op_Implicit((Object)(object)val2) || !RunClipOf.TryGetValue(text, out var value)) { blend = 0f; return; } Animator val3 = AnimatorOf.Invoke(val2); if (!Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)val3.runtimeAnimatorController)) { return; } if ((Object)(object)bonesFor != (Object)(object)val3) { bonesFor = val3; bones = ((Component)val3).GetComponentsInChildren<Transform>(); blend = 0f; } blend = Mathf.MoveTowards(blend, InJump(val3) ? 1f : 0f, Time.deltaTime / 0.25f); if (blend <= 0f) { return; } if (!poseOf.TryGetValue(text, out var value2)) { AnimationClip val4 = null; AnimationClip[] animationClips = val3.runtimeAnimatorController.animationClips; foreach (AnimationClip val5 in animationClips) { if (Object.op_Implicit((Object)(object)val5) && ((Object)val5).name == value) { val4 = val5; break; } } if (!Object.op_Implicit((Object)(object)val4)) { broken = true; return; } float num = Widest(((Component)val3).gameObject, val4, ((Component)val2).transform); val4.SampleAnimation(((Component)val3).gameObject, num * val4.length); value2 = new Pose { Rotation = (Quaternion[])(object)new Quaternion[bones.Length], Position = (Vector3[])(object)new Vector3[bones.Length] }; for (int j = 0; j < bones.Length; j++) { value2.Rotation[j] = bones[j].localRotation; value2.Position[j] = bones[j].localPosition; } poseOf[text] = value2; Plugin.Log.LogInfo((object)$"Leap: {text} leaps with {value} at {num:0.00} of the clip"); blend = 0f; } else { if (value2.Rotation.Length != bones.Length) { return; } float num2 = Mathf.SmoothStep(0f, 1f, blend); for (int k = 1; k < bones.Length; k++) { if (Object.op_Implicit((Object)(object)bones[k])) { bones[k].localRotation = Quaternion.Slerp(bones[k].localRotation, value2.Rotation[k], num2); bones[k].localPosition = Vector3.Lerp(bones[k].localPosition, value2.Position[k], num2); } } } } catch (Exception ex) { broken = true; Plugin.Log.LogError((object)("Leap is disabled: " + ex.Message)); } } private static bool InJump(Animator animator) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) AnimatorClipInfo[] currentAnimatorClipInfo = animator.GetCurrentAnimatorClipInfo(0); for (int i = 0; i < currentAnimatorClipInfo.Length; i++) { AnimatorClipInfo val = currentAnimatorClipInfo[i]; if (Object.op_Implicit((Object)(object)((AnimatorClipInfo)(ref val)).clip) && ((Object)((AnimatorClipInfo)(ref val)).clip).name == "Jump" && ((AnimatorClipInfo)(ref val)).weight > 0.5f) { return true; } } return false; } private static float Widest(GameObject model, AnimationClip clip, Transform root) { //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_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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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) Transform[] componentsInChildren = model.GetComponentsInChildren<Transform>(); float result = 0f; float num = -1f; for (int i = 0; i < 24; i++) { float num2 = (float)i / 24f; clip.SampleAnimation(model, num2 * clip.length); float num3 = float.MaxValue; float num4 = float.MinValue; Transform[] array = componentsInChildren; foreach (Transform val in array) { float y = root.InverseTransformPoint(val.position).y; num3 = Mathf.Min(num3, y); num4 = Mathf.Max(num4, y); } float num5 = num3 + (num4 - num3) * 0.4f; float num6 = float.MaxValue; float num7 = float.MinValue; array = componentsInChildren; foreach (Transform val2 in array) { Vector3 val3 = root.InverseTransformPoint(val2.position); if (!(val3.y > num5)) { num6 = Mathf.Min(num6, val3.z); num7 = Mathf.Max(num7, val3.z); } } if (num7 - num6 > num) { num = num7 - num6; result = num2; } } return result; } } internal static class MountIcon { [HarmonyPatch(typeof(Hud), "UpdateMount")] internal static class OwnIcon { private static readonly FieldRef<Hud, Image> Icon = AccessTools.FieldRefAccess<Hud, Image>("m_mountIcon"); private static void Postfix(Hud __instance, Player player) { Sadle val = (Sadle)(Object.op_Implicit((Object)(object)player) ? /*isinst with value type is only supported in some contexts*/: null); if (!Object.op_Implicit((Object)(object)val) || (Object.op_Implicit((Object)(object)val.m_mountIcon) && (Object)(object)val.m_mountIcon != (Object)(object)LoxIcon())) { return; } Character character = val.GetCharacter(); if (Object.op_Implicit((Object)(object)character) && !(Utils.GetPrefabName(((Component)character).gameObject) == "Lox")) { Sprite val2 = IconFor(character); if (Object.op_Implicit((Object)(object)val2)) { Icon.Invoke(__instance).overrideSprite = val2; } } } } private static readonly Dictionary<string, Sprite> icons = new Dictionary<string, Sprite>(); private static Sprite loxIcon; private static bool loxLooked; private static Sprite LoxIcon() { if (!loxLooked && Object.op_Implicit((Object)(object)ZNetScene.instance)) { loxLooked = true; GameObject prefab = ZNetScene.instance.GetPrefab("Lox"); Sadle val = ((!Object.op_Implicit((Object)(object)prefab)) ? null : prefab.GetComponent<Tameable>()?.m_saddle); loxIcon = (Object.op_Implicit((Object)(object)val) ? val.m_mountIcon : null); } return loxIcon; } private static Sprite IconFor(Character mount) { //IL_0057: 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_0070: Unknown result type (might be due to invalid IL or missing references) string prefabName = Utils.GetPrefabName(((Component)mount).gameObject); if (icons.TryGetValue(prefabName, out var value)) { return value; } value = null; try { GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefab(prefabName) : null); if (Object.op_Implicit((Object)(object)val)) { value = RenderManager.Instance.Render(val, Quaternion.Euler(10f, 0f, 0f) * Quaternion.Euler(0f, 55f, 0f)); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Mount icon for " + prefabName + " couldn't be rendered: " + ex.GetBaseException().Message)); } icons[prefabName] = value; return value; } } internal static class MountedBowSpine { private const string BetterArcheryId = "ishid4.mods.betterarchery"; private static Action<Player> nockedArrow; internal static void Enable(Harmony harmony) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown if (Chainloader.PluginInfos.ContainsKey("ishid4.mods.betterarchery")) { Type type = AccessTools.TypeByName("BetterArchery.Player_LateUpdate_Patch"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "Postfix", (Type[])null, (Type[])null)); Type type2 = AccessTools.TypeByName("BetterArchery.NockedArrow"); MethodInfo methodInfo2 = ((type2 == null) ? null : AccessTools.Method(type2, "LateUpdate", new Type[1] { typeof(Player) }, (Type[])null)); if (methodInfo == null || methodInfo2 == null) { throw new InvalidOperationException("Better Archery's body turn changed."); } nockedArrow = AccessTools.MethodDelegate<Action<Player>>(methodInfo2, (object)null, true); harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(MountedBowSpine), "SkipWhileMounted", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static bool SkipWhileMounted(Player __0) { if (!Object.op_Implicit((Object)(object)__0) || (Object)(object)__0 != (Object)(object)Player.m_localPlayer || !((Character)__0).IsAttached() || ((Character)__0).IsAttachedToShip()) { return true; } nockedArrow(__0); return false; } } [BepInPlugin("potato.rider", "PotatoRider", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Id = "potato.rider"; public const string Version = "1.0.2"; internal static ManualLogSource Log; private Harmony harmony; private void LateUpdate() { Leap.Frame(); } private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Dictionary<string, string> before = ConfigMove.Read(((BaseUnityPlugin)this).Config.ConfigFilePath); harmony = new Harmony("potato.rider"); Patch(typeof(MountedCameraRoll.EyeLevel)); Patch(typeof(MountedCameraRoll.TrueUp)); Patch(typeof(RiddenHorse.HoldsBack)); Patch(typeof(MountIcon.OwnIcon)); Steering.Bind(((BaseUnityPlugin)this).Config); Patch(typeof(Steering.Keyboard)); Patch(typeof(Steering.Turning)); Patch(typeof(Steering.BuildUp)); Patch(typeof(Steering.Look)); RideAnywhere.Bind(((BaseUnityPlugin)this).Config); Patch(typeof(RideAnywhere.Mount)); Patch(typeof(RideAnywhere.Prompt)); Calling.Bind(((BaseUnityPlugin)this).Config); Dictionary<string, ConfigEntryBase> moves = new Dictionary<string, ConfigEntryBase> { { "1 - Steering|Steer with the keys", (ConfigEntryBase)(object)Steering.Keys }, { "1 - Steering|Turn speed percent", (ConfigEntryBase)(object)Steering.TurnPercent }, { "1 - Steering|Seconds to full trot", (ConfigEntryBase)(object)Steering.TrotSeconds }, { "2 - Camera|Turns with the horse", (ConfigEntryBase)(object)Steering.CameraFollows }, { "3 - Bow|Camera stops at the bow arc", (ConfigEntryBase)(object)Steering.BowLock }, { "3 - Bow|Margin inside the arc", (ConfigEntryBase)(object)Steering.EdgeMargin }, { "4 - Mounting|Ride from anywhere on the animal", (ConfigEntryBase)(object)RideAnywhere.Enabled }, { "4 - Mounting|Ride key", (ConfigEntryBase)(object)RideAnywhere.Key }, { "4 - Mounting|Stays where you get off", (ConfigEntryBase)(object)Calling.StayOn }, { "5 - Calling|Call your mount", (ConfigEntryBase)(object)Calling.CallOn }, { "5 - Calling|Call key", (ConfigEntryBase)(object)Calling.CallKey }, { "5 - Calling|Whistle volume", (ConfigEntryBase)(object)Calling.WhistleVolume } }; ConfigMove.Apply(((BaseUnityPlugin)this).Config, before, moves); Patch(typeof(Calling.Remember)); Patch(typeof(Calling.Stay)); Patch(typeof(Calling.CallKeyPress)); Patch(typeof(Smoothing.On)); Patch(typeof(Smoothing.Off)); Run("Better Archery's body turn leaves a mounted rider to the riding mod", delegate { MountedBowSpine.Enable(harmony); }); } private void Patch(Type type) { try { harmony.CreateClassProcessor(type).Patch(); } catch (Exception ex) { Log.LogError((object)(type.Name + " is disabled: " + ex.GetBaseException().Message)); } } private void Run(string name, Action action) { try { action(); } catch (Exception ex) { Log.LogError((object)(name + ": disabled (" + ex.GetBaseException().Message + ")")); } } } internal static class RiddenHorse { [HarmonyPatch(typeof(Humanoid), "StartAttack")] internal static class HoldsBack { private static bool Prefix(Humanoid __instance, ref bool __result) { if (__instance is Player || !((Character)__instance).HaveRider()) { return true; } if (!Utils.GetPrefabName(((Component)__instance).gameObject).StartsWith("rae_OdinHorse", StringComparison.OrdinalIgnoreCase)) { return true; } __result = false; return false; } } } internal static class RideAnywhere { [HarmonyPatch(typeof(Player), "Interact")] internal static class Mount { private static bool Prefix(Player __instance, GameObject go, bool hold) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!Enabled.Value || MountUpAdjusting() || hold || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || ((Character)__instance).IsAttached() || !Input.GetKey(Key.Value)) { return true; } Sadle val = Rideable(go); if (!Object.op_Implicit((Object)(object)val)) { return true; } val.Interact((Humanoid)(object)__instance, false, false); return false; } } [HarmonyPatch(typeof(Tameable), "GetHoverText")] internal static class Prompt { private static void Postfix(Tameable __instance, ref string __result) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (Enabled.Value && !MountUpAdjusting() && !string.IsNullOrEmpty(__result) && Object.op_Implicit((Object)(object)Rideable(((Component)__instance).gameObject))) { __result += Localization.instance.Localize("\n[<color=yellow><b>" + KeyName(Key.Value) + " + $KEY_Use</b></color>] Ride"); } } } internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<KeyCode> Key; private static readonly Func<Tameable, bool> HaveSaddle = AccessTools.MethodDelegate<Func<Tameable, bool>>(AccessTools.Method(typeof(Tameable), "HaveSaddle", (Type[])null, (Type[])null), (object)null, true); private static ConfigEntry<bool> mountUpAdjust; private static bool mountUpLooked; internal static void Bind(ConfigFile config) { Enabled = config.Bind<bool>("1 - Riding", "Ride from anywhere on the animal", true, "Hold the ride key and press Use anywhere on a tamed, saddled animal to get on, not just on the saddle. Helps with big animals whose body hides the saddle."); Key = config.Bind<KeyCode>("1 - Riding", "Ride key", (KeyCode)308, "The key held with Use to get on from anywhere on the animal."); } private static Sadle Rideable(GameObject go) { Character val = (Object.op_Implicit((Object)(object)go) ? go.GetComponentInParent<Character>() : null); if (!Object.op_Implicit((Object)(object)val) || val.IsPlayer() || !val.IsTamed() || val.IsDead()) { return null; } Tameable component = ((Component)val).GetComponent<Tameable>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.m_saddle) || !HaveSaddle(component)) { return null; } if (!component.m_saddle.HaveValidUser()) { return component.m_saddle; } return null; } private static bool MountUpAdjusting() { if (!mountUpLooked) { mountUpLooked = true; if (Chainloader.PluginInfos.TryGetValue("meldurson.MountUpRestored", out var value) && Object.op_Implicit((Object)(object)value.Instance)) { value.Instance.Config.TryGetEntry<bool>("Custom Mounts", "Enable Adjust Custom Mounts", ref mountUpAdjust); } } if (mountUpAdjust != null) { return mountUpAdjust.Value; } return false; } private unsafe static string KeyName(KeyCode k) { //IL_0000: 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_0024: Expected I4, but got Unknown switch (k - 303) { case 4: case 5: return "Alt"; case 2: case 3: return "Ctrl"; case 0: case 1: return "Shift"; default: return ((object)(*(KeyCode*)(&k))/*cast due to .constrained prefix*/).ToString(); } } } internal static class Smoothing { [HarmonyPatch(typeof(Player), "StartDoodadControl")] internal static class On { private static void Postfix(Player __instance, IDoodadController shipControl) { //IL_0042: 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) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Sadle val = (Sadle)(object)((shipControl is Sadle) ? shipControl : null); if (val != null && Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.GetCharacter())) { Rigidbody component = ((Component)val.GetCharacter()).GetComponent<Rigidbody>(); if (Object.op_Implicit((Object)(object)component) && (int)component.interpolation == 0) { before[component] = component.interpolation; component.interpolation = (RigidbodyInterpolation)1; } } } } [HarmonyPatch(typeof(Player), "StopDoodadControl")] internal static class Off { private static void Prefix(Player __instance) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || before.Count == 0) { return; } foreach (KeyValuePair<Rigidbody, RigidbodyInterpolation> item in before) { if (Object.op_Implicit((Object)(object)item.Key)) { item.Key.interpolation = item.Value; } } before.Clear(); } } private static readonly Dictionary<Rigidbody, RigidbodyInterpolation> before = new Dictionary<Rigidbody, RigidbodyInterpolation>(); } internal static class Steering { private enum Speed { Stop, Walk, Run, Turn, NoChange } [HarmonyPatch(typeof(Sadle), "ApplyControlls")] internal static class Keyboard { [HarmonyPriority(600)] private static void Prefix(Sadle __instance, ref Vector3 moveDir, ref Vector3 lookDir, bool run, ref bool block) { //IL_0066: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (!Keys.Value || (Object)(object)Ridden(Player.m_localPlayer) != (Object)(object)__instance) { if ((Object)(object)steered == (Object)(object)__instance) { steered = null; } return; } steered = __instance; turnInput = Mathf.Clamp(moveDir.x, -1f, 1f); bool num = moveDir.z > 0.5f; lookDir = Ahead(__instance.GetCharacter()); if (num) { moveDir = new Vector3(0f, 0f, 1f); } else if (turnInput != 0f && !run) { Speed speed = SpeedOf(__instance); if (speed == Speed.Walk || speed == Speed.Run) { moveDir = new Vector3(0f, 0f, -1f); return; } moveDir = Vector3.zero; block = true; } else { moveDir = new Vector3(0f, 0f, -1f); } } } [HarmonyPatch(typeof(Character), "UpdateRotation")] internal static class Turning { private static bool Prefix(Character __instance, float dt, ref float __result) { //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_00a5: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) Sadle steered = Steering.steered; if (!Object.op_Implicit((Object)(object)steered) || !Keys.Value || (Object)(object)__instance != (Object)(object)steered.GetCharacter() || !steered.HaveValidUser()) { return true; } turnEased = Mathf.MoveTowards(turnEased, turnInput, dt / 0.25f); float num = ((SpeedOf(steered) == Speed.Run) ? __instance.m_runTurnSpeed : __instance.m_turnSpeed) * (float)TurnPercent.Value / 100f; float num2 = turnEased * num * dt; if (num2 != 0f) { Quaternion val = Quaternion.Euler(0f, num2, 0f); ((Component)__instance).transform.rotation = val * ((Component)__instance).transform.rotation; if (MoveDir.Invoke(__instance) != Vector3.zero) { MoveDir.Invoke(__instance) = val * MoveDir.Invoke(__instance); } ControlDir.Invoke(steered) = Ahead(__instance); } __result = turnEased * num * ((float)Math.PI / 180f); return false; } } [HarmonyPatch(typeof(Character), "UpdateWalking")] internal static class BuildUp { private static void Prefix(Character __instance, out Vector2 __state) { //IL_000b: 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) __state = new Vector2(-1f, -1f); Sadle steered = Steering.steered; if (!Object.op_Implicit((Object)(object)steered) || !Keys.Value || (Object)(object)__instance != (Object)(object)steered.GetCharacter() || !steered.HaveValidUser() || SpeedOf(steered) == Speed.Run) { return; } bool flag = Utils.GetPrefabName(((Component)__instance).gameObject).StartsWith("rae_OdinHorse"); if (!flag) { float num = __instance.m_runSpeed * (1f / 3f); if (num > __instance.m_speed) { __state.y = __instance.m_speed; __instance.m_speed = num; } } float num2 = (flag ? TrotSeconds.Value : 0.3f); if (!(num2 <= 0f)) { float num3 = __instance.m_speed * Time.fixedDeltaTime / num2; if (!(num3 <= 0f) && (!flag || !(num3 >= __instance.m_acceleration))) { __state.x = __instance.m_acceleration; __instance.m_acceleration = num3; } } } private static void Postfix(Character __instance, Vector2 __state) { //IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (__state.x >= 0f) { __instance.m_acceleration = __state.x; } if (__state.y >= 0f) { __instance.m_speed = __state.y; } } } [HarmonyPatch(typeof(Player), "SetMouseLook")] internal static class Look { private static void Postfix(Player __instance) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_030d: 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_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: 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_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_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0298: 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_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Sadle val = Ridden(__instance); Transform val2 = (Object.op_Implicit((Object)(object)val) ? AttachPoint.Invoke(__instance) : null); if (!Object.op_Implicit((Object)(object)val2)) { cameraFor = null; return; } bool flag = false; float num = Yaw(val2.forward); if ((Object)(object)cameraFor != (Object)(object)val) { cameraFor = val; lastFacing = num; owed = 0f; } owed += Mathf.DeltaAngle(lastFacing, num); lastFacing = num; if (!CameraFollows.Value || !Keys.Value) { owed = 0f; } if (owed != 0f) { float num2 = ((Mathf.Abs(owed) > 30f) ? owed : (owed * (1f - Mathf.Exp((0f - Time.deltaTime) / 0.06f)))); if (Mathf.Abs(owed - num2) < 0.001f) { num2 = owed; } owed -= num2; LookYaw.Invoke(__instance) = Quaternion.Euler(0f, num2, 0f) * LookYaw.Invoke(__instance); flag = true; } if (BowLock.Value && ((Character)__instance).IsDrawingBow() && Arc(out var left, out var right, out var pitch)) { Vector3 val3 = LookYaw.Invoke(__instance) * Quaternion.Euler(LookPitch.Invoke(__instance), 0f, 0f) * Vector3.forward; Vector3 val4 = val2.InverseTransformDirection(val3); float value = EdgeMargin.Value; float num3 = Yaw(val4); float y = val4.y; Vector2 val5 = new Vector2(val4.x, val4.z); float num4 = Mathf.Atan2(y, ((Vector2)(ref val5)).magnitude) * 57.29578f; float num5 = Mathf.Clamp(num3, 0f - Mathf.Max(0f, left - value), Mathf.Max(0f, right - value)); float num6 = Mathf.Clamp(num4, 0f - Mathf.Max(0f, pitch - value), Mathf.Max(0f, pitch - value)); if (num5 != num3 || num6 != num4) { Vector3 val6 = val2.rotation * (Quaternion.Euler(0f - num6, num5, 0f) * Vector3.forward); LookYaw.Invoke(__instance) = Quaternion.Euler(0f, Yaw(val6), 0f); LookPitch.Invoke(__instance) = (0f - Mathf.Asin(Mathf.Clamp(val6.y, -1f, 1f))) * 57.29578f; flag = true; } } if (flag) { Traverse.Create((object)__instance).Method("UpdateEyeRotation", Array.Empty<object>()).GetValue(); LookDir.Invoke((Character)(object)__instance) = ((Character)__instance).m_eye.forward; } } } internal static ConfigEntry<bool> Keys; internal static ConfigEntry<bool> CameraFollows; internal static ConfigEntry<bool> BowLock; internal static ConfigEntry<int> TurnPercent; internal static ConfigEntry<float> EdgeMargin; internal static ConfigEntry<float> TrotSeconds; private static readonly FieldRef<Player, Transform> AttachPoint = AccessTools.FieldRefAccess<Player, Transform>("m_attachPoint"); private static readonly FieldRef<Player, Quaternion> LookYaw = AccessTools.FieldRefAccess<Player, Quaternion>("m_lookYaw"); private static readonly FieldRef<Character, Vector3> LookDir = AccessTools.FieldRefAccess<Character, Vector3>("m_lookDir"); private static readonly FieldRef<Player, float> LookPitch = AccessTools.FieldRefAccess<Player, float>("m_lookPitch"); private static readonly FieldRef<Sadle, Vector3> ControlDir = AccessTools.FieldRefAccess<Sadle, Vector3>("m_controlDir"); private static readonly FieldInfo SpeedField = AccessTools.Field(typeof(Sadle), "m_speed"); private static Sadle steered; private static float turnInput; private static float turnEased; private static readonly FieldRef<Character, Vector3> MoveDir = AccessTools.FieldRefAccess<Character, Vector3>("m_moveDir"); private const float QuickSeconds = 0.3f; private const float TrotShareOfGallop = 1f / 3f; private static Sadle cameraFor; private static float lastFacing; private static float owed; private const float CameraEase = 0.06f; private static ConfigEntry<float> arcLeft; private static ConfigEntry<float> arcRight; private static ConfigEntry<float> arcPitch; private static bool arcLooked; internal static void Bind(ConfigFile config) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown Keys = config.Bind<bool>("1 - Riding", "Steer with the keys", true, "Every saddled mount: A and D turn it, hold W to walk and Shift to gallop, let go to stop. The mouse only moves the camera. Off: the base game's way, the mount goes where the camera looks."); TurnPercent = config.Bind<int>("1 - Riding", "Turn speed percent", 100, new ConfigDescription("How fast A and D turn the mount, as a percent of its own turn speed (the Odin Horse's Turn Speed and Running Turn Speed are 75 and 120 degrees a second by default).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(25, 300), Array.Empty<object>())); TrotSeconds = config.Bind<float>("1 - Riding", "Seconds to full trot", 0.75f, new ConfigDescription("Odin Horse, holding W: how long it takes to build up from standing to a trot, and slowing down takes half as long. Other mounts keep their own pace (a wolf or boar is quick off the mark). Shift gallops with the mount's own quick build-up. 0 keeps the mount's own build-up for W too.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); CameraFollows = config.Bind<bool>("2 - Camera", "Camera turns with the mount", true, "The camera turns when the mount turns, so you keep your view. Off: the camera holds its direction while the mount turns under you."); BowLock = config.Bind<bool>("2 - Camera", "Camera stops at the bow arc", true, "While a bow is drawn on a mount (the Odin Horse, or any tame its mounted combat covers), the camera stops at the edges of Odin Horse's bow arc, so the crosshair stays where arrows can go."); EdgeMargin = config.Bind<float>("2 - Camera", "Camera margin inside the bow arc", 0f, new ConfigDescription("Degrees the camera stops short of the arc's edges. 0 stops it right at the edge, where arrows still leave along the crosshair.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>())); } private static Sadle Ridden(Player player) { if (Object.op_Implicit((Object)(object)player) && ((Character)player).IsAttached()) { IDoodadController doodadController = player.GetDoodadController(); Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null); if (val != null && Object.op_Implicit((Object)(object)val)) { if (!Object.op_Implicit((Object)(object)val.GetCharacter())) { return null; } return val; } } return null; } private static float Yaw(Vector3 v) { //IL_0000: 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) return Mathf.Atan2(v.x, v.z) * 57.29578f; } private static Speed SpeedOf(Sadle saddle) { return (Speed)Convert.ToInt32(SpeedField.GetValue(saddle)); } private static Vector3 Ahead(Character mount) { //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_002e: 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) Vector3 forward = ((Component)mount).transform.forward; forward.y = 0f; if (!(((Vector3)(ref forward)).sqrMagnitude > 0.0001f)) { return Vector3.forward; } return ((Vector3)(ref forward)).normalized; } private static bool Arc(out float left, out float right, out float pitch) { ConfigFile c; if (!arcLooked) { arcLooked = true; if (Chainloader.PluginInfos.TryGetValue("Raelaziel.OdinHorse", out var value) && Object.op_Implicit((Object)(object)value.Instance)) { c = value.Instance.Config; arcLeft = Find("Bow Turn Left"); arcRight = Find("Bow Turn Right"); arcPitch = Find("Bow Aim Up Down"); } if (arcLeft == null || arcRight == null || arcPitch == null) { Plugin.Log.LogWarning((object)"Odin Horse's bow arc settings weren't found; the camera won't stop at the arc."); } } left = arcLeft?.Value ?? 0f; right = arcRight?.Value ?? 0f; pitch = arcPitch?.Value ?? 0f; if (arcLeft != null && arcRight != null) { return arcPitch != null; } return false; ConfigEntry<float> Find(string key) { return (from k in c.Keys where k.Section == "Mounted Combat" && k.Key == key select c[k] as ConfigEntry<float>).FirstOrDefault(); } } }