Decompiled source of Quads Companion v0.24.3

plugins/AICompanion.dll

Decompiled 13 hours ago
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