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 MuchBetterTames v1.8.0
MuchBetterTames.dll
Decompiled 14 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Configs; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TameCompanions { internal class CompanionController : MonoBehaviour { private struct Throttle { private float _t; public bool Check(float dt) { _t += dt; if (_t < 0.05f) { return false; } _t = 0f; return true; } } private sealed class FieldRef { public object Obj; public FieldInfo F; public string Key; public object Val; } private sealed class Snap { public readonly List<FieldRef> Fields = new List<FieldRef>(); public readonly Dictionary<Behaviour, bool> Enabled = new Dictionary<Behaviour, bool>(); public bool HasRb; public bool RbKin; public bool RbGrav; public bool RbDetect; public RigidbodyConstraints RbConstraints; public bool HasAnim; public bool AnimOn; public bool AnimRoot; public float AnimSpeed; } internal static readonly List<CompanionController> All = new List<CompanionController>(); internal static readonly Dictionary<Character, CompanionController> ByCharacter = new Dictionary<Character, CompanionController>(); internal static readonly Dictionary<BaseAI, CompanionController> ByAi = new Dictionary<BaseAI, CompanionController>(); internal const string K_Leader = "TC_Leader"; internal const string K_DownLeft = "TC_DownLeft"; internal const string K_DownStamp = "TC_DownStamp"; internal const string K_Xp = "TC_Xp"; internal const string K_Level = "TC_Level"; internal const string K_Snap = "TC_Snap"; internal const string K_RecStamp = "TC_RecStamp"; internal static readonly int H_Leader = StringExtensionMethods.GetStableHashCode("TC_Leader"); private static readonly MethodInfo IsHungryMethod = AccessTools.Method(typeof(Tameable), "IsHungry", (Type[])null, (Type[])null); internal Character Ch; internal MonsterAI Ai; internal Tameable Tm; internal ZNetView Nv; internal float LastToggle = -999f; internal bool Aboard; private bool _holding; private float _nextBoard; private float _radius = -1f; private float _lockUntil; private Rigidbody _rb; private Animator _anim; private ZSyncAnimation _zanim; private float _acc; private float _lastHp; private float _lastDamageTime = -999f; private float _farTime; private bool _aiOffByUs; private bool _errLogged; private bool _inited; private Vector3 _lastPos; private float _stuckTime; private int _softResets; private int _sleepParam; private float _butcherUntil; private Vector3 _tickPos; private float _lastMovedTime; private float _nextSnap; private Snap _snap; private float _recoverCheckUntil; private float _standUntil; private Throttle _downedTick; private float _recoverAt = -1f; private Vector3 _recoverPos; private bool _rebindDone; private static readonly FieldInfo SleepingField = AccessTools.Field(typeof(MonsterAI), "m_sleeping"); private bool _visualDown; private readonly Dictionary<string, bool> _paramCache = new Dictionary<string, bool>(); private float _nextRescue; private float _embeddedTime; private static int _embedMask = -1; private static readonly MethodInfo WakeupMethod = AccessTools.Method(typeof(MonsterAI), "Wakeup", (Type[])null, (Type[])null); internal long LeaderId => ((Object)(object)Nv != (Object)null && Nv.GetZDO() != null) ? Nv.GetZDO().GetLong("TC_Leader", 0L) : 0; internal float DownLeft => ((Object)(object)Nv != (Object)null && Nv.GetZDO() != null) ? Nv.GetZDO().GetFloat("TC_DownLeft", 0f) : 0f; internal bool IsDowned => DownLeft > 0f; internal bool ActionLocked { get { float value = Cfg.RecoverLockSeconds.Value; if (value <= 0f) { return false; } if (Time.time < _lockUntil) { return true; } ZDO val = (((Object)(object)Nv != (Object)null) ? Nv.GetZDO() : null); if (val == null || (Object)(object)ZNet.instance == (Object)null) { return false; } long num = val.GetLong("TC_RecStamp", 0L); if (num == 0) { return false; } return NowMs() - num < (long)(value * 1000f); } } internal bool RecoverProtected { get { float value = Cfg.RecoverProtectSeconds.Value; if (value <= 0f) { return false; } ZDO val = (((Object)(object)Nv != (Object)null) ? Nv.GetZDO() : null); if (val == null || (Object)(object)ZNet.instance == (Object)null) { return false; } long num = val.GetLong("TC_RecStamp", 0L); return num != 0L && NowMs() - num < (long)(value * 1000f); } } private float BodyRadius { get { //IL_003d: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (_radius < 0f) { _radius = 0.4f; try { Collider val = ((Component)this).GetComponent<Collider>() ?? ((Component)this).GetComponentInChildren<Collider>(); if ((Object)(object)val != (Object)null) { Bounds bounds = val.bounds; Vector3 extents = ((Bounds)(ref bounds)).extents; _radius = Mathf.Clamp(Mathf.Max(extents.x, extents.z) * 0.8f, 0.3f, 2.5f); } } catch { } } return _radius; } } internal bool ButcherActive => Time.time < _butcherUntil; private void Awake() { Nv = ((Component)this).GetComponent<ZNetView>(); Ch = ((Component)this).GetComponent<Character>(); Ai = ((Component)this).GetComponent<MonsterAI>(); Tm = ((Component)this).GetComponent<Tameable>(); _rb = ((Component)this).GetComponent<Rigidbody>(); _zanim = ((Component)this).GetComponent<ZSyncAnimation>(); _anim = ((Component)this).GetComponentInChildren<Animator>(); if ((Object)(object)Nv == (Object)null || (Object)(object)Ch == (Object)null || (Object)(object)Ai == (Object)null || (Object)(object)Tm == (Object)null) { ((Behaviour)this).enabled = false; } else { TryInit(); } } private void TryInit() { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if (!_inited && !((Object)(object)Nv == (Object)null) && Nv.IsValid()) { _inited = true; Nv.Register<float>("TC_AddXp", (Action<long, float>)RPC_AddXp); Nv.Register<float>("TC_Help", (Action<long, float>)RPC_Help); Nv.Register("TC_Butcher", (Action<long>)RPC_Butcher); All.Add(this); ByCharacter[Ch] = this; ByAi[(BaseAI)(object)Ai] = this; _lastHp = Ch.GetHealth(); _lastPos = ((Component)this).transform.position; } } private void OnDestroy() { All.Remove(this); if (Ch != null) { ByCharacter.Remove(Ch); } if (Ai != null) { ByAi.Remove((BaseAI)(object)Ai); } } private void Update() { if (!_inited) { TryInit(); if (!_inited) { return; } } if ((Object)(object)Nv == (Object)null || !Nv.IsValid()) { return; } ApplyDownVisual(IsDowned); if (_downedTick.Check(Time.deltaTime) && Cfg.Enabled.Value && Nv.IsOwner() && IsDowned && Ch.IsTamed() && DownedWillEnd()) { try { if ((Object)(object)ZNet.instance != (Object)null) { TickDowned(0f); } } catch { } } _acc += Time.deltaTime; if (_acc < 0.5f) { return; } float acc = _acc; _acc = 0f; SyncLevelVisual(); if (!Cfg.Enabled.Value || !Ch.IsTamed() || !Nv.IsOwner()) { return; } try { OwnerTick(acc); } catch (Exception ex) { if (!_errLogged) { _errLogged = true; TameCompanionsPlugin.Log.LogWarning((object)("Controller-Fehler: " + ex)); } } } private void OwnerTick(float dt) { //IL_00dd: 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) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || TickDowned(dt)) { return; } if (!((Behaviour)Ai).enabled) { ((Behaviour)Ai).enabled = true; } _aiOffByUs = false; if (Time.time < _recoverCheckUntil) { try { if (IsStillLying()) { TameCompanionsPlugin.Log.LogInfo((object)("Rest-Knockdown nach Erholung bereinigt: " + ((Object)this).name + " | " + DumpState())); _visualDown = false; ForceAwake(); SetSleepAnim(on: false); if (!_rebindDone) { _rebindDone = true; ResetAnimator(); } } } catch { } } Vector3 position = ((Component)this).transform.position; Vector3 val = position - _tickPos; if (((Vector3)(ref val)).sqrMagnitude > 0.25f) { _lastMovedTime = Time.time; } _tickPos = position; if (Time.time >= _nextSnap) { _nextSnap = Time.time + 10f; if (Time.time - _lastMovedTime < 3f && Time.time > _recoverCheckUntil + 30f && Time.time - _lastDamageTime > 15f && (Object)(object)((BaseAI)Ai).GetTargetCreature() == (Object)null && ((Behaviour)Ai).enabled) { try { _snap = Capture(); } catch { } } } float health = Ch.GetHealth(); if (health < _lastHp - 0.01f) { _lastDamageTime = Time.time; } bool inCombat = Time.time - _lastDamageTime < Cfg.CombatCooldown.Value || (Object)(object)((BaseAI)Ai).GetTargetCreature() != (Object)null; if (Cfg.RegenEnabled.Value) { Regen(dt, inCombat); } _lastHp = Ch.GetHealth(); FollowAndTeleport(dt); } internal bool FollowsPlayer(Player p) { long leaderId = LeaderId; if (leaderId != 0) { return leaderId == p.GetPlayerID(); } return Nv.IsOwner() && (Object)(object)Ai.GetFollowTarget() == (Object)(object)((Component)p).gameObject; } private static long NowMs() { return (long)(ZNet.instance.GetTimeSeconds() * 1000.0); } internal static bool IsDownedTame(Character c) { if ((Object)(object)c == (Object)null || !c.IsTamed()) { return false; } CompanionController value; return ByCharacter.TryGetValue(c, out value) && (Object)(object)value != (Object)null && value.IsDowned; } internal static Player FindPlayer(long id) { if (id == 0) { return null; } foreach (Player allPlayer in Player.GetAllPlayers()) { if ((Object)(object)allPlayer != (Object)null && allPlayer.GetPlayerID() == id) { return allPlayer; } } return null; } private bool SafeHungry() { try { return IsHungryMethod != null && (bool)IsHungryMethod.Invoke(Tm, null); } catch { return false; } } internal void SetFollow(Player p, bool follow) { Nv.ClaimOwnership(); if (follow) { ((BaseAI)Ai).ResetPatrolPoint(); Ai.SetFollowTarget(((Component)p).gameObject); Nv.GetZDO().Set("TC_Leader", p.GetPlayerID()); } else { Ai.SetFollowTarget((GameObject)null); ((BaseAI)Ai).SetPatrolPoint(); Nv.GetZDO().Set("TC_Leader", 0L); } } private void FollowAndTeleport(float dt) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = Nv.GetZDO(); if (zDO == null) { return; } long num = zDO.GetLong("TC_Leader", 0L); GameObject followTarget = Ai.GetFollowTarget(); if (num == 0) { Player val = (((Object)(object)followTarget != (Object)null) ? followTarget.GetComponent<Player>() : null); if (!((Object)(object)val != (Object)null)) { _farTime = 0f; _stuckTime = 0f; _softResets = 0; _lastPos = ((Component)this).transform.position; return; } num = val.GetPlayerID(); zDO.Set("TC_Leader", num); } Player val2 = FindPlayer(num); if ((Object)(object)val2 == (Object)null || ((Character)val2).IsDead()) { _stuckTime = 0f; _lastPos = ((Component)this).transform.position; return; } if ((Object)(object)followTarget == (Object)null) { ((BaseAI)Ai).ResetPatrolPoint(); Ai.SetFollowTarget(((Component)val2).gameObject); } Vector3 position = ((Component)val2).transform.position; Vector3 position2 = ((Component)this).transform.position; bool flag = position.y > 3000f; if (flag && (!Cfg.FollowDungeons.Value || CompanionManager.IsDungeonExcluded(((Component)this).gameObject))) { _stuckTime = 0f; _lastPos = position2; return; } float num2 = Vector3.Distance(position, position2); if (zDO.GetBool("TC_Snap", false)) { zDO.Set("TC_Snap", false); TeleportBehind(val2); return; } if (Time.time >= _nextRescue && IsLost(dt, flag, out var why)) { _nextRescue = Time.time + 3f; TameCompanionsPlugin.Log.LogInfo((object)("Verloren/Eingeklemmt (" + why + "): " + ((Object)this).name + " -> hinter den Spieler gesetzt | " + DumpState())); TeleportBehind(val2); return; } bool flag2 = (Object)(object)((BaseAI)Ai).GetTargetCreature() != (Object)null; Ship val3 = (Cfg.ShipEnabled.Value ? ShipHelper.ShipOf(val2) : null); if ((Object)(object)val3 != (Object)null) { Aboard = ShipHelper.IsAboard(position2, val3); if (Aboard) { _farTime = 0f; _stuckTime = 0f; _softResets = 0; _lastPos = position2; return; } if (Cfg.TeleportEnabled.Value && Time.time >= _nextBoard && !ShipHelper.Excluded(((Component)this).gameObject) && (!flag2 || !(num2 < Cfg.CombatTeleportDistance.Value)) && (num2 > Cfg.ShipBoardDistance.Value || ShipHelper.IsMoving(val3))) { _nextBoard = Time.time + 3f; TeleportBehind(val2); return; } } else { Aboard = false; } if (UpdateStuck(dt, num2, flag2, val2) || !Cfg.TeleportEnabled.Value) { return; } if (flag2 && num2 < Cfg.CombatTeleportDistance.Value) { _farTime = 0f; return; } float num3 = (flag ? Cfg.DungeonTeleportDistance.Value : Cfg.TeleportDistance.Value); bool flag3 = num2 > num3; if (!flag3) { if (num2 > 15f) { _farTime += dt; } else { _farTime = 0f; } if (_farTime >= Cfg.StuckSeconds.Value) { flag3 = true; } } if (flag3) { _farTime = 0f; TeleportBehind(val2); } } private bool UpdateStuck(float dt, float dist, bool fighting, Player leader) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) Vector3 position = ((Component)this).transform.position; Vector3 val = position - _lastPos; float magnitude = ((Vector3)(ref val)).magnitude; _lastPos = position; bool flag = false; try { val = Traverse.Create((object)Ch).Field("m_moveDir").GetValue<Vector3>(); flag = ((Vector3)(ref val)).sqrMagnitude > 0.01f; } catch { } if (fighting || !(magnitude < 0.2f) || (!(dist > 6f) && !(dist > 3.5f && flag))) { _stuckTime = 0f; _softResets = 0; return false; } _stuckTime += dt; if (_stuckTime >= 2f && _softResets == 0) { _softResets = 1; TameCompanionsPlugin.Log.LogInfo((object)("Festhänger-Reset (Stufe 1): " + ((Object)this).name + " | " + DumpState())); SoftReset(leader); return false; } if (_stuckTime >= 4f && _softResets == 1) { _softResets = 2; TameCompanionsPlugin.Log.LogInfo((object)("Festhänger-Reset (Stufe 2): " + ((Object)this).name + " | " + DumpState())); HardReset(leader); return false; } if (_stuckTime >= 6.5f) { _stuckTime = 0f; _softResets = 0; TameCompanionsPlugin.Log.LogInfo((object)("Festhänger (Stufe 3): " + ((Object)this).name + " | " + DumpState())); if (Cfg.TeleportEnabled.Value && dist > Cfg.NoTeleportNear.Value) { TeleportBehind(leader); return true; } HardReset(leader); } return false; } private void SoftReset(Player leader) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) try { ((BaseAI)Ai).StopMoving(); } catch { } ForceAwake(); ResetAnimator(); if ((Object)(object)_rb != (Object)null) { _rb.isKinematic = false; _rb.velocity = Vector3.zero; _rb.angularVelocity = Vector3.zero; _rb.WakeUp(); } ((Behaviour)Ai).enabled = false; ((Behaviour)Ai).enabled = true; _aiOffByUs = false; ((BaseAI)Ai).ResetPatrolPoint(); Ai.SetFollowTarget(((Component)leader).gameObject); } private void HardReset(Player leader) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) SoftReset(leader); ClearStatusEffects(); try { DiffAndRestore(restore: true); } catch (Exception ex) { TameCompanionsPlugin.Log.LogWarning((object)("Zustandsvergleich: " + ex.Message)); } try { if ((Object)(object)_rb != (Object)null) { _rb.constraints = (RigidbodyConstraints)(_rb.constraints & -15); _rb.detectCollisions = true; } if ((Object)(object)_anim != (Object)null) { ((Behaviour)_anim).enabled = true; _anim.speed = 1f; } ZSyncTransform component = ((Component)this).GetComponent<ZSyncTransform>(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = true; } if ((Object)(object)Ch != (Object)null) { ((Behaviour)Ch).enabled = true; } } catch { } } private void ClearStatusEffects() { try { object value = Traverse.Create((object)Ch).Field("m_seman").GetValue(); if (value == null) { return; } MethodInfo[] methods = value.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "RemoveAllStatusEffects")) { ParameterInfo[] parameters = methodInfo.GetParameters(); methodInfo.Invoke(value, (parameters.Length == 0) ? null : new object[1] { true }); break; } } } catch { } } private static bool Simple(Type t) { return t == typeof(bool) || t == typeof(int) || t == typeof(float) || t.IsEnum; } private Snap Capture() { //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) Snap snap = new Snap(); object[] array = new object[3] { Ch, Ai, Tm }; object[] array2 = array; foreach (object obj in array2) { if (obj == null) { continue; } Type type = obj.GetType(); Type type2 = type; while (type2 != null && type2 != typeof(MonoBehaviour)) { FieldInfo[] fields = type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (Simple(fieldInfo.FieldType)) { try { snap.Fields.Add(new FieldRef { Obj = obj, F = fieldInfo, Key = type.Name + "." + type2.Name + "." + fieldInfo.Name, Val = fieldInfo.GetValue(obj) }); } catch { } } } type2 = type2.BaseType; } } Behaviour[] componentsInChildren = ((Component)this).GetComponentsInChildren<Behaviour>(true); foreach (Behaviour val in componentsInChildren) { if ((Object)(object)val != (Object)null) { snap.Enabled[val] = val.enabled; } } if ((Object)(object)_rb != (Object)null) { snap.HasRb = true; snap.RbKin = _rb.isKinematic; snap.RbGrav = _rb.useGravity; snap.RbDetect = _rb.detectCollisions; snap.RbConstraints = _rb.constraints; } if ((Object)(object)_anim != (Object)null) { snap.HasAnim = true; snap.AnimOn = ((Behaviour)_anim).enabled; snap.AnimRoot = _anim.applyRootMotion; snap.AnimSpeed = _anim.speed; } return snap; } private void DiffAndRestore(bool restore) { //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) if (_snap == null) { TameCompanionsPlugin.Log.LogInfo((object)("Zustandsvergleich: noch kein gesunder Schnappschuss vorhanden: " + ((Object)this).name)); return; } StringBuilder stringBuilder = new StringBuilder(); int num = 0; foreach (FieldRef field in _snap.Fields) { object value; try { value = field.F.GetValue(field.Obj); } catch { continue; } if (object.Equals(value, field.Val)) { continue; } Type fieldType = field.F.FieldType; if (fieldType == typeof(float)) { continue; } if (num++ < 80) { stringBuilder.Append(field.Key).Append(": ").Append(field.Val) .Append("->") .Append(value) .Append(" | "); } bool flag = field.Key.IndexOf("sleep", StringComparison.OrdinalIgnoreCase) >= 0; if (restore && !flag && (fieldType == typeof(bool) || fieldType.IsEnum)) { try { field.F.SetValue(field.Obj, field.Val); } catch { } } } int num2 = 0; foreach (KeyValuePair<Behaviour, bool> item in _snap.Enabled) { if ((Object)(object)item.Key != (Object)null && item.Value && !item.Key.enabled) { stringBuilder.Append("DISABLED:").Append(((object)item.Key).GetType().Name).Append(" | "); if (restore) { item.Key.enabled = true; num2++; } } } if ((Object)(object)_rb != (Object)null && _snap.HasRb && (_rb.isKinematic != _snap.RbKin || _rb.useGravity != _snap.RbGrav || _rb.detectCollisions != _snap.RbDetect || _rb.constraints != _snap.RbConstraints)) { stringBuilder.Append("RB:").Append(_snap.RbKin).Append('/') .Append(_snap.RbGrav) .Append('/') .Append(_snap.RbConstraints) .Append("->") .Append(_rb.isKinematic) .Append('/') .Append(_rb.useGravity) .Append('/') .Append(_rb.constraints) .Append(" | "); if (restore) { _rb.isKinematic = _snap.RbKin; _rb.useGravity = _snap.RbGrav; _rb.detectCollisions = _snap.RbDetect; _rb.constraints = _snap.RbConstraints; } } if ((Object)(object)_anim != (Object)null && _snap.HasAnim && (((Behaviour)_anim).enabled != _snap.AnimOn || _anim.applyRootMotion != _snap.AnimRoot || Mathf.Abs(_anim.speed - _snap.AnimSpeed) > 0.01f)) { stringBuilder.Append("ANIM:").Append(_snap.AnimOn).Append('/') .Append(_snap.AnimRoot) .Append('/') .Append(_snap.AnimSpeed) .Append("->") .Append(((Behaviour)_anim).enabled) .Append('/') .Append(_anim.applyRootMotion) .Append('/') .Append(_anim.speed) .Append(" | "); if (restore) { ((Behaviour)_anim).enabled = _snap.AnimOn; _anim.applyRootMotion = _snap.AnimRoot; _anim.speed = _snap.AnimSpeed; } } TameCompanionsPlugin.Log.LogInfo((object)("Zustandsvergleich (" + ((Object)this).name + "): " + ((stringBuilder.Length == 0) ? "keine Unterschiede" : stringBuilder.ToString()))); } private string DumpState() { StringBuilder sb = new StringBuilder(); Action<string, Func<object>> action = delegate(string k, Func<object> f) { try { sb.Append(k).Append('=').Append(f()) .Append(' '); } catch { sb.Append(k).Append("=? "); } }; action("owner", () => Nv.IsOwner()); action("downLeft", () => DownLeft); action("isDowned", () => IsDowned); action("visualDown", () => _visualDown); action("anim.sleeping", () => _anim.GetBool("sleeping")); action("hp", () => Ch.GetHealth()); action("ai.on", () => ((Behaviour)Ai).enabled); action("sleeping", () => Traverse.Create((object)Ai).Field("m_sleeping").GetValue()); action("alerted", () => ((BaseAI)Ai).IsAlerted()); action("follow", () => (Object)(object)Ai.GetFollowTarget() != (Object)null); action("target", () => (Object)(object)((BaseAI)Ai).GetTargetCreature() != (Object)null); action("moveDir", () => Traverse.Create((object)Ch).Field("m_moveDir").GetValue()); action("ground", () => Traverse.Create((object)Ch).Method("IsOnGround", Array.Empty<object>()).GetValue()); action("rb.kin", () => _rb.isKinematic); action("rb.constr", () => _rb.constraints); action("rb.vel", () => _rb.velocity); action("rb.sleep", () => _rb.IsSleeping()); action("rb.grav", () => _rb.useGravity); action("anim.on", () => ((Behaviour)_anim).enabled); action("anim.speed", () => _anim.speed); action("anim.state", delegate { //IL_000c: 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) AnimatorStateInfo currentAnimatorStateInfo = _anim.GetCurrentAnimatorStateInfo(0); return ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash; }); action("zsync", () => ((Behaviour)((Component)this).GetComponent<ZSyncTransform>()).enabled); action("se", delegate { //IL_0061: Unknown result type (might be due to invalid IL or missing references) object value = Traverse.Create((object)Ch).Field("m_seman").GetValue(); List<string> list = new List<string>(); if (Traverse.Create(value).Field("m_statusEffects").GetValue() is IEnumerable enumerable) { foreach (object item in enumerable) { list.Add(((Object)item).name); } } return string.Join(",", list.ToArray()); }); return sb.ToString(); } private bool IsLost(float dt, bool dungeon, out string why) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) why = null; Vector3 position = ((Component)this).transform.position; try { if (!dungeon && (Object)(object)ZoneSystem.instance != (Object)null && position.y < ZoneSystem.instance.GetGroundHeight(position) - 2.5f) { why = "unter dem Boden"; return true; } } catch { } bool flag = false; try { if (_embedMask < 0) { _embedMask = LayerMask.GetMask(new string[2] { "piece", "static_solid" }); } float num = Mathf.Max(0.25f, BodyRadius * 0.6f); float num2 = Mathf.Clamp(BodyRadius * 2f, 1f, 1.5f); Vector3 val = position + Vector3.up * (num + 0.25f); Vector3 val2 = position + Vector3.up * Mathf.Max(num + 0.25f, num2 - num); flag = Physics.CheckCapsule(val, val2, num, _embedMask, (QueryTriggerInteraction)1); } catch { } if (flag) { _embeddedTime += dt; if (_embeddedTime >= 3f) { _embeddedTime = 0f; why = "in Bauteil/Fels eingeklemmt"; return true; } } else { _embeddedTime = 0f; } return false; } private void TeleportBehind(Player leader) { //IL_0157: 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_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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_0124: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) Ship val = (Cfg.ShipEnabled.Value ? ShipHelper.ShipOf(leader) : null); Vector3 pos; Quaternion rot; if ((Object)(object)val != (Object)null) { if (ShipHelper.Excluded(((Component)this).gameObject) || !ShipHelper.TryFindDeck(val, leader, this, out pos)) { return; } Vector3 forward = ((Component)leader).transform.forward; forward.y = 0f; rot = ((((Vector3)(ref forward)).sqrMagnitude > 0.001f) ? Quaternion.LookRotation(forward) : ((Component)this).transform.rotation); } else { pos = CompanionManager.FindBehind(leader, Cfg.BehindDistance.Value, out rot, BodyRadius); } ((Component)this).transform.position = pos; ((Component)this).transform.rotation = rot; if ((Object)(object)_rb != (Object)null) { _rb.position = pos; _rb.rotation = rot; _rb.velocity = Vector3.zero; _rb.angularVelocity = Vector3.zero; _rb.WakeUp(); } Nv.GetZDO().SetPosition(pos); try { ((BaseAI)Ai).StopMoving(); } catch { } try { Traverse.Create((object)Ch).Field("m_maxAirAltitude").SetValue((object)pos.y); } catch { } if (!((Behaviour)Ai).enabled) { ((Behaviour)Ai).enabled = true; } _aiOffByUs = false; ForceAwake(); ((BaseAI)Ai).ResetPatrolPoint(); Ai.SetFollowTarget(((Component)leader).gameObject); _lastPos = pos; _stuckTime = 0f; _softResets = 0; _embeddedTime = 0f; } internal bool HoldFollow(GameObject target) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null || (Object)(object)Ch == (Object)null || !Ch.IsTamed()) { return false; } if (Aboard) { try { ((BaseAI)Ai).StopMoving(); } catch { } return true; } Vector3 val = target.transform.position - ((Component)this).transform.position; val.y = 0f; float magnitude = ((Vector3)(ref val)).magnitude; float num = ((target.transform.position.y > 3000f) ? 0.6f : 1f); float bodyRadius = BodyRadius; float num2 = (Cfg.FollowStopDistance.Value + bodyRadius) * num; float num3 = Mathf.Max((Cfg.FollowResumeDistance.Value + bodyRadius) * num, num2 + 1.5f); if (_holding) { if (magnitude > num3) { _holding = false; } } else if (magnitude < num2) { _holding = true; } if (!_holding) { return false; } try { ((BaseAI)Ai).StopMoving(); } catch { } return true; } private void Regen(float dt, bool inCombat) { float maxHealth = Ch.GetMaxHealth(); float health = Ch.GetHealth(); if (!(health >= maxHealth)) { float num = (inCombat ? Cfg.RegenCombatPct.Value : Cfg.RegenRestPct.Value); float num2 = (SafeHungry() ? Cfg.HungryMult.Value : Cfg.FedMult.Value); float num3 = maxHealth * (num / 100f) * num2 * dt; if (num3 > 0f) { Ch.SetHealth(Mathf.Min(maxHealth, health + num3)); } } } internal void EnterDowned() { ZDO zDO = Nv.GetZDO(); if (zDO.GetFloat("TC_DownLeft", 0f) > 0f) { Ch.SetHealth(1f); return; } long num = zDO.GetLong("TC_RecStamp", 0L); TameCompanionsPlugin.Log.LogInfo((object)("Bewusstlos: " + ((Object)this).name + " | " + ((num == 0L) ? "erstmals" : (((float)(NowMs() - num) / 1000f).ToString("0.0") + " s nach letzter Erholung")) + " | " + DumpState())); int num2 = Mathf.Max(0, Ch.GetLevel() - 1); float num3 = Mathf.Max(0.3f, 1f - Cfg.DownedStarReduction.Value * (float)num2); float num4 = Cfg.DownedSeconds.Value * num3; zDO.Set("TC_DownLeft", num4); zDO.Set("TC_DownStamp", NowMs()); Ch.SetHealth(1f); CompanionManager.SetAlerted(Ai, alerted: false); try { Ai.SetFollowTarget((GameObject)null); } catch { } SetAiActive(on: false); _visualDown = false; ApplyDownVisual(down: true); _stuckTime = 0f; _softResets = 0; CompanionManager.Say(((Component)this).gameObject, Loc.T("down_say")); } private bool DownedWillEnd() { //IL_008c: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = Nv.GetZDO(); if (zDO == null || (Object)(object)ZNet.instance == (Object)null) { return false; } float num = zDO.GetFloat("TC_DownLeft", 0f); if (num <= 0f) { return false; } long num2 = NowMs(); float num3 = Mathf.Max(0f, (float)(num2 - zDO.GetLong("TC_DownStamp", num2)) / 1000f); float num4 = Mathf.Min(num3, 1.5f); float num5 = (((Object)(object)Player.GetClosestPlayer(((Component)this).transform.position, 15f) != (Object)null) ? Cfg.LeaderNearSpeed.Value : 1f); return num - (num3 - num4 + num4 * num5) <= 0f; } private bool TickDowned(float dt) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = Nv.GetZDO(); float num = zDO.GetFloat("TC_DownLeft", 0f); if (num <= 0f) { if (_aiOffByUs) { WakeUp(); } return false; } if (!Cfg.TamesProtected()) { Recover(); return true; } long num2 = NowMs(); long num3 = zDO.GetLong("TC_DownStamp", num2); float num4 = Mathf.Max(0f, (float)(num2 - num3) / 1000f); float num5 = Mathf.Min(num4, 1.5f); float num6 = num4 - num5; float num7 = (((Object)(object)Player.GetClosestPlayer(((Component)this).transform.position, 15f) != (Object)null) ? Cfg.LeaderNearSpeed.Value : 1f); num -= num6 + num5 * num7; zDO.Set("TC_DownStamp", num2); if (num <= 0f) { Recover(); return true; } zDO.Set("TC_DownLeft", num); SetAiActive(on: false); if (Ch.GetHealth() < 1f) { Ch.SetHealth(1f); } if ((Object)(object)_rb != (Object)null) { _rb.velocity = new Vector3(0f, _rb.velocity.y, 0f); } return true; } private void Recover() { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = Nv.GetZDO(); zDO.Set("TC_DownLeft", 0f); zDO.Set("TC_RecStamp", NowMs()); ClearStatusEffects(); Ch.SetHealth(Ch.GetMaxHealth() * Cfg.RecoverHealthPct.Value / 100f); _lastHp = Ch.GetHealth(); WakeUp(); Player val = FindPlayer(zDO.GetLong("TC_Leader", 0L)); if ((Object)(object)val != (Object)null && !((Character)val).IsDead()) { try { ((BaseAI)Ai).ResetPatrolPoint(); Ai.SetFollowTarget(((Component)val).gameObject); } catch { } } _lastPos = ((Component)this).transform.position; _stuckTime = 0f; _softResets = 0; _recoverCheckUntil = Time.time + 20f; _standUntil = Time.time + 4f; _recoverAt = Time.time; _recoverPos = ((Component)this).transform.position; _rebindDone = false; _lockUntil = Mathf.Max(_lockUntil, Time.time + Mathf.Max(0f, Cfg.RecoverLockSeconds.Value)); if (Cfg.DebugLog.Value) { string text = "?"; try { text = Convert.ToString(Traverse.Create((object)Ai).Field("m_sleeping").GetValue()); } catch { } TameCompanionsPlugin.Log.LogInfo((object)string.Format("Recover {0}: ai.enabled={1} m_sleeping={2} follow={3} leader={4}", ((Object)this).name, ((Behaviour)Ai).enabled, text, (Object)(object)Ai.GetFollowTarget() != (Object)null, ((Object)(object)val != (Object)null) ? val.GetPlayerName() : "none")); } CompanionManager.Say(((Component)this).gameObject, Loc.T("up_say")); } private void WakeUp() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) SetAiActive(on: true); _visualDown = false; ForceAwake(); ResetAnimator(skipGetUp: true); if ((Object)(object)_rb != (Object)null) { _rb.isKinematic = false; _rb.velocity = Vector3.zero; _rb.angularVelocity = Vector3.zero; _rb.WakeUp(); } } private void SetAiActive(bool on) { if (!on) { try { ((BaseAI)Ai).StopMoving(); } catch { } } ((Behaviour)Ai).enabled = on; _aiOffByUs = !on; } private void ForceAwake() { try { WakeupMethod?.Invoke(Ai, null); } catch { } try { Traverse.Create((object)Ai).Field("m_sleeping").SetValue((object)false); } catch { } try { Nv.GetZDO().Set("sleeping", false); } catch { } } private bool IsStillLying() { if (_visualDown) { return true; } if (HasSleepParam() && (Object)(object)_anim != (Object)null && _anim.GetBool("sleeping")) { return true; } try { if (SleepingField != null && (bool)SleepingField.GetValue(Ai)) { return true; } } catch { } return false; } private void SetSleepAnim(bool on) { if ((Object)(object)_anim == (Object)null || !HasSleepParam()) { return; } try { if ((Object)(object)Nv != (Object)null && Nv.IsOwner() && (Object)(object)_zanim != (Object)null) { _zanim.SetBool("sleeping", on); } _anim.SetBool("sleeping", on); } catch { } } private void LateUpdate() { //IL_011f: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) if (!_inited || _standUntil <= 0f || (Object)(object)Nv == (Object)null || !Nv.IsValid() || !Nv.IsOwner() || IsDowned) { return; } if (Time.time >= _standUntil) { _standUntil = 0f; if (_recoverAt >= 0f) { TameCompanionsPlugin.Log.LogInfo((object)("Keine Bewegung in 4 s nach Erholung: " + ((Object)this).name + " | " + DumpState())); _recoverAt = -1f; } try { if (IsStillLying()) { TameCompanionsPlugin.Log.LogWarning((object)("Tame liegt nach Erholung noch: " + ((Object)this).name + " | " + DumpState())); } return; } catch { return; } } try { if (_recoverAt >= 0f) { Vector3 val = ((Component)this).transform.position - _recoverPos; if (((Vector3)(ref val)).sqrMagnitude > 0.25f) { TameCompanionsPlugin.Log.LogInfo((object)("Erste Bewegung " + (Time.time - _recoverAt).ToString("0.00") + " s nach Erholung: " + ((Object)this).name)); _recoverAt = -1f; } } if (!((Behaviour)Ai).enabled) { ((Behaviour)Ai).enabled = true; } _aiOffByUs = false; if (SleepingField != null && (bool)SleepingField.GetValue(Ai)) { SleepingField.SetValue(Ai, false); } if (HasSleepParam() && (Object)(object)_anim != (Object)null && _anim.GetBool("sleeping")) { SetSleepAnim(on: false); } if (ParamExists("dead")) { _anim.ResetTrigger("dead"); } } catch { } } private bool ParamExists(string name) { if (_paramCache.TryGetValue(name, out var value)) { return value; } value = false; if ((Object)(object)_anim != (Object)null) { try { AnimatorControllerParameter[] parameters = _anim.parameters; foreach (AnimatorControllerParameter val in parameters) { if (val.name == name) { value = true; break; } } } catch { } } _paramCache[name] = value; return value; } private bool HasSleepParam() { return ParamExists("sleeping"); } private void ApplyDownVisual(bool down) { if (_visualDown == down || (Object)(object)_anim == (Object)null) { return; } _visualDown = down; try { if (down) { if (HasSleepParam()) { if (Nv.IsOwner()) { if ((Object)(object)_zanim != (Object)null) { _zanim.SetBool("sleeping", true); } _anim.SetBool("sleeping", true); } } else if (ParamExists("dead")) { _anim.SetTrigger("dead"); } } else { ResetAnimator(); } } catch { } } private void ResetAnimator(bool skipGetUp = false) { try { if ((Object)(object)Nv != (Object)null && Nv.IsOwner() && (Object)(object)_zanim != (Object)null && HasSleepParam()) { _zanim.SetBool("sleeping", false); } if ((Object)(object)_anim != (Object)null) { _anim.Rebind(); _anim.Update(0f); if (skipGetUp) { _anim.Update(2f); } } } catch { } } private void RPC_Butcher(long sender) { _butcherUntil = Time.time + 2f; } internal void NotifyButcher() { if (_inited && (Object)(object)Nv != (Object)null && Nv.IsValid()) { Nv.InvokeRPC("TC_Butcher", Array.Empty<object>()); } } private void RPC_Help(long sender, float seconds) { if (!Nv.IsOwner()) { return; } ZDO zDO = Nv.GetZDO(); float num = zDO.GetFloat("TC_DownLeft", 0f); if (!(num <= 0f)) { num -= seconds; if (num <= 0.5f) { Recover(); } else { zDO.Set("TC_DownLeft", num); } } } internal void Help() { if (IsDowned) { _lockUntil = Time.time + Mathf.Max(0f, Cfg.RecoverLockSeconds.Value); } Nv.InvokeRPC("TC_Help", new object[1] { Cfg.HelpSeconds.Value }); } internal void GiveXp(float xp) { if (xp > 0f && _inited && (Object)(object)Nv != (Object)null && Nv.IsValid()) { Nv.InvokeRPC("TC_AddXp", new object[1] { xp }); } } private void RPC_AddXp(long sender, float xp) { //IL_011a: 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_0133: 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) if (!Nv.IsOwner() || !Ch.IsTamed() || !Cfg.StarsEnabled.Value || xp <= 0f) { return; } ZDO zDO = Nv.GetZDO(); float num = zDO.GetFloat("TC_Xp", 0f) + xp; zDO.Set("TC_Xp", num); float value = Cfg.XpStar1.Value; float num2 = Mathf.Max(value, Cfg.XpStar2.Value); int num3 = ((num >= num2) ? 2 : ((num >= value) ? 1 : 0)); num3 = Mathf.Min(num3, Cfg.MaxStars.Value); int num4 = Ch.GetLevel() - 1; if (num3 <= num4) { return; } Ch.SetLevel(num3 + 1); zDO.Set("TC_Level", num3 + 1); Ch.SetHealth(Ch.GetMaxHealth()); try { EffectList tamedEffect = Tm.m_tamedEffect; if (tamedEffect != null) { tamedEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID)); } } catch { } CompanionManager.Say(((Component)this).gameObject, Loc.T("star_up", num3, Cfg.MaxStars.Value)); } private void SyncLevelVisual() { ZDO zDO = Nv.GetZDO(); if (zDO != null) { int num = zDO.GetInt("TC_Level", 0); if (num > 0 && num != Ch.GetLevel()) { Ch.SetLevel(num); } } } internal static string Fmt(float sec) { int num = Mathf.Max(0, Mathf.CeilToInt(sec)); return num / 60 + ":" + (num % 60).ToString("00"); } internal string HudLabel() { if ((Object)(object)Nv == (Object)null || !Nv.IsValid() || (Object)(object)Ch == (Object)null || !Ch.IsTamed()) { return ""; } if (IsDowned) { return "<color=#ff5a5a>" + Loc.T("knocked") + " " + Fmt(DownLeft) + "</color>"; } long leaderId = LeaderId; if (leaderId == 0) { return ""; } Player val = FindPlayer(leaderId); if ((Object)(object)val == (Object)null) { return ""; } return "<color=#ffffff>" + Loc.T("follows", val.GetPlayerName()) + "</color>"; } internal string ExtraHover() { if ((Object)(object)Nv == (Object)null) { return ""; } ZDO zDO = Nv.GetZDO(); if (zDO == null) { return ""; } if (!Ch.IsTamed()) { if (!Cfg.ShowTimer.Value) { return ""; } float tamingTime = Tm.m_tamingTime; if (tamingTime <= 0f) { return ""; } float num = zDO.GetFloat("TameTimeLeft", tamingTime); if (!(num < tamingTime - 0.5f)) { return ""; } float num2 = Mathf.Clamp01(1f - num / tamingTime) * 100f; string text = "\n" + Loc.T("taming") + ": <color=yellow>" + Fmt(num) + "</color> / " + Fmt(tamingTime) + " (" + num2.ToString("0") + "%)"; if (SafeHungry()) { text = text + "\n<color=orange>" + Loc.T("paused") + "</color>"; } return text; } string text2 = ""; if (IsDowned) { text2 = text2 + "\n<color=red>" + Loc.T("knocked") + ": " + Fmt(DownLeft) + "</color> " + CompanionManager.WrapHint(CompanionManager.UseKeyHint()) + Loc.T("first_aid"); } else if (Tm.m_commandable && Cfg.ShowGroupKeyHint.Value) { text2 = text2 + "\n" + CompanionManager.WrapHint(CompanionManager.GroupKeyHint()) + Loc.T("all_cmd"); } return text2; } } internal static class CompanionManager { internal const string RecallRpc = "TC_Recall"; internal static bool PlayerDied; internal static float LastGroupCommand; private static int _mask = -1; private static readonly MethodInfo TakeInputMethod = AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null); private static readonly MethodInfo SetAlertedMethod = AccessTools.Method(typeof(BaseAI), "SetAlerted", (Type[])null, (Type[])null); private static readonly HashSet<string> GlyphLogged = new HashSet<string>(); private static int Mask { get { if (_mask < 0) { _mask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "terrain" }); } return _mask; } } internal static void Say(GameObject go, string text) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)Chat.instance == (Object)null) && !((Object)(object)go == (Object)null)) { MethodInfo methodInfo = AccessTools.Method(typeof(Chat), "SetNpcText", (Type[])null, (Type[])null); if (!(methodInfo == null)) { methodInfo.Invoke(Chat.instance, new object[7] { go, Vector3.up * 2f, 25f, 4f, "", text, false }); } } } catch { } } internal static bool CanTakeInput(Player p) { try { return TakeInputMethod == null || (bool)TakeInputMethod.Invoke(p, null); } catch { return true; } } internal static void SetAlerted(MonsterAI ai, bool alerted) { try { if (SetAlertedMethod != null) { SetAlertedMethod.Invoke(ai, new object[1] { alerted }); } } catch { } } internal static bool IsButcherKnife(ItemData w) { if (w == null || w.m_shared == null) { return false; } if (w.m_shared.m_name == "$item_knife_butcher") { return true; } return (Object)(object)w.m_dropPrefab != (Object)null && ((Object)w.m_dropPrefab).name == "KnifeButcher"; } private static string CleanName(string n) { return (n ?? "").Replace("(Clone)", "").Trim(); } internal static bool IsExcludedName(string prefabName) { string text = CleanName(prefabName); if (text.Length == 0) { return false; } string[] array = Cfg.DungeonExcluded.Value.Split(new char[1] { ',' }); foreach (string text2 in array) { if (string.Equals(text2.Trim(), text, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } internal static bool IsDungeonExcluded(GameObject go) { return IsExcludedName(((Object)go).name); } private static List<CompanionController> Nearby(Player p) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Vector3 pos = ((Component)p).transform.position; float r = Cfg.CommandRadius.Value; return CompanionController.All.Where((CompanionController c) => (Object)(object)c != (Object)null && (Object)(object)c.Nv != (Object)null && c.Nv.IsValid() && c.Ch.IsTamed() && c.Tm.m_commandable && !c.IsDowned && !c.ActionLocked && Vector3.Distance(((Component)c).transform.position, pos) <= r).ToList(); } private static void ApplyAll(Player p, List<CompanionController> list, bool follow) { foreach (CompanionController item in list) { item.SetFollow(p, follow); } try { ((MonoBehaviour)TameCompanionsPlugin.Instance).StartCoroutine(PetEffects(list)); } catch { } ((Character)p).Message((MessageType)2, follow ? Loc.T("follow_n", list.Count) : Loc.T("stay_n", list.Count), 0, (Sprite)null, false); } internal static void PlayPet(CompanionController c) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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) try { if (!((Object)(object)c == (Object)null) && !((Object)(object)c.Tm == (Object)null) && c.Tm.m_petEffect != null) { c.Tm.m_petEffect.Create(((Component)c).transform.position, ((Component)c).transform.rotation, (Transform)null, 1f, -1, default(ZDOID)); } } catch { } } private static IEnumerator PetEffects(List<CompanionController> list) { float gap = Mathf.Clamp(1.2f / (float)Mathf.Max(1, list.Count), 0.04f, 0.2f); for (int i = 0; i < list.Count; i++) { PlayPet(list[i]); if (i < list.Count - 1) { yield return (object)new WaitForSeconds(Random.Range(gap * 0.5f, gap)); } } } internal static void ToggleAll(Player p) { if (Time.time - LastGroupCommand < 0.6f) { return; } LastGroupCommand = Time.time; List<CompanionController> list = Nearby(p); if (list.Count == 0) { ((Character)p).Message((MessageType)2, Loc.T("none"), 0, (Sprite)null, false); return; } bool flag = list.Any((CompanionController c) => c.FollowsPlayer(p)); ApplyAll(p, list, !flag); } internal static int CountFollowers(Player p) { long playerID = p.GetPlayerID(); int num = 0; foreach (CompanionController item in CompanionController.All) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item.Nv == (Object)null) && item.Nv.IsValid() && !((Object)(object)item.Ch == (Object)null) && item.Ch.IsTamed() && item.LeaderId == playerID) { num++; } } return num; } internal static void ToggleSingle(CompanionController c, Player p) { if (!c.IsDowned && !c.ActionLocked && !(Time.time - c.LastToggle < 1f)) { c.LastToggle = Time.time; bool flag = c.LeaderId != 0L || (c.Nv.IsOwner() && (Object)(object)c.Ai.GetFollowTarget() != (Object)null); c.SetFollow(p, !flag); PlayPet(c); ((Character)p).Message((MessageType)2, SingleMessage(c, !flag), 0, (Sprite)null, false); if (Cfg.DebugLog.Value) { TameCompanionsPlugin.Log.LogInfo((object)$"ToggleSingle {((Object)c).name}: follow={!flag}"); } } } private static string SingleMessage(CompanionController c, bool follow) { string text = c.Ch.m_name; string text2 = null; try { if (Localization.instance != null) { string hoverName = c.Ch.GetHoverName(); text = Localization.instance.Localize(string.IsNullOrEmpty(hoverName) ? c.Ch.m_name : hoverName); text2 = Localization.instance.Localize(follow ? "$hud_tamefollow" : "$hud_tamestay"); if (string.IsNullOrEmpty(text2) || text2.StartsWith("[") || text2.Contains("$")) { text2 = null; } } } catch { text2 = null; } if (text2 == null) { text2 = Loc.T(follow ? "tame_follow" : "tame_stay"); } return text + " " + text2; } private unsafe static string PadName(GamepadButton b) { return ((object)(*(GamepadButton*)(&b))/*cast due to .constrained prefix*/).ToString() switch { "RightStickButton" => "R3", "LeftStickButton" => "L3", "LeftTrigger" => "L2/LT", "RightTrigger" => "R2/RT", "LeftShoulder" => "L1/LB", "RightShoulder" => "R1/RB", "ButtonSouth" => "✕/A", "ButtonEast" => "○/B", "ButtonWest" => "□/X", "ButtonNorth" => "△/Y", "DPadUp" => "D-Pad ↑", "DPadDown" => "D-Pad ↓", "DPadLeft" => "D-Pad ←", "DPadRight" => "D-Pad →", _ => ((object)(*(GamepadButton*)(&b))/*cast due to .constrained prefix*/).ToString(), }; } internal static string UseKeyHint() { bool flag = false; try { flag = ZInput.IsGamepadActive(); } catch { } try { if (Localization.instance != null) { string text = Localization.instance.Localize("$KEY_Use"); if (IsValidKeyText(text)) { return text; } } } catch { } return flag ? PadName((GamepadButton)5) : "E"; } private static bool IsValidKeyText(string k) { if (string.IsNullOrEmpty(k)) { return false; } if (k.Contains("$") || k.StartsWith("[")) { return false; } if (k.IndexOf("MISSING", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (k.IndexOf("BUTTON DEF", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (k.Contains("TC_Hint")) { return false; } return true; } private static string[] VanillaPadNames(string b) { return b switch { "ButtonSouth" => new string[1] { "JoyButtonA" }, "ButtonEast" => new string[1] { "JoyButtonB" }, "ButtonWest" => new string[1] { "JoyButtonX" }, "ButtonNorth" => new string[1] { "JoyButtonY" }, "LeftShoulder" => new string[1] { "JoyLBumper" }, "RightShoulder" => new string[1] { "JoyRBumper" }, "LeftTrigger" => new string[1] { "JoyLTrigger" }, "RightTrigger" => new string[1] { "JoyRTrigger" }, "LeftStickButton" => new string[1] { "JoyLStick" }, "RightStickButton" => new string[1] { "JoyRStick" }, "Start" => new string[1] { "JoyStart" }, "Select" => new string[1] { "JoyBack" }, "DPadUp" => new string[1] { "JoyDPadUp" }, "DPadDown" => new string[1] { "JoyDPadDown" }, "DPadLeft" => new string[1] { "JoyDPadLeft" }, "DPadRight" => new string[1] { "JoyDPadRight" }, _ => new string[0], }; } private static bool IsGlyph(string g) { return IsValidKeyText(g) && g.IndexOf("<sprite", StringComparison.OrdinalIgnoreCase) >= 0; } private static string LocalizeKey(string name) { try { if (Localization.instance != null) { return Localization.instance.Localize("$KEY_" + name); } } catch { } return null; } private unsafe static string TryPadGlyph(string hintName, GamepadButton btn) { List<string> list = new List<string> { hintName }; list.AddRange(VanillaPadNames(((object)(*(GamepadButton*)(&btn))/*cast due to .constrained prefix*/).ToString())); string result = null; foreach (string item in list) { string text = LocalizeKey(item); if (Cfg.DebugLog.Value && GlyphLogged.Add(item + "|" + text)) { TameCompanionsPlugin.Log.LogInfo((object)$"Glyph-Test $KEY_{item} -> '{text}' (Symbol={IsGlyph(text)})"); } if (IsGlyph(text)) { result = text; break; } } return result; } internal static string GroupKeyHint() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) bool flag = false; try { flag = ZInput.IsGamepadActive(); } catch { } if (!flag) { return ((object)Cfg.CommandAllKey.Value/*cast due to .constrained prefix*/).ToString(); } bool flag2 = ((object)Cfg.CommandAllPadModifier.Value/*cast due to .constrained prefix*/).ToString() != "None"; string text = TryPadGlyph("TC_HintMain", Cfg.CommandAllPad.Value); string text2 = (flag2 ? TryPadGlyph("TC_HintMod", Cfg.CommandAllPadModifier.Value) : null); if (text != null && (!flag2 || text2 != null)) { return flag2 ? (text2 + " + " + text) : text; } string text3 = PadName(Cfg.CommandAllPad.Value); return flag2 ? (PadName(Cfg.CommandAllPadModifier.Value) + " + " + text3) : text3; } internal static string WrapHint(string hint) { if (hint != null && hint.Contains("<sprite")) { return hint + " "; } return "[<color=yellow><b>" + hint + "</b></color>] "; } internal static bool IsFreeSpot(Vector3 feet, float radius) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0069: Unknown result type (might be due to invalid IL or missing references) try { float num = Mathf.Clamp(radius * 0.8f, 0.25f, 1.5f); float num2 = Mathf.Clamp(radius * 2f, 1f, 1.8f); Vector3 val = feet + Vector3.up * (num + 0.2f); Vector3 val2 = feet + Vector3.up * Mathf.Max(num + 0.2f, num2 - num); return !Physics.CheckCapsule(val, val2, num, Mask, (QueryTriggerInteraction)1); } catch { return true; } } internal static Vector3 FindBehind(Player leader, float dist, out Quaternion rot, float radius = 0.5f) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: 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_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: 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_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)leader).transform.position; Vector3 forward = ((Component)leader).transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.001f) { forward = Vector3.forward; } ((Vector3)(ref forward)).Normalize(); rot = Quaternion.LookRotation(forward); float[] array = new float[4] { 1f, 0.7f, 1.5f, 2.2f }; float[] array2 = new float[7] { 0f, 25f, -25f, 50f, -50f, 75f, -75f }; Vector3 val = position + Vector3.up * 1.2f; float[] array3 = array; Vector3 val4 = default(Vector3); RaycastHit val5 = default(RaycastHit); foreach (float num in array3) { float[] array4 = array2; foreach (float num2 in array4) { Vector3 val2 = Quaternion.AngleAxis(num2, Vector3.up) * -forward; if (Vector3.Dot(val2, forward) > -0.2f) { continue; } Vector3 val3 = position + val2 * (dist * num); ((Vector3)(ref val4))..ctor(val3.x, position.y + 1.5f, val3.z); if (Physics.Raycast(val4, Vector3.down, ref val5, 6f, Mask) && !(((RaycastHit)(ref val5)).normal.y < 0.6f)) { Vector3 val6 = ((RaycastHit)(ref val5)).point + Vector3.up * 0.15f; if (!Physics.Linecast(val, val6 + Vector3.up * 1f, Mask) && IsFreeSpot(val6, radius)) { return val6; } } } } Vector3 val7 = position - forward * 1.5f + Vector3.up * 0.2f; if (IsFreeSpot(val7, radius)) { return val7; } float[] array5 = new float[3] { 1.2f, 2f, 2.8f }; RaycastHit val10 = default(RaycastHit); for (int k = 0; k < array5.Length; k++) { for (int l = 0; l < 8; l++) { Vector3 val8 = Quaternion.AngleAxis((float)l * 45f, Vector3.up) * -forward; Vector3 val9 = position + val8 * array5[k]; if (Physics.Raycast(new Vector3(val9.x, position.y + 1.5f, val9.z), Vector3.down, ref val10, 4f, Mask) && !(((RaycastHit)(ref val10)).normal.y < 0.6f)) { Vector3 val11 = ((RaycastHit)(ref val10)).point + Vector3.up * 0.15f; if (!Physics.Linecast(val, val11 + Vector3.up * 1f, Mask) && IsFreeSpot(val11, radius)) { return val11; } } } } return position + Vector3.up * 0.3f; } internal static IEnumerator RecallAfterTeleport(Player p) { yield return null; yield return null; float t = 0f; while ((Object)(object)p != (Object)null && ((Character)p).IsTeleporting() && t < 40f) { t += Time.deltaTime; yield return null; } yield return (object)new WaitForSeconds(1f); if ((Object)(object)p != (Object)null && (Object)(object)p == (Object)(object)Player.m_localPlayer) { SendRecall(p); } } internal static IEnumerator RecallAfterRespawn(Player p) { yield return (object)new WaitForSeconds(3f); if ((Object)(object)p != (Object)null && (Object)(object)p == (Object)(object)Player.m_localPlayer) { SendRecall(p); } } internal static void SendRecall(Player p) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) try { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance != null) { instance.InvokeRoutedRPC(0L, "TC_Recall", new object[2] { p.GetPlayerID(), ((Component)p).transform.position }); } } catch (Exception ex) { TameCompanionsPlugin.Log.LogWarning((object)("Recall-Fehler: " + ex.Message)); } } internal static void RPC_Recall(long sender, long leaderId, Vector3 pos) { //IL_008a: 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_013e: 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_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || !Cfg.Enabled.Value) { return; } FieldInfo fieldInfo = AccessTools.Field(typeof(ZDOMan), "m_objectsByID"); IDictionary dictionary = ((fieldInfo != null) ? (fieldInfo.GetValue(ZDOMan.instance) as IDictionary) : null); if (dictionary == null) { return; } bool flag = pos.y > 3000f; List<ZDO> list = new List<ZDO>(dictionary.Count); foreach (object value in dictionary.Values) { ZDO val = (ZDO)((value is ZDO) ? value : null); if (val != null) { list.Add(val); } } int num = 0; foreach (ZDO item in list) { if (item.GetLong(CompanionController.H_Leader, 0L) != leaderId || Vector3.Distance(item.GetPosition(), pos) < Cfg.NoTeleportNear.Value) { continue; } if (flag) { if (!Cfg.FollowDungeons.Value) { continue; } GameObject val2 = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(item.GetPrefab()) : null); if ((Object)(object)val2 != (Object)null && IsExcludedName(((Object)val2).name)) { continue; } } item.SetOwner(ZDOMan.GetSessionID()); item.Set("TC_Snap", true); item.SetPosition(pos + Vector3.up * 0.5f); item.SetOwner(0L); num++; } if (num > 0) { TameCompanionsPlugin.Log.LogInfo((object)$"Recall: {num} Tame(s) zu Spieler {leaderId} verschoben."); } } catch (Exception ex) { TameCompanionsPlugin.Log.LogWarning((object)("RPC_Recall: " + ex)); } } internal static void AwardKill(Character victim, Character attacker) { //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) if (!Cfg.StarsEnabled.Value || Cfg.MaxStars.Value <= 0 || (Object)(object)victim == (Object)null || (Object)(object)attacker == (Object)null || victim.IsTamed() || victim.IsPlayer()) { return; } float maxHealth = victim.GetMaxHealth(); if (maxHealth < Cfg.MinVictimHp.Value) { return; } float num = maxHealth * (1f + 0.3f * (float)(victim.GetLevel() - 1)) * (victim.IsBoss() ? 2f : 1f) * Cfg.XpMult.Value; CompanionController value = null; long num2 = 0L; if (attacker.IsTamed() && CompanionController.ByCharacter.TryGetValue(attacker, out value)) { value.GiveXp(num); num2 = value.LeaderId; } else { Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null) { num2 = val.GetPlayerID(); } } if (num2 == 0) { return; } Vector3 position = ((Component)victim).transform.position; foreach (CompanionController item in CompanionController.All.ToList()) { if (!((Object)(object)item == (Object)null) && !((Object)(object)item == (Object)(object)value) && item.Ch.IsTamed() && item.LeaderId == num2 && !(Vector3.Distance(((Component)item).transform.position, position) > Cfg.XpShareRadius.Value)) { item.GiveXp(num * Cfg.XpShare.Value); } } } } internal static class ShipHelper { private static readonly MethodInfo GetLocalShip = AccessTools.Method(typeof(Ship), "GetLocalShip", (Type[])null, (Type[])null); private static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[32]; private static long _cId; private static float _cTime = -1f; private static Ship _cShip; private static Ship ShipBelow(Vector3 pos, float maxDown) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) int num = Physics.RaycastNonAlloc(pos + Vector3.up * 0.6f, Vector3.down, Hits, maxDown + 0.6f, -5, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { if (!((Object)(object)((RaycastHit)(ref Hits[i])).collider == (Object)null)) { Ship componentInParent = ((Component)((RaycastHit)(ref Hits[i])).collider).GetComponentInParent<Ship>(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } } } return null; } internal static Ship ShipOf(Player p) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null) { return null; } long playerID = p.GetPlayerID(); if (playerID == _cId && Time.time - _cTime < 0.25f) { return _cShip; } Ship val = null; try { val = ((Character)p).GetStandingOnShip(); if ((Object)(object)val == (Object)null && (Object)(object)p == (Object)(object)Player.m_localPlayer && GetLocalShip != null) { object? obj = GetLocalShip.Invoke(null, null); val = (Ship)((obj is Ship) ? obj : null); } if ((Object)(object)val == (Object)null) { val = ShipBelow(((Component)p).transform.position, 2f); } } catch { val = null; } _cId = playerID; _cTime = Time.time; _cShip = val; return val; } internal static bool IsAboard(Vector3 pos, Ship ship) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) try { return (Object)(object)ship != (Object)null && (Object)(object)ShipBelow(pos, 1.3f) == (Object)(object)ship; } catch { return false; } } internal static bool IsMoving(Ship ship) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) try { Rigidbody component = ((Component)ship).GetComponent<Rigidbody>(); int result; if ((Object)(object)component != (Object)null) { Vector3 velocity = component.velocity; result = ((((Vector3)(ref velocity)).sqrMagnitude > 1f) ? 1 : 0); } else { result = 0; } return (byte)result != 0; } catch { return false; } } internal static bool Excluded(GameObject go) { string text = (((Object)go).name ?? "").Replace("(Clone)", "").Trim(); if (text.Length == 0) { return false; } string[] array = Cfg.ShipExcluded.Value.Split(new char[1] { ',' }); foreach (string text2 in array) { if (string.Equals(text2.Trim(), text, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } internal static bool TryFindDeck(Ship ship, Player leader, CompanionController self, out Vector3 pos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: 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) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: 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_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; Vector3 position = ((Component)leader).transform.position; int num = Mathf.Abs(((Object)self).GetInstanceID()) % 9; float[] array = new float[4] { 1.6f, 2.4f, 3.2f, 4f }; float[] array2 = array; foreach (float num2 in array2) { for (int j = 0; j < 9; j++) { float num3 = (float)((num + j) % 9) * 40f; Vector3 val = Quaternion.AngleAxis(num3, Vector3.up) * Vector3.forward * num2; Vector3 val2 = position + val + Vector3.up * 2.5f; int num4 = Physics.RaycastNonAlloc(val2, Vector3.down, Hits, 5f, -5, (QueryTriggerInteraction)1); bool flag = false; RaycastHit val3 = default(RaycastHit); for (int k = 0; k < num4; k++) { RaycastHit val4 = Hits[k]; if (!((Object)(object)((RaycastHit)(ref val4)).collider == (Object)null) && !(((RaycastHit)(ref val4)).normal.y < 0.6f) && !((Object)(object)((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<Ship>() != (Object)(object)ship) && !(((RaycastHit)(ref val4)).point.y < position.y - 1.2f) && !(((RaycastHit)(ref val4)).point.y > position.y + 1.2f) && (!flag || ((RaycastHit)(ref val4)).distance < ((RaycastHit)(ref val3)).distance)) { val3 = val4; flag = true; } } if (!flag) { continue; } Vector3 val5 = ((RaycastHit)(ref val3)).point + Vector3.up * 0.25f; if (Physics.Linecast(((RaycastHit)(ref val3)).point + Vector3.up * 0.3f, ((RaycastHit)(ref val3)).point + Vector3.up * 1.6f, -5, (QueryTriggerInteraction)1)) { continue; } bool flag2 = false; foreach (CompanionController item in CompanionController.All) { if ((Object)(object)item != (Object)null && (Object)(object)item != (Object)(object)self) { Vector3 val6 = ((Component)item).transform.position - val5; if (((Vector3)(ref val6)).sqrMagnitude < 1f) { flag2 = true; break; } } } if (!flag2) { pos = val5; return true; } } } return false; } } internal static class Loc { internal static readonly string[] Order = new string[14] { "English", "German", "French", "Spanish", "Portuguese", "Italian", "Russian", "Polish", "Turkish", "Dutch", "Swedish", "Chinese", "Japanese", "Korean" }; internal static readonly string[] Options = new string[1] { "Auto" }.Concat(Order).ToArray(); private static readonly Dictionary<string, string[]> Table = new Dictionary<string, string[]> { ["down_say"] = new string[14] { "*knocked out*", "*bewusstlos*", "*assommé*", "*inconsciente*", "*inconsciente*", "*privo di sensi*", "*без сознания*", "*nieprzytomny*", "*bayıldı*", "*bewusteloos*", "*medvetslös*", "*昏迷*", "*気絶*", "*기절*" }, ["up_say"] = new string[14] { "*recovers*", "*erholt sich*", "*se remet*", "*se recupera*", "*se recupera*", "*si riprende*", "*приходит в себя*", "*dochodzi do siebie*", "*kendine geliyor*", "*komt bij*", "*piggnar till*", "*恢复了*", "*回復した*", "*회복했다*" }, ["star_up"] = new string[14] { "Star gained! ({0}/{1})", "Stern aufgestiegen! ({0}/{1})", "Étoile gagnée ! ({0}/{1})", "¡Estrella obtenida! ({0}/{1})", "Estrela conquistada! ({0}/{1})", "Stella ottenuta! ({0}/{1})", "Получена звезда! ({0}/{1})", "Zdobyto gwiazdkę! ({0}/{1})", "Yıldız kazanıldı! ({0}/{1})", "Ster verdiend! ({0}/{1})", "Stjärna intjänad! ({0}/{1})", "获得星级!({0}/{1})", "スターを獲得!({0}/{1})", "별 획득! ({0}/{1})" }, ["taming"] = new string[14] { "Taming", "Zähmung", "Apprivoisement", "Domesticación", "Domesticação", "Addomesticamento", "Приручение", "Oswajanie", "Evcilleştirme", "Temmen", "Tämjning", "驯服", "テイム", "길들이기" }, ["follows"] = new string[14] { "Follows: {0}", "Folgt: {0}", "Suit : {0}", "Sigue a: {0}", "Segue: {0}", "Segue: {0}", "Следует за: {0}", "Idzie za: {0}", "Takip ediyor: {0}", "Volgt: {0}", "Följer: {0}", "跟随:{0}", "追従:{0}", "따라감: {0}" }, ["paused"] = new string[14] { "Paused - hungry, feed it!", "Pausiert - hungrig, bitte füttern!", "En pause - affamé, nourrissez-le !", "En pausa: ¡tiene hambre, aliméntalo!", "Pausado - com fome, alimente-o!", "In pausa - ha fame, dagli da mangiare!", "Пауза - голоден, покормите!", "Wstrzymano - głodny, nakarm go!", "Duraklatıldı - aç, besleyin!", "Gepauzeerd - hongerig, voer het!", "Pausad - hungrigt, mata det!", "已暂停——饥饿,请喂食!", "一時停止 - 空腹です。餌をやってください!", "일시 중지 - 배고픔, 먹이를 주세요!" }, ["stars"] = new string[14] { "Stars", "Sterne", "Étoiles", "Estrellas", "Estrelas", "Stelle", "Звёзды", "Gwiazdki", "Yıldızlar", "Sterren", "Stjärnor", "星级", "スター", "별" }, ["knocked"] = new string[14] { "Knocked out", "Bewusstlos", "Assommé", "Inconsciente", "Inconsciente", "Privo di sensi", "Без сознания", "Nieprzytomny", "Bayıldı", "Bewusteloos", "Medvetslös", "昏迷", "気絶", "기절" }, ["first_aid"] = new string[14] { "First aid", "Erste Hilfe", "Premiers soins", "Primeros auxilios", "Primeiros socorros", "Primo soccorso", "Первая помощь", "Pierwsza pomoc", "İlk yardım", "Eerste hulp", "Första hjälpen", "急救", "応急処置", "응급처치" }, ["all_cmd"] = new string[14] { "All follow / stay", "Alle folgen / bleiben", "Tous suivent / restent", "Todos siguen / se quedan", "Todos seguem / ficam", "Tutti seguono / restano", "Все следуют / стоят", "Wszyscy idą za / stoją", "Hepsi takip eder / bekler", "Allen volgen / blijven", "Alla följer / stannar", "全体跟随 / 停留", "全員追従 / 待機", "전체 따라가기 / 대기" }, ["follow_n"] = new string[14] { "{0} tame(s) following you", "{0} Tame(s) folgen dir", "{0} apprivoisé(s) vous suivent", "{0} domesticado(s) te siguen", "{0} domesticado(s) estão te seguindo", "{0} addomesticato/i ti seguono", "Приручённых следует за вами: {0}", "Oswojone zwierzęta idą za tobą: {0}", "{0} evcil hayvan seni takip ediyor", "{0} getemde dier(en) volgen je", "{0} tämjda djur följer dig", "{0} 只驯服的动物正在跟随你", "{0}匹のテイム済みが付いてきます", "길들인 동물 {0}마리가 따라옵니다" }, ["stay_n"] = new string[14] { "{0} tame(s) staying", "{0} Tame(s) bleiben stehen", "{0} apprivoisé(s) restent sur place", "{0} domesticado(s) se quedan", "{0} domesticado(s) ficam parados", "{0} addomesticato/i restano fermi", "Приручённых остаётся на месте: {0}", "Oswojone zwierzęta zostają: {0}", "{0} evcil hayvan bekliyor", "{0} getemde dier(en) blijven staan", "{0} tämjda djur stannar", "{0} 只驯服的动物原地待命", "{0}匹のテイム済みが待機します", "길들인 동물 {0}마리가 대기합니다" }, ["tame_follow"] = new string[14] { "is following you", "folgt dir", "vous suit", "te sigue", "está te seguindo", "ti segue", "следует за вами", "idzie za tobą", "seni takip ediyor", "volgt je", "följer dig", "正在跟随你", "が付いてきます", "따라옵니다" }, ["tame_stay"] = new string[14] { "is staying", "bleibt stehen", "reste sur place", "se queda", "fica parado", "resta fermo", "остаётся на месте", "zostaje", "bekliyor", "blijft staan", "stannar", "原地待命", "が待機します", "대기합니다" }, ["none"] = new string[14] { "No tames in range", "Keine Tames in Reichweite", "Aucun apprivoisé à portée", "Ningún domesticado a su alcance", "Nenhum domesticado ao alcance", "Nessun addomesticato nelle vicinanze", "Нет приручённых поблизости", "Brak oswojonych w zasięgu", "Menzilde evcil hayvan yok", "Geen getemde dieren in de buurt", "Inga tämjda djur inom räckhåll", "范围内没有驯服的动物", "範囲内にテイム済みがいません", "범위 내에 길들인 동물이 없습니다" } }; private static int CurrentIndex() { string text = ((Cfg.Language != null) ? Cfg.Language.Value : "English"); if (text != "Auto") { int num = Array.IndexOf(Order, text); return (num >= 0) ? num : 0; } try { string text2 = ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : "English"); if (text2.StartsWith("Portuguese")) { text2 = "Portuguese"; } if (text2.StartsWith("Chinese")) { text2 = "Chinese"; } int num2 = Array.IndexOf(Order, text2); return (num2 >= 0) ? num2 : 0; } catch { return 0; } } internal static string T(string key, params object[] args) { string text = key; if (Table.TryGetValue(key, out var value)) { int num = CurrentIndex(); text = ((num < value.Length && !string.IsNullOrEmpty(value[num])) ? value[num] : value[0]); } try { return (args != null && args.Length != 0) ? string.Format(text, args) : text; } catch { return text; } } } [HarmonyPatch(typeof(Tameable), "Awake")] internal static class P_Tameable_Awake { private static void Postfix(Tameable __instance) { try { if ((Object)(object)((Component)__instance).GetComponent<CompanionController>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<CompanionController>(); } } catch (Exception ex) { TameCompanionsPlugin.Log.LogWarning((object)("Tameable.Awake: " + ex.Message)); } } } [HarmonyPatch(typeof(Tameable), "GetHoverText")] internal static class P_Tameable_Hover { private static void Postfix(Tameable __instance, ref string __result) { try { if (Cfg.Enabled.Value) { CompanionController component = ((Component)__instance).GetComponent<CompanionController>(); if ((Object)(object)component != (Object)null) { __result += component.ExtraHover(); } } } catch { } } } [HarmonyPatch(typeof(Tameable), "Interact")] internal static class P_Tameable_Interact { private static bool Prefix(Tameable __instance, Humanoid user, bool hold, bool alt, ref bool __result) { try { if (!Cfg.Enabled.Value) { return true; } CompanionController component = ((Component)__instance).GetComponent<CompanionController>(); Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)component == (Object)null || (Object)(object)val == (Object)null || !component.Ch.IsTamed()) { return true; } if (component.IsDowned) { if (!hold && Time.time - CompanionManager.LastGroupCommand > 0.4f) { CompanionManager.LastGroupCommand = Time.time; component.Help(); } __result = true; return false; } if (Cfg.DebugLog.Value) { TameCompanionsPlugin.Log.LogInfo((object)$"Interact {((Object)component).name}: hold={hold} alt={alt} gamepad={ZInput.IsGamepadActive()} locked={component.ActionLocked}"); } if (!hold && !alt && __instance.m_commandable) { if (!component.ActionLocked) { CompanionManager.ToggleSingle(component, val); } __result = true; return false; } } catch (Exception ex) { TameCompanionsPlugin.Log.LogWarning((object)("Interact: " + ex.Message)); } return true; } } [HarmonyPatch] internal static class P_BaseAI_Follow { private static MethodBase TargetMethod() { return AccessTools.DeclaredMethod(typeof(BaseAI), "Follow", new Type[2] { typeof(GameObject), typeof(float) }, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } private static bool Prefix(BaseAI __instance, GameObject go) { try { if (!Cfg.Enabled.Value) { return true; } if (!CompanionController.ByAi.TryGetValue(__instance, out var value) || (Object)(object)value == (Object)null) { return true; } return !value.HoldFollow(go); } catch { return true; } } } [HarmonyPatch] internal static class P_OnDeath { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.DeclaredMethod(typeof(Character), "OnDeath", (Type[])null, (Type[])null); MethodBase h = AccessTools.DeclaredMethod(typeof(Humanoid), "OnDeath", (Type[])null, (Type[])null); if (h != null) { yield return h; } } private static bool Prefix(Character __instance) { try { if (!Cfg.Enabled.Value || !Cfg.TamesProtected()) { return true; } if ((Object)(object)__instance == (Object)null || __instance.IsPlayer() || !__instance.IsTamed()) { return true; } if (!CompanionController.ByCharacter.TryGetValue(__instance, out var value)) { return true; } if (Cfg.OnlyButcherKnifeKills.Value && value.ButcherActive) { return true; } value.EnterDowned(); return false; } catch (Exception ex) { TameCompanionsPlugin.Log.LogWarning((object)("OnDeath: " + ex.Mes