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 MountedArchery v1.0.0
MountedArchery.dll
Decompiled 4 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("MountedArchery")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+ce2e7fb5fe0ca0d12f467aef05f7f857746877a8")] [assembly: AssemblyProduct("MountedArchery")] [assembly: AssemblyTitle("MountedArchery")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MountedArchery { [HarmonyPatch] internal static class AimAtFirePatches { private static bool s_errorLogged; [HarmonyPatch(typeof(Attack), "GetProjectileSpawnPoint")] [HarmonyPrefix] private static void Align(Attack __instance) { //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_0029: 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) try { Humanoid obj = Riding.Attacker.Invoke(__instance); Player val = (Player)(object)((obj is Player) ? obj : null); if (Riding.IsRiding(val)) { Quaternion lookYaw = ((Character)val).GetLookYaw(); ((Component)val).transform.rotation = lookYaw; Rigidbody val2 = Riding.Body.Invoke((Character)(object)val); if ((Object)(object)val2 != (Object)null) { val2.rotation = lookYaw; } Riding.AimEye(val); } } catch (Exception arg) { if (!s_errorLogged) { s_errorLogged = true; Plugin.Log.LogError((object)$"Aiming a shot from the saddle failed (logged once): {arg}"); } } } } [HarmonyPatch] internal static class BowDrawPatches { internal static Player Drawing; private static bool s_errorLogged; [HarmonyPatch(typeof(Player), "UpdateAttackBowDraw")] [HarmonyPrefix] private static void Begin(Player __instance, ItemData weapon) { try { if (Riding.IsRiding(__instance) && Riding.IsBow(Riding.AttackOf(weapon, secondary: false))) { Drawing = __instance; } } catch (Exception e) { Drawing = null; LogOnce("Drawing a bow from the saddle failed (logged once)", e); } } [HarmonyPatch(typeof(Player), "UpdateAttackBowDraw")] [HarmonyFinalizer] private static void End() { Drawing = null; } [HarmonyPatch(typeof(Player), "IsAttached")] [HarmonyPostfix] private static void IsAttached(Player __instance, ref bool __result) { if ((Object)(object)Drawing != (Object)null && (Object)(object)__instance == (Object)(object)Drawing) { __result = false; } } private static void LogOnce(string what, Exception e) { if (!s_errorLogged) { s_errorLogged = true; Plugin.Log.LogError((object)$"{what}: {e}"); } } } [HarmonyPatch] internal static class FaceAimPatches { private static bool s_errorLogged; [HarmonyPatch(typeof(Player), "UpdateAttach")] [HarmonyPostfix] private static void FaceAim(Player __instance) { //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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) try { if (!Riding.IsRiding(__instance)) { return; } bool bowWeapon = Riding.IsBow(Riding.AttackOf(((Humanoid)__instance).GetCurrentWeapon(), secondary: false)); float sinceShotStart = Time.time - StartAttackPatches.ShotStartedAt; if (SaddleRules.Shooting(((Character)__instance).InAttack(), sinceShotStart, Riding.DrawTime.Invoke((Humanoid)(object)__instance), bowWeapon)) { Quaternion lookYaw = ((Character)__instance).GetLookYaw(); ((Component)__instance).transform.rotation = lookYaw; Rigidbody val = Riding.Body.Invoke((Character)(object)__instance); if ((Object)(object)val != (Object)null) { val.rotation = lookYaw; } } } catch (Exception e) { LogOnce("Turning the rider to the aim failed (logged once)", e); } } private static void LogOnce(string what, Exception e) { if (!s_errorLogged) { s_errorLogged = true; Plugin.Log.LogError((object)$"{what}: {e}"); } } } [HarmonyPatch] internal static class HoverPatches { private static readonly RaycastHit[] s_hits = (RaycastHit[])(object)new RaycastHit[64]; private static readonly IComparer<RaycastHit> s_byDistance = Comparer<RaycastHit>.Create((RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); private static bool s_errorLogged; [HarmonyPatch(typeof(Player), "UpdateHover")] [HarmonyPostfix] private static void LookAtCreature(Player __instance) { try { if (Riding.IsRiding(__instance) && !((Character)__instance).InPlaceMode()) { IDoodadController doodadController = __instance.GetDoodadController(); Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null); Character mount = (((Object)(object)val != (Object)null) ? val.GetCharacter() : null); Riding.HoverCreature.Invoke(__instance) = CreatureUnderCrosshair(__instance, mount); } } catch (Exception arg) { if (!s_errorLogged) { s_errorLogged = true; Plugin.Log.LogError((object)$"Showing enemies' health from the saddle failed (logged once): {arg}"); } } } private static Character CreatureUnderCrosshair(Player player, Character mount) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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) GameCamera instance = GameCamera.instance; if ((Object)(object)instance == (Object)null) { return null; } Transform transform = ((Component)instance).transform; int num = Physics.RaycastNonAlloc(transform.position, transform.forward, s_hits, 50f, Riding.InteractMask.Invoke(player)); Array.Sort(s_hits, 0, num, s_byDistance); for (int i = 0; i < num; i++) { Collider collider = ((RaycastHit)(ref s_hits[i])).collider; Rigidbody attachedRigidbody = collider.attachedRigidbody; if (Object.op_Implicit((Object)(object)attachedRigidbody) && (Object)(object)((Component)attachedRigidbody).gameObject == (Object)(object)((Component)player).gameObject) { continue; } Character val = (Object.op_Implicit((Object)(object)attachedRigidbody) ? ((Component)attachedRigidbody).GetComponent<Character>() : ((Component)collider).GetComponent<Character>()); if (!((Object)(object)val != (Object)null) || !((Object)(object)val == (Object)(object)mount)) { if ((Object)(object)val == (Object)null) { return null; } BaseAI baseAI = val.GetBaseAI(); if ((Object.op_Implicit((Object)(object)baseAI) && baseAI.IsSleeping()) || ParticleMist.IsMistBlocked(((Character)player).GetCenterPoint(), val.GetCenterPoint())) { return null; } return val; } } return null; } } [HarmonyPatch] internal static class KeepSaddlePatches { private static bool s_errorLogged; [HarmonyPatch(typeof(Player), "SetControls")] [HarmonyPrefix] private static void Hide(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, out AttackFlags __state) { __state = default(AttackFlags); try { if (Riding.IsRiding(__instance)) { ItemData currentWeapon = ((Humanoid)__instance).GetCurrentWeapon(); AttackFlags input = new AttackFlags { Attack = attack, AttackHold = attackHold, Secondary = secondaryAttack, SecondaryHold = secondaryAttackHold }; __state = SaddleRules.Hide(riding: true, input, Riding.KeepsSaddle(Riding.AttackOf(currentWeapon, secondary: false), secondary: false), Riding.KeepsSaddle(Riding.AttackOf(currentWeapon, secondary: true), secondary: true)); if (__state.Any) { AttackFlags attackFlags = SaddleRules.Remaining(input, __state); attack = attackFlags.Attack; attackHold = attackFlags.AttackHold; secondaryAttack = attackFlags.Secondary; secondaryAttackHold = attackFlags.SecondaryHold; } } } catch (Exception e) { __state = default(AttackFlags); LogOnce("Keeping the saddle on a shot failed (logged once; vanilla dismounts)", e); } } [HarmonyPatch(typeof(Player), "SetControls")] [HarmonyPostfix] private static void Restore(Player __instance, AttackFlags __state) { try { if (__state.Any) { AttackFlags attackFlags = SaddleRules.Restore(Riding.IsRiding(__instance), __state); if (attackFlags.Attack) { Riding.AttackFlag.Invoke((Character)(object)__instance) = true; } if (attackFlags.AttackHold) { Riding.AttackHoldFlag.Invoke((Character)(object)__instance) = true; } if (attackFlags.Secondary) { Riding.SecondaryFlag.Invoke((Character)(object)__instance) = true; } if (attackFlags.SecondaryHold) { Riding.SecondaryHoldFlag.Invoke((Character)(object)__instance) = true; } } } catch (Exception e) { LogOnce("Passing a shot on to the attack update failed (logged once)", e); } } private static void LogOnce(string what, Exception e) { if (!s_errorLogged) { s_errorLogged = true; Plugin.Log.LogError((object)$"{what}: {e}"); } } } [HarmonyPatch] internal static class LaunchPatches { private static Player s_rider; private static bool s_errorLogged; [HarmonyPatch(typeof(Attack), "FireProjectileBurst")] [HarmonyPrefix] private static void Begin(Attack __instance) { try { Humanoid obj = Riding.Attacker.Invoke(__instance); Player val = (Player)(object)((obj is Player) ? obj : null); s_rider = (Riding.IsRiding(val) ? val : null); } catch (Exception e) { s_rider = null; LogOnce(e); } } [HarmonyPatch(typeof(Attack), "FireProjectileBurst")] [HarmonyFinalizer] private static void End() { s_rider = null; } [HarmonyPatch(typeof(Projectile), "Setup")] [HarmonyPrefix] private static void Launch(Character owner, ref Vector3 velocity) { //IL_001e: 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) try { if (!((Object)(object)s_rider == (Object)null) && !((Object)(object)owner != (Object)(object)s_rider)) { velocity = ShotRules.LaunchVelocity(velocity, ((Character)s_rider).GetVelocity()); } } catch (Exception e) { LogOnce(e); } } private static void LogOnce(Exception e) { if (!s_errorLogged) { s_errorLogged = true; Plugin.Log.LogError((object)$"Adding the rider's speed to a shot failed (logged once): {e}"); } } } [HarmonyPatch] internal static class PickupPatches { private static readonly Collider[] s_colliders = (Collider[])(object)new Collider[100]; private static bool s_errorLogged; [HarmonyPatch(typeof(Player), "AutoPickup")] [HarmonyPostfix] private static void AroundTheMount(Player __instance, float dt) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) try { if (!Riding.IsRiding(__instance) || ((Character)__instance).IsTeleporting() || !Riding.AutoPickupOn.Invoke()) { return; } IDoodadController doodadController = __instance.GetDoodadController(); Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null); Character val2 = (((Object)(object)val != (Object)null) ? val.GetCharacter() : null); if ((Object)(object)val2 == (Object)null) { return; } CapsuleCollider collider = val2.GetCollider(); Vector3 val3 = ((Component)val2).transform.position + Vector3.up; float num = PickupRules.Reach(__instance.m_autoPickupRange, ((Object)(object)collider != (Object)null) ? collider.radius : 0f); Vector3 val4 = ((Component)__instance).transform.position + Vector3.up; Vector3 val5 = ((Vector3.Distance(val4, val3) <= num) ? val4 : val3); Vector3 velocity = ((Character)__instance).GetVelocity(); Inventory inventory = ((Humanoid)__instance).GetInventory(); int num2 = Physics.OverlapSphereNonAlloc(val3, num, s_colliders, Riding.AutoPickupMask.Invoke(__instance)); for (int i = 0; i < num2; i++) { Rigidbody attachedRigidbody = s_colliders[i].attachedRigidbody; if (!Object.op_Implicit((Object)(object)attachedRigidbody)) { continue; } ItemDrop component = ((Component)attachedRigidbody).GetComponent<ItemDrop>(); FloatingTerrainDummy val6 = null; if ((Object)(object)component == (Object)null && Object.op_Implicit((Object)(object)(val6 = ((Component)attachedRigidbody).GetComponent<FloatingTerrainDummy>())) && (Object)(object)val6.m_parent != (Object)null) { component = ((Component)val6.m_parent).GetComponent<ItemDrop>(); } if ((Object)(object)component == (Object)null || !component.m_autoPickup || component.IsPiece() || ((Humanoid)__instance).HaveUniqueKey(component.m_itemData.m_shared.m_name)) { continue; } ZNetView component2 = ((Component)component).GetComponent<ZNetView>(); if ((Object)(object)component2 == (Object)null || !component2.IsValid()) { continue; } if (!component.CanPickup(true)) { component.RequestOwn(); } else { if (component.InTar()) { continue; } component.Load(); if (!inventory.CanAddItem(component.m_itemData, -1) || component.m_itemData.GetWeight(-1) + inventory.GetTotalWeight() > __instance.GetMaxCarryWeight() || Vector3.Distance(((Component)component).transform.position, val3) > num) { continue; } Vector3 toTarget = val5 - ((Component)component).transform.position; if (((Vector3)(ref toTarget)).magnitude < 0.3f) { ((Humanoid)__instance).Pickup(((Component)component).gameObject, true, true); continue; } Vector3 val7 = PickupRules.Step(toTarget, velocity, dt); Transform transform = ((Component)component).transform; transform.position += val7; if (Object.op_Implicit((Object)(object)val6)) { Transform transform2 = ((Component)val6).transform; transform2.position += val7; } } } } catch (Exception arg) { if (!s_errorLogged) { s_errorLogged = true; Plugin.Log.LogError((object)$"Picking items up from the saddle failed (logged once): {arg}"); } } } } internal static class PickupRules { public const float PullSpeed = 15f; public const float PickupDistance = 0.3f; public static float Reach(float gameRange, float bodyRadius) { return gameRange + Mathf.Max(0f, bodyRadius); } public static Vector3 Step(Vector3 toTarget, Vector3 riderVelocity, float dt) { //IL_0002: 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_0013: 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) return ((Vector3)(ref toTarget)).normalized * (15f * dt) + riderVelocity * dt; } } [BepInPlugin("algo7.mountedarchery", "MountedArchery", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "algo7.mountedarchery"; public const string Name = "MountedArchery"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; private void Awake() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; if (Application.isBatchMode) { Log.LogInfo((object)"MountedArchery loaded (v1.0.0): dedicated server, nothing to do"); return; } Install(new Harmony("algo7.mountedarchery")); Log.LogInfo((object)"MountedArchery loaded (v1.0.0)"); } private static void Install(Harmony harmony) { if (!Riding.Prepare()) { return; } if (!TryPatch(harmony, typeof(KeepSaddlePatches), "saddle hook") || !TryPatch(harmony, typeof(StartAttackPatches), "attack start hook") || !TryPatch(harmony, typeof(AimAtFirePatches), "fire aim hook") || !TryPatch(harmony, typeof(RidePosePatches), "seat pose hook")) { harmony.UnpatchSelf(); Log.LogError((object)"Mounted shooting is off: attacks dismount you as in the unmodded game"); return; } if (!TryPatch(harmony, typeof(BowDrawPatches), "bow draw hook")) { Riding.BowsEnabled = false; Log.LogWarning((object)"Bows dismount you as in the unmodded game (crossbows, spears and staffs still fire from the saddle)"); } if (!TryPatch(harmony, typeof(FaceAimPatches), "turn hook")) { Log.LogWarning((object)"The rider won't visibly turn to the aim (shots still fly true)"); } if (!TryPatch(harmony, typeof(SeatedCameraPatches), "seated camera hook")) { Log.LogWarning((object)"Shots from the saddle start a little higher against the crosshair than on foot"); } if (Riding.HoverCreature != null && !TryPatch(harmony, typeof(HoverPatches), "health bar hook")) { Log.LogWarning((object)"Enemies' health bars won't show while riding (as in the unmodded game)"); } if (Riding.AutoPickupOn != null && !TryPatch(harmony, typeof(PickupPatches), "pickup hook")) { Log.LogWarning((object)"Items won't be picked up from the saddle (as in the unmodded game)"); } if (!TryPatch(harmony, typeof(LaunchPatches), "launch speed hook")) { Log.LogWarning((object)"Shots from a moving animal leave at the weapon's own speed (as in the unmodded game)"); } } internal static bool TryPatch(Harmony harmony, Type patches, string what) { try { harmony.PatchAll(patches); return true; } catch (Exception arg) { Log.LogError((object)$"Could not install the {what}: {arg}"); return false; } } } [HarmonyPatch] internal static class RidePosePatches { private static Player s_shot; private static bool s_fired; private static bool s_keepsFiring; private static bool s_poseOff; private static bool s_errorLogged; [HarmonyPatch(typeof(Humanoid), "StartAttack")] [HarmonyPostfix] private static void Started(Humanoid __instance, bool secondaryAttack, bool __result) { try { Player seated = StartAttackPatches.Seated; if (__result && !((Object)(object)seated == (Object)null) && !((Object)(object)__instance != (Object)(object)seated)) { Attack val = Riding.AttackOf(((Humanoid)seated).GetCurrentWeapon(), secondaryAttack); if ((Object)(object)s_shot != (Object)(object)seated) { s_poseOff = false; } s_shot = seated; s_fired = false; s_keepsFiring = val != null && (val.m_loopingAttack || val.m_projectileBursts > 1); } } catch (Exception e) { LogOnce("Keeping the attack clip for a shot from the saddle failed (logged once)", e); } } [HarmonyPatch(typeof(Humanoid), "OnAttackTrigger")] [HarmonyPostfix] private static void Fired(Humanoid __instance) { if ((Object)(object)s_shot != (Object)null && (Object)(object)__instance == (Object)(object)s_shot) { s_fired = true; } } [HarmonyPatch(typeof(Player), "UpdateAttach")] [HarmonyPostfix] private static void Step(Player __instance) { try { if (!Riding.IsRiding(__instance)) { if ((Object)(object)__instance == (Object)(object)s_shot) { Forget(); } return; } bool flag = ((Character)__instance).InAttack(); ZSyncAnimation val = Riding.Anim.Invoke((Character)(object)__instance); if (!flag && !((Character)__instance).InMinorAction() && !((Character)__instance).InEmote() && (Object)(object)val != (Object)null) { val.SetSpeed(1f); } if ((Object)(object)__instance != (Object)(object)s_shot) { return; } bool flag2 = SaddleRules.PoseBack(s_fired, s_keepsFiring, flag, Time.time - StartAttackPatches.ShotStartedAt); if (flag2) { if (s_poseOff) { SetPose(__instance, on: true); } Forget(); } else if (!s_poseOff && SaddleRules.PoseOff(Riding.NextOrCurrentAnimHash((Character)(object)__instance) == Riding.AttackTag, flag2)) { s_poseOff = SetPose(__instance, on: false); } } catch (Exception e) { if ((Object)(object)__instance == (Object)(object)s_shot) { try { if (s_poseOff && Riding.IsRiding(__instance)) { SetPose(__instance, on: true); } } catch (Exception) { } Forget(); } LogOnce("Putting the rider back in the seat's pose failed (logged once)", e); } } private static void Forget() { s_shot = null; s_poseOff = false; } private static bool SetPose(Player player, bool on) { string text = Riding.AttachAnimation.Invoke(player); ZSyncAnimation val = Riding.Anim.Invoke((Character)(object)player); if (string.IsNullOrEmpty(text) || (Object)(object)val == (Object)null) { return false; } val.SetBool(text, on); return true; } private static void LogOnce(string what, Exception e) { if (!s_errorLogged) { s_errorLogged = true; Plugin.Log.LogError((object)$"{what}: {e}"); } } } internal static class Riding { internal static FieldRef<Player, bool> Attached; internal static FieldRef<Character, bool> AttackFlag; internal static FieldRef<Character, bool> AttackHoldFlag; internal static FieldRef<Character, bool> SecondaryFlag; internal static FieldRef<Character, bool> SecondaryHoldFlag; internal static FieldRef<Humanoid, float> DrawTime; internal static FieldRef<Character, Rigidbody> Body; internal static Func<Character, int> NextOrCurrentAnimHash; internal static int SittingTag; internal static int AttackTag; internal static FieldRef<Attack, Humanoid> Attacker; internal static Action<Player> AimEye; internal static FieldRef<Player, string> AttachAnimation; internal static FieldRef<Character, ZSyncAnimation> Anim; internal static FieldRef<GameCamera, Vector3> CameraBaseOffset; internal static FieldRef<Player, Character> HoverCreature; internal static FieldRef<Player, int> InteractMask; internal static FieldRef<bool> AutoPickupOn; internal static FieldRef<Player, int> AutoPickupMask; internal static bool BowsEnabled = true; internal static bool Prepare() { if (Attached != null) { return true; } try { Attached = AccessTools.FieldRefAccess<Player, bool>("m_attached"); AttackFlag = AccessTools.FieldRefAccess<Character, bool>("m_attack"); AttackHoldFlag = AccessTools.FieldRefAccess<Character, bool>("m_attackHold"); SecondaryFlag = AccessTools.FieldRefAccess<Character, bool>("m_secondaryAttack"); SecondaryHoldFlag = AccessTools.FieldRefAccess<Character, bool>("m_secondaryAttackHold"); DrawTime = AccessTools.FieldRefAccess<Humanoid, float>("m_attackDrawTime"); Body = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body"); MethodInfo methodInfo = AccessTools.Method(typeof(Character), "GetNextOrCurrentAnimHash", (Type[])null, (Type[])null); if (methodInfo == null) { throw new MissingMethodException("Character.GetNextOrCurrentAnimHash"); } NextOrCurrentAnimHash = AccessTools.MethodDelegate<Func<Character, int>>(methodInfo, (object)null, true); SittingTag = AccessTools.StaticFieldRefAccess<int>(typeof(Character), "s_animatorTagSitting"); AttackTag = AccessTools.StaticFieldRefAccess<int>(typeof(Humanoid), "s_animatorTagAttack"); Attacker = AccessTools.FieldRefAccess<Attack, Humanoid>("m_character"); MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(Player), "UpdateEyeRotation", (Type[])null, (Type[])null); if (methodInfo2 == null) { throw new MissingMethodException("Player.UpdateEyeRotation"); } AimEye = AccessTools.MethodDelegate<Action<Player>>(methodInfo2, (object)null, false); AttachAnimation = AccessTools.FieldRefAccess<Player, string>("m_attachAnimation"); Anim = AccessTools.FieldRefAccess<Character, ZSyncAnimation>("m_zanim"); } catch (Exception ex) { Attached = null; Plugin.Log.LogError((object)("Mounted shooting is off: a game member the hooks need wasn't found (a game update?): " + ex.Message)); return false; } try { CameraBaseOffset = AccessTools.FieldRefAccess<GameCamera, Vector3>("m_currentBaseOffset"); } catch (Exception ex2) { CameraBaseOffset = null; Plugin.Log.LogWarning((object)("Shots from the saddle line up with where the camera settles, not where it is (a game update?): " + ex2.Message)); } try { HoverCreature = AccessTools.FieldRefAccess<Player, Character>("m_hoveringCreature"); InteractMask = AccessTools.FieldRefAccess<Player, int>("m_interactMask"); } catch (Exception ex3) { HoverCreature = null; InteractMask = null; Plugin.Log.LogWarning((object)("Enemies' health bars won't show while riding (a game update?): " + ex3.Message)); } try { FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_enableAutoPickup"); if (fieldInfo == null || !fieldInfo.IsStatic) { throw new MissingFieldException("Player.m_enableAutoPickup"); } AutoPickupOn = AccessTools.StaticFieldRefAccess<bool>(fieldInfo); AutoPickupMask = AccessTools.FieldRefAccess<Player, int>("m_autoPickupMask"); } catch (Exception ex4) { AutoPickupOn = null; AutoPickupMask = null; Plugin.Log.LogWarning((object)("Items won't be picked up from the saddle (a game update?): " + ex4.Message)); } return true; } internal static bool IsRiding(Player player) { if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || Attached == null || !Attached.Invoke(player)) { return false; } return ((Character)player).IsRiding(); } internal static Attack AttackOf(ItemData weapon, bool secondary) { SharedData val = weapon?.m_shared; if (val == null) { return null; } if (!secondary) { return val.m_attack; } return val.m_secondaryAttack; } internal static bool IsProjectile(Attack attack) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (attack != null) { return SaddleRules.IsProjectile(attack.m_attackType, attack.m_bowDraw, BowsEnabled, !string.IsNullOrEmpty(attack.m_attackAnimation)); } return false; } internal static bool KeepsSaddle(Attack attack, bool secondary) { if (attack != null) { return SaddleRules.KeepsSaddle(IsProjectile(attack), !string.IsNullOrEmpty(attack.m_attackAnimation), secondary); } return false; } internal static bool IsBow(Attack attack) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if (attack != null && (int)attack.m_attackType == 2) { return attack.m_bowDraw; } return false; } } internal struct AttackFlags { public bool Attack; public bool AttackHold; public bool Secondary; public bool SecondaryHold; public bool Any { get { if (!Attack && !AttackHold && !Secondary) { return SecondaryHold; } return true; } } } internal static class SaddleRules { public const float ShotStartGrace = 0.3f; public static bool IsProjectile(AttackType type, bool bowDraw, bool bowsEnabled, bool hasAnimation) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Invalid comparison between Unknown and I4 if (!hasAnimation || (int)type != 2) { return false; } return !bowDraw || bowsEnabled; } public static bool KeepsSaddle(bool isProjectile, bool hasAnimation, bool secondary) { if (!isProjectile) { if (secondary) { return !hasAnimation; } return false; } return true; } public static AttackFlags Hide(bool riding, AttackFlags input, bool primaryKeepsSaddle, bool secondaryKeepsSaddle) { AttackFlags result = default(AttackFlags); if (!riding) { return result; } if (primaryKeepsSaddle) { result.Attack = input.Attack; result.AttackHold = input.AttackHold; } if (secondaryKeepsSaddle) { result.Secondary = input.Secondary; result.SecondaryHold = input.SecondaryHold; } return result; } public static AttackFlags Remaining(AttackFlags input, AttackFlags hidden) { return new AttackFlags { Attack = (input.Attack && !hidden.Attack), AttackHold = (input.AttackHold && !hidden.AttackHold), Secondary = (input.Secondary && !hidden.Secondary), SecondaryHold = (input.SecondaryHold && !hidden.SecondaryHold) }; } public static AttackFlags Restore(bool stillAttached, AttackFlags hidden) { if (!stillAttached) { return default(AttackFlags); } return hidden; } public static bool AttackPlaying(bool inAttack, float sinceShotStart) { if (!inAttack) { return sinceShotStart < 0.3f; } return true; } public static bool PoseOff(bool fullBodyInAttack, bool poseBack) { if (fullBodyInAttack) { return !poseBack; } return false; } public static bool PoseBack(bool shotFired, bool keepsFiring, bool inAttack, float sinceShotStart) { if (!shotFired || keepsFiring) { return !AttackPlaying(inAttack, sinceShotStart); } return true; } public static bool Shooting(bool inAttack, float sinceShotStart, float drawTime, bool bowWeapon) { if (!AttackPlaying(inAttack, sinceShotStart)) { if (bowWeapon) { return drawTime > 0f; } return false; } return true; } } [HarmonyPatch] internal static class SeatedCameraPatches { private static bool s_errorLogged; [HarmonyPatch(typeof(Attack), "GetProjectileSpawnPoint")] [HarmonyPostfix] private static void Shift(Attack __instance, ref Vector3 spawnPoint) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_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) try { Humanoid obj = Riding.Attacker.Invoke(__instance); Player val = (Player)(object)((obj is Player) ? obj : null); if (Riding.IsRiding(val) && string.IsNullOrEmpty(__instance.m_attackOriginJoint)) { spawnPoint += ShotRules.ShotShift(CameraBase(val), ((Character)val).m_eye.position); } } catch (Exception arg) { if (!s_errorLogged) { s_errorLogged = true; Plugin.Log.LogError((object)$"Starting a shot at the seated camera's height failed (logged once): {arg}"); } } } internal static Vector3 CameraBase(Player player) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) GameCamera instance = GameCamera.instance; if (Riding.CameraBaseOffset != null && (Object)(object)instance != (Object)null) { return ((Component)player).transform.position + Riding.CameraBaseOffset.Invoke(instance); } return ShotRules.SeatedCameraBase(((Character)player).GetHeadPoint()); } } internal static class ShotRules { public const float SeatedCameraAboveHead = 0.3f; public const float MinLaunchSpeed = 1f; public static Vector3 ShotShift(Vector3 cameraBase, Vector3 eye) { //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) return cameraBase - eye; } public static Vector3 SeatedCameraBase(Vector3 head) { //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_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) return head + Vector3.up * 0.3f; } public static Vector3 LaunchVelocity(Vector3 velocity, Vector3 riderVelocity) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0027: 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_0034: 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) float magnitude = ((Vector3)(ref velocity)).magnitude; if (magnitude < 0.01f) { return velocity; } Vector3 val = velocity / magnitude; return val * Mathf.Max(Mathf.Min(magnitude, 1f), magnitude + Vector3.Dot(riderVelocity, val)); } } [HarmonyPatch] internal static class StartAttackPatches { internal static Player Seated; internal static float ShotStartedAt = float.NegativeInfinity; private static bool s_errorLogged; [HarmonyPatch(typeof(Humanoid), "StartAttack")] [HarmonyPrefix] private static void Begin(Humanoid __instance, bool secondaryAttack) { try { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (Riding.IsRiding(val) && Riding.IsProjectile(Riding.AttackOf(((Humanoid)val).GetCurrentWeapon(), secondaryAttack))) { Seated = val; } } catch (Exception e) { Seated = null; LogOnce("Starting a shot from the saddle failed (logged once)", e); } } [HarmonyPatch(typeof(Humanoid), "StartAttack")] [HarmonyPostfix] private static void Started(Humanoid __instance, bool __result) { if (__result && (Object)(object)Seated != (Object)null && (Object)(object)__instance == (Object)(object)Seated) { ShotStartedAt = Time.time; } } [HarmonyPatch(typeof(Humanoid), "StartAttack")] [HarmonyFinalizer] private static void End() { Seated = null; } [HarmonyPatch(typeof(Character), "CanMove")] [HarmonyPostfix] private static void CanMove(Character __instance, ref bool __result) { try { if (!__result && !((Object)(object)Seated == (Object)null) && !((Object)(object)__instance != (Object)(object)Seated)) { __result = !__instance.IsStaggering() && Riding.NextOrCurrentAnimHash(__instance) == Riding.SittingTag; } } catch (Exception e) { LogOnce("Allowing a shot from the saddle failed (logged once)", e); } } private static void LogOnce(string what, Exception e) { if (!s_errorLogged) { s_errorLogged = true; Plugin.Log.LogError((object)$"{what}: {e}"); } } } internal static class PluginInfo { public const string Version = "1.0.0"; } }