Decompiled source of Companions of Northarun v0.1.0

Companions.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Companions;

public class Companion : MonoBehaviour, Interactable
{
	public const string ZOwner = "nc_owner";

	public const string ZSpecies = "nc_species";

	public const string ZName = "nc_name";

	public const string ZLevel = "nc_level";

	public const string ZSkin = "nc_skin";

	public const string ZTalents = "nc_talents";

	public const string ZMode = "nc_mode";

	public const string ZStay = "nc_stay";

	public const string ZBond = "nc_bond";

	public const string ZRows = "nc_rows";

	public const string ZAway = "nc_away";

	public string SpeciesId = "";

	public static readonly List<Companion> All = new List<Companion>();

	internal ZNetView NView;

	internal Character Char;

	internal Container Bag;

	internal SpeciesDef Def;

	private string _talentSrc;

	private Dictionary<string, int> _talents = new Dictionary<string, int>();

	private int _looksHash = int.MinValue;

	private float _looksTimer;

	private Vector3 _baseScale = Vector3.one;

	private GameObject _aura;

	private Light _glow;

	private float _baseWalk;

	private float _baseSpeed;

	private float _baseRun;

	internal float FenrirReady;

	internal float UnbrokenReady;

	internal float FrenzyReady;

	internal float BulwarkReady;

	internal float StompReady;

	internal float TauntTimer;

	internal float DistractTimer;

	internal float HarassTimer;

	internal float LastHurt = -100f;

	internal float LastCombat = -100f;

	internal float BuffUntil;

	internal float BulwarkUntil;

	internal float FrenzyUntil;

	internal Character LastTarget;

	internal Character ChargedTarget;

	internal ZDO Zdo
	{
		get
		{
			if (!((Object)(object)NView != (Object)null) || !NView.IsValid())
			{
				return null;
			}
			return NView.GetZDO();
		}
	}

	public long OwnerId
	{
		get
		{
			ZDO zdo = Zdo;
			if (zdo == null)
			{
				return 0L;
			}
			return zdo.GetLong("nc_owner", 0L);
		}
	}

	public bool IsMine
	{
		get
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && OwnerId != 0)
			{
				return OwnerId == localPlayer.GetPlayerID();
			}
			return false;
		}
	}

	public Player OwnerPlayer
	{
		get
		{
			long ownerId = OwnerId;
			if (ownerId == 0)
			{
				return null;
			}
			return Player.GetPlayer(ownerId);
		}
	}

	public int Level
	{
		get
		{
			ZDO zdo = Zdo;
			if (zdo == null)
			{
				return 1;
			}
			return Math.Max(1, zdo.GetInt("nc_level", 1));
		}
	}

	public string PetName
	{
		get
		{
			ZDO zdo = Zdo;
			string text = ((zdo != null) ? zdo.GetString("nc_name", "") : "");
			if (text.Length <= 0)
			{
				return Loc.T("nc_species_" + SpeciesId);
			}
			return text;
		}
	}

	internal Mode Mode
	{
		get
		{
			ZDO zdo = Zdo;
			if (zdo == null)
			{
				return Mode.Follow;
			}
			return (Mode)zdo.GetInt("nc_mode", 0);
		}
	}

	public Vector3 StayPoint
	{
		get
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			ZDO zdo = Zdo;
			if (zdo == null)
			{
				return ((Component)this).transform.position;
			}
			return zdo.GetVec3("nc_stay", ((Component)this).transform.position);
		}
	}

	public float Bond
	{
		get
		{
			ZDO zdo = Zdo;
			if (zdo == null)
			{
				return 50f;
			}
			return zdo.GetFloat("nc_bond", 50f);
		}
	}

	public bool Away
	{
		get
		{
			ZDO zdo = Zdo;
			if (zdo != null)
			{
				return zdo.GetBool("nc_away", false);
			}
			return false;
		}
	}

	private void Awake()
	{
		//IL_003c: 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)
		NView = ((Component)this).GetComponent<ZNetView>();
		Char = ((Component)this).GetComponent<Character>();
		Bag = ((Component)this).GetComponent<Container>();
		Def = Species.Get(SpeciesId);
		_baseScale = ((Component)this).transform.localScale;
		if ((Object)(object)Char != (Object)null)
		{
			_baseWalk = Char.m_walkSpeed;
			_baseSpeed = Char.m_speed;
			_baseRun = Char.m_runSpeed;
		}
	}

	private void Start()
	{
		if (!((Object)(object)NView == (Object)null) && NView.IsValid())
		{
			All.Add(this);
			ApplyLooks(force: true);
			if (IsMine)
			{
				Manager.Adopt(this);
			}
		}
	}

	private void OnDestroy()
	{
		All.Remove(this);
		if (IsMine)
		{
			Manager.OnPetDestroyed(this);
		}
	}

	private void Update()
	{
		if (!((Object)(object)NView == (Object)null) && NView.IsValid())
		{
			_looksTimer -= Time.deltaTime;
			if (_looksTimer <= 0f)
			{
				_looksTimer = 1.5f;
				ApplyLooks(force: false);
			}
		}
	}

	public int Rank(string id)
	{
		ZDO zdo = Zdo;
		string text = ((zdo != null) ? zdo.GetString("nc_talents", "") : "");
		if (text != _talentSrc)
		{
			_talentSrc = text;
			_talents = PetData.ParseTalents(text);
		}
		if (!_talents.TryGetValue(id, out var value))
		{
			return 0;
		}
		return value;
	}

	public float Val(string id)
	{
		return Talents.Get(id)?.Value(Rank(id)) ?? 0f;
	}

	internal void ApplyLooks(bool force)
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = Zdo;
		if (zdo == null || Def == null)
		{
			return;
		}
		int level = Level;
		int num = Species.Stage(level);
		int num2 = zdo.GetInt("nc_skin", 0);
		int num3 = num * 100 + num2;
		if (!force && num3 == _looksHash)
		{
			return;
		}
		_looksHash = num3;
		float num4 = Def.Scale[Mathf.Clamp(num, 0, Def.Scale.Length - 1)];
		((Component)this).transform.localScale = _baseScale * num4;
		try
		{
			Visuals.Tint(((Component)this).gameObject, Def.Skins[Mathf.Clamp(num2, 0, Def.Skins.Length - 1)], num, num2);
		}
		catch (Exception ex)
		{
			if (Plugin.DebugLog.Value)
			{
				Plugin.Log.LogWarning((object)("Companion tint: " + ex.Message));
			}
		}
		if (num >= 2 && (Object)(object)_glow == (Object)null && !GUIManager.IsHeadless())
		{
			_glow = Visuals.AddEyeGlow(this);
		}
		if (num < 2 && (Object)(object)_glow != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)_glow).gameObject);
			_glow = null;
		}
		if (num >= 3 && (Object)(object)_aura == (Object)null && !GUIManager.IsHeadless())
		{
			_aura = Visuals.AddAura(this, Def.Skins[Mathf.Clamp(num2, 0, Def.Skins.Length - 1)]);
		}
		if (num < 3 && (Object)(object)_aura != (Object)null)
		{
			Object.Destroy((Object)(object)_aura);
			_aura = null;
		}
		if ((Object)(object)Char != (Object)null && NView.IsOwner())
		{
			RefreshMaxHealth();
		}
	}

	internal void RefreshMaxHealth()
	{
		if (!((Object)(object)Char == (Object)null) && Def != null)
		{
			float num = Def.Health * Species.HealthMult(Level) * Plugin.HealthMultiplier.Value;
			num *= 1f + Val("w_coat") + Val("b_thick") + Val("t_stone") + Val("l_hide");
			float maxHealth = Char.GetMaxHealth();
			if (!(Mathf.Abs(maxHealth - num) < 0.5f))
			{
				float num2 = ((maxHealth > 0f) ? Mathf.Clamp01(Char.GetHealth() / maxHealth) : 1f);
				Char.SetMaxHealth(num);
				Char.SetHealth(num * ((num2 <= 0f) ? 1f : num2));
			}
		}
	}

	internal void RefreshSpeed()
	{
		if (!((Object)(object)Char == (Object)null))
		{
			float num = 1f + Val("l_stride");
			if (Time.time < BuffUntil)
			{
				num += Val("w_rescue");
			}
			if (Time.time < FrenzyUntil)
			{
				num += 0.3f;
			}
			if ((Object)(object)Bag != (Object)null && Def != null && Def.Role == Role.Carry)
			{
				float totalWeight = Bag.GetInventory().GetTotalWeight();
				float num2 = Mathf.Min(0.4f, totalWeight / 1000f) * Mathf.Max(0f, 1f - Val("l_light"));
				num *= 1f - num2;
			}
			Char.m_walkSpeed = _baseWalk * num;
			Char.m_speed = _baseSpeed * num;
			Char.m_runSpeed = _baseRun * num;
		}
	}

	internal float HitDamage(Character target)
	{
		if (Def == null)
		{
			return 10f;
		}
		float num = Def.Damage * Species.DamageMult(Level) * Plugin.DamageMultiplier.Value;
		float num2 = 1f + Val("w_jaws") + Val("b_charge") + Val("t_slam");
		Player ownerPlayer = OwnerPlayer;
		if ((Object)(object)target != (Object)null)
		{
			BaseAI baseAI = target.GetBaseAI();
			if ((Object)(object)ownerPlayer != (Object)null && (Object)(object)baseAI != (Object)null && (Object)(object)baseAI.GetTargetCreature() == (Object)(object)ownerPlayer)
			{
				num2 += Val("w_hunter");
			}
			if (target.IsStaggering())
			{
				num2 += Val("w_steel");
			}
		}
		if (Time.time < BuffUntil)
		{
			num2 += Val("w_rescue");
		}
		if (Time.time < FrenzyUntil)
		{
			num2 += 0.5f;
		}
		if (Mode == Mode.Stay && Rank("t_guardian") > 0)
		{
			num2 += Val("t_guardian");
		}
		return num * num2;
	}

	internal float DamageTakenFactor()
	{
		//IL_0039: 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_0044: Invalid comparison between Unknown and I4
		float num = 1f - Val("w_hide") - Val("l_wall");
		if (Rank("b_mud") > 0 && (EnvMan.IsWet() || (int)Heightmap.FindBiome(((Component)this).transform.position) == 2))
		{
			num -= Val("b_mud");
		}
		if (Time.time < BulwarkUntil)
		{
			num *= 0.5f;
		}
		return Mathf.Clamp(num, 0.2f, 1f);
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		if (hold || (Object)(object)user != (Object)(object)Player.m_localPlayer)
		{
			return false;
		}
		if (!IsMine)
		{
			((Character)user).Message((MessageType)2, Loc.T("not_yours", PetName), 0, (Sprite)null, false);
			return true;
		}
		if (alt)
		{
			OpenBag();
			return true;
		}
		Manager.PetPet(this);
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		if ((Object)(object)user != (Object)(object)Player.m_localPlayer || item == null)
		{
			return false;
		}
		if (!IsMine)
		{
			return false;
		}
		Manager.Feed(this, item);
		return true;
	}

	internal void OpenBag()
	{
		if ((Object)(object)Bag == (Object)null || Zdo == null || Zdo.GetInt("nc_rows", 0) <= 0)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null)
			{
				((Character)localPlayer).Message((MessageType)2, Loc.T("no_bag", PetName), 0, (Sprite)null, false);
			}
		}
		else
		{
			Bag.Interact((Humanoid)(object)Player.m_localPlayer, false, false);
		}
	}

	internal string HoverText()
	{
		string text = "<color=#F4C870>" + PetName + "</color>  <color=#A8A8A8>" + Loc.T("hover_level", Level, Loc.T("stage_" + Species.Stage(Level))) + "</color>";
		if (!IsMine)
		{
			Player ownerPlayer = OwnerPlayer;
			return text + "\n<color=#A8A8A8>" + Loc.T("hover_owner", ((Object)(object)ownerPlayer != (Object)null) ? ownerPlayer.GetPlayerName() : "?") + "</color>";
		}
		text = text + "\n<color=#A8A8A8>" + Loc.T("mode_" + (int)Mode) + "</color>";
		text = text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + Loc.T("hover_pet");
		if (Zdo != null && Zdo.GetInt("nc_rows", 0) > 0)
		{
			text = text + "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] " + Loc.T("hover_bag");
		}
		text = text + "\n<color=#A8A8A8>" + Loc.T("hover_feed") + "</color>";
		return Localization.instance.Localize(text);
	}

	internal void Say(string text)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		if (!string.IsNullOrEmpty(text) && !((Object)(object)Chat.instance == (Object)null) && IsMine && Plugin.Speech.Value)
		{
			float num = ((Def != null && Def.Flying) ? 0.6f : (((Object)(object)Char != (Object)null) ? Mathf.Max(1.2f, Char.GetHeight() * 1.05f) : 1.5f));
			Chat.instance.SetNpcText(((Component)this).gameObject, Vector3.up * num, 30f, 7f, "", "<i>" + text + "</i>", false);
		}
	}
}
public class CompanionAI : BaseAI
{
	private enum Job
	{
		None,
		Chop,
		Mine,
		Forage,
		Harvest,
		Collect,
		Deposit,
		Dig,
		Rest
	}

	private struct Replant
	{
		public Vector3 Pos;

		public string Sapling;

		public string Seed;
	}

	private Companion _c;

	private Humanoid _h;

	private Character _target;

	private ItemData _weapon;

	private float _attackTimer;

	private float _targetTimer;

	private float _tick;

	private float _idleLook;

	private float _stuck;

	private Vector3 _lastPos;

	private Job _job;

	private Component _work;

	private Collider _workCol;

	private Vector3 _workPos;

	private string _workName = "";

	private float _swingTimer;

	private float _hitAt = -1f;

	private float _jobTimer;

	private float _workedFor;

	private float _scanTimer;

	private float _collectUntil;

	private Container _depositTo;

	private readonly List<KeyValuePair<float, Replant>> _replants = new List<KeyValuePair<float, Replant>>();

	private bool _digRequested;

	private static readonly Collider[] Buf = (Collider[])(object)new Collider[256];

	private static int _workMask;

	private static readonly MethodInfo MSetTarget = AccessTools.Method(typeof(MonsterAI), "SetTarget", new Type[1] { typeof(Character) }, (Type[])null);

	private static readonly FieldInfo FTarget = AccessTools.Field(typeof(MonsterAI), "m_targetCreature");

	internal static readonly HashSet<string> Wild = new HashSet<string>
	{
		"RaspberryBush", "BlueberryBush", "CloudberryBush", "Pickable_Mushroom", "Pickable_Mushroom_yellow", "Pickable_Mushroom_blue", "Pickable_Dandelion", "Pickable_Thistle", "Pickable_Fiddlehead", "Pickable_Barley_Wild",
		"Pickable_Flax_Wild", "Pickable_SmokePuff", "Pickable_Mushroom_JotunPuffs", "Pickable_Mushroom_Magecap", "Pickable_Branch", "Pickable_Stone", "Pickable_Flint"
	};

	internal static readonly Dictionary<string, string[]> Crops = new Dictionary<string, string[]>
	{
		{
			"Pickable_Carrot",
			new string[2] { "sapling_carrot", "CarrotSeeds" }
		},
		{
			"Pickable_SeedCarrot",
			new string[2] { "sapling_seedcarrot", "Carrot" }
		},
		{
			"Pickable_Turnip",
			new string[2] { "sapling_turnip", "TurnipSeeds" }
		},
		{
			"Pickable_SeedTurnip",
			new string[2] { "sapling_seedturnip", "Turnip" }
		},
		{
			"Pickable_Onion",
			new string[2] { "sapling_onion", "OnionSeeds" }
		},
		{
			"Pickable_SeedOnion",
			new string[2] { "sapling_seedonion", "Onion" }
		},
		{
			"Pickable_Barley",
			new string[2] { "sapling_barley", "Barley" }
		},
		{
			"Pickable_Flax",
			new string[2] { "sapling_flax", "Flax" }
		}
	};

	private static readonly string[][] Saplings = new string[6][]
	{
		new string[3] { "Beech", "Beech_Sapling", "BeechSeeds" },
		new string[3] { "Birch", "Birch_Sapling", "BirchSeeds" },
		new string[3] { "Oak", "Oak_Sapling", "Acorn" },
		new string[3] { "FirTree", "FirTree_Sapling", "FirCone" },
		new string[3] { "Pinetree", "PineTree_Sapling", "PineCone" },
		new string[3] { "PineTree", "PineTree_Sapling", "PineCone" }
	};

	private static readonly MethodInfo MCheckAccess = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null);

	private Companion C
	{
		get
		{
			if ((Object)(object)_c == (Object)null)
			{
				_c = ((Component)this).GetComponent<Companion>();
			}
			return _c;
		}
	}

	internal bool Busy => (Object)(object)_target != (Object)null;

	private int ChopTier => 1 + C.Rank("t_tier");

	private int PickTier => C.Rank("t_knuckles");

	public override bool UpdateAI(float dt)
	{
		if (!((BaseAI)this).UpdateAI(dt))
		{
			return false;
		}
		if ((Object)(object)_h == (Object)null)
		{
			ref Humanoid h = ref _h;
			Character character = base.m_character;
			h = (Humanoid)(object)((character is Humanoid) ? character : null);
		}
		Companion c = C;
		if ((Object)(object)c == (Object)null || c.Def == null || base.m_character.IsDead())
		{
			return true;
		}
		try
		{
			Think(dt);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Companion AI (" + c.SpeciesId + "): " + ex.Message));
			_job = Job.None;
			_work = null;
		}
		return true;
	}

	internal void RequestDig()
	{
		_digRequested = true;
	}

	private void Think(float dt)
	{
		//IL_00e1: 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_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		Companion c = C;
		Player ownerPlayer = c.OwnerPlayer;
		_attackTimer -= dt;
		_tick -= dt;
		if (_tick <= 0f)
		{
			_tick = 1f;
			Abilities(ownerPlayer);
		}
		ProcessReplants();
		if ((Object)(object)ownerPlayer == (Object)null || ((Character)ownerPlayer).IsDead())
		{
			((BaseAI)this).StopMoving();
			return;
		}
		_targetTimer -= dt;
		if (_targetTimer <= 0f)
		{
			_targetTimer = 0.5f;
			_target = PickTarget(ownerPlayer);
		}
		if ((Object)(object)_target != (Object)null)
		{
			Fight(dt, ownerPlayer);
			return;
		}
		if (_digRequested && c.Def.Id == "boar")
		{
			_digRequested = false;
			StartJob(Job.Dig, null, null, ((Component)this).transform.position);
		}
		switch (c.Mode)
		{
		case Mode.Stay:
			if (c.Def.Id == "boar" && c.Rank("b_keeper") > 0)
			{
				Work(dt, c.StayPoint, 2f);
			}
			else if (_job == Job.Dig || _job == Job.Collect)
			{
				Work(dt, c.StayPoint, 1f);
			}
			else
			{
				StayPut(dt, c.StayPoint);
			}
			break;
		case Mode.Work:
			if (!c.Def.CanWork)
			{
				FollowOwner(dt, ownerPlayer);
			}
			else if (Utils.DistanceXZ(((Component)ownerPlayer).transform.position, ((Component)this).transform.position) > 28f && _job != Job.Deposit)
			{
				CancelJob();
				FollowOwner(dt, ownerPlayer);
			}
			else
			{
				Work(dt, ((Component)ownerPlayer).transform.position, 1f);
			}
			break;
		default:
			if (_job == Job.Dig || _job == Job.Collect)
			{
				Work(dt, ((Component)this).transform.position, 1f);
			}
			else
			{
				FollowOwner(dt, ownerPlayer);
			}
			break;
		}
	}

	private void FollowOwner(float dt, Player owner)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		float num = Utils.DistanceXZ(((Component)owner).transform.position, ((Component)this).transform.position);
		if (num < 3.5f)
		{
			((BaseAI)this).StopMoving();
			_idleLook -= dt;
			if (_idleLook <= 0f)
			{
				_idleLook = Random.Range(3f, 8f);
				((BaseAI)this).LookAt(((Character)owner).GetHeadPoint());
			}
			_stuck = 0f;
			return;
		}
		((BaseAI)this).Follow(((Component)owner).gameObject, dt);
		Vector3 val = ((Component)this).transform.position - _lastPos;
		if (((Vector3)(ref val)).sqrMagnitude < 0.04f && num > 10f)
		{
			_stuck += dt;
		}
		else
		{
			_stuck = 0f;
		}
		_lastPos = ((Component)this).transform.position;
		if (_stuck > 6f)
		{
			_stuck = 0f;
			Manager.WarpNear(C, owner);
		}
	}

	private void StayPut(float dt, Vector3 at)
	{
		//IL_0000: 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_0026: 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)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		if (Utils.DistanceXZ(at, ((Component)this).transform.position) > 2f)
		{
			base.m_character.SetWalk(true);
			((BaseAI)this).MoveTo(dt, at, 1f, false);
			return;
		}
		((BaseAI)this).StopMoving();
		_idleLook -= dt;
		if (_idleLook <= 0f)
		{
			_idleLook = Random.Range(4f, 10f);
			((BaseAI)this).LookTowards(Quaternion.Euler(0f, Random.Range(0f, 360f), 0f) * Vector3.forward);
		}
	}

	private Character PickTarget(Player owner)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: 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_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Invalid comparison between Unknown and I4
		Companion c = C;
		Vector3 val = ((c.Mode == Mode.Stay) ? c.StayPoint : ((Component)owner).transform.position);
		float num = ((c.Mode != Mode.Stay) ? 20f : ((c.Rank("t_guardian") > 0) ? 20f : 12f));
		if ((Object)(object)_target != (Object)null && !_target.IsDead())
		{
			Vector3 val2 = ((Component)_target).transform.position - val;
			if (((Vector3)(ref val2)).sqrMagnitude < (num + 12f) * (num + 12f))
			{
				return _target;
			}
		}
		Character val3 = null;
		float num2 = float.MaxValue;
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if ((Object)(object)allCharacter == (Object)null || allCharacter.IsDead() || (Object)(object)allCharacter == (Object)(object)base.m_character || allCharacter.IsPlayer() || (Object)(object)((Component)allCharacter).GetComponent<Companion>() != (Object)null || !BaseAI.IsEnemy(base.m_character, allCharacter))
			{
				continue;
			}
			Vector3 val4 = ((Component)allCharacter).transform.position - val;
			float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude;
			if (sqrMagnitude > num * num)
			{
				continue;
			}
			BaseAI baseAI = allCharacter.GetBaseAI();
			Character val5 = (((Object)(object)baseAI != (Object)null) ? baseAI.GetTargetCreature() : null);
			bool flag = (Object)(object)val5 == (Object)(object)owner || (Object)(object)val5 == (Object)(object)base.m_character || ((Object)(object)baseAI != (Object)null && baseAI.IsAlerted() && sqrMagnitude < 64f);
			if (((int)allCharacter.GetFaction() != 1 || !((Object)(object)val5 != (Object)(object)owner) || !((Object)(object)val5 != (Object)(object)base.m_character)) && (flag || (c.Mode == Mode.Follow && !(sqrMagnitude > 100f))))
			{
				float num3 = sqrMagnitude - (((Object)(object)val5 == (Object)(object)owner) ? 400f : 0f) - (((Object)(object)val5 == (Object)(object)base.m_character) ? 200f : 0f);
				if (num3 < num2)
				{
					num2 = num3;
					val3 = allCharacter;
				}
			}
		}
		if ((Object)(object)val3 != (Object)null && (Object)(object)val3 != (Object)(object)_target)
		{
			CancelJob();
			if (c.IsMine)
			{
				Manager.OnCombatStart(c, val3);
			}
		}
		return val3;
	}

	private void Fight(float dt, Player owner)
	{
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		Companion c = C;
		c.LastCombat = Time.time;
		c.LastTarget = _target;
		if ((Object)(object)_h == (Object)null)
		{
			_target = null;
			return;
		}
		if (_weapon == null || !_h.GetInventory().ContainsItem(_weapon) || _attackTimer < -6f)
		{
			_weapon = SelectWeapon();
		}
		if (_weapon == null)
		{
			((BaseAI)this).Follow(((Component)owner).gameObject, dt);
			return;
		}
		if (_h.GetCurrentWeapon() != _weapon)
		{
			_h.EquipItem(_weapon, true);
		}
		float num = Mathf.Max(1.2f, _weapon.m_shared.m_aiAttackRange * Mathf.Max(0.6f, ((Component)this).transform.localScale.y));
		Vector3 position = ((Component)_target).transform.position;
		float num2 = Vector3.Distance(((Component)this).transform.position, position);
		if (num2 > num)
		{
			((BaseAI)this).MoveTo(dt, position, num * 0.8f, true);
			return;
		}
		((BaseAI)this).StopMoving();
		((BaseAI)this).LookAt(_target.GetCenterPoint());
		float num3 = ((_weapon.m_shared.m_aiAttackMaxAngle > 0f) ? _weapon.m_shared.m_aiAttackMaxAngle : 25f);
		if (_attackTimer <= 0f && !base.m_character.InAttack() && ((BaseAI)this).IsLookingAt(_target.GetCenterPoint(), num3, false))
		{
			if (((Character)_h).StartAttack(_target, false))
			{
				_attackTimer = Mathf.Max(1.1f, _weapon.m_shared.m_aiAttackInterval);
			}
			else
			{
				_attackTimer = 0.4f;
			}
		}
	}

	private ItemData SelectWeapon()
	{
		List<ItemData> list = new List<ItemData>();
		foreach (ItemData allItem in _h.GetInventory().GetAllItems())
		{
			if (allItem != null && allItem.m_shared != null && !(allItem.m_shared.m_aiAttackRange <= 0f) && string.IsNullOrEmpty(allItem.m_shared.m_ammoType) && ((BaseAI)this).CanUseAttack(allItem))
			{
				list.Add(allItem);
			}
		}
		if (list.Count == 0)
		{
			return null;
		}
		list.Sort((ItemData a, ItemData b) => a.m_shared.m_aiAttackRange.CompareTo(b.m_shared.m_aiAttackRange));
		if (!(Random.value < 0.75f))
		{
			return list[Random.Range(0, list.Count)];
		}
		return list[0];
	}

	private void Abilities(Player owner)
	{
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Invalid comparison between Unknown and I4
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_0279: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_041c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0421: Unknown result type (might be due to invalid IL or missing references)
		//IL_042b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0430: Unknown result type (might be due to invalid IL or missing references)
		//IL_0444: Unknown result type (might be due to invalid IL or missing references)
		//IL_0318: Unknown result type (might be due to invalid IL or missing references)
		//IL_0323: 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_032d: Unknown result type (might be due to invalid IL or missing references)
		Companion c = C;
		float time = Time.time;
		c.RefreshSpeed();
		float maxHealth = base.m_character.GetMaxHealth();
		bool flag = time - c.LastCombat > 8f && time - c.LastHurt > 8f;
		float num = 0f;
		if (flag)
		{
			num += c.Val("w_lick");
		}
		num += c.Val("t_regen");
		if (c.Rank("b_mud") > 0 && (EnvMan.IsWet() || (int)Heightmap.FindBiome(((Component)this).transform.position) == 2))
		{
			num += 0.002f * (float)c.Rank("b_mud");
		}
		if (flag)
		{
			num += 0.004f;
		}
		if (num > 0f && base.m_character.GetHealth() < maxHealth)
		{
			base.m_character.Heal(maxHealth * num, false);
		}
		if ((Object)(object)owner == (Object)null)
		{
			return;
		}
		if (c.Rank("w_rescue") > 0 && ((Character)owner).GetHealth() < ((Character)owner).GetMaxHealth() * 0.35f && time > c.BuffUntil + 20f)
		{
			c.BuffUntil = time + 10f;
			Character val = AttackerOf((Character)(object)owner, 15f);
			if ((Object)(object)val != (Object)null)
			{
				_target = val;
			}
			if (c.IsMine)
			{
				Manager.Line(c, "rescue");
			}
		}
		if (c.Rank("w_taunt") > 0)
		{
			c.TauntTimer -= 1f;
			if (c.TauntTimer <= 0f)
			{
				int num2 = TauntAround(((Component)owner).transform.position, 8f, onlyOwnerAttackers: true);
				c.TauntTimer = ((num2 > 0) ? c.Val("w_taunt") : 2f);
			}
		}
		if (c.Rank("l_stomp") > 0 && time > c.StompReady && CountEnemies(((Component)this).transform.position, 5f) >= 2)
		{
			c.StompReady = time + 20f;
			Stomp(c.Val("l_stomp") * Species.DamageMult(c.Level) * Plugin.DamageMultiplier.Value);
		}
		if (c.Rank("l_bulwark") > 0 && time > c.BulwarkReady && (Object)(object)AttackerOf((Character)(object)owner, 10f) != (Object)null)
		{
			c.BulwarkReady = time + c.Val("l_bulwark");
			c.BulwarkUntil = time + 6f;
			TauntAround(((Component)this).transform.position, 10f, onlyOwnerAttackers: false);
			Visuals.Burst(((Component)this).transform.position + Vector3.up, new Color(0.9f, 0.8f, 0.5f), 30);
			if (c.IsMine)
			{
				Manager.Line(c, "bulwark");
			}
		}
		if (c.Rank("l_calm") > 0)
		{
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if ((Object)(object)allCharacter == (Object)null || allCharacter.IsDead())
				{
					continue;
				}
				Vector3 val2 = ((Component)allCharacter).transform.position - ((Component)this).transform.position;
				if (!(((Vector3)(ref val2)).sqrMagnitude > 400f))
				{
					BaseAI baseAI = allCharacter.GetBaseAI();
					MonsterAI val3 = (MonsterAI)(object)((baseAI is MonsterAI) ? baseAI : null);
					if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((BaseAI)val3).GetTargetCreature() != (Object)(object)base.m_character) && OwnsObject((Component)(object)allCharacter) && Random.value < c.Val("l_calm") * 0.5f)
					{
						Retarget(val3, (Character)(object)((((Character)owner).GetHealth() > ((Character)owner).GetMaxHealth() * 0.5f) ? owner : null));
					}
				}
			}
		}
		if (c.Rank("b_frenzy") > 0 && time > c.FrenzyReady && base.m_character.GetHealth() < maxHealth * 0.3f)
		{
			c.FrenzyReady = time + c.Val("b_frenzy");
			c.FrenzyUntil = time + 10f;
			Visuals.Burst(((Component)this).transform.position + Vector3.up * 0.6f, new Color(1f, 0.3f, 0.2f), 25);
			if (c.IsMine)
			{
				Manager.Line(c, "frenzy");
			}
		}
	}

	private Character AttackerOf(Character victim, float range)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if ((Object)(object)allCharacter == (Object)null || allCharacter.IsDead() || allCharacter.IsPlayer())
			{
				continue;
			}
			Vector3 val = ((Component)allCharacter).transform.position - ((Component)victim).transform.position;
			if (!(((Vector3)(ref val)).sqrMagnitude > range * range))
			{
				BaseAI baseAI = allCharacter.GetBaseAI();
				if ((Object)(object)baseAI != (Object)null && (Object)(object)baseAI.GetTargetCreature() == (Object)(object)victim && BaseAI.IsEnemy(base.m_character, allCharacter))
				{
					return allCharacter;
				}
			}
		}
		return null;
	}

	private int CountEnemies(Vector3 at, float r)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: 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)
		int num = 0;
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if ((Object)(object)allCharacter != (Object)null && !allCharacter.IsDead() && !allCharacter.IsPlayer())
			{
				Vector3 val = ((Component)allCharacter).transform.position - at;
				if (((Vector3)(ref val)).sqrMagnitude <= r * r && BaseAI.IsEnemy(base.m_character, allCharacter))
				{
					num++;
				}
			}
		}
		return num;
	}

	private int TauntAround(Vector3 at, float r, bool onlyOwnerAttackers)
	{
		//IL_0057: 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_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		Player ownerPlayer = C.OwnerPlayer;
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if ((Object)(object)allCharacter == (Object)null || allCharacter.IsDead() || allCharacter.IsPlayer() || allCharacter.IsBoss())
			{
				continue;
			}
			Vector3 val = ((Component)allCharacter).transform.position - at;
			if (!(((Vector3)(ref val)).sqrMagnitude > r * r))
			{
				BaseAI baseAI = allCharacter.GetBaseAI();
				MonsterAI val2 = (MonsterAI)(object)((baseAI is MonsterAI) ? baseAI : null);
				if (!((Object)(object)val2 == (Object)null) && BaseAI.IsEnemy(base.m_character, allCharacter) && OwnsObject((Component)(object)allCharacter) && (!onlyOwnerAttackers || !((Object)(object)((BaseAI)val2).GetTargetCreature() != (Object)(object)ownerPlayer)) && !((Object)(object)((BaseAI)val2).GetTargetCreature() == (Object)(object)base.m_character))
				{
					Retarget(val2, base.m_character);
					num++;
				}
			}
		}
		return num;
	}

	private static bool OwnsObject(Component x)
	{
		ZNetView component = x.GetComponent<ZNetView>();
		if ((Object)(object)component != (Object)null && component.IsValid())
		{
			return component.IsOwner();
		}
		return false;
	}

	internal static void Retarget(MonsterAI mai, Character to)
	{
		try
		{
			if ((Object)(object)to != (Object)null && MSetTarget != null)
			{
				MSetTarget.Invoke(mai, new object[1] { to });
			}
			else if (FTarget != null)
			{
				FTarget.SetValue(mai, null);
			}
		}
		catch
		{
		}
	}

	private void Stomp(float dmg)
	{
		//IL_0105: 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_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: 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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected O, but got Unknown
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: 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)
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsDead() && !allCharacter.IsPlayer())
			{
				Vector3 val = ((Component)allCharacter).transform.position - ((Component)this).transform.position;
				if (!(((Vector3)(ref val)).sqrMagnitude > 25f) && BaseAI.IsEnemy(base.m_character, allCharacter))
				{
					HitData val2 = new HitData();
					val2.m_damage.m_blunt = dmg;
					val2.m_pushForce = 80f;
					val2.m_staggerMultiplier = 2f;
					val2.m_point = allCharacter.GetCenterPoint();
					Vector3 val3 = ((Component)allCharacter).transform.position - ((Component)this).transform.position;
					val2.m_dir = ((Vector3)(ref val3)).normalized;
					val2.SetAttacker(base.m_character);
					allCharacter.Damage(val2);
				}
			}
		}
		Visuals.Burst(((Component)this).transform.position + Vector3.up * 0.2f, new Color(0.7f, 0.6f, 0.45f), 40);
		if ((Object)(object)base.m_animator != (Object)null && (Object)(object)_h != (Object)null && _h.GetCurrentWeapon() != null && _h.GetCurrentWeapon().m_shared.m_attack != null)
		{
			base.m_animator.SetTrigger(_h.GetCurrentWeapon().m_shared.m_attack.m_attackAnimation);
		}
	}

	private void CancelJob()
	{
		_job = Job.None;
		_work = null;
		_workCol = null;
		_hitAt = -1f;
		_depositTo = null;
	}

	private void StartJob(Job j, Component work, Collider col, Vector3 pos)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		_job = j;
		_work = work;
		_workCol = col;
		_workPos = pos;
		_workName = (((Object)(object)work != (Object)null) ? Utils.GetPrefabName(work.gameObject) : "");
		_jobTimer = 0f;
		_hitAt = -1f;
		_swingTimer = 0.3f;
	}

	private void Work(float dt, Vector3 anchor, float radiusMult)
	{
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: 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_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02af: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_032f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0330: Unknown result type (might be due to invalid IL or missing references)
		Companion c = C;
		_jobTimer += dt;
		_swingTimer -= dt;
		if (_hitAt > 0f && Time.time >= _hitAt)
		{
			_hitAt = -1f;
			ApplyWorkHit();
		}
		switch (_job)
		{
		case Job.Rest:
			((BaseAI)this).StopMoving();
			if (_jobTimer > 15f)
			{
				CancelJob();
				_workedFor = 0f;
			}
			return;
		case Job.Dig:
			DoDig(dt);
			return;
		case Job.Collect:
			DoCollect(dt);
			return;
		case Job.Deposit:
			DoDeposit(dt);
			return;
		}
		if (_job != Job.None && ((Object)(object)_work == (Object)null || !_work.gameObject.activeInHierarchy))
		{
			OnWorkDone();
			return;
		}
		if (_job != Job.None && _jobTimer > 25f)
		{
			CancelJob();
			_scanTimer = 2f;
			return;
		}
		if (_job == Job.None)
		{
			if (c.Def.Id == "troll" && c.Rank("t_tireless") == 0 && _workedFor > 60f)
			{
				StartJob(Job.Rest, null, null, ((Component)this).transform.position);
				if (c.IsMine)
				{
					Manager.Line(c, "rest");
				}
				return;
			}
			if (c.Def.Id == "boar" && BagFull() && c.Rank("b_pantry") > 0)
			{
				Container val = FindChest(c.Val("b_pantry"));
				if ((Object)(object)val != (Object)null)
				{
					_depositTo = val;
					StartJob(Job.Deposit, (Component)(object)val, null, ((Component)val).transform.position);
					return;
				}
			}
			_scanTimer -= dt;
			if (_scanTimer > 0f)
			{
				IdleNear(dt, anchor);
				return;
			}
			_scanTimer = 1.5f;
			if (!FindWork(anchor, radiusMult))
			{
				IdleNear(dt, anchor);
				return;
			}
		}
		_workedFor += dt;
		Vector3 val2 = (((Object)(object)_workCol != (Object)null) ? _workCol.ClosestPoint(((Component)this).transform.position) : _work.transform.position);
		float num = ((c.Def.Id == "troll") ? 1.4f : 0.9f);
		if (Utils.DistanceXZ(val2, ((Component)this).transform.position) > num + 0.4f)
		{
			((BaseAI)this).MoveTo(dt, val2, num, false);
			return;
		}
		((BaseAI)this).StopMoving();
		((BaseAI)this).LookAt(val2 + Vector3.up * 0.8f);
		if (_swingTimer <= 0f && _hitAt < 0f)
		{
			float num2 = 1f + c.Val("t_tireless");
			_swingTimer = ((c.Def.Id == "troll") ? 2.4f : 1.6f) / num2;
			PlayWorkAnim();
			_hitAt = Time.time + 0.55f;
			_workPos = val2;
		}
	}

	private void IdleNear(float dt, Vector3 anchor)
	{
		//IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references)
		if (Utils.DistanceXZ(anchor, ((Component)this).transform.position) > 6f)
		{
			((BaseAI)this).MoveTo(dt, anchor, 3f, false);
		}
		else
		{
			((BaseAI)this).StopMoving();
		}
	}

	private void PlayWorkAnim()
	{
		if ((Object)(object)base.m_animator == (Object)null)
		{
			return;
		}
		if (C.Def.Id == "boar")
		{
			base.m_animator.SetTrigger("consume");
			return;
		}
		ItemData val = (((Object)(object)_h != (Object)null) ? (_h.GetCurrentWeapon() ?? SelectWeapon()) : null);
		if (val != null && val.m_shared.m_attack != null && !string.IsNullOrEmpty(val.m_shared.m_attack.m_attackAnimation))
		{
			base.m_animator.SetTrigger(val.m_shared.m_attack.m_attackAnimation);
		}
	}

	private bool FindWork(Vector3 anchor, float radiusMult)
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		Companion c = C;
		if (_workMask == 0)
		{
			_workMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "item" });
		}
		if (c.Def.Id == "troll")
		{
			return FindTrollWork(anchor, 20f * radiusMult);
		}
		if (c.Def.Id == "boar")
		{
			float forage = ((c.Rank("b_forage") > 0) ? c.Val("b_forage") : 10f) * radiusMult;
			float harvest = ((c.Rank("b_harvest") > 0) ? (c.Val("b_harvest") * radiusMult) : 0f);
			return FindBoarWork(anchor, forage, harvest);
		}
		return false;
	}

	private bool FindTrollWork(Vector3 anchor, float radius)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0266: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: 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_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: 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_0223: 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_017a: Invalid comparison between Unknown and I4
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Invalid comparison between Unknown and I4
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Invalid comparison between Unknown and I4
		int num = C.Rank("t_split");
		int num2 = Physics.OverlapSphereNonAlloc(anchor, radius, Buf, _workMask);
		Component val = null;
		Collider col = null;
		Job j = Job.None;
		float num3 = float.MaxValue;
		for (int i = 0; i < num2; i++)
		{
			Collider val2 = Buf[i];
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			Component val3 = null;
			Job job = Job.None;
			TreeBase componentInParent = ((Component)val2).GetComponentInParent<TreeBase>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				if (componentInParent.m_minToolTier <= ChopTier)
				{
					val3 = (Component)(object)componentInParent;
					job = Job.Chop;
				}
			}
			else
			{
				TreeLog componentInParent2 = ((Component)val2).GetComponentInParent<TreeLog>();
				if ((Object)(object)componentInParent2 != (Object)null)
				{
					bool flag = (Object)(object)componentInParent2.m_subLogPrefab == (Object)null;
					if (num >= ((!flag) ? 1 : 2) && componentInParent2.m_minToolTier <= ChopTier)
					{
						val3 = (Component)(object)componentInParent2;
						job = Job.Chop;
					}
				}
				else
				{
					MineRock5 componentInParent3 = ((Component)val2).GetComponentInParent<MineRock5>();
					if ((Object)(object)componentInParent3 != (Object)null)
					{
						if (componentInParent3.m_minToolTier <= PickTier)
						{
							val3 = (Component)(object)componentInParent3;
							job = Job.Mine;
						}
					}
					else
					{
						MineRock componentInParent4 = ((Component)val2).GetComponentInParent<MineRock>();
						if ((Object)(object)componentInParent4 != (Object)null)
						{
							if (componentInParent4.m_minToolTier <= PickTier)
							{
								val3 = (Component)(object)componentInParent4;
								job = Job.Mine;
							}
						}
						else
						{
							Destructible componentInParent5 = ((Component)val2).GetComponentInParent<Destructible>();
							if ((Object)(object)componentInParent5 != (Object)null && (Object)(object)((Component)componentInParent5).GetComponent<Piece>() == (Object)null)
							{
								string text = ((Object)((Component)componentInParent5).gameObject).name.ToLowerInvariant();
								if ((int)componentInParent5.m_destructibleType == 2 && text.Contains("stub") && num >= 3 && componentInParent5.m_minToolTier <= ChopTier)
								{
									val3 = (Component)(object)componentInParent5;
									job = Job.Chop;
								}
								else if ((int)componentInParent5.m_destructibleType == 1 && text.Contains("rock") && componentInParent5.m_minToolTier <= PickTier && (int)componentInParent5.m_damages.m_pickaxe != 3)
								{
									val3 = (Component)(object)componentInParent5;
									job = Job.Mine;
								}
							}
						}
					}
				}
			}
			if ((Object)(object)val3 == (Object)null)
			{
				continue;
			}
			Vector3 val4 = val2.ClosestPoint(((Component)this).transform.position);
			if (PrivateArea.CheckAccess(val4, 0f, false, false))
			{
				Vector3 val5 = val4 - ((Component)this).transform.position;
				float sqrMagnitude = ((Vector3)(ref val5)).sqrMagnitude;
				if (sqrMagnitude < num3)
				{
					num3 = sqrMagnitude;
					val = val3;
					col = val2;
					j = job;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		StartJob(j, val, col, val.transform.position);
		return true;
	}

	private bool FindBoarWork(Vector3 anchor, float forage, float harvest)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Max(forage, harvest);
		int num2 = Physics.OverlapSphereNonAlloc(anchor, num, Buf, _workMask);
		Pickable val = null;
		Job j = Job.None;
		float num3 = float.MaxValue;
		for (int i = 0; i < num2; i++)
		{
			Collider val2 = Buf[i];
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			Pickable componentInParent = ((Component)val2).GetComponentInParent<Pickable>();
			if ((Object)(object)componentInParent == (Object)null || !componentInParent.CanBePicked())
			{
				continue;
			}
			string prefabName = Utils.GetPrefabName(((Component)componentInParent).gameObject);
			float num4 = Utils.DistanceXZ(((Component)componentInParent).transform.position, anchor);
			Job job = Job.None;
			if (Wild.Contains(prefabName) && num4 <= forage)
			{
				job = Job.Forage;
			}
			else if (Crops.ContainsKey(prefabName) && num4 <= harvest)
			{
				job = Job.Harvest;
			}
			if (job != Job.None && PrivateArea.CheckAccess(((Component)componentInParent).transform.position, 0f, false, false))
			{
				Vector3 val3 = ((Component)componentInParent).transform.position - ((Component)this).transform.position;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				if (sqrMagnitude < num3)
				{
					num3 = sqrMagnitude;
					val = componentInParent;
					j = job;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		StartJob(j, (Component)(object)val, null, ((Component)val).transform.position);
		return true;
	}

	private void ApplyWorkHit()
	{
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Expected O, but got Unknown
		//IL_021c: 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_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_0234: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		Companion c = C;
		if ((Object)(object)_work == (Object)null)
		{
			return;
		}
		if (_job == Job.Forage || _job == Job.Harvest)
		{
			Component work = _work;
			Pickable val = (Pickable)(object)((work is Pickable) ? work : null);
			if ((Object)(object)val == (Object)null || !val.CanBePicked())
			{
				CancelJob();
				return;
			}
			ZNetView component = ((Component)val).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				CancelJob();
				return;
			}
			string prefabName = Utils.GetPrefabName(((Component)val).gameObject);
			component.InvokeRPC("RPC_Pick", new object[1] { 0 });
			if (_job == Job.Harvest && c.Rank("b_replant") > 0 && Random.value < c.Val("b_replant") + 0.001f && Crops.TryGetValue(prefabName, out var value))
			{
				_replants.Add(new KeyValuePair<float, Replant>(Time.time + 1.5f, new Replant
				{
					Pos = ((Component)val).transform.position,
					Sapling = value[0],
					Seed = value[1]
				}));
			}
			if (c.IsMine)
			{
				Manager.AddXp(c, (_job == Job.Harvest) ? 6f : 8f, "gather");
			}
			_collectUntil = Time.time + 2.5f;
			StartJob(Job.Collect, null, null, ((Component)val).transform.position);
			return;
		}
		Component work2 = _work;
		IDestructible val2 = (IDestructible)(object)((work2 is IDestructible) ? work2 : null);
		if (val2 == null)
		{
			CancelJob();
			return;
		}
		HitData val3 = new HitData();
		float num = 22f * Species.DamageMult(c.Level) * Plugin.WorkMultiplier.Value;
		if (_job == Job.Chop)
		{
			val3.m_damage.m_chop = num * (1f + c.Val("t_axe"));
			val3.m_toolTier = (short)ChopTier;
		}
		else
		{
			val3.m_damage.m_pickaxe = num * (1f + c.Val("t_pick"));
			val3.m_toolTier = (short)PickTier;
		}
		val3.m_point = _workPos;
		Vector3 val4 = _workPos - ((Component)this).transform.position;
		val3.m_dir = ((Vector3)(ref val4)).normalized;
		val3.m_hitCollider = _workCol;
		val3.SetAttacker(base.m_character);
		val2.Damage(val3);
		if (c.IsMine)
		{
			Manager.AddXp(c, 3f, "gather");
		}
	}

	private void OnWorkDone()
	{
		//IL_0016: 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_0189: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		Companion c = C;
		Job job = _job;
		string workName = _workName;
		Vector3 workPos = _workPos;
		CancelJob();
		if (job != Job.Chop && job != Job.Mine)
		{
			return;
		}
		if (c.IsMine)
		{
			Manager.AddXp(c, 20f, "gather");
		}
		if (c.IsMine && Random.value < 0.25f)
		{
			Manager.Line(c, (job == Job.Chop) ? "chopped" : "mined");
		}
		if (job == Job.Chop && c.Rank("t_sapling") > 0 && !workName.ToLowerInvariant().Contains("log") && !workName.ToLowerInvariant().Contains("stub"))
		{
			string[][] saplings = Saplings;
			foreach (string[] array in saplings)
			{
				if (workName.StartsWith(array[0], StringComparison.OrdinalIgnoreCase))
				{
					Vector3 pos = workPos + Quaternion.Euler(0f, Random.Range(0f, 360f), 0f) * Vector3.forward * 2.2f;
					_replants.Add(new KeyValuePair<float, Replant>(Time.time + 4f, new Replant
					{
						Pos = pos,
						Sapling = array[1],
						Seed = array[2]
					}));
					break;
				}
			}
		}
		if (c.Rank("t_haul") > 0)
		{
			_collectUntil = Time.time + 6f;
			StartJob(Job.Collect, null, null, workPos);
		}
	}

	private bool BagFull()
	{
		Container bag = C.Bag;
		if ((Object)(object)bag != (Object)null && C.Zdo != null && C.Zdo.GetInt("nc_rows", 0) > 0)
		{
			return !bag.GetInventory().HaveEmptySlot();
		}
		return false;
	}

	private void DoCollect(float dt)
	{
		//IL_005a: 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_0151: 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_00f4: 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_0104: 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)
		Companion c = C;
		if (Time.time > _collectUntil || (Object)(object)c.Bag == (Object)null || c.Zdo == null || c.Zdo.GetInt("nc_rows", 0) <= 0)
		{
			CancelJob();
			return;
		}
		Inventory inventory = c.Bag.GetInventory();
		ItemDrop val = null;
		float num = 64f;
		Collider[] array = Physics.OverlapSphere(_workPos, 8f, LayerMask.GetMask(new string[1] { "item" }));
		foreach (Collider val2 in array)
		{
			ItemDrop componentInParent = ((Component)val2).GetComponentInParent<ItemDrop>();
			if (!((Object)(object)componentInParent == (Object)null) && componentInParent.m_itemData != null && componentInParent.CanPickup(false) && inventory.CanAddItem(componentInParent.m_itemData, -1) && (!(c.Def.Id == "troll") || IsHaul(componentInParent.m_itemData)))
			{
				Vector3 val3 = ((Component)componentInParent).transform.position - ((Component)this).transform.position;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					val = componentInParent;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			((BaseAI)this).StopMoving();
			return;
		}
		if (Vector3.Distance(((Component)val).transform.position, ((Component)this).transform.position) > 1.6f)
		{
			((BaseAI)this).MoveTo(dt, ((Component)val).transform.position, 1f, false);
			return;
		}
		ZNetView component = ((Component)val).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return;
		}
		if (!component.IsOwner())
		{
			component.ClaimOwnership();
			return;
		}
		ItemData val4 = val.m_itemData.Clone();
		if (inventory.AddItem(val4))
		{
			ZNetScene.instance.Destroy(((Component)val).gameObject);
		}
	}

	private static bool IsHaul(ItemData it)
	{
		string text = (((Object)(object)it.m_dropPrefab != (Object)null) ? ((Object)it.m_dropPrefab).name : "");
		if (!text.Contains("Wood") && !(text == "RoundLog") && !(text == "Stone") && !text.EndsWith("Ore") && !text.EndsWith("Scrap") && !(text == "Flint") && !(text == "Resin") && !text.EndsWith("Seeds"))
		{
			switch (text)
			{
			default:
				return text == "BlackMarble";
			case "PineCone":
			case "FirCone":
			case "Acorn":
			case "Obsidian":
			case "Grausten":
				break;
			}
		}
		return true;
	}

	private Container FindChest(float radius)
	{
		//IL_0037: 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_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_0114: Unknown result type (might be due to invalid IL or missing references)
		Companion c = C;
		Inventory val = (((Object)(object)c.Bag != (Object)null) ? c.Bag.GetInventory() : null);
		if (val == null)
		{
			return null;
		}
		Container result = null;
		float num = float.MaxValue;
		Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, radius, LayerMask.GetMask(new string[3] { "piece", "piece_nonsolid", "Default" }));
		foreach (Collider val2 in array)
		{
			Container componentInParent = ((Component)val2).GetComponentInParent<Container>();
			if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent == (Object)(object)c.Bag || (Object)(object)((Component)componentInParent).GetComponent<Piece>() == (Object)null || (Object)(object)((Component)componentInParent).GetComponent<Companion>() != (Object)null || componentInParent.IsInUse() || !componentInParent.GetInventory().HaveEmptySlot() || !CanAccess(componentInParent, c.OwnerId))
			{
				continue;
			}
			Vector3 val3 = ((Component)componentInParent).transform.position - ((Component)this).transform.position;
			float num2 = ((Vector3)(ref val3)).sqrMagnitude;
			foreach (ItemData allItem in val.GetAllItems())
			{
				if (componentInParent.GetInventory().ContainsItemByName(allItem.m_shared.m_name))
				{
					num2 -= 1000f;
					break;
				}
			}
			if (num2 < num)
			{
				num = num2;
				result = componentInParent;
			}
		}
		return result;
	}

	internal static bool CanAccess(Container ct, long pid)
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (MCheckAccess != null && !(bool)MCheckAccess.Invoke(ct, new object[1] { pid }))
			{
				return false;
			}
		}
		catch
		{
			return false;
		}
		return PrivateArea.CheckAccess(((Component)ct).transform.position, 0f, false, false);
	}

	private void DoDeposit(float dt)
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		Container depositTo = _depositTo;
		Companion c = C;
		if ((Object)(object)depositTo == (Object)null || (Object)(object)c.Bag == (Object)null || _jobTimer > 30f)
		{
			CancelJob();
			return;
		}
		if (Vector3.Distance(((Component)depositTo).transform.position, ((Component)this).transform.position) > 2.2f)
		{
			((BaseAI)this).MoveTo(dt, ((Component)depositTo).transform.position, 1.6f, false);
			return;
		}
		((BaseAI)this).StopMoving();
		ZNetView component = ((Component)depositTo).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid() || depositTo.IsInUse())
		{
			CancelJob();
			return;
		}
		if (!component.IsOwner())
		{
			component.ClaimOwnership();
			return;
		}
		int num = Manager.Transfer(c.Bag.GetInventory(), depositTo.GetInventory());
		if (num > 0 && c.IsMine)
		{
			Manager.Line(c, "pantry");
		}
		CancelJob();
	}

	private void DoDig(float dt)
	{
		((BaseAI)this).StopMoving();
		if (_jobTimer < 0.1f && (Object)(object)base.m_animator != (Object)null)
		{
			base.m_animator.SetTrigger("consume");
		}
		if (_jobTimer > 2.2f)
		{
			CancelJob();
			if (C.IsMine)
			{
				Manager.CompleteDig(C);
			}
		}
	}

	private void ProcessReplants()
	{
		if (_replants.Count == 0)
		{
			return;
		}
		for (int num = _replants.Count - 1; num >= 0; num--)
		{
			if (!(Time.time < _replants[num].Key))
			{
				Replant value = _replants[num].Value;
				_replants.RemoveAt(num);
				TryPlant(value);
			}
		}
	}

	private void TryPlant(Replant r)
	{
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		Companion c = C;
		if ((Object)(object)c.Bag == (Object)null || (Object)(object)ZNetScene.instance == (Object)null)
		{
			return;
		}
		GameObject prefab = ZNetScene.instance.GetPrefab(r.Sapling);
		if ((Object)(object)prefab == (Object)null)
		{
			return;
		}
		Inventory inventory = c.Bag.GetInventory();
		ItemData val = null;
		foreach (ItemData allItem in inventory.GetAllItems())
		{
			if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == r.Seed)
			{
				val = allItem;
				break;
			}
		}
		if (val == null)
		{
			return;
		}
		Collider[] array = Physics.OverlapSphere(r.Pos, 0.6f, LayerMask.GetMask(new string[4] { "Default", "piece", "piece_nonsolid", "Default_small" }));
		foreach (Collider val2 in array)
		{
			if ((Object)(object)((Component)val2).GetComponentInParent<Plant>() != (Object)null || (Object)(object)((Component)val2).GetComponentInParent<Pickable>() != (Object)null)
			{
				return;
			}
		}
		Vector3 pos = r.Pos;
		float y = default(float);
		if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(pos, ref y))
		{
			pos.y = y;
		}
		inventory.RemoveItem(val, 1);
		Object.Instantiate<GameObject>(prefab, pos, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
		if (c.IsMine)
		{
			Manager.AddXp(c, 4f, "gather");
		}
	}
}
internal static class CompanionUI
{
	private const float W = 1040f;

	private const float H = 700f;

	public static bool IsOpen;

	public static int OpenedFrame;

	public static int ClosedFrame = -10;

	private static GameObject _root;

	private static Lair _lair;

	private static int _tab;

	private static string _selTalent = "";

	private static float _refresh;

	private static float _statusUntil;

	private static Text _title;

	private static Text _subtitle;

	private static Text _status;

	private static readonly List<Button> Tabs = new List<Button>();

	private static readonly List<GameObject> Pages = new List<GameObject>();

	private static Text _name;

	private static Text _species;

	private static Text _levelTxt;

	private static Text _xpTxt;

	private static Text _bondTxt;

	private static Text _stats;

	private static Text _lairHint;

	private static Text _ritualTxt;

	private static Text _reviveTxt;

	private static Text _empty;

	private static Image _xpFill;

	private static Image _bondFill;

	private static InputField _nameField;

	private static InputField _playerField;

	private static Button _skinBtn;

	private static Button _bagBtn;

	private static Button _feedBtn;

	private static Button _sendLairBtn;

	private static Button _sendPlayerBtn;

	private static Button _ritualBtn;

	private static Button _reviveBtn;

	private static Button _mailBtn;

	private static Button _unloadBtn;

	private static readonly List<Button> ModeBtns = new List<Button>();

	private static GameObject _ravenGroup;

	private static GameObject _companionGroup;

	private static readonly List<KeyValuePair<string, Button>> TalentBtns = new List<KeyValuePair<string, Button>>();

	private static readonly List<Text> BranchTitles = new List<Text>();

	private static Text _talentInfo;

	private static Text _pointsTxt;

	private static Text _talentEmpty;

	private static Button _raiseBtn;

	private static Button _respecBtn;

	private static GameObject _talentGroup;

	private static readonly List<Text> HerdTexts = new List<Text>();

	private static readonly List<Button> HerdBtns = new List<Button>();

	private static readonly List<Image> HerdBgs = new List<Image>();

	private static bool AtLair
	{
		get
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)_lair != (Object)null && (Object)(object)localPlayer != (Object)null)
			{
				Vector3 val = ((Component)_lair).transform.position - ((Component)localPlayer).transform.position;
				return ((Vector3)(ref val)).sqrMagnitude < 64f;
			}
			return false;
		}
	}

	public static void Open(Lair lair)
	{
		if ((Object)(object)GUIManager.CustomGUIFront == (Object)null)
		{
			return;
		}
		try
		{
			if ((Object)(object)_root == (Object)null)
			{
				Build();
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Could not build the companion window: " + ex));
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			_root = null;
			return;
		}
		if (InventoryGui.IsVisible())
		{
			InventoryGui.instance.Hide();
		}
		_lair = lair;
		_root.SetActive(true);
		IsOpen = true;
		OpenedFrame = Time.frameCount;
		GUIManager.BlockInput(true);
		if (Manager.Roster.Pets.Count == 0)
		{
			_tab = 2;
		}
		SwitchTab(_tab);
	}

	public static void Close()
	{
		if ((Object)(object)_root != (Object)null)
		{
			_root.SetActive(false);
		}
		if (IsOpen)
		{
			GUIManager.BlockInput(false);
		}
		IsOpen = false;
		_lair = null;
		ClosedFrame = Time.frameCount;
	}

	public static void Rebuild()
	{
		Lair lair = _lair;
		bool isOpen = IsOpen;
		if (isOpen)
		{
			Close();
		}
		if ((Object)(object)_root != (Object)null)
		{
			Object.Destroy((Object)(object)_root);
		}
		_root = null;
		if (isOpen)
		{
			Open(lair);
		}
	}

	public static void Update()
	{
		if (IsOpen && !((Object)(object)_root == (Object)null))
		{
			if (_status.text.Length > 0 && Time.time > _statusUntil)
			{
				_status.text = "";
			}
			_refresh -= Time.deltaTime;
			if (_refresh <= 0f)
			{
				_refresh = 0.5f;
				Refresh();
			}
		}
	}

	private static void Status(string text, bool ok)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_status == (Object)null))
		{
			_status.text = text ?? "";
			((Graphic)_status).color = (ok ? Ui.Yellow : Ui.Bad);
			_statusUntil = Time.time + 6f;
		}
	}

	private static void Result(string err, string okText)
	{
		if (err != null)
		{
			Status(err, ok: false);
		}
		else if (okText != null)
		{
			Status(okText, ok: true);
		}
		Refresh();
	}

	private static void Build()
	{
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: 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)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Expected O, but got Unknown
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Expected O, but got Unknown
		//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
		Tabs.Clear();
		Pages.Clear();
		ModeBtns.Clear();
		TalentBtns.Clear();
		BranchTitles.Clear();
		HerdTexts.Clear();
		HerdBtns.Clear();
		HerdBgs.Clear();
		_root = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 1040f, 700f, true);
		((Object)_root).name = "Companions_Panel";
		Transform transform = _root.transform;
		_title = Ui.Txt(transform, Loc.T("ui_title"), 34, Ui.Orange, GUIManager.Instance.NorseBold, (TextAnchor)4);
		Ui.Place(((Component)_title).gameObject, 160f, 12f, 720f, 46f);
		_subtitle = Ui.Label(transform, "", 160f, 56f, 720f, 24f, 15, Ui.Grey, (TextAnchor)4);
		Button b = Ui.Btn(transform, "X", 974f, 22f, 40f, 40f, new UnityAction(Close));
		Ui.SetBtnText(b, "X");
		string[] array = new string[3]
		{
			Loc.T("tab_companion"),
			Loc.T("tab_talents"),
			Loc.T("tab_herd")
		};
		float num = 326.66666f;
		for (int i = 0; i < 3; i++)
		{
			int idx = i;
			Tabs.Add(Ui.Btn(transform, array[i], 30f + (float)i * num, 88f, num - 8f, 40f, (UnityAction)delegate
			{
				SwitchTab(idx);
			}));
			GameObject item = Ui.Group(transform, "Page" + i, 0f, 140f, 1040f, 500f);
			Pages.Add(item);
		}
		BuildCompanionPage(Pages[0].transform);
		BuildTalentPage(Pages[1].transform);
		BuildHerdPage(Pages[2].transform);
		_status = Ui.Label(transform, "", 30f, 644f, 980f, 30f, 16, Ui.Yellow, (TextAnchor)4);
		_root.SetActive(false);
	}

	private static void BuildCompanionPage(Transform page)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: 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_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_021a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Expected O, but got Unknown
		//IL_0336: 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_02db: Expected O, but got Unknown
		//IL_0399: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a3: Expected O, but got Unknown
		//IL_042b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0435: Expected O, but got Unknown
		//IL_0492: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f0: Expected O, but got Unknown
		//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04dc: Expected O, but got Unknown
		//IL_0581: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0541: Unknown result type (might be due to invalid IL or missing references)
		//IL_054b: Expected O, but got Unknown
		//IL_062c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0668: Unknown result type (might be due to invalid IL or missing references)
		//IL_0672: Expected O, but got Unknown
		//IL_0693: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0601: Expected O, but got Unknown
		//IL_06cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d5: Expected O, but got Unknown
		//IL_0717: Unknown result type (might be due to invalid IL or missing references)
		//IL_0721: Expected O, but got Unknown
		_empty = Ui.Label(page, "", 60f, 160f, 920f, 120f, 20, Ui.Grey, (TextAnchor)4);
		_companionGroup = Ui.Group(page, "Companion", 0f, 0f, 1040f, 500f);
		Transform transform = _companionGroup.transform;
		Image val = Ui.Img(transform, "LeftBg", 30f, 0f, 480f, 490f, Ui.PanelDark);
		Transform transform2 = ((Component)val).transform;
		_name = Ui.Txt(transform2, "", 30, Ui.Orange, GUIManager.Instance.NorseBold, (TextAnchor)3);
		Ui.Place(((Component)_name).gameObject, 16f, 8f, 448f, 40f);
		_species = Ui.Label(transform2, "", 16f, 46f, 448f, 24f, 15, Ui.Grey, (TextAnchor)3);
		_nameField = Ui.Field(transform2, 16f, 78f, 300f, 34f, 20);
		Ui.Btn(transform2, Loc.T("btn_rename"), 324f, 76f, 140f, 38f, (UnityAction)delegate
		{
			Manager.Rename(_nameField.text);
			Result(null, Loc.T("ok_renamed"));
		});
		_levelTxt = Ui.Label(transform2, "", 16f, 124f, 448f, 26f, 18, Ui.Beige, (TextAnchor)3);
		_xpFill = Ui.BarFill(transform2, 16f, 154f, 448f, 20f, new Color(0.95f, 0.75f, 0.25f, 0.9f));
		_xpTxt = Ui.Label(transform2, "", 16f, 176f, 448f, 22f, 14, Ui.Grey, (TextAnchor)3);
		_bondFill = Ui.BarFill(transform2, 16f, 204f, 448f, 20f, new Color(0.95f, 0.45f, 0.55f, 0.9f));
		_bondTxt = Ui.Label(transform2, "", 16f, 226f, 448f, 22f, 14, Ui.Grey, (TextAnchor)3);
		_stats = Ui.Txt(transform2, "", 15, Ui.Beige, GUIManager.Instance.AveriaSerif, (TextAnchor)0);
		Ui.Place(((Component)_stats).gameObject, 16f, 256f, 448f, 180f);
		Ui.Fit(_stats, 10, 15);
		_skinBtn = Ui.Btn(transform2, "", 16f, 440f, 448f, 38f, (UnityAction)delegate
		{
			Manager.NextSkin();
			Refresh();
		});
		Transform transform3 = Ui.Group(transform, "Right", 530f, 0f, 480f, 490f).transform;
		Ui.Label(transform3, Loc.T("hdr_orders"), 0f, 0f, 480f, 26f, 18, Ui.Orange, (TextAnchor)3);
		for (int num = 0; num < 3; num++)
		{
			Mode m = (Mode)num;
			ModeBtns.Add(Ui.Btn(transform3, Loc.T("mode_" + num), (float)num * 160f, 30f, 152f, 40f, (UnityAction)delegate
			{
				Manager.SetMode(m);
				Refresh();
			}));
		}
		_bagBtn = Ui.Btn(transform3, Loc.T("btn_bag"), 0f, 78f, 236f, 40f, (UnityAction)delegate
		{
			if ((Object)(object)Manager.Pet == (Object)null)
			{
				Status(Loc.T("err_not_here"), ok: false);
			}
			else
			{
				Close();
				Manager.Pet.OpenBag();
			}
		});
		_feedBtn = Ui.Btn(transform3, Loc.T("btn_feed"), 244f, 78f, 236f, 40f, new UnityAction(FeedFavorite));
		_ravenGroup = Ui.Group(transform3, "Raven", 0f, 128f, 480f, 110f);
		Transform transform4 = _ravenGroup.transform;
		Ui.Label(transform4, Loc.T("hdr_post"), 0f, 0f, 480f, 24f, 16, Ui.Orange, (TextAnchor)3);
		_sendLairBtn = Ui.Btn(transform4, Loc.T("btn_send_lair"), 0f, 28f, 480f, 36f, (UnityAction)delegate
		{
			Result(Manager.SendToLair(), Loc.T("ok_sent"));
		});
		_playerField = Ui.Field(transform4, 0f, 72f, 230f, 34f, 30);
		_sendPlayerBtn = Ui.Btn(transform4, Loc.T("btn_send_player"), 238f, 70f, 242f, 38f, (UnityAction)delegate
		{
			Result(Manager.SendToPlayer(_playerField.text), Loc.T("ok_sent"));
		});
		Ui.Label(transform3, Loc.T("hdr_lair"), 0f, 250f, 480f, 24f, 16, Ui.Orange, (TextAnchor)3);
		_lairHint = Ui.Label(transform3, Loc.T("lair_only"), 0f, 274f, 480f, 22f, 13, Ui.Grey, (TextAnchor)3);
		_ritualBtn = Ui.Btn(transform3, Loc.T("btn_ritual"), 0f, 298f, 200f, 38f, (UnityAction)delegate
		{
			Result(Manager.DoRitual(), null);
		});
		_ritualTxt = Ui.Label(transform3, "", 208f, 298f, 272f, 38f, 13, Ui.Beige, (TextAnchor)3);
		_reviveBtn = Ui.Btn(transform3, Loc.T("btn_revive"), 0f, 342f, 200f, 38f, new UnityAction(Revive));
		_reviveTxt = Ui.Label(transform3, "", 208f, 342f, 272f, 38f, 13, Ui.Beige, (TextAnchor)3);
		_mailBtn = Ui.Btn(transform3, "", 0f, 386f, 480f, 38f, (UnityAction)delegate
		{
			int num2 = Manager.TakeMailbox();
			Result((num2 > 0) ? null : Loc.T("err_mailbox_empty_or_full"), Loc.T("ok_mail", num2));
		});
		_unloadBtn = Ui.Btn(transform3, Loc.T("btn_unload"), 0f, 430f, 480f, 38f, (UnityAction)delegate
		{
			if ((Object)(object)_lair != (Object)null)
			{
				Result(Manager.UnloadLox(_lair), Loc.T("ok_unloaded"));
			}
		});
	}

	private static void BuildTalentPage(Transform page)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0194: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_0263: Expected O, but got Unknown
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a4: Expected O, but got Unknown
		_talentEmpty = Ui.Label(page, Loc.T("no_companion_yet"), 60f, 160f, 920f, 120f, 20, Ui.Grey, (TextAnchor)4);
		_talentGroup = Ui.Group(page, "Talents", 0f, 0f, 1040f, 500f);
		Transform transform = _talentGroup.transform;
		float num = 326.66666f;
		for (int i = 0; i < 3; i++)
		{
			Image val = Ui.Img(transform, "Branch" + i, 30f + (float)i * num, 0f, num - 10f, 330f, Ui.PanelDark);
			Text item = Ui.Label(((Component)val).transform, "", 10f, 4f, num - 30f, 28f, 18, Ui.Orange, (TextAnchor)4);
			BranchTitles.Add(item);
			for (int j = 0; j < 4; j++)
			{
				Button val2 = Ui.Btn(((Component)val).transform, "", 10f, 38f + (float)j * 72f, num - 30f, 66f, null);
				Text componentInChildren = ((Component)val2).GetComponentInChildren<Text>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.alignment = (TextAnchor)4;
					componentInChildren.supportRichText = true;
					componentInChildren.resizeTextMaxSize = 15;
				}
				TalentBtns.Add(new KeyValuePair<string, Button>("", val2));
			}
		}
		Image val3 = Ui.Img(transform, "Info", 30f, 340f, 980f, 100f, Ui.PanelDark);
		_talentInfo = Ui.Txt(((Component)val3).transform, "", 15, Ui.Beige, GUIManager.Instance.AveriaSerif, (TextAnchor)0);
		Ui.Place(((Component)_talentInfo).gameObject, 14f, 8f, 952f, 86f);
		Ui.Fit(_talentInfo, 10, 15);
		_pointsTxt = Ui.Label(transform, "", 30f, 450f, 360f, 38f, 17, Ui.Yellow, (TextAnchor)3);
		_raiseBtn = Ui.Btn(transform, Loc.T("btn_raise"), 400f, 448f, 260f, 40f, (UnityAction)delegate
		{
			Result(Manager.RaiseTalent(_selTalent), Loc.T("ok_raised"));
		});
		_respecBtn = Ui.Btn(transform, "", 670f, 448f, 340f, 40f, (UnityAction)delegate
		{
			Result(Manager.Respec(), Loc.T("ok_respec"));
		});
	}

	private static void BuildHerdPage(Transform page)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Expected O, but got Unknown
		for (int i = 0; i < Species.All.Count; i++)
		{
			SpeciesDef speciesDef = Species.All[i];
			Image val = Ui.Img(page, "Herd" + i, 30f, (float)i * 96f, 980f, 90f, Ui.RowBase);
			HerdBgs.Add(val);
			Text val2 = Ui.Txt(((Component)val).transform, "", 15, Ui.Beige, GUIManager.Instance.AveriaSerif, (TextAnchor)0);
			Ui.Place(((Component)val2).gameObject, 14f, 6f, 710f, 80f);
			Ui.Fit(val2, 10, 15);
			HerdTexts.Add(val2);
			string id = speciesDef.Id;
			HerdBtns.Add(Ui.Btn(((Component)val).transform, "", 750f, 24f, 210f, 42f, (UnityAction)delegate
			{
				HerdAction(id);
			}));
		}
	}

	private static void SwitchTab(int i)
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		_tab = i;
		for (int j = 0; j < Pages.Count; j++)
		{
			Pages[j].SetActive(j == i);
		}
		for (int k = 0; k < Tabs.Count; k++)
		{
			Text componentInChildren = ((Component)Tabs[k]).GetComponentInChildren<Text>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((Graphic)componentInChildren).color = ((k == i) ? Ui.Yellow : Ui.Beige);
			}
		}
		Refresh();
	}

	private static void Refresh()
	{
		//IL_002d: 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)
		if ((Object)(object)_root == (Object)null)
		{
			return;
		}
		_subtitle.text = (AtLair ? Loc.T("sub_lair") : Loc.T("sub_anywhere", ((object)Plugin.WindowKey.Value/*cast due to .constrained prefix*/).ToString()));
		try
		{
			if (_tab == 0)
			{
				RefreshCompanion();
			}
			else if (_tab == 1)
			{
				RefreshTalents();
			}
			else
			{
				RefreshHerd();
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Companion window: " + ex.Message));
		}
	}

	private static void RefreshCompanion()
	{
		//IL_0656: Unknown result type (might be due to invalid IL or missing references)
		//IL_064f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0648: Unknown result type (might be due to invalid IL or missing references)
		PetData active = Manager.Active;
		_companionGroup.SetActive(active != null);
		_empty.text = ((active == null) ? Loc.T("no_companion_yet") : "");
		if (active == null)
		{
			return;
		}
		SpeciesDef def = active.Def;
		Companion pet = Manager.Pet;
		_name.text = Manager.PetNameOf(active);
		_species.text = Loc.T("nc_species_" + def.Id) + " · " + Loc.T("role_" + def.Role.ToString().ToLowerInvariant());
		if (!_nameField.isFocused && _nameField.text.Length == 0)
		{
			_nameField.text = active.Name;
		}
		int num = Species.Stage(active.Level);
		_levelTxt.text = Loc.T("ui_level", active.Level, 30, Loc.T("stage_" + num));
		float num2 = Species.XpToNext(active.Level);
		bool flag = active.Level >= 30;
		Ui.Bar(_xpFill, 448f, flag ? 1f : (active.Xp / num2));
		bool flag2 = !flag && active.Level >= Species.RitualGate(active.Rituals);
		_xpTxt.text = (flag ? Loc.T("ui_xp_max") : (Loc.T("ui_xp", Mathf.FloorToInt(active.Xp), Mathf.RoundToInt(num2)) + (flag2 ? ("  <color=#FF9966>" + Loc.T("ui_gated") + "</color>") : "")));
		Ui.Bar(_bondFill, 448f, active.Bond / 100f);
		_bondTxt.text = Loc.T("ui_bond", Mathf.RoundToInt(active.Bond), Loc.T(BondWord(active.Bond)), Mathf.RoundToInt((0.6f + 0.8f * active.Bond / 100f) * 100f));
		List<string> list = new List<string>();
		float num3 = Manager.KoSecondsLeft(active);
		if (num3 > 0f)
		{
			list.Add("<color=#FF8866>" + Loc.T("ui_ko", Mathf.CeilToInt(num3)) + "</color>");
		}
		else if ((Object)(object)pet != (Object)null && (Object)(object)pet.Char != (Object)null)
		{
			list.Add(Loc.T("ui_hp", Mathf.RoundToInt(pet.Char.GetHealth()), Mathf.RoundToInt(pet.Char.GetMaxHealth())));
		}
		else if ((Object)(object)pet == (Object)null)
		{
			list.Add(Loc.T("ui_not_here"));
		}
		list.Add(Loc.T("ui_mode", Loc.T("mode_" + (int)Manager.Roster.Mode)));
		if (!def.Flying)
		{
			list.Add(Loc.T("ui_damage", Mathf.RoundToInt(def.Damage * Species.DamageMult(active.Level) * Plugin.DamageMultiplier.Value)));
		}
		int num4 = Manager.BagRows(active);
		if (num4 > 0)
		{
			list.Add(Loc.T("ui_bag", num4 * 4));
		}
		list.Add(Loc.T("ui_points", active.PointsFree));
		list.Add(Loc.T("ui_kills", active.Kills, (float)Mathf.RoundToInt(active.Travelled / 1000f * 10f) / 10f));
		if (active.FedUntil > (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTime().Ticks : 0))
		{
			list.Add(Loc.T("ui_fed"));
		}
		list.Add(Loc.T("ui_favorite", FavoriteNames(def)));
		_stats.text = string.Join("\n", list.ToArray());
		Ui.SetBtnText(_skinBtn, Loc.T("btn_skin", Loc.T("skin_" + active.Skin)) + "  (" + UnlockedSkins(active) + "/" + def.Skins.Length + ")");
		for (int i = 0; i < ModeBtns.Count; i++)
		{
			bool flag3 = i != 2 || def.CanWork;
			((Selectable)ModeBtns[i]).interactable = flag3;
			Text componentInChildren = ((Component)ModeBtns[i]).GetComponentInChildren<Text>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((Graphic)componentInChildren).color = ((Manager.Roster.Mode == (Mode)i) ? Ui.Yellow : (flag3 ? Ui.Beige : Ui.Grey));
			}
		}
		((Selectable)_bagBtn).interactable = num4 > 0 && (Object)(object)pet != (Object)null;
		((Selectable)_feedBtn).interactable = (Object)(object)pet != (Object)null;
		_ravenGroup.SetActive(def.Flying);
		if (def.Flying)
		{
			((Selectable)_sendLairBtn).interactable = (Object)(object)pet != (Object)null;
			((Selectable)_sendPlayerBtn).interactable = (Object)(object)pet != (Object)null && active.Rank("r_messenger") > 0;
		}
		bool atLair = AtLair;
		((Component)_lairHint).gameObject.SetActive(!atLair);
		bool flag4 = Manager.RitualReady(active);
		((Selectable)_ritualBtn).interactable = atLair && flag4;
		_ritualTxt.text = ((active.Rituals >= 3) ? Loc.T("ritual_all_done") : (flag4 ? Loc.T("ritual_cost", Costs.Describe(Manager.RitualCost(active))) : Loc.T("ritual_at", Species.RitualGate(active.Rituals))));
		((Selectable)_reviveBtn).interactable = atLair && num3 > 0f;
		_reviveTxt.text = Loc.T("revive_cost");
		int num5 = Manager.MailboxCount();
		Ui.SetBtnText(_mailBtn, Loc.T("btn_mail", num5));
		((Selectable)_mailBtn).interactable = atLair && num5 > 0;
		((Component)_unloadBtn).gameObject.SetActive(Manager.Roster.Has("lox"));
		((Selectable)_unloadBtn).interactable = atLair;
	}

	private static string BondWord(float b)
	{
		if (b >= 85f)
		{
			return "bond_4";
		}
		if (b >= 60f)
		{
			return "bond_3";
		}
		if (b >= 35f)
		{
			return "bond_2";
		}
		if (b >= 15f)
		{
			return "bond_1";
		}
		return "bond_0";
	}

	private static int UnlockedSkins(PetData d)
	{
		int num = 0;
		for (int i = 0; i < d.Def.Skins.Length; i++)
		{
			if (d.SkinUnlocked(i))
			{
				num++;
			}
		}
		return num;
	}

	private static string FavoriteNames(SpeciesDef s)
	{
		List<string> list = new List<string>();
		for (int i = 0; i < s.Favorite.Length && i < 5; i++)
		{
			list.Add(Costs.ItemName(s.Favorite[i]));
		}
		return string.Join(", ", list.ToArray());
	}

	private static void RefreshTalents()
	{
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Expected O, but got Unknown
		PetData active = Manager.Active;
		_talentGroup.SetActive(active != null);
		((Component)_talentEmpty).gameObject.SetActive(active == null);
		if (active == null)
		{
			return;
		}
		List<TalentDef> list = Talents.For(active.Species);
		for (int i = 0; i < 3; i++)
		{
			BranchTitles[i].text = Loc.T("br_" + active.Species + "_" + i) + "  (" + Talents.PointsInBranch(active, i) + ")";
		}
		for (int j = 0; j < TalentBtns.Count; j++)
		{
			int branch = j / 4;
			int tier = j % 4;
			TalentDef talentDef = list.Find((TalentDef x) => x.Branch == branch && x.Tier == tier);
			Button value = TalentBtns[j].Value;
			if (talentDef == null)
			{
				((Component)value).gameObject.SetActive(false);
				continue;
			}
			((Component)value).gameObject.SetActive(true);
			if (TalentBtns[j].Key != talentDef.Id)
			{
				string id = talentDef.Id;
				((UnityEventBase)value.onClick).RemoveAllListeners();
				((UnityEvent)value.onClick).AddListener((UnityAction)delegate
				{
					_selTalent = id;
					Refresh();
				});
				TalentBtns[j] = new KeyValuePair<string, Button>(talentDef.Id, value);
			}
			int num = active.Rank(talentDef.Id);
			string text = Talents.CanRaise(active, talentDef);
			string text2 = ((num >= talentDef.MaxRank) ? "#9BE37A" : ((text == null) ? "#FFD27A" : ((num > 0) ? "#E8DCC0" : "#8A8478")));
			string text3 = ((_selTalent == talentDef.Id) ? "▶ " : "");
			Ui.SetBtnText(value, "<color=" + text2 + ">" + text3 + Loc.T("t_" + talentDef.Id) + "  " + num + "/" + talentDef.MaxRank + "</color>\n<size=12><color=#BFB6A2>" + Talents.Fmt(talentDef, Math.Max(1, num)) + ((num == 0) ? (" " + Loc.T("at_rank1")) : "") + "</color></size>");
		}
		TalentDef talentDef2 = Talents.Get(_selTalent);
		if (talentDef2 == null || talentDef2.Species != active.Species)
		{
			talentDef2 = ((list.Count > 0) ? list[0] : null);
			_selTalent = ((talentDef2 != null) ? talentDef2.Id : "");
		}
		if (talentDef2 != null)
		{
			int num2 = active.Rank(talentDef2.Id);
			string text4 = ((num2 > 0) ? Talents.Fmt(talentDef2, num2) : "—");
			string text5 = ((num2 < talentDef2.MaxRank) ? Talents.Fmt(talentDef2, num2 + 1) : "—");
			string text6 = Talents.CanRaise(active, talentDef2);
			string text7 = Loc.T("tal_req", Talents.TierLevel[talentDef2.Tier], Talents.TierPoints[talentDef2.Tier]);
			_talentInfo.text = "<color=#F4C870><b>" + Loc.T("t_" + talentDef2.Id) + "</b></color>  <color=#A8A8A8>" + Loc.T("tal_rank", num2, talentDef2.MaxRank) + " · " + text7 + "</color>\n" + Loc.T("td_" + talentDef2.Id, text4, text5) + ((text6 != null && num2 < talentDef2.MaxRank) ? ("\n<color=#FF9977>" + Loc.T(text6) + "</color>") : "");
			((Selectable)_raiseBtn).interactable = text6 == null;
		}
		_pointsTxt.text = Loc.T("ui_points", active.PointsFree);
		Ui.SetBtnText(_respecBtn, Loc.T("btn_respec", Costs.Describe(Plugin.RespecCost.Value)));
		((Selectable)_respecBtn).interactable = active.PointsSpent > 0;
	}

	private static void RefreshHerd()
	{
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		bool atLair = AtLair;
		for (int i = 0; i < Species.All.Count && i < HerdTexts.Count; i++)
		{
			SpeciesDef speciesDef = Species.All[i];
			PetData value;
			bool flag = Manager.Roster.Pets.TryGetValue(speciesDef.Id, out value);
			bool flag2 = flag && Manager.Roster.Active == speciesDef.Id;
			string text = (flag ? null : Manager.WhyLocked(speciesDef));
			string text2 = "<color=#F4C870><b>" + Loc.T("nc_species_" + speciesDef.Id) + "</b></color>  <color=#A8A8A8>" + Loc.T("role_" + speciesDef.Role.ToString().ToLowerInvariant()) + "</color>";
			string text3 = (flag2 ? ("<color=#9BE37A>" + Loc.T("herd_active", Manager.PetNameOf(value), value.Level) + "</color>") : (flag ? Loc.T("herd_owned", Manager.PetNameOf(value), value.Level) : ((text != null) ? ("<color=#A0948A>" + text + "</color>") : ("<color=#FFD27A>" + Loc.T("herd_available") + "</color>"))));
			HerdTexts[i].text = text2 + "   " + text3 + "\n<size=13>" + Loc.T("desc_" + speciesDef.Id) + "</size>";
			((Graphic)HerdBgs[i]).color = (flag2 ? Ui.RowOwned : ((flag || text == null) ? Ui.RowBase : Ui.RowLocked));
			Button val = HerdBtns[i];
			if (flag2)
			{
				Ui.SetBtnText(val, Loc.T("btn_active"));
				((Selectable)val).interactable = false;
			}
			else if (flag)
			{
				Ui.SetBtnText(val, Loc.T("btn_choose"));
				((Selectable)val).interactable = atLair;
			}
			else
			{
				Ui.SetBtnText(val, Loc.T((Manager.Roster.Pets.Count == 0) ? "btn_choose_first" : "btn_adopt"));
				((Selectable)val).interactable = text == null && (atLair || Manager.Roster.Pets.Count == 0);
			}
		}
	}

	private static void HerdAction(string id)
	{
		if (Manager.Roster.Has(id))
		{
			if (!AtLair)
			{
				Status(Loc.T("lair_only"), ok: false);
				return;
			}
			Result(Manager.Swap(id), Loc.T("ok_swapped", Loc.T("nc_species_" + id)));
			return;
		}
		bool flag = Manager.Roster.Pets.Count == 0;
		string text = Manager.Adopt(id);
		Result(text, Loc.T("ok_adopted", Loc.T("nc_species_" + id)));
		if (text == null && flag)
		{
			SwitchTab(0);
		}
	}

	private static void FeedFavorite()
	{
		Player localPlayer = Player.m_localPlayer;
		PetData active = Manager.Active;
		if ((Object)(object)localPlayer == (Object)null || active == null)
		{
			return;
		}
		if ((Object)(object)Manager.Pet == (Object)null)
		{
			Status(Loc.T("err_not_here"), ok: false);
			return;
		}
		ItemData val = null;
		foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems())
		{
			if (Species.IsFavorite(active.Def, allItem))
			{
				val = allItem;
				break;
			}
		}
		if (val == null)
		{
			Status(Loc.T("err_no_favorite"), ok: false);
			return;
		}
		Manager.Feed(Manager.Pet, val);
		Refresh();
	}

	private static void Revive()
	{
		Player localPlayer = Player.m_localPlayer;
		PetData active = Manager.Active;
		if ((Object)(object)localPlayer == (Object)null || active == null)
		{
			return;
		}
		ItemData val = null;
		foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems())
		{
			if (Species.IsFavorite(active.Def, allItem))
			{
				val = allItem;
				break;
			}
		}
		if (val == null)
		{
			Status(Loc.T("err_no_favorite"), ok: false);
			return;
		}
		((Humanoid)localPlayer).GetInventory().RemoveItem(val, 1);
		Manager.Revive();
		Result(null, Loc.T("ok_revived", Manager.PetNameOf(active)));
	}
}
public class Lair : MonoBehaviour, Hoverable, Interactable
{
	private ZNetView _nv;

	private Container _chest;

	private static readonly List<Lair> All = new List<Lair>();

	public Container Chest => _chest;

	private void Awake()
	{
		_nv = ((Component)this).GetComponent<ZNetView>();
		_chest = ((Component)this).GetComponent<Container>();
	}

	private void Start()
	{
		if (!((Object)(object)_nv == (Object)null) && _nv.IsValid())
		{
			All.Add(this);
		}
	}

	private void OnDestroy()
	{
		All.Remove(this);
	}

	public static Lair Nearest(Vector3 p, float range)
	{
		//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_0036: Unknown result type (might be due to invalid IL or missing references)
		Lair result = null;
		float num = range * range;
		foreach (Lair item in All)
		{
			if (!((Object)(object)item == (Object)null))
			{
				Vector3 val = ((Component)item).transform.position - p;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					result = item;
				}
			}
		}
		return result;
	}

	public string GetHoverName()
	{
		return Loc.T("nc_lair");
	}

	public float GetHoverOffset()
	{
		return 0f;
	}

	public string GetHoverText()
	{
		string text = "<color=#F4C870>" + Loc.T("nc_lair") + "</color>";
		text = text + "\n[<color=yellow><b>$KEY_Use</b></color>] " + Loc.T("hover_lair_open");
		if ((Object)(object)_chest != (Object)null)
		{
			text = text + "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] " + Loc.T("hover_lair_chest");
		}
		return Localization.instance.Localize(text);
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		if (hold || (Object)(object)user != (Object)(object)Player.m_localPlayer)
		{
			return false;
		}
		if (alt && (Object)(object)_chest != (Object)null)
		{
			return _chest.Interact(user, false, false);
		}
		CompanionUI.Open(this);
		return true;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}
}
internal static class Lines
{
	private static Dictionary<string, List<string>> _lines;

	private static string _lang = "";

	private static readonly Dictionary<string, float> KeyCooldown = new Dictionary<string, float>();

	private static readonly Dictionary<string, int> LastIndex = new Dictionary<string, int>();

	private static readonly Dictionary<string, float> LongCooldown = new Dictionary<string, float>
	{
		{ "cold", 300f },
		{ "lowhp", 90f },
		{ "hungry", 900f },
		{ "boss_near", 300f },
		{ "trader", 1200f },
		{ "idle", 300f },
		{ "rain", 600f },
		{ "swim", 240f },
		{ "sail", 600f },
		{ "dungeon", 300f },
		{ "rested", 1200f },
		{ "fight", 60f },
		{ "kill", 60f }
	};

	private static float _lastSpoke = -100f;

	private static float _nextAmbient;

	private static Biome _biome;

	private static bool _night;

	private static bool _wet;

	private static bool _interior;

	private static bool _ship;

	private static bool _swim;

	private static bool _rested;

	private static float _stillFor;

	private static int _traderScan;

	private static Vector3 _lastOwnerPos;

	private static readonly Dictionary<string, float> BiomeSeen = new Dictionary<string, float>();

	internal static int SectionCount
	{
		get
		{
			Ensure();
			return _lines.Count;
		}
	}

	public static void ResetCooldowns()
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		KeyCooldown.Clear();
		_lastSpoke = -100f;
		_nextAmbient = Time.time + 90f;
		_biome = (Biome)0;
		BiomeSeen.Clear();
	}

	private static void Ensure()
	{
		string langCode = Loc.LangCode;
		if (_lines != null && langCode == _lang)
		{
			return;
		}
		_lang = langCode;
		_lines = new Dictionary<string, List<string>>();
		Parse(ReadEmbedded("lines_" + langCode + ".txt") ?? ReadEmbedded("lines_en.txt") ?? "", _lines);
		try
		{
			string text = Path.Combine(Path.Combine(Paths.ConfigPath, "Companions"), "lines_" + langCode + ".txt");
			if (!File.Exists(text))
			{
				return;
			}
			Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
			Parse(File.ReadAllText(text, Encoding.UTF8), dictionary);
			foreach (KeyValuePair<string, List<string>> item in dictionary)
			{
				_lines[item.Key] = item.Value;
			}
			Plugin.Log.LogInfo((object)("Companion lines: " + dictionary.Count + " sections overridden from " + text));
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Companion lines override: " + ex.Message));
		}
	}

	public static void Reload()
	{
		_lines = null;
	}

	private static string ReadEmbedded(string file)
	{
		Assembly assembly = typeof(Lines).Assembly;
		using Stream stream = assembly.GetManifestResourceStream("Companions." + file);
		if (stream == null)
		{
			return null;
		}
		using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
		return streamReader.ReadToEnd();
	}

	internal static void Parse(string text, Dictionary<string, List<string>> into)
	{
		List<string> value = null;
		string[] array = text.Split('\n');
		foreach (string text2 in array)
		{
			string text3 = text2.Trim();
			if (text3.Length == 0 || text3.StartsWith("#"))
			{
				continue;
			}
			if (text3.StartsWith("[") && text3.EndsWith("]"))
			{