using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("FehuMounts")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("FehuMounts")] [assembly: AssemblyTitle("FehuMounts")] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 FehuMounts { [BepInPlugin("wmymysl.fehumounts", "FehuMounts", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { public const string ModGuid = "wmymysl.fehumounts"; public const string ModName = "FehuMounts"; public const string ModVersion = "1.0.0"; internal static ConfigEntry EnableDeerTaming = null; internal static ConfigEntry DeerTamingFoods = null; internal static ConfigEntry MinStarsToRide = null; internal static ConfigEntry EnableWhistle = null; internal static ConfigEntry RegisterWhistleItem = null; internal static ConfigEntry WhistleRange = null; internal static ConfigEntry OnlyOwnerCanSummon = null; internal static readonly int FehuOwnerHash = StableHash("FehuMounts.Owner"); internal static readonly int FehuOwnerNameHash = StableHash("FehuMounts.OwnerName"); internal static readonly int FehuLegendaryCallHash = StableHash("FehuMounts.LegendaryCall"); internal const string WhistlePrefabName = "FehuWhistle"; internal const string WhistleToken = "$item_fehu_whistle"; internal const string CallMountRpc = "FehuMounts_CallMount"; internal const string ConfigSyncRpc = "FehuMounts_ConfigSync"; private static readonly Harmony Harmony = new Harmony("wmymysl.fehumounts"); private static readonly HashSet RegisteredObjectDb = new HashSet(StringComparer.Ordinal); private static readonly HashSet RegisteredZNetScene = new HashSet(StringComparer.Ordinal); private void Awake() { EnableDeerTaming = ((BaseUnityPlugin)this).Config.Bind("General", "EnableDeerTaming", true, "Enable taming support for vanilla Deer."); DeerTamingFoods = ((BaseUnityPlugin)this).Config.Bind("General", "DeerTamingFoods", "Raspberry,Blueberry,Blueberries,Carrot,Turnip", "Comma-separated prefab names that Deer can eat while taming. Blueberry and Blueberries are both accepted."); MinStarsToRide = ((BaseUnityPlugin)this).Config.Bind("General", "MinStarsToRide", 2, "Minimum deer stars required to ride. Vanilla level is stars + 1."); EnableWhistle = ((BaseUnityPlugin)this).Config.Bind("Whistle", "EnableWhistle", false, "Enable Fehu Whistle item and summon behavior. Disabled by default while deer taming is validated with mixed ItemManager modlists."); RegisterWhistleItem = ((BaseUnityPlugin)this).Config.Bind("Whistle", "RegisterWhistleItem", false, "Register the Fehu Whistle item prefab and recipe. Keep false while testing deer taming if ItemManager mods throw prefab errors."); WhistleRange = ((BaseUnityPlugin)this).Config.Bind("Whistle", "WhistleRange", 80f, "Range in meters for finding an owned tamed deer."); OnlyOwnerCanSummon = ((BaseUnityPlugin)this).Config.Bind("Whistle", "OnlyOwnerCanSummon", true, "Only the recorded deer owner may summon it."); ConfigSync.HookSettings(); Harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"FehuMounts 1.0.0 loaded."); } private void OnDestroy() { Harmony.UnpatchSelf(); } internal static bool IsDeer(Character? character) { if ((Object)(object)character != (Object)null) { return Utils.GetPrefabName(((Component)character).gameObject).Equals("Deer", StringComparison.OrdinalIgnoreCase); } return false; } internal static int GetStars(Character character) { return Math.Max(0, character.GetLevel() - 1); } internal static bool CanRide(Character character) { if (IsDeer(character)) { return GetStars(character) >= Math.Max(0, MinStarsToRide.Value); } return false; } internal static MountTier GetTier(Character character) { int stars = GetStars(character); if (stars < 5) { return stars switch { 4 => new MountTier(1.25f, 1.4f, 0.85f, legendaryRecall: false), 3 => new MountTier(1.15f, 1.25f, 1f, legendaryRecall: false), _ => new MountTier(1f, 1f, 1f, legendaryRecall: false), }; } return new MountTier(1.35f, 1.6f, 0.7f, legendaryRecall: true); } internal static void ConfigureDeer(GameObject deer) { Character component = deer.GetComponent(); MonsterAI component2 = deer.GetComponent(); ZNetView nview = deer.GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)nview == (Object)null) { return; } if (nview.IsValid()) { nview.Unregister("FehuMounts_CallMount"); nview.Register("FehuMounts_CallMount", (Action)delegate(long sender, long playerId, string playerName, Vector3 playerPos) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) RPC_CallMount(nview, sender, playerId, playerName, playerPos); }); } if (EnableDeerTaming.Value) { Tameable val = deer.GetComponent() ?? deer.AddComponent(); val.m_commandable = true; val.m_startsTamed = false; val.m_tamingTime = Math.Max(1f, val.m_tamingTime); val.m_fedDuration = Math.Max(30f, val.m_fedDuration); Tameable val2 = val; if (val2.m_randomStartingName == null) { val2.m_randomStartingName = new List(); } AddFoods(component2); component2.m_fleeIfNotAlerted = false; component2.m_fleeIfHurtWhenTargetCantBeReached = false; component2.m_fleeIfLowHealth = 0f; component2.m_consumeRange = Math.Max(component2.m_consumeRange, 2f); component2.m_consumeSearchRange = Math.Max(component2.m_consumeSearchRange, 10f); } Tameable component3 = deer.GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.m_saddleItem = null; component3.m_dropSaddleOnDeath = false; } } internal static Sadle EnsureRideController(GameObject deer, Character character, Tameable tameable) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Sadle val = deer.GetComponent() ?? deer.AddComponent(); val.m_hoverText = "Ride Deer"; val.m_maxUseRange = 4f; val.m_attachAnimation = "attach_chair"; val.m_detachOffset = new Vector3(0f, 0.2f, -1.2f); val.m_attachPoint = EnsureAttachPoint(deer.transform); ApplyTierStats(val, character); tameable.m_saddle = val; tameable.m_saddleItem = null; tameable.m_dropSaddleOnDeath = false; return val; } internal static void ApplyTierStats(Sadle sadle, Character character) { MountTier tier = GetTier(character); sadle.m_maxStamina = 100f * tier.StaminaMultiplier; sadle.m_runStaminaDrain = 10f * tier.StaminaDrainMultiplier; sadle.m_swimStaminaDrain = 20f * tier.StaminaDrainMultiplier; sadle.m_staminaRegen = 15f * tier.StaminaMultiplier; sadle.m_staminaRegenHungry = 5f; } internal static bool IsWhistle(ItemData? item) { if ((Object)(object)item?.m_dropPrefab != (Object)null) { return Utils.GetPrefabName(item.m_dropPrefab) == "FehuWhistle"; } return false; } internal static void UseWhistle(Player player) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (!EnableWhistle.Value) { ((Character)player).Message((MessageType)2, "The whistle is silent.", 0, (Sprite)null); return; } Tameable val = FindNearestOwnedTamedDeer(player, WhistleRange.Value); if ((Object)(object)val == (Object)null) { ((Character)player).Message((MessageType)2, "No loyal deer answers.", 0, (Sprite)null); return; } ZNetView component = ((Component)val).GetComponent(); Character component2 = ((Component)val).GetComponent(); MonsterAI component3 = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null) && !((Object)(object)component3 == (Object)null) && component.IsValid()) { component.InvokeRPC(ZNetView.Everybody, "FehuMounts_CallMount", new object[3] { player.GetPlayerID(), player.GetPlayerName(), ((Component)player).transform.position }); ((Character)player).Message((MessageType)2, val.GetName() + " hears the whistle.", 0, (Sprite)null); } } internal static void StoreOwnerIfMissing(ZNetView? nview, Player? player) { if (!((Object)(object)nview == (Object)null) && !((Object)(object)player == (Object)null) && nview.IsValid()) { ZDO zDO = nview.GetZDO(); if (zDO.GetLong(FehuOwnerHash, 0L) == 0L) { StoreOwnerData(zDO, player.GetPlayerID(), player.GetPlayerName()); } } } internal static void StoreOwnerData(ZDO zdo, long playerId, string playerName) { zdo.Set(FehuOwnerHash, playerId); zdo.Set(FehuOwnerNameHash, playerName); } private static void RPC_CallMount(ZNetView nview, long sender, long playerId, string playerName, Vector3 playerPos) { //IL_00b2: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_00d8: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) if (!nview.IsValid() || !nview.IsOwner()) { return; } Tameable component = ((Component)nview).GetComponent(); Character component2 = ((Component)nview).GetComponent(); MonsterAI component3 = ((Component)nview).GetComponent(); if (IsDeer(component2) && !((Object)(object)component == (Object)null) && !((Object)(object)component3 == (Object)null) && component.IsTamed()) { ZDO zDO = nview.GetZDO(); long num = zDO.GetLong(FehuOwnerHash, 0L); if (num == 0L) { StoreOwnerData(zDO, playerId, playerName); } else if (OnlyOwnerCanSummon.Value && num != playerId) { return; } Player player = Player.GetPlayer(playerId); if ((Object)(object)player != (Object)null) { component3.SetFollowTarget(((Component)player).gameObject); } if (GetTier(component2).LegendaryRecall && Vector3.Distance(playerPos, ((Component)component2).transform.position) > 25f) { Vector3 position = (((Object)(object)player != (Object)null) ? (((Component)player).transform.position - ((Component)player).transform.forward * 3f) : playerPos); ((Component)component2).transform.position = position; zDO.SetPosition(position); zDO.Set(FehuLegendaryCallHash, ((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTime().Ticks : DateTime.UtcNow.Ticks); } } } private static Tameable? FindNearestOwnedTamedDeer(Player player, float range) { //IL_007b: 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) Tameable result = null; float num = range; foreach (BaseAI allInstance in BaseAI.GetAllInstances()) { Character component = ((Component)allInstance).GetComponent(); Tameable component2 = ((Component)allInstance).GetComponent(); ZNetView component3 = ((Component)allInstance).GetComponent(); if (IsDeer(component) && !((Object)(object)component2 == (Object)null) && !((Object)(object)component3 == (Object)null) && component3.IsValid() && component2.IsTamed() && (!OnlyOwnerCanSummon.Value || IsOwner(component3, player))) { float num2 = Vector3.Distance(((Component)player).transform.position, ((Component)component).transform.position); if (num2 <= num) { result = component2; num = num2; } } } return result; } private static bool IsOwner(ZNetView nview, Player player) { long num = nview.GetZDO().GetLong(FehuOwnerHash, 0L); if (num != 0L) { return num == player.GetPlayerID(); } return true; } private static Transform EnsureAttachPoint(Transform root) { //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_002e: 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_004d: 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) Transform val = root.Find("FehuMountAttachPoint"); if ((Object)(object)val != (Object)null) { return val; } GameObject val2 = new GameObject("FehuMountAttachPoint"); val2.transform.SetParent(root, false); val2.transform.localPosition = new Vector3(0f, 1f, -0.15f); val2.transform.localRotation = Quaternion.identity; return val2.transform; } private static void AddFoods(MonsterAI ai) { if ((Object)(object)ObjectDB.instance == (Object)null) { return; } if (ai.m_consumeItems == null) { ai.m_consumeItems = new List(); } foreach (string item in from s in DeerTamingFoods.Value.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries) select NormalizeFoodPrefab(s.Trim())) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent() : null); if ((Object)(object)val != (Object)null && !ai.m_consumeItems.Contains(val)) { ai.m_consumeItems.Add(val); } } } private static string NormalizeFoodPrefab(string prefabName) { if (!prefabName.Equals("Blueberry", StringComparison.OrdinalIgnoreCase)) { return prefabName; } return "Blueberries"; } internal static void RegisterWhistle(ObjectDB objectDb) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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) if (EnableWhistle.Value && RegisterWhistleItem.Value && !RegisteredObjectDb.Contains("FehuWhistle")) { GameObject itemPrefab = objectDb.GetItemPrefab("BoneFragments"); if (!((Object)(object)itemPrefab == (Object)null)) { GameObject val = Object.Instantiate(itemPrefab); ((Object)val).name = "FehuWhistle"; Object.DontDestroyOnLoad((Object)(object)val); ItemDrop component = val.GetComponent(); component.m_itemData.m_shared.m_name = "Fehu Whistle"; component.m_itemData.m_shared.m_description = "A carved whistle used to call loyal mounts."; component.m_itemData.m_shared.m_maxStackSize = 1; component.m_itemData.m_shared.m_weight = 0.2f; component.m_itemData.m_shared.m_value = 5; component.m_itemData.m_shared.m_itemType = (ItemType)18; component.m_itemData.m_dropPrefab = val; val.transform.localScale = Vector3.one * 0.3f; objectDb.m_items.Add(val); objectDb.m_recipes.Add(CreateWhistleRecipe(objectDb, component)); RegisteredObjectDb.Add("FehuWhistle"); } } } internal static void RegisterWhistleScenePrefab(ZNetScene scene) { if (EnableWhistle.Value && RegisterWhistleItem.Value && !RegisteredZNetScene.Contains("FehuWhistle") && !((Object)(object)ObjectDB.instance == (Object)null)) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("FehuWhistle"); if ((Object)(object)itemPrefab != (Object)null && !scene.m_prefabs.Contains(itemPrefab)) { scene.m_prefabs.Add(itemPrefab); RegisteredZNetScene.Add("FehuWhistle"); } } } internal static void ConfigureDeerPrefab(ZNetScene scene) { GameObject val = ((IEnumerable)scene.m_prefabs).FirstOrDefault((Func)((GameObject prefab) => (Object)(object)prefab != (Object)null && ((Object)prefab).name == "Deer")) ?? scene.GetPrefab("Deer"); if ((Object)(object)val != (Object)null) { ConfigureDeer(val); } } internal static void UpdateRideController(Tameable tameable) { Character component = ((Component)tameable).GetComponent(); if (IsDeer(component)) { ((Component)tameable).GetComponent(); if (!tameable.IsTamed() || !CanRide(component)) { tameable.m_saddleItem = null; } else { EnsureRideController(((Component)tameable).gameObject, component, tameable); } } } private static Recipe CreateWhistleRecipe(ObjectDB objectDb, ItemDrop whistle) { Recipe val = ScriptableObject.CreateInstance(); ((Object)val).name = "Recipe_FehuWhistle"; val.m_item = whistle; val.m_amount = 1; val.m_enabled = true; val.m_minStationLevel = 1; val.m_resources = (Requirement[])(object)new Requirement[3] { Requirement(objectDb, "BoneFragments", 2), Requirement(objectDb, "DeerHide", 1), Requirement(objectDb, "Resin", 1) }; return val; } private static Requirement Requirement(ObjectDB objectDb, string prefabName, int amount) { //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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown Requirement val = new Requirement(); GameObject itemPrefab = objectDb.GetItemPrefab(prefabName); val.m_resItem = ((itemPrefab != null) ? itemPrefab.GetComponent() : null); val.m_amount = amount; val.m_recover = true; return val; } private static int StableHash(string text) { int num = 5381; foreach (char c in text) { num = ((num << 5) + num) ^ c; } return num; } } internal static class ConfigSync { private static bool _registered; private static bool _applyingRemote; public static void HookSettings() { Plugin.EnableDeerTaming.SettingChanged += delegate { SendToAll(); }; Plugin.DeerTamingFoods.SettingChanged += delegate { SendToAll(); }; Plugin.MinStarsToRide.SettingChanged += delegate { SendToAll(); }; Plugin.EnableWhistle.SettingChanged += delegate { SendToAll(); }; Plugin.WhistleRange.SettingChanged += delegate { SendToAll(); }; Plugin.OnlyOwnerCanSummon.SettingChanged += delegate { SendToAll(); }; } public static void Register() { if (!_registered && ZRoutedRpc.instance != null) { _registered = true; ZRoutedRpc.instance.Register("FehuMounts_ConfigSync", (Action)Receive); ZRoutedRpc instance = ZRoutedRpc.instance; instance.m_onNewPeer = (Action)Delegate.Combine(instance.m_onNewPeer, (Action)delegate(long peerId) { SendToPeer(peerId); }); SendToAll(); } } private static void Receive(long sender, string payload) { if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer()) { return; } string[] array = payload.Split('|'); if (array.Length != 6) { return; } try { _applyingRemote = true; Plugin.EnableDeerTaming.Value = bool.Parse(array[0]); Plugin.DeerTamingFoods.Value = Encoding.UTF8.GetString(Convert.FromBase64String(array[1])); Plugin.MinStarsToRide.Value = int.Parse(array[2]); Plugin.EnableWhistle.Value = bool.Parse(array[3]); Plugin.WhistleRange.Value = float.Parse(array[4], CultureInfo.InvariantCulture); Plugin.OnlyOwnerCanSummon.Value = bool.Parse(array[5]); } finally { _applyingRemote = false; } } private static void SendToPeer(long peerId) { if (CanSend()) { ZRoutedRpc.instance.InvokeRoutedRPC(peerId, "FehuMounts_ConfigSync", new object[1] { Payload() }); } } private static void SendToAll() { if (CanSend()) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "FehuMounts_ConfigSync", new object[1] { Payload() }); } } private static bool CanSend() { if (!_applyingRemote && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { return ZRoutedRpc.instance != null; } return false; } private static string Payload() { string text = Convert.ToBase64String(Encoding.UTF8.GetBytes(Plugin.DeerTamingFoods.Value)); return string.Join("|", Plugin.EnableDeerTaming.Value.ToString(), text, Plugin.MinStarsToRide.Value.ToString(), Plugin.EnableWhistle.Value.ToString(), Plugin.WhistleRange.Value.ToString(CultureInfo.InvariantCulture), Plugin.OnlyOwnerCanSummon.Value.ToString()); } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class ZNetAwakePatch { private static void Postfix() { ConfigSync.Register(); } } internal readonly struct MountTier { public float SpeedMultiplier { get; } public float StaminaMultiplier { get; } public float StaminaDrainMultiplier { get; } public bool LegendaryRecall { get; } public MountTier(float speedMultiplier, float staminaMultiplier, float staminaDrainMultiplier, bool legendaryRecall) { SpeedMultiplier = speedMultiplier; StaminaMultiplier = staminaMultiplier; StaminaDrainMultiplier = staminaDrainMultiplier; LegendaryRecall = legendaryRecall; } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDbAwakePatch { private static void Postfix(ObjectDB __instance) { Plugin.RegisterWhistle(__instance); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetSceneAwakePatch { private static void Postfix(ZNetScene __instance) { Plugin.ConfigureDeerPrefab(__instance); Plugin.RegisterWhistleScenePrefab(__instance); } } [HarmonyPatch(typeof(ZNetScene), "GetPrefab", new Type[] { typeof(string) })] internal static class ZNetSceneGetPrefabPatch { private static void Postfix(string name, ref GameObject __result) { if ((Object)(object)__result == (Object)null && name == "FehuWhistle" && (Object)(object)ObjectDB.instance != (Object)null) { __result = ObjectDB.instance.GetItemPrefab("FehuWhistle"); } } } [HarmonyPatch(typeof(Character), "Awake")] internal static class CharacterAwakePatch { private static void Postfix(Character __instance) { if (Plugin.IsDeer(__instance)) { Plugin.ConfigureDeer(((Component)__instance).gameObject); } } } [HarmonyPatch(typeof(Character), "SetLevel")] internal static class CharacterSetLevelPatch { private static void Postfix(Character __instance) { if (Plugin.IsDeer(__instance)) { Sadle component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { Plugin.ApplyTierStats(component, __instance); } } } } [HarmonyPatch(typeof(Sadle), "IsValid")] internal static class SadleIsValidPatch { private static bool Prefix(Sadle __instance, ref bool __result) { Character character = __instance.GetCharacter(); Tameable tameable = __instance.GetTameable(); if (!Plugin.IsDeer(character)) { return true; } __result = (Object)(object)tameable != (Object)null && tameable.IsTamed() && Plugin.CanRide(character); return false; } } [HarmonyPatch(typeof(Sadle), "GetHoverText")] internal static class SadleHoverTextPatch { private static bool Prefix(Sadle __instance, ref string __result) { Character character = __instance.GetCharacter(); if (!Plugin.IsDeer(character)) { return true; } Tameable tameable = __instance.GetTameable(); if ((Object)(object)tameable == (Object)null || !tameable.IsTamed()) { __result = ""; return false; } __result = (Plugin.CanRide(character) ? "[$KEY_Use] Ride Deer" : ""); return false; } } [HarmonyPatch(typeof(Sadle), "Interact")] internal static class SadleInteractPatch { private static bool Prefix(Sadle __instance, Humanoid character, ref bool __result) { Character character2 = __instance.GetCharacter(); if (!Plugin.IsDeer(character2)) { return true; } if (Plugin.CanRide(character2) && __instance.IsValid()) { Plugin.StoreOwnerIfMissing(((Component)character2).GetComponent(), (Player?)(object)((character is Player) ? character : null)); return true; } __result = false; return false; } } [HarmonyPatch(typeof(Tameable), "Command")] internal static class TameableCommandPatch { private static void Prefix(Tameable __instance, Humanoid user) { if (Plugin.IsDeer(((Component)__instance).GetComponent())) { Plugin.StoreOwnerIfMissing(((Component)__instance).GetComponent(), (Player?)(object)((user is Player) ? user : null)); } } } [HarmonyPatch(typeof(Tameable), "Interact")] internal static class TameableInteractPatch { private static void Prefix(Tameable __instance, Humanoid user) { if (Plugin.IsDeer(((Component)__instance).GetComponent())) { Plugin.StoreOwnerIfMissing(((Component)__instance).GetComponent(), (Player?)(object)((user is Player) ? user : null)); } } } [HarmonyPatch(typeof(Tameable), "Update")] internal static class TameableUpdatePatch { private static void Postfix(Tameable __instance) { Plugin.UpdateRideController(__instance); } } [HarmonyPatch(typeof(Humanoid), "UseItem")] internal static class WhistleUsePatch { private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null || !Plugin.IsWhistle(item)) { return true; } Plugin.UseWhistle(val); return false; } } [HarmonyPatch(typeof(Sadle), "UpdateRiding")] internal static class SadleUpdateRidingPatch { private static void Prefix(Sadle __instance) { Character character = __instance.GetCharacter(); if (Plugin.IsDeer(character)) { Plugin.ApplyTierStats(__instance, character); } } } [HarmonyPatch(typeof(Character), "GetJogSpeedFactor")] internal static class CharacterJogSpeedPatch { private static void Postfix(Character __instance, ref float __result) { if (Plugin.IsDeer(__instance) && __instance.HaveRider()) { __result *= Plugin.GetTier(__instance).SpeedMultiplier; } } } [HarmonyPatch(typeof(Character), "GetRunSpeedFactor")] internal static class CharacterRunSpeedPatch { private static void Postfix(Character __instance, ref float __result) { if (Plugin.IsDeer(__instance) && __instance.HaveRider()) { __result *= Plugin.GetTier(__instance).SpeedMultiplier; } } } }