using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Valheim.SettingsGui;
using Zen.Config;
using Zen.Controls;
using Zen.Lib;
using Zen.Logging;
using ZenTargeting.Compatibility;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenTargeting")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenTargeting")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 ZenTargeting
{
public static class Configs
{
public static readonly ConfigEntry<float> ScanLimitCycleTarget;
public static readonly ConfigEntry<float> ScanLimitNoTarget;
public static readonly ConfigEntry<bool> IsEnabledLoS;
public static readonly ConfigEntry<StringList> ExcludeTargetsLoS;
public static readonly ConfigEntry<StringList> IgnoreTargets;
public static readonly ConfigEntry<float> MaxTimeNoLoS;
public static readonly ConfigEntry<float> MaxTargetRange;
public static readonly ConfigEntry<bool> TargetSoftEnable;
public static readonly ConfigEntry<KeyCode> TargetSoftKey;
public static readonly ConfigEntry<KeyCode> TargetLockKey;
public static readonly ConfigEntry<KeyCode> TargetNextKey;
public static readonly ConfigEntry<KeyCode> TargetPrevKey;
public static readonly ConfigEntry<bool> AlwaysAttackTowardsLockedTarget;
public static readonly ConfigEntry<float> FloatingHudLingerDuration;
public static readonly ConfigEntry<int> TargetHUDMaxStars;
public static readonly ConfigEntry<bool> ShowTargetMark;
public static readonly (ConfigEntry<bool> Name, ConfigEntry<bool> Stars, ConfigEntry<bool> Health) ShowTargetHUD;
public static readonly (ConfigEntry<bool> Name, ConfigEntry<bool> Stars, ConfigEntry<bool> Health) ShowFloating;
static Configs()
{
ScanLimitNoTarget = Config.Define<float>(true, "Scanning", "Scan Ratio - No Target", 0.95f, Config.AcceptRange<float>(-1f, 1f), "Scan deviation ratio from camera line of sight when nothing is targeted. \nAs you approach 1 the more narrow your scan area.\nIf you set this to a negative value it will scan behind you.\n1 = looking directly at target, 0 = 180 degree fov, -1 = 360 degree fov");
ScanLimitCycleTarget = Config.Define<float>(true, "Scanning", "Scan Ratio - Cycle Target", 0.6f, Config.AcceptRange<float>(-1f, 1f), "Scan deviation ratio when from camera line of sight when locked and cycling for the next target.\nWhen a target is already locked it can scan a wider area to find the next target more easily.\nShould be equal to or less than \"" + ((ConfigEntryBase)ScanLimitNoTarget).Definition.Key + "\"\n1 = looking directly at the target, 0 = 180 degree fov, -1 = 360 degree fov");
IsEnabledLoS = Config.Define<bool>(true, "Scanning", "Line Of Sight", true, "Use line of sight when checking for target. If disabled then enemies can be targeted through walls.\nUseful for debugging compatibility with mods that did not set the layer mask correctly on their mobs.\nAs such they are being detected as terrain. You can disable Line of Sight checks to see if the monster\nis targetable. If it is then add the monster to the ExcludeLoSTargets list and contact the mod author to correct\ntheir layer mask to be 'character' not 'Default'");
ExcludeTargetsLoS = Config.Define<StringList>(true, "Scanning", "Exculde LoS Targets", StringList.Empty, "Comma separated list of prefab names that will always ignore Line of Sight checks.\nUse for compatibility with other mods that do not have the correct layer mask set for monsters.");
MaxTimeNoLoS = Config.Define<float>(true, "Scanning", "Max Time No Line Of Sight", 6f, "Maximum amount of time that line of sight can be lost before the lock will break. (seconds)");
MaxTargetRange = Config.Define<float>(true, "Scanning", "Max Target Range", 0f, Config.AcceptRange<float>(0f, 50f), "Maximum distance the target can be from the player for targeting.\nIf set to 0 then the max distance will be the vanilla EnemyHud.m_maxShowDistance (30).\nThe farther this distance is the more targets will be found at once and can make the game too easy.");
IgnoreTargets = Config.Define<StringList>(true, "Scanning", "Ignore Targets", StringList.Empty, "Comma separated list of prefab names that will always be ignored and can not be targeted\nIgnored targets do not display their name or stars or hp bars. They are ignored - no info.");
TargetSoftEnable = Config.Define<bool>(false, "Input", "Target Soft - Enable", true, "Target lock - Press and hold (Zelda-style) [Restart required]\nIf disabled then no soft lock is possible on gamepad or keyboard.");
TargetSoftKey = Config.Define<KeyCode>(false, "Input", "Target Soft - Override", (KeyCode)0, "Keyboard: Target lock - Press and hold (Zelda-style)\nIf set to None defaults to the Block button as defined to in the game settings.");
TargetLockKey = Config.Define<KeyCode>(false, "Input", "Target Lock", (KeyCode)116, "Keyboard: Target lock - Toggle lock (Souls-style)");
TargetPrevKey = Config.Define<KeyCode>(false, "Input", "Target Prev", (KeyCode)113, "Keyboard: Cycle target prev (Left)");
TargetNextKey = Config.Define<KeyCode>(false, "Input", "Target Next", (KeyCode)101, "Keyboard: Cycle target next (Right)");
AlwaysAttackTowardsLockedTarget = Config.Define<bool>(false, "Input", "Always Attack Towards Locked Target", false, "If target locked, always attack in the direction of the locked target.\nIf the game setting 'Attack towards look direction' is enabled this will override it.");
TargetHUDMaxStars = Config.Define<int>(true, "UI", "Target HUD - Max Stars", 10, Config.AcceptRange<int>(2, 30), "Max number of stars that can be displayed on the Target HUD (Vanilla: 2) \r\nOnly needed if you use mods which which increase the max number of stars such as Humanoid Randomizer or CLLC\r\nDefault is 10 because that way it works out of the box with most mods that increase the max monster level.\r\nIf you need to display more than 10 stars you can adjust it here. Anything more than you need is just wasting CPU.\r\nNOTE: This does not affect the level of spawned monsters. It just affects how many stars the HUD can display.");
ShowTargetHUD.Name = Config.Define<bool>(true, "UI", "Target HUD - Show Name", true, "Show current target name at the top of the screen.\nIf disabled the name will show floating over the target, cluttering your view with stupid redudnant immersion breaking text, yuck.");
ShowTargetHUD.Stars = Config.Define<bool>(true, "UI", "Target HUD - Show Stars", true, "Show current target stars at the top of the screen.\nIf disabled the stars will show floating over the target, cluttering your view with big ugly immersion breaking stars, yuck.");
ShowTargetHUD.Health = Config.Define<bool>(true, "UI", "Target HUD - Show Health", true, "Show the current target's HP bar at the top of the screen near their name.");
ShowFloating.Name = Config.Define<bool>(true, "UI", "Floating HUD - Show Name", false, "Show enemy name floating over their head.\nWhen enabled you see the name floating over the target's head with stupid redundant immersion breaking text, yuck!");
ShowFloating.Stars = Config.Define<bool>(true, "UI", "Floating HUD - Show Stars", false, "Show enemy stars floating over their head.\nWhen enabled you see the big ugly stars floating over the target's head breaking immersion and looking goofy, yuck!");
ShowFloating.Health = Config.Define<bool>(true, "UI", "Floating HUD - Show Health", false, "Show enemy HP bars floating over their head.\nWhen disabled it is more immersive and challenging. You don't see the bar over the target. Prettier too.");
ShowTargetMark = Config.Define<bool>(true, "UI", "Target Marker - Show", true, "Show the target marker on the selected target.\r\nWithout it you will have to rely on your eyes alone.\r\nMore immersive to not see the target marker, but also more challenging.");
FloatingHudLingerDuration = Config.Define<float>(true, "UI", "Floating HUD - Linger Duration", 0.3f, Config.AcceptRange<float>(0f, 60f), $"How long the floating HUD will linger before vanishing. (Vanilla: {60f}s)\r\nThis is how long the HUD will be shown after the cursor passes over a target before it disappears when you do not have a lock.");
}
}
[HarmonyPatch]
internal static class InputPatch
{
[HarmonyPrefix]
[HarmonyPatch(typeof(Player), "Interact")]
public static void Player_Interact(ref bool __runOriginal)
{
__runOriginal = TargetHud.CanShowCrosshair();
}
[HarmonyPostfix]
[HarmonyPatch(typeof(GamepadMap), "UpdateMap")]
private static void GamepadMap_UpdateMap(GamepadMap __instance)
{
TextMeshProUGUI label = __instance.joyAxis4And5.Label;
((TMP_Text)label).text = ((TMP_Text)label).text + " / Cycle targets";
}
}
internal static class Inputs
{
public static readonly ActionString TargetQuick = new ActionString("TargetQuick", "Target hold", true);
public static readonly ActionString TargetLock = new ActionString("TargetLock", "Target lock", true);
public static readonly ActionString TargetNext = new ActionString("TargetNext", "Next", true);
public static readonly ActionString TargetPrev = new ActionString("TargetPrev", "Prev", true);
private const string CycleTargetHintName = "ZenTargeting_CycleTargets";
internal const string CycleTargetLabel = "Cycle targets";
private static (GameObject? Keyboard, GameObject? Gamepad) _cycleHints;
public static void RegisterConfigEvents()
{
Configs.TargetSoftKey.SettingChanged += delegate
{
RegisterInputs();
};
Configs.TargetLockKey.SettingChanged += delegate
{
RegisterInputs();
};
Configs.TargetNextKey.SettingChanged += delegate
{
RegisterInputs();
};
Configs.TargetPrevKey.SettingChanged += delegate
{
RegisterInputs();
};
}
public static void Init()
{
AddKeyHints();
}
public static void Shutdown()
{
Object.Destroy((Object)(object)_cycleHints.Keyboard);
Object.Destroy((Object)(object)_cycleHints.Gamepad);
}
public static void RegisterInputs()
{
ResetInputs();
SetKeyboardInputs();
SetGamepadInputs();
}
private static void ResetInputs()
{
TargetLock.RemoveButtons();
TargetQuick.RemoveButtons();
TargetNext.RemoveButtons();
TargetPrev.RemoveButtons();
}
private static void SetKeyboardInputs()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: 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_0095: Unknown result type (might be due to invalid IL or missing references)
TargetLock.AddButton(Configs.TargetLockKey.Value, false, false, false, 0f, 0f);
TargetPrev.AddButton(Configs.TargetPrevKey.Value, false, false, false, 0f, 0f);
TargetNext.AddButton(Configs.TargetNextKey.Value, false, false, false, 0f, 0f);
if (Configs.TargetSoftEnable.Value)
{
if ((int)Configs.TargetSoftKey.Value == 0)
{
TargetQuick.Alias("Block");
}
else
{
TargetQuick.AddButton(Configs.TargetSoftKey.Value, false, false, false, 0f, 0f);
}
}
}
private static void SetGamepadInputs()
{
TargetLock.AddButton((GamepadInput)14, false, true, false, 0f, 0f);
TargetPrev.AddButton((GamepadInput)24, false, true, false, 0f, 0f);
TargetNext.AddButton((GamepadInput)25, false, true, false, 0f, 0f);
if (Configs.TargetSoftEnable.Value)
{
TargetQuick.Alias("JoyBlock");
}
}
private static void AddKeyHints()
{
KeyHint.Create((HintType)1, TargetLock, 0, false);
KeyHint.SetEvent((HintType)1, (Action)UpdateCombatHints);
KeyHint.SetEvent((HintType)2, (Action)UpdateBowHints);
CreateCycleTargetHints();
}
private static void CreateCycleTargetHints()
{
Transform source2 = KeyHints.instance.m_buildHints.transform.Find("Keyboard/Snap");
Transform destRoot2 = KeyHints.instance.m_combatHints.transform.Find("Keyboard");
_cycleHints.Keyboard = CopyHint(source2, destRoot2, "Cycle targets");
Transform source3 = KeyHints.instance.m_buildHints.transform.Find("Gamepad/Text - Snap");
Transform destRoot3 = KeyHints.instance.m_combatHints.transform.Find("Gamepad");
string spriteTag = ZInputExt.GetSpriteTag(ZInput.instance, (GamepadInput)12);
_cycleHints.Gamepad = CopyHint(source3, destRoot3, StringExt.Localize("Cycle targets ⇐ " + spriteTag + " ⇒"));
static GameObject CopyHint(Transform source, Transform destRoot, string label)
{
Transform obj = Object.Instantiate<Transform>(source, destRoot);
((Object)obj).name = ((Object)source).name.Replace("Snap", "ZenTargeting_CycleTargets");
obj.SetSiblingIndex(0);
((Component)obj).GetComponentInChildren<TMP_Text>().text = label;
return ((Component)obj).gameObject;
}
}
private static void UpdateCombatHints()
{
KeyHint.SetVisible(TargetLock, true);
KeyHint.SetVisible("ZenTargeting_CycleTargets", Object.op_Implicit((Object)(object)TargetTrack.LockedTarget));
}
private static void UpdateBowHints()
{
KeyHint.SetVisible(TargetLock, true);
KeyHint.SetVisible("ZenTargeting_CycleTargets", Object.op_Implicit((Object)(object)TargetTrack.LockedTarget));
}
}
internal struct LineOfSight
{
private const float _cooldown = 0.2f;
private float _lastTime;
private bool _result;
private bool Result
{
get
{
return _result;
}
set
{
_result = value;
IsCached = true;
}
}
private bool IsCached
{
get
{
return _lastTime != 0f;
}
set
{
_lastTime = (value ? Time.time : 0f);
}
}
public void UpdateCache()
{
if (Time.time > _lastTime + 0.2f)
{
this = default(LineOfSight);
}
}
public bool Scan(Target target, Transform? viewFrom)
{
//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_0076: 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_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: 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)
if (!Configs.IsEnabledLoS.Value)
{
return false;
}
if (IsCached)
{
return Result;
}
Hoverable? refComponent = target.RefComponent;
Character val = (Character)(object)((refComponent is Character) ? refComponent : null);
if (val != null)
{
string prefabName = Utils.GetPrefabName(((Object)val).name);
if (Configs.ExcludeTargetsLoS.Value.Contains(prefabName, true))
{
return Result = false;
}
}
viewFrom = (Transform?)(Object.op_Implicit((Object)(object)viewFrom) ? ((object)viewFrom) : ((object)((Component)GameCamera.instance).transform));
Vector3 position = viewFrom.position;
Result = Vector3.Dot(viewFrom.forward, target.LookAtPosition - position) < 0f || Physics.Linecast(position, target.LookAtPosition, Character.s_groundRayMask);
Log.Debug((object)$"{target.Name} _isObstructed: {Result}", (ushort)0);
return Result;
}
}
[DisallowMultipleComponent]
public class Target : MonoBehaviour
{
private float _lastSeenTime;
private LineOfSight _lineOfSight;
private static float MaxRange
{
get
{
if (!(Configs.MaxTargetRange.Value > 0f))
{
return EnemyHud.instance.m_maxShowDistance;
}
return Configs.MaxTargetRange.Value;
}
}
public Hoverable? RefComponent { get; private set; }
public string Name => GetName();
public bool IsBoss
{
get
{
Hoverable? refComponent = RefComponent;
Character val = (Character)(object)((refComponent is Character) ? refComponent : null);
if (val != null)
{
return val.IsBoss();
}
return false;
}
}
public Vector3 LookAtPosition => GetLookAtPosition();
private bool IsSelected => (Object)(object)TargetHud.SelectedTarget == (Object)(object)this;
public static bool IsValid(Target? target)
{
if (Object.op_Implicit((Object)(object)target))
{
return target.IsValid();
}
return false;
}
public static bool IsValid(MonoBehaviour? m)
{
if (Object.op_Implicit((Object)(object)m))
{
return IsValid(((Component)m).gameObject.Target());
}
return false;
}
public static bool IsValid(GameObject? g)
{
if (Object.op_Implicit((Object)(object)g))
{
return IsValid(g.Target());
}
return false;
}
private static Target Create(GameObject gameObject)
{
Target result = default(Target);
if (gameObject.TryGetComponent<Target>(ref result))
{
return result;
}
return gameObject.AddComponent<Target>();
}
public static Target Create(Character toon)
{
Target target = Create(((Component)toon).gameObject);
target.RefComponent = (Hoverable?)(object)toon;
return target;
}
private string GetName()
{
Hoverable? refComponent = RefComponent;
Player val = (Player)(object)((refComponent is Player) ? refComponent : null);
if (val != null)
{
return val.GetPlayerName();
}
if (RefComponent != null)
{
return RefComponent.GetHoverName();
}
return ((Object)((Component)this).gameObject).name;
}
private Vector3 GetLookAtPosition()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
Hoverable? refComponent = RefComponent;
Character val = (Character)(object)((refComponent is Character) ? refComponent : null);
if (val != null)
{
return val.GetCenterPoint();
}
return ((Component)this).transform.position;
}
private void OnEnable()
{
TargetList.Add(this);
}
private void OnDisable()
{
TargetList.Remove(this);
}
private void Update()
{
_lineOfSight.UpdateCache();
}
public bool IsValid()
{
if (Configs.IgnoreTargets.Value.Contains(GameObjectExt.GetPrefabName(((Component)this).gameObject), true))
{
return false;
}
Hoverable? refComponent = RefComponent;
Character val = (Character)(object)((refComponent is Character) ? refComponent : null);
if (val != null && (val.IsDead() || val.IsTamed() || (val.IsPlayer() && !val.IsPVPEnabled())))
{
return false;
}
if (!IsInRange(MaxRange))
{
return false;
}
if (!IsSeen())
{
return false;
}
return true;
}
public bool IsInRange(float range)
{
//IL_0016: 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)
Player localPlayer = Player.m_localPlayer;
if (!Object.op_Implicit((Object)(object)localPlayer))
{
return false;
}
return Utils.DistanceSqr(((Component)localPlayer).transform.position, ((Component)this).transform.position) < range * range;
}
internal bool IsObstructed(Transform? viewFrom = null)
{
return _lineOfSight.Scan(this, viewFrom);
}
public bool IsSeen()
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Invalid comparison between Unknown and I4
//IL_0037: 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)
if (Time.time < _lastSeenTime + Configs.MaxTimeNoLoS.Value)
{
return true;
}
Transform transform = ((Component)GameCamera.instance).transform;
if ((int)Player.m_localPlayer.GetCurrentBiome() == 512 && ParticleMist.IsMistBlocked(transform.position, LookAtPosition))
{
return false;
}
if (IsObstructed(transform))
{
return false;
}
_lastSeenTime = Time.time;
return true;
}
}
public class TargetHud : MonoBehaviour
{
private static TargetHud? _instance;
private readonly List<Transform> Stars = new List<Transform>();
private TextMeshProUGUI _displayName;
private GameObject _root;
private Transform _healthRoot;
private GuiBar _healthFast;
private GuiBar _healthSlow;
private Image _targetMark;
private float _hpPercentCached;
private const float TargetMarkScale = 0.35f;
private const float TargetHudOffsetY = 60f;
public static Target? SelectedTarget { get; private set; }
public static void Init()
{
//IL_001c: 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_003c: 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_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
if (Object.op_Implicit((Object)(object)_instance))
{
throw new Exception("TargetHud already initialized");
}
GameObject val = new GameObject("ZenTargeting");
val.transform.SetParent(Hud.instance.m_rootObject.transform, false);
val.transform.SetAsFirstSibling();
RectTransform obj = val.AddComponent<RectTransform>();
obj.anchorMin = new Vector2(0f, 1f);
obj.anchorMax = new Vector2(1f, 1f);
obj.offsetMax = new Vector2(0f, -60f);
_instance = val.AddComponent<TargetHud>();
}
public static void Shutdown()
{
if (Object.op_Implicit((Object)(object)_instance))
{
Object.Destroy((Object)(object)_instance);
}
}
public static void RegisterConfigEvents()
{
Configs.ShowTargetHUD.Stars.SettingChanged += delegate
{
UpdateConfigs();
};
Configs.ShowTargetHUD.Name.SettingChanged += delegate
{
UpdateConfigs();
};
Configs.ShowTargetHUD.Health.SettingChanged += delegate
{
UpdateConfigs();
};
Configs.TargetHUDMaxStars.SettingChanged += delegate
{
UpdateConfigs();
};
}
private static void UpdateConfigs()
{
if (Object.op_Implicit((Object)(object)_instance))
{
_instance.CreateHUD();
}
}
private void Awake()
{
CreateHUD();
CreateTargetMark();
}
private void OnDestroy()
{
Object.Destroy((Object)(object)((Component)_targetMark).gameObject);
Object.Destroy((Object)(object)((Component)this).gameObject);
}
private void CreateHUD()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_00ca: 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_00e5: 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_0161: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: Unknown result type (might be due to invalid IL or missing references)
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
//IL_023c: Unknown result type (might be due to invalid IL or missing references)
//IL_0276: Unknown result type (might be due to invalid IL or missing references)
//IL_028f: Unknown result type (might be due to invalid IL or missing references)
Log.Info((object)"Creating Targeting HUD", (ushort)0);
Object.Destroy((Object)(object)_root);
Stars.Clear();
_root = new GameObject("TargetHud", new Type[1] { typeof(RectTransform) });
_root.transform.SetParent(((Component)this).transform, false);
Transform transform = EnemyHud.instance.m_baseHudBoss.transform;
Log.Info((object)"Create name node", (ushort)0);
Transform val = Object.Instantiate<Transform>(transform.Find("Name"), _root.transform, false);
((Object)val).name = "Name";
_displayName = ((Component)val).GetComponent<TextMeshProUGUI>();
((Behaviour)_displayName).enabled = Configs.ShowTargetHUD.Name.Value;
((Graphic)_displayName).color = ZColor.op_Implicit(UIColor.ValheimOrange);
Transform transform2 = ((TMP_Text)_displayName).transform;
transform2.localScale *= 0.8f;
Log.Info((object)"Create health node", (ushort)0);
_healthRoot = Object.Instantiate<Transform>(transform.Find("Health"), _root.transform, false);
((Component)_healthRoot).gameObject.SetActive(Configs.ShowTargetHUD.Health.Value);
((Object)_healthRoot).name = "Health";
Transform healthRoot = _healthRoot;
Vector3 localScale = _healthRoot.localScale;
localScale.x = 0.5f;
localScale.y = 0.4f;
healthRoot.localScale = localScale;
Transform healthRoot2 = _healthRoot;
localScale = _healthRoot.localPosition;
localScale.y = 46f;
healthRoot2.localPosition = localScale;
_healthFast = ((Component)_healthRoot.Find("health_fast")).GetComponent<GuiBar>();
_healthSlow = ((Component)_healthRoot.Find("health_slow")).GetComponent<GuiBar>();
Log.Info((object)"Create star nodes", (ushort)0);
Transform val2 = EnemyHud.instance.m_baseHud.transform.Find("level_2");
for (int i = 0; i < Configs.TargetHUDMaxStars.Value; i++)
{
Transform val3 = Object.Instantiate<Transform>(val2, _root.transform, false);
((Object)val3).name = $"level_{i + 2}";
val3.localPosition = Vector3.zero;
for (int j = 0; j < i; j++)
{
Object.Instantiate<Transform>(val3.GetChild(0), val3, false);
}
for (int k = 0; k < val3.childCount; k++)
{
val3.GetChild(k).localPosition = Vector3.right * (float)(k * 8 - (val3.childCount - k - 1) * 8);
}
Stars.Add(val3);
}
}
private void CreateTargetMark()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: 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_0053: 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_0093: 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)
Log.Info((object)"Create target mark", (ushort)0);
GameObject val = new GameObject("TargetMark");
val.transform.SetParent(((Component)this).transform, false);
val.transform.localScale = Vector3.one * 0.35f;
Outline obj = val.AddComponent<Outline>();
((Shadow)obj).effectColor = Color.black;
((Shadow)obj).effectDistance = Vector2.one * 3f;
_targetMark = val.AddComponent<Image>();
_targetMark.sprite = Hud.instance.m_crosshair.sprite;
((Graphic)_targetMark).color = ZColor.op_Implicit(UIColor.ValheimOrange);
((Component)_targetMark).gameObject.SetActive(false);
}
private void SetPercentHP(float hpPercent)
{
if (!(Math.Abs(_hpPercentCached - hpPercent) < 0.001f))
{
_healthFast.SetValue(hpPercent);
_healthSlow.SetValue(hpPercent);
_hpPercentCached = hpPercent;
}
}
private bool UpdateVisibility(Target? target)
{
bool flag = Object.op_Implicit((Object)(object)target);
bool flag2 = !Object.op_Implicit((Object)(object)Player.m_localPlayer) || ((Character)Player.m_localPlayer).IsDead();
int num;
if (Object.op_Implicit((Object)(object)target))
{
Hoverable? refComponent = target.RefComponent;
Character val = (Character)(object)((refComponent is Character) ? refComponent : null);
if (val != null)
{
num = (val.IsBoss() ? 1 : 0);
goto IL_0041;
}
}
num = 0;
goto IL_0041;
IL_0041:
bool flag3 = (byte)num != 0;
_root.gameObject.SetActive(!flag2 && flag && !flag3);
return _root.gameObject.activeSelf;
}
private void ResetHealthBar()
{
ResetBar(_healthFast);
ResetBar(_healthSlow);
_hpPercentCached = _healthFast.m_maxValue;
static void ResetBar(GuiBar bar)
{
bar.m_firstSet = true;
bar.m_value = bar.m_maxValue;
bar.SetBar(bar.m_maxValue);
}
}
private void LateUpdate()
{
if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
{
return;
}
Target target = TargetTrack.LockedTarget;
if (!Object.op_Implicit((Object)(object)target))
{
Character hoveringCreature = Player.m_localPlayer.m_hoveringCreature;
target = (Object.op_Implicit((Object)(object)hoveringCreature) ? ((MonoBehaviour)(object)hoveringCreature).Target() : null);
if (Object.op_Implicit((Object)(object)target) && !target.IsValid())
{
target = null;
}
}
UpdateTarget(target);
}
private void UpdateTarget(Target? target)
{
UpdateCrosshair();
UpdateTargetMark(target);
if (!UpdateVisibility(target))
{
SelectedTarget = null;
return;
}
if ((Object)(object)SelectedTarget != (Object)(object)target)
{
SelectedTarget = target;
ResetHealthBar();
}
UpdateHealthBar(target);
UpdateName(target);
UpdateStars(target);
}
private void UpdateName(Target target)
{
((TMP_Text)_displayName).text = Localization.instance.Localize(target.Name);
}
private void UpdateHealthBar(Target target)
{
Hoverable? refComponent = target.RefComponent;
Character val = (Character)(object)((refComponent is Character) ? refComponent : null);
if (val != null)
{
SetPercentHP(val.GetHealthPercentage());
}
}
private void UpdateStars(Target target)
{
Hoverable? refComponent = target.RefComponent;
int num = ((Character)(((refComponent is Character) ? refComponent : null)?)).m_level ?? 0;
int num2 = 2;
foreach (Transform star in Stars)
{
bool flag = num == num2;
((Component)star).gameObject.SetActive(flag && Configs.ShowTargetHUD.Stars.Value);
num2++;
}
if (num > Configs.TargetHUDMaxStars.Value)
{
((Component)Stars.Last()).gameObject.SetActive(Configs.ShowTargetHUD.Stars.Value);
}
}
private void UpdateTargetMark(Target? target)
{
//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_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: 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_005b: 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)
//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_00c7: 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)
if (!Object.op_Implicit((Object)(object)target) || !Object.op_Implicit((Object)(object)TargetTrack.LockedTarget) || !Configs.ShowTargetMark.Value || ((Character)Player.m_localPlayer).IsDead())
{
((Component)_targetMark).gameObject.SetActive(false);
return;
}
Hoverable? refComponent = target.RefComponent;
Character val = (Character)(object)((refComponent is Character) ? refComponent : null);
Vector3 val2 = ((val == null) ? target.LookAtPosition : (Object.op_Implicit((Object)(object)val.m_head) ? Vector3.Lerp(val.GetHeadPoint(), val.GetCenterPoint(), 0.5f) : val.GetCenterPoint()));
if (MathExt.AlignmentRatioTo(((Component)GameCamera.instance).transform, val2) < 0f)
{
((Component)_targetMark).gameObject.SetActive(false);
return;
}
Vector3 position = Utils.WorldToScreenPointScaled(GameCamera.instance.m_camera, val2);
((Component)_targetMark).transform.position = position;
((Component)_targetMark).gameObject.SetActive(!target.IsObstructed());
}
private static void UpdateCrosshair()
{
((Component)((Component)Hud.instance.m_crosshair).transform.parent).gameObject.SetActive(CanShowCrosshair());
}
public static bool CanShowCrosshair()
{
Player localPlayer = Player.m_localPlayer;
if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead())
{
return false;
}
if (((Character)localPlayer).IsBlocking())
{
return false;
}
if (HumanoidExt.IsUsingRangedWeapon((Humanoid)(object)localPlayer))
{
return true;
}
if (((Character)localPlayer).IsCrouching())
{
return true;
}
return !Object.op_Implicit((Object)(object)TargetTrack.LockedTarget);
}
}
internal static class TargetList
{
private static readonly Dictionary<GameObject, Target> TargetMap = new Dictionary<GameObject, Target>();
public static IEnumerable<Target> All => TargetMap.Select<KeyValuePair<GameObject, Target>, Target>((KeyValuePair<GameObject, Target> kvp) => kvp.Value);
public static int Count => TargetMap.Count;
public static Target? Target(this GameObject self)
{
return Get(self);
}
public static Target? Target(this MonoBehaviour self)
{
return Get(((Component)self).gameObject);
}
public static void Add(Target t)
{
if (!TargetMap.ContainsKey(((Component)t).gameObject))
{
Log.Debug((object)("Target Add: " + t.Name), (ushort)0);
TargetMap.Add(((Component)t).gameObject, t);
}
}
public static void Remove(Target t)
{
Log.Debug((object)("Target Remove: " + t.Name), (ushort)0);
TargetMap.Remove(((Component)t).gameObject);
}
private static Target? Get(GameObject? g)
{
if (!Object.op_Implicit((Object)(object)g))
{
return null;
}
TargetMap.TryGetValue(g, out Target value);
return value;
}
public static void Shutdown()
{
foreach (Target item in All.ToList())
{
Object.Destroy((Object)(object)item);
}
}
}
internal static class TargetTrack
{
private class Measurement
{
[CompilerGenerated]
private float <measure>P;
[CompilerGenerated]
private Target? <target>P;
public float Measure => <measure>P;
public Target? Target => <target>P;
public Measurement(float measure, Target? target)
{
<measure>P = measure;
<target>P = target;
base..ctor();
}
}
private enum CycleDirection
{
Next,
Prev
}
private static float _lastTargetCycleTime;
private static bool IsHardLock;
private static Measurement? _best;
private static bool IsPlayerDead
{
get
{
if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
{
return ((Character)Player.m_localPlayer).IsDead();
}
return true;
}
}
public static Target? LockedTarget { get; private set; }
private static bool IsTapped(this ActionString input)
{
if (!UI.IsOpen)
{
return ZInput.GetButtonDown(ActionString.op_Implicit(input));
}
return false;
}
private static bool IsPressed(this ActionString input)
{
if (!UI.IsOpen)
{
return ZInput.GetButton(ActionString.op_Implicit(input));
}
return false;
}
public static void HandleInputAndCamera()
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
if (!IsPlayerDead)
{
HandleInput();
if (Object.op_Implicit((Object)(object)LockedTarget))
{
FocusCamera(LockedTarget.LookAtPosition);
}
}
}
private static void HandleInput()
{
if (NotAllowedEquipment())
{
ResetLocks();
return;
}
if (Inputs.TargetLock.IsTapped())
{
IsHardLock = !IsHardLock;
}
if (!IsHardLock && !Inputs.TargetQuick.IsPressed())
{
ResetLocks();
return;
}
Target target = GetTarget();
if (Object.op_Implicit((Object)(object)target))
{
if (Inputs.TargetNext.IsTapped())
{
target = GetAdjacentTarget(target, CycleDirection.Next);
}
if (Inputs.TargetPrev.IsTapped())
{
target = GetAdjacentTarget(target, CycleDirection.Prev);
}
LockedTarget = target;
}
else
{
ResetLocks();
}
static void ResetLocks()
{
IsHardLock = false;
LockedTarget = null;
}
}
private static bool NotAllowedEquipment()
{
return HumanoidExt.IsUsingTool((Humanoid)(object)Player.m_localPlayer, true);
}
internal static void FindBestTarget()
{
_best = null;
if (IsHardLock)
{
return;
}
float value = Configs.ScanLimitNoTarget.Value;
foreach (Target item in TargetList.All)
{
if (item.IsInsideScan(value, out var ratio) && item.IsValid() && !item.IsObstructed() && ratio > (_best?.Measure ?? 0f))
{
_best = new Measurement(ratio, item);
}
}
}
private static bool IsInsideScan(this Target target, float limit, out float ratio)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
ratio = MathExt.AlignmentRatioTo(((Component)GameCamera.instance).transform, target.LookAtPosition);
return ratio >= limit;
}
private static bool IsInsideScan(this Target target, float limit)
{
float ratio;
return target.IsInsideScan(limit, out ratio);
}
private static Target? GetTarget()
{
if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
{
return null;
}
if (Target.IsValid(LockedTarget))
{
return LockedTarget;
}
Character hoverCreature = Player.m_localPlayer.GetHoverCreature();
if (Target.IsValid((MonoBehaviour?)(object)hoverCreature))
{
return ((MonoBehaviour)(object)hoverCreature).Target();
}
return _best?.Target;
}
private static Target GetAdjacentTarget(Target curTarget, CycleDirection cycleDir)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: 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_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_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: 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_009a: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: 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_00ab: 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_00af: Unknown result type (might be due to invalid IL or missing references)
if (ZInput.IsGamepadActive() && Time.time < _lastTargetCycleTime + 0.3f)
{
return curTarget;
}
_lastTargetCycleTime = Time.time;
Vector3 lookAtPosition = curTarget.LookAtPosition;
Vector3 position = ((Component)GameCamera.instance).transform.position;
float value = Configs.ScanLimitCycleTarget.Value;
SortedList<float, Target> sortedList = new SortedList<float, Target>();
foreach (Target item in TargetList.All)
{
if (item.IsInsideScan(value) && item.IsValid() && !item.IsObstructed())
{
Vector3 lookAtPosition2 = item.LookAtPosition;
Vector3 val = lookAtPosition - position;
Vector3 normalized = ((Vector3)(ref val)).normalized;
val = lookAtPosition2 - position;
Vector3 normalized2 = ((Vector3)(ref val)).normalized;
float key = Vector3.SignedAngle(normalized, normalized2, Vector3.up);
sortedList.Add(key, item);
}
}
if (sortedList.Count == 0)
{
return curTarget;
}
switch (cycleDir)
{
case CycleDirection.Next:
{
Target target2 = (from x in sortedList
where x.Key > 0f
select x.Value).FirstOrDefault();
if (!Object.op_Implicit((Object)(object)target2))
{
return sortedList.First().Value;
}
return target2;
}
case CycleDirection.Prev:
{
Target target = (from x in sortedList
where x.Key < 0f
select x.Value).LastOrDefault();
if (!Object.op_Implicit((Object)(object)target))
{
return sortedList.Last().Value;
}
return target;
}
default:
throw new ArgumentOutOfRangeException("cycleDir", cycleDir, "Invalid CycleDirection");
}
}
private static void FocusCamera(Vector3 targetPos)
{
//IL_0010: 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_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
Player localPlayer = Player.m_localPlayer;
Transform transform = ((Component)GameCamera.instance).transform;
Vector3 val = targetPos - transform.position;
Vector3 normalized = ((Vector3)(ref val)).normalized;
Vector3 val2 = Vector3.Slerp(transform.forward, normalized, 0.2f);
((Character)localPlayer).SetLookDir(val2, 0f);
localPlayer.SetMouseLook(Vector2.zero);
}
}
[BepInPlugin("ZenDragon.ZenTargeting", "ZenTargeting", "0.5.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[SynchronizationMode(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
internal class Plugin : ZenMod<Plugin>
{
public const string PluginName = "ZenTargeting";
public const string PluginVersion = "0.5.2";
public const string PluginGUID = "ZenDragon.ZenTargeting";
protected override void Setup()
{
((ZenMod)this).RequireGamepadRemap = true;
CLLC.Detect();
((ZenMod)this).RegisterInputs += Inputs.RegisterInputs;
TargetHud.RegisterConfigEvents();
Inputs.RegisterConfigEvents();
}
protected override void TitleScene(bool isFirstBoot)
{
}
protected override void WorldStart()
{
DebugHotLoad();
Inputs.Init();
TargetHud.Init();
FloatingHud.Init();
((MonoBehaviour)this).InvokeRepeating("SlowUpdate", 0f, 0.2f);
}
protected override void Shutdown()
{
Inputs.Shutdown();
TargetHud.Shutdown();
TargetList.Shutdown();
}
private void SlowUpdate()
{
TargetTrack.FindBestTarget();
}
private void LateUpdate()
{
if (ZenMod<Plugin>.Initialized)
{
TargetTrack.HandleInputAndCamera();
}
}
private void DebugHotLoad()
{
if (Object.op_Implicit((Object)(object)EnemyHud.instance))
{
foreach (HudData value in EnemyHud.instance.m_huds.Values)
{
Object.Destroy((Object)(object)value.m_gui);
}
EnemyHud.instance.m_huds.Clear();
}
foreach (Character allCharacter in Character.GetAllCharacters())
{
if ((Object)(object)allCharacter != (Object)(object)Player.m_localPlayer)
{
Target.Create(allCharacter);
}
}
}
}
[HarmonyPatch]
internal static class FloatingHud
{
[HarmonyPatch(typeof(EnemyHud), "UpdateHuds")]
private static class UpdateHuds
{
[HarmonyTranspiler]
[HarmonyPatch]
private static IEnumerable<CodeInstruction> EnemyHud_UpdateHuds_Transpile(IEnumerable<CodeInstruction> codes, ILGenerator il)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Expected O, but got Unknown
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Expected O, but got Unknown
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Expected O, but got Unknown
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Expected O, but got Unknown
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Expected O, but got Unknown
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Expected O, but got Unknown
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: Expected O, but got Unknown
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Expected O, but got Unknown
//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Expected O, but got Unknown
//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
//IL_01db: Expected O, but got Unknown
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
//IL_01ef: Expected O, but got Unknown
//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(KeyValuePair<Character, HudData>), "Value");
MethodInfo methodInfo2 = AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(Dictionary<Character, HudData>), "GetEnumerator", (Type[])null, (Type[])null));
CodeMatcher val = new CodeMatcher(codes, il);
val.MatchEndForward((CodeMatch[])(object)new CodeMatch[3]
{
new CodeMatch((OpCode?)OpCodes.Ldloca_S, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Call, (object)methodInfo, (string)null),
new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction c) => c.opcode == OpCodes.Stloc_S && ((LocalBuilder)c.operand).LocalIndex == 6), (string)null)
}).ThrowIfInvalid("Can not match IL position for start of foreach loop").Advance(1)
.Insert((CodeInstruction[])(object)new CodeInstruction[2]
{
new CodeInstruction(OpCodes.Ldloc_S, (object)(byte)6),
CodeInstruction.Call(typeof(UpdateHuds), "LoopStart", (Type[])null, (Type[])null)
});
Label label = default(Label);
val.MatchStartForward((CodeMatch[])(object)new CodeMatch[3]
{
new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction c) => c.opcode == OpCodes.Ldloca_S && ((LocalBuilder)c.operand).LocalIndex == 4), (string)null),
new CodeMatch((OpCode?)OpCodes.Call, (object)methodInfo2, (string)null),
new CodeMatch((OpCode?)OpCodes.Brtrue, (object)null, (string)null)
}).ThrowIfInvalid("Can not match IL position for end of foreach loop").SetAndAdvance(OpCodes.Ldloc_S, (object)(byte)6)
.SetAndAdvance(OpCodes.Call, (object)AccessTools.Method(typeof(UpdateHuds), "LoopEnd", (Type[])null, (Type[])null))
.Insert((CodeInstruction[])(object)new CodeInstruction[2]
{
new CodeInstruction(OpCodes.Ldloca_S, (object)(byte)4),
new CodeInstruction(OpCodes.Call, (object)methodInfo2)
})
.CreateLabel(ref label);
val.Start().MatchEndForward((CodeMatch[])(object)new CodeMatch[4]
{
new CodeMatch((OpCode?)OpCodes.Ldfld, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Callvirt, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Stloc_S, (object)null, (string)null),
new CodeMatch((OpCode?)OpCodes.Br, (object)null, (string)null)
}).ThrowIfInvalid("Can not find loop entry BR")
.Operand = label;
return val.InstructionEnumeration();
}
private static void LoopStart(HudData hudData)
{
SetFloatingHudShowDuration(hudData);
}
private static void LoopEnd(HudData hudData)
{
UpdateHud(hudData);
}
}
public const float VanillaHoverShowDuration = 60f;
private static Color _hpBarRed;
public static void Init()
{
//IL_001e: 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)
_hpBarRed = ((Component)EnemyHud.instance.m_baseHud.transform.Find("Health/health_fast")).GetComponent<GuiBar>().m_originalColor;
if (Configs.MaxTargetRange.Value > 0f)
{
EnemyHud.instance.m_maxShowDistance = Configs.MaxTargetRange.Value;
}
}
private static void SetFloatingHudShowDuration(HudData hudData)
{
Character character = hudData.m_character;
bool num = (Object)(object)TargetTrack.LockedTarget == (Object)(object)((MonoBehaviour)(object)character).Target();
bool flag = IsFloatingHudException(character);
if (num)
{
EnemyHud.instance.m_hoverShowDuration = float.MaxValue;
}
else if (Object.op_Implicit((Object)(object)TargetTrack.LockedTarget) && !flag)
{
EnemyHud.instance.m_hoverShowDuration = 0f;
}
else
{
EnemyHud.instance.m_hoverShowDuration = (flag ? 60f : Configs.FloatingHudLingerDuration.Value);
}
}
private static bool IsFloatingHudException(Character c)
{
if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
{
return false;
}
IDoodadController doodadController = Player.m_localPlayer.GetDoodadController();
Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
if ((val == null || !((Object)(object)val.GetCharacter() == (Object)(object)c)) && !c.IsBoss() && !c.IsTamed())
{
if (c.IsPlayer())
{
return !c.IsPVPEnabled();
}
return false;
}
return true;
}
public static void UpdateHud(HudData hudData)
{
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
if (!Object.op_Implicit((Object)(object)hudData.m_character))
{
Log.Warning((object)"No character found in hudData.", (ushort)0);
return;
}
Character character = hudData.m_character;
bool flag = Configs.IgnoreTargets.Value.Contains(GameObjectExt.GetPrefabName(((Component)character).gameObject), true);
bool flag2 = IsFloatingHudException(character);
bool flag3 = Object.op_Implicit((Object)(object)((MonoBehaviour)(object)character).Target()) && ((MonoBehaviour)(object)character).Target().IsObstructed();
if (flag)
{
((Component)hudData.m_name).gameObject.SetActive(false);
}
else
{
((Component)hudData.m_name).gameObject.SetActive(flag2 || (Configs.ShowFloating.Name.Value && !flag3));
}
bool flag4 = flag2 || (Configs.ShowFloating.Health.Value && !flag3);
((Component)((Component)hudData.m_healthFast).transform.parent).gameObject.SetActive(!flag && flag4);
if (character.IsPlayer())
{
if (character.IsPVPEnabled())
{
hudData.m_healthFast.SetColor(_hpBarRed);
}
else
{
hudData.m_healthFast.ResetColor();
}
}
if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)hudData.m_alerted) && Object.op_Implicit((Object)(object)hudData.m_aware))
{
bool flag5 = ((Character)Player.m_localPlayer).IsCrouching() && ((Character)Player.m_localPlayer).IsOnGround() && !flag3 && !flag;
bool activeSelf = ((Component)hudData.m_alerted).gameObject.activeSelf;
bool activeSelf2 = ((Component)hudData.m_aware).gameObject.activeSelf;
((Component)hudData.m_alerted).gameObject.SetActive(flag5 && activeSelf);
((Component)hudData.m_aware).gameObject.SetActive(flag5 && activeSelf2);
}
if (flag)
{
hudData.ShowStars(show: false);
}
else if (flag2)
{
hudData.ShowStars(show: true);
}
else
{
hudData.ShowStars(Configs.ShowFloating.Stars.Value && !flag3);
}
}
private static void ShowStars(this HudData hudData, bool show)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
int num = 2;
foreach (Transform item in hudData.m_gui.transform)
{
Transform val = item;
if (((Object)val).name.StartsWith("level_"))
{
bool flag = hudData.m_character.GetLevel() == num;
((Component)val).gameObject.SetActive(show && flag);
num++;
}
}
}
}
[HarmonyPatch]
internal static class TargetPatch
{
private static class HandleAttackTowardsPlayerLookDir
{
[HarmonyPatch(typeof(Attack), "Start")]
private static class Attack_Start
{
[UsedImplicitly]
private static void Prefix()
{
Override();
}
[UsedImplicitly]
private static void Postfix()
{
Restore();
}
}
[HarmonyPatch(typeof(Player), "AlwaysRotateCamera")]
private static class Player_AlwaysRotateCamera
{
[UsedImplicitly]
private static void Prefix()
{
Override();
}
[UsedImplicitly]
private static void Postfix()
{
Restore();
}
}
private static bool _saved;
private static void Override()
{
Player localPlayer = Player.m_localPlayer;
_saved = localPlayer.AttackTowardsPlayerLookDir;
if (localPlayer.AttackTowardsPlayerLookDir && Configs.AlwaysAttackTowardsLockedTarget.Value)
{
localPlayer.AttackTowardsPlayerLookDir = !Object.op_Implicit((Object)(object)TargetTrack.LockedTarget);
}
}
private static void Restore()
{
Player.m_localPlayer.AttackTowardsPlayerLookDir = _saved;
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Character), "Awake")]
private static void Character_Awake(Character __instance)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
Scene activeScene = SceneManager.GetActiveScene();
if (!(((Scene)(ref activeScene)).name != "main"))
{
Target.Create(__instance);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(Player), "SetLocalPlayer")]
private static void Player_SetLocalPlayer(Player __instance)
{
if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
{
Object.Destroy((Object)(object)((Component)__instance).gameObject.Target());
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(Attack), "GetMeleeAttackDir")]
private static void Attack_GetMeleeAttackDir(Attack __instance, ref bool __runOriginal, out Transform originJoint, out Vector3 attackDir)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected O, but got Unknown
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: 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_00c4: 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)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: 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: Invalid comparison between Unknown and I4
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_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_007a: 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)
if ((Object)(object)__instance.m_character != (Object)(object)Player.m_localPlayer)
{
originJoint = null;
attackDir = Vector3.zero;
return;
}
__runOriginal = false;
originJoint = __instance.GetAttackOrigin();
Player val = (Player)__instance.m_character;
Vector3 val2;
if (Object.op_Implicit((Object)(object)TargetTrack.LockedTarget) && !((Character)val).IsDead() && (int)__instance.m_attackType != 4)
{
Target lockedTarget = TargetTrack.LockedTarget;
val2 = ((Component)lockedTarget).transform.position - ((Component)val).transform.position;
attackDir = ((Vector3)(ref val2)).normalized;
return;
}
Vector3 forward = ((Component)val).transform.forward;
val2 = ((Humanoid)val).GetAimDir(originJoint.position);
val2.x = forward.x;
val2.z = forward.z;
Vector3 val3 = val2;
((Vector3)(ref val3)).Normalize();
attackDir = Vector3.RotateTowards(forward, val3, (float)Math.PI / 180f * __instance.m_maxYAngle, 10f);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterAnimEvent), "UpdateHeadRotation")]
private static void CharacterrAnimEvent_UpdateHeadRotation(CharacterAnimEvent __instance, ref bool __runOriginal)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: 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_0053: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)__instance.m_character != (Object)(object)Player.m_localPlayer))
{
Target selectedTarget = TargetHud.SelectedTarget;
if (Object.op_Implicit((Object)(object)selectedTarget))
{
__runOriginal = false;
Vector3 lookFromPos = __instance.GetLookFromPos();
Vector3 lookAtPosition = selectedTarget.LookAtPosition;
Vector3 headLookDir = __instance.m_headLookDir;
Vector3 val = lookAtPosition - lookFromPos;
__instance.m_headLookDir = Vector3.Slerp(headLookDir, ((Vector3)(ref val)).normalized, 0.1f);
}
}
}
}
[HarmonyPatch]
public static class VanillaBugfix
{
[HarmonyPostfix]
[HarmonyPatch(typeof(Character), "OnDestroy")]
private static void Character_OnDestroy(Character __instance)
{
if (Object.op_Implicit((Object)(object)EnemyHud.instance) && EnemyHud.instance.m_huds.TryGetValue(__instance, out var value))
{
Object.Destroy((Object)(object)value.m_gui);
EnemyHud.instance.m_huds.Remove(__instance);
}
}
}
}
namespace ZenTargeting.Compatibility
{
[HarmonyPatch]
public static class CLLC
{
public static bool IsLoaded { get; private set; }
public static void Detect()
{
IsLoaded = Chainloader.PluginInfos.ContainsKey("org.bepinex.plugins.creaturelevelcontrol");
if (IsLoaded)
{
Log.Message((object)"CLLC detected. Extra iteration of hudData required because CLLC EnemyHud modifications happen after the loop in EnemyHud.UpdateHuds instead of inside the loop", (ushort)0);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(EnemyHud), "UpdateHuds")]
[HarmonyPriority(100)]
private static void EnemyHud_UpdateHuds(EnemyHud __instance)
{
if (!IsLoaded)
{
return;
}
foreach (HudData value in EnemyHud.instance.m_huds.Values)
{
FloatingHud.UpdateHud(value);
}
}
}
}