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 Odins Second Hand v0.1.1
plugins/OdinsSecondHand.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("OdinsSecondHand")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: AssemblyInformationalVersion("0.1.1+cce88f4f5e8d204139e621ed2600df67090ba08d")] [assembly: AssemblyProduct("OdinsSecondHand")] [assembly: AssemblyTitle("OdinsSecondHand")] [assembly: AssemblyVersion("0.1.1.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 OdinsSecondHand { internal static class HudText { private sealed class Scale : MonoBehaviour { private const float ReferenceWidth = 1920f; private const float ReferenceHeight = 1080f; private static readonly FieldRef<float> GameGuiScale = TryFindGuiScale(); internal CanvasScaler Scaler; private float _logged = -1f; private void Update() { if (!((Object)(object)Scaler == (Object)null)) { float num = ((GameGuiScale != null) ? GameGuiScale.Invoke() : 1f); if (num <= 0f) { num = 1f; } float num2 = Mathf.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f) * num * Plugin.TextScale.Value; if (Mathf.Abs(Scaler.scaleFactor - num2) > 0.0001f) { Scaler.scaleFactor = num2; } if (Plugin.DebugLog.Value && Mathf.Abs(_logged - num2) > 0.0001f) { _logged = num2; Plugin.Log.LogInfo((object)$"Text scale {num2:0.###}: screen {Screen.width}x{Screen.height}, game GUI scale {num:0.##}, TextScale {Plugin.TextScale.Value:0.##}."); } } } private static FieldRef<float> TryFindGuiScale() { FieldInfo fieldInfo = AccessTools.Field(typeof(GuiScaler), "m_largeGuiScale"); if (fieldInfo == null || fieldInfo.FieldType != typeof(float) || !fieldInfo.IsStatic) { Plugin.Log.LogWarning((object)"Couldn't find the game's GUI scale; text follows the screen size only."); return null; } return AccessTools.StaticFieldRefAccess<float>(fieldInfo); } } private static Canvas _canvas; public static TMP_Text Create(string name, Transform owner) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_00b7: 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_00cc: 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_00e1: Unknown result type (might be due to invalid IL or missing references) TMP_Text val = (((Object)(object)MessageHud.instance != (Object)null) ? MessageHud.instance.m_messageCenterText : null); if ((Object)(object)val == (Object)null || (Object)(object)val.font == (Object)null || !EnsureCanvas(owner)) { return null; } GameObject val2 = new GameObject(name, new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(((Component)_canvas).transform, false); TextMeshProUGUI obj = val2.AddComponent<TextMeshProUGUI>(); ((TMP_Text)obj).font = val.font; ((TMP_Text)obj).fontSharedMaterial = val.fontSharedMaterial; ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; ((TMP_Text)obj).textWrappingMode = (TextWrappingModes)1; ((Graphic)obj).raycastTarget = false; ((TMP_Text)obj).outlineWidth = 0.15f; ((TMP_Text)obj).outlineColor = new Color32((byte)0, (byte)0, (byte)0, (byte)200); RectTransform val3 = (RectTransform)val2.transform; val3.pivot = new Vector2(0.5f, 0.5f); val3.anchoredPosition = Vector2.zero; return (TMP_Text)(object)obj; } private static bool EnsureCanvas(Transform owner) { //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_0026: 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) if ((Object)(object)_canvas != (Object)null) { return true; } GameObject val = new GameObject("OdinsSecondHand_Canvas"); val.transform.SetParent(owner, false); _canvas = val.AddComponent<Canvas>(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 5000; CanvasScaler val2 = val.AddComponent<CanvasScaler>(); val2.uiScaleMode = (ScaleMode)0; val.AddComponent<Scale>().Scaler = val2; Plugin.Log.LogInfo((object)"On-screen text layer created."); return true; } } internal class OdinLine : MonoBehaviour { private const float ScreenY = 0.72f; private const float FadeIn = 0.2f; private const float Hold = 2.5f; private const float FadeOut = 0.8f; private const float TextSize = 21f; private static readonly Color Tint = new Color(1f, 0.86f, 0.62f); private TMP_Text _text; private float _elapsed = -1f; public void Show(string line) { if (EnsureText()) { _text.text = line; _elapsed = 0f; SetAlpha(0f); ((Component)_text).gameObject.SetActive(true); } } private void Update() { if (_elapsed < 0f || (Object)(object)_text == (Object)null) { return; } _elapsed += Time.deltaTime; float num = 3.5f; if (_elapsed >= num) { _elapsed = -1f; ((Component)_text).gameObject.SetActive(false); return; } float num2 = Mathf.Min(Mathf.Clamp01(_elapsed / 0.2f), Mathf.Clamp01((num - _elapsed) / 0.8f)); if (!HudVisible()) { num2 = 0f; } SetAlpha(Mathf.SmoothStep(0f, 1f, num2)); } private void SetAlpha(float alpha) { //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) //IL_0014: Unknown result type (might be due to invalid IL or missing references) Color tint = Tint; tint.a = alpha; ((Graphic)_text).color = tint; } private bool EnsureText() { //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_0051: 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_0066: 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) if ((Object)(object)_text != (Object)null) { return true; } _text = HudText.Create("OdinsSecondHand_Line", ((Component)this).transform); if ((Object)(object)_text == (Object)null) { return false; } RectTransform val = (RectTransform)_text.transform; val.anchorMin = new Vector2(0.5f, 0.72f); val.anchorMax = new Vector2(0.5f, 0.72f); val.sizeDelta = new Vector2(1400f, 160f); _text.fontSize = 21f; return true; } private static bool HudVisible() { if ((Object)(object)Hud.instance != (Object)null && !Hud.IsUserHidden()) { return Hud.instance.IsVisible(); } return false; } private void OnDestroy() { if ((Object)(object)_text != (Object)null) { Object.Destroy((Object)(object)((Component)_text).gameObject); } } } [HarmonyPatch(typeof(Player), "SetControls")] internal static class ControlsPatch { private static void Prefix(Player __instance, ref bool attack, ref bool attackHold) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && (Object)(object)SecondHand.Instance != (Object)null && SecondHand.Instance.HoldBackAttack) { attack = false; attackHold = false; } } } [BepInPlugin("hevyh2o.valheim.odinssecondhand", "Odin's Second Hand", "0.1.1")] public class Plugin : BaseUnityPlugin { public const string Guid = "hevyh2o.valheim.odinssecondhand"; public const string Name = "Odin's Second Hand"; public const string Version = "0.1.1"; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> InstantSwap; internal static ConfigEntry<bool> AutoSwap; internal static ConfigEntry<float> SwapDistance; internal static ConfigEntry<float> ReachMargin; internal static ConfigEntry<bool> SwapBack; internal static ConfigEntry<float> SwapBackDelay; internal static ConfigEntry<bool> IncludeStaffs; internal static ConfigEntry<string> PreferredWeapon; internal static ConfigEntry<string> Exclude; internal static ConfigEntry<KeyboardShortcut> SwapKey; internal static ConfigEntry<bool> ShowRemarks; internal static ConfigEntry<float> RemarkCooldown; internal static ConfigEntry<float> TextScale; internal static ConfigEntry<bool> DebugLog; private Harmony _harmony; private SecondHand _hand; private void Awake() { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Expected O, but got Unknown //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Expected O, but got Unknown //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch."); InstantSwap = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "InstantSwap", true, "On: swaps happen at once, the way the game equips items that have no equip time. Off: swaps use the game's own equip timer and animation, so a slow weapon takes as long to draw as it would from the hotbar."); AutoSwap = ((BaseUnityPlugin)this).Config.Bind<bool>("Auto", "AutoSwap", true, "While a bow or crossbow is in your hands, switch to your best melee weapon for the enemy the moment it comes close (see SwapDistance)."); SwapDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Auto", "SwapDistance", 6f, new ConfigDescription("How close, in metres, an enemy gets before Odin swaps, 0 to 15, measured to the creature's edge. Higher draws steel sooner: 6 gives you a step or two before it reaches you. 0 = auto: the melee weapon's own reach plus ReachMargin, so a spear comes out further away than a knife. The bow comes back once nothing is this close.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f), Array.Empty<object>())); ReachMargin = ((BaseUnityPlugin)this).Config.Bind<float>("Auto", "ReachMargin", 1f, new ConfigDescription("Only used when SwapDistance is 0 (auto). Metres added to the melee weapon's own reach before Odin swaps, 0 to 5. Larger swaps sooner.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>())); SwapBack = ((BaseUnityPlugin)this).Config.Bind<bool>("Auto", "SwapBack", true, "After an automatic swap, hand the bow back once no enemy is close. If you're still holding the attack button, the bow carries on drawing."); SwapBackDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Auto", "SwapBackDelay", 1.5f, new ConfigDescription("Seconds with no enemy close before the bow comes back, 0 to 10. 0 = straight away.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); IncludeStaffs = ((BaseUnityPlugin)this).Config.Bind<bool>("Auto", "IncludeStaffs", false, "Also swap away from magic staffs (elemental and blood magic) when an enemy gets close. Bows and crossbows always swap."); PreferredWeapon = ((BaseUnityPlugin)this).Config.Bind<string>("Weapons", "PreferredWeapon", "", "Always take this weapon when you carry it, whatever the enemy. Its prefab name (MaceIron) or its name as the game shows it (Iron mace); several, separated by commas, are tried in order. Empty = Odin picks the best for each enemy."); Exclude = ((BaseUnityPlugin)this).Config.Bind<string>("Weapons", "Exclude", "", "Weapons Odin never picks, separated by commas, by prefab name or shown name. Handy for the knife you keep for skinning."); SwapKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Keys", "SwapKey", KeyboardShortcut.Empty, "Optional key: with a bow out, swap to the best melee weapon for the nearest enemy now; press again to get the bow back. A swap you make with this key isn't undone by itself. Unbound by default."); ShowRemarks = ((BaseUnityPlugin)this).Config.Bind<bool>("Messages", "ShowRemarks", true, "Odin says a word when he swaps for you, often about why he picked that weapon."); RemarkCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Messages", "RemarkCooldown", 20f, new ConfigDescription("Seconds between remarks, 0 to 300. Swaps in between happen quietly.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>())); TextScale = ((BaseUnityPlugin)this).Config.Bind<float>("Messages", "TextScale", 1f, new ConfigDescription("Size of Odin's remarks, 0.5 to 2. 1 = sized to match the game's own HUD, which already follows your screen height and the game's GUI scale setting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>())); DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLog", false, "Write each swap to the BepInEx log: the enemy, every weapon Odin weighed and its damage against it, the reach and the equip times."); _harmony = new Harmony("hevyh2o.valheim.odinssecondhand"); _harmony.PatchAll(typeof(Plugin).Assembly); _hand = ((Component)this).gameObject.AddComponent<SecondHand>(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Odin's Second Hand 0.1.1 loaded. Odin is minding your back."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)_hand != (Object)null) { Object.Destroy((Object)(object)_hand); } } } internal sealed class SecondHand : MonoBehaviour { private const float ScanInterval = 0.1f; private const float LookRadius = 16f; private const float StayMargin = 0.5f; private const float AutoCooldown = 1f; private const float DrawResumeWindow = 3f; private const float HoldBackLimit = 3f; private const float TieMargin = 0.05f; private static readonly MethodInfo ToggleEquipped = AccessTools.Method(typeof(Player), "ToggleEquipped", (Type[])null, (Type[])null); private static readonly FieldInfo AttackDrawTime = AccessTools.Field(typeof(Humanoid), "m_attackDrawTime"); private static readonly DamageType[] Types; private static readonly string[] Openers; private static readonly Dictionary<DamageType, string[]> Because; private static readonly string[] Plain; private OdinLine _line; private ItemData _origin; private ItemData _melee; private bool _auto; private float _lastEnemyNear; private float _holdBackSince = -1f; private float _nextScan; private float _nextAutoAt; private float _resumeUntil = -1f; private float _nextRemarkAt; private string _lastRemark; internal static SecondHand Instance { get; private set; } internal bool HoldBackAttack => _holdBackSince >= 0f; private void Awake() { Instance = this; _line = ((Component)this).gameObject.AddComponent<OdinLine>(); } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void Update() { //IL_007b: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !Plugin.Enabled.Value) { Clear(); _resumeUntil = -1f; return; } ResumeDraw(localPlayer); if (_melee != null && !Holding(localPlayer, _melee)) { Clear(); } if (HoldBackAttack && Time.time - _holdBackSince > 3f) { _holdBackSince = -1f; } if (Pressed(Plugin.SwapKey.Value) && CanSwap(localPlayer)) { SwapNow(localPlayer); } else { if (Time.time < _nextScan) { return; } _nextScan = Time.time + 0.1f; if (CanSwap(localPlayer)) { if (_melee == null) { TryAutoSwap(localPlayer); } else if (_auto) { TrySwapBack(localPlayer); } } } } private void TryAutoSwap(Player player) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.AutoSwap.Value || Time.time < _nextAutoAt) { return; } ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon == null || !IsRanged(currentWeapon)) { return; } float distance; Character val = NearestThreat(player, 16f, out distance); if ((Object)(object)val == (Object)null) { return; } DamageType reason; ItemData val2 = BestMelee(player, val, out reason); if (val2 != null) { float num = Reach(val2); if (!(distance > num) && Equip(player, val2)) { Begin(currentWeapon, val2, auto: true); _lastEnemyNear = Time.time; Remark(val2, val, reason); Note($"Auto-swap: {Describe(currentWeapon)} -> {Describe(val2)}, reach {num:0.0} m, {val.m_name} at {distance:0.0} m."); } } } private void TrySwapBack(Player player) { if (Plugin.SwapBack.Value) { if (ThreatInReach(player)) { _lastEnemyNear = Time.time; _holdBackSince = -1f; } else if (!(Time.time - _lastEnemyNear < Plugin.SwapBackDelay.Value)) { BackToRanged(player); } } } private void BackToRanged(Player player) { if (_origin == null || !((Humanoid)player).GetInventory().ContainsItem(_origin)) { Clear(); return; } ItemData origin = _origin; ItemData melee = _melee; if (Equip(player, origin)) { Note("Swap back: " + Describe(melee) + " -> " + Describe(origin) + "."); if (origin.m_shared.m_attack.m_bowDraw) { _resumeUntil = Time.time + 3f; } Clear(); _nextAutoAt = Time.time + 1f; } } private void SwapNow(Player player) { if (_melee != null) { BackToRanged(player); return; } ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon != null && IsRanged(currentWeapon)) { float distance; Character val = NearestThreat(player, 16f, out distance); DamageType reason; ItemData val2 = BestMelee(player, val, out reason); if (val2 != null && Equip(player, val2)) { Begin(currentWeapon, val2, auto: false); Note("Swap key: " + Describe(currentWeapon) + " -> " + Describe(val2) + (((Object)(object)val != (Object)null) ? (", for " + val.m_name + ".") : ".")); } } } private bool ThreatInReach(Player player) { if ((Object)(object)NearestThreat(player, 16f, out var distance) != (Object)null) { return distance <= Reach(_melee) + 0.5f; } return false; } private void WantHoldBack(Player player) { if (Plugin.SwapBack.Value && AttackHeld()) { if (ThreatInReach(player)) { _lastEnemyNear = Time.time; _holdBackSince = -1f; } else if (_holdBackSince < 0f && Time.time - _lastEnemyNear >= Plugin.SwapBackDelay.Value) { _holdBackSince = Time.time; } } } private void ResumeDraw(Player player) { if (_resumeUntil < 0f) { return; } if (Time.time > _resumeUntil || !AttackHeld() || AttackDrawTime == null) { _resumeUntil = -1f; return; } ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon != null && currentWeapon.m_shared.m_attack.m_bowDraw && !((Character)player).InMinorAction()) { float num = (float)AttackDrawTime.GetValue(player); if (num < 0f) { AttackDrawTime.SetValue(player, 0f); } else if (num > 0f) { _resumeUntil = -1f; } } } private static ItemData BestMelee(Player player, Character enemy, out DamageType reason) { //IL_00ad: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected I4, but got Unknown reason = (DamageType)1024; List<ItemData> allItems = ((Humanoid)player).GetInventory().GetAllItems(); foreach (string item2 in Names(Plugin.PreferredWeapon.Value)) { foreach (ItemData item3 in allItems) { if (IsCandidate(item3) && Matches(item3, item2)) { return item3; } } } DamageModifiers mods = (DamageModifiers)(((Object)(object)enemy != (Object)null) ? enemy.GetDamageModifiers((WeakSpot)null) : default(DamageModifiers)); List<string> list = Names(Plugin.Exclude.Value); ItemData val = null; float num = 0f; float num2 = 0f; List<string> list2 = (Plugin.DebugLog.Value ? new List<string>() : null); foreach (ItemData item in allItems) { if (IsCandidate(item) && !list.Exists((string n) => Matches(item, n))) { DamageType why; float num3 = Effective(item.GetDamage(), mods, out why); float skillLevel = ((Character)player).GetSkillLevel(item.m_shared.m_skillType); list2?.Add($"{Name(item)} q{item.m_quality} {num3:0.#}"); if (!(num3 <= 0f) && (val == null || num3 > num * 1.05f || (num3 >= num * 0.95f && skillLevel > num2))) { val = item; num = num3; num2 = skillLevel; reason = (DamageType)(int)why; } } } if (list2 != null && list2.Count > 0) { Plugin.Log.LogInfo((object)("Weighed against " + (((Object)(object)enemy != (Object)null) ? enemy.m_name : "nothing in particular") + ": " + string.Join(", ", list2) + ".")); } return val; } private static float Effective(DamageTypes damage, DamageModifiers mods, out DamageType why) { //IL_0007: 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_0023: 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_0038: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected I4, but got Unknown why = (DamageType)1024; float num = damage.m_damage; float num2 = 1f; DamageType[] types = Types; foreach (DamageType val in types) { float num3 = Amount(damage, val); if (!(num3 <= 0f)) { float num4 = Factor(((DamageModifiers)(ref mods)).GetModifier(val)); num += num3 * num4; if (num4 > num2) { num2 = num4; why = (DamageType)(int)val; } } } return num; } private static float Amount(DamageTypes d, DamageType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Invalid comparison between Unknown and I4 //IL_0005: 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_001d: Expected I4, but got Unknown //IL_0066: 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_0037: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 //IL_006d: 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_003f: Invalid comparison between Unknown and I4 //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if ((int)type <= 64) { switch (type - 1) { default: if ((int)type != 32) { if ((int)type != 64) { break; } return d.m_frost; } return d.m_fire; case 0: return d.m_blunt; case 1: return d.m_slash; case 3: return d.m_pierce; case 2: break; } } else { if ((int)type == 128) { return d.m_lightning; } if ((int)type == 256) { return d.m_poison; } if ((int)type == 512) { return d.m_spirit; } } return 0f; } private static float Factor(DamageModifier mod) { //IL_0000: 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_0028: Expected I4, but got Unknown switch (mod - 1) { case 6: return 0.75f; case 0: return 0.5f; case 4: return 0.25f; case 7: return 1.25f; case 1: return 1.5f; case 5: return 2f; case 2: case 3: return 0f; default: return 1f; } } private static bool IsCandidate(ItemData item) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Invalid comparison between Unknown and I4 if (item == null || !item.IsWeapon() || IsRanged(item) || (int)item.m_shared.m_attack.m_attackType == 2) { return false; } if (item.m_shared.m_useDurability && item.m_durability <= 0f) { return false; } SkillType skillType = item.m_shared.m_skillType; if (skillType - 1 <= 4 || (int)skillType == 7) { return true; } return false; } private static bool IsRanged(ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 SkillType skillType = item.m_shared.m_skillType; if ((int)skillType == 8 || (int)skillType == 14 || (int)item.m_shared.m_itemType == 4) { return true; } if (Plugin.IncludeStaffs.Value) { if ((int)skillType != 9) { return (int)skillType == 10; } return true; } return false; } private static float Reach(ItemData melee) { if (!(Plugin.SwapDistance.Value > 0f)) { return melee.m_shared.m_attack.m_attackRange + Plugin.ReachMargin.Value; } return Plugin.SwapDistance.Value; } private static List<string> Names(string list) { List<string> list2 = new List<string>(); string[] array = (list ?? "").Split(new char[1] { ',' }); foreach (string text in array) { if (text.Trim().Length > 0) { list2.Add(text.Trim()); } } return list2; } private static bool Matches(ItemData item, string wanted) { if ((Object)(object)item.m_dropPrefab != (Object)null && string.Equals(((Object)item.m_dropPrefab).name, wanted, StringComparison.OrdinalIgnoreCase)) { return true; } string text = item.m_shared.m_name ?? ""; if (string.Equals(text.TrimStart(new char[1] { '$' }), wanted.TrimStart(new char[1] { '$' }), StringComparison.OrdinalIgnoreCase)) { return true; } if (Localization.instance != null) { return string.Equals(Localization.instance.Localize(text), wanted, StringComparison.OrdinalIgnoreCase); } return false; } private static Character NearestThreat(Player player, float radius, out float distance) { //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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) distance = float.MaxValue; Character result = null; Vector3 position = ((Component)player).transform.position; foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)player) && !allCharacter.IsDead() && !allCharacter.IsTamed()) { float num = Mathf.Max(0f, Vector3.Distance(((Component)allCharacter).transform.position, position) - allCharacter.GetRadius()); if (!(num > radius) && !(num >= distance) && IsThreat(player, allCharacter)) { result = allCharacter; distance = num; } } } return result; } private static bool IsThreat(Player player, Character other) { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 if (!BaseAI.IsEnemy((Character)(object)player, other)) { return false; } Faction faction = other.GetFaction(); if ((int)faction != 1) { if ((int)faction == 12) { return false; } return true; } BaseAI baseAI = other.GetBaseAI(); MonsterAI val = (MonsterAI)(object)((baseAI is MonsterAI) ? baseAI : null); if (val != null) { return (Object)(object)((BaseAI)val).GetTargetCreature() == (Object)(object)player; } return false; } private static bool Equip(Player player, ItemData item) { if (Holding(player, item)) { return true; } if (Plugin.InstantSwap.Value || ToggleEquipped == null) { return ((Humanoid)player).EquipItem(item, true); } ToggleEquipped.Invoke(player, new object[1] { item }); return Holding(player, item); } private static bool Holding(Player player, ItemData item) { if (!((Humanoid)player).IsItemEquiped(item)) { return player.IsEquipActionQueued(item); } return true; } private void Begin(ItemData origin, ItemData melee, bool auto) { _origin = origin; _melee = melee; _auto = auto; _holdBackSince = -1f; } private void Clear() { _origin = null; _melee = null; _auto = false; _holdBackSince = -1f; } private bool CanSwap(Player player) { if (((Character)player).IsDead() || ((Character)player).InCutscene() || ((Character)player).IsTeleporting() || player.IsSleeping() || ((Character)player).InDodge() || ((Character)player).IsSwimming() || ((Character)player).InPlaceMode()) { return false; } if (Menu.IsVisible() || InventoryGui.IsVisible() || Minimap.IsOpen() || StoreGui.IsVisible() || Typing()) { return false; } if (((Character)player).InAttack()) { if (_auto && _melee != null) { WantHoldBack(player); } return false; } return true; } private static bool Typing() { if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible()) { return TextInput.IsVisible(); } return true; } private static bool AttackHeld() { if (!ZInput.GetButton("Attack")) { return ZInput.GetButton("JoyAttack"); } return true; } private static bool Pressed(KeyboardShortcut key) { //IL_0002: 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_0031: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref key)).MainKey == 0 || Typing() || !ZInput.GetKeyDown(((KeyboardShortcut)(ref key)).MainKey, false)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref key)).Modifiers) { if (!ZInput.GetKey(modifier, false)) { return false; } } return true; } private void Remark(ItemData melee, Character enemy, DamageType reason) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ShowRemarks.Value || Time.time < _nextRemarkAt) { return; } string[] value; string[] lines = (Because.TryGetValue(reason, out value) ? value : Plain); string text = null; for (int i = 0; i < 6; i++) { if (text != null && !(text == _lastRemark)) { break; } text = Pick(Openers) + " " + string.Format(Pick(lines), ShownName(melee), ShownName(enemy)); } _lastRemark = text; _nextRemarkAt = Time.time + Plugin.RemarkCooldown.Value; _line.Show(text); } private static string Pick(string[] lines) { return lines[Random.Range(0, lines.Length)]; } private static string ShownName(ItemData item) { return Localize(item.m_shared.m_name).ToLowerInvariant(); } private static string ShownName(Character c) { return Localize(c.m_name); } private static string Localize(string token) { if (Localization.instance == null) { return token.TrimStart(new char[1] { '$' }); } return Localization.instance.Localize(token); } private static string Name(ItemData item) { if (!((Object)(object)item.m_dropPrefab != (Object)null)) { return item.m_shared.m_name; } return ((Object)item.m_dropPrefab).name; } private static string Describe(ItemData item) { return $"{Name(item)} (equip time {item.m_shared.m_equipDuration:0.##} s)"; } private static void Note(string message) { if (Plugin.DebugLog.Value) { Plugin.Log.LogInfo((object)(message + (Plugin.InstantSwap.Value ? " Instant." : " Game timer."))); } } static SecondHand() { DamageType[] array = new DamageType[8]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Types = (DamageType[])(object)array; Openers = new string[4] { "Too close for arrows.", "Bow down.", "No time to nock.", "Close enough to smell." }; Because = new Dictionary<DamageType, string[]> { [(DamageType)1] = new string[3] { "Odin chose the {0}. {1}s hate something heavy.", "The {0}. Some things only listen to blunt arguments.", "Odin chose the {0}. Bones break; that's what they're for." }, [(DamageType)2] = new string[3] { "Odin chose the {0}. {1}s don't care for edges.", "The {0}. Long cuts for soft things.", "Odin chose the {0}. The sharp end goes in front." }, [(DamageType)4] = new string[3] { "Odin chose the {0}. Find the gap and lean on it.", "The {0}. {1}s have holes in their plans; make more.", "Odin chose the {0}. Poke, then poke again." }, [(DamageType)32] = new string[3] { "Odin chose the {0}. {1}s and fire don't get on.", "The {0}. Warm it up.", "Odin chose the {0}. He likes a bit of smoke." }, [(DamageType)64] = new string[3] { "Odin chose the {0}. Cool it down.", "The {0}. {1}s hate the cold almost as much as you do.", "Odin chose the {0}. Frost it." }, [(DamageType)128] = new string[3] { "Odin chose the {0}. A little thunder, up close.", "The {0}. {1}s don't like a spark.", "Odin chose the {0}. Don't tell Thor." }, [(DamageType)256] = new string[3] { "Odin chose the {0}. Slow, but it gets there.", "The {0}. {1}s can't keep poison down.", "Odin chose the {0}. Let the venom do the walking." }, [(DamageType)512] = new string[3] { "Odin chose the {0}. The dead hate spirit.", "The {0}. {1}s should have stayed in the ground.", "Odin chose the {0}. Send it back where it came from." } }; Plain = new string[3] { "Odin chose the {0}. It hits hardest.", "The {0}. Nothing clever, just the biggest stick you've got.", "Odin chose the {0}. You're welcome." }; } } internal static class BuildInfo { public const string Version = "0.1.1"; } }