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 CompanionTraining v0.6.7
BepInEx/plugins/Goblinheim - Companion/CompanionTraining.dll
Decompiled 16 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.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GoblinHeim.CoreStorage; using GoblinHeim.ValheimCore; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; using Valheim.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("CompanionTraining")] [assembly: AssemblyDescription("Persistent trained companions for Valheim")] [assembly: AssemblyCompany("GoblinHeim")] [assembly: AssemblyProduct("CompanionTraining")] [assembly: AssemblyFileVersion("0.6.7.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.6.7.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace GoblinHeim.CompanionTraining { internal static class CharmBinding { private sealed class PendingName : TextReceiver { internal readonly Player Player; internal readonly Inventory Inventory; internal readonly ItemData Item; internal readonly Character Target; internal readonly CompanionTrainingPlugin.Species Species; internal PendingName(Player p, Inventory i, ItemData item, Character target, CompanionTrainingPlugin.Species species) { Player = p; Inventory = i; Item = item; Target = target; Species = species; } public string GetText() { return ""; } public void SetText(string text) { Commit(this, text); } } private sealed class ColliderShape { internal CapsuleCollider Collider; internal float Radius; internal float Height; internal Vector3 Center; } private const float Range = 5f; internal const string AlphaKey = "GoblinHeim.Companion.Alpha"; internal const string OwnerKey = "GoblinHeim.Companion.Owner"; internal const string SpeciesKey = "GoblinHeim.Companion.Species"; internal const string RetiredKey = "GoblinHeim.Companion.Retired"; private const string AlphaScaleAppliedKey = "GoblinHeim.Companion.AlphaScaleApplied"; private const string WoundedKey = "GoblinHeim.Companion.Wounded"; private const string HealKey = "GoblinHeim.Companion.Healing"; private const string FeedUntilKey = "GoblinHeim.Companion.FeedUntil"; private const string FeedCooldownKey = "GoblinHeim.Companion.FeedCooldown"; private const string WasFollowKey = "GoblinHeim.Companion.WasFollow"; private const string AttackSkillKey = "GoblinHeim.Companion.AttackSkill"; private const string RobustSkillKey = "GoblinHeim.Companion.RobustSkill"; private static readonly Dictionary<Character, float> NextRegen = new Dictionary<Character, float>(); private static readonly Dictionary<Character, float> LastCombat = new Dictionary<Character, float>(); private static readonly Dictionary<Character, Vector2> SavedSpeeds = new Dictionary<Character, Vector2>(); private static readonly Dictionary<Character, Vector2> NamingSpeeds = new Dictionary<Character, Vector2>(); private static readonly Dictionary<Character, float> SavedFleeThresholds = new Dictionary<Character, float>(); private static readonly Dictionary<Character, Vector3> OriginalScales = new Dictionary<Character, Vector3>(); private static readonly HashSet<Character> ButcherKills = new HashSet<Character>(); private static PendingName _pending; private static readonly Dictionary<ZDOID, PinData> PersonalPins = new Dictionary<ZDOID, PinData>(); private static readonly Dictionary<Character, ColliderShape> OriginalColliders = new Dictionary<Character, ColliderShape>(); internal static bool HasPendingName => _pending != null; internal static bool CanBecomeCompanion(Character c) { if ((Object)(object)c == (Object)null || c.IsDead() || !c.IsTamed() || c.GetLevel() != 3 || IsAlpha(c)) { return false; } return CompanionTrainingPlugin.GetSpecies((Component)(object)c) != CompanionTrainingPlugin.Species.None; } internal static void BeginDamage(Character victim, HitData hit) { if ((Object)(object)victim == (Object)null || hit == null) { return; } if (IsAlpha(victim)) { LastCombat[victim] = Time.time; } Character attacker = hit.GetAttacker(); if ((Object)(object)attacker != (Object)null && IsAlpha(attacker)) { LastCombat[attacker] = Time.time; } if (IsAlpha(victim)) { Character attacker2 = hit.GetAttacker(); Character obj = ((attacker2 is Player) ? attacker2 : null); ItemData val = ((obj != null) ? ((Humanoid)obj).GetCurrentWeapon() : null); string obj2 = (((Object)(object)val?.m_dropPrefab == (Object)null) ? "" : ((Object)val.m_dropPrefab).name); string text = val?.m_shared?.m_name ?? ""; if (obj2.IndexOf("Butcher", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("butcher", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("boucher", StringComparison.OrdinalIgnoreCase) >= 0) { ButcherKills.Add(victim); } } } internal static void EndDamage(Character victim) { if ((Object)(object)victim != (Object)null) { ButcherKills.Remove(victim); } } internal static bool IsButcherKill(Character victim) { if ((Object)(object)victim != (Object)null) { return ButcherKills.Contains(victim); } return false; } internal static bool IsAlpha(Character c) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if ((Object)c == (Object)null) { return false; } ZNetView component = ((Component)c).GetComponent<ZNetView>(); if ((Object)component == (Object)null || !component.IsValid()) { return false; } ZDO zDO = component.GetZDO(); if (zDO != null) { return zDO.GetBool("GoblinHeim.Companion.Alpha", false); } return false; } internal static bool IsTrained(Character c) { if ((Object)(object)c == (Object)null) { return false; } ZNetView component = ((Component)c).GetComponent<ZNetView>(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val != null) { if (!val.GetBool("GoblinHeim.Companion.Alpha", false)) { return val.GetBool("GoblinHeim.Companion.Retired", false); } return true; } return false; } internal static float Skill(Character c, string key) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown ZNetView val = (((Object)(object)c != (Object)null) ? ((Component)c).GetComponent<ZNetView>() : null); ZDO val2 = (((Object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null); if (val2 != null) { return Mathf.Clamp(val2.GetFloat(key, 0f), 0f, 100f); } return 0f; } internal static float CompanionDamage(Character c) { float num = 1f + Skill(c, "GoblinHeim.Companion.AttackSkill") * 0.01f; return CompanionTrainingPlugin.GetSpecies((Component)(object)c) switch { CompanionTrainingPlugin.Species.Wolf => 200f * num, CompanionTrainingPlugin.Species.Lox => 300f * num, CompanionTrainingPlugin.Species.Asksvin => 220f * num, CompanionTrainingPlugin.Species.Moose => 180f * num, _ => 32f * num, }; } internal static float CompanionMaxHealth(Character c) { float num = Skill(c, "GoblinHeim.Companion.RobustSkill"); return CompanionTrainingPlugin.GetSpecies((Component)(object)c) switch { CompanionTrainingPlugin.Species.Wolf => 300f * (1f + num * 0.01f), CompanionTrainingPlugin.Species.Lox => 3500f * (1f + num * 0.01f), CompanionTrainingPlugin.Species.Asksvin => 1800f * (1f + num * 0.01f), CompanionTrainingPlugin.Species.Moose => 1200f * (1f + num * 0.01f), _ => 60f * (1f + num * 0.01f), }; } internal static float CompanionArmor(Character c) { float num = Skill(c, "GoblinHeim.Companion.RobustSkill"); return CompanionTrainingPlugin.GetSpecies((Component)(object)c) switch { CompanionTrainingPlugin.Species.Lox => 40f * (1f + num * 0.01f), CompanionTrainingPlugin.Species.Wolf => 10f * (1f + num * 0.01f), CompanionTrainingPlugin.Species.Asksvin => 30f * (1f + num * 0.01f), CompanionTrainingPlugin.Species.Moose => 25f * (1f + num * 0.01f), _ => 10f * (1f + num * 0.01f), }; } internal static void AddAttackXp(Character c, float xp) { AddSkill(c, "GoblinHeim.Companion.AttackSkill", xp, "Attack"); } internal static void AddRobustXp(Character c, float xp) { AddSkill(c, "GoblinHeim.Companion.RobustSkill", xp, "Robustness"); } private static void AddSkill(Character c, string key, float xp, string label) { if (!IsAlpha(c)) { return; } ZDO zDO = ((Component)c).GetComponent<ZNetView>().GetZDO(); if (zDO != null) { float num = Mathf.Clamp(zDO.GetFloat(key, 0f), 0f, 100f); float num2 = Mathf.Clamp(num + Mathf.Max(0f, xp), 0f, 100f); if (num2 != num) { zDO.Set(key, num2); CompanionTrainingPlugin.Log.LogInfo((object)$"[COMPANION-SKILL] {label} {num:0.##}->{num2:0.##}"); } } } internal static bool AreEnemies(Character a, Character b) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if ((Object)a == (Object)null || (Object)b == (Object)null) { return false; } return BaseAI.IsEnemy(a, b); } internal static bool IsWounded(Character c) { if (!IsAlpha(c)) { return false; } ZDO zDO = ((Component)c).GetComponent<ZNetView>().GetZDO(); if (zDO != null) { return zDO.GetBool("GoblinHeim.Companion.Wounded", false); } return false; } internal static void EnterWounded(Character c) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown if (!IsAlpha(c)) { return; } ZDO zDO = ((Component)c).GetComponent<ZNetView>().GetZDO(); if (zDO == null || zDO.GetBool("GoblinHeim.Companion.Wounded", false)) { return; } zDO.Set("GoblinHeim.Companion.Wounded", true); zDO.Set("GoblinHeim.Companion.Healing", false); MonsterAI component = ((Component)c).GetComponent<MonsterAI>(); bool flag = (Object)component != (Object)null && (Object)component.GetFollowTarget() != (Object)null; if ((Object)(object)component != (Object)null && !SavedFleeThresholds.ContainsKey(c)) { SavedFleeThresholds[c] = component.m_fleeIfLowHealth; component.m_fleeIfLowHealth = 1f; } zDO.Set("GoblinHeim.Companion.WasFollow", flag); TryStagger(c); SetHalfSpeed(c, half: true); BaseAI component2 = ((Component)c).GetComponent<BaseAI>(); if ((Object)component2 != (Object)null) { MethodInfo methodInfo = AccessTools.Method(((object)component2).GetType(), "SetAlerted", new Type[1] { typeof(bool) }, (Type[])null); if (methodInfo != null) { try { methodInfo.Invoke(component2, new object[1] { true }); } catch { } } } CompanionTrainingPlugin.Log.LogInfo((object)("[COMPANION] WOUNDED: " + Utils.GetPrefabName(((Component)c).gameObject) + " intercepted at 1 HP; skills preserved, vanilla flee enabled, speed 50%, previous=" + (flag ? "Follow" : "Stay"))); } private static void TryStagger(Character c) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) try { MethodInfo methodInfo = AccessTools.Method(((object)c).GetType(), "Stagger", new Type[1] { typeof(Vector3) }, (Type[])null); if (methodInfo == null) { methodInfo = AccessTools.Method(typeof(Character), "Stagger", new Type[1] { typeof(Vector3) }, (Type[])null); } if (methodInfo != null) { methodInfo.Invoke(c, new object[1] { -((Component)c).transform.forward }); } } catch { } } private static void SetHalfSpeed(Character c, bool half) { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) FieldInfo fieldInfo = AccessTools.Field(((object)c).GetType(), "m_runSpeed") ?? AccessTools.Field(typeof(Character), "m_runSpeed"); FieldInfo fieldInfo2 = AccessTools.Field(((object)c).GetType(), "m_walkSpeed") ?? AccessTools.Field(typeof(Character), "m_walkSpeed"); if (fieldInfo == null || fieldInfo2 == null) { return; } Vector2 value; if (half) { if (!SavedSpeeds.ContainsKey(c)) { SavedSpeeds[c] = new Vector2((float)fieldInfo2.GetValue(c), (float)fieldInfo.GetValue(c)); } Vector2 val = SavedSpeeds[c]; fieldInfo2.SetValue(c, val.x * 0.5f); fieldInfo.SetValue(c, val.y * 0.5f); } else if (SavedSpeeds.TryGetValue(c, out value)) { fieldInfo2.SetValue(c, value.x); fieldInfo.SetValue(c, value.y); SavedSpeeds.Remove(c); } } private static void FreezeForNaming(Character c, bool frozen) { //IL_00db: 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_009d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)c == (Object)null) { return; } FieldInfo fieldInfo = AccessTools.Field(((object)c).GetType(), "m_runSpeed") ?? AccessTools.Field(typeof(Character), "m_runSpeed"); FieldInfo fieldInfo2 = AccessTools.Field(((object)c).GetType(), "m_walkSpeed") ?? AccessTools.Field(typeof(Character), "m_walkSpeed"); if (fieldInfo == null || fieldInfo2 == null) { return; } Vector2 value; if (frozen) { if (!NamingSpeeds.ContainsKey(c)) { NamingSpeeds[c] = new Vector2((float)fieldInfo2.GetValue(c), (float)fieldInfo.GetValue(c)); } fieldInfo2.SetValue(c, 0f); fieldInfo.SetValue(c, 0f); } else if (NamingSpeeds.TryGetValue(c, out value)) { fieldInfo2.SetValue(c, value.x); fieldInfo.SetValue(c, value.y); NamingSpeeds.Remove(c); } } internal static void Feed(Character c, Player player) { //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Expected O, but got Unknown if (!IsAlpha(c) || c.IsDead() || (Object)(object)player == (Object)null) { return; } ZNetView component = ((Component)c).GetComponent<ZNetView>(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val == null) { return; } long ticks = DateTime.UtcNow.Ticks; long num = val.GetLong("GoblinHeim.Companion.FeedCooldown", 0L); if (ticks < num) { ((Character)player).Message((MessageType)2, "Ce compagnon pourra être nourri dans " + Mathf.CeilToInt((float)(num - ticks) / 10000000f) + " s.", 0, (Sprite)null, false); return; } if (c.GetHealth() >= CompanionMaxHealth(c) - 0.01f) { ((Character)player).Message((MessageType)2, "Ce compagnon est déjà en pleine santé.", 0, (Sprite)null, false); return; } MonsterAI ai = ((Component)c).GetComponent<MonsterAI>(); Inventory inventory = ((Humanoid)player).GetInventory(); ItemData val2 = ((inventory != null) ? ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData item) => (Object)(object)ai != (Object)null && ai.m_consumeItems != null && ai.m_consumeItems.Any((ItemDrop accepted) => (Object)(object)accepted != (Object)null && item != null && item.m_shared != null && (accepted.m_itemData.m_shared.m_name == item.m_shared.m_name || ((Object)(object)item.m_dropPrefab != (Object)null && ((Object)((Component)accepted).gameObject).name == ((Object)item.m_dropPrefab).name))))) : null); if (val2 == null && (Object)(object)ai != (Object)null && ai.m_consumeItems != null) { float num2 = 0f; if (StoragePolicy.CraftFromContainers) { num2 = Mathf.Max(num2, StoragePolicy.CraftRange); } if (StoragePolicy.BuildFromContainers) { num2 = Mathf.Max(num2, StoragePolicy.BuildRange); } foreach (ItemDrop consumeItem in ai.m_consumeItems) { string acceptedName = consumeItem?.m_itemData?.m_shared?.m_name; if (string.IsNullOrEmpty(acceptedName) || num2 <= 0f) { continue; } List<ResourceCost> list = new List<ResourceCost> { new ResourceCost { Name = acceptedName, Amount = 1 } }; if (ResourceLedger.Prepare(player, list, num2, true)) { val2 = ((IEnumerable<ItemData>)inventory.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData item) => item?.m_shared?.m_name == acceptedName)); if (val2 != null) { break; } } } } if (val2 == null) { ((Character)player).Message((MessageType)2, "Vous n'avez aucune nourriture compatible pour soigner ce compagnon.", 0, (Sprite)null, false); return; } inventory.RemoveOneItem(val2); val.Set("GoblinHeim.Companion.FeedUntil", ticks + 50000000); val.Set("GoblinHeim.Companion.FeedCooldown", ticks + 600000000); NextRegen.Remove(c); CompanionTrainingPlugin.Log.LogInfo((object)$"[COMPANION] FED: hp={c.GetHealth():0.##}/{CompanionMaxHealth(c):0.##}; +10% max HP/s for 5 seconds."); } internal static void UpdateCompanion(Character c) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown if (!IsAlpha(c) || c.IsDead()) { return; } float num = CompanionMaxHealth(c); ZNetView component = ((Component)c).GetComponent<ZNetView>(); if ((Object)component == (Object)null || !component.IsValid() || !component.IsOwner()) { return; } ZDO zDO = component.GetZDO(); if (zDO == null) { return; } if (zDO.GetBool("GoblinHeim.Companion.Wounded", false) || zDO.GetBool("GoblinHeim.Companion.Healing", false)) { zDO.Set("GoblinHeim.Companion.Wounded", false); zDO.Set("GoblinHeim.Companion.Healing", false); SetHalfSpeed(c, half: false); } if (!(c.GetHealth() < num - 0.01f)) { return; } float time = Time.time; if (DateTime.UtcNow.Ticks < zDO.GetLong("GoblinHeim.Companion.FeedUntil", 0L)) { if (!NextRegen.TryGetValue(c, out var value) || time >= value) { NextRegen[c] = time + 1f; c.Heal(Mathf.Max(0.1f, num * 0.1f), true); } return; } BaseAI baseAI = c.GetBaseAI(); float value2; float value3; if ((Object)(object)baseAI != (Object)null && (baseAI.IsAlerted() || (Object)(object)baseAI.GetTargetCreature() != (Object)null)) { LastCombat[c] = time; } else if (!LastCombat.TryGetValue(c, out value2)) { LastCombat[c] = time; } else if (!(time - value2 < 60f) && (!NextRegen.TryGetValue(c, out value3) || !(time < value3))) { NextRegen[c] = time + 1f; c.Heal(Mathf.Max(0.1f, num * CompanionTrainingPlugin.CompanionRegen.Value / 100f), true); } } private static void FinishWounded(Character c) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown ZNetView component = ((Component)c).GetComponent<ZNetView>(); ZDO val = (((Object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val == null) { return; } bool flag = val.GetBool("GoblinHeim.Companion.WasFollow", false); val.Set("GoblinHeim.Companion.Wounded", false); val.Set("GoblinHeim.Companion.Healing", false); SetHalfSpeed(c, half: false); NextRegen.Remove(c); BaseAI component2 = ((Component)c).GetComponent<BaseAI>(); if ((Object)component2 != (Object)null) { MethodInfo methodInfo = AccessTools.Method(((object)component2).GetType(), "SetAlerted", new Type[1] { typeof(bool) }, (Type[])null); if (methodInfo != null) { try { methodInfo.Invoke(component2, new object[1] { false }); } catch { } } } if (flag) { Player val2 = FindOwner(val.GetLong("GoblinHeim.Companion.Owner", 0L)); if ((Object)val2 != (Object)null) { MonsterAI component3 = ((Component)c).GetComponent<MonsterAI>(); if ((Object)component3 != (Object)null) { component3.SetFollowTarget(((Component)val2).gameObject); ((BaseAI)component3).ResetPatrolPoint(); } } } MonsterAI component4 = ((Component)c).GetComponent<MonsterAI>(); if ((Object)(object)component4 != (Object)null && SavedFleeThresholds.TryGetValue(c, out var value)) { component4.m_fleeIfLowHealth = value; SavedFleeThresholds.Remove(c); } CompanionTrainingPlugin.Log.LogInfo((object)("[COMPANION] RECOVERED 100%: resumes " + (flag ? "Follow" : "Stay") + ".")); } private static Player FindOwner(long id) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown foreach (Character allCharacter in Character.GetAllCharacters()) { Player val = (Player)((allCharacter is Player) ? allCharacter : null); if ((Object)(object)val != (Object)null && val.GetPlayerID() == id) { return val; } } return null; } private static void TryCommand(Tameable tame, Humanoid user, bool desiredFollow) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if ((Object)tame == (Object)null || (Object)user == (Object)null) { return; } try { FieldInfo fieldInfo = AccessTools.Field(typeof(Tameable), "m_follow"); if (fieldInfo != null && fieldInfo.FieldType == typeof(bool) && (bool)fieldInfo.GetValue(tame) == desiredFollow) { return; } MethodInfo methodInfo = typeof(Tameable).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo x) => x.Name == "Command" && x.GetParameters().Length >= 1 && typeof(Humanoid).IsAssignableFrom(x.GetParameters()[0].ParameterType)); if (!(methodInfo == null)) { ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; array[0] = user; for (int num = 1; num < parameters.Length; num++) { array[num] = ((parameters[num].ParameterType == typeof(bool)) ? ((object)true) : (parameters[num].HasDefaultValue ? parameters[num].DefaultValue : null)); } methodInfo.Invoke(tame, array); } } catch { } } internal static bool IsOwnedAlpha(Tameable tame, Player player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if ((Object)tame == (Object)null || (Object)player == (Object)null) { return false; } ZNetView component = ((Component)tame).GetComponent<ZNetView>(); if ((Object)component == (Object)null || !component.IsValid()) { return false; } ZDO zDO = component.GetZDO(); if (zDO != null && zDO.GetBool("GoblinHeim.Companion.Alpha", false)) { return zDO.GetLong("GoblinHeim.Companion.Owner", 0L) == player.GetPlayerID(); } return false; } internal static bool IsFollowing(Character character) { MonsterAI val = (((Object)(object)character == (Object)null) ? null : ((Component)character).GetComponent<MonsterAI>()); if ((Object)(object)val != (Object)null) { return (Object)(object)val.GetFollowTarget() != (Object)null; } return false; } internal static void StopOtherOwnedCompanions(Player owner, Character selected) { if ((Object)(object)owner == (Object)null) { return; } long playerID = owner.GetPlayerID(); foreach (Character allCharacter in Character.GetAllCharacters()) { if ((Object)(object)allCharacter == (Object)null || (Object)(object)allCharacter == (Object)(object)selected || !IsAlpha(allCharacter)) { continue; } ZNetView component = ((Component)allCharacter).GetComponent<ZNetView>(); ZDO val = (((Object)(object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); if (val != null && val.GetLong("GoblinHeim.Companion.Owner", 0L) == playerID) { MonsterAI component2 = ((Component)allCharacter).GetComponent<MonsterAI>(); if (!((Object)(object)component2 == (Object)null) && !((Object)(object)component2.GetFollowTarget() == (Object)null)) { component2.SetFollowTarget((GameObject)null); ((BaseAI)component2).SetPatrolPoint(); CompanionTrainingPlugin.Log.LogInfo((object)"[COMPANION] other active follower switched to Stay."); } } } } internal static void ApplyAlphaVisual(Character character) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0077: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0181: 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_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) if ((Object)character == (Object)null) { return; } ZNetView component = ((Component)character).GetComponent<ZNetView>(); if ((Object)component == (Object)null || !component.IsValid()) { return; } ZDO zDO = component.GetZDO(); if (zDO == null || (!zDO.GetBool("GoblinHeim.Companion.Alpha", false) && !zDO.GetBool("GoblinHeim.Companion.Retired", false))) { return; } if (!OriginalScales.ContainsKey(character)) { OriginalScales[character] = ((Component)character).transform.localScale; } float num = CompanionTrainingPlugin.GetSpecies((Component)(object)character) switch { CompanionTrainingPlugin.Species.Asksvin => 1.08f + Skill(character, "GoblinHeim.Companion.RobustSkill") * 0.00075f, CompanionTrainingPlugin.Species.Lox => 1.03f + Skill(character, "GoblinHeim.Companion.RobustSkill") * 0.0005f, _ => 1.1f + Skill(character, "GoblinHeim.Companion.RobustSkill") * 0.001f, }; ((Component)character).transform.localScale = OriginalScales[character] * num; CapsuleCollider component2 = ((Component)character).GetComponent<CapsuleCollider>(); if ((Object)(object)component2 != (Object)null) { if (!OriginalColliders.TryGetValue(character, out var value)) { value = new ColliderShape { Collider = component2, Radius = component2.radius, Height = component2.height, Center = component2.center }; OriginalColliders[character] = value; } component2.radius = value.Radius / num; component2.height = value.Height / num; component2.center = value.Center / num; } BaseAI baseAI = character.GetBaseAI(); if ((Object)(object)baseAI != (Object)null) { baseAI.m_avoidFire = true; baseAI.m_avoidLava = true; MonsterAI val = (MonsterAI)(object)((baseAI is MonsterAI) ? baseAI : null); baseAI.m_avoidWater = val == null || (Object)(object)val.GetFollowTarget() == (Object)null; } } private static void RestoreAlphaVisual(Character character) { //IL_001f: 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) if ((Object)(object)character == (Object)null) { return; } if (OriginalScales.TryGetValue(character, out var value)) { ((Component)character).transform.localScale = value; OriginalScales.Remove(character); } if (OriginalColliders.TryGetValue(character, out var value2)) { if ((Object)(object)value2.Collider != (Object)null) { value2.Collider.radius = value2.Radius; value2.Collider.height = value2.Height; value2.Collider.center = value2.Center; } OriginalColliders.Remove(character); } } internal static void RestoreReleasedVisual(Character character) { RestoreAlphaVisual(character); } internal static void UpdatePersonalCompanionPin() { //IL_008a: 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_005d: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)Minimap.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { return; } ZDOID companionId; string name; Vector3 position; bool flag = CompanionRecovery.TryGetActiveBackup(out companionId, out name, out position); KeyValuePair<ZDOID, PinData>[] array = PersonalPins.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair<ZDOID, PinData> keyValuePair = array[i]; if (CompanionTrainingPlugin.ShowPins.Value && flag) { ZDOID key = keyValuePair.Key; if (((ZDOID)(ref key)).Equals(companionId)) { continue; } } if (keyValuePair.Value != null) { Minimap.instance.RemovePin(keyValuePair.Value); } PersonalPins.Remove(keyValuePair.Key); } if (!CompanionTrainingPlugin.ShowPins.Value || !flag) { return; } ZDOMan instance = ZDOMan.instance; ZDO val = ((instance != null) ? instance.GetZDO(companionId) : null); Vector3 val2 = ((val != null) ? val.GetPosition() : position); string name2 = (CompanionTrainingPlugin.ShowPinNames.Value ? name : ""); if (!PersonalPins.TryGetValue(companionId, out var value) || value == null) { value = AddPin(val2, (PinType)3, name2); if (value != null) { PersonalPins[companionId] = value; } } if (value != null) { value.m_pos = val2; value.m_name = name2; } } catch (Exception ex) { CompanionTrainingPlugin.Log.LogWarning((object)("[COMPANION-PIN] update failed: " + ex.Message)); } } private static PinData AddPin(Vector3 position, PinType type, string name) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) MethodInfo methodInfo = typeof(Minimap).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "AddPin" && m.GetParameters().Length >= 5); if (methodInfo == null) { return null; } ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array = new object[parameters.Length]; array[0] = position; array[1] = type; array[2] = name; array[3] = false; array[4] = false; for (int num = 5; num < array.Length; num++) { array[num] = (parameters[num].HasDefaultValue ? parameters[num].DefaultValue : (parameters[num].ParameterType.IsValueType ? Activator.CreateInstance(parameters[num].ParameterType) : null)); } object? obj = methodInfo.Invoke(Minimap.instance, array); return (PinData)((obj is PinData) ? obj : null); } internal static string GetCompanionName(Character c) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown try { ZNetView component = ((Component)c).GetComponent<ZNetView>(); ZDO val = (((Object)component != (Object)null && component.IsValid()) ? component.GetZDO() : null); string text = ((val != null) ? val.GetString(ZDOVars.s_tamedName, "") : null); return string.IsNullOrWhiteSpace(text) ? SpeciesName(CompanionTrainingPlugin.GetSpecies((Component)c)) : text; } catch { return "Companion"; } } internal static bool TryBegin(Player player, Inventory inventory, ItemData item, CompanionTrainingPlugin.Species species) { //IL_0055: 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) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown Character val = (from candidate in Character.GetAllCharacters() where (Object)(object)candidate != (Object)null && !candidate.IsDead() && !IsAlpha(candidate) && candidate.IsTamed() && candidate.GetLevel() == 3 && CompanionTrainingPlugin.GetSpecies((Component)(object)candidate) == species && Vector3.Distance(((Component)player).transform.position, ((Component)candidate).transform.position) <= 5f orderby Vector3.Distance(((Component)player).transform.position, ((Component)candidate).transform.position) select candidate).FirstOrDefault(); float num = (((Object)(object)val == (Object)null) ? 5.001f : Vector3.Distance(((Component)player).transform.position, ((Component)val).transform.position)); if ((Object)val == (Object)null) { ((Character)player).Message((MessageType)2, "Trouvez un compagnon digne", 0, (Sprite)null, false); CompanionTrainingPlugin.Log.LogInfo((object)$"[CHARM] use refused: no tame 2-star {species} within 5m"); return false; } if ((Object)TextInput.instance == (Object)null) { ((Character)player).Message((MessageType)2, "Fenêtre de nom indisponible.", 0, (Sprite)null, false); return false; } FreezeForNaming(val, frozen: true); _pending = new PendingName(player, inventory, item, val, species); TextInput.instance.RequestText((TextReceiver)_pending, "Choisissez un nom à votre compagnon", 20); CompanionTrainingPlugin.Log.LogInfo((object)$"[CHARM] binding pending: {species}, target={Utils.GetPrefabName(((Component)val).gameObject)}, distance={num:0.00}m"); return true; } internal static bool TryBeginDirect(Player player, Character target) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || !CanBecomeCompanion(target) || Vector3.Distance(((Component)player).transform.position, ((Component)target).transform.position) > 5f) { return false; } if ((Object)(object)TextInput.instance == (Object)null) { ((Character)player).Message((MessageType)2, "Fenêtre de nom indisponible.", 0, (Sprite)null, false); return false; } CompanionTrainingPlugin.Species species = CompanionTrainingPlugin.GetSpecies((Component)(object)target); FreezeForNaming(target, frozen: true); _pending = new PendingName(player, null, null, target, species); CompanionCoatPalette.ResetSelection(); TextInput.instance.RequestText((TextReceiver)(object)_pending, "Choisissez un nom à votre compagnon", 20); CompanionTrainingPlugin.Log.LogInfo((object)$"[COMPANION] direct binding pending: {species}, target={Utils.GetPrefabName(((Component)target).gameObject)}"); return true; } private static void Commit(PendingName p, string raw) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Expected O, but got Unknown if (_pending != p) { return; } string text = (raw ?? "").Trim(); if (text.Length == 0) { ((Character)p.Player).Message((MessageType)2, "Le compagnon doit avoir un nom.", 0, (Sprite)null, false); TextInput instance = TextInput.instance; if ((Object)(object)instance != (Object)null) { instance.RequestText((TextReceiver)p, "Choisissez un nom à votre compagnon", 20); } return; } if ((Object)p.Target == (Object)null || p.Target.IsDead() || !p.Target.IsTamed() || p.Target.GetLevel() != 3 || CompanionTrainingPlugin.GetSpecies((Component)p.Target) != p.Species || Vector3.Distance(((Component)p.Player).transform.position, ((Component)p.Target).transform.position) > 5f) { ((Character)p.Player).Message((MessageType)2, "La liaison a été annulée : cible invalide ou hors de portée.", 0, (Sprite)null, false); FreezeForNaming(p.Target, frozen: false); _pending = null; CompanionCoatPalette.ResetSelection(); return; } if (p.Item != null && p.Item.m_stack <= 0) { ((Character)p.Player).Message((MessageType)2, "Le charme n'est plus disponible.", 0, (Sprite)null, false); FreezeForNaming(p.Target, frozen: false); _pending = null; CompanionCoatPalette.ResetSelection(); return; } long playerID = p.Player.GetPlayerID(); CompanionRecovery.ReleasePrevious(p.Player, p.Species, p.Target); if ((Object)((Component)p.Target).GetComponent<ZNetView>() == (Object)null || !((Component)p.Target).GetComponent<ZNetView>().IsValid()) { ((Character)p.Player).Message((MessageType)2, "La liaison a échoué : ZNetView invalide.", 0, (Sprite)null, false); FreezeForNaming(p.Target, frozen: false); _pending = null; CompanionCoatPalette.ResetSelection(); return; } ZNetView component = ((Component)p.Target).GetComponent<ZNetView>(); component.ClaimOwnership(); ZDO zDO = component.GetZDO(); if (zDO == null) { FreezeForNaming(p.Target, frozen: false); _pending = null; CompanionCoatPalette.ResetSelection(); return; } bool flag = zDO.GetBool("GoblinHeim.Companion.Retired", false); zDO.Set("GoblinHeim.Companion.Alpha", true); zDO.Set("GoblinHeim.Companion.Retired", false); zDO.Set("GoblinHeim.Companion.Owner", playerID); zDO.Set("GoblinHeim.Companion.Species", p.Species.ToString()); if (!flag) { zDO.Set("GoblinHeim.Companion.AttackSkill", 0f); zDO.Set("GoblinHeim.Companion.RobustSkill", 0f); } zDO.Set("GoblinHeim.Companion.Wounded", false); zDO.Set("GoblinHeim.Companion.Healing", false); CompanionCoatPalette.SaveSelected(zDO); ApplyAlphaVisual(p.Target); CompanionCoatPalette.Apply(p.Target); p.Target.SetHealth(CompanionMaxHealth(p.Target)); CompanionTrainingPlugin.Log.LogInfo((object)$"[COMPANION] Alpha visual/stats applied: {p.Species} scale={((Component)p.Target).transform.localScale}, HP={CompanionMaxHealth(p.Target):0.#}, damage={CompanionDamage(p.Target):0.#}, armor={CompanionArmor(p.Target):0.#}."); Tameable component2 = ((Component)p.Target).GetComponent<Tameable>(); if ((Object)component2 != (Object)null) { MethodInfo methodInfo = AccessTools.Method(typeof(Tameable), "RPC_SetName", (Type[])null, (Type[])null); if (methodInfo != null) { try { methodInfo.Invoke(component2, new object[2] { 0L, text }); } catch { zDO.Set(ZDOVars.s_tamedName, text); } } else { zDO.Set(ZDOVars.s_tamedName, text); } } else { zDO.Set(ZDOVars.s_tamedName, text); } if (p.Item != null && p.Inventory != null) { p.Inventory.RemoveOneItem(p.Item); } ((Character)p.Player).Message((MessageType)2, text + " est désormais votre compagnon.", 0, (Sprite)null, false); CompanionTrainingPlugin.Log.LogInfo((object)$"[COMPANION] binding committed: species={p.Species}, name='{text}', owner={playerID}."); CompanionRecovery.SaveBackup(p.Target); FreezeForNaming(p.Target, frozen: false); _pending = null; CompanionCoatPalette.ResetSelection(); } private static string SpeciesName(CompanionTrainingPlugin.Species s) { return s switch { CompanionTrainingPlugin.Species.Wolf => "loup", CompanionTrainingPlugin.Species.Boar => "sanglier", CompanionTrainingPlugin.Species.Asksvin => "asksvin", CompanionTrainingPlugin.Species.Moose => "élan", _ => "lox", }; } } internal static class CharmRegistry { internal sealed class Def { internal string Prefab; internal string Name; internal string Icon; internal string Trophy; internal string Hide; internal string Metal; internal string Mead; internal string RecipeLabel; internal CompanionTrainingPlugin.Species Species; internal int StationLevel; } internal static readonly Def[] Defs = new Def[3] { new Def { Prefab = "GoblinHeim_BoarCharm", Name = "Charme du Sanglier", RecipeLabel = "Boar", Icon = "BoarCharm.png", Trophy = "TrophyBoar", Hide = "LeatherScraps", Metal = "Bronze", Mead = "MeadHealthMinor", Species = CompanionTrainingPlugin.Species.Boar, StationLevel = 1 }, new Def { Prefab = "GoblinHeim_WolfCharm", Name = "Charme du Loup", RecipeLabel = "Wolf", Icon = "WolfCharm.png", Trophy = "TrophyWolf", Hide = "WolfPelt", Metal = "Silver", Mead = "MeadBzerker", Species = CompanionTrainingPlugin.Species.Wolf, StationLevel = 3 }, new Def { Prefab = "GoblinHeim_LoxCharm", Name = "Charme du Lox", RecipeLabel = "Lox", Icon = "LoxCharm.png", Trophy = "TrophyLox", Hide = "LoxPelt", Metal = "BlackMetal", Mead = "MeadStrength", Species = CompanionTrainingPlugin.Species.Lox, StationLevel = 4 } }; private static readonly Dictionary<string, GameObject> Prefabs = new Dictionary<string, GameObject>(); private static readonly Dictionary<CompanionTrainingPlugin.Species, Sprite> UiIcons = new Dictionary<CompanionTrainingPlugin.Species, Sprite>(); private static bool _itemsRegistered; private static bool _recipesRegistered; private static bool _registrationInProgress; private static bool _completeLogged; internal static void TryRegisterContent(string trigger) { if (_registrationInProgress) { return; } ObjectDB db = ObjectDB.instance; if ((Object)(object)db == (Object)null || db.m_items == null) { CompanionTrainingPlugin.Log.LogDebug((object)("[CHARM] waiting (" + trigger + "): ObjectDB unavailable")); return; } _registrationInProgress = true; try { EnsureItems(db); if ((Object)(object)ZNetScene.instance != (Object)null) { EnsureNetworkPrefabs(ZNetScene.instance, db); EnsureRecipes(db, ZNetScene.instance); } else { CompanionTrainingPlugin.Log.LogDebug((object)("[CHARM] items ready (" + trigger + "); recipes waiting for ZNetScene")); } _itemsRegistered = Defs.All((Def d) => db.m_items.Any((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == d.Prefab)); _recipesRegistered = db.m_recipes != null && Defs.All((Def d) => db.m_recipes.Any((Recipe r) => (Object)(object)r != (Object)null && ((Object)r).name == "Recipe_" + d.Prefab)); if (_itemsRegistered && _recipesRegistered && !_completeLogged) { _completeLogged = true; CompanionTrainingPlugin.Log.LogInfo((object)"Vanilla dependencies ready."); CompanionTrainingPlugin.Log.LogInfo((object)"[CHARM] Charms registered: 3."); CompanionTrainingPlugin.Log.LogInfo((object)"[CHARM] registration complete: items=3 recipes=3"); CompanionTrainingPlugin.Log.LogInfo((object)"Companion systems ready."); } } catch (Exception ex) { CompanionTrainingPlugin.Log.LogError((object)("[CHARM] content registration error: " + ex)); } finally { _registrationInProgress = false; } } private static void EnsureItems(ObjectDB db) { bool flag = false; Def[] defs = Defs; foreach (Def def in defs) { GameObject val = Create(def, db); if (!((Object)(object)val == (Object)null) && !db.m_items.Any((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == def.Prefab)) { db.m_items.Add(val); flag = true; CompanionTrainingPlugin.Log.LogInfo((object)("[CHARM] " + def.Prefab + " registered")); } } if (flag) { MethodInfo methodInfo = AccessTools.Method(((object)db).GetType(), "UpdateRegisters", (Type[])null, (Type[])null); if (methodInfo == null) { throw new MissingMethodException(((object)db).GetType().FullName, "UpdateRegisters"); } methodInfo.Invoke(db, null); } defs = Defs; foreach (Def def2 in defs) { if ((Object)(object)db.GetItemPrefab(def2.Prefab) == (Object)null) { throw new InvalidOperationException("ObjectDB hash register missing " + def2.Prefab); } } } private static GameObject Create(Def def, ObjectDB db) { //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) if (Prefabs.TryGetValue(def.Prefab, out var value) && (Object)(object)value != (Object)null) { return value; } GameObject val = FindItemPrefab(db, "Amber") ?? FindItemPrefab(db, "AmberPearl") ?? FindItemPrefab(db, "Coins") ?? FindItemPrefab(db, "CryptKey") ?? ((IEnumerable<GameObject>)db.m_items).FirstOrDefault((Func<GameObject, bool>)((GameObject x) => (Object)(object)x != (Object)null && (Object)(object)x.GetComponent<ItemDrop>() != (Object)null)); if ((Object)(object)val == (Object)null) { return null; } GameObject val2 = Object.Instantiate<GameObject>(val); ((Object)val2).name = def.Prefab; Object.DontDestroyOnLoad((Object)(object)val2); ZSyncTransform[] componentsInChildren = val2.GetComponentsInChildren<ZSyncTransform>(true); for (int num = 0; num < componentsInChildren.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren[num]); } WearNTear[] componentsInChildren2 = val2.GetComponentsInChildren<WearNTear>(true); for (int num = 0; num < componentsInChildren2.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[num]); } ZNetView[] componentsInChildren3 = val2.GetComponentsInChildren<ZNetView>(true); for (int num = 0; num < componentsInChildren3.Length; num++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[num]); } ItemDrop component = val2.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); return null; } MethodInfo method = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic); component.m_itemData.m_shared = (SharedData)method.Invoke(component.m_itemData.m_shared, null); component.m_itemData.m_shared.m_name = def.Name; component.m_itemData.m_shared.m_description = "Lie votre âme à celle de votre companion."; component.m_itemData.m_shared.m_itemType = (ItemType)2; component.m_itemData.m_shared.m_maxStackSize = 20; component.m_itemData.m_shared.m_weight = 0.1f; AccessTools.Field(typeof(SharedData), "m_consumeStatusEffect")?.SetValue(component.m_itemData.m_shared, null); Sprite val3 = LoadEmbeddedIcon(def.Icon); if ((Object)(object)val3 != (Object)null) { component.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val3 }; } component.m_itemData.m_dropPrefab = val2; Prefabs[def.Prefab] = val2; return val2; } private static GameObject FindItemPrefab(ObjectDB db, string name) { object obj = db.m_items?.FirstOrDefault((Func<GameObject, bool>)((GameObject x) => (Object)(object)x != (Object)null && ((Object)x).name == name)); if (obj == null) { ZNetScene instance = ZNetScene.instance; if (instance == null) { return null; } obj = instance.GetPrefab(name); } return (GameObject)obj; } private static void EnsureNetworkPrefabs(ZNetScene scene, ObjectDB db) { Def[] defs = Defs; foreach (Def def in defs) { GameObject val = Create(def, db); if ((Object)(object)val == (Object)null) { continue; } if (AccessTools.Field(((object)scene).GetType(), "m_prefabs")?.GetValue(scene) is IList list) { bool flag = false; foreach (object item in list) { GameObject val2 = (GameObject)((item is GameObject) ? item : null); if (val2 != null && ((Object)val2).name == def.Prefab) { flag = true; break; } } if (!flag) { list.Add(val); } } if (AccessTools.Field(((object)scene).GetType(), "m_namedPrefabs")?.GetValue(scene) is IDictionary dictionary) { int stableHashCode = StringExtensionMethods.GetStableHashCode(def.Prefab); if (!dictionary.Contains(stableHashCode)) { dictionary.Add(stableHashCode, val); } } } } private static void EnsureRecipes(ObjectDB db, ZNetScene scene) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: 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_014a: 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_015d: Expected O, but got Unknown if (db.m_recipes == null) { return; } GameObject prefab = scene.GetPrefab("piece_workbench"); CraftingStation val = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null); if ((Object)(object)val == (Object)null) { CompanionTrainingPlugin.Log.LogDebug((object)"[CHARM] recipes waiting for piece_workbench"); return; } Def[] defs = Defs; foreach (Def def in defs) { string recipeName = "Recipe_" + def.Prefab; if (db.m_recipes.Any((Recipe r) => (Object)(object)r != (Object)null && ((Object)r).name == recipeName)) { continue; } GameObject val2 = Create(def, db); (string, int)[] obj = new(string, int)[4] { (def.Trophy, 1), (def.Metal, 4), (def.Hide, 4), (def.Mead, 1) }; List<Requirement> list = new List<Requirement>(); bool flag = (Object)(object)val2 != (Object)null; (string, int)[] array = obj; for (int num = 0; num < array.Length; num++) { (string, int) tuple = array[num]; GameObject obj2 = FindItemPrefab(db, tuple.Item1); ItemDrop val3 = ((obj2 != null) ? obj2.GetComponent<ItemDrop>() : null); if ((Object)(object)val3 == (Object)null) { flag = false; break; } list.Add(new Requirement { m_resItem = val3, m_amount = tuple.Item2, m_amountPerLevel = 0, m_recover = true }); } if (flag) { Recipe val4 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val4).name = recipeName; val4.m_item = val2.GetComponent<ItemDrop>(); val4.m_amount = 1; val4.m_minStationLevel = def.StationLevel; val4.m_resources = list.ToArray(); val4.m_craftingStation = val; db.m_recipes.Add(val4); CompanionTrainingPlugin.Log.LogInfo((object)("[CHARM] " + def.RecipeLabel + " recipe registered")); } } } internal static bool IsCharm(ItemData item, out CompanionTrainingPlugin.Species species) { species = CompanionTrainingPlugin.Species.None; if (item == null) { return false; } string prefab = (((Object)(object)item.m_dropPrefab == (Object)null) ? "" : ((Object)item.m_dropPrefab).name); Def def = Defs.FirstOrDefault((Def d) => d.Prefab == prefab || item.m_shared?.m_name == d.Name); if (def == null) { return false; } species = def.Species; return true; } internal static Sprite GetIcon(CompanionTrainingPlugin.Species species) { if (UiIcons.TryGetValue(species, out var value) && (Object)(object)value != (Object)null) { return value; } Def def = Defs.FirstOrDefault((Def d) => d.Species == species); GameObject value2; GameObject obj = ((def == null) ? null : (Prefabs.TryGetValue(def.Prefab, out value2) ? value2 : null)); Sprite[] array = ((obj == null) ? null : obj.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_icons); Sprite val = ((array != null && array.Length != 0) ? array[0] : ((def == null) ? null : LoadEmbeddedIcon(def.Icon))); if ((Object)(object)val == (Object)null && species == CompanionTrainingPlugin.Species.Asksvin) { ObjectDB instance = ObjectDB.instance; object obj2 = ((instance != null) ? instance.GetItemPrefab("TrophyAsksvin") : null); if (obj2 == null) { ObjectDB instance2 = ObjectDB.instance; obj2 = ((instance2 != null) ? instance2.GetItemPrefab("TrophyAsksvinQueen") : null); } Sprite[] array2 = ((obj2 == null) ? null : ((GameObject)obj2).GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_icons); if (array2 != null && array2.Length != 0) { val = array2[0]; } } if ((Object)(object)val == (Object)null && species == CompanionTrainingPlugin.Species.Moose) { ObjectDB instance3 = ObjectDB.instance; GameObject obj3 = ((instance3 != null) ? instance3.GetItemPrefab("TrophyMoose") : null); Sprite[] array3 = ((obj3 == null) ? null : obj3.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_icons); if (array3 != null && array3.Length != 0) { val = array3[0]; } } if ((Object)(object)val != (Object)null) { UiIcons[species] = val; } return val; } internal static Sprite GetTrophyIcon(CompanionTrainingPlugin.Species species) { string text = Defs.FirstOrDefault((Def d) => d.Species == species)?.Trophy; if (species == CompanionTrainingPlugin.Species.Asksvin) { text = "TrophyAsksvin"; } else if (species == CompanionTrainingPlugin.Species.Moose) { text = "TrophyMoose"; } object obj; if (!string.IsNullOrEmpty(text)) { ObjectDB instance = ObjectDB.instance; obj = ((instance != null) ? instance.GetItemPrefab(text) : null); } else { obj = null; } Sprite[] array = ((obj == null) ? null : ((GameObject)obj).GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_icons); if (array == null || array.Length == 0) { return GetIcon(species); } return array[0]; } private static Sprite LoadEmbeddedIcon(string file) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) string text = Assembly.GetExecutingAssembly().GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith("." + file, StringComparison.OrdinalIgnoreCase)); if (text == null) { return null; } using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); MethodInfo methodInfo = (Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule") ?? (from a in AppDomain.CurrentDomain.GetAssemblies() select a.GetType("UnityEngine.ImageConversion")).FirstOrDefault((Type t) => t != null))?.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "LoadImage" && m.GetParameters().Length >= 2 && m.GetParameters()[0].ParameterType == typeof(Texture2D) && m.GetParameters()[1].ParameterType == typeof(byte[])); if (methodInfo == null) { CompanionTrainingPlugin.Log.LogError((object)("[CHARM] UnityEngine.ImageConversion.LoadImage unavailable for " + file)); return null; } object[] parameters = ((methodInfo.GetParameters().Length != 2) ? new object[3] { val, memoryStream.ToArray(), false } : new object[2] { val, memoryStream.ToArray() }); if (!(bool)methodInfo.Invoke(null, parameters)) { CompanionTrainingPlugin.Log.LogError((object)("[CHARM] PNG decoding failed for " + file)); return null; } ((Object)val).name = file; CompanionTrainingPlugin.Log.LogInfo((object)("[CHARM] icon loaded: " + file)); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } } internal static class CompanionAlliances { internal static bool IsProtected(Character character) { if ((Object)(object)character == (Object)null) { return false; } if (character.IsPlayer() || character.IsTamed()) { return true; } string text = ((Object)((Component)character).gameObject).name.Replace("(Clone)", ""); if (!text.StartsWith("Dverger", StringComparison.OrdinalIgnoreCase) && !text.StartsWith("Dvergr", StringComparison.OrdinalIgnoreCase)) { return false; } BaseAI baseAI = character.GetBaseAI(); if (!((Object)(object)baseAI == (Object)null)) { return !baseAI.IsAggravated(); } return true; } internal static bool IsPlayerBuilding(Component component) { Piece val = (((Object)(object)component == (Object)null) ? null : component.GetComponentInParent<Piece>()); if ((Object)(object)val != (Object)null) { return val.IsPlacedByPlayer(); } return false; } } [HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[] { typeof(Character), typeof(Character) })] internal static class CompanionAlliancePatch { private static void Postfix(Character a, Character b, ref bool __result) { if (__result && !((Object)(object)a == (Object)null) && !((Object)(object)b == (Object)null) && ((CharmBinding.IsAlpha(a) && CompanionAlliances.IsProtected(b)) || (CharmBinding.IsAlpha(b) && CompanionAlliances.IsProtected(a)))) { __result = false; } } } [HarmonyPatch(typeof(BaseAI), "CanSeeTarget", new Type[] { typeof(StaticTarget) })] internal static class CompanionBuildingSelectionPatch { private static bool Prefix(BaseAI __instance, StaticTarget __0, ref bool __result) { if (!CharmBinding.IsAlpha(((Component)__instance).GetComponent<Character>()) || !CompanionAlliances.IsPlayerBuilding((Component)(object)__0)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(MonsterAI), "UpdateTarget")] internal static class CompanionBuildingTargetPatch { private static void Prefix(MonsterAI __instance, ref StaticTarget ___m_targetStatic) { if (CharmBinding.IsAlpha(((Component)__instance).GetComponent<Character>()) && CompanionAlliances.IsPlayerBuilding((Component)(object)___m_targetStatic)) { ___m_targetStatic = null; } } } [HarmonyPatch(typeof(WearNTear), "Damage")] internal static class CompanionBuildingDamagePatch { private static bool Prefix(WearNTear __instance, HitData hit) { if (hit != null && CharmBinding.IsAlpha(hit.GetAttacker())) { return !CompanionAlliances.IsPlayerBuilding((Component)(object)__instance); } return true; } } [HarmonyPatch(typeof(WearNTear), "RPC_Damage")] internal static class CompanionBuildingRpcDamagePatch { private static bool Prefix(WearNTear __instance, HitData hit) { if (hit != null && CharmBinding.IsAlpha(hit.GetAttacker())) { return !CompanionAlliances.IsPlayerBuilding((Component)(object)__instance); } return true; } } internal sealed class CompanionBeacon : MonoBehaviour, Hoverable, Interactable { internal const string PrefabName = "piece_companion_beacon"; internal static readonly HashSet<CompanionBeacon> Instances = new HashSet<CompanionBeacon>(); private Piece piece; private void Awake() { piece = ((Component)this).GetComponent<Piece>(); Instances.Add(this); } private void OnDestroy() { Instances.Remove(this); } internal bool IsOwnedBy(Player player) { if (Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)piece)) { return piece.GetCreator() == player.GetPlayerID(); } return false; } public string GetHoverName() { return "Balise de Compagnon"; } public float GetHoverOffset() { return 0f; } public string GetHoverText() { Player localPlayer = Player.m_localPlayer; if (!IsOwnedBy(localPlayer)) { return "Balise de Compagnon\n<color=grey>Personnelle</color>"; } return "Balise de Compagnon\n[<color=yellow><b>$KEY_Use</b></color>] Rappeler"; } public bool Interact(Humanoid user, bool hold, bool alt) { if (!hold) { Player val = (Player)(object)((user is Player) ? user : null); if (val != null && IsOwnedBy(val)) { CompanionBeaconUI.Open(this); return true; } } return false; } public bool UseItem(Humanoid user, ItemData item) { return false; } } internal static class CompanionBeaconPrefab { private const string SourceName = "guard_stone"; private static GameObject root; private static GameObject prefab; internal static void Register(ZNetScene scene) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)scene)) { return; } GameObject val = ((IEnumerable<GameObject>)scene.m_prefabs).FirstOrDefault((Func<GameObject, bool>)((GameObject go) => Object.op_Implicit((Object)(object)go) && ((Object)go).name == "guard_stone")); if (!Object.op_Implicit((Object)(object)val)) { CompanionTrainingPlugin.Log.LogError((object)"[BEACON] Vanilla guardstone prefab not found."); return; } root = new GameObject("CompanionBeacon_PrefabRoot"); Object.DontDestroyOnLoad((Object)(object)root); root.SetActive(false); prefab = Object.Instantiate<GameObject>(val, root.transform, false); ((Object)prefab).name = "piece_companion_beacon"; PrivateArea[] componentsInChildren = prefab.GetComponentsInChildren<PrivateArea>(true); foreach (PrivateArea val2 in componentsInChildren) { if (Object.op_Implicit((Object)(object)val2.m_enabledEffect)) { val2.m_enabledEffect.SetActive(false); } if (Object.op_Implicit((Object)(object)val2.m_areaMarker)) { ((Component)val2.m_areaMarker).gameObject.SetActive(false); } if (Object.op_Implicit((Object)(object)val2.m_connectEffect)) { val2.m_connectEffect.SetActive(false); } if (Object.op_Implicit((Object)(object)val2.m_inRangeEffect)) { val2.m_inRangeEffect.SetActive(false); } Object.DestroyImmediate((Object)(object)val2); } Piece component = prefab.GetComponent<Piece>(); if (!Object.op_Implicit((Object)(object)component)) { Object.Destroy((Object)(object)prefab); prefab = null; return; } component.m_name = "Balise de Compagnon"; component.m_description = "Rappelle uniquement vos compagnons personnels."; prefab.AddComponent<CompanionBeacon>(); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.38f, 0.43f, 0.42f, 1f); Renderer[] componentsInChildren2 = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val4 in componentsInChildren2) { Material[] materials = val4.materials; Material[] array = materials; foreach (Material val5 in array) { if (Object.op_Implicit((Object)(object)val5) && val5.HasProperty("_Color")) { val5.color = Color.Lerp(val5.color, val3, 0.68f); } } val4.materials = materials; } scene.m_prefabs.Add(prefab); CompanionTrainingPlugin.Log.LogInfo((object)"[BEACON] Personal Companion beacon registered from Vanilla guardstone."); } internal static void AddToHammer() { if (!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)ObjectDB.instance)) { return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Hammer"); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); PieceTable val2 = (Object.op_Implicit((Object)(object)val) ? val.m_itemData.m_shared.m_buildPieces : null); if (Object.op_Implicit((Object)(object)val2) && !val2.m_pieces.Contains(prefab)) { int num = val2.m_pieces.FindIndex((GameObject go) => Object.op_Implicit((Object)(object)go) && ((Object)go).name == "guard_stone"); if (num < 0) { val2.m_pieces.Add(prefab); } else { val2.m_pieces.Insert(num + 1, prefab); } CompanionTrainingPlugin.Log.LogInfo((object)"[BEACON] Added beside the Vanilla guardstone in the hammer table."); } } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class CompanionBeaconScenePatch { [HarmonyPrefix] private static void Prefix(ZNetScene __instance) { CompanionBeaconPrefab.Register(__instance); } [HarmonyPostfix] private static void Postfix() { CompanionBeaconPrefab.AddToHammer(); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class CompanionBeaconObjectDbPatch { [HarmonyPostfix] private static void Postfix() { CompanionBeaconPrefab.AddToHammer(); } } internal sealed class CompanionBeaconUI : MonoBehaviour { [CompilerGenerated] private static class <>O { public static UnityAction <0>__CloseCurrent; public static Action <1>__CloseCurrent; } private static CompanionBeaconUI current; private Component anchor; private Image vanillaBackground; private Image windowBackground; internal static void Open(CompanionBeacon source) { OpenWindow((Component)(object)source, delegate(CompanionTrainingPlugin.Species species) { CompanionRecovery.RecallFromBeacon(species, source); }); } internal static void OpenStation(CraftingStation source) { OpenWindow((Component)(object)source, delegate(CompanionTrainingPlugin.Species species) { CompanionRecovery.RecallFromStation(species, source); }); } private static void OpenWindow(Component source, Action<CompanionTrainingPlugin.Species> recall) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Expected O, but got Unknown //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Expected O, but got Unknown //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04a7: Unknown result type (might be due to invalid IL or missing references) //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04da: Unknown result type (might be due to invalid IL or missing references) //IL_04df: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Unknown result type (might be due to invalid IL or missing references) //IL_04eb: Unknown result type (might be due to invalid IL or missing references) //IL_04f5: Unknown result type (might be due to invalid IL or missing references) //IL_0500: Unknown result type (might be due to invalid IL or missing references) //IL_0514: Unknown result type (might be due to invalid IL or missing references) CloseCurrent(); InventoryGui instance = InventoryGui.instance; if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.m_container) || !Object.op_Implicit((Object)(object)instance.m_takeAllButton)) { return; } Canvas componentInParent = ((Component)instance).GetComponentInParent<Canvas>(true); Transform val = (Object.op_Implicit((Object)(object)componentInParent) ? ((Component)componentInParent).transform : ((Component)instance).transform); Transform obj = ((Transform)instance.m_container).Find("Bkg"); RectTransform val2 = (RectTransform)(object)((obj is RectTransform) ? obj : null); if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)((Component)val2).GetComponent<Image>())) { return; } GameObject obj2 = Object.Instantiate<GameObject>(((Component)val2).gameObject, val, false); ((Object)obj2).name = "CompanionBeaconWindow"; CompanionBeaconUI companionBeaconUI = obj2.AddComponent<CompanionBeaconUI>(); companionBeaconUI.anchor = source; current = companionBeaconUI; RectTransform val3 = (RectTransform)obj2.transform; Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(0.5f, 0.5f); val3.pivot = val4; Vector2 val5 = (val3.anchorMin = (val3.anchorMax = val4)); List<CompanionTrainingPlugin.Species> list = (from CompanionTrainingPlugin.Species s in Enum.GetValues(typeof(CompanionTrainingPlugin.Species)) where s != CompanionTrainingPlugin.Species.None && CompanionRecovery.HasBackup(s) select s).ToList(); int num = Mathf.Clamp(list.Count, 1, 5); int num2 = Mathf.Max(1, Mathf.CeilToInt((float)list.Count / 5f)); val3.sizeDelta = new Vector2((float)Mathf.Max(290, num * 88 + 30), (float)(105 + num2 * 100)); Image component = ((Component)val2).GetComponent<Image>(); Image component2 = obj2.GetComponent<Image>(); companionBeaconUI.vanillaBackground = component; companionBeaconUI.windowBackground = component2; companionBeaconUI.SyncBackground(); TMP_Text obj3 = Object.Instantiate<TMP_Text>(instance.m_containerName, (Transform)(object)val3); obj3.text = "BALISE DE COMPAGNON"; RectTransform rectTransform = obj3.rectTransform; ((Vector2)(ref val5))..ctor(0.5f, 1f); rectTransform.anchorMax = val5; rectTransform.anchorMin = val5; rectTransform.pivot = new Vector2(0.5f, 1f); rectTransform.anchoredPosition = new Vector2(0f, -12f); rectTransform.sizeDelta = new Vector2(val3.sizeDelta.x - 70f, 28f); Button obj4 = Object.Instantiate<Button>(instance.m_takeAllButton, (Transform)(object)val3); ((UnityEventBase)obj4.onClick).RemoveAllListeners(); ButtonClickedEvent onClick = obj4.onClick; object obj5 = <>O.<0>__CloseCurrent; if (obj5 == null) { UnityAction val8 = CloseCurrent; <>O.<0>__CloseCurrent = val8; obj5 = (object)val8; } ((UnityEvent)onClick).AddListener((UnityAction)obj5); ((Component)obj4).GetComponentInChildren<TMP_Text>(true).text = "×"; RectTransform component3 = ((Component)obj4).GetComponent<RectTransform>(); ((Vector2)(ref val5))..ctor(1f, 1f); component3.anchorMax = val5; component3.anchorMin = val5; component3.pivot = new Vector2(1f, 1f); component3.anchoredPosition = new Vector2(-8f, -8f); component3.sizeDelta = new Vector2(34f, 30f); for (int num3 = 0; num3 < list.Count; num3++) { CompanionTrainingPlugin.Species species = list[num3]; Button val9 = Object.Instantiate<Button>(instance.m_takeAllButton, (Transform)(object)val3); ((UnityEventBase)val9.onClick).RemoveAllListeners(); ((UnityEvent)val9.onClick).AddListener((UnityAction)delegate { recall(species); CloseCurrent(); }); RectTransform component4 = ((Component)val9).GetComponent<RectTransform>(); ((Vector2)(ref val5))..ctor(0.5f, 1f); component4.anchorMax = val5; component4.anchorMin = val5; component4.pivot = new Vector2(0.5f, 1f); component4.sizeDelta = new Vector2(80f, 92f); component4.anchoredPosition = new Vector2(((float)(num3 % 5) - (float)(num - 1) * 0.5f) * 88f, -52f - (float)(num3 / 5) * 100f); TMP_Text componentInChildren = ((Component)val9).GetComponentInChildren<TMP_Text>(true); if (Object.op_Implicit((Object)(object)componentInChildren)) { componentInChildren.text = CompanionRecovery.GetBackupName(species); RectTransform rectTransform2 = componentInChildren.rectTransform; rectTransform2.anchorMin = new Vector2(0f, 0f); rectTransform2.anchorMax = new Vector2(1f, 0f); rectTransform2.pivot = new Vector2(0.5f, 0f); rectTransform2.anchoredPosition = new Vector2(0f, 3f); rectTransform2.sizeDelta = new Vector2(-6f, 19f); } Sprite trophyIcon = CharmRegistry.GetTrophyIcon(species); if (Object.op_Implicit((Object)(object)trophyIcon)) { GameObject val10 = new GameObject("Portrait", new Type[2] { typeof(RectTransform), typeof(Image) }); val10.transform.SetParent(((Component)val9).transform, false); Image component5 = val10.GetComponent<Image>(); component5.sprite = trophyIcon; component5.preserveAspect = true; ((Graphic)component5).raycastTarget = false; RectTransform val11 = (RectTransform)val10.transform; val11.anchorMin = Vector2.zero; val11.anchorMax = Vector2.one; val11.offsetMin = new Vector2(8f, 25f); val11.offsetMax = new Vector2(-8f, -5f); } } CoreUiWindows.Open((object)companionBeaconUI, (Action)CloseCurrent); } private void Update() { //IL_002a: 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) SyncBackground(); if (!Object.op_Implicit((Object)(object)anchor) || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || Vector3.Distance(anchor.transform.position, ((Component)Player.m_localPlayer).transform.position) > 6f) { CloseCurrent(); } } private void SyncBackground() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)vanillaBackground) && Object.op_Implicit((Object)(object)windowBackground)) { windowBackground.sprite = vanillaBackground.sprite; windowBackground.overrideSprite = vanillaBackground.overrideSprite; ((Graphic)windowBackground).color = ((Graphic)vanillaBackground).color; ((Graphic)windowBackground).material = ((Graphic)vanillaBackground).material; windowBackground.type = vanillaBackground.type; windowBackground.preserveAspect = vanillaBackground.preserveAspect; windowBackground.fillCenter = vanillaBackground.fillCenter; windowBackground.pixelsPerUnitMultiplier = vanillaBackground.pixelsPerUnitMultiplier; } } internal static void CloseCurrent() { if (Object.op_Implicit((Object)(object)current)) { CompanionBeaconUI companionBeaconUI = current; current = null; CoreUiWindows.CloseRegistration((object)companionBeaconUI); Object.Destroy((Object)(object)((Component)companionBeaconUI).gameObject); } } } [HarmonyPatch(typeof(CraftingStation), "Interact")] internal static class CompanionWorkshopRecallPatch { [HarmonyPostfix] private static void Postfix(CraftingStation __instance, Humanoid user, bool repeat, bool __result) { if (!repeat && !((Object)(object)user != (Object)(object)Player.m_localPlayer) && __instance.InUseDistance(user)) { CompanionRecovery.RememberStation(__instance); if ((Object)(object)Player.m_localPlayer.GetCurrentCraftingStation() != (Object)(object)__instance) { CompanionBeaconUI.OpenStation(__instance); } } } } internal static class CompanionBoat { private sealed class DeckState { internal Ship Ship; internal Transform Anchor; internal int AnchorIndex; internal Vector3 FloorLocal; internal Quaternion RotationLocal; internal bool AiWasEnabled; internal bool BodyWasKinematic; internal readonly Dictionary<Collider, bool> Colliders = new Dictionary<Collider, bool>(); internal readonly Dictionary<Renderer, bool> Renderers = new Dictionary<Renderer, bool>(); internal GameObject PassengerCard; } private const string DeckedKey = "GoblinHeim.Companion.Boat.Decked"; private const string BoatUserKey = "GoblinHeim.Companion.Boat.User"; private const string BoatIdKey = "GoblinHeim.Companion.Boat.Id"; private const string AnchorIndexKey = "GoblinHeim.Companion.Boat.Anchor"; private static readonly Dictionary<Character, DeckState> Decked = new Dictionary<Character, DeckState>(); private static readonly Dictionary<Character, float> SwimSpeeds = new Dictionary<Character, float>(); internal static void Update() { //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) SynchronizeNetworkPassengers(); foreach (Character item in Decked.Keys.ToList()) { if ((Object)(object)item == (Object)null) { Decked.Remove(item); continue; } ZDO zdo = GetZdo(item); if (item.IsDead() || !CharmBinding.IsAlpha(item) || zdo == null || !zdo.GetBool("GoblinHeim.Companion.Boat.Decked", false)) { ZNetView component = ((Component)item).GetComponent<ZNetView>(); bool clearNetwork = zdo != null && zdo.GetBool("GoblinHeim.Companion.Boat.Decked", false) && (Object)(object)component != (Object)null && component.IsValid() && component.IsOwner(); Detach(item, null, placeByPlayer: false, 0, clearNetwork); } else { KeepOnDeck(item, Decked[item]); } } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } Ship localShip = Ship.GetLocalShip(); if ((Object)(object)localShip == (Object)null || !localShip.IsPlayerInBoat(localPlayer)) { DisembarkOwned(localPlayer); RestoreAllSwim(); } else { if (!((Object)(object)localPlayer.GetControlledShip() == (Object)(object)localShip) && !((Character)localPlayer).IsAttached()) { return; } List<Transform> anchors = GetAnchors(localShip); if (anchors.Count == 0) { return; } foreach (KeyValuePair<Character, int> item2 in BuildAssignments(localShip, anchors)) { Character key = item2.Key; ZDO zdo2 = GetZdo(key); if (zdo2 == null || zdo2.GetLong("GoblinHeim.Companion.Owner", 0L) != localPlayer.GetPlayerID() || (Object)(object)key == (Object)null) { continue; } if (Decked.TryGetValue(key, out var value)) { if ((Object)(object)value.Ship == (Object)(object)localShip && value.AnchorIndex == item2.Value) { continue; } Detach(key, null, placeByPlayer: false, 0, clearNetwork: true); } Transform val = anchors[item2.Value]; if (Vector3.Distance(((Component)key).transform.position, val.position) > 14f) { BoostSwim(key); } else { Board(key, localShip, val, item2.Value); } } } } private static void Board(Character companion, Ship ship, Transform anchor, int anchorIndex) { ZNetView component = ((Component)companion).GetComponent<ZNetView>(); ZNetView component2 = ((Component)ship).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && !((Object)(object)component2 == (Object)null) && component2.IsValid()) { component.ClaimOwnership(); ZDO zDO = component.GetZDO(); ZDO zDO2 = component2.GetZDO(); if (zDO != null && zDO2 != null) { zDO.Set("GoblinHeim.Companion.Boat.Decked", true); zDO.Set("GoblinHeim.Companion.Boat.User", ((ZDOID)(ref zDO2.m_uid)).UserID); zDO.Set("GoblinHeim.Companion.Boat.Id", (long)((ZDOID)(ref zDO2.m_uid)).ID); zDO.Set("GoblinHeim.Companion.Boat.Anchor", anchorIndex); AttachLocalRepresentation(companion, ship, anchor, anchorIndex); CompanionTrainingPlugin.Log.LogInfo((object)("[COMPANION-BOAT] " + CharmBinding.GetCompanionName(companion) + " boarded on network slot " + anchorIndex + ".")); } } } private static void AttachLocalRepresentation(Character companion, Ship ship, Transform anchor, int anchorIndex) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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) if ((Object)(object)companion == (Object)null || (Object)(object)ship == (Object)null || (Object)(object)anchor == (Object)null || Decked.ContainsKey(companion)) { return; } ZNetView component = ((Component)companion).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner()) { BoostSwim(companion); } MonsterAI component2 = ((Component)companion).GetComponent<MonsterAI>(); Rigidbody component3 = ((Component)companion).GetComponent<Rigidbody>(); Vector3 val = FindDeckSurface(ship, anchor, companion); DeckState deckState = new DeckState { Ship = ship, Anchor = anchor, AnchorIndex = anchorIndex, FloorLocal = ((Component)ship).transform.InverseTransformPoint(val), RotationLocal = Quaternion.Inverse(((Component)ship).transform.rotation) * anchor.rotation, AiWasEnabled = ((Object)(object)component2 != (Object)null && ((Behaviour)component2).enabled), BodyWasKinematic = ((Object)(object)component3 != (Object)null && component3.isKinematic) }; Decked[companion] = deckState; if ((Object)(object)component2 != (Object)null) { ((Behaviour)component2).enabled = false; } if ((Object)(object)component3 != (Object)null) { component3.linearVelocity = Vector3.zero; component3.angularVelocity = Vector3.zero; component3.isKinematic = true; } Collider[] componentsInChildren = ((Component)companion).GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { deckState.Colliders[val2] = val2.enabled; val2.enabled = false; } } Sprite animalIcon = GetAnimalIcon(companion); if ((Object)(object)animalIcon != (Object)null) { Renderer[] componentsInChildren2 = ((Component)companion).GetComponentsInChildren<Renderer>(true); foreach (Renderer val3 in componentsInChildren2) { if (!((Object)(object)val3 == (Object)null)) { deckState.Renderers[val3] = val3.enabled; val3.enabled = false; } } deckState.PassengerCard = CreatePassengerCard(companion, deckState, animalIcon); } KeepOnDeck(companion, deckState); } private static void KeepOnDeck(Character companion, DeckState state) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_00d6: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)companion == (Object)null || (Object)(object)state?.Ship == (Object)null || (Object)(object)state.Anchor == (Object)null) { return; } ZNetView component = ((Component)companion).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner()) { SetNetworkPosition(companion, ((Component)state.Ship).transform.TransformPoint(state.FloorLocal), ((Component)state.Ship).transform.rotation * state.RotationLocal); } if (!((Object)(object)state.PassengerCard != (Object)null)) { return; } float num = ((CompanionTrainingPlugin.GetSpecies((Component)(object)companion) == CompanionTrainingPlugin.Species.Lox) ? 1.25f : 0.95f); state.PassengerCard.transform.position = ((Component)state.Ship).transform.TransformPoint(state.FloorLocal) + ((Component)state.Ship).transform.up * (num * 0.5f + 0.08f); Camera main = Camera.main; if ((Object)(object)main != (Object)null) { Vector3 val = ((Component)main).transform.position - state.PassengerCard.transform.position; if (((Vector3)(ref val)).sqrMagnitude > 0.01f) { state.PassengerCard.transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized, ((Component)state.Ship).transform.up); } } } private static void SynchronizeNetworkPassengers() { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) ZDOID val = default(ZDOID); foreach (Character allCharacter in Character.GetAllCharacters()) { if ((Object)(object)allCharacter == (Object)null) { continue; } ZDO zdo = GetZdo(allCharacter); if (zdo != null && zdo.GetBool("GoblinHeim.Companion.Boat.Decked", false) && !CharmBinding.IsAlpha(allCharacter)) { ZNetView component = ((Component)allCharacter).GetComponent<ZNetView>(); bool clearNetwork = (Object)(object)component != (Object)null && component.IsValid() && component.IsOwner(); if (Decked.ContainsKey(allCharacter)) { Detach(allCharacter, null, placeByPlayer: false, 0, clearNetwork); } continue; } if (zdo == null || !zdo.GetBool("GoblinHeim.Companion.Boat.Decked", false)) { if (Decked.ContainsKey(allCharacter)) { Detach(allCharacter, null, placeByPlayer: false, 0, clearNetwork: false); } continue; } ((ZDOID)(ref val))..ctor(zdo.GetLong("GoblinHeim.Companion.Boat.User", 0L), (uint)zdo.GetLong("GoblinHeim.Companion.Boat.Id", 0L)); ZNetScene instance = ZNetScene.instance; GameObject val2 = ((instance != null) ? instance.FindInstance(val) : null); Ship val3 = (((Object)(object)val2 == (Object)null) ? null : val2.GetComponent<Ship>()); List<Transform> list = (((Object)(object)val3 == (Object)null) ? null : GetAnchors(val3)); int num = zdo.GetInt("GoblinHeim.Companion.Boat.Anchor", -1); if ((Object)(object)val3 == (Object)null || list == null || num < 0 || num >= list.Count) { continue; } if (Decked.TryGetValue(allCharacter, out var value)) { if ((Object)(object)value.Ship == (Object)(object)val3 && value.AnchorIndex == num) { continue; } Detach(allCharacter, null, placeByPlayer: false, 0, clearNetwork: false); } AttachLocalRepresentation(allCharacter, val3, list[num], num); } } private static Dictionary<Character, int> BuildAssignments(Ship ship, List<Transform> anchors) { Dictionary<Character, int> dictionary = new Dictionary<Character, int>(); HashSet<int> hashSet = new HashSet<int>(); for (int i = 0; i < anchors.Count; i++) { foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null && (Object)(object)allPlayer.GetAttachPoint() == (Object)(object)anchors[i]) { hashSet.Add(i); } } } ZNetView component = ((Component)ship).GetComponent<ZNetView>(); ZDO val = ((component != null) ? component.GetZDO() : null); if (val == null) { return dictionary; } List<Character> list = (from character in Character.GetAllCharacters() where (Object)(object)character != (Object)null && CharmBinding.IsAlpha(character) && GetZdo(character) != null orderby GetZdo(character).GetLong("GoblinHeim.Companion.Owner", 0L), ((ZDOID)(ref GetZdo(character).m_uid)).UserID, ((ZDOID)(ref GetZdo(character).m_uid)).ID select character).ToList(); foreach (Character item in list) { ZDO zdo = GetZdo(item); if (zdo.GetBool("GoblinHeim.Companion.Boat.Decked", false) && zdo.GetLong("GoblinHeim.Companion.Boat.User", 0L) == ((ZDOID)(ref val.m_uid)).UserID && (uint)zdo.GetLong("GoblinHeim.Companion.Boat.Id", 0L) == ((ZDOID)(ref val.m_uid)).ID) { int num = zdo.GetInt("GoblinHeim.Companion.Boat.Anchor", -1); int num2 = ((num >= 0 && num < anchors.Count && !hashSet.Contains(num)) ? num : FirstFree(anchors.Count, hashSet)); if (num2 >= 0) { dictionary[item] = num2; hashSet.Add(num2); } } } foreach (Character item2 in list) { if (dictionary.ContainsKey(item2) || (CompanionTrainingPlugin.GetSpecies((Component)(object)item2) == CompanionTrainingPlugin.Species.Lox && !AllowsLox(ship))) { continue; } MonsterAI component2 = ((Component)item2).GetComponent<MonsterAI>(); object obj; if (component2 == null) { obj = null; } else { GameObject followTarget = component2.GetFollowTarget(); obj = ((followTarget != null) ? followTarget.GetComponent<Player>() : null); } Player val2 = (Player)obj; if (!((Object)(object)val2 == (Object)null) && ship.IsPlayerInBoat(val2) && ((Object)(object)val2.GetControlledShip() == (Object)(object)ship || ((Character)val2).IsAttached())) { int num3 = FirstFree(anchors.Count, hashSet); if (num3 < 0) { break; } dictionary[item2] = num3; hashSet.Add(num3); } } return dictionary; } private static int FirstFree(int count, HashSet<int> unavailable) { for (int i = 0; i < count; i++) { if (!unavailable.Contains(i)) { return i; } } return -1; } private static List<Transform> GetAnchors(Ship ship) { List<Transform> list = new List<Transform>(); Chair[] componentsInChildren = ((Component)ship).GetComponentsInChildren<Chair>(true); foreach (Chair val in componentsInChildren) { Transform val2 = (((Object)(object)val == (Object)null) ? null : val.m_attachPoint); if ((Object)(object)val2 != (Object)null && !list.Contains(val2)) { list.Add(val2); } } return list.OrderBy(StablePath).ToList(); } private static string StablePath(Transform transform) { string text = ""; Transform val = transform; while ((Object)(object)val != (Object)null) { text = val.GetSiblingIndex().ToString("D4") + "/" + ((Object)val).name + "/" + text; val = val.parent; } return text; } private static Vector3 FindDeckSurface(Ship ship, Transform anchor, Character companion) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_0027: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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) float num = 0.05f; Collider component = ((Component)companion).GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { float y = ((Component)companion).transform.position.y; Bounds bounds = component.bounds; num = Mathf.Clamp(y - ((Bounds)(ref bounds)).min.y, 0.05f, 2.5f); } RaycastHit[] array = Physics.RaycastAll(anchor.position + ((Component)ship).transform.up * 2f, -((Component)ship).transform.up, 6f, -1, (QueryTriggerInteraction)1); RaycastHit? val = null; float num2 = float.MaxValue; RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit value = array2[i]; if (!((Object)(object)((RaycastHit)(ref value)).collider == (Object)null) && ((Component)((RaycastHit)(ref value)).collider).transform.IsChildOf(((Component)ship).transform) && ((RaycastHit)(ref value)).distance < num2) { val = value; num2 = ((RaycastHit)(ref value)).distance; } } Vector3 val2; if (!val.HasValue) { val2 = anchor.position; } else { RaycastHit value2 = val.Value; val2 = ((RaycastHit)(ref value2)).point; } return val2 + ((Component)ship).transform.up * num; } private static bool AllowsLox(Ship ship) { string text = Utils.GetPrefabName(((Component)ship).gameObject).ToLowerInvariant(); if (!text.Contains("viking") && !text.Contains("long") && !text.Contains("ashland")) { return text.Contains("drakkar"); } return true; } private static Sprite GetAnimalIcon(Character compani