Decompiled source of Hati Wolf Companion v0.7.38

BepInEx/plugins/AIfriend/ValheimAICompanion.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Splatform;
using UnityEngine;
using UnityEngine.UI;

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

public enum CompanionMode
{
	Stay,
	Follow,
	Guard
}
public sealed class CompanionAI
{
	private readonly MonsterAI _monster;

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

	private float _nextProtect;

	private bool _targetErrorLogged;

	public CompanionAI(MonsterAI monster)
	{
		_monster = monster;
	}

	public void Apply(CompanionMode mode, Player owner, bool modeChanged)
	{
		if ((Object)(object)_monster == (Object)null)
		{
			return;
		}
		if (mode == CompanionMode.Follow || mode == CompanionMode.Guard)
		{
			if (!((Object)(object)owner == (Object)null))
			{
				if ((Object)(object)_monster.GetFollowTarget() != (Object)(object)((Component)owner).gameObject)
				{
					_monster.SetFollowTarget(((Component)owner).gameObject);
				}
				if (modeChanged)
				{
					((BaseAI)_monster).ResetPatrolPoint();
				}
			}
		}
		else if (modeChanged || (Object)(object)_monster.GetFollowTarget() != (Object)null)
		{
			_monster.SetFollowTarget((GameObject)null);
			((BaseAI)_monster).SetPatrolPoint();
		}
	}

	public void Protect(Humanoid companion, Player owner, CompanionMode mode)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_monster == (Object)null || (Object)(object)companion == (Object)null || (Object)(object)owner == (Object)null || Time.time < _nextProtect)
		{
			return;
		}
		_nextProtect = Time.time + 2f;
		if (Vector3.Distance(((Component)owner).transform.position, ((Component)companion).transform.position) > 18f)
		{
			return;
		}
		Character val = BaseAI.FindClosestEnemy((Character)(object)companion, ((Component)owner).transform.position, (mode == CompanionMode.Guard) ? 18f : 12f);
		if ((Object)(object)val == (Object)null || val.IsDead() || SetTargetMethod == null)
		{
			return;
		}
		try
		{
			((BaseAI)_monster).Alert();
			SetTargetMethod.Invoke(_monster, new object[1] { val });
		}
		catch (Exception ex)
		{
			if (!_targetErrorLogged && (Object)(object)Plugin.Instance != (Object)null)
			{
				Plugin.Instance.LogWarning("Guard behavior failed: " + ex.Message);
			}
			_targetErrorLogged = true;
		}
	}
}
public sealed class CompanionCharacter : MonoBehaviour
{
	internal const string OwnerKey = "aifriend.owner";

	private const string ModeKey = "aifriend.mode";

	private ZNetView _view;

	private Humanoid _humanoid;

	private CompanionAI _ai;

	private CompanionEquipment _equipment;

	private CompanionShipPassenger _shipPassenger;

	private float _nextUpdate;

	private int _appliedMode = -1;

	private float _lastOwnerHit = -1000f;

	private bool _warnedLowHealth;

	public bool WasHitByOwnerRecently => Time.time - _lastOwnerHit < 180f;

	public bool IsAboard => _shipPassenger != null && _shipPassenger.IsAboard;

	public long OwnerId
	{
		get
		{
			ZDO zdo = GetZdo();
			return (zdo == null) ? 0 : zdo.GetLong("aifriend.owner", 0L);
		}
	}

	public CompanionMode Mode
	{
		get
		{
			ZDO zdo = GetZdo();
			return (zdo != null) ? ((CompanionMode)zdo.GetInt("aifriend.mode", 0)) : CompanionMode.Stay;
		}
	}

	internal void OnOwnerHit()
	{
		if (!(Time.time - _lastOwnerHit < 15f))
		{
			_lastOwnerHit = Time.time;
			Talker component = ((Component)this).GetComponent<Talker>();
			if ((Object)(object)component != (Object)null)
			{
				component.Say((Type)1, "Эй, осторожнее. Я рядом с тобой.");
			}
		}
	}

	private void Awake()
	{
		_view = ((Component)this).GetComponent<ZNetView>();
		_humanoid = ((Component)this).GetComponent<Humanoid>();
		_equipment = new CompanionEquipment(_humanoid);
		MonsterAI component = ((Component)this).GetComponent<MonsterAI>();
		if ((Object)(object)component != (Object)null)
		{
			_ai = new CompanionAI(component);
			_shipPassenger = new CompanionShipPassenger(_humanoid, component);
		}
		NpcTalk component2 = ((Component)this).GetComponent<NpcTalk>();
		if ((Object)(object)component2 != (Object)null)
		{
			((Behaviour)component2).enabled = false;
		}
	}

	public bool Initialize(Player owner)
	{
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner() || (Object)(object)_humanoid == (Object)null || _ai == null)
		{
			return false;
		}
		zdo.Set("aifriend.owner", owner.GetPlayerID());
		((Character)_humanoid).SetTamed(true);
		_equipment.Synchronize(owner, force: true);
		return SetMode(CompanionMode.Follow, owner);
	}

	public bool SetMode(CompanionMode mode, Player owner)
	{
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner() || OwnerId != owner.GetPlayerID() || _ai == null)
		{
			return false;
		}
		zdo.Set("aifriend.mode", (int)mode);
		if (_shipPassenger == null || !_shipPassenger.IsAboard)
		{
			_ai.Apply(mode, owner, modeChanged: true);
		}
		_appliedMode = (int)mode;
		return true;
	}

	private void Update()
	{
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		if (Time.time < _nextUpdate)
		{
			return;
		}
		_nextUpdate = Time.time + 1f;
		ZDO zdo = GetZdo();
		if (zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner() || _ai == null)
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || localPlayer.GetPlayerID() != OwnerId)
		{
			return;
		}
		CompanionMode mode = Mode;
		bool modeChanged = _appliedMode != (int)mode;
		_equipment.Synchronize(localPlayer, force: false);
		if (_shipPassenger == null || !_shipPassenger.Update(localPlayer, mode))
		{
			_ai.Apply(mode, localPlayer, modeChanged);
			_ai.Protect(_humanoid, localPlayer, mode);
		}
		if (((Character)localPlayer).GetHealthPercentage() > 0.7f)
		{
			_warnedLowHealth = false;
		}
		else if (!_warnedLowHealth && ((Character)localPlayer).GetHealthPercentage() < 0.3f && Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position) < 18f)
		{
			Talker component = ((Component)this).GetComponent<Talker>();
			if ((Object)(object)component != (Object)null)
			{
				component.Say((Type)1, "Ты ранен. Держись ближе, я прикрою.");
			}
			_warnedLowHealth = true;
		}
		_appliedMode = (int)mode;
	}

	private void FixedUpdate()
	{
		if (_shipPassenger != null)
		{
			_shipPassenger.FixedUpdate();
		}
	}

	private void OnDisable()
	{
		if (_shipPassenger != null)
		{
			_shipPassenger.Release(null, moveToOwner: false);
		}
	}

	private ZDO GetZdo()
	{
		if ((Object)(object)_view == (Object)null)
		{
			_view = ((Component)this).GetComponent<ZNetView>();
		}
		return ((Object)(object)_view != (Object)null && _view.IsValid()) ? _view.GetZDO() : null;
	}
}
public sealed class CompanionCommand : ConsoleCommand
{
	public override string Name => "companion";

	public override string Help => "companion dog | dogfollow | dogstay | dismissdog | status | dismissbjorn";

	public override void Run(string[] args, Terminal context)
	{
		if ((Object)(object)context == (Object)null)
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			context.AddString("Enter a world first.");
			return;
		}
		if (args.Length != 1)
		{
			context.AddString(((ConsoleCommand)this).Help);
			return;
		}
		string text = args[0].ToLowerInvariant();
		switch (text)
		{
		case "dog":
			Plugin.Instance.RequestDog(localPlayer, (Action<string>)context.AddString);
			break;
		case "dismissdog":
			Plugin.Instance.RequestDismissDog(localPlayer, (Action<string>)context.AddString);
			break;
		case "dismissbjorn":
			Plugin.Instance.RequestDismissBjorn(localPlayer, (Action<string>)context.AddString);
			break;
		default:
			if (!(text == "dogstay"))
			{
				if (text == "status")
				{
					CompanionDog companionDog = Plugin.Instance.FindOwnedDog(localPlayer);
					CompanionDogLifecycle component = ((Component)Plugin.Instance).GetComponent<CompanionDogLifecycle>();
					ZDO val = (((Object)(object)companionDog != (Object)null) ? companionDog.GetZdo() : (((Object)(object)component == (Object)null) ? null : component.TrackedDog(localPlayer)));
					context.AddString("Хати 0.7.37: " + ((val == null) ? "пока не найден" : ((DogMode)val.GetInt("aifriend.dog.mode", 0)).ToString()));
					context.AddString(HatiStatus.Describe(val));
					if (val != null)
					{
						context.AddString("Выносливость Хати: максимум " + (val.GetFloat("aifriend.dog.ownerPeakStamina", 50f) * 2f).ToString("0.#") + ".");
					}
					if ((Object)(object)companionDog != (Object)null && companionDog.Backpack != null)
					{
						context.AddString("Карман: " + companionDog.Backpack.UsedSlots + "/15, вес " + companionDog.Backpack.Weight.ToString("0.#") + "/150.");
					}
				}
				else
				{
					context.AddString(((ConsoleCommand)this).Help);
				}
				break;
			}
			goto case "dogfollow";
		case "dogfollow":
			Plugin.Instance.GiveDogOrder(localPlayer, (text == "dogfollow") ? 2 : 8, (Character)null, (Action<string>)context.AddString, (Vector3?)null);
			break;
		}
	}
}
public sealed class CompanionDog : MonoBehaviour
{
	internal const string DownPointKey = "aifriend.dog.downPoint";

	internal const string FoodTierKey = "aifriend.dog.foodTier";

	internal const string OwnerKey = "aifriend.dog.owner";

	internal const string HuntUntilKey = "aifriend.dog.huntUntil";

	internal const float HuntAimDistance = 200f;

	internal const string ModeKey = "aifriend.dog.mode";

	internal const string BoardKey = "aifriend.dog.boardRequested";

	internal const string LifeKey = "aifriend.dog.life";

	internal const string DownUntilKey = "aifriend.dog.downUntil";

	internal const string ReturnDayKey = "aifriend.dog.returnDay";

	internal const string HomeKey = "aifriend.dog.home";

	internal const string CatchupAtKey = "aifriend.dog.catchupAt";

	private const string GuardPointKey = "aifriend.dog.guardPoint";

	internal const string StayPointKey = "aifriend.dog.stayPoint";

	internal const string AwayPointKey = "aifriend.dog.awayPoint";

	internal const string UnloadPointKey = "aifriend.dog.unloadPoint";

	internal const string KennelKey = "aifriend.dog.kennel";

	internal const string AwayFromBaseKey = "aifriend.dog.awayFromBase";

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

	private ZNetView _view;

	private Humanoid _wolf;

	private MonsterAI _ai;

	private CompanionShipPassenger _passenger;

	private CompanionDogBackpack _backpack;

	private float _nextUpdate;

	private float _nextWarning;

	private float _nextPet;

	private readonly HatiDownedMotion _downedMotion = new HatiDownedMotion();

	private readonly DogIdlePoseTimer _idlePoseTimer = new DogIdlePoseTimer();

	private DogRestPose _idlePose;

	private readonly DogRestTimer _restTimer = new DogRestTimer();

	private readonly HatiRestMotion _restMotion = new HatiRestMotion();

	private readonly DogRestTimer _sleepRestTimer = new DogRestTimer();

	private readonly DogFoodRegeneration _foodRegen = new DogFoodRegeneration();

	private float _nextSleepDamageLog;

	private float _nextRestDiagnostic;

	private bool _targetErrorLogged;

	private Character _huntTarget;

	private float _huntUntil;

	private bool _huntLootActive;

	private DogMode _huntLootMode;

	private Vector3 _huntDeathPoint;

	private float _huntLootStarted;

	private float _huntLastLoot;

	private GameObject _huntLootMarker;

	private Renderer[] _renderers;

	private Collider[] _colliders;

	private bool[] _rendererWasEnabled;

	private bool[] _colliderWasEnabled;

	private bool _hidden;

	private readonly HatiShelterMotion _shelterMotion = new HatiShelterMotion();

	private bool _seaRetrieval;

	private float _seaRetrievalStarted;

	private float _seaLastLoot;

	private Vector3 _serpentDeathPoint;

	private GameObject _seaMarker;

	private GameObject _unloadMarker;

	private GameObject _kennelMarker;

	private GameObject _commandMarker;

	private bool _unloadRequested;

	private HatiForaging forage;

	private float fastDecisionUntil;

	internal int FoodTier
	{
		get
		{
			ZDO zdo = GetZdo();
			return (zdo != null) ? Mathf.Clamp(zdo.GetInt("aifriend.dog.foodTier", 0), 0, 3) : 0;
		}
	}

	public long OwnerId
	{
		get
		{
			ZDO zdo = GetZdo();
			return (zdo == null) ? 0 : zdo.GetLong("aifriend.dog.owner", 0L);
		}
	}

	public DogMode Mode
	{
		get
		{
			ZDO zdo = GetZdo();
			return (zdo != null) ? ((DogMode)zdo.GetInt("aifriend.dog.mode", 0)) : DogMode.Follow;
		}
	}

	public bool IsFollowing => Mode == DogMode.Follow || Mode == DogMode.Hunt || Mode == DogMode.Gather || Mode == DogMode.Fish;

	public CompanionDogBackpack Backpack => _backpack;

	public DogLifeState LifeState
	{
		get
		{
			ZDO zdo = GetZdo();
			return (zdo != null) ? ((DogLifeState)zdo.GetInt("aifriend.dog.life", 0)) : DogLifeState.Alive;
		}
	}

	public bool IsDowned => LifeState == DogLifeState.Downed;

	public bool IsAboard => _passenger != null && _passenger.IsAboard;

	public bool Initialize(Player owner)
	{
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || ((Character)owner).IsDead() || owner.GetPlayerID() <= 0 || zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner() || (Object)(object)_wolf == (Object)null || (Object)(object)_ai == (Object)null || zdo.GetLong("aifriend.dog.owner", 0L) != 0)
		{
			return false;
		}
		zdo.Set("aifriend.dog.owner", owner.GetPlayerID());
		CompanionDogProgression.Initialize(zdo, owner);
		zdo.Set("aifriend.dog.mode", 0);
		zdo.Set("aifriend.dog.boardRequested", false);
		zdo.Set("aifriend.dog.life", 0);
		((Character)_wolf).SetTamed(true);
		((Character)_wolf).SetLevel(1);
		MatchOwnerHealth(owner);
		_ai.SetFollowTarget(((Component)owner).gameObject);
		((BaseAI)_ai).ResetPatrolPoint();
		return true;
	}

	public bool SetMode(Player owner, DogMode mode)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0230: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = GetZdo();
		if (mode == DogMode.Home && zdo != null && zdo.GetVec3("aifriend.dog.kennel", Vector3.zero) != Vector3.zero)
		{
			mode = DogMode.Kennel;
		}
		if ((Object)(object)owner == (Object)null || zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner() || (Object)(object)_wolf == (Object)null || (Object)(object)_ai == (Object)null || owner.GetPlayerID() != OwnerId || mode < DogMode.Follow || mode > DogMode.Fish || LifeState != DogLifeState.Alive)
		{
			return false;
		}
		if (mode == DogMode.Kennel && zdo.GetVec3("aifriend.dog.kennel", Vector3.zero) == Vector3.zero)
		{
			return false;
		}
		if (mode == DogMode.Home && zdo.GetVec3("aifriend.dog.home", Vector3.zero) == Vector3.zero)
		{
			return false;
		}
		ResetRest();
		ResetIdlePose();
		CancelForaging();
		HatiPersonality component = ((Component)this).GetComponent<HatiPersonality>();
		if ((Object)(object)component != (Object)null)
		{
			component.Cancel();
		}
		FinishHuntLoot();
		_unloadRequested = false;
		ClearUnloadMarker();
		FinishSerpentRetrieval();
		_huntTarget = null;
		ClearHuntDeadline();
		ClearNativeCombatTarget();
		fastDecisionUntil = Time.time + 2f;
		_nextUpdate = 0f;
		DogMode mode2 = Mode;
		if (mode == DogMode.Guard)
		{
			zdo.Set("aifriend.dog.guardPoint", ((Component)this).transform.position);
		}
		if (mode == DogMode.Away)
		{
			zdo.Set("aifriend.dog.awayPoint", ((Component)owner).transform.position - ((Component)owner).transform.forward * 10f);
		}
		zdo.Set("aifriend.dog.catchupAt", 0L);
		zdo.Set("aifriend.dog.mode", (int)mode);
		if (mode == DogMode.Stay)
		{
			zdo.Set("aifriend.dog.stayPoint", ((Component)this).transform.position);
		}
		object obj;
		switch (mode)
		{
		default:
			obj = ((Component)owner).gameObject;
			break;
		case DogMode.Home:
		case DogMode.Away:
			obj = GetCommandMarker(zdo, mode);
			break;
		case DogMode.Kennel:
			obj = GetKennelMarker(zdo);
			break;
		case DogMode.Stay:
		case DogMode.Guard:
			obj = null;
			break;
		}
		GameObject val = (GameObject)obj;
		_ai.SetFollowTarget(val);
		if ((Object)(object)val == (Object)null && !HatiPointWaiting.IsPointMode(mode))
		{
			((BaseAI)_ai).SetPatrolPoint();
		}
		else
		{
			((BaseAI)_ai).ResetPatrolPoint();
		}
		if (mode2 != mode && (Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.DogSay(this, mode switch
			{
				DogMode.Away => "Ладно, отойду.", 
				DogMode.Home => "Возвращаюсь домой.", 
				DogMode.Fish => "Пойду за рыбой. Сухим не обещаю вернуться.", 
				DogMode.Gather => "Поищу, что нам пригодится.", 
				DogMode.Hunt => "Покажи, кого взять.", 
				DogMode.Guard => "Посторожу это место.", 
				DogMode.Stay => "Останусь в указанном месте.", 
				DogMode.Follow => "Я рядом.", 
				_ => "Пойду к будке отдохнуть.", 
			});
		}
		return true;
	}

	internal bool StayAt(Player owner, Vector3 point)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		if (!SetMode(owner, DogMode.Stay))
		{
			return false;
		}
		ZDO zdo = GetZdo();
		zdo.Set("aifriend.dog.stayPoint", point);
		ClearNativeCombatTarget();
		_ai.SetFollowTarget(GetCommandMarker(zdo, DogMode.Stay));
		((BaseAI)_ai).ResetPatrolPoint();
		return true;
	}

	private bool UpdateUnload(Player owner)
	{
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: 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_012f: Expected O, but got Unknown
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: 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)
		if (_backpack == null || !_backpack.HasItems)
		{
			_unloadRequested = false;
			ClearUnloadMarker();
			return false;
		}
		if (!_unloadRequested && (!_backpack.IsFull || !IsFollowing))
		{
			ClearUnloadMarker();
			return false;
		}
		ZDO zdo = GetZdo();
		if (zdo == null || IsAboard || (Object)(object)CompanionShipPassenger.GetOwnerShip(owner) != (Object)null)
		{
			ClearUnloadMarker();
			return false;
		}
		Vector3 vec = zdo.GetVec3("aifriend.dog.unloadPoint", zdo.GetVec3("aifriend.dog.home", Vector3.zero));
		if (vec == Vector3.zero)
		{
			ClearUnloadMarker();
			return false;
		}
		if (Vector3.Distance(((Component)owner).transform.position, vec) > 45f)
		{
			ClearUnloadMarker();
			return false;
		}
		if ((Object)(object)_unloadMarker == (Object)null)
		{
			_unloadMarker = new GameObject("Hati unload target");
			_unloadMarker.AddComponent<HatiNavigationGoal>();
		}
		_unloadMarker.transform.position = vec;
		if ((Object)(object)_ai.GetFollowTarget() != (Object)(object)_unloadMarker)
		{
			_ai.SetFollowTarget(_unloadMarker);
		}
		if (Vector3.Distance(((Component)this).transform.position, vec) > 3.5f)
		{
			return true;
		}
		_backpack.DropAll(vec + Vector3.up * 0.8f);
		if (!_backpack.HasItems)
		{
			_unloadRequested = false;
			ClearUnloadMarker();
		}
		return true;
	}

	private void ClearUnloadMarker()
	{
		if (!((Object)(object)_unloadMarker == (Object)null))
		{
			if ((Object)(object)_ai != (Object)null && (Object)(object)_ai.GetFollowTarget() == (Object)(object)_unloadMarker)
			{
				_ai.SetFollowTarget((GameObject)null);
			}
			Object.Destroy((Object)(object)_unloadMarker);
			_unloadMarker = null;
		}
	}

	internal bool Pet(Player owner)
	{
		//IL_0030: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || owner.GetPlayerID() != OwnerId || zdo == null || LifeState != DogLifeState.Alive || Vector3.Distance(((Component)owner).transform.position, ((Component)this).transform.position) > 4f || !CompanionDogOrders.CanControl(zdo, owner))
		{
			return false;
		}
		if (Time.time < _nextPet)
		{
			return true;
		}
		_nextPet = Time.time + 8f;
		Tameable component = ((Component)this).GetComponent<Tameable>();
		if ((Object)(object)component != (Object)null)
		{
			component.m_petEffect.Create(((Component)this).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
		}
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.DogSay(this, "Хрр. Вот за ухом — самое место.");
		}
		return true;
	}

	public bool RequestBoard(Player owner)
	{
		return false;
	}

	public bool RequestDisembark(Player owner)
	{
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner() || owner.GetPlayerID() != OwnerId || LifeState != DogLifeState.Alive)
		{
			return false;
		}
		zdo.Set("aifriend.dog.boardRequested", false);
		if (!IsAboard)
		{
			return true;
		}
		if (!((Character)owner).IsOnGround() || (Object)(object)CompanionShipPassenger.GetOwnerShip(owner) != (Object)null)
		{
			return false;
		}
		_passenger.Release(owner, moveToOwner: true);
		return true;
	}

	internal bool RecallAfterOwnerRespawn(Player owner, Vector3 point)
	{
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || ((Character)owner).IsDead() || owner.GetPlayerID() != OwnerId || zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner() || LifeState != DogLifeState.Alive || (Object)(object)_wolf == (Object)null || ((Character)_wolf).IsDead() || ((Character)_wolf).GetHealth() <= 0f || (Object)(object)_ai == (Object)null)
		{
			return false;
		}
		if (_passenger != null)
		{
			_passenger.Release(null, moveToOwner: false);
		}
		zdo.Set("aifriend.dog.boardRequested", false);
		FinishSerpentRetrieval();
		_unloadRequested = false;
		if (!SetMode(owner, DogMode.Follow))
		{
			return false;
		}
		HatiPersonality component = ((Component)this).GetComponent<HatiPersonality>();
		if ((Object)(object)component != (Object)null)
		{
			component.QueueReunion();
		}
		FieldInfo fieldInfo = AccessTools.Field(typeof(MonsterAI), "m_targetCreature");
		FieldInfo fieldInfo2 = AccessTools.Field(typeof(MonsterAI), "m_targetStatic");
		if (fieldInfo != null)
		{
			fieldInfo.SetValue(_ai, null);
		}
		if (fieldInfo2 != null)
		{
			fieldInfo2.SetValue(_ai, null);
		}
		TeleportNearOwner(point);
		return true;
	}

	internal void TeleportNearOwner(Vector3 point)
	{
		//IL_0001: 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)
		if (!Character.InInterior(point))
		{
			TeleportDungeon(point);
		}
	}

	internal void TeleportDungeon(Vector3 point)
	{
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = GetZdo();
		if (zdo != null && !((Object)(object)_view == (Object)null) && _view.IsOwner() && LifeState == DogLifeState.Alive && !IsAboard)
		{
			_shelterMotion.Release();
			ClearNativeCombatTarget();
			FinishHuntLoot();
			CancelForaging();
			ResetRest();
			ResetIdlePose();
			_huntTarget = null;
			ClearHuntDeadline();
			((Character)_wolf).SetMoveDir(Vector3.zero);
			((Character)_wolf).SetRun(false);
			((Component)this).transform.position = point;
			zdo.SetPosition(point);
			_view.SetLocalScale(Vector3.one * HatiDungeonTravel.BodyScale(Character.InInterior(point)));
			Rigidbody component = ((Component)this).GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.position = point;
			}
			if ((Object)(object)component != (Object)null && !component.isKinematic)
			{
				component.linearVelocity = Vector3.zero;
				component.angularVelocity = Vector3.zero;
			}
		}
	}

	internal void StartSerpentRetrieval(Player owner, Vector3 point)
	{
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)owner == (Object)null) && owner.GetPlayerID() == OwnerId && !((Object)(object)_view == (Object)null) && _view.IsOwner() && LifeState == DogLifeState.Alive && IsFollowing && !((Object)(object)CompanionShipPassenger.GetOwnerShip(owner) == (Object)null) && !(((Character)_wolf).GetHealthPercentage() < 0.2f) && !(Vector3.Distance(((Component)owner).transform.position, point) > 35f))
		{
			_serpentDeathPoint = point;
			_seaRetrieval = true;
			_seaRetrievalStarted = Time.time;
			_seaLastLoot = Time.time;
		}
	}

	private bool UpdateSerpentRetrieval(Player owner)
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: 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)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Expected O, but got Unknown
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		if (!_seaRetrieval)
		{
			return false;
		}
		Ship ownerShip = CompanionShipPassenger.GetOwnerShip(owner);
		if ((Object)(object)ownerShip == (Object)null || Time.time - _seaRetrievalStarted > 45f || ((Character)_wolf).GetHealthPercentage() < 0.2f)
		{
			FinishSerpentRetrieval();
			return false;
		}
		ItemDrop val = _backpack.FindSerpentLoot(_serpentDeathPoint, ((Component)this).transform.position);
		if ((Object)(object)val == (Object)null)
		{
			if (Time.time - _seaLastLoot > 5f)
			{
				FinishSerpentRetrieval();
				return false;
			}
			return true;
		}
		_seaLastLoot = Time.time;
		if (IsAboard)
		{
			_passenger.Release(null, moveToOwner: false);
		}
		if ((Object)(object)_seaMarker == (Object)null)
		{
			_seaMarker = new GameObject("Hati sea loot target");
			_seaMarker.AddComponent<HatiNavigationGoal>();
		}
		_seaMarker.transform.position = new Vector3(((Component)val).transform.position.x, ((Component)owner).transform.position.y - 0.8f, ((Component)val).transform.position.z);
		if ((Object)(object)_ai.GetFollowTarget() != (Object)(object)_seaMarker)
		{
			_ai.SetFollowTarget(_seaMarker);
		}
		Vector3 val2 = ((Component)this).transform.position - ((Component)val).transform.position;
		Vector2 val3 = new Vector2(val2.x, val2.z);
		float magnitude = ((Vector2)(ref val3)).magnitude;
		if (magnitude < 2.5f && Mathf.Abs(val2.y) < 80f)
		{
			_backpack.CollectSerpentLoot(val);
		}
		return true;
	}

	private void FinishSerpentRetrieval()
	{
		_seaRetrieval = false;
		if ((Object)(object)_seaMarker != (Object)null)
		{
			Object.Destroy((Object)(object)_seaMarker);
			_seaMarker = null;
		}
		if ((Object)(object)_ai != (Object)null)
		{
			_ai.SetFollowTarget((GameObject)null);
		}
	}

	private void Awake()
	{
		_view = ((Component)this).GetComponent<ZNetView>();
		_wolf = ((Component)this).GetComponent<Humanoid>();
		_ai = ((Component)this).GetComponent<MonsterAI>();
		if ((Object)(object)_ai != (Object)null && _ai.m_consumeItems != null)
		{
			_ai.m_consumeItems.Clear();
		}
		_backpack = new CompanionDogBackpack(_view);
		if ((Object)(object)((Component)this).GetComponent<HatiInteractionTarget>() == (Object)null)
		{
			((Component)this).gameObject.AddComponent<HatiInteractionTarget>();
		}
		if ((Object)(object)((Component)this).GetComponent<HatiRestPresentation>() == (Object)null)
		{
			((Component)this).gameObject.AddComponent<HatiRestPresentation>();
		}
		_renderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
		_colliders = ((Component)this).GetComponentsInChildren<Collider>(true);
		_rendererWasEnabled = new bool[_renderers.Length];
		_colliderWasEnabled = new bool[_colliders.Length];
		for (int i = 0; i < _renderers.Length; i++)
		{
			_rendererWasEnabled[i] = _renderers[i].enabled;
		}
		for (int i = 0; i < _colliders.Length; i++)
		{
			_colliderWasEnabled[i] = _colliders[i].enabled;
		}
		if ((Object)(object)_wolf != (Object)null)
		{
			Humanoid wolf = _wolf;
			((Character)wolf).m_onDeath = (Action)Delegate.Combine(((Character)wolf).m_onDeath, new Action(OnDogDeath));
		}
		if ((Object)(object)_wolf != (Object)null && (Object)(object)_ai != (Object)null)
		{
			_passenger = new CompanionShipPassenger(_wolf, _ai, preferLeft: true);
		}
	}

	public bool SetFollowing(Player owner, bool following)
	{
		return SetMode(owner, (!following) ? DogMode.Stay : DogMode.Follow);
	}

	public bool SetHome(Player owner)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner() || owner.GetPlayerID() != OwnerId)
		{
			return false;
		}
		zdo.Set("aifriend.dog.home", ((Component)owner).transform.position);
		return true;
	}

	public bool MarkUnloadPoint(Player owner)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner() || owner.GetPlayerID() != OwnerId)
		{
			return false;
		}
		zdo.Set("aifriend.dog.unloadPoint", ((Component)owner).transform.position);
		return true;
	}

	public bool MarkKennel(Player owner)
	{
		//IL_0055: 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)
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner() || owner.GetPlayerID() != OwnerId)
		{
			return false;
		}
		zdo.Set("aifriend.dog.kennel", ((Component)owner).transform.position);
		if ((Object)(object)_kennelMarker != (Object)null)
		{
			_kennelMarker.transform.position = ((Component)owner).transform.position;
		}
		return true;
	}

	private GameObject GetCommandMarker(ZDO zdo, DogMode mode)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Expected O, but got Unknown
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_commandMarker == (Object)null)
		{
			_commandMarker = new GameObject("Hati command target");
			_commandMarker.AddComponent<HatiNavigationGoal>();
		}
		_commandMarker.transform.position = zdo.GetVec3(mode switch
		{
			DogMode.Stay => "aifriend.dog.stayPoint", 
			DogMode.Home => "aifriend.dog.home", 
			_ => "aifriend.dog.awayPoint", 
		}, ((Component)this).transform.position);
		return _commandMarker;
	}

	private GameObject GetKennelMarker(ZDO zdo)
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Expected O, but got Unknown
		if ((Object)(object)_kennelMarker == (Object)null)
		{
			_kennelMarker = new GameObject("Hati kennel target");
			_kennelMarker.AddComponent<HatiNavigationGoal>();
		}
		_kennelMarker.transform.position = zdo.GetVec3("aifriend.dog.kennel", ((Component)this).transform.position);
		return _kennelMarker;
	}

	public bool RequestUnload(Player owner)
	{
		if ((Object)(object)owner == (Object)null || owner.GetPlayerID() != OwnerId || LifeState != DogLifeState.Alive || _backpack == null || !_backpack.HasItems || !CompanionDogOrders.CanControl(GetZdo(), owner))
		{
			return false;
		}
		_unloadRequested = true;
		return true;
	}

	public void EnterDowned()
	{
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = GetZdo();
		if (zdo == null || (Object)(object)_view == (Object)null || !_view.IsOwner())
		{
			return;
		}
		if (LifeState != DogLifeState.Alive)
		{
			((Character)_wolf).SetHealth(1f);
			return;
		}
		double now = (((Object)(object)ZNet.instance == (Object)null) ? double.NaN : ZNet.instance.GetTimeSeconds());
		ClearFoodRegeneration();
		CancelForaging();
		ResetRest();
		ResetIdlePose();
		FinishHuntLoot();
		FinishSerpentRetrieval();
		_unloadRequested = false;
		ClearUnloadMarker();
		Vector3 position = ((Component)this).transform.position;
		if (!IsAboard && ((Character)_wolf).IsSwimming() && (Object)(object)ZoneSystem.instance != (Object)null)
		{
			position.y = Mathf.Max(position.y, ZoneSystem.instance.m_waterLevel + 0.4f);
		}
		zdo.Set("aifriend.dog.downPoint", position);
		zdo.SetPosition(position);
		zdo.Set("aifriend.dog.life", 1);
		zdo.Set("aifriend.dog.catchupAt", 0L);
		HatiDawnRecovery.Schedule(zdo, EnvMan.instance, now);
		((Character)_wolf).SetHealth(1f);
		ApplyLifeState(DogLifeState.Downed);
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer != (Object)null && localPlayer.GetPlayerID() == OwnerId)
		{
			HatiFeedback.Show(localPlayer, "Хати ранен. До рассвета можно поднять мясом или рыбой.");
		}
	}

	internal void BeginWaitingDawn(int returnDay, Vector3 home)
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = GetZdo();
		if (zdo != null && !((Object)(object)_view == (Object)null) && _view.IsOwner())
		{
			ClearFoodRegeneration();
			ResetRest();
			zdo.Set("aifriend.dog.life", 2);
			zdo.Set("aifriend.dog.returnDay", returnDay);
			if (_passenger != null)
			{
				_passenger.Release(null, moveToOwner: false);
			}
			((Component)this).transform.position = home;
			zdo.SetPosition(home);
			zdo.Set("aifriend.dog.downPoint", home);
			ApplyLifeState(DogLifeState.WaitingDawn);
		}
	}

	internal void ReturnAtDawn(Vector3 home)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = GetZdo();
		if (zdo != null && !((Object)(object)_view == (Object)null) && _view.IsOwner())
		{
			_downedMotion.Release();
			((Component)this).transform.position = home;
			Rigidbody component = ((Component)this).GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.position = home;
			}
			zdo.SetPosition(home);
			zdo.Set("aifriend.dog.life", 0);
			HatiDawnRecovery.Clear(zdo);
			zdo.Set("aifriend.dog.mode", 0);
			zdo.Set("aifriend.dog.catchupAt", (long)(ZNet.instance.GetTimeSeconds() * 1000.0) + 60000);
			((Character)_wolf).SetHealth(Mathf.Max(15f, ((Character)_wolf).GetMaxHealth() * 0.5f));
			ApplyLifeState(DogLifeState.Alive);
		}
	}

	private void Update()
	{
		//IL_0d9b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0da0: Unknown result type (might be due to invalid IL or missing references)
		//IL_033a: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_0784: Unknown result type (might be due to invalid IL or missing references)
		//IL_0789: Unknown result type (might be due to invalid IL or missing references)
		//IL_0766: Unknown result type (might be due to invalid IL or missing references)
		//IL_076b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0748: Unknown result type (might be due to invalid IL or missing references)
		//IL_074d: Unknown result type (might be due to invalid IL or missing references)
		//IL_072a: Unknown result type (might be due to invalid IL or missing references)
		//IL_072f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0712: Unknown result type (might be due to invalid IL or missing references)
		//IL_081c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0871: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_08c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_09d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b48: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b4d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b08: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b0d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ac6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0acb: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_view != (Object)null && _view.IsValid())
		{
			Player val = ((OwnerId == 0) ? null : Player.GetPlayer(OwnerId));
			if (_view.IsOwner() && (Object)(object)val != (Object)null)
			{
				GetZdo().Set("aifriend.dog.waitOutside", ((Character)val).InInterior());
			}
			ApplyLifeState(LifeState);
			if (HatiDungeonShelter.IsProtected(this))
			{
				ClearNativeCombatTarget();
				CancelForaging();
				ResetRest();
				ResetIdlePose();
				return;
			}
		}
		WatchOwnerAim();
		if (Time.time < _nextUpdate)
		{
			return;
		}
		_nextUpdate = Time.time + ((((Object)(object)_ai != (Object)null && ((BaseAI)_ai).HaveTarget()) || Time.time < fastDecisionUntil || Mode == DogMode.Fish || Mode == DogMode.Gather) ? 0.25f : 1f);
		if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner() || (Object)(object)_wolf == (Object)null || (Object)(object)_ai == (Object)null || ((Character)_wolf).IsDead())
		{
			ResetRest();
			ResetIdlePose();
			CancelForaging();
			return;
		}
		Player val2 = ((OwnerId == 0) ? null : Player.GetPlayer(OwnerId));
		HatiPersonality component = ((Component)this).GetComponent<HatiPersonality>();
		if ((Object)(object)component != (Object)null)
		{
			component.ObserveOwner(val2);
		}
		if (LifeState != DogLifeState.Alive)
		{
			ResetRest();
			ClearFoodRegeneration();
			CancelForaging();
			return;
		}
		if ((Object)(object)val2 != (Object)null && val2.GetPlayerID() == OwnerId && !((Character)val2).IsDead())
		{
			MatchOwnerHealth(val2);
		}
		UpdateFoodHealing((Object)(object)val2 != (Object)null && val2.IsSleeping());
		if ((Object)(object)val2 == (Object)null || val2.GetPlayerID() != OwnerId || ((Character)val2).IsDead())
		{
			CancelForaging();
			UpdateRestHealing();
			return;
		}
		if (((Character)val2).IsDead() || ((Character)val2).IsTeleporting() || (((Character)val2).InCutscene() && !val2.IsSleeping()))
		{
			CancelForaging();
			ResetRest();
			ResetIdlePose();
			_foodRegen.Reset();
			return;
		}
		if ((Object)(object)component != (Object)null && (Mode == DogMode.Gather || Mode == DogMode.Hunt || Mode == DogMode.Fish) && _backpack != null && _backpack.IsFull && !((BaseAI)_ai).HaveTarget() && !BaseAI.HaveEnemyInRange((Character)(object)_wolf, ((Component)val2).transform.position, 20f))
		{
			component.Explain((_backpack.Weight >= 150f) ? "Карман достиг 150 веса. Забери часть добычи через взаимодействие — продолжу сбор." : "Все 15 ячеек кармана заполнены. Освободи место через взаимодействие — продолжу сбор.");
		}
		CompanionDogCombat component2 = ((Component)this).GetComponent<CompanionDogCombat>();
		Character val3 = (((Object)(object)component2 == (Object)null) ? null : component2.SelectPriorityThreat(val2));
		if (val2.IsSleeping() && (Object)(object)val3 == (Object)null)
		{
			CancelForaging();
			_restTimer.Reset();
			if ((Object)(object)((BaseAI)_ai).GetTargetCreature() == (Object)null && (Object)(object)BaseAI.FindClosestEnemy((Character)(object)_wolf, ((Component)this).transform.position, 15f) == (Object)null)
			{
				_ai.SetFollowTarget((GameObject)null);
				((BaseAI)_ai).ResetPatrolPoint();
				((BaseAI)_ai).StopMoving();
				((Character)_wolf).SetRun(false);
			}
			UpdateRestHealing(sleeping: true);
			return;
		}
		_sleepRestTimer.Reset();
		HatiMount component3 = ((Component)this).GetComponent<HatiMount>();
		if ((Object)(object)component3 != (Object)null && component3.IsRidden)
		{
			CancelForaging();
			ClearNativeCombatTarget();
			_ai.SetFollowTarget((GameObject)null);
			UpdateRestHealing();
			return;
		}
		CompanionDogStealth.Update(this, val2, GetZdo());
		CompanionDogLifecycle companionDogLifecycle = (((Object)(object)Plugin.Instance == (Object)null) ? null : ((Component)Plugin.Instance).GetComponent<CompanionDogLifecycle>());
		if ((Object)(object)companionDogLifecycle != (Object)null && companionDogLifecycle.IsOwnerRespawnPending(val2))
		{
			ResetRest();
			ResetIdlePose();
			CancelForaging();
			return;
		}
		UpdateRestHealing();
		if (!((Character)_wolf).IsTamed())
		{
			((Character)_wolf).SetTamed(true);
		}
		_ai.m_maxChaseDistance = ((Mode == DogMode.Hunt && (Object)(object)GetHuntTarget(val2) != (Object)null) ? 10000f : ((Mode == DogMode.Guard) ? 25f : 15f));
		CompanionDogTravel component4 = ((Component)this).GetComponent<CompanionDogTravel>();
		bool flag = ((Character)_wolf).GetHealthPercentage() < 0.2f;
		if (flag)
		{
			FinishHuntLoot();
		}
		if ((Object)(object)val3 == (Object)null && _huntLootActive && !flag)
		{
			ClearNativeCombatTarget();
			ResetRest();
			ResetIdlePose();
			if (UpdateHuntLoot(val2))
			{
				CancelForaging();
				return;
			}
		}
		if ((Object)(object)val3 == (Object)null)
		{
			if (UpdateSerpentRetrieval(val2))
			{
				CancelForaging();
				return;
			}
			if ((Object)(object)component4 != (Object)null && component4.UpdateTravel(val2, _passenger))
			{
				CancelForaging();
				return;
			}
			bool flag2 = Mode == DogMode.Hunt && (Object)(object)GetHuntTarget(val2) != (Object)null;
			if (!flag && !flag2 && (Object)(object)((BaseAI)_ai).GetTargetCreature() == (Object)null && UpdateUnload(val2))
			{
				CancelForaging();
				return;
			}
			ClearUnloadMarker();
		}
		else
		{
			ClearUnloadMarker();
			ResetRest();
			ResetIdlePose();
		}
		DogMode mode = Mode;
		bool flag3 = DogCareRules.RetreatToOwner(mode, ((Character)_wolf).GetHealthPercentage());
		Vector3 val4 = (Vector3)(mode switch
		{
			DogMode.Away => GetZdo().GetVec3("aifriend.dog.awayPoint", ((Component)this).transform.position), 
			DogMode.Home => GetZdo().GetVec3("aifriend.dog.home", ((Component)this).transform.position), 
			DogMode.Guard => GetZdo().GetVec3("aifriend.dog.guardPoint", ((Component)this).transform.position), 
			DogMode.Kennel => GetZdo().GetVec3("aifriend.dog.kennel", ((Component)this).transform.position), 
			DogMode.Stay => GetZdo().GetVec3("aifriend.dog.stayPoint", ((Component)this).transform.position), 
			_ => ((Component)val2).transform.position, 
		});
		Character val5 = (((Object)(object)val3 != (Object)null) ? val3 : (flag ? null : ((Mode == DogMode.Hunt) ? GetHuntTarget(val2) : null)));
		if ((Object)(object)val3 != (Object)null)
		{
			flag3 = false;
		}
		if ((Object)(object)val5 == (Object)null && flag && (Object)(object)component2 != (Object)null)
		{
			val5 = component2.SelectTarget(((Component)val2).transform.position, 5.01f);
			if ((Object)(object)val5 != (Object)null)
			{
				flag3 = false;
			}
		}
		if ((Object)(object)val5 == (Object)null && !flag && (Object)(object)component2 != (Object)null)
		{
			val5 = component2.SelectTarget(((Component)this).transform.position, 5.01f);
			if ((Object)(object)val5 == (Object)null && mode == DogMode.Stay)
			{
				val5 = component2.SelectOwnerThreat(val2);
			}
			if ((Object)(object)val5 == (Object)null)
			{
				Vector3 center = ((mode == DogMode.Stay) ? ((Component)this).transform.position : val4);
				float range;
				switch (mode)
				{
				default:
					range = 20f;
					break;
				case DogMode.Kennel:
				case DogMode.Guard:
					range = 25f;
					break;
				case DogMode.Stay:
					range = 5.01f;
					break;
				}
				val5 = component2.SelectTarget(center, range);
			}
		}
		if ((Object)(object)val5 != (Object)null && !CompanionDogStealth.CanEngage(this, val5))
		{
			val5 = null;
		}
		if ((Object)(object)val5 != (Object)null)
		{
			ResetIdlePose();
			_ai.m_sleeping = false;
			GetZdo().Set(ZDOVars.s_sleeping, false);
			if ((Object)(object)val3 != (Object)null)
			{
				_ai.m_maxChaseDistance = 200f;
			}
		}
		if (flag)
		{
			FinishHuntLoot();
		}
		if ((Object)(object)val5 == (Object)null && UpdateHuntLoot(val2))
		{
			CancelForaging();
			return;
		}
		ItemDrop val6 = null;
		if (_backpack != null)
		{
			val6 = _backpack.FindGroundLoot(val2, ((Component)this).transform.position, (Mode == DogMode.Gather || Mode == DogMode.Hunt) && !flag3 && (Object)(object)val5 == (Object)null);
			if (UpdateForaging(val2, val5, flag3, (Object)(object)val6 != (Object)null))
			{
				return;
			}
		}
		object obj;
		if (!((Object)(object)val3 != (Object)null) || !((Object)(object)val5 != (Object)null))
		{
			if (!flag3)
			{
				if (!flag || !((Object)(object)val5 != (Object)null))
				{
					switch (mode)
					{
					default:
						obj = (((Object)(object)val5 != (Object)null && mode == DogMode.Hunt && (Object)(object)val5 == (Object)(object)_huntTarget) ? ((Component)val5).gameObject : (((Object)(object)val6 != (Object)null) ? ((Component)val6).gameObject : ((Component)val2).gameObject));
						break;
					case DogMode.Home:
					case DogMode.Away:
						obj = (((Object)(object)val5 != (Object)null) ? ((Component)val5).gameObject : ((Vector3.Distance(((Component)this).transform.position, val4) > 2f) ? GetCommandMarker(GetZdo(), mode) : null));
						break;
					case DogMode.Kennel:
						obj = (((Object)(object)val5 != (Object)null) ? ((Component)val5).gameObject : ((Vector3.Distance(((Component)this).transform.position, val4) > 2f) ? GetKennelMarker(GetZdo()) : null));
						break;
					case DogMode.Stay:
						obj = (((Object)(object)val5 != (Object)null) ? ((Component)val5).gameObject : ((Vector3.Distance(((Component)this).transform.position, val4) > 2f) ? GetCommandMarker(GetZdo(), mode) : null));
						break;
					case DogMode.Guard:
						obj = null;
						break;
					}
				}
				else
				{
					obj = ((Component)val5).gameObject;
				}
			}
			else
			{
				obj = ((Component)val2).gameObject;
			}
		}
		else
		{
			obj = ((Component)val5).gameObject;
		}
		GameObject val7 = (GameObject)obj;
		if ((Object)(object)component != (Object)null)
		{
			if (component.TryActivity(val2, val5, flag3 || (Object)(object)val6 != (Object)null || _huntLootActive || _seaRetrieval || _unloadRequested))
			{
				return;
			}
			component.CheckBlockedOrder();
		}
		if ((Object)(object)_ai.GetFollowTarget() != (Object)(object)val7)
		{
			_ai.SetFollowTarget(val7);
			if ((Object)(object)val7 != (Object)null)
			{
				((BaseAI)_ai).ResetPatrolPoint();
			}
			else if (HatiPointWaiting.IsPointMode(mode))
			{
				((BaseAI)_ai).ResetPatrolPoint();
			}
			else
			{
				((BaseAI)_ai).SetPatrolPoint();
			}
		}
		if ((Object)(object)val5 == (Object)null && (Object)(object)val7 == (Object)null)
		{
			HatiPointWaiting.TryHold((BaseAI)(object)_ai);
		}
		if ((flag && (Object)(object)val5 == (Object)null) || ((mode == DogMode.Stay || mode == DogMode.Kennel || mode == DogMode.Home || mode == DogMode.Away) && (Object)(object)val5 == (Object)null))
		{
			ClearNativeCombatTarget();
		}
		if ((Object)(object)val5 == (Object)null || val5.IsDead())
		{
			return;
		}
		if (SetTargetMethod != null)
		{
			try
			{
				((BaseAI)_ai).Alert();
				SetTargetMethod.Invoke(_ai, new object[1] { val5 });
			}
			catch (Exception ex)
			{
				if (!_targetErrorLogged && (Object)(object)Plugin.Instance != (Object)null)
				{
					Plugin.Instance.LogWarning("Dog guard failed: " + ex.Message);
				}
				_targetErrorLogged = true;
			}
		}
		if (Time.time >= _nextWarning && Vector3.Distance(((Component)val2).transform.position, val4) < 20f)
		{
			_nextWarning = Time.time + 40f;
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				Plugin.Instance.DogSay(this, "Чую врага. Держись рядом.");
			}
		}
	}

	internal void ResumeAfterRide()
	{
		if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner() || LifeState != DogLifeState.Alive)
		{
			return;
		}
		HatiMount component = ((Component)this).GetComponent<HatiMount>();
		if (!((Object)(object)component != (Object)null) || !component.IsRidden)
		{
			ResetIdlePose();
			ResetRest();
			_ai.m_sleeping = false;
			GetZdo().Set(ZDOVars.s_sleeping, false);
			if ((Object)(object)component != (Object)null)
			{
				component.WakeForRide();
			}
			fastDecisionUntil = Time.time + 2f;
			_nextUpdate = 0f;
		}
	}

	private void ResetRest()
	{
		_restTimer.Reset();
		_sleepRestTimer.Reset();
		_restMotion.Reset();
	}

	internal void NotifyRestDamage()
	{
		ResetRest();
		ResetIdlePose();
	}

	private void ResetIdlePose()
	{
		_idlePoseTimer.Reset();
		_idlePose = DogRestPose.Standing;
		HatiRestPresentation component = ((Component)this).GetComponent<HatiRestPresentation>();
		if ((Object)(object)component != (Object)null)
		{
			component.SetPose(DogRestPose.Standing);
		}
	}

	internal void HoldDowned()
	{
		if (!HatiDungeonShelter.IsProtected(this) && (Object)(object)_wolf != (Object)null && (Object)(object)_ai != (Object)null)
		{
			_downedMotion.Apply(this, (Character)(object)_wolf, _ai);
		}
	}

	internal void LogSleepDamage(HitData hit, float before)
	{
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if (!((Object)(object)localPlayer == (Object)null) && localPlayer.GetPlayerID() == OwnerId && localPlayer.IsSleeping() && !((Object)(object)Plugin.Instance == (Object)null) && (!(Time.time < _nextSleepDamageLog) || !(((Character)_wolf).GetHealth() > 0f)))
		{
			_nextSleepDamageLog = Time.time + 10f;
			Character val = ((hit == null) ? null : hit.GetAttacker());
			Plugin.Instance.LogWarning("Hati damage during owner sleep: HP " + before.ToString("0.0") + " -> " + ((Character)_wolf).GetHealth().ToString("0.0") + "; type=" + ((hit == null) ? "unknown" : ((object)hit.m_hitType).ToString()) + "; attacker=" + (((Object)(object)val == (Object)null) ? "unknown" : ((Object)((Component)val).gameObject).name));
		}
	}

	private void ClearFoodRegeneration()
	{
		_foodRegen.Reset();
		ZDO zdo = GetZdo();
		if (zdo != null && (Object)(object)_view != (Object)null && _view.IsOwner() && zdo.GetInt("aifriend.dog.foodTier", 0) != 0)
		{
			zdo.Set("aifriend.dog.foodTier", 0);
		}
	}

	private static long FoodClock()
	{
		return (long)((((Object)(object)ZNet.instance == (Object)null) ? ((double)Time.time) : ZNet.instance.GetTimeSeconds()) * 1000.0);
	}

	private void UpdateFoodHealing(bool sleeping = false)
	{
		if (LifeState != DogLifeState.Alive || ((Character)_wolf).GetHealth() >= ((Character)_wolf).GetMaxHealth())
		{
			ClearFoodRegeneration();
			return;
		}
		float num = _foodRegen.Update(FoodTier, alive: true, full: false, FoodClock(), sleeping);
		if (num > 0f)
		{
			((Character)_wolf).Heal(num, false);
		}
		if (((Character)_wolf).GetHealth() >= ((Character)_wolf).GetMaxHealth())
		{
			ClearFoodRegeneration();
		}
	}

	private void UpdateRestHealing(bool sleeping = false)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: 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_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0241: Unknown result type (might be due to invalid IL or missing references)
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d8: Unknown result type (might be due to invalid IL or missing references)
		bool flag = HatiRestSite.AtMarkedSite(GetZdo(), ((Component)this).transform.position) || HatiBaseArea.Contains(GetZdo(), ((Component)this).transform.position);
		bool flag2 = _restMotion.Update(((Component)this).transform.position, Time.time);
		SEMan sEMan = ((Character)_wolf).GetSEMan();
		bool flag3 = sEMan != null && (sEMan.HaveStatusEffect(SEMan.s_statusEffectPoison) || sEMan.HaveStatusEffect(SEMan.s_statusEffectBurning) || sEMan.HaveStatusEffect(SEMan.s_statusEffectSmoked) || sEMan.HaveStatusEffect(SEMan.s_statusEffectSpirit));
		bool flag4 = !flag3 && !((Character)_wolf).IsSwimming() && (((Character)_wolf).IsOnGround() || IsAboard || flag) && !((Character)_wolf).InAttack() && ((Character)_wolf).GetTimeSinceLastAttack() >= 1f && ((Object)(object)((BaseAI)_ai).GetTargetCreature() == (Object)null || ((BaseAI)_ai).GetTargetCreature().IsDead()) && !_seaRetrieval && !_huntLootActive && (Object)(object)_unloadMarker == (Object)null && (Object)(object)BaseAI.FindClosestEnemy((Character)(object)_wolf, ((Component)this).transform.position, 15f) == (Object)null;
		DogRestTimer dogRestTimer = (sleeping ? _sleepRestTimer : _restTimer);
		long now = (long)(((sleeping && (Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : ((double)Time.time)) * 1000.0);
		ZDO zdo = GetZdo();
		Vector3 val = ((Mode == DogMode.Stay) ? zdo.GetVec3("aifriend.dog.stayPoint", ((Component)this).transform.position) : ((Mode == DogMode.Kennel) ? zdo.GetVec3("aifriend.dog.kennel", ((Component)this).transform.position) : zdo.GetVec3("aifriend.dog.home", ((Component)this).transform.position)));
		HatiPersonality component = ((Component)this).GetComponent<HatiPersonality>();
		DogIdlePoseTimer idlePoseTimer;
		int calmAtDestination;
		if ((Object)(object)component == (Object)null || !component.RestingAtFire)
		{
			idlePoseTimer = _idlePoseTimer;
			if (flag4 && (IsAboard || flag2))
			{
				Vector3 moveDir = ((Character)_wolf).GetMoveDir();
				if (((Vector3)(ref moveDir)).sqrMagnitude < 0.01f)
				{
					calmAtDestination = ((Vector3.Distance(((Component)this).transform.position, val) <= 2.5f) ? 1 : 0);
					goto IL_0275;
				}
			}
			calmAtDestination = 0;
			goto IL_0275;
		}
		goto IL_02d2;
		IL_0275:
		DogRestPose dogRestPose = idlePoseTimer.Update((byte)calmAtDestination != 0, Mode, (long)((double)Time.time * 1000.0));
		if (dogRestPose != _idlePose)
		{
			_idlePose = dogRestPose;
			HatiRestPresentation component2 = ((Component)this).GetComponent<HatiRestPresentation>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.SetPose(dogRestPose);
			}
		}
		goto IL_02d2;
		IL_02d2:
		float num = dogRestTimer.Update(flag4 && ((Character)_wolf).GetHealth() < ((Character)_wolf).GetMaxHealth(), now, ((Character)_wolf).GetMaxHealth(), flag, sleeping, !IsAboard && !flag2);
		if (num > 0f)
		{
			((Character)_wolf).Heal(num, true);
		}
		if (!flag4 && ((Character)_wolf).GetHealth() < ((Character)_wolf).GetMaxHealth() && Time.time >= _nextRestDiagnostic)
		{
			_nextRestDiagnostic = Time.time + 30f;
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				Plugin.Instance.LogWarning("Hati rest blocked: still=" + flag2 + ", grounded=" + ((Character)_wolf).IsOnGround() + ", swimming=" + ((Character)_wolf).IsSwimming() + ", harmful=" + flag3 + ", attacking=" + ((Character)_wolf).InAttack() + ", sinceAttack=" + ((Character)_wolf).GetTimeSinceLastAttack() + ", combatTarget=" + ((Object)(object)((BaseAI)_ai).GetTargetCreature() != (Object)null) + ", seaRetrieval=" + _seaRetrieval + ", huntLoot=" + _huntLootActive + ", unloading=" + ((Object)(object)_unloadMarker != (Object)null) + ", nearbyEnemy=" + ((Object)(object)BaseAI.FindClosestEnemy((Character)(object)_wolf, ((Component)this).transform.position, 15f) != (Object)null));
			}
		}
	}

	private void ClearHuntDeadline()
	{
		ZDO zdo = GetZdo();
		if (zdo != null && _view.IsOwner())
		{
			zdo.Set("aifriend.dog.huntUntil", 0L);
		}
	}

	internal void ClearNativeCombatTarget()
	{
		if (!((Object)(object)_ai == (Object)null))
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(MonsterAI), "m_targetCreature");
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(MonsterAI), "m_targetStatic");
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(_ai, null);
			}
			if (fieldInfo2 != null)
			{
				fieldInfo2.SetValue(_ai, null);
			}
		}
	}

	internal void CancelCombat()
	{
		_huntTarget = null;
		ClearHuntDeadline();
		FinishHuntLoot();
		FieldInfo fieldInfo = AccessTools.Field(typeof(MonsterAI), "m_targetCreature");
		FieldInfo fieldInfo2 = AccessTools.Field(typeof(MonsterAI), "m_targetStatic");
		if ((Object)(object)_ai != (Object)null)
		{
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(_ai, null);
			}
			if (fieldInfo2 != null)
			{
				fieldInfo2.SetValue(_ai, null);
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && IsFollowing)
			{
				_ai.SetFollowTarget(((Component)localPlayer).gameObject);
			}
		}
	}

	internal bool IsOrderedPrey(Character target)
	{
		return Mode == DogMode.Hunt && (Object)(object)target == (Object)(object)_huntTarget && Time.time < _huntUntil;
	}

	private void MatchOwnerHealth(Player owner)
	{
		float health = CompanionDogProgression.Observe(GetZdo(), owner).Health;
		float maxHealth = ((Character)_wolf).GetMaxHealth();
		if (!(Mathf.Abs(maxHealth - health) < 0.01f))
		{
			float num = ((maxHealth > 0f) ? Mathf.Clamp01(((Character)_wolf).GetHealth() / maxHealth) : 1f);
			((Character)_wolf).SetMaxHealth(health);
			((Character)_wolf).SetHealth(Mathf.Max(1f, health * num));
		}
	}

	public void MarkPrey(Player owner, Character prey)
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)owner == (Object)null) && owner.GetPlayerID() == OwnerId && !((Object)(object)_view == (Object)null) && _view.IsOwner() && Mode == DogMode.Hunt && !((Object)(object)prey == (Object)null) && !prey.IsDead() && !prey.IsTamed() && IsSmallPrey(prey) && !(Vector3.Distance(((Component)owner).transform.position, ((Component)prey).transform.position) > 200f))
		{
			bool flag = (Object)(object)_huntTarget != (Object)(object)prey;
			if (flag)
			{
				FinishHuntLoot();
			}
			_huntTarget = prey;
			_huntUntil = Time.time + 120f;
			ZDO zdo = GetZdo();
			if (zdo != null && (Object)(object)ZNet.instance != (Object)null)
			{
				zdo.Set("aifriend.dog.huntUntil", (long)(ZNet.instance.GetTimeSeconds() * 1000.0) + 120000);
			}
			if (flag && (Object)(object)Plugin.Instance != (Object)null)
			{
				Plugin.Instance.DogSay(this, "След взят.");
			}
		}
	}

	public bool TakeAimedPrey(Player owner, Character prey)
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)owner == (Object)null || (Object)(object)prey == (Object)null || (Object)(object)_wolf == (Object)null || owner.GetPlayerID() != OwnerId || prey is Player || prey.IsDead() || prey.IsTamed() || (!IsSmallPrey(prey) && !BaseAI.IsEnemy((Character)(object)_wolf, prey)) || Vector3.Distance(((Component)owner).transform.position, ((Component)prey).transform.position) > 200f || !SetMode(owner, DogMode.Hunt))
		{
			return false;
		}
		_huntTarget = prey;
		_huntUntil = Time.time + 120f;
		ZDO zdo = GetZdo();
		if (zdo != null && (Object)(object)ZNet.instance != (Object)null)
		{
			zdo.Set("aifriend.dog.huntUntil", (long)(ZNet.instance.GetTimeSeconds() * 1000.0) + 120000);
		}
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.DogSay(this, "Вижу цель. Беру след!");
		}
		return true;
	}

	public static Character FindAimedPrey(Player owner)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: 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_0102: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)owner == (Object)null)
		{
			return null;
		}
		Vector3 eyePoint = ((Character)owner).GetEyePoint();
		RaycastHit[] array = Physics.RaycastAll(eyePoint, ((Humanoid)owner).GetAimDir(eyePoint), 200f);
		Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
		for (int num = 0; num < array.Length; num++)
		{
			Collider collider = ((RaycastHit)(ref array[num])).collider;
			if ((Object)(object)collider == (Object)null || collider.isTrigger)
			{
				continue;
			}
			Character componentInParent = ((Component)collider).GetComponentInParent<Character>();
			if (!((Object)(object)componentInParent == (Object)(object)owner) && (!((Object)(object)componentInParent != (Object)null) || !((Object)(object)((Component)componentInParent).GetComponent<CompanionDog>() != (Object)null)))
			{
				if ((Object)(object)componentInParent != (Object)null && !(componentInParent is Player) && !componentInParent.IsTamed() && !componentInParent.IsDead() && Vector3.Distance(((Component)owner).transform.position, ((Component)componentInParent).transform.position) <= 200f)
				{
					return componentInParent;
				}
				return null;
			}
		}
		return null;
	}

	internal void OnHuntTargetDied(Character prey)
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)_view == (Object)null) && _view.IsOwner() && Mode == DogMode.Hunt && !((Object)(object)prey == (Object)null) && !((Object)(object)prey != (Object)(object)_huntTarget) && LifeState == DogLifeState.Alive && !((Object)((Component)prey).gameObject).name.StartsWith("Serpent", StringComparison.Ordinal))
		{
			_huntDeathPoint = ((Component)prey).transform.position;
			_huntTarget = null;
			ClearHuntDeadline();
			OnKilledPrey(_huntDeathPoint);
		}
	}

	internal void OnKilledPrey(Vector3 point)
	{
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner() || LifeState != DogLifeState.Alive || !IsFollowing || _backpack == null || !_backpack.IsReadable)
		{
			return;
		}
		HatiMount component = ((Component)this).GetComponent<HatiMount>();
		if (!IsAboard && (!((Object)(object)component != (Object)null) || (!component.IsRidden && !component.WaitingOutside)))
		{
			if ((Object)(object)_huntTarget != (Object)null && (_huntTarget.IsDead() || _huntTarget.GetHealth() <= 0f))
			{
				_huntTarget = null;
				ClearHuntDeadline();
			}
			_huntDeathPoint = point;
			_huntLootMode = Mode;
			_huntLootStarted = Time.time;
			_huntLastLoot = Time.time;
			_huntLootActive = true;
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				Plugin.Instance.DogSay(this, "Добыча наша. Подожди, соберу что осталось.");
			}
		}
	}

	private bool UpdateHuntLoot(Player owner)
	{
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: 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_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Expected O, but got Unknown
		if (!_huntLootActive)
		{
			return false;
		}
		if (Mode != _huntLootMode || _backpack == null || !_backpack.IsReadable || Time.time - _huntLootStarted > 35f || _backpack.Items.GetTotalWeight() >= 150f)
		{
			FinishHuntLoot();
			return false;
		}
		ItemDrop val = _backpack.FindHuntLoot(_huntDeathPoint, ((Component)this).transform.position);
		Vector3 val2;
		if ((Object)(object)val != (Object)null)
		{
			_huntLastLoot = Time.time;
			val2 = ((Component)val).transform.position - ((Component)this).transform.position;
			if (((Vector3)(ref val2)).sqrMagnitude < 4f)
			{
				_backpack.CollectHuntLoot(val);
			}
			else
			{
				_ai.SetFollowTarget(((Component)val).gameObject);
				((BaseAI)_ai).ResetPatrolPoint();
			}
			return true;
		}
		if (Time.time - _huntLootStarted >= 12f && Time.time - _huntLastLoot >= 4f)
		{
			FinishHuntLoot();
			return false;
		}
		if ((Object)(object)_huntLootMarker == (Object)null)
		{
			_huntLootMarker = new GameObject("Hati hunt loot point");
			_huntLootMarker.AddComponent<HatiNavigationGoal>();
		}
		_huntLootMarker.transform.position = _huntDeathPoint;
		val2 = ((Component)this).transform.position - _huntDeathPoint;
		if (((Vector3)(ref val2)).sqrMagnitude > 4f)
		{
			_ai.SetFollowTarget(_huntLootMarker);
			((BaseAI)_ai).ResetPatrolPoint();
		}
		else
		{
			_ai.SetFollowTarget((GameObject)null);
			((BaseAI)_ai).ResetPatrolPoint();
			((BaseAI)_ai).StopMoving();
		}
		return true;
	}

	private void FinishHuntLoot()
	{
		_huntLootActive = false;
		if ((Object)(object)_huntLootMarker != (Object)null)
		{
			Object.Destroy((Object)(object)_huntLootMarker);
			_huntLootMarker = null;
		}
	}

	private Character GetHuntTarget(Player owner)
	{
		if ((Object)(object)_huntTarget == (Object)null || _huntTarget.IsDead() || Time.time > _huntUntil || ((Character)_wolf).GetHealthPercentage() < 0.2f)
		{
			_huntTarget = null;
			ClearHuntDeadline();
			return null;
		}
		return _huntTarget;
	}

	private void WatchOwnerAim()
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Invalid comparison between Unknown and I4
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		if (Mode != DogMode.Hunt || !Input.GetMouseButtonDown(0))
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || localPlayer.GetPlayerID() != OwnerId)
		{
			ResetRest();
			ResetIdlePose();
			CancelForaging();
			return;
		}
		ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon();
		if (currentWeapon == null || currentWeapon.m_shared == null || (int)currentWeapon.m_shared.m_itemType != 4)
		{
			return;
		}
		Vector3 eyePoint = ((Character)localPlayer).GetEyePoint();
		Vector3 aimDir = ((Humanoid)localPlayer).GetAimDir(eyePoint);
		RaycastHit[] array = Physics.RaycastAll(eyePoint, aimDir, 200f);
		Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
		for (int num = 0; num < array.Length; num++)
		{
			RaycastHit val = array[num];
			if ((Object)(object)((RaycastHit)(ref val)).collider == (Object)null)
			{
				continue;
			}
			Character componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>();
			if (!((Object)(object)componentInParent == (Object)(object)localPlayer) && !((Object)(object)componentInParent == (Object)(object)_wolf))
			{
				if ((Object)(object)componentInParent != (Object)null)
				{
					MarkPrey(localPlayer, componentInParent);
				}
				break;
			}
		}
	}

	internal static bool IsSmallPrey(Character candidate)
	{
		string name = ((Object)((Component)candidate).gameObject).name;
		return name.StartsWith("Deer", StringComparison.Ordinal) || name.StartsWith("Boar", StringComparison.Ordinal) || name.StartsWith("Neck", StringComparison.Ordinal) || name.StartsWith("Hare", StringComparison.Ordinal);
	}

	private void FixedUpdate()
	{
		if (HatiDungeonShelter.IsProtected(this))
		{
			ApplyLifeState(LifeState);
			return;
		}
		HoldDowned();
		if (_passenger != null)
		{
			if ((Object)(object)_view == (Object)null || !_view.IsValid() || !_view.IsOwner())
			{
				_passenger.Release(null, moveToOwner: false);
			}
			else
			{
				_passenger.FixedUpdate();
			}
		}
	}

	private void OnDisable()
	{
		_shelterMotion.Release();
		_downedMotion.Release();
		FinishHuntLoot();
		FinishSerpentRetrieval();
		ClearUnloadMarker();
		if ((Object)(object)_kennelMarker != (Object)null)
		{
			Object.Destroy((Object)(object)_kennelMarker);
			_kennelMarker = null;
		}
		if ((Object)(object)_commandMarker != (Object)null)
		{
			Object.Destroy((Object)(object)_commandMarker);
			_commandMarker = null;
		}
		if (_passenger != null)
		{
			_passenger.Release(null, moveToOwner: false);
		}
	}

	private void OnDestroy()
	{
		_shelterMotion.Release();
		CancelForaging();
		if ((Object)(object)_wolf != (Object)null)
		{
			Humanoid wolf = _wolf;
			((Character)wolf).m_onDeath = (Action)Delegate.Remove(((Character)wolf).m_onDeath, new Action(OnDogDeath));
		}
	}

	private void OnDogDeath()
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		if (_backpack != null)
		{
			_backpack.DropAll(((Component)this).transform.position);
		}
	}

	private void ApplyLifeState(DogLifeState state)
	{
		bool flag = HatiDungeonShelter.IsProtected(this);
		if (state != DogLifeState.Alive)
		{
			HatiMount component = ((Component)this).GetComponent<HatiMount>();
			if ((Object)(object)component != (Object)null)
			{
				component.ReleaseLocalRider();
			}
		}
		if ((Object)(object)_ai != (Object)null)
		{
			((Behaviour)_ai).enabled = state == DogLifeState.Alive && (_passenger == null || !_passenger.IsAboard);
		}
		if (state != DogLifeState.Alive)
		{
			ResetIdlePose();
		}
		if (flag)
		{
			_downedMotion.Release();
			_shelterMotion.Apply((Character)(object)_wolf, _ai);
		}
		else
		{
			_shelterMotion.Release();
			HoldDowned();
		}
		bool flag2 = state == DogLifeState.WaitingDawn || flag;
		if (_hidden == flag2)
		{
			return;
		}
		_hidden = flag2;
		for (int i = 0; i < _renderers.Length; i++)
		{
			if ((Object)(object)_renderers[i] != (Object)null)
			{
				_renderers[i].enabled = !flag2 && _rendererWasEnabled[i];
			}
		}
		for (int i = 0; i < _colliders.Length; i++)
		{
			if ((Object)(object)_colliders[i] != (Object)null)
			{
				_colliders[i].enabled = !flag2 && _colliderWasEnabled[i];
			}
		}
	}

	internal ZDO GetZdo()
	{
		if ((Object)(object)_view == (Object)null)
		{
			_view = ((Component)this).GetComponent<ZNetView>();
		}
		return ((Object)(object)_view != (Object)null && _view.IsValid()) ? _view.GetZDO() : null;
	}

	private bool BoardRequested()
	{
		ZDO zdo = GetZdo();
		return zdo != null && zdo.GetBool("aifriend.dog.boardRequested", false);
	}

	internal void CancelForaging()
	{
		if (forage != null)
		{
			forage.Cancel();
		}
	}

	private bool UpdateForaging(Player owner, Character enemy, bool retreat, bool loot)
	{
		if (forage == null)
		{
			forage = new HatiForaging(this, _wolf, _ai, _view);
		}
		return forage.Tick(owner, enemy, retreat, loot);
	}

	internal float FishingDepth(float normal)
	{
		return (forage == null) ? normal : forage.SwimmingDepth(normal);
	}

	internal bool FishingPursuit(out Vector3 point)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		point = Vector3.zero;
		return forage != null && forage.PursuitPoint(out point);
	}

	public bool Revive(Player owner, ItemData offered = null)
	{
		//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)
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || zdo == null || (Object)(object)_view == (Object)null || owner.GetPlayerID() != OwnerId || LifeState != DogLifeState.Downed || Vector3.Distance(((Component)owner).transform.position, ((Component)this).transform.position) > 4f || !CompanionDogOrders.CanControl(zdo, owner))
		{
			return false;
		}
		Inventory inventory = ((Humanoid)owner).GetInventory();
		ItemData val = offered ?? FindMeatOrFish(inventory);
		if (inventory == null || val == null || !IsMeatOrFish(val) || !inventory.ContainsItem(val) || !inventory.RemoveOneItem(val))
		{
			return false;
		}
		zdo.Set("aifriend.dog.life", 0);
		HatiDawnRecovery.Clear(zdo);
		MarkNativeFed();
		zdo.Set("aifriend.dog.catchupAt", 0L);
		((Character)_wolf).SetHealth(Mathf.Max(10f, ((Character)_wolf).GetMaxHealth() * 0.35f));
		ApplyLifeState(DogLifeState.Alive);
		return true;
	}

	public bool Feed(Player owner)
	{
		return Feed(owner, FindMeatOrFish(((Object)(object)owner == (Object)null) ? null : ((Humanoid)owner).GetInventory()));
	}

	public bool Feed(Player owner, ItemData food)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		ZDO zdo = GetZdo();
		if ((Object)(object)owner == (Object)null || food == null || zdo == null || owner.GetPlayerID() != OwnerId || LifeState != DogLifeState.Alive || (Object)(object)_view == (Object)null || Vector3.Distance(((Component)owner).transform.position, ((Component)this).transform.position) > 4f || ((Character)_wolf).GetHealth() >= ((Character)_wolf).GetMaxHealth() - 1f || !IsMeatOrFish(food) || FoodTier >= 3 || !CompanionDogOrders.CanControl(zdo, owner))
		{
			return false;
		}
		Inventory inventory = ((Humanoid)owner).GetInventory();
		if (inventory == null || !inventory.ContainsItem(food) || !inventory.RemoveOneItem(food))
		{
			return false;
		}
		BeginMealHealing();
		if ((Object)(object)Plugin.Instance != (Object)null)
		{
			Plugin.Instance.DogSay(this, "Вот это кстати. Спасибо.");
		}
		return true;
	}

	private void BeginMealHealing()
	{
		int num = FoodTier + 1;
		MarkNativeFed();
		GetZdo().Set("aifriend.dog.foodTier", num);
		((Character)_wolf).Heal(_foodRegen.Begin(num, FoodClock()), true);
		if (((Character)_wolf).GetHealth() >= ((Character)_wolf).GetMaxHealth())
		{
			ClearFoodRegeneration();
		}
	}

	private void MarkNativeFed()
	{
		if ((Object)(object)ZNet.instance != (Object)null)
		{
			GetZdo().Set(ZDOVars.s_tameLastFeeding, ZNet.instance.GetTime().Ticks);
		}
	}

	private static ItemData FindMeatOrFish(Inventory inventory)
	{
		if (inventory == null)
		{
			return null;
		}
		ItemData val = null;
		List<ItemData> allItems = inventory.GetAllItems();
		for (int i = 0; i < allItems.Count; i++)
		{
			ItemData val2 = allItems[i];
			if (val2 != null && val2.m_shared != null && IsMeatOrFish(val2) && !HatiFood.IsOffering(val2) && (val == null || !(val2.m_shared.m_food >= val.m_shared.m_food)))
			{
				val = val2;
			}
		}
		return val;
	}

	internal static bool IsMeatOrFish(ItemData item)
	{
		return HatiFood.Accepts(item);
	}
}
public enum DogLifeState
{
	Alive,
	Downed,
	WaitingDawn
}
[HarmonyPatch(typeof(Character), "UpdateSwimming")]
internal static class HatiFishingDepthPatch
{
	private static void Prefix(Character __instance, out float __state)
	{
		__state = __instance.m_swimDepth;
		CompanionDog component = ((Component)__instance).GetComponent<CompanionDog>();
		if ((Object)(object)component != (Object)null)
		{
			__instance.m_swimDepth = component.FishingDepth(__state);
		}
	}

	private static void Postfix(Character __instance, float __state)
	{
		__instance.m_swimDepth = __state;
	}

	private static void Finalizer(Character __instance, float __state)
	{
		__instance.m_swimDepth = __state;
	}
}
public sealed class CompanionDogBackpack
{
	private const string InventoryKey = "aifriend.dog.backpack";

	internal const float MaxWeight = 150f;

	private const string UnloadOwnerKey = "aifriend.dog.unloadedBy";

	private readonly ZNetView _view;

	private Inventory _items;

	private readonly Collider[] _nearby = (Collider[])(object)new Collider[64];

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

	private ItemDrop _target;

	private float _nextSearch;

	private float _targetSince;

	private float _nextFindNotice;

	private bool _loaded;

	private bool _loadError;

	private byte[] _snapshot;

	internal bool IsReadable
	{
		get
		{
			EnsureLoaded();
			return !_loadError;
		}
	}

	internal float Weight
	{
		get
		{
			EnsureLoaded();
			return _items.GetTotalWeight();
		}
	}

	internal int UsedSlots
	{
		get
		{
			EnsureLoaded();
			return _items.GetAllItems().Count;
		}
	}

	private bool CanWrite
	{
		get
		{
			EnsureLoaded();
			return !_loadError && (Object)(object)_view != (Object)null && _view.IsValid() && _view.IsOwner();
		}
	}

	public Inventory Items
	{
		get
		{
			EnsureLoaded();
			return _items;
		}
	}

	internal bool HasItems
	{
		get
		{
			EnsureLoaded();
			return _items.GetAllItems().Count > 0;
		}
	}

	internal bool IsFull
	{
		get
		{
			EnsureLoaded();
			if (_loadError || _items.GetTotalWeight() >= 150f)
			{
				return true;
			}
			List<ItemData> allItems = _items.GetAllItems();
			if (allItems.Count < 15)
			{
				return false;
			}
			foreach (ItemData item in allItems)
			{
				if (item != null && item.m_shared != null && item.m_stack < item.m_shared.m_maxStackSize)
				{
					return false;
				}
			}
			return true;
		}
	}

	public CompanionDogBackpack(ZNetView view)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		_view = view;
		_items = new Inventory("Карман Хати", (Sprite)null, 5, 3);
	}

	public void EnsureLoaded()
	{
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Expected O, but got Unknown
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Expected O, but got Unknown
		if ((Object)(object)_view == (Object)null || !_view.IsValid())
		{
			return;
		}
		byte[] byteArray = _view.GetZDO().GetByteArray("aifriend.dog.backpack", (byte[])null);
		if (_loaded && Same(byteArray, _snapshot))
		{
			return;
		}
		_loaded = true;
		_snapshot = ((byteArray == null) ? null : ((byte[])byteArray.Clone()));
		Inventory val = new Inventory("Карман Хати", (Sprite)null, 5, 3);
		try
		{
			if (byteArray != null && byteArray.Length > 0)
			{
				val.Load(new ZPackage(byteArray));
			}
			Inventory items = _items;
			items.m_onChanged = (Action)Delegate.Remove(items.m_onChanged, new Action(Save));
			_items = val;
			Inventory items2 = _items;
			items2.m_onChanged = (Action)Delegate.Combine(items2.m_onChanged, new Action(Save));
			_loadError = false;
		}
		catch (Exception ex)
		{
			_loadError = true;
			if ((Object)(object)Plugin.Instance != (Object)null)
			{
				Plugin.Instance.LogWarning("Could not load Hati backpack; original data preserved: " + ex.Message);
			}
		}
	}

	private static bool Same(byte[] a, byte[] b)
	{
		if (a == null || b == null)
		{
			return a == b;
		}
		if (a.Length != b.Length)
		{
			return false;
		}
		for (int i = 0; i < a.Length; i++)
		{
			if (a[i] != b[i])
			{
				return false;
			}
		}
		return true;
	}

	public void Save()
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Expected O, but got Unknown
		if (!_loadError && !((Object)(object)_view == (Object)null) && _view.IsValid() && _view.IsOwner())
		{
			ZPackage val = new ZPackage();
			_items.Save(val);
			byte[] array = val.GetArray();
			_view.GetZDO().Set("aifriend.dog.backpack", array);
			_snapshot = (byte[])array.Clone();
		}
	}

	public int TakeAll(Player owner)
	{
		EnsureLoaded();
		if ((Object)(object)owner == (Object)null || !CanWrite || _view.GetZDO().GetLong("aifriend.dog.owner", 0L) != owner.GetPlayerID())
		{
			return 0;
		}
		int num = _items.NrOfItemsIncludingStacks();
		((Humanoid)owner).GetInventory().MoveAll(_items);
		Save();
		return num - _items.NrOfItemsIncludingStacks();
	}

	public void DropAll(Vector3 position)
	{
		//IL_0064: 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_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		EnsureLoaded();
		if (!CanWrite)
		{
			return;
		}
		List<ItemData> allItems = _items.GetAllItems();
		for (int num = allItems.Count - 1; num >= 0; num--)
		{
			ItemData val = allItems[num];
			if (val != null && !((Object)(object)val.m_dropPrefab == (Object)null))
			{
				ItemDrop val2 = ItemDrop.DropItem(val, val.m_stack, position + Random.insideUnitSphere * 0.5f, Quaternion.identity);
				if ((Object)(object)val2 != (Object)null)
				{
					ZNetView component = ((Component)val2).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner())
					{
						component.GetZDO().Set("aifriend.dog.unloadedBy", _view.GetZDO().GetLong("aifriend.dog.owner", 0L));
					}
					_items.RemoveItem(val);
				}
			}
		}
		Save();
	}

	public ItemDrop FindGroundLoot(Player owner, Vector3 dogPosition, bool active)
	{
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: 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_0207: Unknown result type (might be due to invalid IL or missing references)
		EnsureLoaded();
		if (!active || (Object)(object)owner == (Object)null || (Object)(object)_view == (Object)null || !CanWrite || _items.GetTotalWeight() >= 150f || Vector3.Distance(((Component)owner).transform.position, dogPosition) > 25f)
		{
			_target = null;
			return null;
		}
		if ((Object)(object)_target != (Object)null)
		{
			if (Time.time - _targetSince > 18f || Vector3.Distance(((Component)owner).transform.position, ((Component)_target).transform.position) > 30f)
			{
				_target = null;
			}
			else if (Vector3.Distance(dogPosition, ((Component)_target).transform.position) < 2f)
			{
				TryCollect(_target);
				_target = null;
			}
			if ((Object)(object)_target != (Object)null)
			{
				return _target;
			}
		}
		if (Time.time < _nextSearch)
		{
			return null;
		}
		_nextSearch = Time.time + 2f;
		int num = Physics.OverlapSphereNonAlloc(dogPosition, 13f, _nearby);
		float num2 = 13f;
		ItemDrop target = null;
		for (int i = 0; i < num; i++)
		{
			Collider val = _nearby[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			ItemDrop componentInParent = ((Component)val).GetComponentInParent<ItemDrop>();
			if (CanCollect(componentInParent) && FitAmount(componentInParent.m_itemData) != 0 && !(Vector3.Distance(((Component)owner).transform.position, ((Component)componentInParent).transform.position) > 25f))
			{
				float num3 = Vector3.Distance(dogPosition, ((Component)componentInParent).transform.position);
				if (num3 < num2)
				{
					num2 = num3;
					target = componentInParent;
				}
			}
		}
		_target = target;
		_targetSince = Time.time;
		if ((Object)(object)_target != (Object)null && num2 < 2f)
		{
			TryCollect(_target);
			_target = null;
		}
		return _target;
	}

	public void NoticePickables(Player owner, Vector3 dogPosition)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)owner == (Object)null || Time.time < _nextFindNotice || Vector3.Distance(((Component)owner).transform.position, dogPosition) > 18f)
		{
			return;
		}
		int num = Physics.OverlapSphereNonAlloc(dogPosition, 8f, _nearby);
		for (int i = 0; i < num; i++)
		{
			Collider val = _nearby[i];
			if (!((Object)(object)val == (Object)null))
			{
				Pickable componentInParent = ((Component)val).GetComponentInParent<Pickable>();
				if (!((Object)(object)componentInParent == (Object)null) && componentInParent.CanBePicked())
				{
					_nextFindNotice = Time.time + 30f;
					((Character)owner).Message((MessageType)1, "Хати учуял: " + componentInParent.GetHoverName(), 0, (Sprite)null, false);
					break;
				}
			}
		}
	}

	internal ItemDrop FindHuntLoot(Vector3 center, Vector3 dogPosition)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//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)
		EnsureLoaded();
		if (!CanWrite)
		{
			return null;
		}
		int num = Physics.OverlapSphereNonAlloc(center, 14f, _seaNearby);
		ItemDrop result = null;
		float num2 = float.MaxValue;
		for (int i = 0; i < num; i++)
		{
			Collider val = _seaNearby[i];
			ItemDrop val2 = (((Object)(object)val == (Object)null) ? null : ((Component)val).GetComponentInParent<ItemDrop>());
			if (!CanCollect(val2))
			{
				continue;
			}
			ItemData itemData = val2.m_itemData;
			if (FitAmount(itemData) != 0)
			{
				Vector3 val3 = ((Component)val2).transform.position - dogPosition;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				if (sqrMagnitude < num2)
				{
					num2 = sqrMagnitude;
					result = val2;
				}
			}
		}
		return result;
	}

	internal bool CollectHuntLoot(ItemDrop drop)
	{
		return TryCollect(drop);
	}

	internal ItemDrop FindSerpentLoot(Vector3 center, Vector3 dogPosition)
	{
		//IL_0042: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
		EnsureLoaded();
		if ((Object)(object)_view == (Object)null || !CanWrite || _items.GetTotalWeight() >= 150f)
		{
			return null;
		}
		int num = Physics.OverlapSphereNonAlloc(center, 35f, _seaNearby);
		ItemDrop result = null;
		float num2 = float.MaxValue;
		for (int i = 0; i < num; i++)
		{
			Collider val = _seaNearby[i];
			ItemDrop val2 = (((Object)(object)val == (Object)null) ? null : ((Component)val).GetComponentInParent<ItemDrop>());
			if (!CanCollect(val2) || !IsSerpentLoot(val2))
			{
				continue;
			}
			ItemData itemData = val2.m_itemData;
			if (FitAmount(itemData) != 0)
			{
				float num3 = Vector3.Distance(dogPosition, ((Component)val2).transform.position);
				if (num3 < num2)
				{
					num2 = num3;
					result = val2;
				}
			}
		}
		return result;
	}

	internal bool CollectSerpentLoot(ItemDrop drop)
	{
		return IsSerpentLoot(drop) && TryCollect(drop);
	}

	private static bool IsSerpentLoot(ItemDrop drop)
	{
		if ((Object)(object)drop == (Object)null || drop.m_itemData == null)
		{
			return false;
		}
		string text = (((Object)(object)drop.m_itemData.m_dropPrefab == (Object)null) ? ((Object)((Component)drop).gameObject).name : ((Object)drop.m_itemData.m_dropPrefab).name);
		return text.StartsWith("SerpentMeat", StringComparison.OrdinalIgnoreCase) || text.StartsWith("SerpentScale", StringComparison.OrdinalIgnoreCase) || text.StartsWith("TrophySerpent", StringComparison.OrdinalIgnoreCase);
	}

	internal bool CanStore(ItemData item)
	{
		return CanWrite && item != null && FitAmount(item) == item.m_stack;
	}

	internal bool StoreHarvest(ItemData item)
	{
		if (!CanStore(item) || !_items.AddItem(item.Clone()))
		{
			return false;
		}
		Save();
		return true;
	}

	private int FitAmount(ItemData item)
	{
		if (item == null || item.m_shared == null || item.m_stack <= 0)
		{
			return 0;
		}
		int num = DogCargoCapacity.Fit(item.m_stack, item.GetWeight(-1) / (float)item.m_stack, _items.GetTotalWeight(), 150f);
		int num2 = 0;
		int num3 = num;
		while (num2 < num3)
		{
			int num4 = num2 + (num3 - num2) / 2 + 1;
			if (_items.CanAddItem(item, num4))
			{
				num2 = num4;
			}
			else
			{
				num3 = num4 - 1;
			}
		}
		return num2;
	}

	internal bool CollectFish(ItemDrop drop)
	{
		return TryCollectCore(drop, fishing: true);
	}

	private bool TryCollect(ItemDrop drop)
	{
		return TryCollectCore(drop, fishing: false);
	}

	private bool TryCollectCore(ItemDrop drop, bool fishing)
	{
		if (!CanWrite || !CanCollect(drop, fishing) || (Object)(object)ZNetScene.instance == (Object)null)
		{
			return false;
		}
		ZNetView component = ((Component)drop).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid())
		{
			return false;
		}
		if (!component.IsOwner())
		{
			drop.RequestOwn();
			return false;
		}
		if (!drop.CanPickup(true))
		{
			return false;
		}
		int num = FitAmount(drop.m_itemData);
		if (num <= 0)
		{
			return false;
		}
		ItemData val = drop.m_itemData.Clone();
		val.m_stack = num;
		if (!_items.AddItem(val))
		{
			return false;
		}
		ItemData itemData = drop.m_itemData;
		itemData.m_stack -= num;
		if (drop.m_itemData.m_stack <= 0)
		{
			ZNetScene.instance.Destroy(((Component)drop).gameObject);
		}
		else
		{
			ItemDrop.SaveToZDO(drop.m_itemData, component.GetZDO(), -1);
		}
		Save();
		return true;
	}

	private bool CanCollect(ItemDrop drop, bool fishing = false)
	{
		//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)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Invalid comparison between Unknown and I4
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Invalid comparison between Unknown and I4
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Invalid comparison between Unknown and I4
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Invalid comparison between Unknown and I4
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Invalid comparison between Unknown and I4
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Invalid comparison between Unknown and I4
		if ((Object)(object)drop == (Object)null || drop.m_itemData == null || drop.m_itemData.m_shared == null)
		{
			return false;
		}
		Fish component = ((Component)drop).GetComponent<Fish>();
		if ((Object)(object)component != (Object)null && (component.IsHooked() || (Object)(object)FishingFloat.FindFloat(component) != (Object)null || (!fishing && !component.IsOutOfWater())))
		{
			return false;
		}
		ZNetView component2 = ((Component)drop).GetComponent<ZNetView>();
		if ((Object)(object)_view != (Object)null && _view.IsValid() && (Object)(object)component2 != (Object)null && component2.IsValid() && component2.GetZDO().GetLong("aifriend.dog.unloadedBy", 0L) == _view.GetZDO().GetLong("aifriend.dog.owner", 0L))
		{
			return false;
		}
		ItemData itemData = drop.m_itemData;
		ItemType itemType = itemData.m_shared.m_itemType;
		return !itemData.IsWeapon() && (int)itemType != 5 && (int)itemType != 6 && (int)itemType != 7 && (int)itemType != 11 && (int)itemType != 17 && (int)itemType != 12;
	}
}
public sealed class CompanionDogBleeding : MonoBehaviour
{
	private readonly DogBleedTimer timer = new DogBleedTimer();

	private Character victim;

	private Character attacker;

	private ZNetView view;

	internal static HitData ApplyingTick;

	internal void Bite(Character target, Character source, float damage)
	{
		victim = target;
		attacker = source;
		view = ((Component)target).GetComponent<ZNetView>();
		timer.Bite(Time.time, damage);
	}

	private void Update()
	{
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)victim == (Object)null || victim.IsDead() || victim.GetHealth() <= 0f || victim.IsTamed() || (Object)(object)view == (Object)null || !view.IsValid() || !view.IsOwner())
		{
			Object.Destroy((Object)(object)this);
			return;
		}
		float num = timer.Tick(Time.time);
		if (num > 0f)
		{
			HitData val = new HitData();
			val.m_damage.m_damage = num;
			val.m_point = victim.GetCenterPoint();
			val.m_staggerMultiplier = 0f;
			if ((Object)(object)attacker != (Object)null)
			{
				val.SetAttacker(attacker);
			}
			HitData applyingTick = ApplyingTick;
			ApplyingTick = val;
			try
			{
				victim.ApplyDamage(val, true, false, (DamageModifier)0);
			}
			finally
			{
				ApplyingTick = applyingTick;
			}
		}
		if (!timer.Active)
		{
			Object.Destroy((Object)(object)this);
		}
	}
}
[HarmonyPatch(typeof(Character), "ApplyDamage")]
internal static class HatiBiteBleedPatch
{
	internal struct BiteState
	{
		internal Character Attacker;

		internal float Health;

		internal float MaxHealth;

		internal float Damage;
	}

	[HarmonyPrefix]
	private static void Prefix(Character __instance, HitData hit, out BiteState __state)
	{
		__state = default(BiteState);
		if (hit != null && hit != CompanionDogBleeding.ApplyingTick && !__instance.IsPlayer() && !__instance.IsTamed() && !(((DamageTypes)(ref hit.m_damage)).GetTotalPhysicalDamage() <= 0f))
		{
			Character attacker = hit.GetAttacker();
			CompanionDog companionDog = (((Object)(object)attack