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 Quads Companion v0.24.3
plugins/AICompanion.dll
Decompiled 13 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 System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DHack.Shared; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Splatform; using TMPro; using UnityEngine; using UnityEngine.AI; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI (Claude Code).")] [assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")] [assembly: AssemblyMetadata("ClaudeTools.Reload", "world")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace AICompanion { internal static class Activity { private static readonly Dictionary<long, List<string>> Lines = new Dictionary<long, List<string>>(); private static string _file; private static float _nextSizeCheck; public static void Forget() { Lines.Clear(); } public static void Log(Humanoid c, string text) { if (!((Object)(object)c == (Object)null) && !string.IsNullOrEmpty(text)) { text = Words.English(text); long key = Companion.IdOf((Component)(object)c); string text2 = $"{DateTime.Now:HH:mm:ss} {text}"; if (!Lines.TryGetValue(key, out var value)) { value = (Lines[key] = new List<string>()); } value.Add(text2); if (value.Count > 400) { value.RemoveRange(0, value.Count - 400); } Write(Companion.NameOf((Component)(object)c) + ": " + text2); } } public static List<string> Recent(Humanoid c, int n) { if (!Lines.TryGetValue(Companion.IdOf((Component)(object)c), out var value)) { return new List<string>(); } return value.Skip(Math.Max(0, value.Count - n)).ToList(); } private static void Write(string line) { try { if (_file == null) { string text = Path.Combine(Paths.BepInExRootPath, "AICompanion"); Directory.CreateDirectory(text); _file = Path.Combine(text, "activity.log"); } if (Time.time >= _nextSizeCheck) { _nextSizeCheck = Time.time + 30f; FileInfo fileInfo = new FileInfo(_file); if (fileInfo.Exists && fileInfo.Length > 2000000) { string text2 = Path.Combine(fileInfo.DirectoryName, "activity.old.log"); if (File.Exists(text2)) { File.Delete(text2); } File.Move(_file, text2); } } File.AppendAllText(_file, line + Environment.NewLine); } catch (Exception) { } } public static string Vitals(Humanoid c, BrainState st) { List<Food.Meal> list = Food.Meals(c); Inventory inventory = c.GetInventory(); string text = ((list.Count == 0) ? "none" : string.Format("{0} ({1})", list.Count, string.Join(", ", list.Select((Food.Meal m) => $"{Localization.instance.Localize(m.Item.m_shared.m_name)} {Mathf.CeilToInt(m.Time / 60f)}m")))); int num = inventory.GetAllItems().Where(Food.IsFood).Sum((ItemData i) => i.m_stack); return $"hp {((Character)c).GetHealth():0}/{((Character)c).GetMaxHealth():0}, st {Stamina.Get((Character)(object)c):0}/{Stamina.Max((Character)(object)c):0}, food {text}, food in bag {num}, " + $"bag {inventory.NrOfItems()}/{inventory.GetWidth() * inventory.GetHeight()} {Carry.Weight(c):0}kg, armour {Companion.Armor(c):0}, weapon {Name(Companion.BestMelee(c) ?? Companion.BestRanged(c))}, " + string.Format("order {0}, goal {1}", Companion.OrderOf((Component)(object)c), st.Goal?.What ?? "-"); } private static string Name(ItemData i) { if (i != null) { return Localization.instance.Localize(i.m_shared.m_name); } return "none"; } public static void Tick(BrainState st) { if (!(Time.time < st.NextSnapshot)) { st.NextSnapshot = Time.time + 30f; Log(st.Body, "· " + Vitals(st.Body, st)); } } } internal static class Archery { public static Vector3? Aim(Humanoid me, ItemData bow, Character target) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013b: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) if (bow == null || (Object)(object)target == (Object)null) { return null; } ItemData ammoItem = me.GetAmmoItem(); Attack attack = bow.m_shared.m_attack; Attack val = (((Object)(object)ammoItem?.m_shared.m_attack?.m_attackProjectile != (Object)null) ? ammoItem.m_shared.m_attack : null); if (attack == null) { return null; } float num = Mathf.Max(5f, attack.m_projectileVel + (val?.m_projectileVel ?? 0f)); GameObject val2 = val?.m_attackProjectile ?? attack.m_attackProjectile; Projectile val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Projectile>() : null); float num2 = (((Object)(object)val3 != (Object)null) ? Mathf.Max(0f, val3.m_gravity) : 0f); Vector3 val4 = ((Component)me).transform.position + Vector3.up * 1.5f; Vector3 centerPoint = target.GetCenterPoint(); Vector3 velocity = target.GetVelocity(); if (target.IsOnGround()) { velocity.y = 0f; } Vector3 val5 = centerPoint; for (int i = 0; i < 3; i++) { float num3 = Vector3.Distance(val4, val5) / num; val5 = centerPoint + velocity * num3; } Vector3 val6 = val5 - val4; float y = val6.y; val6.y = 0f; float magnitude = ((Vector3)(ref val6)).magnitude; Vector3 val7; if (magnitude < 0.5f) { val7 = val5 - val4; return ((Vector3)(ref val7)).normalized; } Vector3 val8 = val6 / magnitude; if (num2 <= 0.01f) { val7 = val5 - val4; return ((Vector3)(ref val7)).normalized; } float num4 = num * num; float num5 = num4 * num4 - num2 * (num2 * magnitude * magnitude + 2f * y * num4); if (num5 < 0f) { return null; } float num6 = Mathf.Atan((num4 - Mathf.Sqrt(num5)) / (num2 * magnitude)); val7 = val8 * Mathf.Cos(num6) + Vector3.up * Mathf.Sin(num6); return ((Vector3)(ref val7)).normalized; } } internal static class Armory { public const string Key = "dhc_armory"; private static readonly GearKind[] Kinds = new GearKind[10] { GearKind.Weapon, GearKind.Shield, GearKind.Bow, GearKind.Ammo, GearKind.Axe, GearKind.Pickaxe, GearKind.Head, GearKind.Chest, GearKind.Legs, GearKind.Cape }; public static bool Allowed(Component c) { ZDO obj = Companion.Zdo(c); if (obj == null) { return true; } return obj.GetBool("dhc_armory", true); } private static bool Worn(ItemData i) { if (i.m_shared.m_useDurability && i.m_shared.m_maxDurability > 0f) { return i.m_durability < i.GetMaxDurability() * 0.25f; } return false; } private static float Current(Humanoid me, Gear.Slot s) { if (s.Kind == GearKind.Weapon) { return (from i in me.GetInventory().GetAllItems().Where(Companion.IsMelee) select Gear.Score(me, s, i)).DefaultIfEmpty(0f).Max(); } ItemData val = Gear.In(me, s); if (val == null) { return -1f; } return Gear.Score(me, s, val); } private static bool Better(Humanoid me, Gear.Slot s, ItemData i) { if (!Gear.Fits(s, i) || Worn(i) || i.m_shared.m_questItem) { return false; } if (s.Kind == GearKind.Weapon && (Gear.IsTool(i) || !Companion.IsMelee(i))) { return false; } if (s.Kind == GearKind.Ammo) { ItemData val = Gear.In(me, Gear.All.First((Gear.Slot x) => x.Kind == GearKind.Bow)); if (val == null || val.m_shared.m_ammoType != i.m_shared.m_ammoType) { return false; } ItemData val2 = Gear.In(me, s); if (val2 != null && !(val2.m_shared.m_ammoType != val.m_shared.m_ammoType)) { return Gear.Harm(i) > Gear.Harm(val2) + 0.5f; } return true; } float num = Current(me, s); float num2 = Gear.Score(me, s, i); if (num < 0f) { return true; } return num2 > num * 1.05f + 0.5f; } private static IEnumerable<Container> YourChests(Humanoid me, Vector3 center, float radius, Func<Container, bool> allowed) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) return from c in Work.YourChests(me, center, radius) where (allowed == null || allowed(c)) && (!c.m_checkGuardStone || PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false)) select c; } private static Dictionary<ItemData, Container> Best(Humanoid me, IEnumerable<Container> chests) { List<KeyValuePair<ItemData, Container>> source = chests.SelectMany((Container c) => from i in c.GetInventory().GetAllItems() select new KeyValuePair<ItemData, Container>(i, c)).ToList(); Dictionary<ItemData, Container> picks = new Dictionary<ItemData, Container>(); GearKind[] kinds = Kinds; foreach (GearKind kind in kinds) { Gear.Slot s = Gear.All.First((Gear.Slot x) => x.Kind == kind); KeyValuePair<ItemData, Container> keyValuePair = (from p in source where !picks.ContainsKey(p.Key) && Better(me, s, p.Key) orderby Gear.Score(me, s, p.Key) descending, Vector3.Distance(((Component)p.Value).transform.position, ((Component)me).transform.position) select p).FirstOrDefault(); if (keyValuePair.Key != null) { picks[keyValuePair.Key] = keyValuePair.Value; } } return picks; } private static List<ItemData> Picks(Humanoid me, Container chest) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) return (from kv in Best(me, Work.YourChests(me, ((Component)chest).transform.position, 30f)) where (Object)(object)kv.Value == (Object)(object)chest select kv.Key).ToList(); } public static Container Find(Humanoid me, Vector3 center, float radius, Func<Container, bool> allowed = null, bool force = false) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (!force && !Allowed((Component)(object)me)) { return null; } return (from c in Best(me, YourChests(me, center, radius, allowed)).Values.Distinct() orderby Vector3.Distance(((Component)c).transform.position, ((Component)me).transform.position) select c).Take(4).FirstOrDefault((Func<Container, bool>)((Container c) => Brain.CanReach(me, ((Component)c).transform.position))); } public static string TakeFrom(BrainState st, Container chest, bool force = false) { //IL_023a: Unknown result type (might be due to invalid IL or missing references) Humanoid body = st.Body; if ((Object)(object)chest == (Object)null || (!force && !Allowed((Component)(object)body)) || Home.IdOn((Component)(object)chest) != 0L) { return null; } if (!Containers.Take(chest)) { return null; } Inventory inventory = body.GetInventory(); Inventory inventory2 = chest.GetInventory(); List<string> list = new List<string>(); foreach (ItemData pick in Picks(body, chest)) { if (!inventory2.ContainsItem(pick)) { continue; } if (inventory.GetEmptySlots() == 0) { Talk.Tell(body, Words.P("aicompanion_armory_bag_full"), "armoryfull", 60f); break; } Gear.Slot s = Gear.All.First((Gear.Slot slot) => Gear.Fits(slot, pick) && Kinds.Contains(slot.Kind) && (slot.Kind != GearKind.Weapon || !Gear.IsTool(pick))); ItemData val = Gear.In(body, s); pick.m_equipped = false; inventory.MoveItemToThis(inventory2, pick); if (!inventory.ContainsItem(pick)) { continue; } Gear.Arrange(body); string text = NameOf(pick); if (val != null && inventory.ContainsItem(val) && !Gear.InSlot(val)) { if (body.IsItemEquiped(val)) { body.UnequipItem(val, false); } val.m_equipped = false; inventory2.MoveItemToThis(inventory, val); string text2 = NameOf(val); list.Add(inventory2.ContainsItem(val) ? Words.P("aicompanion_armory_swapped", text, text2) : Words.P("aicompanion_armory_swapped_kept", text, text2)); } else { list.Add(text); } } if (list.Count == 0) { return null; } Companion.Maintain(body, wantRanged: false); Companion.SaveBag(body); string text3 = string.Join(", ", list); st.Remember(Words.P("aicompanion_armory_took", text3)); Talk.Say(body, Words.P("aicompanion_armory_found", text3)); Plugin.Instance?.Note($"{Companion.NameOf((Component)(object)body)} took better gear from the chest at {((Component)chest).transform.position:F0}: {Words.English(text3)}"); return text3; } private static string NameOf(ItemData i) { if (i.m_shared.m_maxQuality <= 1) { return Words.P("aicompanion_armory_item", Words.Low(i.m_shared.m_name)); } return Words.P("aicompanion_armory_item_level", Words.Low(i.m_shared.m_name), i.m_quality); } public static string CatchUp(BrainState st, Vector3 center, float radius) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) Humanoid body = st.Body; if (!Allowed((Component)(object)body)) { return null; } List<string> list = new List<string>(); for (int i = 0; i < 10; i++) { Container val = Best(body, Work.YourChests(body, center, radius)).Values.FirstOrDefault(); string text = (((Object)(object)val != (Object)null) ? TakeFrom(st, val) : null); if (text == null) { break; } list.Add(text); } if (list.Count <= 0) { return null; } return string.Join(", ", list); } } internal static class BagPanel { private static readonly FieldRef<InventoryGui, InventoryGrid> ContainerGrid = AccessTools.FieldRefAccess<InventoryGui, InventoryGrid>("m_containerGrid"); private static readonly FieldRef<InventoryGui, ItemData> DragItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_dragItem"); private static readonly FieldRef<InventoryGui, Container> CurrentContainer = AccessTools.FieldRefAccess<InventoryGui, Container>("m_currentContainer"); private static RectTransform _panel; private static InventoryGrid _grid; private static TMP_Text _name; private static TMP_Text _weight; private static Humanoid _shown; private static Vector2 _placedFor; private static bool _warned; public static Humanoid Shown => _shown; public static void Tick(InventoryGui gui) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_011d: Unknown result type (might be due to invalid IL or missing references) try { Humanoid val = Pick(gui); if ((Object)(object)val == (Object)null) { Hide(); } else if (!((Object)(object)_panel == (Object)null) || Build(gui)) { if (!((Component)_panel).gameObject.activeSelf) { ((Component)_panel).gameObject.SetActive(true); } if ((Object)(object)_shown != (Object)(object)val) { _shown = val; _placedFor = Vector2.zero; } _grid.UpdateInventory(val.GetInventory(), (Player)null, DragItem.Invoke(gui)); if ((Object)(object)_name != (Object)null) { _name.text = Translations.T("aicompanion_bagpanel_title", Companion.NameOf((Component)(object)val)); } if ((Object)(object)_weight != (Object)null) { _weight.text = $"{Carry.Weight(val):0}/{Carry.Max(val):0}"; } Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor((float)Screen.width, (float)Screen.height); if (_placedFor != val2) { Place(gui); _placedFor = val2; } } } catch (Exception ex) { if (!_warned) { _warned = true; Plugin.Instance?.Warn("Companion bag panel: " + ex); } Hide(); } } private static Humanoid Pick(InventoryGui gui) { Player p = Player.m_localPlayer; if ((Object)(object)p == (Object)null || !InventoryGui.IsVisible()) { return null; } Container open = CurrentContainer.Invoke(gui); return (from c in Companion.All() where Companion.IsMine((Component)(object)c, p) && !((Character)c).IsDead() && ((Component)c).GetComponent<ZNetView>().IsOwner() && Vector3.Distance(((Component)c).transform.position, ((Component)p).transform.position) < 10f && ((Object)(object)open == (Object)null || (Object)(object)((Component)open).gameObject != (Object)(object)((Component)c).gameObject) orderby Vector3.Distance(((Component)c).transform.position, ((Component)p).transform.position) select c).FirstOrDefault(); } private static bool Build(InventoryGui gui) { //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown InventoryGrid val = ContainerGrid.Invoke(gui); if ((Object)(object)gui.m_container == (Object)null || (Object)(object)val == (Object)null) { return false; } GameObject val2 = Object.Instantiate<GameObject>(((Component)gui.m_container).gameObject, ((Transform)gui.m_container).parent, false); ((Object)val2).name = "DHack_CompanionBag"; _panel = val2.GetComponent<RectTransform>(); Button[] componentsInChildren = val2.GetComponentsInChildren<Button>(true); foreach (Button val3 in componentsInChildren) { Object.Destroy((Object)(object)((Component)val3).gameObject); } _grid = val2.GetComponentInChildren<InventoryGrid>(true); if ((Object)(object)_grid == (Object)null) { Object.Destroy((Object)(object)val2); _panel = null; return false; } if ((Object)(object)_grid.m_gridRoot != (Object)null) { foreach (Transform item in (Transform)_grid.m_gridRoot) { Transform val4 = item; Object.Destroy((Object)(object)((Component)val4).gameObject); } } _grid.m_onSelected = Wire<Action<InventoryGrid, ItemData, Vector2i, Modifier>>(gui, "OnSelectedItem"); _grid.m_onReleased = Wire<Action<InventoryGrid, ItemData, Vector2i>>(gui, "OnReleasedItem"); _grid.m_onEnter = Wire<Action<InventoryGrid, Vector2i>>(gui, "OnEnterElement"); _grid.OnSetTouchSelection = Wire<Action<InventoryGrid>>(gui, "SetTouchSelection"); _grid.CanDropDragOntoItem = Wire<Func<ItemData, bool>>(gui, "CanDropDragOntoItem") ?? ((Func<ItemData, bool>)((ItemData item) => true)); _grid.m_onRightClick = TakeToYou; _name = Find(val2, gui.m_container, gui.m_containerName); _weight = Find(val2, gui.m_container, gui.m_containerWeight); float num = 2f * _grid.m_elementSpace + 14f; RectTransform panel = _panel; panel.sizeDelta += new Vector2(0f, num); InventoryGrid_UpdateGui_Bag.Forget(); val2.SetActive(true); Plugin.Instance?.Note("Companion bag panel made beside the inventory"); return true; } private static T Wire<T>(InventoryGui gui, string method) where T : Delegate { MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), method, (Type[])null, (Type[])null); if (!(methodInfo != null)) { return null; } return (T)Delegate.CreateDelegate(typeof(T), gui, methodInfo, throwOnBindFailure: false); } private static TMP_Text Find(GameObject copy, RectTransform original, TMP_Text text) { if ((Object)(object)text == (Object)null) { return null; } string text2 = ""; Transform val = text.transform; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)((Component)original).transform) { text2 = ((text2.Length == 0) ? ((Object)val).name : (((Object)val).name + "/" + text2)); val = val.parent; } Transform val2 = copy.transform.Find(text2); if (!((Object)(object)val2 != (Object)null)) { return null; } return ((Component)val2).GetComponent<TMP_Text>(); } private static void TakeToYou(InventoryGrid grid, ItemData item, Vector2i pos) { Player localPlayer = Player.m_localPlayer; if (item != null && !((Object)(object)localPlayer == (Object)null) && !((Object)(object)_shown == (Object)null) && !Companion.Take(_shown, localPlayer, item, out var why) && why != null) { ((Character)localPlayer).Message((MessageType)2, Words.Show(why), 0, (Sprite)null, false); } } private static void Place(InventoryGui gui) { //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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) Vector3[] array = (Vector3[])(object)new Vector3[4]; gui.m_player.GetWorldCorners(array); Vector3[] array2 = (Vector3[])(object)new Vector3[4]; _panel.GetWorldCorners(array2); float num = array2[2].x - array2[1].x; float num2 = array2[1].y - array2[0].y; float num3 = (array[2].x - array[1].x) * 0.13f; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(array[2].x + num3, array[2].y, array2[1].z); if ((Object)(object)gui.m_crafting != (Object)null && ((Component)gui.m_crafting).gameObject.activeInHierarchy) { Vector3[] array3 = (Vector3[])(object)new Vector3[4]; gui.m_crafting.GetWorldCorners(array3); if (val.x + num > array3[0].x - num3 * 0.3f && val.y - num2 < array3[1].y) { ((Vector3)(ref val))..ctor(array3[0].x, array3[0].y - num3 * 0.3f, array2[1].z); } } RectTransform panel = _panel; ((Transform)panel).position = ((Transform)panel).position + (val - array2[1]); } private static void Hide() { _shown = null; if ((Object)(object)_panel != (Object)null && ((Component)_panel).gameObject.activeSelf) { ((Component)_panel).gameObject.SetActive(false); } } public static bool IsBagGrid(InventoryGrid grid) { if ((Object)(object)grid != (Object)null) { return (Object)(object)grid == (Object)(object)_grid; } return false; } public static void Destroy() { if ((Object)(object)_panel != (Object)null) { Object.Destroy((Object)(object)((Component)_panel).gameObject); } _panel = null; _grid = null; _name = (_weight = null); _shown = null; } } [HarmonyPatch(typeof(InventoryGui), "Update")] internal static class InventoryGui_Update_Bag { private static void Postfix(InventoryGui __instance) { BagPanel.Tick(__instance); } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] internal static class InventoryGui_OnSelectedItem_QuickMove { private static readonly FieldRef<InventoryGui, GameObject> DragGo = AccessTools.FieldRefAccess<InventoryGui, GameObject>("m_dragGo"); private static readonly FieldRef<InventoryGui, Container> Open = AccessTools.FieldRefAccess<InventoryGui, Container>("m_currentContainer"); private static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 Humanoid shown = BagPanel.Shown; Player localPlayer = Player.m_localPlayer; if ((int)mod != 2 || item == null || (Object)(object)shown == (Object)null || (Object)(object)localPlayer == (Object)null || (Object)(object)Open.Invoke(__instance) != (Object)null || (Object)(object)DragGo.Invoke(__instance) != (Object)null) { return true; } string why; if (BagPanel.IsBagGrid(grid)) { if (!Companion.Take(shown, localPlayer, item, out why) && why != null) { ((Character)localPlayer).Message((MessageType)2, Words.Show(why), 0, (Sprite)null, false); } return false; } if ((Object)(object)grid == (Object)(object)__instance.m_playerGrid) { if (!Companion.Give(shown, localPlayer, item, out why) && why != null) { ((Character)localPlayer).Message((MessageType)2, Words.Show(why), 0, (Sprite)null, false); } return false; } return true; } } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] internal static class InventoryGui_UpdateContainer_Bag { internal static bool Inside; private static void Prefix() { Inside = true; } private static void Finalizer() { Inside = false; } } [HarmonyPatch(typeof(InventoryGui), "SetupDragItem")] internal static class InventoryGui_SetupDragItem_Bag { private static readonly FieldRef<InventoryGui, Inventory> DragFrom = AccessTools.FieldRefAccess<InventoryGui, Inventory>("m_dragInventory"); private static bool Prefix(InventoryGui __instance, ItemData item) { if (item != null || !InventoryGui_UpdateContainer_Bag.Inside) { return true; } Inventory val = DragFrom.Invoke(__instance); if ((Object)(object)BagPanel.Shown != (Object)null && val != null) { return val != BagPanel.Shown.GetInventory(); } return true; } } internal class BookData { public long Id; public long MasterId; public string MasterName = ""; public readonly List<string> Entries = new List<string>(); public readonly Dictionary<string, int> Tally = new Dictionary<string, int>(); public string Missions = ""; public bool Fresh; public float AskedAt = -99f; public float UsedAt; public float OfferedAt; public float ParkSentAt; public int OfferTries; public int ParkTries; public int LastParked; public bool Dirty; public readonly List<string> NewEntries = new List<string>(); public readonly Dictionary<string, int> NewCounts = new Dictionary<string, int>(); public string NewMissions; public string JournalText => string.Join("\n", Entries); public string TallyText => string.Join(";", Tally.Select((KeyValuePair<string, int> kv) => $"{kv.Key}={kv.Value}")); public bool HasNews { get { if (NewEntries.Count <= 0 && NewCounts.Count <= 0) { return NewMissions != null; } return true; } } } internal static class Book { private const string RpcAsk = "DHack_CompanionBookAsk"; private const string RpcWhole = "DHack_CompanionBook"; private const string RpcNews = "DHack_CompanionBookNews"; private const string RpcOffer = "DHack_CompanionBookOffer"; private const string RpcTaken = "DHack_CompanionBookTaken"; private const string RpcParked = "DHack_CompanionBookParked"; public static readonly string[] RpcNames = new string[6] { "DHack_CompanionBookAsk", "DHack_CompanionBook", "DHack_CompanionBookNews", "DHack_CompanionBookOffer", "DHack_CompanionBookTaken", "DHack_CompanionBookParked" }; private const char Field = '\u001e'; private const char Item = '\u001f'; public const string OldEntriesKey = "dhc_journal"; public const string OldTallyKey = "dhc_tally"; public const string OldMissionsKey = "dhc_missions"; public const string ParkedKey = "dhc_booknews"; private const int ParkedMax = 1500; private static float _nextPark; private static readonly Dictionary<long, BookData> Books = new Dictionary<long, BookData>(); private static float _nextTick; private static float _nextSave; public static void Stop() { if ((Object)(object)Player.m_localPlayer != (Object)null) { SaveProfiles(Player.m_localPlayer); } Books.Clear(); } public static void Register(ZRoutedRpc rpc) { Books.Clear(); rpc.Register<string>("DHack_CompanionBookAsk", (Action<long, string>)OnAsk); rpc.Register<string>("DHack_CompanionBook", (Action<long, string>)OnWhole); rpc.Register<string>("DHack_CompanionBookNews", (Action<long, string>)OnNews); rpc.Register<string>("DHack_CompanionBookOffer", (Action<long, string>)OnOffer); rpc.Register<string>("DHack_CompanionBookTaken", (Action<long, string>)OnTaken); rpc.Register<string>("DHack_CompanionBookParked", (Action<long, string>)OnParked); } public static BookData Of(Component c) { ZDO val = Companion.Zdo(c); if (val != null) { return Of(Companion.IdOf(c), val, 0L); } return new BookData(); } public static BookData Of(long id, ZDO z, long master = 0L) { if ((Object)(object)Player.m_localPlayer == (Object)null) { return new BookData { Id = id }; } if (!Books.TryGetValue(id, out var value)) { value = (Books[id] = Make(id, z, master)); } else if (!value.Fresh && master != 0L && value.MasterId == 0L) { value.MasterId = master; } if (!value.Fresh && Ours(value)) { value = (Books[id] = Make(id, z, value.MasterId)); } if (z != null && value.MasterId == 0L) { value.MasterId = z.GetLong("dhc_master", 0L); value.MasterName = z.GetString("dhc_mastername", ""); } value.UsedAt = Time.time; if (!value.Fresh) { Ask(value); } return value; } private static BookData Make(long id, ZDO z, long master) { BookData bookData = new BookData { Id = id, MasterId = master }; Player localPlayer = Player.m_localPlayer; if (z != null) { bookData.MasterId = z.GetLong("dhc_master", 0L); bookData.MasterName = z.GetString("dhc_mastername", ""); } Profile profile = (((Object)(object)localPlayer != (Object)null) ? Profile.Find(localPlayer, id) : null); if (profile != null && bookData.MasterId == 0L) { bookData.MasterId = localPlayer.GetPlayerID(); } if (Ours(bookData) && string.IsNullOrEmpty(bookData.MasterName)) { bookData.MasterName = localPlayer.GetPlayerName(); } if (Ours(bookData)) { if (profile != null) { Fill(bookData, profile.JournalText, profile.TallyText, profile.MissionText); } if (z != null && HasOld(z)) { Join(bookData, z.GetString("dhc_journal", ""), z.GetString("dhc_tally", ""), z.GetString("dhc_missions", "")); } bookData.Fresh = true; } else if (z != null && HasOld(z)) { Fill(bookData, z.GetString("dhc_journal", ""), z.GetString("dhc_tally", ""), z.GetString("dhc_missions", "")); bookData.Fresh = true; } return bookData; } private static bool Ours(BookData b) { if ((Object)(object)Player.m_localPlayer != (Object)null && b.MasterId != 0L) { return b.MasterId == Player.m_localPlayer.GetPlayerID(); } return false; } private static bool HasOld(ZDO z) { if (!(z.GetString("dhc_journal", "") != "") && !(z.GetString("dhc_tally", "") != "")) { return z.GetString("dhc_missions", "") != ""; } return true; } private static void Fill(BookData b, string journal, string tally, string missions) { b.Entries.Clear(); b.Entries.AddRange((journal ?? "").Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries)); b.Tally.Clear(); string[] array = (tally ?? "").Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { int num = text.LastIndexOf('='); if (num > 0 && int.TryParse(text.Substring(num + 1), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { b.Tally[text.Substring(0, num)] = result; } } b.Missions = missions ?? ""; } public static void AddEntry(Humanoid c, string entry) { BookData bookData = Of((Component)(object)c); entry = Plain(entry); Entry(bookData, entry); bookData.NewEntries.Add(entry); if (bookData.NewEntries.Count > 150) { bookData.NewEntries.RemoveRange(0, bookData.NewEntries.Count - 150); } } public static int AddCount(Humanoid c, string what, int n) { BookData bookData = Of((Component)(object)c); what = Plain(what).Replace(';', ',').Replace('=', '-'); bookData.NewCounts[what] = (bookData.NewCounts.TryGetValue(what, out var value) ? value : 0) + n; return Count(bookData, what, n); } public static void SetMissions(Humanoid c, string text) { BookData bookData = Of((Component)(object)c); text = Plain(text); if (!(bookData.Missions == text)) { bookData.Missions = text; bookData.NewMissions = text; bookData.Dirty = true; } } private static string Plain(string s) { return (s ?? "").Replace('\u001f', ' ').Replace('\u001e', ' '); } private static void Entry(BookData b, string entry) { b.Entries.Add(entry); if (b.Entries.Count > 150) { b.Entries.RemoveRange(0, b.Entries.Count - 150); } b.Dirty = true; } private static int Count(BookData b, string what, int n) { b.Tally[what] = (b.Tally.TryGetValue(what, out var value) ? value : 0) + n; b.Dirty = true; return b.Tally[what]; } public static void Tick() { if (Time.time < _nextTick || (Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null) { return; } _nextTick = Time.time + 1f; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } HashSet<string> hashSet = Online(); Dictionary<long, ZDO> dictionary = new Dictionary<long, ZDO>(); foreach (Humanoid item in Companion.All()) { if (((Component)item).GetComponent<ZNetView>().IsOwner()) { dictionary[Companion.IdOf((Component)(object)item)] = Companion.Zdo((Component)(object)item); } } foreach (KeyValuePair<long, ZDO> item2 in dictionary) { if (item2.Value.GetString("dhc_booknews", "") != "") { Of(item2.Key, item2.Value, 0L); } } bool flag = Time.time >= _nextPark; if (flag) { _nextPark = Time.time + 5f; } foreach (BookData value2 in Books.Values) { dictionary.TryGetValue(value2.Id, out var value); bool flag2 = hashSet.Contains(value2.MasterName); if (value2.HasNews) { if (Ours(value2)) { if (hashSet.Count > 1) { Send(value2); } else { Clear(value2); } } else if (flag2) { Send(value2); } else if (flag && value != null) { Park(value2, value); } } string text = ((value != null) ? value.GetString("dhc_booknews", "") : null) ?? ""; if (text != "") { if (Ours(value2)) { Apply(value2, text.Split(new char[1] { '\u001f' })); value.Set("dhc_booknews", ""); } else if (flag2 && Due(ref value2.ParkSentAt, ref value2.ParkTries)) { Invoke(MasterPeer(value2), "DHack_CompanionBookParked", Head(value2) + "\u001e" + text); } } if (!value2.Fresh && Time.time - value2.UsedAt < 10f) { Ask(value2); } } foreach (Humanoid item3 in Companion.All()) { ZNetView component = ((Component)item3).GetComponent<ZNetView>(); if (component.IsOwner() && HasOld(component.GetZDO())) { ZDO zDO = component.GetZDO(); BookData bookData = Of((Component)(object)item3); string text2 = zDO.GetString("dhc_journal", ""); string text3 = zDO.GetString("dhc_tally", ""); string text4 = zDO.GetString("dhc_missions", ""); if (Ours(bookData)) { Join(bookData, text2, text3, text4); ClearOld(zDO); Plugin.Instance?.Note(Companion.NameOf((Component)(object)item3) + "'s journal moved off its network data (it was sent to every player with each step)"); } else if (hashSet.Contains(bookData.MasterName) && Due(ref bookData.OfferedAt, ref bookData.OfferTries)) { Invoke(MasterPeer(bookData), "DHack_CompanionBookOffer", string.Join('\u001e'.ToString(), Head(bookData), text2, text3, text4)); } } } if (Time.time >= _nextSave) { _nextSave = Time.time + 5f; SaveProfiles(localPlayer); } } private static bool Due(ref float at, ref int tries) { if (tries >= 8 || Time.time < at) { return false; } at = Time.time + Mathf.Min(300f, 10f * Mathf.Pow(2f, (float)tries)); tries++; return true; } private static long MasterPeer(BookData b) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) foreach (PlayerInfo player in ZNet.instance.GetPlayerList()) { if (player.m_name == b.MasterName) { ZDOID characterID = player.m_characterID; if (!((ZDOID)(ref characterID)).IsNone()) { characterID = player.m_characterID; return ((ZDOID)(ref characterID)).UserID; } } } return 0L; } private static void Join(BookData b, string journal, string tally, string missions) { BookData bookData = new BookData(); Fill(bookData, journal, tally, missions); HashSet<string> known = new HashSet<string>(bookData.Entries); List<string> list = bookData.Entries.Concat(b.Entries.Where((string e) => !known.Contains(e))).ToList(); b.Entries.Clear(); b.Entries.AddRange(list.Skip(Math.Max(0, list.Count - 150))); foreach (KeyValuePair<string, int> item in bookData.Tally) { b.Tally[item.Key] = Math.Max(item.Value, b.Tally.TryGetValue(item.Key, out var value) ? value : 0); } if (bookData.Missions != "") { b.Missions = bookData.Missions; } b.Fresh = (b.Dirty = true); } private static void ClearOld(ZDO z) { z.Set("dhc_journal", ""); z.Set("dhc_tally", ""); z.Set("dhc_missions", ""); } private static int OldStamp(ZDO z) { return StringExtensionMethods.GetStableHashCode(string.Join('\u001e'.ToString(), z.GetString("dhc_journal", ""), z.GetString("dhc_tally", ""), z.GetString("dhc_missions", ""))); } private static void OnOffer(long sender, string payload) { string[] array = (payload ?? "").Split(new char[1] { '\u001e' }); if (array.Length >= 4 && ParseHead(array[0], out var id, out var master) && !((Object)(object)Player.m_localPlayer == (Object)null) && master != 0L && Player.m_localPlayer.GetPlayerID() == master && Profile.Find(Player.m_localPlayer, id) != null) { BookData b = Of(id, null, master); Join(b, array[1], array[2], array[3]); SaveProfiles(Player.m_localPlayer); string text = StringExtensionMethods.GetStableHashCode(string.Join('\u001e'.ToString(), array[1], array[2], array[3])).ToString(CultureInfo.InvariantCulture); Invoke(sender, "DHack_CompanionBookTaken", id.ToString(CultureInfo.InvariantCulture) + "|" + text + "|old"); Plugin.Instance?.Note($"A companion's journal ({id}) was handed over by the game running it"); } } private static void OnParked(long sender, string payload) { int num = (payload ?? "").IndexOf('\u001e'); if (num >= 0 && ParseHead(payload.Substring(0, num), out var id, out var master) && !((Object)(object)Player.m_localPlayer == (Object)null) && master != 0L && Player.m_localPlayer.GetPlayerID() == master && Profile.Find(Player.m_localPlayer, id) != null) { string text = payload.Substring(num + 1); int stableHashCode = StringExtensionMethods.GetStableHashCode(text); BookData bookData = Of(id, null, master); if (bookData.LastParked != stableHashCode) { Apply(bookData, text.Split(new char[1] { '\u001f' })); bookData.LastParked = stableHashCode; SaveProfiles(Player.m_localPlayer); } Invoke(sender, "DHack_CompanionBookTaken", id.ToString(CultureInfo.InvariantCulture) + "|" + stableHashCode.ToString(CultureInfo.InvariantCulture) + "|parked"); } } private static void OnTaken(long sender, string payload) { string[] array = (payload ?? "").Split(new char[1] { '|' }); if (array.Length < 2 || !long.TryParse(array[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var id) || !int.TryParse(array[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return; } Humanoid val = Companion.All().FirstOrDefault((Func<Humanoid, bool>)((Humanoid x) => Companion.IdOf((Component)(object)x) == id)); ZDO val2 = Companion.Zdo((Component)(object)val); if (val2 == null || !((Component)val).GetComponent<ZNetView>().IsOwner()) { return; } Books.TryGetValue(id, out var value); if (array.Length >= 3 && array[2] == "parked") { if (StringExtensionMethods.GetStableHashCode(val2.GetString("dhc_booknews", "")) != result) { if (value != null) { value.ParkTries = 0; } return; } val2.Set("dhc_booknews", ""); if (value != null) { value.ParkTries = 0; } Plugin.Instance?.Note(Companion.NameOf((Component)(object)val) + "'s news from while its player was away was handed over"); } else if (!HasOld(val2) || OldStamp(val2) != result) { if (value != null) { value.OfferTries = 0; } } else { ClearOld(val2); Plugin.Instance?.Note(Companion.NameOf((Component)(object)val) + "'s journal moved off its network data (its player's game has it)"); } } public static void SaveProfiles(Player me) { foreach (BookData item in Books.Values.Where((BookData x) => x.Dirty && x.Fresh && Ours(x))) { item.Dirty = false; Profile profile = Profile.Find(me, item.Id); if (profile != null) { profile.JournalText = item.JournalText; profile.TallyText = item.TallyText; profile.MissionText = item.Missions; Profile.Save(me, profile); } } } private static HashSet<string> Online() { return new HashSet<string>(from p in ZNet.instance.GetPlayerList() where !((ZDOID)(ref p.m_characterID)).IsNone() select p.m_name); } public static void Leaving() { if ((Object)(object)ZNet.instance == (Object)null) { return; } HashSet<string> hashSet = Online(); foreach (Humanoid item in Companion.All()) { if (((Component)item).GetComponent<ZNetView>().IsOwner() && Books.TryGetValue(Companion.IdOf((Component)(object)item), out var value) && value.HasNews && !Ours(value) && !hashSet.Contains(value.MasterName)) { Park(value, Companion.Zdo((Component)(object)item)); } } } private static void Park(BookData b, ZDO z) { List<string> entries = new List<string>(); Dictionary<string, int> counts = new Dictionary<string, int>(); string missions = null; foreach (string item in z.GetString("dhc_booknews", "").Split(new char[1] { '\u001f' }).Concat(Items(b))) { if (item.Length != 0) { string text = item.Substring(1); string what; int n; if (item[0] == 'e') { entries.Add(text); } else if (item[0] == 'm') { missions = text; } else if (item[0] == 'c' && SplitCount(text, out what, out n)) { counts[what] = (counts.TryGetValue(what, out var value) ? value : 0) + n; } } } Clear(b); string text2 = Build(); if (text2.Length > 1500 && missions != null) { missions = null; text2 = Build(); } while (text2.Length > 1500 && entries.Count > 0) { entries.RemoveAt(0); text2 = Build(); } z.Set("dhc_booknews", text2); string Build() { return string.Join('\u001f'.ToString(), entries.Select((string e) => "e" + e).Concat(counts.Select((KeyValuePair<string, int> kv) => "c" + kv.Key + "=" + kv.Value.ToString(CultureInfo.InvariantCulture))).Concat((missions == null) ? new string[0] : new string[1] { "m" + missions })); } } private static void Clear(BookData b) { b.NewEntries.Clear(); b.NewCounts.Clear(); b.NewMissions = null; } private static string Head(BookData b) { return b.Id.ToString(CultureInfo.InvariantCulture) + "|" + b.MasterId.ToString(CultureInfo.InvariantCulture); } private static bool ParseHead(string head, out long id, out long master) { master = 0L; string[] array = head.Split(new char[1] { '|' }); if (long.TryParse(array[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out id) && array.Length >= 2) { return long.TryParse(array[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out master); } return false; } private static List<string> Items(BookData b) { List<string> list = new List<string>(); list.AddRange(b.NewEntries.Select((string e) => "e" + e)); list.AddRange(b.NewCounts.Select((KeyValuePair<string, int> kv) => "c" + kv.Key + "=" + kv.Value.ToString(CultureInfo.InvariantCulture))); if (b.NewMissions != null) { list.Add("m" + b.NewMissions); } return list; } private static bool SplitCount(string text, out string what, out int n) { int num = text.LastIndexOf('='); what = ((num > 0) ? text.Substring(0, num) : null); n = 0; if (num > 0) { return int.TryParse(text.Substring(num + 1), NumberStyles.Integer, CultureInfo.InvariantCulture, out n); } return false; } private static void Send(BookData b, IEnumerable<string> items = null) { List<string> list = items?.Where((string x) => x.Length > 0).ToList(); if (list == null) { list = Items(b); Clear(b); } if (list.Count != 0) { Invoke(0L, "DHack_CompanionBookNews", Head(b) + "\u001f" + string.Join('\u001f'.ToString(), list)); } } private static void OnNews(long sender, string payload) { if (sender == ZDOMan.GetSessionID()) { return; } string[] array = (payload ?? "").Split(new char[1] { '\u001f' }); if (ParseHead(array[0], out var id, out var master)) { BookData value; if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() == master) { value = Of(id, null, master); } else if (!Books.TryGetValue(id, out value)) { return; } Apply(value, array.Skip(1)); } } private static void Apply(BookData b, IEnumerable<string> items) { foreach (string item in items) { if (item.Length != 0) { string text = item.Substring(1); string what; int n; if (item[0] == 'e') { Entry(b, text); } else if (item[0] == 'm') { b.Missions = text; b.Dirty = true; } else if (item[0] == 'c' && SplitCount(text, out what, out n)) { Count(b, what, n); } } } } private static void Ask(BookData b) { if (!(Time.time - b.AskedAt < 5f) && ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.GetPlayerList().Count >= 2) { b.AskedAt = Time.time; Invoke(0L, "DHack_CompanionBookAsk", Head(b)); } } private static void OnAsk(long sender, string payload) { if (sender == ZDOMan.GetSessionID() || !ParseHead(payload ?? "", out var id, out var master)) { return; } BookData value; if ((Object)(object)Player.m_localPlayer != (Object)null && master != 0L && Player.m_localPlayer.GetPlayerID() == master) { value = Of(id, null, master); } else { Humanoid val = Companion.All().FirstOrDefault((Func<Humanoid, bool>)((Humanoid x) => Companion.IdOf((Component)(object)x) == id)); if ((Object)(object)val == (Object)null || !((Component)val).GetComponent<ZNetView>().IsOwner() || !Books.TryGetValue(id, out value) || !value.Fresh || Online().Contains(value.MasterName)) { return; } } if (value.Fresh) { Invoke(sender, "DHack_CompanionBook", string.Join('\u001e'.ToString(), id.ToString(CultureInfo.InvariantCulture), value.JournalText, value.TallyText, value.Missions)); } } private static void OnWhole(long sender, string payload) { string[] array = (payload ?? "").Split(new char[1] { '\u001e' }); if (array.Length < 4 || !long.TryParse(array[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !Books.TryGetValue(result, out var value) || value.Fresh) { return; } Fill(value, array[1], array[2], array[3]); foreach (string newEntry in value.NewEntries) { Entry(value, newEntry); } foreach (KeyValuePair<string, int> newCount in value.NewCounts) { Count(value, newCount.Key, newCount.Value); } if (value.NewMissions != null) { value.Missions = value.NewMissions; } value.Fresh = true; } private static void Invoke(long target, string rpc, string payload) { try { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(target, rpc, new object[1] { payload }); } } catch (Exception ex) { Plugin.Instance?.Warn("Could not send " + rpc + ": " + ex.Message); } } } public enum Tactic { Attack, DefendPlayer, BackOff, Retreat, Flee } internal class Decision { public Tactic Action; public Character Target; public bool Ranged; public bool Drink; public float Confidence = 1f; public string Note = ""; public float Time; public string Describe(Func<Character, string> label) { bool flag = Ranged && (Action == Tactic.Attack || Action == Tactic.DefendPlayer); string text = Action switch { Tactic.Attack => ((Object)(object)Target != (Object)null) ? Words.P(flag ? "aicompanion_brain_do_attack_bow" : "aicompanion_brain_do_attack", label(Target)) : Words.P(flag ? "aicompanion_brain_do_attack_nearest_bow" : "aicompanion_brain_do_attack_nearest"), Tactic.DefendPlayer => Words.P(flag ? "aicompanion_brain_do_defend_bow" : "aicompanion_brain_do_defend"), Tactic.BackOff => Words.P("aicompanion_brain_do_back_off"), Tactic.Retreat => Words.P("aicompanion_brain_do_fall_back"), _ => Words.P("aicompanion_brain_do_flee"), }; if (Drink) { text = Words.P("aicompanion_brain_do_drink", text); } return text; } } internal class BrainState { public Humanoid Body; public MonsterAI Ai; public Decision Current = new Decision(); public readonly List<Character> Enemies = new List<Character>(); public readonly Dictionary<Character, string> Labels = new Dictionary<Character, string>(); public readonly List<string> History = new List<string>(); public bool InCombat; public bool Asking; public int Fights; public int Potions; public float FightStart; public float Taken; public float Dealt; public float LastHealth; public int FightKills; public int FightDecisions; public bool Sitting; public bool IdleReady; public Chair SitChair; public Chair IdleChair; public Fireplace IdleFire; public IdlePlan IdlePlan; public float SitKeep; public float StillSince; public float AwaySince; public float NextGreetLook; public float ComeUntil; public float EmoteUntil; public float PendingEmoteAt; public float YouStillSince; public float IdleUntil; public float IdleSince; public float NextLookAround; public string PendingEmote; public Character EmoteFace; public int YourEmoteId = int.MinValue; public Vector3 YouWere; public Vector3 IdleAt; public Vector3 LookAroundAt; public TombStone GraveOrdered; public TombStone GraveOn; public readonly List<ItemDrop> PickQueue = new List<ItemDrop>(); private Work.Area _area; public List<Vector3> Path; public Vector3? PathTo; public int PathIndex; public float PathUntil; public float NextPathTry; public float PathProgressAt; public float PathBest; public readonly Dictionary<Door, float> OpenedDoors = new Dictionary<Door, float>(); public bool SwingMissed; public float NextRefillLook; public float NextArmoryLook; public float BedSince; public Vector3 BedFrom; public float NextDeliver; public float NextTidy; public float NextStockLook; public Dictionary<string, int> StockCaps; public float MissionSince; public float MissionBest; public float MissionAskSince; public float MissionReadySince; public readonly Dictionary<string, float> DroppedUntil = new Dictionary<string, float>(); public List<Goal> Candidates = new List<Goal>(); public float WokeAt = -999f; public Work.Task Task; public CraftingStation RepairAt; public float NextRepairLook; public float RepairSince; public bool RepairAll; public bool RollCredited; public Ship Riding; public Chair Seat; public Vector3 DeckSpot; public float RideLastSeen; public ItemData WorkTool; public string WorkNote; public Vector3 WorkSpot; public float NextWorkLook; public float NextDoorLook; public float NextUpgradeLook; public float YieldUntil; public Vector3 YieldTo; public Player YieldFrom; public bool CaughtUp; public float NextStamp; public float NextBagSave; public float NextGraveLook; public readonly List<Loot.Spot> LootSpots = new List<Loot.Spot>(); public readonly List<KeyValuePair<ItemDrop, float>> LootDrops = new List<KeyValuePair<ItemDrop, float>>(); public Vector3 CookedAt; public float NextPassBy; public Brain.DoorPlan Door; public Character StallOn; public float StallSince; public float StallHealth; public readonly Dictionary<Character, float> LeaveAlone = new Dictionary<Character, float>(); public float BlockUntil; public float NextBanterLook; public bool SaidNight; public string LastLand = ""; public string LastBoss = ""; public bool Asleep; public Bed SleepBed; public Vagon Cart; public float CartSince; public float CartAsked; public float ClearUntil; public Vector3 ClearTo; public int UnstickStage; public float SideStepUntil; public float NextLoanLook; public Vector3 SideStepTo; public Character Focus; public float FocusUntil; public float CommandUntil; public float InvulnUntil; public float NextMeadLook; public float RunBackUntil; public bool HitAndRun; public int Blows; public int FightDodges; public int ParriesAtStart; public int BlocksAtStart; public int PotionsAtStart; public readonly HashSet<string> FightFoes = new HashSet<string>(); public readonly List<string> FightLog = new List<string>(); public float EvadeUntil; public float NextEvade; public float EvadeSide; public float CounterUntil; public Vector3 EvadeTo; public int Parries; public int Blocks; public Character Blocker; public float NextSnapshot; public float LastHurtAt; public float GraveSince; public float GraveBest = float.MaxValue; public string LastHurtBy = ""; public bool Hungry; public bool Weak; public List<Building.Cand> BuildList = new List<Building.Cand>(); public readonly Dictionary<string, float> BuildSkip = new Dictionary<string, float>(); public Dictionary<string, int> BuildWant = new Dictionary<string, int>(); public float NextBuildLook; public readonly HashSet<string> BuildKeep = new HashSet<string>(); public float BuildKeepUntil; public int Built; public string BuildNote; public float PlanGoalAt; public Goal PlanGoal; public Duties.Entry Duty; public bool OnDuties; public readonly Dictionary<string, float> Unfindable = new Dictionary<string, float>(); public Goal Goal; public string GoalSaid; public float NextTripLook; public float TripUntil; public float NextFireLook; public float NextMendLook; public float NextMend; public float NextReadLook; public float ManualOrderAt = -999f; public float HomeSince; public bool Outing; public bool MasterWasHome; public bool SortWhenHome; public Doing Doing; public bool DefendOnly; public bool Outmatched; public bool Helping; public Style AutoStyle = Style.Balanced; public string AutoNote = ""; public float NextFoodLook; public float NextNeedLook; public float MasterGoneSince; public float TripStart; public readonly HashSet<string> Wanted = new HashSet<string>(); public readonly Dictionary<int, float> Skipped = new Dictionary<int, float>(); public readonly Dictionary<string, int> Gathered = new Dictionary<string, int>(); public float NextEnemyScan; public float NextGear; public float NextAsk; public float LastAsk; public float HealthAtAsk = 1f; public float NextStuckCheck; public float StuckDistance = float.MaxValue; public Vector3 StuckFrom; public int StuckFor; public int EnemyCountAtAsk; public string Status = ""; public float NextStatusSave; public Work.Area Area { get { return _area; } set { _area = value; Work.SaveArea(this); } } public string Label(Character c) { if ((Object)(object)c == (Object)null) { return "?"; } if (Labels.TryGetValue(c, out var value)) { return value; } string name = c.m_name; int i; for (i = 1; Labels.ContainsValue($"{name} {i}"); i++) { } return Labels[c] = $"{name} {i}"; } public void Remember(string line) { Activity.Log(Body, "» " + line); History.Insert(0, line); if (History.Count > 8) { History.RemoveAt(History.Count - 1); } } } internal static class Brain { internal class DoorPlan { public Door Door; public Vector3 Near; public Vector3 Far; public Vector3 Target; public float Until; public bool Through; public DoorPlan Next; } private static readonly Dictionary<Humanoid, BrainState> States = new Dictionary<Humanoid, BrainState>(); private static readonly Func<BaseAI, float, Vector3, float, bool, bool> MoveToRaw = AccessTools.MethodDelegate<Func<BaseAI, float, Vector3, float, bool, bool>>(AccessTools.Method(typeof(BaseAI), "MoveTo", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<BaseAI, Vector3, bool> HavePath = AccessTools.MethodDelegate<Func<BaseAI, Vector3, bool>>(AccessTools.Method(typeof(BaseAI), "HavePath", (Type[])null, (Type[])null), (object)null, true); private static readonly Action<BaseAI, Vector3> LookAt = AccessTools.MethodDelegate<Action<BaseAI, Vector3>>(AccessTools.Method(typeof(BaseAI), "LookAt", (Type[])null, (Type[])null), (object)null, true); private static readonly Action<BaseAI, float> Regenerate = AccessTools.MethodDelegate<Action<BaseAI, float>>(AccessTools.Method(typeof(BaseAI), "UpdateRegeneration", (Type[])null, (Type[])null), (object)null, true); private static readonly FieldRef<BaseAI, float> TimeSinceHurt = AccessTools.FieldRefAccess<BaseAI, float>("m_timeSinceHurt"); private static readonly FieldRef<Character, bool> Blocking = AccessTools.FieldRefAccess<Character, bool>("m_blocking"); private static readonly FieldRef<Humanoid, float> DrawTime = AccessTools.FieldRefAccess<Humanoid, float>("m_attackDrawTime"); private static readonly Collider[] DoorHits = (Collider[])(object)new Collider[128]; private static readonly int Solid = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "vehicle" }); private static readonly int PieceMask = LayerMask.GetMask(new string[3] { "piece", "piece_nonsolid", "Default" }); private static bool MoveTo(BaseAI ai, float dt, Vector3 point, float dist, bool run) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0229: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) Character component = ((Component)ai).GetComponent<Character>(); bool flag = run && Stamina.CanRun(component); bool result = MoveToRaw(ai, dt, point, dist, flag); Vector3 position = ((Component)component).transform.position; if (!(Utils.DistanceXZ(point, position) <= Mathf.Max(dist, 0.75f))) { Vector3 moveDir = component.GetMoveDir(); if (!(((Vector3)(ref moveDir)).sqrMagnitude > 0.01f)) { Humanoid val = (Humanoid)(object)((component is Humanoid) ? component : null); BrainState brainState = (((Object)(object)val != (Object)null) ? Get(val) : null); if (brainState != null) { DoorPlan doorPlan = ((brainState.Door != null && Time.time < brainState.Door.Until && Vector3.Distance(brainState.Door.Target, point) < 4f) ? brainState.Door : (brainState.Door = PlanDoor(ai, position, point))); if (doorPlan != null) { if (!doorPlan.Through) { if (Utils.DistanceXZ(doorPlan.Near, position) > 1.2f) { MoveToRaw(ai, dt, doorPlan.Near, 0.8f, flag); moveDir = component.GetMoveDir(); if (((Vector3)(ref moveDir)).sqrMagnitude > 0.01f) { return false; } } ZDO obj = Companion.Zdo((Component)(object)doorPlan.Door); if ((obj == null || obj.GetInt(ZDOVars.s_state, 0) == 0) && (Object)(object)doorPlan.Door.m_keyItem == (Object)null) { doorPlan.Door.Interact(val, false, false); Opened(brainState, doorPlan.Door); } doorPlan.Through = true; } if (Utils.DistanceXZ(doorPlan.Far, position) > 1f) { Vector3 val2 = doorPlan.Far - position; val2.y = 0f; component.SetMoveDir(((Vector3)(ref val2)).normalized); component.SetLookDir(((Vector3)(ref val2)).normalized, 0f); return false; } brainState.Door = doorPlan.Next; return false; } } if (brainState != null && Wayfinding.Follow(brainState, val, point, flag)) { return false; } if ((Object)(object)val != (Object)null && Steer.HazardsNear(val) > 0 && !ClearLine(val, position, point)) { return result; } Vector3 val3 = point - position; val3.y = 0f; if (((Vector3)(ref val3)).sqrMagnitude < 0.01f) { return result; } ((Vector3)(ref val3)).Normalize(); component.SetMoveDir(val3); component.SetRun(flag); component.SetLookDir(val3, 0f); return false; } } return result; } private static bool ClearLine(Humanoid h, Vector3 from, Vector3 to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) float num = Utils.DistanceXZ(from, to); if (num > 8f) { return false; } for (float num2 = 0.5f; num2 < num + 0.25f; num2 += 0.5f) { if (!Steer.Safe(Vector3.Lerp(from, to, Mathf.Min(1f, num2 / num)), h)) { return false; } } return true; } internal static bool CanReach(Humanoid me, Vector3 to, float near = 2.5f) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) BaseAI component = ((Component)me).GetComponent<BaseAI>(); Pathfinding instance = Pathfinding.instance; if ((Object)(object)component == (Object)null || (Object)(object)instance == (Object)null) { return true; } Vector3 val = default(Vector3); if (!instance.FindValidPoint(ref val, ((Component)me).transform.position, 2f, component.m_pathAgentType)) { return Wayfinding.CanReach(Get(me), me, to); } Vector3 val2 = default(Vector3); if (!instance.FindValidPoint(ref val2, to, near, component.m_pathAgentType)) { return false; } if (!instance.HavePath(((Component)me).transform.position, val2, component.m_pathAgentType)) { return PlanDoor(component, ((Component)me).transform.position, to) != null; } return true; } internal static List<string> PathReport(Humanoid me, Vector3 to) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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) //IL_0061: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03ea: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0429: Unknown result type (might be due to invalid IL or missing references) //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_047d: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0633: Unknown result type (might be due to invalid IL or missing references) //IL_0639: 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_04ec: Unknown result type (might be due to invalid IL or missing references) //IL_04f6: Unknown result type (might be due to invalid IL or missing references) //IL_04fb: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Unknown result type (might be due to invalid IL or missing references) //IL_0521: Unknown result type (might be due to invalid IL or missing references) //IL_052d: Unknown result type (might be due to invalid IL or missing references) //IL_0537: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Unknown result type (might be due to invalid IL or missing references) //IL_0547: Unknown result type (might be due to invalid IL or missing references) //IL_0577: Unknown result type (might be due to invalid IL or missing references) //IL_058b: Unknown result type (might be due to invalid IL or missing references) //IL_0591: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Invalid comparison between I4 and Unknown //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_05ee: Unknown result type (might be due to invalid IL or missing references) //IL_05fb: Unknown result type (might be due to invalid IL or missing references) List<string> list = new List<string>(); BaseAI component = ((Component)me).GetComponent<BaseAI>(); Pathfinding pf = Pathfinding.instance; if ((Object)(object)component == (Object)null || (Object)(object)pf == (Object)null) { list.Add("no pathfinding"); return list; } AgentType agent = component.m_pathAgentType; Vector3 from = ((Component)me).transform.position; Vector3 goal = default(Vector3); bool goalOk = pf.FindValidPoint(ref goal, to, 2.5f, agent); Vector3 val = default(Vector3); bool flag = pf.FindValidPoint(ref val, from, 1.5f, agent); list.Add(string.Format("from {0:F1} (navmesh point {1}) to {2:F1} (navmesh point {3}), agent {4}", from, flag ? ((Vector3)(ref val)).ToString("F1") : "NONE", to, goalOk ? ((Vector3)(ref goal)).ToString("F1") : "NONE", agent)); try { Traverse val2 = Traverse.Create((object)pf); IDictionary dictionary = val2.Field("m_tiles").GetValue() as IDictionary; object value = val2.Field("m_buildOperation").GetValue(); int num = Mathf.FloorToInt((from.x + 16f) / 32f); int num2 = Mathf.FloorToInt((from.z + 16f) / 32f); object obj = null; if (dictionary != null) { foreach (DictionaryEntry item in dictionary) { Vector3Int val3 = (Vector3Int)item.Key; if (((Vector3Int)(ref val3)).x == num && ((Vector3Int)(ref val3)).y == num2 && ((Vector3Int)(ref val3)).z == (int)agent) { obj = item.Value; } } } string text = ((obj == null) ? "none" : string.Format("built {0}, poked {1}, now {2:0.0}", Traverse.Create(obj).Field("m_buildTime").GetValue(), Traverse.Create(obj).Field("m_pokeTime").GetValue(), Time.time)); object value2 = Traverse.Create((object)pf).Method("GetSettings", new object[1] { agent }).GetValue(); NavMeshQueryFilter val4 = default(NavMeshQueryFilter); ((NavMeshQueryFilter)(ref val4)).agentTypeID = (int)Traverse.Create(value2).Field("m_agentType").GetValue(); ((NavMeshQueryFilter)(ref val4)).areaMask = (int)Traverse.Create(value2).Field("m_areaMask").GetValue(); NavMeshQueryFilter val5 = val4; NavMeshHit val6 = default(NavMeshHit); bool flag2 = NavMesh.SamplePosition(from, ref val6, 10f, val5); object[] obj2 = new object[4] { dictionary?.Count ?? (-1), null, null, null }; AsyncOperation val7 = (AsyncOperation)((value is AsyncOperation) ? value : null); obj2[1] = ((val7 == null) ? "no" : (val7.isDone ? "no" : $"yes {val7.progress:0.00}")); obj2[2] = text; obj2[3] = (flag2 ? $"{((NavMeshHit)(ref val6)).position:F1} ({Vector3.Distance(((NavMeshHit)(ref val6)).position, from):0.0} m)" : "none"); list.Add(string.Format("walk map: {0} tiles, building {1}, its tile {2}; nearest walkable within 10 m: {3}", obj2)); } catch (Exception ex) { list.Add("walk map: " + ex.Message); } object arg = pf.HavePath(from, goalOk ? goal : to, agent); DoorPlan doorPlan = PlanDoor(component, from, to); list.Add(string.Format("direct path: {0}; door plan: {1}", arg, (doorPlan != null) ? ($"through the door at {((Component)doorPlan.Door).transform.position:F0}" + ((doorPlan.Next != null) ? $" then {((Component)doorPlan.Next.Door).transform.position:F0}" : "")) : "none")); int num3 = Physics.OverlapSphereNonAlloc(from, 40f, DoorHits, PieceMask); HashSet<Door> hashSet = new HashSet<Door>(); Vector3 p = default(Vector3); Vector3 p2 = default(Vector3); for (int i = 0; i < num3; i++) { Door componentInParent = ((Component)DoorHits[i]).GetComponentInParent<Door>(); if (!((Object)(object)componentInParent == (Object)null) && hashSet.Add(componentInParent)) { bool ok = pf.FindValidPoint(ref p, ((Component)componentInParent).transform.position + ((Component)componentInParent).transform.forward * 1.6f, 1.5f, agent); bool ok2 = pf.FindValidPoint(ref p2, ((Component)componentInParent).transform.position - ((Component)componentInParent).transform.forward * 1.6f, 1.5f, agent); object[] obj3 = new object[7] { Utils.GetPrefabName(((Component)componentInParent).gameObject), ((Component)componentInParent).transform.position, Vector3.Distance(((Component)componentInParent).transform.position, from), null, null, null, null }; ZDO obj4 = Companion.Zdo((Component)(object)componentInParent); obj3[3] = ((obj4 == null || obj4.GetInt(ZDOVars.s_state, 0) == 0) ? "shut" : "open"); obj3[4] = (((Object)(object)componentInParent.m_keyItem != (Object)null) ? ", locked" : ""); obj3[5] = side(ok, p); obj3[6] = side(ok2, p2); list.Add(string.Format("{0} at {1:F1} ({2:0} m, {3}{4}): side A {5}; side B {6}", obj3)); } } if (hashSet.Count == 0) { list.Add("no doors within 40 m"); } List<Vector3> own = Wayfinding.Find(me, from, to); list.Add((own == null) ? "its own way-finding: no way found" : string.Format("its own way-finding: {0} steps, by {1}", own.Count, string.Join(" ", from q in own.Where((Vector3 _, int num4) => num4 % Mathf.Max(1, own.Count / 8) == 0) select $"({q.x:0},{q.z:0})"))); return list; string side(bool flag3, Vector3 val8) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (!flag3) { return "no navmesh"; } return $"{val8:F1} reach {pf.HavePath(from, val8, agent)}, to bed {pf.HavePath(val8, goalOk ? goal : to, agent)}"; } } private static DoorPlan PlanDoor(BaseAI ai, Vector3 from, Vector3 to) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_00f3: 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_0102: 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_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: 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) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: 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) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: 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_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: 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_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0360: 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_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) Pathfinding instance = Pathfinding.instance; if ((Object)(object)instance == (Object)null) { return null; } AgentType pathAgentType = ai.m_pathAgentType; Vector3 val = default(Vector3); if (!instance.FindValidPoint(ref val, to, 2.5f, pathAgentType)) { val = to; } List<KeyValuePair<Door, Vector3[]>> list = new List<KeyValuePair<Door, Vector3[]>>(); HashSet<Door> hashSet = new HashSet<Door>(); int num = Physics.OverlapSphereNonAlloc(from, 40f, DoorHits, PieceMask); Vector3 val2 = default(Vector3); Vector3 val3 = default(Vector3); for (int i = 0; i < num; i++) { Door componentInParent = ((Component)DoorHits[i]).GetComponentInParent<Door>(); if (!((Object)(object)componentInParent == (Object)null) && !((Object)(object)componentInParent.m_keyItem != (Object)null) && hashSet.Add(componentInParent) && instance.FindValidPoint(ref val2, ((Component)componentInParent).transform.position + ((Component)componentInParent).transform.forward * 1.6f, 1.5f, pathAgentType) && instance.FindValidPoint(ref val3, ((Component)componentInParent).transform.position - ((Component)componentInParent).transform.forward * 1.6f, 1.5f, pathAgentType)) { list.Add(new KeyValuePair<Door, Vector3[]>(componentInParent, (Vector3[])(object)new Vector3[2] { val2, val3 })); } } list.Sort((KeyValuePair<Door, Vector3[]> x, KeyValuePair<Door, Vector3[]> y) => Vector3.Distance(((Component)x.Key).transform.position, from).CompareTo(Vector3.Distance(((Component)y.Key).transform.position, from))); if (list.Count > 10) { list.RemoveRange(10, list.Count - 10); } DoorPlan doorPlan = null; float num2 = float.MaxValue; List<DoorPlan> list2 = new List<DoorPlan>(); foreach (KeyValuePair<Door, Vector3[]> item in list) { Vector3 val4 = Side(item.Value, from, near: true); Vector3 val5 = Side(item.Value, from, near: false); if (instance.HavePath(from, val4, pathAgentType)) { DoorPlan doorPlan2 = new DoorPlan { Door = item.Key, Near = val4, Far = val5, Target = to, Until = Time.time + 20f }; list2.Add(doorPlan2); float num3 = Vector3.Distance(from, val4) + Vector3.Distance(val5, val); if (num3 < num2 && instance.HavePath(val5, val, pathAgentType)) { num2 = num3; doorPlan = doorPlan2; } } } if (doorPlan != null) { return doorPlan; } foreach (DoorPlan item2 in list2) { foreach (KeyValuePair<Door, Vector3[]> item3 in list) { if (!((Object)(object)item3.Key == (Object)(object)item2.Door)) { Vector3 val6 = Side(item3.Value, item2.Far, near: true); Vector3 val7 = Side(item3.Value, item2.Far, near: false); float num4 = Vector3.Distance(from, item2.Near) + Vector3.Distance(item2.Far, val6) + Vector3.Distance(val7, val); if (!(num4 >= num2) && instance.HavePath(item2.Far, val6, pathAgentType) && instance.HavePath(val7, val, pathAgentType)) { num2 = num4; doorPlan = new DoorPlan { Door = item2.Door, Near = item2.Near, Far = item2.Far, Target = to, Until = Time.time + 30f, Next = new DoorPlan { Door = item3.Key, Near = val6, Far = val7, Target = to, Until = Time.time + 30f } }; } } } } return doorPlan; } private static Vector3 Side(Vector3[] sides, Vector3 from, bool near) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (Vector3.Distance(sides[0], from) < Vector3.Distance(sides[1], from) != near) { return sides[1]; } return sides[0]; } private static Door DoorOnTheWay(Vector3 from, Vector3 to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_0069: 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_006f: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) Vector3 val = to - from; val.y = 0f; Door result = null; float num = float.MaxValue; int num2 = Physics.OverlapSphereNonAlloc(from, 12f, DoorHits, PieceMask); for (int i = 0; i < num2; i++) { Door componentInParent = ((Component)DoorHits[i]).GetComponentInParent<Door>(); if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent.m_keyItem != (Object)null) { continue; } Vector3 val2 = ((Component)componentInParent).transform.position - from; val2.y = 0f; float magnitude = ((Vector3)(ref val2)).magnitude; if (!(magnitude < 1f) && !(magnitude >= num) && !(Vector3.Angle(val, val2) > 90f)) { ZDO obj = Companion.Zdo((Component)(object)componentInParent); if (obj == null || obj.GetInt(ZDOVars.s_state, 0) == 0) { result = componentInParent; num = magnitude; } } } return result; } public static void Forget() { foreach (BrainState value in States.Values) { if ((Object)(object)value.Body != (Object)null) { Blocking.Invoke((Character)(object)value.Body) = false; } } States.Clear(); } public static void Forget(Humanoid h) { if ((Object)(object)h != (Object)null) { States.Remove(h); } } public static BrainState Get(Humanoid h) { if ((Object)(object)h == (Object)null) { return null; } if (!States.TryGetValue(h, out var value)) { foreach (Humanoid item in States.Keys.Where((Humanoid k) => (Object)(object)k == (Object)null).ToList()) { States.Remove(item); } value = (States[h] = new BrainState { Body = h, Ai = ((Component)h).GetComponent<MonsterAI>() }); ZNetView component = ((Component)h).GetComponent<ZNetView>(); if (component != null && component.IsValid() && component.IsOwner()) { Work.RestoreArea(value); Rigidbody component2 = ((Component)h).GetComponent<Rigidbody>(); if (component2 != null && component2.isKinematic && (Object)(object)((Component)h).GetComponentInParent<Ship>() == (Object)null && !((Character)h).IsAttached()) { component2.isKinematic = false; component2.detectCollisions = true; } value.Cart = ((IEnumerable<Vagon>)Object.FindObjectsByType<Vagon>((FindObjectsSortMode)0)).FirstOrDefault((Func<Vagon, bool>)((Vagon cart) => (Object)(object)cart != (Object)null && cart.IsAttached((Character)(object)h))); } } return value; } public static bool Update(MonsterAI ai, float dt) { //IL_0282: Unknown result type (might be due to invalid IL or missing references) ZNetView component = ((Component)ai).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner()) { return false; } TimeSinceHurt.Invoke((BaseAI)(object)ai) += dt; Humanoid component2 = ((Component)ai).GetComponent<Humanoid>(); Stamina.Tick(component2, dt); Tactics.Tick(Get(component2)); Eitr.Tick(component2, dt); Weather.Tick(component2); Humanoid component3 = ((Component)ai).GetComponent<Humanoid>(); BrainState brainState = Get(component3); Player master = Companion.Master((Component)(object)component3); Container component4 = ((Component)component3).GetComponent<Container>(); if (!brainState.CaughtUp) { CatchUp.OnArrive(brainState); } if (Companion.OrderOf((Component)(object)component3) == Order.Gather && Time.time >= brainState.NextStamp) { brainState.NextStamp = Time.time + 30f; CatchUp.Stamp(component3); } SaveStatus(brainState); Food.Tick(component3, brainState); Activity.Tick(brainState); Following.Tick(brainState, master); Banter.Tick(brainState, master); Idle.Tick(brainState, master); if (Time.time >= brainState.NextBagSave) { brainState.NextBagSave = Time.time + 30f; Companion.SaveBag(component3); } if (Ride.Tick(brainState, master)) { return true; } Loot.PassBy(brainState); if (Time.time >= brainState.NextGear) { brainState.NextGear = Time.time + 0.5f; Companion.Maintain(component3, brainState.Current.Ranged, brainState.InCombat ? null : brainState.WorkTool, brainState.InCombat ? brainState.Current.Target : null); } if ((Object)(object)component4 != (Object)null && Containers.InUse(component4)) { ((BaseAI)ai).StopMoving(); Blocking.Invoke((Character)(object)component3) = false; SetStatus(brainState, Words.P("aicompanion_brain_status_gear_open")); return true; } if (!brainState.Asleep && Carts.Tick(brainState, delegate(Vector3 p, float dd, bool run) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) MoveTo((BaseAI)(object)ai, dt, p, dd, run); }, delegate { ((BaseAI)ai).StopMoving(); })) { return true; } if (Time.time >= brainState.NextEnemyScan) { brainState.NextEnemyScan = Time.time + 0.25f; ScanEnemies(brainState, master); } foreach (Character enemy in brainState.Enemies) { if ((Object)(object)enemy != (Object)null && enemy.IsDead()) { Loot.AddSpot(brainState, ((Component)enemy).transform.position); } } brainState.Enemies.RemoveAll((Character e) => (Object)(object)e == (Object)null || e.IsDead()); if (Time.time >= brainState.NextDoorLook) { brainState.NextDoorLook = Time.time + 0.4f; OpenDoorAhead(component3); CloseBehind(brainState); } if (Companion.OrderOf((Component)(object)component3) != Order.Gather && (Companion.OrderOf((Component)(object)component3) != Order.Follow || (!brainState.Helping && !(Time.time < brainState.CommandUntil) && brainState.Area == null))) { brainState.Task = null; brainState.WorkTool = null; } if (brainState.Enemies.Count > 0 && brainState.Asleep) { Sleep.Wake(brainState, Words.P("aicompanion_brain_wake_something_came")); } Character val = ((IEnumerable<Character>)brainState.Enemies).FirstOrDefault((Func<Character, bool>)((Character e) => (Object)(object)e != (Object)null && e.IsBoss())); if ((Object)(object)val != (Object)null && brainState.LastBoss != val.m_name) { brainState.LastBoss = val.m_name; Banter.BossSeen(component3, val.m_name); } if (brainState.Enemies.Count == 0) { if (brainState.InCombat) { brainState.InCombat = false; brainState.Labels.Clear(); Summarise(brainState, fell: false); if (((Character)component3).GetHealthPercentage() < 0.3f) { Banter.CloseFight(component3); } else if (brainState.FightKills >= 3) { Idle.Queue(brainState, "cheer", 1f); } } Blocking.Invoke((Character)(object)component3) = false; Peaceful(brainState, master, dt); return true; } if (!brainState.InCombat) { brainState.FightFoes.Clear(); brainState.FightDodges = 0; brainState.ParriesAtStart = brainState.Parries; brainState.BlocksAtStart = brainState.Blocks; brainState.PotionsAtStart = brainState.Potions; brainState.InCombat = true; brainState.NextAsk = 0f; brainState.Fights++; brainState.FightStart = Time.time; brainState.Taken = (brainState.Dealt = 0f); brainState.FightKills = (brainState.FightDecisions = 0); brainState.LastHealth = ((Character)component3).GetHealth(); } foreach (Character enemy2 in brainState.Enemies) { if (!((Object)(object)enemy2 == (Object)null)) { string name = enemy2.m_name; if (brainState.FightFoes.Add(name) && Tactics.Feared(component3, enemy2)) { Banter.Say(component3, "feared:" + name, 10f, Words.P("aicompanion_brain_feared_1", name), Words.P("aicompanion_brain_feared_2", Words.Low(name)), Words.P("aicompanion_brain_feared_3", Words.Low(name))); } } } float health = ((Character)compo