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 FehuMounts v420.0.2
FehuMounts.dll
Decompiled 19 hours agousing 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<bool> EnableDeerTaming = null; internal static ConfigEntry<string> DeerTamingFoods = null; internal static ConfigEntry<int> MinStarsToRide = null; internal static ConfigEntry<bool> EnableWhistle = null; internal static ConfigEntry<bool> RegisterWhistleItem = null; internal static ConfigEntry<float> WhistleRange = null; internal static ConfigEntry<bool> 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<string> RegisteredObjectDb = new HashSet<string>(StringComparer.Ordinal); private static readonly HashSet<string> RegisteredZNetScene = new HashSet<string>(StringComparer.Ordinal); private void Awake() { EnableDeerTaming = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDeerTaming", true, "Enable taming support for vanilla Deer."); DeerTamingFoods = ((BaseUnityPlugin)this).Config.Bind<string>("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<int>("General", "MinStarsToRide", 2, "Minimum deer stars required to ride. Vanilla level is stars + 1."); EnableWhistle = ((BaseUnityPlugin)this).Config.Bind<bool>("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<bool>("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<float>("Whistle", "WhistleRange", 80f, "Range in meters for finding an owned tamed deer."); OnlyOwnerCanSummon = ((BaseUnityPlugin)this).Config.Bind<bool>("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<Character>(); MonsterAI component2 = deer.GetComponent<MonsterAI>(); ZNetView nview = deer.GetComponent<ZNetView>(); 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<long, string, Vector3>("FehuMounts_CallMount", (Action<long, long, string, Vector3>)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<Tameable>() ?? deer.AddComponent<Tameable>(); 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<string>(); } 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<Tameable>(); 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<Sadle>() ?? deer.AddComponent<Sadle>(); 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<ZNetView>(); Character component2 = ((Component)val).GetComponent<Character>(); MonsterAI component3 = ((Component)val).GetComponent<MonsterAI>(); 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<Tameable>(); Character component2 = ((Component)nview).GetComponent<Character>(); MonsterAI component3 = ((Component)nview).GetComponent<MonsterAI>(); 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<Character>(); Tameable component2 = ((Component)allInstance).GetComponent<Tameable>(); ZNetView component3 = ((Component)allInstance).GetComponent<ZNetView>(); 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<ItemDrop>(); } 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<ItemDrop>() : 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<GameObject>(itemPrefab); ((Object)val).name = "FehuWhistle"; Object.DontDestroyOnLoad((Object)(object)val); ItemDrop component = val.GetComponent<ItemDrop>(); 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<GameObject>)scene.m_prefabs).FirstOrDefault((Func<GameObject, bool>)((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<Character>(); if (IsDeer(component)) { ((Component)tameable).GetComponent<Sadle>(); 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<Recipe>(); ((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<ItemDrop>() : 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<string>("FehuMounts_ConfigSync", (Action<long, string>)Receive); ZRoutedRpc instance = ZRoutedRpc.instance; instance.m_onNewPeer = (Action<long>)Delegate.Combine(instance.m_onNewPeer, (Action<long>)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<Sadle>(); 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) ? "[<color=yellow><b>$KEY_Use</b></color>] 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<ZNetView>(), (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<Character>())) { Plugin.StoreOwnerIfMissing(((Component)__instance).GetComponent<ZNetView>(), (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<Character>())) { Plugin.StoreOwnerIfMissing(((Component)__instance).GetComponent<ZNetView>(), (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; } } } }