Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Hati Wolf Companion v0.7.38
BepInEx/plugins/AIfriend/ValheimAICompanion.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.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