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 Monster Leash v1.0.0
plugins/MonsterLeash.dll
Decompiled 15 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; 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 System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using AnimalLeash.Core; using AnimalLeash.Gameplay; using AnimalLeash.Visual; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using MonsterLeash.Core; using MonsterLeash.Dev; using MonsterLeash.Gameplay; using MonsterLeash.Visual; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("AnimalLeash")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [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 MonsterLeash { public static class Cfg { public static ConfigEntry<float> StruggleSeconds; public static ConfigEntry<int> Struggles; public static ConfigEntry<float> BaseEscape; public static ConfigEntry<float> RankFactor; public static ConfigEntry<float> BossBaseEscape; public static ConfigEntry<float> BossRankFactor; public static ConfigEntry<float> BossMaxHealth; public static ConfigEntry<float> BossMinEscape; public static ConfigEntry<float> HealthFloor; public static ConfigEntry<float> BossHealthFloor; public static ConfigEntry<float> EscapePenalty; public static ConfigEntry<string> Ranks; public static ConfigEntry<string> Never; public static ConfigEntry<bool> Peaceful; public static ConfigEntry<bool> KeepLeashed; public static readonly ConfigEntry<string>[] Cost = new ConfigEntry<string>[17]; public static readonly ConfigEntry<string>[] Station = new ConfigEntry<string>[17]; public static ConfigEntry<bool> HoverHints; public static ConfigEntry<bool> StruggleMessages; private static Dictionary<string, RankNeed> _overrides; private static string _overridesSource; private static HashSet<string> _never; private static string _neverSource; private static OddsTuning _tuning; public static Dictionary<string, RankNeed> OverrideMap { get { if (_overrides == null || _overridesSource != Ranks.Value) { _overridesSource = Ranks.Value; _overrides = RankTable.ParseOverrides(_overridesSource); } return _overrides; } } public static HashSet<string> NeverSet { get { if (_never == null || _neverSource != Never.Value) { _neverSource = Never.Value; _never = RankTable.Names(_neverSource); } return _never; } } public static OddsTuning Tuning { get { object obj = _tuning; if (obj == null) { obj = new OddsTuning { BaseEscape = BaseEscape.Value, RankFactor = RankFactor.Value, BossBaseEscape = BossBaseEscape.Value, BossRankFactor = BossRankFactor.Value, BossMaxHealth = BossMaxHealth.Value, BossMinEscape = BossMinEscape.Value, HealthFloor = HealthFloor.Value, BossHealthFloor = BossHealthFloor.Value, EscapePenalty = EscapePenalty.Value, Struggles = Struggles.Value }; _tuning = (OddsTuning)obj; } return (OddsTuning)obj; } } public static event Action RecipesChanged; public static void Bind(ConfigFile c) { //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_000d: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Expected O, but got Unknown //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Expected O, but got Unknown //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Expected O, but got Unknown //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Expected O, but got Unknown //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Expected O, but got Unknown //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Expected O, but got Unknown //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Expected O, but got Unknown //IL_03b5: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Expected O, but got Unknown //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Expected O, but got Unknown ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; StruggleSeconds = c.Bind<float>("1 - Breaking free", "StruggleSeconds", 300f, new ConfigDescription("How long a wild creature fights a fresh leash, in seconds. After that it is subdued and does not break free while it wears the leash.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 3600f), new object[1] { val })); Struggles = c.Bind<int>("1 - Breaking free", "Struggles", 10, new ConfigDescription("How many times it pulls at the leash in that time. The chance to break free is spread over all of them.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60), new object[1] { val })); BaseEscape = c.Bind<float>("1 - Breaking free", "BaseEscape", 0.75f, new ConfigDescription("Chance that a creature at full health breaks free in that time, on the rank that just unlocked it (0.75 = 75 %).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { val })); RankFactor = c.Bind<float>("1 - Breaking free", "RankFactor", 0.55f, new ConfigDescription("Each rank of the leash above the unlocking one multiplies that chance by this.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { val })); BossBaseEscape = c.Bind<float>("1 - Breaking free", "BossBaseEscape", 0.95f, new ConfigDescription("Bosses: chance to break free at the health they first take a leash, on their unlocking rank.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { val })); BossRankFactor = c.Bind<float>("1 - Breaking free", "BossRankFactor", 0.95f, new ConfigDescription("Bosses: each rank above the unlocking one multiplies their chance by this, so a boss stays hard on every leash.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { val })); BossMinEscape = c.Bind<float>("1 - Breaking free", "BossMinEscape", 0.05f, new ConfigDescription("Bosses never break free less often than this, whatever the rank and their wounds (0.05 = 5 %): a boss is never a sure catch.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { val })); BossMaxHealth = c.Bind<float>("1 - Breaking free", "BossMaxHealth", 0.25f, new ConfigDescription("Bosses take a leash only at or below this share of their health (0.25 = 25 %).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), new object[1] { val })); HealthFloor = c.Bind<float>("1 - Breaking free", "HealthFloor", 0.04f, new ConfigDescription("What is left of the chance when a creature is down to its last breath (0.04 = 4 % of it). Less health always means less chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { val })); BossHealthFloor = c.Bind<float>("1 - Breaking free", "BossHealthFloor", 0.2f, new ConfigDescription("The same for bosses: even a beaten boss keeps this share of its chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { val })); EscapePenalty = c.Bind<float>("1 - Breaking free", "EscapePenalty", 0.6f, new ConfigDescription("Each time a creature has broken free, its next leash is harder to keep: as if it pulled 60 % more often. Weaken it further to win the chance back.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), new object[1] { val })); Ranks = c.Bind<string>("2 - Creatures", "Ranks", "", new ConfigDescription("Your own ranks for creatures, as prefab:rank, comma separated, e.g. 'Troll:5, Bonemass:6!, Serpent:0'. A '!' adds boss rules (weaken first), 0 means never. Creatures of other mods get a rank from the biome they spawn in, or from their health.", (AcceptableValueBase)null, new object[1] { val })); Never = c.Bind<string>("2 - Creatures", "Never", string.Join(",", RankTable.NeverByDefault), new ConfigDescription("Creatures that never take the monster leash: sea creatures, roots, hives and dummies. Summoned helpers and Thrallhold's thralls never do anyway.", (AcceptableValueBase)null, new object[1] { val })); Peaceful = c.Bind<bool>("2 - Creatures", "PeacefulWhileHeld", true, new ConfigDescription("A wild creature that you lead, or that is tied up to keep still, attacks nobody, and players' tame animals leave it alone. Tied up free within reach it guards as a wild one: it attacks whatever comes within reach.", (AcceptableValueBase)null, new object[1] { val })); KeepLeashed = c.Bind<bool>("2 - Creatures", "NoDespawn", true, new ConfigDescription("A creature that has once worn the monster leash no longer vanishes at daybreak or when its raid ends.", (AcceptableValueBase)null, new object[1] { val })); for (int i = 0; i < 17; i++) { int num = i + 1; Cost[i] = c.Bind<string>("3 - Recipes", "Rank" + num, RankRecipes.Cost[i], new ConfigDescription((num == 1) ? "Cost of the monster leash (rank 1)." : $"Cost of the upgrade to rank {num}.", (AcceptableValueBase)null, new object[1] { val })); Station[i] = c.Bind<string>("3 - Recipes", "Rank" + num + "Station", RankRecipes.Station[i], new ConfigDescription((num == 1) ? "Where the monster leash is made: station prefab and level." : $"Where it is upgraded to rank {num}: station prefab and level.", (AcceptableValueBase)null, new object[1] { val })); } HoverHints = c.Bind<bool>("4 - Client", "HoverHints", true, "While you carry a monster leash, a wild creature's hover text says whether your leash holds it."); StruggleMessages = c.Bind<bool>("4 - Client", "StruggleMessages", true, "A message in the middle of the screen each time your creature pulls at the leash."); c.SettingChanged += delegate(object _, SettingChangedEventArgs a) { if (a != null) { ConfigEntryBase changedSetting = a.ChangedSetting; if (((changedSetting != null) ? new bool?(changedSetting.Definition.Section.StartsWith("3")) : ((bool?)null)) == true) { Cfg.RecipesChanged?.Invoke(); } } _overrides = null; _never = null; _tuning = null; }; SynchronizationManager.OnConfigurationSynchronized += delegate { _overrides = null; _never = null; _tuning = null; Cfg.RecipesChanged?.Invoke(); }; } } public static class Lang { private static readonly (string key, string en, string de)[] Texts = new(string, string, string)[28] { ("ml_item_leash", "Monster leash", "Monsterleine"), ("ml_item_leash_desc", "A chain of black metal with a spiked iron collar, made to hold what was never tame. Upgrade it rank by rank with the materials of each land, and it holds ever greater beasts – at the last rank it is Gleipnir, the fetter that bound Fenrir.", "Eine Kette aus Schwarzmetall mit einem eisernen Stachelhalsband, gemacht für das, was nie zahm war. Werte sie Rang um Rang mit den Stoffen jedes Landes auf, und sie hält immer größere Bestien – im letzten Rang ist sie Gleipnir, die Fessel, die Fenrir hielt."), ("ml_tt_rank", "<color=orange>Rank {0} of {1}</color>", "<color=orange>Rang {0} von {1}</color>"), ("ml_tt_gleipnir", "<color=orange>Rank {0} of {1} – Gleipnir</color>", "<color=orange>Rang {0} von {1} – Gleipnir</color>"), ("ml_tt_use", "Use it from the hotbar while you look at a creature, wild or tame. Tied fast it reaches {0} m.", "Benutze sie aus der Schnellleiste, während du ein Wesen ansiehst, wild oder zahm. Angebunden reicht sie {0} m."), ("ml_tt_new", "This rank holds: {0}", "Dieser Rang hält: {0}"), ("ml_tt_newboss", "Bosses: {0} – only below {1} % health", "Bosse: {0} – nur unter {1} % Leben"), ("ml_tt_rule", "A wild creature fights a fresh leash for {0} min. Each rank above the one it needs, and every wound you give it, makes it less likely to break free.", "Ein wildes Wesen kämpft {0} min gegen eine frische Leine. Jeder Rang über dem nötigen und jede Wunde, die du ihm schlägst, macht ein Losreißen unwahrscheinlicher."), ("ml_tt_next", "Rank {0}: {1}", "Rang {0}: {1}"), ("ml_msg_needmonster", "Only a monster leash holds a wild creature ({0})", "Nur eine Monsterleine hält ein wildes Wesen ({0})"), ("ml_msg_never", "No leash holds {0}", "Keine Leine hält {0}"), ("ml_msg_rank", "Your leash is too weak for {0}: it needs rank {1}", "Deine Leine ist zu schwach für {0}: Sie braucht Rang {1}"), ("ml_msg_weaken", "Weaken {0} first: below {2} % health", "Schwäche {0} erst: unter {2} % Leben"), ("ml_msg_pull", "{0} pulls at the leash!", "{0} zerrt an der Leine!"), ("ml_msg_free", "{0} has broken free!", "{0} hat sich losgerissen!"), ("ml_msg_subdued", "{0} is subdued", "{0} ist gebändigt"), ("ml_hover_struggle", "<color=orange>Fights the leash – {0}</color> · danger: {1}", "<color=orange>Wehrt sich – {0}</color> · Ausbruchgefahr: {1}"), ("ml_hover_subdued", "<color=#b0b0b0>Subdued (monster leash, rank {0})</color>", "<color=#b0b0b0>Gebändigt (Monsterleine, Rang {0})</color>"), ("ml_hover_never", "<color=#b0b0b0>No leash holds it</color>", "<color=#b0b0b0>Keine Leine hält es</color>"), ("ml_hover_rank", "<color=#e06060>Needs a monster leash of rank {0}</color>", "<color=#e06060>Braucht eine Monsterleine von Rang {0}</color>"), ("ml_hover_weaken", "<color=orange>Weaken it first: below {0} % health (now {1} %)</color>", "<color=orange>Erst schwächen: unter {0} % Leben (jetzt {1} %)</color>"), ("ml_hover_usehint", "<color=#b0b0b0>Your monster leash (rank {0}) holds it</color> · danger: {1}", "<color=#b0b0b0>Deine Monsterleine (Rang {0}) hält es</color> · Ausbruchgefahr: {1}"), ("ml_hover_escaped", "<color=#e06060>Broke free {0}× – weaken it more</color>", "<color=#e06060>{0}× losgerissen – schwäche es stärker</color>"), ("ml_danger_0", "none", "keine"), ("ml_danger_1", "low", "gering"), ("ml_danger_2", "medium", "mittel"), ("ml_danger_3", "<color=orange>high</color>", "<color=orange>hoch</color>"), ("ml_danger_4", "<color=#e06060>very high</color>", "<color=#e06060>sehr hoch</color>") }; public static void Register() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); Dictionary<string, string> dictionary2 = new Dictionary<string, string>(); (string, string, string)[] texts = Texts; for (int i = 0; i < texts.Length; i++) { (string, string, string) tuple = texts[i]; string item = tuple.Item1; string item2 = tuple.Item2; string item3 = tuple.Item3; dictionary[item] = item2; dictionary2[item] = item3; } string text = "English"; localization.AddTranslation(ref text, dictionary); text = "German"; localization.AddTranslation(ref text, dictionary2); } public static string L(string token) { if (Localization.instance == null) { return token; } return Localization.instance.Localize(token); } public static string T(string token, params object[] args) { string text = ((Localization.instance != null) ? Localization.instance.Localize("$" + token) : token); if (args == null || args.Length == 0) { return text; } try { return string.Format(text, args); } catch (FormatException) { return text; } } } [BepInPlugin("zap.monsterleash", "MonsterLeash", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class MonsterLeashPlugin : BaseUnityPlugin { public const string PluginGuid = "zap.monsterleash"; public const string PluginName = "MonsterLeash"; public const string PluginVersion = "1.0.0"; public const string AnimalLeashGuid = "zap.animalleash"; private Harmony _harmony; public static MonsterLeashPlugin Instance { get; private set; } public static string PluginDir { get; private set; } public static ManualLogSource Log { get; private set; } public static string AssetPath(string fileName) { return Path.Combine(PluginDir ?? "", "Assets", fileName); } private void Awake() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; PluginDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); Cfg.Bind(((BaseUnityPlugin)this).Config); Lang.Register(); Item.Init(); _harmony = new Harmony("zap.monsterleash"); _harmony.PatchAll(typeof(MonsterLeashPlugin).Assembly); SelfTest.TryStart(((Component)this).gameObject); } private void Update() { Hooks.Sweep(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } } namespace MonsterLeash.Visual { internal static class LeashModel { public static GameObject Build() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) GameObject val = Models.LeashItem((LeashKind)3); PartSet val2 = new PartSet(); Quaternion val3 = Quaternion.Euler(6f, 25f, -4f); Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(0.01f, 0.05f, 0f); MeshKit.Torus(val2[Mats.Leather], val4 + Vector3.up * 0.012f, val3, 0.075f, 0.017f, 22, 6, 3f, 1f); MeshKit.Torus(val2[Mats.Iron], val4 + Vector3.up * 0.024f, val3, 0.077f, 0.009f, 22, 6, 3f, 1f); for (int i = 0; i < 8; i++) { float num = (float)i * (float)Math.PI * 2f / 8f; Vector3 val5 = val3 * new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)); Vector3 val6 = val4 + Vector3.up * 0.018f + val5 * 0.088f; MeshKit.Cylinder(val2[Mats.Iron], val6, val6 + val5 * 0.035f + Vector3.up * 0.006f, 0.009f, 0.0008f, 8, true, true, 1f, 1f, false); } val2.Emit(val.transform, "spikes"); return val; } } } namespace MonsterLeash.Gameplay { public static class Hooks { [HarmonyPatch] private static class WildPasses { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Leash), "UseLeash", (Type[])null, (Type[])null); yield return AccessTools.PropertyGetter(typeof(Leash), "CanWear"); yield return AccessTools.Method(typeof(Leash), "Hover", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Patches), "UseOn", (Type[])null, (Type[])null); MethodInfo methodInfo = AccessTools.Method("AnimalLeash.Gameplay.Patches+HoverWithoutTameable:Postfix", (Type[])null, (Type[])null); if (methodInfo != null) { yield return methodInfo; } } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> code, MethodBase original) { MethodInfo isTamed = AccessTools.Method(typeof(Character), "IsTamed", Type.EmptyTypes, (Type[])null); MethodInfo ours = AccessTools.Method(typeof(Hooks), "TameEnough", (Type[])null, (Type[])null); int n = 0; foreach (CodeInstruction item in code) { if ((item.opcode == OpCodes.Callvirt || item.opcode == OpCodes.Call) && item.operand is MethodInfo methodInfo && methodInfo == isTamed) { n++; yield return new CodeInstruction(OpCodes.Call, (object)ours) { labels = item.labels, blocks = item.blocks }; } else { yield return item; } } if (n == 0) { MonsterLeashPlugin.Log.LogWarning((object)("No tame check found in " + original.DeclaringType?.Name + "." + original.Name + " (Animal Leash changed?).")); } } } [HarmonyPatch(typeof(Patches), "UseOn")] private static class GiveWildOneALeash { private static void Prefix(Character c, ItemData item) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)c == (Object)null || c.IsTamed() || !Item.Is(item) || (Object)(object)((Component)c).GetComponent<Leash>() != (Object)null || Ranks.For(c).Never) { return; } try { Patches.TryAttach(((Component)c).gameObject); ZNetView nview = c.m_nview; if ((Object)(object)nview != (Object)null && nview.IsValid() && !nview.IsOwner() && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(nview.GetZDO().GetOwner(), "ML_Attach", new object[1] { nview.GetZDO().m_uid }); } } catch (Exception ex) { MonsterLeashPlugin.Log.LogWarning((object)("Leash on " + ((Object)c).name + ": " + ex.Message)); } } } [HarmonyPatch(typeof(Game), "Start")] private static class RegisterAttach { private static void Postfix() { try { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.Register<ZDOID>("ML_Attach", (Action<long, ZDOID>)RPC_Attach); } } catch (Exception ex) { MonsterLeashPlugin.Log.LogWarning((object)("RPC: " + ex.Message)); } } } [HarmonyPatch(typeof(Leash), "UseLeash")] private static class WildRules { [HarmonyPriority(600)] private static bool Prefix(Leash __instance, Player p, ItemData item, ref bool __result) { _usingRank = Item.RankOf(item); _usingWild = false; _allowing = null; Character character = __instance.Character; if ((Object)(object)p == (Object)null || (Object)(object)character == (Object)null || character.IsTamed()) { return true; } if (__instance.Valid && __instance.Wearing) { return true; } if (!Item.Is(item)) { ((Character)p).Message((MessageType)2, Lang.T("ml_msg_needmonster", __instance.Name), 0, (Sprite)null, false); __result = true; return false; } string text = RefusalText(character, _usingRank); if (text != null) { ((Character)p).Message((MessageType)2, text, 0, (Sprite)null, false); __result = true; return false; } _usingWild = true; _allowing = character; return true; } private static void Finalizer() { _allowing = null; _usingRank = 0; _usingWild = false; } } [HarmonyPatch(typeof(Leash), "Send")] private static class TellOwner { private static void Prefix(Leash __instance, LeashOp op, out int __state) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Invalid comparison between Unknown and I4 __state = Leash.Waiting.Count; _sending = null; if (!__instance.Valid) { return; } int rank = (((int)op == 1) ? _usingRank : __instance.Zdo.GetInt(Keys.Rank, 0)); _sending = new Sending { Animal = __instance.Zdo.m_uid, Op = op, Rank = rank }; if ((int)op != 1) { return; } try { __instance.NView.InvokeRPC("ML_PutOn", new object[2] { _usingRank, _usingWild }); } catch (Exception ex) { MonsterLeashPlugin.Log.LogWarning((object)("Monster leash rank: " + ex.Message)); } } private static void Postfix(Leash __instance, int __state) { Sending sending = _sending; _sending = null; if (sending != null && sending.Rank > 0 && Leash.Waiting.Count > __state) { PendingRanks[Leash.Waiting[Leash.Waiting.Count - 1]] = sending.Rank; } } } private sealed class Sending { public ZDOID Animal; public LeashOp Op; public int Rank; } [HarmonyPatch(typeof(Leash), "RPC_Request")] private static class RankPerRequest { private static void Prefix(Leash __instance, long sender, ZPackage pkg, out Wild __state) { __state = null; if (!__instance.IsOwner || pkg == null) { return; } int pos = pkg.GetPos(); int num = pkg.ReadInt(); pkg.SetPos(pos); if (num == 1) { Wild component = ((Component)__instance).GetComponent<Wild>(); if ((Object)(object)component != (Object)null && component.BeforePutOn(sender)) { __state = component; } } } private static void Postfix(Wild __state) { if ((Object)(object)__state != (Object)null) { __state.AfterPutOn(); } } } [HarmonyPatch(typeof(Leash), "HandOver")] private static class HandOverRank { private static void Prefix(Leash __instance) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) if (!__instance.IsOwner || !__instance.Wearing) { return; } Wild component = ((Component)__instance).GetComponent<Wild>(); if ((Object)(object)component == (Object)null || (component.Rank <= 0 && !component.IsWild)) { return; } foreach (Leash item in Leash.All) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)__instance) && item.Valid && item.IsOwner && !item.Wearing && item._bornFrame == Time.frameCount && !(Vector3.Distance(((Component)item).transform.position, ((Component)__instance).transform.position) > 0.6f)) { component.CopyTo(item.Zdo); break; } } } } [HarmonyPatch] private static class GiveBackWithRank { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Leash), "RPC_Answer", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Leash), "TickWaiting", (Type[])null, (Type[])null); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> code, MethodBase original) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown FieldInfo objB = AccessTools.Field(typeof(Pending), "Kind"); MethodInfo methodInfo = AccessTools.Method(typeof(Leash), "GiveLeash", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Hooks), "GiveBack", (Type[])null, (Type[])null); List<CodeInstruction> list = new List<CodeInstruction>(code); int num = 0; for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Ldfld && object.Equals(list[i].operand, objB) && CodeInstructionExtensions.Calls(list[i + 1], methodInfo)) { list[i + 1] = new CodeInstruction(OpCodes.Call, (object)methodInfo2) { labels = list[i + 1].labels, blocks = list[i + 1].blocks }; list[i] = new CodeInstruction(OpCodes.Nop, (object)null) { labels = list[i].labels, blocks = list[i].blocks }; num++; } } if (num == 0) { MonsterLeashPlugin.Log.LogWarning((object)("No leash refund found in " + original.Name + " (Animal Leash changed?).")); } return list; } } [HarmonyPatch(typeof(Leash), "DropOnDeath")] private static class DropWithRank { private static bool Prefix(Leash __instance) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) if (!__instance.IsOwner || !__instance.Wearing) { return true; } int num = __instance.Zdo.GetInt(Keys.Rank, 0); if (num <= 0) { return true; } __instance.Zdo.Set(Keys.State, 0, false); __instance.Zdo.Set(Keys.Rank, 0, false); __instance.Zdo.Set(Keys.Wild, false); Item.Drop(num, ((Component)__instance).transform.position); return false; } } [HarmonyPatch(typeof(Items), "KindOf")] private static class MonsterLeashIsALeash { private static void Postfix(ItemData item, ref LeashKind kind, ref bool __result) { if (!__result && Item.Is(item)) { kind = (LeashKind)RankRecipes.LookOf(Item.RankOf(item)); __result = true; } } } [HarmonyPatch] private static class OwnTooltip { private static MethodBase TargetMethod() { return AccessTools.Method("AnimalLeash.Gameplay.Items+Tooltip:Postfix", (Type[])null, (Type[])null); } private static bool Prefix(ItemData item) { return !Item.Is(item); } } [HarmonyPatch(typeof(Patches), "Attach")] private static class WildBesideLeash { private static void Postfix(GameObject go) { if ((Object)(object)go != (Object)null && (Object)(object)go.GetComponent<Wild>() == (Object)null) { go.AddComponent<Wild>(); } } } [HarmonyPatch(typeof(BaseAI), "Awake")] private static class LeashOnWildWearer { [HarmonyAfter(new string[] { "zap.animalleash" })] private static void Postfix(BaseAI __instance) { try { ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val != null && !((Object)(object)((Component)__instance).GetComponent<Leash>() != (Object)null) && (val.GetInt(Keys.State, 0) != 0 || val.GetBool(Keys.Wild, false) || val.GetBool(Keys.Kept, false))) { Patches.TryAttach(((Component)__instance).gameObject); } } catch (Exception ex) { MonsterLeashPlugin.Log.LogWarning((object)("Leash on " + ((Object)__instance).name + ": " + ex.Message)); } } } [HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[] { typeof(Character), typeof(Character) })] private static class HeldIsNoFoe { private static void Postfix(Character a, Character b, ref bool __result) { if (__result && Wild.Held.Count != 0 && !((Object)(object)a == (Object)null) && !((Object)(object)b == (Object)null) && ((Wild.Held.Contains(a) && OnOurSide(b)) || (Wild.Held.Contains(b) && OnOurSide(a)))) { __result = false; } } private static bool OnOurSide(Character c) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (!c.IsPlayer() && !c.IsTamed() && (int)c.m_faction != 0) { return Wild.Held.Contains(c); } return true; } } [HarmonyPatch(typeof(Character), "TakeOff")] private static class NoTakeOffOnTheLeash { private static bool Prefix(Character __instance) { Wild component = ((Component)__instance).GetComponent<Wild>(); if ((Object)(object)component == (Object)null || !component.IsWild || (Object)(object)component.Leash == (Object)null || !component.Leash.Holds) { return true; } return __instance.HaveRider(); } } [HarmonyPatch(typeof(Character), "GetHoverText")] private static class WildHover { [HarmonyAfter(new string[] { "zap.animalleash" })] [HarmonyPriority(200)] private static void Postfix(Character __instance, ref string __result) { try { if (__instance.IsTamed() || __instance.IsPlayer()) { return; } Wild component = ((Component)__instance).GetComponent<Wild>(); string text = (((Object)(object)component != (Object)null && component.IsWild && (Object)(object)component.Leash != (Object)null && component.Leash.Wearing) ? StruggleLine(component) : Hint(__instance, component)); if (!string.IsNullOrEmpty(text)) { if (string.IsNullOrEmpty(__result)) { __result = Lang.L(__instance.GetHoverName()); } __result = __result + "\n" + text; } } catch (Exception ex) { MonsterLeashPlugin.Log.LogWarning((object)("Hover: " + ex.Message)); } } } private static Character _allowing; private static int _usingRank; private static bool _usingWild; public const string RpcAttach = "ML_Attach"; private static Sending _sending; private static readonly Dictionary<Pending, int> PendingRanks = new Dictionary<Pending, int>(); private static float _nextSweep; private static int _best; private static float _bestUntil; public static bool TameEnough(Character c) { if ((Object)(object)c == (Object)null) { return false; } if (c.IsTamed()) { return true; } if ((Object)(object)c == (Object)(object)_allowing) { return true; } ZNetView nview = c.m_nview; if ((Object)(object)nview != (Object)null && nview.IsValid() && nview.GetZDO() != null) { return nview.GetZDO().GetBool(Keys.Wild, false); } return false; } public static string Refusal(Character c, int rank) { if ((Object)(object)c == (Object)null || c.IsDead()) { return "ml_msg_never"; } RankNeed rankNeed = Ranks.For(c); if (rankNeed.Never || !Patches.Eligible(((Component)c).gameObject)) { return "ml_msg_never"; } if (rank < rankNeed.Rank) { return "ml_msg_rank"; } if (rankNeed.Boss && c.GetHealthPercentage() > Cfg.BossMaxHealth.Value + 0.0001f) { return "ml_msg_weaken"; } return null; } public static string RefusalText(Character c, int rank) { string text = Refusal(c, rank); if (text == null) { return null; } string text2 = (((Object)(object)c != (Object)null) ? Lang.L(c.GetHoverName()) : "?"); RankNeed rankNeed = Ranks.For(c); return Lang.T(text, text2, rankNeed.Rank, Mathf.RoundToInt(Cfg.BossMaxHealth.Value * 100f)); } internal static void RPC_Attach(long sender, ZDOID id) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNetScene.instance == (Object)null) { return; } GameObject val = ZNetScene.instance.FindInstance(id); Character val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Character>() : null); if ((Object)(object)val2 == (Object)null || val2.IsPlayer() || (Object)(object)((Component)val2).GetComponent<Leash>() != (Object)null || Ranks.For(val2).Never) { return; } try { Patches.TryAttach(val); } catch (Exception ex) { MonsterLeashPlugin.Log.LogWarning((object)("Leash on " + ((Object)val2).name + ": " + ex.Message)); } } public static void GiveBack(Player p, Pending q) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_005f: Unknown result type (might be due to invalid IL or missing references) if (q != null && PendingRanks.TryGetValue(q, out var value)) { PendingRanks.Remove(q); Item.Give(p, value); } else if (q != null && _sending != null && _sending.Rank > 0 && _sending.Animal == q.Animal && _sending.Op == q.Op) { Item.Give(p, _sending.Rank); } else { Leash.GiveLeash(p, (LeashKind)((q != null) ? ((int)q.Kind) : 0)); } } public static void Sweep() { if (Time.time < _nextSweep || (Object)(object)ZNetScene.instance == (Object)null) { return; } _nextSweep = Time.time + 2f; if (PendingRanks.Count > 0) { foreach (Pending item in new List<Pending>(PendingRanks.Keys)) { if (!Leash.Waiting.Contains(item)) { PendingRanks.Remove(item); } } } foreach (Character allCharacter in Character.GetAllCharacters()) { if ((Object)(object)allCharacter == (Object)null || allCharacter.IsPlayer() || (Object)(object)((Component)allCharacter).GetComponent<Leash>() != (Object)null) { continue; } ZNetView nview = allCharacter.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.GetZDO() != null && nview.GetZDO().GetInt(Keys.State, 0) != 0) { try { Patches.TryAttach(((Component)allCharacter).gameObject); } catch (Exception ex) { MonsterLeashPlugin.Log.LogWarning((object)("Leash on " + ((Object)allCharacter).name + ": " + ex.Message)); } } } } private static string StruggleLine(Wild w) { if (w.Subdued) { return Lang.T("ml_hover_subdued", w.Rank); } float num = Mathf.Max(0f, w.Left); string text = $"{(int)(num / 60f)}:{(int)(num % 60f):00}"; return Lang.T("ml_hover_struggle", text, DangerWord(Odds.Rate(w.ChanceLeft()))); } private static string Hint(Character c, Wild w) { Player localPlayer = Player.m_localPlayer; if (!Cfg.HoverHints.Value || (Object)(object)localPlayer == (Object)null) { return null; } if (Time.time >= _bestUntil) { _best = Item.BestCarried(localPlayer); _bestUntil = Time.time + 0.5f; } int best = _best; if (best == 0) { return null; } RankNeed rankNeed = Ranks.For(c); if (rankNeed.Never || !Patches.Eligible(((Component)c).gameObject)) { return Lang.T("ml_hover_never"); } if (best < rankNeed.Rank) { return Lang.T("ml_hover_rank", rankNeed.Rank); } StringBuilder stringBuilder = new StringBuilder(); if (rankNeed.Boss && c.GetHealthPercentage() > Cfg.BossMaxHealth.Value + 0.0001f) { stringBuilder.Append(Lang.T("ml_hover_weaken", Mathf.RoundToInt(Cfg.BossMaxHealth.Value * 100f), Mathf.RoundToInt(c.GetHealthPercentage() * 100f))); } else { int escapes = (((Object)(object)w != (Object)null) ? w.Escapes : (((Object)(object)c.m_nview != (Object)null && c.m_nview.GetZDO() != null) ? c.m_nview.GetZDO().GetInt(Keys.Escapes, 0) : 0)); double total = Odds.Escape(Cfg.Tuning, best - rankNeed.Rank, rankNeed.Boss, c.GetHealthPercentage(), escapes); stringBuilder.Append(Lang.T("ml_hover_usehint", best, DangerWord(Odds.Rate(total)))); } int num = (((Object)(object)c.m_nview != (Object)null && c.m_nview.GetZDO() != null) ? c.m_nview.GetZDO().GetInt(Keys.Escapes, 0) : 0); if (num > 0) { stringBuilder.Append('\n').Append(Lang.T("ml_hover_escaped", num)); } return stringBuilder.ToString(); } public static string DangerWord(Danger d) { int num = (int)d; return Lang.T("ml_danger_" + num); } } public static class Item { [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class AddToObjectDB { [HarmonyPriority(0)] private static void Postfix() { Apply(); } } [HarmonyPatch] private static class UpgradeByRank { [HarmonyPatch(typeof(Requirement), "GetAmount")] [HarmonyPostfix] private static void Amount(Requirement __instance, int qualityLevel, ref int __result) { if (Amounts.Count != 0 && Amounts.TryGetValue(__instance, out var value)) { __result = value[RankRecipes.Clamp(qualityLevel)]; } } [HarmonyPatch(typeof(Recipe), "GetRequiredStation")] [HarmonyPostfix] private static void Where(Recipe __instance, int quality, ref CraftingStation __result) { if (quality > 1 && Stations.TryGetValue(__instance, out (CraftingStation, int)[] value)) { __result = value[RankRecipes.Clamp(quality)].Item1; } } [HarmonyPatch(typeof(Recipe), "GetRequiredStationLevel")] [HarmonyPostfix] private static void Level(Recipe __instance, int quality, ref int __result) { if (Stations.TryGetValue(__instance, out (CraftingStation, int)[] value) && (quality > 1 || !((Object)(object)__instance != (Object)(object)Recipes[0]))) { __result = value[RankRecipes.Clamp(quality)].Item2; } } } [HarmonyPatch(typeof(InventoryGui), "AddRecipeToList")] private static class ListOnlyWhereMade { private static bool Prefix(Recipe recipe, ItemData item) { if (!Stations.TryGetValue(recipe, out (CraftingStation, int)[] value)) { return true; } if (item == null) { return (Object)(object)recipe == (Object)(object)Recipes[0]; } int num = item.m_quality + 1; if (num > 17) { return (Object)(object)recipe == (Object)(object)Recipes[0]; } return (Object)(object)value[num].Item1 == (Object)(object)recipe.m_craftingStation; } } [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int), typeof(bool) })] private static class Tooltip { private static void Postfix(ItemData item, int qualityLevel, ref string __result) { if (!Is(item)) { return; } try { __result = __result + "\n\n" + TooltipFor(RankRecipes.Clamp(qualityLevel)); } catch (Exception ex) { MonsterLeashPlugin.Log.LogWarning((object)("Tooltip: " + ex.Message)); } } } public const string Prefab = "ML_MonsterLeash"; public const string Token = "$ml_item_leash"; private const string BasePrefab = "LeatherScraps"; private static readonly List<Recipe> Recipes = new List<Recipe>(); private static readonly Dictionary<Recipe, (CraftingStation st, int level)[]> Stations = new Dictionary<Recipe, (CraftingStation, int)[]>(); private static readonly Dictionary<Requirement, int[]> Amounts = new Dictionary<Requirement, int[]>(); public static void Init() { PrefabManager.OnVanillaPrefabsAvailable += Add; Cfg.RecipesChanged += Apply; } public static bool Is(ItemData item) { if (item != null) { if (!(item.m_shared?.m_name == "$ml_item_leash")) { if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name == "ML_MonsterLeash"; } return false; } return true; } return false; } public static int RankOf(ItemData item) { if (!Is(item)) { return 0; } return RankRecipes.Clamp(item.m_quality); } private static void Add() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = LeashModel.Build(); Sprite val2 = (GUIManager.IsHeadless() ? null : Items.RenderIcon(val, Quaternion.Euler(38f, 150f, 0f))); CustomItem val3 = new CustomItem("ML_MonsterLeash", "LeatherScraps"); if ((Object)(object)val3.ItemPrefab == (Object)null) { Object.Destroy((Object)(object)val); MonsterLeashPlugin.Log.LogError((object)"Cloning LeatherScraps failed: no ML_MonsterLeash."); return; } Items.Reskin(val3.ItemPrefab, val); SharedData shared = val3.ItemDrop.m_itemData.m_shared; shared.m_name = "$ml_item_leash"; shared.m_description = "$ml_item_leash_desc"; shared.m_itemType = (ItemType)16; shared.m_maxStackSize = 1; shared.m_maxQuality = 17; shared.m_useDurability = false; shared.m_weight = 3f; shared.m_value = 0; shared.m_teleportable = true; shared.m_questItem = false; if ((Object)(object)val2 != (Object)null) { shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 }; } ItemManager.Instance.AddItem(val3); } catch (Exception ex) { MonsterLeashPlugin.Log.LogError((object)("Could not register the monster leash: " + ex)); } finally { PrefabManager.OnVanillaPrefabsAvailable -= Add; } } public static ItemData Make(int rank) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab("ML_MonsterLeash") : null); if ((Object)(object)val == (Object)null) { return null; } ItemData obj = val.GetComponent<ItemDrop>().m_itemData.Clone(); obj.m_dropPrefab = val; obj.m_quality = RankRecipes.Clamp(rank); obj.m_stack = 1; obj.m_durability = obj.GetMaxDurability(); return obj; } public static void Give(Player p, int rank) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) ItemData val = Make(rank); if (!((Object)(object)p == (Object)null) && val != null) { Inventory inventory = ((Humanoid)p).GetInventory(); if (!inventory.CanAddItem(val, -1) || !inventory.AddItem(val)) { ItemDrop.DropItem(val, 1, ((Component)p).transform.position + ((Component)p).transform.forward * 0.5f + Vector3.up, Quaternion.identity); } } } public static void Drop(int rank, Vector3 at) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) ItemData val = Make(rank); if (val != null) { ItemDrop.DropItem(val, 1, at + Vector3.up * 0.8f, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f)); } } public static int BestCarried(Player p) { int num = 0; if ((Object)(object)p == (Object)null) { return 0; } foreach (ItemData allItem in ((Humanoid)p).GetInventory().GetAllItems()) { if (Is(allItem)) { num = Math.Max(num, RankOf(allItem)); } } return num; } public static void Apply() { //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Unknown result type (might be due to invalid IL or missing references) //IL_03fa: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Expected O, but got Unknown ObjectDB db = ObjectDB.instance; if ((Object)(object)db == (Object)null || db.m_items == null || db.m_items.Count == 0) { return; } try { foreach (Recipe recipe in Recipes) { db.m_recipes.Remove(recipe); Object.Destroy((Object)(object)recipe); } Recipes.Clear(); Stations.Clear(); Amounts.Clear(); GameObject itemPrefab = db.GetItemPrefab("ML_MonsterLeash"); if ((Object)(object)itemPrefab == (Object)null) { return; } (CraftingStation, int)[] array = new(CraftingStation, int)[18]; List<KeyValuePair<string, int>>[] array2 = new List<KeyValuePair<string, int>>[18]; for (int i = 1; i <= 17; i++) { KeyValuePair<string, int> keyValuePair = RecipeText.Station(Cfg.Station[i - 1].Value); CraftingStation val = StationOf(keyValuePair.Key); if ((Object)(object)val == (Object)null) { MonsterLeashPlugin.Log.LogWarning((object)$"Monster leash rank {i}: no crafting station '{keyValuePair.Key}', using {RankRecipes.Station[i - 1]}."); KeyValuePair<string, int> keyValuePair2 = RecipeText.Station(RankRecipes.Station[i - 1]); val = StationOf(keyValuePair2.Key); keyValuePair = keyValuePair2; } array[i] = (val, Math.Max(1, keyValuePair.Value)); array2[i] = (from kv in RecipeText.Parse(Cfg.Cost[i - 1].Value) where (Object)(object)db.GetItemPrefab(kv.Key) != (Object)null select kv).ToList(); foreach (KeyValuePair<string, int> item in RecipeText.Parse(Cfg.Cost[i - 1].Value)) { if ((Object)(object)db.GetItemPrefab(item.Key) == (Object)null) { MonsterLeashPlugin.Log.LogWarning((object)$"Monster leash rank {i}: no item '{item.Key}'."); } } if (array2[i].Count == 0) { array2[i] = (from kv in RecipeText.Parse(RankRecipes.Cost[i - 1]) where (Object)(object)db.GetItemPrefab(kv.Key) != (Object)null select kv).ToList(); } } List<CraftingStation> list = new List<CraftingStation>(); for (int num = 1; num <= 17; num++) { if ((Object)(object)array[num].Item1 != (Object)null && !list.Contains(array[num].Item1)) { list.Add(array[num].Item1); } } foreach (CraftingStation item2 in list) { Recipe val2 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val2).name = "Recipe_ML_MonsterLeash" + ((Recipes.Count == 0) ? "" : ("_" + ((Object)item2).name)); val2.m_item = itemPrefab.GetComponent<ItemDrop>(); val2.m_amount = 1; val2.m_enabled = true; val2.m_craftingStation = item2; val2.m_repairStation = item2; val2.m_minStationLevel = ((Recipes.Count != 0) ? 1 : array[1].Item2); List<Requirement> list2 = new List<Requirement>(); Dictionary<string, Requirement> dictionary = new Dictionary<string, Requirement>(); for (int num2 = 1; num2 <= 17; num2++) { foreach (KeyValuePair<string, int> item3 in array2[num2]) { if (!dictionary.TryGetValue(item3.Key, out var value)) { value = new Requirement { m_resItem = db.GetItemPrefab(item3.Key).GetComponent<ItemDrop>(), m_amount = 0, m_amountPerLevel = 0, m_recover = false }; dictionary[item3.Key] = value; list2.Add(value); Amounts[value] = new int[18]; } Amounts[value][num2] = item3.Value; } } foreach (Requirement item4 in list2) { item4.m_amount = Amounts[item4][1]; } val2.m_resources = list2.ToArray(); db.m_recipes.Add(val2); Recipes.Add(val2); Stations[val2] = array; } } catch (Exception ex) { MonsterLeashPlugin.Log.LogError((object)("Could not set up the monster leash recipes: " + ex)); } } private static CraftingStation StationOf(string name) { if (string.IsNullOrEmpty(name)) { return null; } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(name) : PrefabManager.Instance.GetPrefab(name)); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<CraftingStation>(); } public static string TooltipFor(int rank) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(Lang.T((rank == 17) ? "ml_tt_gleipnir" : "ml_tt_rank", rank, 17)); stringBuilder.Append('\n').Append(Lang.T("ml_tt_use", Kinds.TieLength((LeashKind)RankRecipes.LookOf(rank)).ToString("0.#"))); string text = Ranks.NamesAt(rank, bosses: false); if (text.Length > 0) { stringBuilder.Append('\n').Append(Lang.T("ml_tt_new", text)); } string text2 = Ranks.NamesAt(rank, bosses: true); if (text2.Length > 0) { stringBuilder.Append('\n').Append(Lang.T("ml_tt_newboss", text2, Mathf.RoundToInt(Cfg.BossMaxHealth.Value * 100f))); } stringBuilder.Append('\n').Append(Lang.T("ml_tt_rule", (Cfg.StruggleSeconds.Value / 60f).ToString("0.#"))); if (rank < 17) { string text3 = Ranks.NamesAt(rank + 1, bosses: false); string text4 = Ranks.NamesAt(rank + 1, bosses: true); string text5 = ((text3.Length > 0 && text4.Length > 0) ? (text3 + ", " + text4) : (text3 + text4)); if (text5.Length > 0) { stringBuilder.Append('\n').Append(Lang.T("ml_tt_next", rank + 1, text5)); } } return stringBuilder.ToString(); } } public static class Keys { public static readonly int Rank = StringExtensionMethods.GetStableHashCode("ml_rank"); public static readonly int Wild = StringExtensionMethods.GetStableHashCode("ml_wild"); public static readonly int Left = StringExtensionMethods.GetStableHashCode("ml_left"); public static readonly int Done = StringExtensionMethods.GetStableHashCode("ml_done"); public static readonly int Subdued = StringExtensionMethods.GetStableHashCode("ml_subdued"); public static readonly int Escapes = StringExtensionMethods.GetStableHashCode("ml_escapes"); public static readonly int LastPull = StringExtensionMethods.GetStableHashCode("ml_lastpull"); public static readonly int Kept = StringExtensionMethods.GetStableHashCode("ml_kept"); public const string RpcPutOn = "ML_PutOn"; public const string RpcPull = "ML_Pull"; } public enum PullOutcome { Pulled, BrokeFree, Subdued } public static class Ranks { private static readonly Dictionary<string, RankNeed> Cache = new Dictionary<string, RankNeed>(); private static Dictionary<string, HashSet<string>> _biomes; private static string _cacheRanks; private static string _cacheNever; public static RankNeed For(Character c) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Invalid comparison between Unknown and I4 if ((Object)(object)c == (Object)null || c.IsPlayer()) { return new RankNeed(0, boss: false); } if ((Object)(object)((Component)c).GetComponent<CharacterTimedDestruction>() != (Object)null) { return new RankNeed(0, boss: false); } Faction faction = c.m_faction; if ((int)faction == 0 || (int)faction == 11 || (int)faction == 12) { return new RankNeed(0, boss: false); } return For(Utils.GetPrefabName(((Component)c).gameObject), c.m_health, c.m_boss, (int)faction == 8); } public static RankNeed For(string prefab, float health, bool boss, bool bossFaction) { if (((object)Cfg.Ranks.Value != _cacheRanks && Cfg.Ranks.Value != _cacheRanks) || ((object)Cfg.Never.Value != _cacheNever && Cfg.Never.Value != _cacheNever)) { Cache.Clear(); _cacheRanks = Cfg.Ranks.Value; _cacheNever = Cfg.Never.Value; } if (Cache.TryGetValue(prefab, out var value)) { return value; } value = RankTable.For(prefab, Cfg.OverrideMap, Cfg.NeverSet, health, boss, bossFaction, BiomesOf(prefab)); Cache[prefab] = value; return value; } private static IEnumerable<string> BiomesOf(string prefab) { //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_00c0: 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_00cd: Unknown result type (might be due to invalid IL or missing references) if (_biomes == null) { _biomes = new Dictionary<string, HashSet<string>>(); try { SpawnSystemList[] array = Resources.FindObjectsOfTypeAll<SpawnSystemList>(); for (int i = 0; i < array.Length; i++) { foreach (SpawnData spawner in array[i].m_spawners) { if (spawner == null || (Object)(object)spawner.m_prefab == (Object)null || !spawner.m_enabled) { continue; } if (!_biomes.TryGetValue(((Object)spawner.m_prefab).name, out var value)) { value = (_biomes[((Object)spawner.m_prefab).name] = new HashSet<string>()); } foreach (Biome value3 in Enum.GetValues(typeof(Biome))) { if ((int)value3 != 0 && (spawner.m_biome & value3) != 0) { value.Add(((object)value3/*cast due to .constrained prefix*/).ToString()); } } } } } catch (Exception ex) { MonsterLeashPlugin.Log.LogWarning((object)("Spawn lists: " + ex.Message)); } if (_biomes.Count == 0) { _biomes = null; return null; } } if (!_biomes.TryGetValue(prefab, out var value2)) { return null; } return value2; } public static string NamesAt(int rank, bool bosses) { if ((Object)(object)ZNetScene.instance == (Object)null) { return ""; } List<string> list = new List<string>(); HashSet<string> hashSet = new HashSet<string>(); foreach (KeyValuePair<string, RankNeed> item2 in RankTable.Vanilla) { if (item2.Value.Boss != bosses) { continue; } RankNeed rankNeed = For(item2.Key, 0f, item2.Value.Boss, bossFaction: false); if (rankNeed.Rank != rank || rankNeed.Boss != bosses) { continue; } GameObject prefab = ZNetScene.instance.GetPrefab(item2.Key); Character val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Character>() : null); if (!((Object)(object)val == (Object)null)) { string text = Lang.L(val.m_name); if (!string.IsNullOrEmpty(text) && !text.StartsWith("[", StringComparison.Ordinal) && hashSet.Add(text)) { list.Add(text); } } } foreach (KeyValuePair<string, RankNeed> item3 in Cfg.OverrideMap) { if (item3.Value.Rank == rank && item3.Value.Boss == bosses) { GameObject prefab2 = ZNetScene.instance.GetPrefab(item3.Key); Character val2 = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<Character>() : null); string item = (((Object)(object)val2 != (Object)null) ? Lang.L(val2.m_name) : item3.Key); if (hashSet.Add(item)) { list.Add(item); } } } if (list.Count > 8) { return string.Join(", ", list.Take(8)) + " …"; } return string.Join(", ", list); } } public class Wild : MonoBehaviour { public static readonly HashSet<Character> Held = new HashSet<Character>(); private ZNetView _nview; private float _nextTick; private float _lastTick; private float _noneSince = -1f; private float _saveLeft; private bool _keptApplied; private readonly Dictionary<long, (int rank, bool wild)> _asked = new Dictionary<long, (int, bool)>(); private float _left = -1f; public Leash Leash { get; private set; } public Character Character { get; private set; } public bool Valid { get { if ((Object)(object)_nview != (Object)null && _nview.IsValid()) { return _nview.GetZDO() != null; } return false; } } private ZDO Zdo => _nview.GetZDO(); public bool IsWild { get { if (Valid) { return Zdo.GetBool(Keys.Wild, false); } return false; } } public int Rank { get { if (!Valid) { return 0; } return Zdo.GetInt(Keys.Rank, 0); } } public bool Subdued { get { if (Valid) { return Zdo.GetBool(Keys.Subdued, false); } return false; } } public int Escapes { get { if (!Valid) { return 0; } return Zdo.GetInt(Keys.Escapes, 0); } } public float Left { get { if (!Valid) { return 0f; } return Zdo.GetFloat(Keys.Left, 0f); } } public int Done { get { if (!Valid) { return 0; } return Zdo.GetInt(Keys.Done, 0); } } public bool HoldsCalm { get { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 if ((Object)(object)Leash == (Object)null || !Leash.Valid) { return false; } LeashState state = Leash.State; if (state - 1 > 2) { if ((int)state == 5) { return Leash.Calm; } return false; } return true; } } private long Seed => ((ZDOID)(ref Zdo.m_uid)).UserID ^ (long)((ulong)((ZDOID)(ref Zdo.m_uid)).ID << 20); private void Awake() { Leash = ((Component)this).GetComponent<Leash>(); Character = ((Component)this).GetComponent<Character>(); _nview = ((Component)this).GetComponent<ZNetView>(); if (Valid) { _nview.Register<int, bool>("ML_PutOn", (Action<long, int, bool>)RPC_PutOn); _nview.Register<long, int>("ML_Pull", (Action<long, long, int>)RPC_Pull); } } private void OnDestroy() { Held.Remove(Character); } public double ChanceLeft() { if (!IsWild || Subdued) { return 0.0; } RankNeed rankNeed = Ranks.For(Character); double total = Odds.Escape(Cfg.Tuning, Rank - rankNeed.Rank, rankNeed.Boss, Character.GetHealthPercentage(), Escapes); int num = Math.Max(1, Cfg.Struggles.Value); int num2 = Math.Max(0, num - Done); double num3 = Odds.PerStruggle(total, num); return 1.0 - Math.Pow(1.0 - num3, num2); } internal void RPC_PutOn(long sender, int rank, bool wild) { if (_nview.IsOwner()) { _asked[sender] = (Math.Max(0, rank), wild); } } internal bool BeforePutOn(long sender) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Leash == (Object)null || (int)Leash.State != 0) { return false; } int num; bool flag; if (_asked.TryGetValue(sender, out (int, bool) value)) { (num, flag) = value; } else { num = 0; flag = false; } _asked.Remove(sender); Zdo.Set(Keys.Rank, num, false); bool flag2 = flag && !Character.IsTamed() && Hooks.Refusal(Character, num) == null; Zdo.Set(Keys.Wild, flag2); return flag2; } internal void AfterPutOn() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Leash == (Object)null || (int)Leash.State == 0) { Zdo.Set(Keys.Wild, false); return; } Zdo.Set(Keys.Subdued, false); Zdo.Set(Keys.Left, Cfg.StruggleSeconds.Value); Zdo.Set(Keys.Done, 0, false); Zdo.Set(Keys.Kept, true); _noneSince = -1f; _left = -1f; KeepFromDespawning(); } internal void CopyTo(ZDO z) { int[] array = new int[3] { Keys.Rank, Keys.Done, Keys.Escapes }; foreach (int num in array) { z.Set(num, Zdo.GetInt(num, 0), false); } array = new int[3] { Keys.Wild, Keys.Subdued, Keys.Kept }; foreach (int num2 in array) { z.Set(num2, Zdo.GetBool(num2, false)); } z.Set(Keys.Left, Zdo.GetFloat(Keys.Left, 0f)); } private void KeepFromDespawning() { if (!Cfg.KeepLeashed.Value || !_nview.IsOwner()) { return; } BaseAI component = ((Component)this).GetComponent<BaseAI>(); MonsterAI val = (MonsterAI)(object)((component is MonsterAI) ? component : null); if (val != null) { if (val.DespawnInDay()) { val.SetDespawnInDay(false); } if (val.IsEventCreature()) { val.SetEventCreature(false); } } _keptApplied = true; } private void Update() { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Invalid comparison between Unknown and I4 if (!Valid || (Object)(object)Leash == (Object)null) { return; } float time = Time.time; if (time < _nextTick) { return; } float num = ((_lastTick > 0f) ? Mathf.Min(1f, time - _lastTick) : 0.25f); _lastTick = time; _nextTick = time + 0.25f; bool isWild = IsWild; if (isWild && Cfg.Peaceful.Value && HoldsCalm) { Held.Add(Character); } else { Held.Remove(Character); } if (!_nview.IsOwner()) { _left = -1f; return; } if (!_keptApplied && Zdo.GetBool(Keys.Kept, false)) { KeepFromDespawning(); } if (!isWild) { return; } LeashState state = Leash.State; if ((int)state == 0) { if (_noneSince < 0f) { _noneSince = time; } else if (time - _noneSince > 3f) { Zdo.Set(Keys.Wild, false); Zdo.Set(Keys.Subdued, false); _noneSince = -1f; } return; } _noneSince = -1f; if (Zdo.GetBool(Keys.Subdued, false) || (int)state == 4 || Character.IsDead()) { return; } float num2 = Mathf.Max(1f, Cfg.StruggleSeconds.Value); if (_left < 0f) { _left = Zdo.GetFloat(Keys.Left, num2); } _left -= num; int num3 = Math.Max(1, Cfg.Struggles.Value); int num4 = Zdo.GetInt(Keys.Done, 0); double num5 = num2 - _left; if (num4 < num3 && num5 >= Odds.StruggleAt(num2, num3, num4, Odds.Jitter(Seed, num4))) { Zdo.Set(Keys.Done, num4 + 1, false); Zdo.Set(Keys.Left, _left); if (Struggle(num3)) { return; } } if (_left <= 0f) { Zdo.Set(Keys.Left, 0f); Zdo.Set(Keys.Subdued, true); Broadcast(PullOutcome.Subdued, 0L); return; } _saveLeft += num; if (_saveLeft >= 1f) { _saveLeft = 0f; Zdo.Set(Keys.Left, _left); } } private bool Struggle(int n) { //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) RankNeed rankNeed = Ranks.For(Character); double num = Odds.Escape(Cfg.Tuning, Rank - rankNeed.Rank, rankNeed.Boss, Character.GetHealthPercentage(), Escapes); double num2 = Odds.PerStruggle(num, n); bool flag = (double)Random.value < num2; if (SelfTest.ForcePull != null) { flag = SelfTest.ForcePull(this, flag); } Zdo.Set(Keys.LastPull, ZNet.instance.GetTime().Ticks); MonsterLeashPlugin.Log.LogDebug((object)string.Format("{0} pulls at rank {1} (needs {2}{3}), health {4:0.00}, escapes {5}: p {6:0.000} of {7:0.000} -> {8}", ((Object)this).name, Rank, rankNeed.Rank, rankNeed.Boss ? " boss" : "", Character.GetHealthPercentage(), Escapes, num2, num, flag ? "free" : "held")); if (flag) { BreakFree(); return true; } Broadcast(PullOutcome.Pulled, 0L); Player holder; Vector3 val = HolderPosition(out holder); Vector3 val2 = ((Component)this).transform.position - val; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = -((Component)this).transform.forward; } Character.Stagger(((Vector3)(ref val2)).normalized); return false; } public void BreakFree() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if (!_nview.IsOwner()) { return; } HolderPosition(out var holder); long holderId = Leash.HolderId; int rank = Rank; Broadcast(PullOutcome.BrokeFree, holderId); Leash.SetState((LeashState)0); Held.Remove(Character); _left = -1f; Zdo.Set(Keys.Wild, false); Zdo.Set(Keys.Subdued, false); Zdo.Set(Keys.Rank, 0, false); Zdo.Set(Keys.Escapes, Zdo.GetInt(Keys.Escapes, 0) + 1, false); if (rank > 0) { Item.Drop(rank, ((Component)this).transform.position); } if ((Object)(object)holder == (Object)null) { holder = Player.GetClosestPlayer(((Component)this).transform.position, 40f); } BaseAI component = ((Component)this).GetComponent<BaseAI>(); if (component != null) { component.ResetPatrolPoint(); if ((Object)(object)holder != (Object)null) { component.SetAggravated(true, (AggravatedReason)0); MonsterAI val = (MonsterAI)(object)((component is MonsterAI) ? component : null); if (val != null) { val.m_targetCreature = (Character)(object)holder; } component.Alert(); } } MonsterLeashPlugin.Log.LogInfo((object)$"{((Object)this).name} broke free (escapes now {Escapes})."); } private Vector3 HolderPosition(out Player holder) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) holder = Leash.FindPlayer(Leash.HolderId); if ((Object)(object)holder != (Object)null) { return ((Component)holder).transform.position; } if ((int)Leash.State == 5 || (int)Leash.State == 2) { return Zdo.GetVec3(Keys.Anchor, ((Component)this).transform.position); } return ((Component)this).transform.position - ((Component)this).transform.forward; } private void Broadcast(PullOutcome o, long holder = 0L) { if (holder == 0L) { holder = Leash.HolderId; } _nview.InvokeRPC(ZNetView.Everybody, "ML_Pull", new object[2] { holder, (int)o }); } private void RPC_Pull(long sender, long holderId, int outcome) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) if (!Valid) { return; } try { if (outcome != 2) { BaseAI component = ((Component)this).GetComponent<BaseAI>(); if (component != null && component.m_alertedEffects != null) { component.m_alertedEffects.Create(((Component)this).transform.position, ((Component)this).transform.rotation, ((Component)this).transform, 1f, -1, default(ZDOID)); } } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } bool flag = holderId != 0L && localPlayer.GetPlayerID() == holderId; if (!flag && Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position) > 30f) { return; } string text = (((Object)(object)Leash != (Object)null) ? Leash.Name : Lang.L(Character.m_name)); if (outcome == 0 && flag) { Vector3 val = ((Component)this).transform.position - ((Component)localPlayer).transform.position; val.y = 0f; float num = Mathf.Clamp(((Object)(object)Character.m_body != (Object)null) ? Character.m_body.mass : 50f, 10f, 1000f); ((Character)localPlayer).ApplyPushback(((Vector3)(ref val)).normalized, 25f + num * 0.15f); if (Ranks.For(Character).Boss) { ((Character)localPlayer).Stagger(-((Vector3)(ref val)).normalized); } } if (Cfg.StruggleMessages.Value || outcome != 0) { string token = outcome switch { 1 => "ml_msg_free", 0 => "ml_msg_pull", _ => "ml_msg_subdued", }; if (outcome != 0 || flag) { ((Character)localPlayer).Message((MessageType)((!(outcome == 1 || flag)) ? 1 : 2), Lang.T(token, text), 0, (Sprite)null, false); } } } catch (Exception ex) { MonsterLeashPlugin.Log.LogWarning((object)("Pull: " + ex.Message)); } } } } namespace MonsterLeash.Dev { public class SelfTest : MonoBehaviour { private string _out; private readonly List<string> _report = new List<string>(); private int _pass; private int _fail; private bool _soft; private int _softFail; public static Func<Wild, bool, bool> ForcePull; private const float MpStruggleSeconds = 30f; private const int MpStruggles = 3; private const string MpRanks = "Troll:3"; private const string MpRank4 = "Bronze:5,TrollHide:3,BjornHide:1"; private static Harmony _probe; private Vector3 _home; private Vector3 _stage; private readonly List<GameObject> _spawned = new List<GameObject>(); private IEnumerator BearWalkScene() { yield return ((MonoBehaviour)this).StartCoroutine(Stage(9)); Vector3 stage = _stage; Player p = Player.m_localPlayer; Stand(p, stage); p.SetGhostMode(true); Cfg.StruggleSeconds.Value = 600f; ForcePull = (Wild w, bool free) => false; string[] array = new string[3] { "Bjorn", "Wolf", "Troll" }; foreach (string prefab in array) { Character a = SpawnWild(prefab, ((Component)p).transform.position + new Vector3(0f, 0f, 3.5f), 180f); yield return (object)new WaitForSecondsRealtime(1.5f); Note(prefab + " components: " + string.Join(", ", from m in ((Component)a).GetComponents<MonoBehaviour>() select ((object)m).GetType().FullName)); int rank = Ranks.For(a).Rank; GiveMonsterLeash(rank); UseOn(a, rank); Leash l = Leash.Of(((Component)a).gameObject); yield return ((MonoBehaviour)this).StartCoroutine(WaitFor(() => (Object)(object)l != (Object)null && (int)l.State == 1, 3f)); for (int i = 0; i < 16; i++) { if (i % 2 == 0) { Note(string.Format("{0} t{1:0.0}: {2} dist {3:0.0} vel {4} target {5} flee {6}", prefab, (float)i * 0.5f, l.State, Utils.DistanceXZ(((Component)a).transform.position, ((Component)p).transform.position), a.m_body.linearVelocity, ((Object)(object)((Component)a).GetComponent<MonsterAI>()?.m_targetCreature != (Object)null) ? ((Object)((Component)a).GetComponent<MonsterAI>().m_targetCreature).name : "-", ((Component)a).GetComponent<MonsterAI>()?.m_fleeIfLowHealth)); } yield return (object)new WaitForSecondsRealtime(0.5f); } Check((int)l.State == 1, prefab + " stays on the leash for 8 s: " + ((object)l.State/*cast due to .constrained prefix*/).ToString()); Kill(a); } ForcePull = null; p.SetGhostMode(false); } public static void TryStart(GameObject host) { string environmentVariable = Environment.GetEnvironmentVariable("MLEASH_SELFTEST"); if (string.IsNullOrEmpty(environmentVariable)) { return; } Application.runInBackground = true; string[] commandLineArgs = Environment.GetCommandLineArgs(); bool flag = false; for (int i = 0; i < commandLineArgs.Length - 1; i++) { if (commandLineArgs[i] == "-savedir" && !string.IsNullOrEmpty(commandLineArgs[i + 1])) { Directory.CreateDirectory(commandLineArgs[i + 1]); Utils.SetSaveDataPath(commandLineArgs[i + 1]); flag = true; } } if (!flag) { MonsterLeashPlugin.Log.LogError((object)"Self test needs -savedir <scratch folder>; not starting it."); return; } if (!Flag("PHOTO")) { QualitySettings.globalTextureMipmapLimit = 1; } host.AddComponent<SelfTest>()._out = environmentVariable; } private static bool Flag(string name) { return (Environment.GetEnvironmentVariable("MLEASH_SELFTEST_" + name) ?? "") == "1"; } private void Start() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown Directory.CreateDirectory(_out); Application.logMessageReceived += new LogCallback(OnLog); ((MonoBehaviour)this).StartCoroutine(Run()); } private void OnLog(string condition, string stackTrace, LogType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) if ((int)type == 4 || (int)type == 0) { _report.Add($"[{type}] {condition}\n{stackTrace}"); } } private IEnumerator Run() { float timeout = Time.realtimeSinceStartup + 600f; while (((Object)(object)FejdStartup.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) && Time.realtimeSinceStartup < timeout) { yield return null; } yield return (object)new WaitForSecondsRealtime(4f); string environmentVariable = Environment.GetEnvironmentVariable("MLEASH_SELFTEST_JOIN"); if (!string.IsNullOrEmpty(environmentVariable)) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(EnterServer(environmentVariable))); if ((Object)(object)Player.m_localPlayer != (Object)null) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(WorldTest())); } } else if (Flag("WORLD")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(EnterWorld())); if ((Object)(object)Player.m_localPlayer != (Object)null) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(WorldTest())); } } _report.Add($"RESULT pass {_pass} fail {_fail}"); Flush(); Application.logMessageReceived -= new LogCallback(OnLog); yield return (object)new WaitForSecondsRealtime(0.5f); Application.Quit(); } private IEnumerator Safe(IEnumerator inner) { while (true) { object current; try { if (!inner.MoveNext()) { break; } current = inner.Current; } catch (Exception ex) { _report.Add("step failed: " + ex); _fail++; break; } yield return current; } } private void Flush() { File.WriteAllLines(Path.Combine(_out, "report.txt"), _report); } private void Check(bool ok, string what) { if (ok) { _pass++; } else if (_soft) { _softFail++; } else { _fail++; } _report.Add((ok ? "PASS " : (_soft ? "SOFT " : "FAIL ")) + what); Flush(); } private IEnumerator EnterWorld() { FejdStartup instance = FejdStartup.instance; if ((Object)(object)instance == (Object)null) { _report.Add("world: no FejdStartup"); yield break; } PlayerProfile val = new PlayerProfile("mleashtester", (FileSource)2); val.SetName("Tamer"); val.m_firstSpawn = false; val.Save(); Game.SetProfile("mleashtester", (FileSource)2); World val2 = new World("MonsterLeashTest", "HQ7GnTiegh") { m_fileSource = (FileSource)2 }; val2.SaveWorldFWLData(DateTime.Now); instance.m_world = val2; instance.m_startingWorld = true; ZNet.SetServer(true, false, false, val2.m_name, "", val2); ZNet.ResetServerHost(); instance.TransitionToMainScene(); _report.Add("world: loading " + val2.m_name + " seed " + val2.m_seedName); float timeout = Time.realtimeSinceStartup + 300f; while (((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || ((Character)Player.m_localPlayer).IsTeleporting()) && Time.realtimeSinceStartup < timeout) { yield return null; } if ((Object)(object)Player.m_localPlayer == (Object)null) { _report.Add("world: player never spawned"); yield break; } yield return (object)new WaitForSecondsRealtime(6f); _report.Add("world: spawned at " + ((object)((Component)Player.m_localPlayer).transform.position/*cast due to .constrained prefix*/).ToString()); } private IEnumerator EnterServer(string address) { FejdStartup instance = FejdStartup.instance; if ((Object)(object)instance == (Object)null) { _report.Add("join: no FejdStartup"); yield break; } PlayerProfile val = new PlayerProfile("mleashmp", (FileSource)2); val.SetName("Guest"); val.m_firstSpawn = false; val.Save(); Game.SetProfile("mleashmp", (FileSource)2); instance.SetServerToJoin(new ServerJoinData(new ServerJoinDataDedicated(address))); instance.JoinServer(); _report.Add("join: connecting to " + address); float timeout = Time.realtimeSinceStartup + 240f; while (((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || ((Character)Player.m_localPlayer).IsTeleporting()) && Time.realtimeSinceStartup < timeout) { yield return null; } if ((Object)(object)Player.m_localPlayer == (Object)null) { _report.Add("join: player never spawned"); yield break; } Player.m_localPlayer.SetGodMode(true); Player.m_localPlayer.SetGhostMode(true); float settle = Time.realtimeSinceStartup + 90f; Player stable = null; float since = 0f; while (Time.realtimeSinceStartup < settle) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting()) { localPlayer.SetGodMode(true); localPlayer.SetGhostMode(true); if ((Object)(object)localPlayer != (Object)(object)stable) { stable = localPlayer; since = Time.realtimeSinceStartup; } else if (Time.realtimeSinceStartup - since > 8f) { break; } } else { stable = null; } yield return null; } List<string> report = _report; object[] array = new object[4]; Player localPlayer2 = Player.m_localPlayer; array[0] = ((localPlayer2 != null) ? new Vector3?(((Component)localPlayer2).transform.position) : ((Vector3?)null)); array[1] = ZNet.instance.IsServer(); array[2] = ZNet.instance.GetPeers().Count; array[3] = (Object)(object)Player.m_localPlayer != (Object)null && !((Character)Player.m_localPlayer).IsDead(); report.Add(string.Format("join: spawned at {0}, server {1}, peers {2}, alive {3}", array)); } private IEnumerator WorldTest() { if (Flag("RESEARCH")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(Research())); } if (Flag("RULES")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(RulesScene())); } if (Flag("LEAD")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(LeadScene())); } if (Flag("FREE")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(FreeScene())); } if (Flag("BOSS")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(BossScene())); } if (Flag("FIGHT")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(FightScene())); } if (Flag("CRAFT")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(CraftScene())); } if (Flag("GROW")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(GrowScene())); } if (Flag("REMOTE")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(RemoteScene())); } if (Flag("MP")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(MpScene())); } if (Flag("BEARWALK")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(BearWalkScene())); } if (Flag("LOOK")) { yield return ((MonoBehaviour)this).StartCoroutine(Safe(LookScene())); } } private static void Stand(Player p, Vector3 at) { //IL_0007: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) at.y = ZoneSystem.instance.GetGroundHeight(at) + 0.1f; ((Component)p).transform.position = at; ((Character)p).m_body.position = at; ((Character)p).m_body.linearVelocity = Vector3.zero; } private void ClearArea(Vector3 c, float r) { //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) int num = 0; ZNetView[] array = Object.FindObjectsByType<ZNetView>((FindObjectsSortMode)0); foreach (ZNetView val in array) { if (!((Object)(object)val == (Object)null) && val.IsValid() && !((Object)(object)((Component)val).GetComponent<Player>() != (Object)null) && !(Utils.DistanceXZ(((Component)val).transform.position, c) > r) && (Object.op_Implicit((Object)(object)((Component)val).GetComponent<TreeBase>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<TreeLog>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<Destructible>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<MineRock>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<MineRock5>()) || Object.op_Implicit((Object)(object)((Component)val).GetComponent<Pickable>()) || (Object.op_Implicit((Object)(object)((Component)val).GetComponent<Character>()) && !((Component)val).GetComponent<Character>().IsTamed()))) { val.Destroy(); num++; } } _report.Add("scene: cleared " + num + " objects"); } private Vector3 FlatSpot(Vector3 from) { //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: 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_0048: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Invalid comparison between Unknown and I4 //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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_00db: 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_00e7: Unknown result type (might be due to invalid IL or missing references) float waterLevel = ZoneSystem.instance.m_waterLevel; Vector3 val = default(Vector3); for (float num = 40f; num < 300f; num += 8f) { for (int i = 0; i < 24; i++) { float num2 = (float)i * (float)Math.PI * 2f / 24f; ((Vector3)(ref val))..ctor(from.x + Mathf.Cos(num2) * num, 0f, from.z + Mathf.Sin(num2) * num); if ((int)WorldGenerator.instance.GetBiome(val) != 1) { continue; } float groundHeight = ZoneSystem.instance.GetGroundHeight(val); bool flag = groundHeight > waterLevel + 2f; for (int j = 0; j < 12 && flag; j++) { float num3 = (float)j * (float)Math.PI / 6f; float[] array = new float[3] { 6f, 12f, 18f }; foreach (float num4 in array) { float groundHeight2 = ZoneSystem.instance.GetGroundHeight(val + new Vector3(Mathf.Cos(num3), 0f, Mathf.Sin(num3)) * num4); flag &= groundHeight2 > waterLevel + 1.5f && Mathf.Abs(groundHeight2 - groundHeight) < 1.6f; } } if (flag) { return new Vector3(val.x, groundHeight, val.z); } } } _report.Add("scene: no flat spot found"); return from + new Vector3(40f, 0f, 0f); } private static Pose Look(Vector3 target, float bearing, float dist, float height) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_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_0026: 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) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target + Quaternion.Euler(0f, bearing, 0f) * Vector3.forward * dist + Vector3.up * height; return new Pose(val, Quaternion.LookRotation(target - val)); } private IEnumerator MainShot(string name, Pose pose) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Camera main = Utils.GetMainCamera(); GameCamera gc = GameCamera.instance; if ((Object)(object)main == (Object)null) { _report.Add("mainshot: no camera"); yield break; } if ((Object)(object)gc != (Object)null) { ((Behaviour)gc).enabled = false; } if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.m_userHidden = true; } ((Component)main).transform.SetPositionAndRotation(pose.position, pose.rotation); float fov = main.fieldOfView; main.fieldOfView = 50f; yield return null; yield return null; yield return (object)new WaitForEndOfFrame(); ScreenCapture.CaptureScreenshot(Path.Combine(_out, name + ".png")); yield return null; yield return null; main.fieldOfView = fov; if ((Object)(object)gc != (Object)null) { ((Behaviour)gc).enabled = true; } if ((Object)(object)Hud.instance != (Object)null) { Hud.instance.m_userHidden = false; } } private IEnumerator Shot(string name) { yield return (object)new WaitForEndOfFrame(); ScreenCapture.CaptureScreenshot(Path.Combine(_out, name + ".png")); yield return null; yield return null; } private static void SavePng(Texture tex, string path) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) RenderTexture temporary = RenderTexture.GetTemporary(tex.width, tex.height, 0, (RenderTextureFormat)0); Graphics.Blit(tex, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Texture2D val = new Texture2D(tex.width, tex.height, (TextureFormat)4, false); val.ReadPixels(new Rect(0f, 0f, (float)tex.width, (float)tex.height), 0, 0); val.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); File.WriteAllBytes(path, EncodePng(val)); Object.Destroy((Object)(object)val); } private static byte[] EncodePng(Texture2D tex) { MethodInfo methodInfo = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("EncodeToPNG", new Type[1] { typeof(Texture2D) }); if (!(methodInfo != null)) { return new byte[0]; } return (byte[])methodInfo.Invoke(null, new object[1] { tex }); } private static string Flat(string s) { if (s != null) { return s.Replace('\n', '|'); } return "null"; } private static Bounds RendererBounds(GameObject go) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0036: Unknown result type (might be due to invalid IL or missing references) Bounds result = default(Bounds); bool flag = false; Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if (!(val is ParticleSystemRenderer) && val.enabled) { if (!flag) { result = val.bounds; flag = true; } else { ((Bounds)(ref result)).Encapsulate(val.bounds); } } } return result; } private IEnumerator GrowScene() { yield return ((MonoBehaviour)this).StartCoroutine(Stage(7)); Vector3 stage = _stage; Player p = Player.m_localPlayer; Stand(p, stage); Cfg.StruggleSeconds.Value = 600f; ForcePull = (Wild w, bool free) => false; p.SetGhostMode(true); Character cub = SpawnWild("Bjorn_cub", stage + new Vector3(0f, 0f, 2.5f), 180f); yield return (object)new WaitForSecondsRealtime(1.5f); GiveMonsterLeash(3); Check(UseOn(cub, 3), "a rank 3 leash goes on a wild bear cub"); Leash l = Leash.Of(((Component)cub).gameObject); yield return ((MonoBehaviour)this).StartCoroutine(WaitFor(() => (Object)(object)l != (Object)null && (int)l.State == 1, 3f)); Check((Object)(object)l != (Object)null && (int)l.State == 1 && ((Component)cub).GetComponent<Wild>().IsWild, "the cub is led, wild"); if ((Object)(object)l == (Object)null || (int)l.State != 1) { yield break; } Vector3 at = ((Component)cub).transform.position; Growup component = ((Component)cub).GetComponent<Growup>(); component.m_growTime = 0f; cub.m_nview.GetZDO().Set(ZDOVars.s_spawnTime, ZNet.instance.GetTime().Ticks - 50000000); component.GrowUpdate(); yield return (object)new WaitForSecondsRealtime(1.5f); Character bear = ((IEnumerable<Character>)Character.GetAllCharacters()).FirstOrDefault((Func<Character, bool>)((Character x) => (Object)(object)x != (Object)null && Utils.GetPrefabName(((Component)x).gameObject) == "Bjorn" && Vector3.Distance(((Component)x).tran