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 Armory v1.0.0
BepInEx/plugins/Armory.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Armory { [BepInPlugin("GBahns.Armory", "Armory", "1.0.0")] [BepInProcess("valheim.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ArmoryMod : BaseUnityPlugin { public const string ModGuid = "GBahns.Armory"; private readonly Harmony _harmony = new Harmony("GBahns.Armory"); public static ArmoryMod Instance; public static ConfigEntry<bool> ModEnabled; private bool _initialized; public static ConfigEntry<bool> PauseGameWhileOpen; public static ConfigEntry<bool> ShowSummaryText; public static ConfigEntry<bool> ShowIcons; public static ConfigEntry<float> PanelPosX; public static ConfigEntry<float> PanelPosY; private void Awake() { Instance = this; ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Mod Enabled", true, "Master toggle for the entire mod. Set to false to disable the Armory Rack piece, the UI, and all Harmony patches without removing the DLL. Useful for quickly isolating mod conflicts. Requires a game restart to take effect."); PauseGameWhileOpen = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Pause Game While Armory Open", false, "Pause the game (Time.timeScale = 0) while the Armory Rack panel is open. Intended for singleplayer — in multiplayer this only pauses your local clock, which can desync you from the server."); ShowSummaryText = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Show Summary Text", true, "Show the textual list of items below each loadout's name (Helm:..., Chest:..., etc)."); ShowIcons = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Show Icons", true, "Show the row of item icons at the bottom of each loadout row."); PanelPosX = ((BaseUnityPlugin)this).Config.Bind<float>("Window", "Panel Position X", 380f, "Saved horizontal panel position (auto-updated when you close the rack)."); PanelPosY = ((BaseUnityPlugin)this).Config.Bind<float>("Window", "Panel Position Y", 0f, "Saved vertical panel position (auto-updated when you close the rack)."); if (!ModEnabled.Value) { Logger.LogInfo((object)"[Armory] Mod Enabled = false in config — skipping piece registration and Harmony patches."); return; } _initialized = true; _harmony.PatchAll(); CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { ["armory_rack_name"] = "Armory Rack", ["armory_rack_desc"] = "A masterwork rack for storing and instantly recalling named equipment sets." }); PrefabManager.OnVanillaPrefabsAvailable += ArmoryPieces.CreatePiece; PieceManager.OnPiecesRegistered += ArmoryPieces.ConfigureAndRegister; } private void Update() { if (_initialized) { ArmoryUI.Tick(); } } private void OnDestroy() { if (_initialized) { _harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(Player), "TakeInput")] internal static class Player_TakeInput_Patch { private static bool Prefix() { return !ArmoryUI.IsOpen; } } [HarmonyPatch(typeof(Player), "SetMouseLook")] internal static class Player_SetMouseLook_Patch { private static bool Prefix() { return !ArmoryUI.IsOpen; } } [HarmonyPatch(typeof(Chat), "HasFocus")] internal static class Chat_HasFocus_Patch { private static void Postfix(ref bool __result) { if (ArmoryUI.IsEditing) { __result = true; } } } internal static class ArmoryPieces { private const string PieceName = "armory_rack"; private const string BasePrefab = "piece_chest_blackmetal"; private const string PieceTable = "_HammerPieceTable"; private const string Category = "Furniture"; private static GameObject _clone; private static bool _clonesCreated; private static bool _piecesConfigured; private static readonly FieldInfo _namedPrefabsField = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs"); private static Dictionary<int, GameObject> GetNamedPrefabs() { if (!((Object)(object)ZNetScene.instance != (Object)null)) { return null; } return _namedPrefabsField?.GetValue(ZNetScene.instance) as Dictionary<int, GameObject>; } internal static void CreatePiece() { if (_clonesCreated) { return; } _clonesCreated = true; GameObject prefab = PrefabManager.Instance.GetPrefab("piece_chest_blackmetal"); if ((Object)(object)prefab == (Object)null) { Logger.LogError((object)"[Armory] Base prefab 'piece_chest_wood' not found."); return; } _clone = PrefabManager.Instance.CreateClonedPrefab("armory_rack", prefab); Dictionary<int, GameObject> namedPrefabs = GetNamedPrefabs(); if (namedPrefabs != null) { namedPrefabs[StringExtensionMethods.GetStableHashCode(((Object)_clone).name)] = _clone; } Container component = _clone.GetComponent<Container>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } _clone.AddComponent<ArmoryRack>(); BuildArmoireMesh(_clone); Piece obj = _clone.GetComponent<Piece>() ?? _clone.AddComponent<Piece>(); obj.m_name = "$armory_rack_name"; obj.m_description = "$armory_rack_desc"; obj.m_groundOnly = false; obj.m_groundPiece = false; obj.m_resources = (Requirement[])(object)new Requirement[0]; Logger.LogInfo((object)"[Armory] Phase 1 — cloned armory_rack"); } private static void BuildArmoireMesh(GameObject parent) { //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = parent.GetComponentsInChildren<Renderer>(); Renderer[] array = componentsInChildren; for (int i = 0; i < array.Length; i++) { array[i].enabled = false; } GameObject prefab = PrefabManager.Instance.GetPrefab("wood_floor_1x1"); if ((Object)(object)prefab == (Object)null) { Logger.LogWarning((object)"[Armory] wood_floor_1x1 unavailable — reverting to chest visual."); array = componentsInChildren; for (int i = 0; i < array.Length; i++) { array[i].enabled = true; } return; } GameObject val = null; string text = null; string[] array2 = new string[4] { "wood_shutter", "wood_shutter_closed", "wood_window_shutter", "wood_window" }; foreach (string text2 in array2) { val = PrefabManager.Instance.GetPrefab(text2); if ((Object)(object)val != (Object)null) { text = text2; break; } } if ((Object)(object)val == (Object)null) { val = prefab; text = "wood_floor_1x1 (shutter unavailable)"; } Logger.LogInfo((object)("[Armory] BuildArmoireMesh: door prefab = '" + text + "'.")); for (int j = 0; j < 2; j++) { for (int k = 0; k < 3; k++) { AddPanel(parent, prefab, new Vector3(-0.5f + (float)j, 0.5f + (float)k, -0.5f), Quaternion.Euler(-90f, 0f, 0f)); } } for (int l = 0; l < 3; l++) { AddPanel(parent, prefab, new Vector3(-1f, 0.5f + (float)l, 0f), Quaternion.Euler(0f, 0f, -90f)); } for (int m = 0; m < 3; m++) { AddPanel(parent, prefab, new Vector3(1f, 0.5f + (float)m, 0f), Quaternion.Euler(0f, 0f, 90f)); } for (int n = 0; n < 2; n++) { AddPanel(parent, prefab, new Vector3(-0.5f + (float)n, 3f, 0f), Quaternion.identity); } for (int num = 0; num < 2; num++) { AddPanel(parent, prefab, new Vector3(-0.5f + (float)num, 0f, 0f), Quaternion.Euler(180f, 0f, 0f)); } BuildDoor(parent, val, "ArmoryDoorLeft", new Vector3(-1f, 0f, 0.5f), 0f, flipped: true); BuildDoor(parent, val, "ArmoryDoorRight", new Vector3(1f, 0f, 0.5f), 0f, flipped: false); BoxCollider obj = parent.AddComponent<BoxCollider>(); obj.center = new Vector3(0f, 1.5f, 0f); obj.size = new Vector3(2f, 3f, 1f); ApplyTint(parent.transform, new Color(0.5f, 0.5f, 0.5f)); Transform val2 = parent.transform.Find("ArmoryDoorLeft"); Transform val3 = parent.transform.Find("ArmoryDoorRight"); if ((Object)(object)val2 != (Object)null) { ApplyTint(val2, new Color(0.75f, 0.75f, 0.75f)); } if ((Object)(object)val3 != (Object)null) { ApplyTint(val3, new Color(0.75f, 0.75f, 0.75f)); } Logger.LogInfo((object)"[Armory] BuildArmoireMesh: composed 16 wood panels + 2 doors (panels 50%, shutters 75%)."); } private static void ApplyTint(Transform root, Color tint) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if (!val.enabled) { continue; } Material[] materials = val.materials; foreach (Material val2 in materials) { if (val2.HasProperty("_Color")) { val2.color = tint; } } } } private static void BuildDoor(GameObject parent, GameObject panelSrc, string hingeName, Vector3 hingeLocalPos, float panelOffsetX, bool flipped) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_001f: 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_004f: 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_0054: 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_008a: 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) GameObject val = new GameObject(hingeName); val.transform.SetParent(parent.transform, false); val.transform.localPosition = hingeLocalPos; val.transform.localRotation = Quaternion.identity; Vector3 localScale = (Vector3)(flipped ? new Vector3(-1f, 1f, 1f) : Vector3.one); for (int i = 0; i < 3; i++) { GameObject obj = Object.Instantiate<GameObject>(panelSrc, val.transform); obj.transform.localPosition = new Vector3(panelOffsetX, 0.5f + (float)i, 0f); obj.transform.localRotation = Quaternion.identity; obj.transform.localScale = localScale; ((Object)obj).name = ((Object)panelSrc).name + "_panel"; StripChildComponents(obj); } } private static void StripChildComponents(GameObject visual) { Door[] componentsInChildren = visual.GetComponentsInChildren<Door>(); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Piece[] componentsInChildren2 = visual.GetComponentsInChildren<Piece>(); for (int i = 0; i < componentsInChildren2.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren2[i]); } WearNTear[] componentsInChildren3 = visual.GetComponentsInChildren<WearNTear>(); for (int i = 0; i < componentsInChildren3.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren3[i]); } ZNetView[] componentsInChildren4 = visual.GetComponentsInChildren<ZNetView>(); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren4[i]); } ZSyncTransform[] componentsInChildren5 = visual.GetComponentsInChildren<ZSyncTransform>(); for (int i = 0; i < componentsInChildren5.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren5[i]); } Collider[] componentsInChildren6 = visual.GetComponentsInChildren<Collider>(); for (int i = 0; i < componentsInChildren6.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren6[i]); } SnapToGround[] componentsInChildren7 = visual.GetComponentsInChildren<SnapToGround>(); for (int i = 0; i < componentsInChildren7.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren7[i]); } } private static void AddPanel(GameObject parent, GameObject source, Vector3 localPos, Quaternion localRot) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) GameObject obj = Object.Instantiate<GameObject>(source, parent.transform); obj.transform.localPosition = localPos; obj.transform.localRotation = localRot; ((Object)obj).name = ((Object)source).name + "_panel"; StripChildComponents(obj); } internal static void ConfigureAndRegister() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Expected O, but got Unknown if (_piecesConfigured) { return; } _piecesConfigured = true; if ((Object)(object)_clone == (Object)null) { Logger.LogError((object)"[Armory] Phase 2: no clone from Phase 1 — Armory Rack unavailable."); return; } Piece component = _clone.GetComponent<Piece>(); if ((Object)(object)component == (Object)null) { return; } GameObject prefab = PrefabManager.Instance.GetPrefab("piece_chest_blackmetal"); WearNTear val = ((prefab != null) ? prefab.GetComponent<WearNTear>() : null); WearNTear val2 = _clone.GetComponent<WearNTear>() ?? _clone.AddComponent<WearNTear>(); val2.m_health = 500f; val2.m_materialType = (MaterialType)0; if ((Object)(object)val != (Object)null) { val2.m_destroyedEffect = val.m_destroyedEffect; val2.m_hitEffect = val.m_hitEffect; } List<Requirement> requirements = new List<Requirement>(); AddReq("FineWood", 8); AddReq("RoundLog", 4); AddReq("BronzeNails", 4); AddReq("Bronze", 2); AddReq("DeerHide", 2); component.m_resources = requirements.ToArray(); GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_workbench"); component.m_craftingStation = ((prefab2 != null) ? prefab2.GetComponent<CraftingStation>() : null); object obj = LoadEmbeddedIcon("armory.png"); if (obj == null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("ArmorLeatherChest"); if (itemPrefab == null) { obj = null; } else { ItemDrop component2 = itemPrefab.GetComponent<ItemDrop>(); if (component2 == null) { obj = null; } else { ItemData itemData = component2.m_itemData; if (itemData == null) { obj = null; } else { SharedData shared = itemData.m_shared; if (shared == null) { obj = null; } else { Sprite[] icons = shared.m_icons; obj = ((icons != null) ? icons[0] : null); } } } } } component.m_icon = (Sprite)obj; GameObject prefab3 = PrefabManager.Instance.GetPrefab("piece_chest_blackmetal"); Piece val3 = ((prefab3 != null) ? prefab3.GetComponent<Piece>() : null); if ((Object)(object)val3 != (Object)null) { component.m_placeEffect = val3.m_placeEffect; } if ((Object)(object)_clone.GetComponent<Container>() == (Object)null) { Container val4 = _clone.AddComponent<Container>(); GameObject prefab4 = PrefabManager.Instance.GetPrefab("piece_chest_blackmetal"); Container val5 = ((prefab4 != null) ? prefab4.GetComponent<Container>() : null); if ((Object)(object)val5 != (Object)null) { val4.m_bkg = val5.m_bkg; val4.m_destroyedLootPrefab = val5.m_destroyedLootPrefab; } val4.m_name = "$armory_rack_name"; val4.m_width = 8; val4.m_height = 4; } PieceConfig val6 = new PieceConfig { Name = "Armory Rack", PieceTable = "_HammerPieceTable", Category = "Furniture" }; PieceManager.Instance.AddPiece(new CustomPiece(_clone, false, val6)); Logger.LogInfo((object)"[Armory] Phase 2 — registered armory_rack"); EnsureInPieceTable(); EnsureInNamedPrefabs(); void AddReq(string prefabName, int amount) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_0046: Expected O, but got Unknown GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(prefabName); ItemDrop val7 = ((itemPrefab2 != null) ? itemPrefab2.GetComponent<ItemDrop>() : null); if ((Object)(object)val7 != (Object)null) { requirements.Add(new Requirement { m_resItem = val7, m_amount = amount, m_recover = true }); } else { Logger.LogWarning((object)("[Armory] Recipe ingredient '" + prefabName + "' not found in ObjectDB — skipped.")); } } } private static void EnsureInPieceTable() { if (!((Object)(object)_clone == (Object)null)) { ObjectDB instance = ObjectDB.instance; object obj; if (instance == null) { obj = null; } else { GameObject itemPrefab = instance.GetItemPrefab("Hammer"); obj = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared?.m_buildPieces); } PieceTable val = (PieceTable)obj; if ((Object)(object)val == (Object)null) { Logger.LogInfo((object)"[Armory] EnsureInPieceTable: Hammer not accessible yet."); return; } if (val.m_pieces.Contains(_clone)) { Logger.LogInfo((object)"[Armory] EnsureInPieceTable: armory_rack already present."); return; } val.m_pieces.Add(_clone); Logger.LogInfo((object)"[Armory] EnsureInPieceTable: inserted armory_rack."); } } private static Sprite LoadEmbeddedIcon(string fileName) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = Array.Find(executingAssembly.GetManifestResourceNames(), (string n) => n.EndsWith(fileName)); if (text == null) { return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!UnityLoadImage(val, array)) { return null; } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)((Texture)val).width); } catch (Exception ex) { Logger.LogWarning((object)("[Armory] Failed to load embedded icon '" + fileName + "': " + ex.Message)); return null; } } private static bool UnityLoadImage(Texture2D tex, byte[] bytes) { try { MethodInfo methodInfo = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }); return methodInfo != null && (bool)methodInfo.Invoke(null, new object[2] { tex, bytes }); } catch { return false; } } private static void EnsureInNamedPrefabs() { if ((Object)(object)_clone == (Object)null) { return; } Dictionary<int, GameObject> namedPrefabs = GetNamedPrefabs(); if (namedPrefabs != null) { int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)_clone).name); if (!namedPrefabs.ContainsKey(stableHashCode)) { namedPrefabs[stableHashCode] = _clone; Logger.LogInfo((object)"[Armory] EnsureInNamedPrefabs: added armory_rack."); } } } } public class ArmoryRack : MonoBehaviour, Hoverable, Interactable { private ZNetView m_nview; private Transform _leftHinge; private Transform _rightHinge; private float _doorAngle01; private const float DoorOpenRate = 4f; private const float DoorOpenDegrees = 95f; private void Awake() { m_nview = ((Component)this).GetComponent<ZNetView>(); if ((Object)(object)m_nview != (Object)null) { m_nview.Register<string>("ArmoryRPC_SetData", (Action<long, string>)RPC_SetData); } _leftHinge = ((Component)this).transform.Find("ArmoryDoorLeft"); _rightHinge = ((Component)this).transform.Find("ArmoryDoorRight"); } public Container GetStorage() { return ((Component)this).GetComponent<Container>(); } public Inventory GetStorageInventory() { Container storage = GetStorage(); if (storage == null) { return null; } return storage.GetInventory(); } private void Update() { //IL_007a: 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 (!((Object)(object)_leftHinge == (Object)null) && !((Object)(object)_rightHinge == (Object)null)) { float num = ((ArmoryUI.IsOpen && (Object)(object)ArmoryUI.CurrentRack == (Object)(object)this) ? 1f : 0f); _doorAngle01 = Mathf.MoveTowards(_doorAngle01, num, 4f * Time.deltaTime); float num2 = _doorAngle01 * 95f; _leftHinge.localRotation = Quaternion.Euler(0f, 0f - num2, 0f); _rightHinge.localRotation = Quaternion.Euler(0f, num2, 0f); } } public string GetHoverName() { return "Armory"; } public float GetHoverOffset() { return 0f; } public string GetHoverText() { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { return string.Empty; } return LocalizeText("Armory\n[<color=yellow><b>$KEY_Use</b></color>] Manage Loadouts\n<color=#aaaaaa>Save and recall named equipment sets.</color>"); } private static string LocalizeText(string text) { try { Type type = AccessTools.TypeByName("Localization"); if (type == null) { return text; } object obj = AccessTools.Property(type, "instance")?.GetValue(null) ?? AccessTools.Field(type, "instance")?.GetValue(null); if (obj == null) { return text; } return (AccessTools.Method(type, "Localize", new Type[1] { typeof(string) }, (Type[])null)?.Invoke(obj, new object[1] { text }) as string) ?? text; } catch { return text; } } public bool Interact(Humanoid user, bool hold, bool alt) { if (hold || !(user is Player)) { return false; } ArmoryUI.Open(this); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } public ArmoryData GetData() { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { Logger.LogWarning((object)"[Armory] GetData: ZNetView not valid, returning empty data"); return new ArmoryData(); } string text = m_nview.GetZDO().GetString("armory_data", ""); Logger.LogInfo((object)$"[Armory] GetData: read {text.Length} bytes from ZDO"); if (string.IsNullOrEmpty(text)) { return new ArmoryData(); } try { ArmoryData armoryData = ArmorySerializer.Deserialize(text); Logger.LogInfo((object)$"[Armory] GetData: parsed {armoryData.Slots.Count} slot(s)"); return armoryData; } catch (Exception ex) { Logger.LogError((object)("[Armory] GetData parse error: " + ex.Message)); return new ArmoryData(); } } public void SaveData(ArmoryData data) { if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid()) { Logger.LogWarning((object)"[Armory] SaveData: ZNetView not valid, dropping save"); return; } string text = ArmorySerializer.Serialize(data); if (m_nview.IsOwner()) { m_nview.GetZDO().Set("armory_data", text); Logger.LogInfo((object)$"[Armory] SaveData: direct write ({text.Length} bytes) — isOwner=true"); } else { m_nview.InvokeRPC("ArmoryRPC_SetData", new object[1] { text }); Logger.LogInfo((object)$"[Armory] SaveData: RPC to owner ({text.Length} bytes) — isOwner=false"); } } private void RPC_SetData(long sender, string json) { if (m_nview.IsOwner()) { m_nview.GetZDO().Set("armory_data", json); Logger.LogInfo((object)$"[Armory] RPC_SetData: applied {json.Length} bytes"); } } } internal static class ArmoryUI { private class SlotRowRefs { public GameObject Root; public GameObject NameLabelGo; public Text NameLabel; public GameObject NameInputGo; public InputField NameInput; public Button LoadButton; public Text LoadButtonLabel; public Color LoadButtonDefaultColor; public Button CompareButton; public Button ClearButton; public Text Summary; public GameObject IconsContainer; } [CompilerGenerated] private static class <>O { public static UnityAction <0>__Close; public static UnityAction <1>__OnAddSlotClicked; public static UnityAction <2>__CloseConfirmModal; public static UnityAction <3>__ToggleCompareOff; } private static ArmoryRack _rack; private static ArmoryData _data; private static bool _isOpen; private static Vector2? _savedMainPos; private static Vector2? _savedComparePos; private static bool _pausedGame; private static float _previousTimeScale; private static float _lastIconRefresh; private const int DefaultSlotCount = 5; private const int MaxSlotCount = 10; private const float MaxInteractDistance = 5f; private static int _editingSlot = -1; private static int _compareSlot = -1; private static GameObject _mainPanel; private static GameObject _comparePanel; private static GameObject _confirmModal; private static RectTransform _slotsContent; private static readonly List<SlotRowRefs> _rows = new List<SlotRowRefs>(); private const string SaveIcon = "↓"; private const string LoadIcon = "↑"; private const float TitleAreaPx = 70f; private const float FooterAreaPx = 70f; private const float TopRowPx = 48f; private const float SummaryRowPx = 22f; private const float IconStripPx = 66f; private const float RowPaddingPx = 8f; private const float RowSpacingPx = 2f; private const float ScrollListPadPx = 8f; private const float ScrollListGapPx = 4f; private static bool? _lastShowSummary; private static bool? _lastShowIcons; private static RectTransform _scrollRT; private const float IconSize = 60f; private static GameObject _tooltipGo; private static Text _tooltipText; private static RectTransform _tooltipRT; public static bool IsOpen => _isOpen; public static ArmoryRack CurrentRack => _rack; public static bool IsEditing { get { if (_isOpen) { return _editingSlot >= 0; } return false; } } public static void Open(ArmoryRack rack) { if (_isOpen) { Close(); } _rack = rack; _data = rack.GetData(); LoadoutManager.EnsureSlots(_data, 5); Logger.LogInfo((object)$"[Armory] Open: rack instance {((Object)rack).GetInstanceID()}, slots loaded={_data.Slots.Count}"); for (int i = 0; i < _data.Slots.Count; i++) { Logger.LogInfo((object)$"[Armory] slot {i}: name='{_data.Slots[i].Name}' empty={_data.Slots[i].IsEmpty()}"); } _editingSlot = -1; _compareSlot = -1; _isOpen = true; BuildUI(); LoadoutManager.MigrateOutOfBoundsItems(rack.GetStorageInventory()); if ((Object)(object)InventoryGui.instance != (Object)null) { InventoryGui.instance.Show(rack.GetStorage(), 1); } bool flag = ArmoryMod.PauseGameWhileOpen != null && ArmoryMod.PauseGameWhileOpen.Value; Logger.LogInfo((object)$"[Armory] Open: PauseGameWhileOpen={flag}, currentTimeScale={Time.timeScale}"); if (flag) { _previousTimeScale = ((Time.timeScale > 0f) ? Time.timeScale : 1f); Time.timeScale = 0f; _pausedGame = true; Logger.LogInfo((object)$"[Armory] Open: paused — previousTimeScale={_previousTimeScale}, newTimeScale={Time.timeScale}"); } } public static void Close() { //IL_0034: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) _isOpen = false; _editingSlot = -1; _compareSlot = -1; if ((Object)(object)_mainPanel != (Object)null) { RectTransform component = _mainPanel.GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { _savedMainPos = component.anchoredPosition; if (ArmoryMod.PanelPosX != null) { ArmoryMod.PanelPosX.Value = component.anchoredPosition.x; } if (ArmoryMod.PanelPosY != null) { ArmoryMod.PanelPosY.Value = component.anchoredPosition.y; } } Object.Destroy((Object)(object)_mainPanel); _mainPanel = null; } if ((Object)(object)_tooltipGo != (Object)null) { Object.Destroy((Object)(object)_tooltipGo); _tooltipGo = null; _tooltipText = null; _tooltipRT = null; } CloseConfirmModal(); if ((Object)(object)_comparePanel != (Object)null) { RectTransform component2 = _comparePanel.GetComponent<RectTransform>(); if ((Object)(object)component2 != (Object)null) { _savedComparePos = component2.anchoredPosition; } Object.Destroy((Object)(object)_comparePanel); _comparePanel = null; } _slotsContent = null; _rows.Clear(); _lastShowSummary = null; _lastShowIcons = null; _rack = null; if ((Object)(object)InventoryGui.instance != (Object)null) { InventoryGui.instance.Hide(); } if (_pausedGame) { Time.timeScale = ((_previousTimeScale > 0f) ? _previousTimeScale : 1f); _pausedGame = false; Logger.LogInfo((object)$"[Armory] Close: restored timeScale={Time.timeScale}"); } } public static void Tick() { //IL_0089: 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) if (!_isOpen) { return; } if ((Object)(object)_confirmModal != (Object)null && Input.GetKeyDown((KeyCode)27)) { CloseConfirmModal(); return; } if ((Object)(object)InventoryGui.instance == (Object)null || !InventoryGui.IsVisible()) { Close(); return; } if (_editingSlot >= 0 && (Input.GetKeyDown((KeyCode)13) || Input.GetKeyDown((KeyCode)271))) { CommitPendingEdit(); return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)_rack == (Object)null) { Close(); return; } if (Vector3.Distance(((Component)localPlayer).transform.position, ((Component)_rack).transform.position) > 5f) { ((Character)localPlayer).Message((MessageType)2, "Moved too far from the Armory Rack.", 0, (Sprite)null, false); Close(); return; } bool flag = ArmoryMod.ShowSummaryText?.Value ?? true; bool flag2 = ArmoryMod.ShowIcons?.Value ?? true; if (_lastShowSummary != flag || _lastShowIcons != flag2) { _lastShowSummary = flag; _lastShowIcons = flag2; ResizeMainPanel(); } for (int i = 0; i < _rows.Count && i < _data.Slots.Count; i++) { SlotRowRefs slotRowRefs = _rows[i]; LoadoutSlot slot = _data.Slots[i]; UpdateRowEmptyState(slotRowRefs, slot); if ((Object)(object)slotRowRefs.Summary != (Object)null) { slotRowRefs.Summary.text = BuildSummary(slot); if (((Component)slotRowRefs.Summary).gameObject.activeSelf != flag) { ((Component)slotRowRefs.Summary).gameObject.SetActive(flag); } } if ((Object)(object)slotRowRefs.IconsContainer != (Object)null && slotRowRefs.IconsContainer.activeSelf != flag2) { slotRowRefs.IconsContainer.SetActive(flag2); } } if (flag2 && Time.unscaledTime - _lastIconRefresh > 0.5f) { _lastIconRefresh = Time.unscaledTime; for (int j = 0; j < _rows.Count && j < _data.Slots.Count; j++) { RebuildIcons(_rows[j], _data.Slots[j]); } } if (_pausedGame && Time.timeScale != 0f) { Time.timeScale = 0f; } } private static void BuildUI() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (GUIManager.Instance != null && !((Object)(object)GUIManager.CustomGUIFront == (Object)null)) { Transform transform = GUIManager.CustomGUIFront.transform; Vector2 val = (Vector2)(((??)_savedMainPos) ?? new Vector2(ArmoryMod.PanelPosX?.Value ?? 380f, ArmoryMod.PanelPosY?.Value ?? 0f)); _mainPanel = GUIManager.Instance.CreateWoodpanel(transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), val, 760f, ComputePanelHeight(), true); BuildMainPanel(_mainPanel.transform); } } private static void BuildMainPanel(Transform panel) { //IL_0015: 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_0033: 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_004f: 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_0089: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0146: 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_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Expected O, but got Unknown //IL_0348: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Expected O, but got Unknown GUIManager.Instance.CreateText("Armory Rack", panel, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -32f), GUIManager.Instance.AveriaSerifBold, 24, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false); ButtonClickedEvent onClick = GUIManager.Instance.CreateButton("x", panel, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-32f, -32f), 36f, 36f).GetComponent<Button>().onClick; object obj = <>O.<0>__Close; if (obj == null) { UnityAction val = Close; <>O.<0>__Close = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); GUIManager instance = GUIManager.Instance; ColorBlock val2 = default(ColorBlock); ((ColorBlock)(ref val2)).normalColor = new Color(0.5f, 0.4f, 0.2f, 0.8f); ((ColorBlock)(ref val2)).highlightedColor = new Color(0.7f, 0.55f, 0.25f, 0.9f); ((ColorBlock)(ref val2)).pressedColor = new Color(0.4f, 0.3f, 0.15f, 1f); ((ColorBlock)(ref val2)).selectedColor = new Color(0.6f, 0.5f, 0.2f, 0.9f); ((ColorBlock)(ref val2)).disabledColor = new Color(0.3f, 0.25f, 0.15f, 0.5f); ((ColorBlock)(ref val2)).colorMultiplier = 1f; ((ColorBlock)(ref val2)).fadeDuration = 0.1f; GameObject val3 = instance.CreateScrollView(panel, false, true, 10f, 4f, val2, new Color(0.04f, 0.04f, 0.04f, 0.6f), 700f, ComputePanelHeight() - 70f - 70f); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.anchoredPosition = new Vector2(0f, 10f); _scrollRT = component; ScrollRect componentInChildren = val3.GetComponentInChildren<ScrollRect>(); if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren.content == (Object)null) { Logger.LogError((object)"[Armory] CreateScrollView did not yield a ScrollRect with content."); return; } ScrollRect[] componentsInChildren = val3.GetComponentsInChildren<ScrollRect>(true); foreach (ScrollRect val4 in componentsInChildren) { Logger.LogInfo((object)$"[Armory] ScrollRect found on '{((Object)val4).name}': sensitivity was {val4.scrollSensitivity}"); val4.scrollSensitivity = 100f; } RectTransform content = componentInChildren.content; LayoutGroup[] components = ((Component)content).GetComponents<LayoutGroup>(); for (int i = 0; i < components.Length; i++) { Object.DestroyImmediate((Object)(object)components[i]); } VerticalLayoutGroup obj2 = ((Component)content).gameObject.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 4f; ((LayoutGroup)obj2).padding = new RectOffset(4, 4, 4, 4); ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; if ((Object)(object)((Component)content).GetComponent<ContentSizeFitter>() == (Object)null) { ((Component)content).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; } _slotsContent = content; ButtonClickedEvent onClick2 = GUIManager.Instance.CreateButton("+ Add Slot", panel, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 36f), 180f, 40f).GetComponent<Button>().onClick; object obj3 = <>O.<1>__OnAddSlotClicked; if (obj3 == null) { UnityAction val5 = OnAddSlotClicked; <>O.<1>__OnAddSlotClicked = val5; obj3 = (object)val5; } ((UnityEvent)onClick2).AddListener((UnityAction)obj3); RebuildSlotRows(); } private static void RebuildSlotRows() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_slotsContent == (Object)null) { return; } foreach (Transform item in (Transform)_slotsContent) { Object.Destroy((Object)(object)((Component)item).gameObject); } _rows.Clear(); for (int i = 0; i < _data.Slots.Count; i++) { _rows.Add(BuildSlotRow(i)); } } private static SlotRowRefs BuildSlotRow(int index) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_00e2: 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_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Expected O, but got Unknown //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0267: 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_027b: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Expected O, but got Unknown //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Expected O, but got Unknown //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03be: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Expected O, but got Unknown //IL_040c: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Expected O, but got Unknown //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_0476: Unknown result type (might be due to invalid IL or missing references) //IL_0496: Unknown result type (might be due to invalid IL or missing references) //IL_04a6: Unknown result type (might be due to invalid IL or missing references) //IL_04d4: Unknown result type (might be due to invalid IL or missing references) //IL_0449: Unknown result type (might be due to invalid IL or missing references) LoadoutSlot loadoutSlot = _data.Slots[index]; SlotRowRefs slotRowRefs = new SlotRowRefs(); GameObject val = new GameObject($"SlotRow_{index}", new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)_slotsContent, false); VerticalLayoutGroup obj = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 2f; ((LayoutGroup)obj).padding = new RectOffset(6, 6, 4, 4); ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((Graphic)val.AddComponent<Image>()).color = ((index % 2 == 0) ? new Color(0.2f, 0.15f, 0.08f, 0.55f) : new Color(0.13f, 0.1f, 0.06f, 0.55f)); val.AddComponent<LayoutElement>().minHeight = 60f; GameObject val2 = new GameObject("Top", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent(val.transform, false); HorizontalLayoutGroup obj2 = val2.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((LayoutGroup)obj2).childAlignment = (TextAnchor)3; val2.AddComponent<LayoutElement>().preferredHeight = 48f; (GameObject, Text) tuple = AddText(val2.transform, loadoutSlot.Name, 16, 200f, 44f, GUIManager.Instance.ValheimOrange, leftAlign: true); slotRowRefs.NameLabel = tuple.Item2; (slotRowRefs.NameLabelGo, _) = tuple; if ((Object)(object)slotRowRefs.NameLabel != (Object)null) { ((Graphic)slotRowRefs.NameLabel).raycastTarget = true; } Button obj3 = tuple.Item1.AddComponent<Button>(); int capturedNameIdx = index; ((UnityEvent)obj3.onClick).AddListener((UnityAction)delegate { OnNameClicked(capturedNameIdx); }); ColorBlock colors = ((Selectable)obj3).colors; ((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 0.95f, 0.75f, 1f); ((ColorBlock)(ref colors)).pressedColor = new Color(1f, 0.85f, 0.55f, 1f); ((Selectable)obj3).colors = colors; GameObject val3 = GUIManager.Instance.CreateInputField(val2.transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), Vector2.zero, (ContentType)0, "", 14, 200f, 44f); slotRowRefs.NameInput = val3.GetComponent<InputField>(); slotRowRefs.NameInputGo = val3; LayoutElement obj4 = val3.GetComponent<LayoutElement>() ?? val3.AddComponent<LayoutElement>(); obj4.preferredWidth = 200f; obj4.preferredHeight = 44f; val3.SetActive(false); GameObject val4 = new GameObject("Spacer", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(val2.transform, false); LayoutElement obj5 = val4.AddComponent<LayoutElement>(); obj5.flexibleWidth = 1f; obj5.minWidth = 0f; AttachTooltip(AddRowButton(val2.transform, "↓", 44f, (UnityAction)delegate { OnSaveClicked(index); }), "Save"); GameObject val5 = AddRowButton(val2.transform, "↑", 44f, (UnityAction)delegate { OnLoadClicked(index); }); AttachTooltip(val5, "Load"); slotRowRefs.LoadButton = val5.GetComponent<Button>(); slotRowRefs.LoadButtonLabel = val5.GetComponentInChildren<Text>(); slotRowRefs.LoadButtonDefaultColor = (((Object)(object)slotRowRefs.LoadButtonLabel != (Object)null) ? ((Graphic)slotRowRefs.LoadButtonLabel).color : Color.white); GameObject val6 = AddRowButton(val2.transform, "Cmp", 75f, (UnityAction)delegate { OnCompareClicked(index); }); slotRowRefs.CompareButton = val6.GetComponent<Button>(); GameObject val7 = AddRowButton(val2.transform, "x", 50f, (UnityAction)delegate { OnClearClicked(index); }); slotRowRefs.ClearButton = val7.GetComponent<Button>(); Text componentInChildren = val7.GetComponentInChildren<Text>(); if ((Object)(object)componentInChildren != (Object)null) { ((Graphic)componentInChildren).color = new Color(0.95f, 0.35f, 0.35f); } ColorBlock colors2 = ((Selectable)slotRowRefs.ClearButton).colors; ((ColorBlock)(ref colors2)).highlightedColor = new Color(0.85f, 0.2f, 0.2f, 1f); ((ColorBlock)(ref colors2)).pressedColor = new Color(0.65f, 0.12f, 0.12f, 1f); ((Selectable)slotRowRefs.ClearButton).colors = colors2; (GameObject, Text) tuple3 = AddText(val.transform, BuildSummary(loadoutSlot), 12, 480f, 22f, new Color(0.78f, 0.72f, 0.58f), leftAlign: true, richText: true); slotRowRefs.Summary = tuple3.Item2; SetHeight(tuple3.Item1, 22f); slotRowRefs.IconsContainer = BuildIconsStrip(); slotRowRefs.IconsContainer.transform.SetParent(val.transform, false); PopulateIcons(slotRowRefs.IconsContainer.transform, loadoutSlot); slotRowRefs.Root = val; UpdateRowEditState(slotRowRefs, index); UpdateRowEmptyState(slotRowRefs, _data.Slots[index]); return slotRowRefs; } private static GameObject BuildIconsStrip() { //IL_0018: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown GameObject val = new GameObject("Icons", new Type[1] { typeof(RectTransform) }); HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 3f; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((LayoutGroup)obj).padding = new RectOffset(4, 4, 2, 2); ((LayoutGroup)obj).childAlignment = (TextAnchor)3; val.AddComponent<LayoutElement>().preferredHeight = 66f; return val; } private static void PopulateIcons(Transform parent, LoadoutSlot slot) { Player localPlayer = Player.m_localPlayer; Inventory playerInv = ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null); Inventory rackInv = _rack?.GetStorageInventory(); AddIcon(parent, slot.Helmet, playerInv, rackInv); AddIcon(parent, slot.Chest, playerInv, rackInv); AddIcon(parent, slot.Legs, playerInv, rackInv); AddIcon(parent, slot.Shoulder, playerInv, rackInv); AddIcon(parent, slot.Utility, playerInv, rackInv); AddIconSpacer(parent, 10f); if (slot.Hotbar != null) { for (int i = 0; i < 8 && i < slot.Hotbar.Length; i++) { AddIcon(parent, slot.Hotbar[i], playerInv, rackInv); } } if (slot.Extended == null || slot.Extended.Count <= 0) { return; } AddIconSpacer(parent, 10f); foreach (SavedItem item in slot.Extended) { AddIcon(parent, item, playerInv, rackInv); } } private static void AddIcon(Transform parent, SavedItem item, Inventory playerInv, Inventory rackInv) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(item?.SharedName ?? "EmptySlot", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); LayoutElement obj = val.AddComponent<LayoutElement>(); obj.preferredWidth = 60f; obj.preferredHeight = 60f; Image val2 = val.AddComponent<Image>(); ((Graphic)val2).raycastTarget = true; if (item == null) { ((Graphic)val2).color = new Color(0.1f, 0.1f, 0.1f, 0.35f); } else { bool flag = LoadoutManager.IsItemAvailable(item, playerInv, rackInv); ((Graphic)val2).color = (flag ? new Color(0.15f, 0.12f, 0.08f, 0.8f) : new Color(0.55f, 0.15f, 0.15f, 0.9f)); } if (item != null) { GameObject val3 = new GameObject("Icon", new Type[1] { typeof(RectTransform) }); val3.transform.SetParent(val.transform, false); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(2f, 2f); component.offsetMax = new Vector2(-2f, -2f); Image val4 = val3.AddComponent<Image>(); ((Graphic)val4).raycastTarget = false; Sprite icon = LoadoutManager.GetIcon(item); if ((Object)(object)icon != (Object)null) { val4.sprite = icon; val4.preserveAspect = true; ((Graphic)val4).color = Color.white; } else { ((Graphic)val4).color = new Color(0.5f, 0.4f, 0.3f, 0.7f); } AttachTooltip(val, LoadoutManager.GetItemDisplayName(item)); } } private static void EnsureTooltip() { //IL_019b: 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_0040: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_tooltipGo != (Object)null) { return; } GameObject customGUIFront = GUIManager.CustomGUIFront; if (!((Object)(object)customGUIFront == (Object)null)) { _tooltipGo = new GameObject("ArmoryTooltip", new Type[1] { typeof(RectTransform) }); _tooltipGo.transform.SetParent(customGUIFront.transform, false); _tooltipRT = _tooltipGo.GetComponent<RectTransform>(); _tooltipRT.pivot = new Vector2(0f, 0f); Image obj = _tooltipGo.AddComponent<Image>(); ((Graphic)obj).color = new Color(0.04f, 0.04f, 0.04f, 0.92f); ((Graphic)obj).raycastTarget = false; GameObject val = new GameObject("Text", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(_tooltipGo.transform, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(8f, 4f); component.offsetMax = new Vector2(-8f, -4f); _tooltipText = val.AddComponent<Text>(); ((Graphic)_tooltipText).color = GUIManager.Instance.ValheimOrange; _tooltipText.fontSize = 14; _tooltipText.alignment = (TextAnchor)3; ((Graphic)_tooltipText).raycastTarget = false; _tooltipText.horizontalOverflow = (HorizontalWrapMode)1; try { GUIManager.Instance.ApplyTextStyle(_tooltipText, ((Graphic)_tooltipText).color, 16, true); } catch { } ((Graphic)_tooltipText).color = GUIManager.Instance.ValheimOrange; _tooltipGo.SetActive(false); } } private static void ShowTooltip(string text, Vector2 screenPos) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) EnsureTooltip(); if (!((Object)(object)_tooltipGo == (Object)null)) { _tooltipText.text = text; float num = _tooltipText.preferredWidth + 16f; float num2 = _tooltipText.preferredHeight + 8f; _tooltipRT.sizeDelta = new Vector2(num, num2); ((Transform)_tooltipRT).position = new Vector3(screenPos.x + 12f, screenPos.y + 12f, 0f); _tooltipGo.SetActive(true); _tooltipGo.transform.SetAsLastSibling(); } } private static void HideTooltip() { if ((Object)(object)_tooltipGo != (Object)null) { _tooltipGo.SetActive(false); } } private static void AttachTooltip(GameObject host, string text) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown EventTrigger obj = host.AddComponent<EventTrigger>(); Entry val = new Entry { eventID = (EventTriggerType)0 }; ((UnityEvent<BaseEventData>)(object)val.callback).AddListener((UnityAction<BaseEventData>)delegate { //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) ShowTooltip(text, Vector2.op_Implicit(Input.mousePosition)); }); obj.triggers.Add(val); Entry val2 = new Entry { eventID = (EventTriggerType)1 }; ((UnityEvent<BaseEventData>)(object)val2.callback).AddListener((UnityAction<BaseEventData>)delegate { HideTooltip(); }); obj.triggers.Add(val2); } private static void AddIconSpacer(Transform parent, float width) { //IL_0018: 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) GameObject val = new GameObject("Spacer", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); val.AddComponent<LayoutElement>().preferredWidth = width; } private static void RebuildIcons(SlotRowRefs refs, LoadoutSlot slot) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)refs?.IconsContainer == (Object)null) { return; } foreach (Transform item in refs.IconsContainer.transform) { Object.Destroy((Object)(object)((Component)item).gameObject); } PopulateIcons(refs.IconsContainer.transform, slot); } private static void UpdateRowEmptyState(SlotRowRefs refs, LoadoutSlot slot) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) bool flag = !slot.IsEmpty(); bool flag2 = flag && LoadoutManager.IsLoadoutActive(slot, Player.m_localPlayer); if ((Object)(object)refs.CompareButton != (Object)null) { ((Selectable)refs.CompareButton).interactable = flag; } if ((Object)(object)refs.ClearButton != (Object)null) { ((Selectable)refs.ClearButton).interactable = true; } if ((Object)(object)refs.LoadButton != (Object)null) { ((Selectable)refs.LoadButton).interactable = flag && !flag2; } if ((Object)(object)refs.LoadButtonLabel != (Object)null) { refs.LoadButtonLabel.text = (flag2 ? "●" : "↑"); ((Graphic)refs.LoadButtonLabel).color = (Color)(flag2 ? new Color(0.35f, 0.85f, 0.35f) : refs.LoadButtonDefaultColor); } } private static void OnAddSlotClicked() { Logger.LogInfo((object)"[Armory] Click: AddSlot"); CommitPendingEdit(); if (_data.Slots.Count < 10) { _data.Slots.Add(new LoadoutSlot { Name = $"Slot {_data.Slots.Count + 1}" }); _rack.SaveData(_data); RebuildSlotRows(); ResizeMainPanel(); } } private static float ComputeRowHeight() { bool num = ArmoryMod.ShowSummaryText?.Value ?? true; bool flag = ArmoryMod.ShowIcons?.Value ?? true; float num2 = 56f; int num3 = 0; if (num) { num2 += 22f; num3++; } if (flag) { num2 += 66f; num3++; } return num2 + (float)num3 * 2f; } private static float ComputePanelHeight() { int num = _data?.Slots?.Count ?? 5; float num2 = ComputeRowHeight(); float num3 = (float)num * num2 + (float)Math.Max(0, num - 1) * 4f + 8f; float num4 = 140f + num3; float num5 = 140f + (3f * num2 + 8f + 8f); float num6 = (float)Screen.height * 0.9f; return Mathf.Clamp(num4, num5, num6); } private static void ResizeMainPanel() { //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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_mainPanel == (Object)null) { return; } RectTransform component = _mainPanel.GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null)) { float num = ComputePanelHeight(); component.sizeDelta = new Vector2(component.sizeDelta.x, num); if ((Object)(object)_scrollRT != (Object)null) { _scrollRT.sizeDelta = new Vector2(_scrollRT.sizeDelta.x, num - 70f - 70f); } } } private static void OnSaveClicked(int index) { Logger.LogInfo((object)$"[Armory] Click: Save slot {index}"); CommitPendingEdit(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { Logger.LogWarning((object)"[Armory] OnSaveClicked: no local player"); return; } string name = _data.Slots[index].Name; LoadoutSlot loadoutSlot = LoadoutManager.CaptureCurrentEquipment(localPlayer); loadoutSlot.Name = name; _data.Slots[index] = loadoutSlot; _rack.SaveData(_data); ((Character)localPlayer).Message((MessageType)2, "Saved: " + name, 0, (Sprite)null, false); Logger.LogInfo((object)$"[Armory] Saved slot {index} '{name}': {BuildSummary(loadoutSlot)}"); RefreshRowVisual(index); } private static void OnLoadClicked(int index) { Logger.LogInfo((object)$"[Armory] Click: Load slot {index}"); CommitPendingEdit(); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } LoadoutSlot loadoutSlot = _data.Slots[index]; if (loadoutSlot.IsEmpty()) { Logger.LogInfo((object)$"[Armory] Load slot {index}: slot is empty, ignoring"); return; } Container val = _rack?.GetStorage(); Inventory val2 = _rack?.GetStorageInventory(); Logger.LogInfo((object)("[Armory] Load: container=" + (((object)val)?.GetType().Name ?? "null") + ", rackInv=" + ((val2 == null) ? "null" : $"size {val2.GetWidth()}x{val2.GetHeight()}, items={val2.GetAllItems().Count}"))); if (val2 != null) { foreach (ItemData allItem in val2.GetAllItems()) { Logger.LogInfo((object)$"[Armory] rack item: '{allItem.m_shared?.m_name}' qty={allItem.m_stack} quality={allItem.m_quality} at ({allItem.m_gridPos.x},{allItem.m_gridPos.y})"); } } (int found, int missing) tuple = LoadoutManager.ApplyLoadout(localPlayer, loadoutSlot, val2); int item = tuple.found; int item2 = tuple.missing; string text = ((item2 > 0) ? $"Loaded '{loadoutSlot.Name}': {item} equipped, {item2} not in inventory or rack" : $"Loaded '{loadoutSlot.Name}': {item} item(s) equipped"); ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } private static void OnClearClicked(int index) { Logger.LogInfo((object)$"[Armory] Click: Delete slot {index}"); CommitPendingEdit(); if (index >= 0 && index < _data.Slots.Count) { if (!_data.Slots[index].IsEmpty() && !HasDuplicateElsewhere(index)) { ShowDeleteConfirm(index); } else { DeleteSlot(index); } } } private static void DeleteSlot(int index) { if (index >= 0 && index < _data.Slots.Count) { string name = _data.Slots[index].Name; _data.Slots.RemoveAt(index); _rack.SaveData(_data); if (_compareSlot == index) { ToggleCompareOff(); } else if (_compareSlot > index) { _compareSlot--; } if (_editingSlot == index) { _editingSlot = -1; } else if (_editingSlot > index) { _editingSlot--; } Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, "Deleted: " + name, 0, (Sprite)null, false); } RebuildSlotRows(); ResizeMainPanel(); } } private static bool HasDuplicateElsewhere(int index) { if (index < 0 || index >= _data.Slots.Count) { return false; } LoadoutSlot a = _data.Slots[index]; for (int i = 0; i < _data.Slots.Count; i++) { if (i != index && SlotsHaveSameItems(a, _data.Slots[i])) { return true; } } return false; } private static bool SlotsHaveSameItems(LoadoutSlot a, LoadoutSlot b) { if (!SameSavedItem(a.Helmet, b.Helmet)) { return false; } if (!SameSavedItem(a.Chest, b.Chest)) { return false; } if (!SameSavedItem(a.Legs, b.Legs)) { return false; } if (!SameSavedItem(a.Shoulder, b.Shoulder)) { return false; } if (!SameSavedItem(a.Utility, b.Utility)) { return false; } if (!SameSavedItem(a.RightHand, b.RightHand)) { return false; } if (!SameSavedItem(a.LeftHand, b.LeftHand)) { return false; } SavedItem[] hotbar = a.Hotbar; int num = ((hotbar != null) ? hotbar.Length : 0); SavedItem[] hotbar2 = b.Hotbar; int num2 = ((hotbar2 != null) ? hotbar2.Length : 0); int num3 = Math.Max(num, num2); for (int i = 0; i < num3; i++) { SavedItem a2 = ((i < num) ? a.Hotbar[i] : null); SavedItem b2 = ((i < num2) ? b.Hotbar[i] : null); if (!SameSavedItem(a2, b2)) { return false; } } int num4 = a.Extended?.Count ?? 0; int num5 = b.Extended?.Count ?? 0; if (num4 != num5) { return false; } for (int j = 0; j < num4; j++) { SavedItem savedItem = a.Extended[j]; SavedItem b3 = null; for (int k = 0; k < num5; k++) { SavedItem savedItem2 = b.Extended[k]; if (savedItem2 != null && savedItem2.GridX == savedItem.GridX && savedItem2.GridY == savedItem.GridY) { b3 = savedItem2; break; } } if (!SameSavedItem(savedItem, b3)) { return false; } } return true; } private static bool SameSavedItem(SavedItem a, SavedItem b) { bool flag = a == null || string.IsNullOrEmpty(a.SharedName); bool flag2 = b == null || string.IsNullOrEmpty(b.SharedName); if (flag && flag2) { return true; } if (flag || flag2) { return false; } if (a.SharedName == b.SharedName && a.Quality == b.Quality) { return a.Variant == b.Variant; } return false; } private static void ShowDeleteConfirm(int index) { //IL_0026: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Expected O, but got Unknown //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Expected O, but got Unknown CloseConfirmModal(); Transform transform = GUIManager.CustomGUIFront.transform; _confirmModal = GUIManager.Instance.CreateWoodpanel(transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 420f, 180f, false); _confirmModal.transform.SetAsLastSibling(); string name = _data.Slots[index].Name; GUIManager.Instance.CreateText("Delete '" + name + "'?", _confirmModal.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -42f), GUIManager.Instance.AveriaSerifBold, 20, GUIManager.Instance.ValheimOrange, true, Color.black, 380f, 32f, false); GUIManager.Instance.CreateText("This loadout will be removed.", _confirmModal.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -80f), GUIManager.Instance.AveriaSerifBold, 14, new Color(0.85f, 0.8f, 0.7f), true, Color.black, 380f, 24f, false); GameObject obj = GUIManager.Instance.CreateButton("Delete", _confirmModal.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(-75f, 36f), 130f, 40f); Text componentInChildren = obj.GetComponentInChildren<Text>(); if ((Object)(object)componentInChildren != (Object)null) { ((Graphic)componentInChildren).color = new Color(0.95f, 0.35f, 0.35f); } Button component = obj.GetComponent<Button>(); ColorBlock colors = ((Selectable)component).colors; ((ColorBlock)(ref colors)).highlightedColor = new Color(0.85f, 0.2f, 0.2f, 1f); ((ColorBlock)(ref colors)).pressedColor = new Color(0.65f, 0.12f, 0.12f, 1f); ((Selectable)component).colors = colors; int captured = index; ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { CloseConfirmModal(); DeleteSlot(captured); }); ButtonClickedEvent onClick = GUIManager.Instance.CreateButton("Cancel", _confirmModal.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(75f, 36f), 130f, 40f).GetComponent<Button>().onClick; object obj2 = <>O.<2>__CloseConfirmModal; if (obj2 == null) { UnityAction val = CloseConfirmModal; <>O.<2>__CloseConfirmModal = val; obj2 = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj2); } private static void CloseConfirmModal() { if ((Object)(object)_confirmModal != (Object)null) { Object.Destroy((Object)(object)_confirmModal); _confirmModal = null; } } private static void OnCompareClicked(int index) { Logger.LogInfo((object)$"[Armory] Click: Compare slot {index}"); CommitPendingEdit(); if (_compareSlot == index) { ToggleCompareOff(); return; } _compareSlot = index; BuildCompareWindow(); } private static void UpdateRowEditState(SlotRowRefs refs, int index) { bool flag = _editingSlot == index; if ((Object)(object)refs.NameLabelGo != (Object)null) { refs.NameLabelGo.SetActive(!flag); } if ((Object)(object)refs.NameInputGo != (Object)null) { refs.NameInputGo.SetActive(flag); } if (!flag && (Object)(object)refs.NameLabel != (Object)null) { refs.NameLabel.text = _data.Slots[index].Name; } } private static void OnNameClicked(int index) { Logger.LogInfo((object)$"[Armory] Click: Name slot {index} (currently editing={_editingSlot})"); if (_editingSlot == index) { return; } if (_editingSlot >= 0) { CommitPendingEdit(); } _editingSlot = index; if ((Object)(object)_rows[index].NameInput != (Object)null) { _rows[index].NameInput.text = _data.Slots[index].Name; } UpdateRowEditState(_rows[index], index); InputField nameInput = _rows[index].NameInput; if ((Object)(object)nameInput != (Object)null) { EventSystem current = EventSystem.current; if (current != null) { current.SetSelectedGameObject(((Component)nameInput).gameObject); } nameInput.ActivateInputField(); nameInput.caretPosition = nameInput.text.Length; } } private static void CommitPendingEdit() { if (_editingSlot >= 0) { int editingSlot = _editingSlot; string text = _rows[editingSlot].NameInput.text.Trim(); if (string.IsNullOrEmpty(text)) { text = $"Slot {editingSlot + 1}"; } _data.Slots[editingSlot].Name = text; _rack.SaveData(_data); _editingSlot = -1; UpdateRowEditState(_rows[editingSlot], editingSlot); RefreshRowVisual(editingSlot); } } private static void RefreshRowVisual(int index) { if (index >= 0 && index < _rows.Count) { SlotRowRefs slotRowRefs = _rows[index]; if ((Object)(object)slotRowRefs.NameLabel != (Object)null) { slotRowRefs.NameLabel.text = _data.Slots[index].Name; } if ((Object)(object)slotRowRefs.Summary != (Object)null) { slotRowRefs.Summary.text = BuildSummary(_data.Slots[index]); } RebuildIcons(slotRowRefs, _data.Slots[index]); UpdateRowEmptyState(slotRowRefs, _data.Slots[index]); } } private static void ToggleCompareOff() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) _compareSlot = -1; if ((Object)(object)_comparePanel != (Object)null) { RectTransform component = _comparePanel.GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { _savedComparePos = component.anchoredPosition; } Object.Destroy((Object)(object)_comparePanel); _comparePanel = null; } } private static void BuildCompareWindow() { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01da: 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_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Expected O, but got Unknown //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown if ((Object)(object)_comparePanel != (Object)null) { Object.Destroy((Object)(object)_comparePanel); _comparePanel = null; } if (_compareSlot < 0 || _compareSlot >= _data.Slots.Count) { return; } LoadoutSlot loadoutSlot = _data.Slots[_compareSlot]; Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Transform transform = GUIManager.CustomGUIFront.transform; Vector2 val = (Vector2)(((??)_savedComparePos) ?? new Vector2(300f, -610f)); _comparePanel = GUIManager.Instance.CreateWoodpanel(transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), val, 560f, 360f, true); GUIManager.Instance.CreateText("Compare: " + loadoutSlot.Name, _comparePanel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -28f), GUIManager.Instance.AveriaSerifBold, 20, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false); ButtonClickedEvent onClick = GUIManager.Instance.CreateButton("x", _comparePanel.transform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-32f, -28f), 36f, 36f).GetComponent<Button>().onClick; object obj = <>O.<3>__ToggleCompareOff; if (obj == null) { UnityAction val2 = ToggleCompareOff; <>O.<3>__ToggleCompareOff = val2; obj = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj); GameObject val3 = new GameObject("CompareGrid", new Type[1] { typeof(RectTransform) }); val3.transform.SetParent(_comparePanel.transform, false); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 1f); component.offsetMin = new Vector2(20f, 30f); component.offsetMax = new Vector2(-20f, -60f); VerticalLayoutGroup obj2 = val3.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 4f; ((LayoutGroup)obj2).padding = new RectOffset(0, 0, 0, 0); ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; AddCompareHeader(val3.transform); Inventory inventory = ((Humanoid)localPlayer).GetInventory(); LoadoutSlot loadoutSlot2 = LoadoutManager.CaptureCurrentEquipment(localPlayer); AddCompareRow(val3.transform, "Helmet", loadoutSlot2.Helmet, loadoutSlot.Helmet, inventory); AddCompareRow(val3.transform, "Chest", loadoutSlot2.Chest, loadoutSlot.Chest, inventory); AddCompareRow(val3.transform, "Legs", loadoutSlot2.Legs, loadoutSlot.Legs, inventory); AddCompareRow(val3.transform, "Cape", loadoutSlot2.Shoulder, loadoutSlot.Shoulder, inventory); AddCompareRow(val3.transform, "Utility", loadoutSlot2.Utility, loadoutSlot.Utility, inventory); AddCompareRow(val3.transform, "Weapon", loadoutSlot2.RightHand, loadoutSlot.RightHand, inventory); AddCompareRow(val3.transform, "Shield", loadoutSlot2.LeftHand, loadoutSlot.LeftHand, inventory); } } private static void AddCompareHeader(Transform parent) { //IL_0018: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Header", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 10f; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; val.AddComponent<LayoutElement>().preferredHeight = 22f; AddText(val.transform, "Slot", 14, 70f, 20f, GUIManager.Instance.ValheimOrange); AddText(val.transform, "Equipped", 14, 200f, 20f, GUIManager.Instance.ValheimOrange); AddText(val.transform, "Loadout", 14, 200f, 20f, GUIManager.Instance.ValheimOrange); } private static void AddCompareRow(Transform parent, string label, SavedItem current, SavedItem saved, Inventory inv) { //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) //IL_0030: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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) //IL_0186: 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_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Row_" + label, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 10f; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; val.AddComponent<LayoutElement>().preferredHeight = 20f; AddText(val.transform, label, 12, 70f, 18f, new Color(0.75f, 0.7f, 0.55f)); AddText(val.transform, (current != null) ? LoadoutManager.GetItemDisplayName(current) : "—", 12, 200f, 18f, Color.white); string text; Color color = default(Color); if (saved == null) { text = "—"; ((Color)(ref color))..ctor(0.45f, 0.45f, 0.45f); } else { string itemDisplayName = LoadoutManager.GetItemDisplayName(saved); bool num = current != null && current.SharedName == saved.SharedName && current.Quality == saved.Quality; bool flag = LoadoutManager.IsInInventory(inv, saved); color = (num ? new Color(0.4f, 0.8f, 0.4f) : (flag ? new Color(0.85f, 0.7f, 0.3f) : new Color(0.85f, 0.3f, 0.3f))); text = $"{itemDisplayName} (Q{saved.Quality})"; } AddText(val.transform, text, 12, 200f, 18f, color); } private static (GameObject Go, Text Txt) AddText(Transform parent, string text, int fontSize, float width, float height, Color color, bool leftAlign = false, bool richText = false) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0041: 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_0079: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("ArmoryText", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); Text val2 = val.AddComponent<Text>(); val2.text = text; val2.fontSize = fontSize; ((Graphic)val2).color = color; val2.supportRichText = richText; val2.alignment = (TextAnchor)(leftAlign ? 3 : 3); ((Graphic)val2).raycastTarget = false; val2.horizontalOverflow = (HorizontalWrapMode)1; val2.verticalOverflow = (VerticalWrapMode)1; try { GUIManager.Instance.ApplyTextStyle(val2, color, 16, true); } catch { } ((Graphic)val2).color = color; val2.fontSize = fontSize; if (width > 0f) { LayoutElement val3 = val.AddComponent<LayoutElement>(); val3.preferredWidth = width; if (height > 0f) { val3.preferredHeight = height; } } return (Go: val, Txt: val2); } private static void SetHeight(GameObject go, float height) { if (!((Object)(object)go == (Object)null)) { (go.GetComponent<LayoutElement>() ?? go.AddComponent<LayoutElement>()).preferredHeight = height; } } private static GameObject AddRowButton(Transform parent, string text, float width, UnityAction onClick) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) GameObject val = GUIManager.Instance.CreateButton(text, parent, Vector2.zero, Vector2.zero, Vector2.zero, width, 44f); ((UnityEvent)val.GetComponent<Button>().onClick).AddListener(onClick); LayoutElement obj = val.GetComponent<LayoutElement>() ?? val.AddComponent<LayoutElement>(); obj.preferredWidth = width; obj.preferredHeight = 44f; return val; } private static string BuildSummary(LoadoutSlot slot) { if (slot.IsEmpty()) { return "<color=#666666>empty</color>"; } Player localPlayer = Player.m_localPlayer; Inventory val = ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null); Inventory val2 = _rack?.GetStorageInventory(); List<string> list = new List<string>(8); Append(list, "Helm", slot.Helmet, val, val2); Append(list, "Chest", slot.Chest, val, val2); Append(list, "Legs", slot.Legs, val, val2); Append(list, "Cape", slot.Shoulder, val, val2); Append(list, "Wpn", slot.RightHand, val, val2); Append(list, "Shld", slot.LeftHand, val, val2); Append(list, "Util", slot.Utility, val, val2); if (slot.Hotbar != null) { List<string> list2 = new List<string>(8); for (int i = 0; i < slot.Hotbar.Length; i++) { SavedItem savedItem = slot.Hotbar[i]; if (savedItem != null && !string.IsNullOrEmpty(savedItem.SharedName)) { bool flag = LoadoutManager.IsItemAvailable(savedItem, val, val2); string text = $"{i + 1}={LoadoutManager.GetItemDisplayName(savedItem)}"; list2.Add(flag ? text : ("<color=#d8584a>" + text + "</color>")); } } if (list2.Count > 0) { list.Add("<color=#b8943a>Hotbar:</color>" + string.Join(" ", list2)); } } if (slot.Extended != null && slot.Extended.Count > 0) { List<string> list3 = new List<string>(slot.Extended.Count); foreach (SavedItem item in slot.Extended) { if (item != null && !string.IsNullOrEmpty(item.SharedName)) { bool flag2 = LoadoutManager.IsItemAvailable(item, val, val2); string itemDisplayName = LoadoutManager.GetItemDisplayName(item); list3.Add(flag2 ? itemDisplayName : ("<color=#d8584a>" + itemDisplayName + "</color>")); } } if (list3.Count > 0) { list.Add("<color=#b8943a>Extra:</color>" + string.Join(" ", list3)); } } return string.Join(" ", list); } private static void Append(List<string> parts, string label, SavedItem item, Inventory playerInv, Inventory rackInv) { if (item != null) { if (LoadoutManager.IsItemAvailable(item, playerInv, rackInv)) { parts.Add("<color=#b8943a>" + label + ":</color>" + LoadoutManager.GetItemDisplayName(item)); return; } parts.Add("<color=#d8584a>" + label + ":" + LoadoutManager.GetItemDisplayName(item) + "</color>"); } } } [Serializable] public class SavedItem { public string SharedName; public int Quality; public int Variant; public int Stack; public int GridX = -1; public int GridY = -1; } [Serializable] public class LoadoutSlot { public string Name = "New Loadout"; public SavedItem Helmet; public SavedItem Chest; public SavedItem Legs; public SavedItem Shoulder; public SavedItem Utility; public SavedItem RightHand; public SavedItem LeftHand; public SavedItem[] Hotbar = new SavedItem[8]; public List<SavedItem> Extended = new List<SavedItem>(); public bool IsEmpty() { if (Helmet == null && Chest == null && Legs == null && Shoulder == null && Utility == null && RightHand == null && LeftHand == null && (Hotbar == null || Hotbar.All((SavedItem h) => h == null || string.IsNullOrEmpty(h.SharedName)))) { if (Extended != null) { return Extended.Count == 0; } return true; } return false; } } [Serializable] public class ArmoryData { public List<LoadoutSlot> Slots = new List<LoadoutSlot>(); } internal static class ArmorySerializer { private const string SLOT_MARKER = "SLOT"; public static string Serialize(ArmoryData data) { StringBuilder stringBuilder = new StringBuilder(); if (data?.Slots == null) { return stringBuilder.ToString(); } foreach (LoadoutSlot slot in data.Slots) { stringBuilder.AppendLine("SLOT"); stringBuilder.Append("NAME=").AppendLine(Uri.EscapeDataString(slot.Name ?? "Loadout")); AppendItem(stringBuilder, "HELMET", slot.Helmet); AppendItem(stringBuilder, "CHEST", slot.Chest); AppendItem(stringBuilder, "LEGS", slot.Legs); AppendItem(stringBuilder, "SHOULDER", slot.Shoulder); AppendItem(stringBuilder, "UTILITY", slot.Utility); AppendItem(stringBuilder, "RIGHT", slot.RightHand); AppendItem(stringBuilder, "LEFT", slot.LeftHand); if (slot.Hotbar != null) { for (int i = 0; i < slot.Hotbar.Length; i++) { AppendItem(stringBuilder, "HOTBAR" + i, slot.Hotbar[i]); } } if (slot.Extended == null) { continue; } foreach (SavedItem item in slot.Extended) { AppendItem(stringBuilder, "EXT", item); } } return stringBuilder.ToString(); } private static void AppendItem(StringBuilder sb, string key, SavedItem item) { if (item != null && !string.IsNullOrEmpty(item.SharedName)) { sb.Append(key).Append('=').Append(item.SharedName) .Append('|') .Append(item.Quality) .Append('|') .Append(item.Variant) .Append('|') .Append(item.Stack); if (item.GridX >= 0 || item.GridY >= 0) { sb.Append('|').Append(item.GridX).Append('|') .Append(item.GridY); } sb.AppendLine(); } } public static ArmoryData Deserialize(string text) { ArmoryData armoryData = new ArmoryData(); if (string.IsNullOrEmpty(text)) { return armoryData; } LoadoutSlot loadoutSlot = null; string[] array = text.Split(new char[1] { '\n' }); for (int i = 0; i < array.Length; i++) { string text2 = array[i].TrimEnd(new char[1] { '\r' }); if (string.IsNullOrEmpty(text2)) { continue; } if (text2 == "SLOT") { loadoutSlot = new LoadoutSlot { Hotbar = new SavedItem[8], Extended = new List<SavedItem>() }; armoryData.Slots.Add(loadoutSlot); } else { if (loadoutSlot == null) { continue; } int num = text2.IndexOf('='); if (num < 0) { continue; } string text3 = text2.Substring(0, num); string text4 = text2.Substring(num + 1); if (text3 == "NAME") { loadoutSlot.Name = Uri.UnescapeDataString(text4); continue; } SavedItem savedItem = ParseItem(text4); if (savedItem == null) { continue; } switch (text3) { case "HELMET": loadoutSlot.Helmet = savedItem; continue; case "CHEST": loadoutSlot.Chest = savedItem; continue; case "LEGS": loadoutSlot.Legs = savedItem; continue; case "SHOULDER": loadoutSlot.Shoulder = savedItem; continue; case "UTILITY": loadoutSlot.Utility = savedItem; continue; case "RIGHT": loadoutSlot.RightHand = savedItem; continue; case "LEFT": loadoutSlot.LeftHand = savedItem; continue; case "EXT": loadoutSlot.Extended.Add(savedItem); continue; } if (text3.StartsWith("HOTBAR") && int.TryParse(text3.Substring(6), out var result) && result >= 0 && result < loadoutSlot.Hotbar.Length) { loadoutSlot.Hotbar[result] = savedItem; } } } return armoryData; } private static SavedItem ParseItem(string val) { string[] array = val.Split(new char[1] { '|' }); if (array.Length < 1 || string.IsNullOrEmpty(array[0])) { return null; } SavedItem savedItem = new SavedItem { SharedName = array[0] }; if (array.Length > 1) { int.TryParse(array[1], out savedItem.Quality); } if (array.Length > 2) { int.TryParse(array[2], out savedItem.Variant); } if (array.Length > 3) { int.TryParse(array[3], out savedItem.Stack); } if (array.Length > 4) { int.TryParse(array[4], out savedItem.GridX); } if (array.Length > 5) { int.TryParse(array[5], out savedItem.GridY); } return savedItem; } } internal static class LoadoutManager { public static readonly FieldRef<Humanoid, ItemData> F_Helmet = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_helmetItem"); public static readonly FieldRef<Humanoid, ItemData> F_Chest = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_chestItem"); public static readonly FieldRef<Humanoid, ItemData> F_Leg = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_legItem"); public static readonly FieldRef<Humanoid, ItemData> F_Shoulder = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_shoulderItem"); public static readonly FieldRef<Humanoid, ItemData> F_Utility = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_utilityItem"); public static readonly FieldRef<Humanoid, ItemData> F_Right = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_rightItem"); public static readonly FieldRef<Humanoid, ItemData> F_Left = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_leftItem"); private static readonly MethodInfo M_InvChanged = AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null); private static readonly object[] M_InvChangedArgs = BuildInvChangedArgs(); private static readonly FieldRef<Inventory, List<ItemData>> F_InvList = AccessTools.FieldRefAccess<Inventory, List<ItemData>>("m_inventory"); private static readonly FieldRef<ObjectDB, List<GameObject>> F_ObjectDBItems = AccessTools.FieldRefAccess<ObjectDB, List<GameObject>>("m_items"); private static Dictionary<string, Sprite> _iconBySharedName; public static bool IsLoadoutActive(LoadoutSlot slot, Player player) { if (slot == null || (Object)(object)player == (Object)null || slot.IsEmpty()) { return false; } if (!ItemMatches(slot.Helmet, F_Helmet.Invoke((Humanoid)(object)player))) { return false; } if (!ItemMatches(slot.Chest, F_Chest.Invoke((Humanoid)(object)player))) { return false; } if (!ItemMatches(slot.Legs, F_Leg.Invoke((Humanoid)(object)player))) { return false; } if (!ItemMatches(slot.Shoulder, F_Shoulder.Invoke((Humanoid)(object)player))) { return false; } if (!ItemMatches(slot.Utility, F_Utility.Invoke((Humanoid)(object)player))) { return false; } if (!ItemMatches(slot.RightHand, F_Right.Invoke((Humanoid)(object)player))) { return false; } if (!ItemMatches(slot.LeftHand, F_Left.Invoke((Humanoid)(object)player))) { return false; } Inventory inventory = ((Humanoid)player).GetInventory(); if (slot.Hotbar != null) { for (int i = 0; i < 8 && i < slot.Hotbar.Length; i++) { SavedItem savedItem = slot.Hotbar[i]; if (savedItem != null && !string.IsNullOrEmpty(savedItem.SharedName)) { ItemData equipped = ((inventory != null) ? inventory.GetItemAt(i, 0) : null); if (!ItemMatches(savedItem, equipped)) { return false; } } } } if (slot.Extended != null && inventory != null) { foreach (SavedItem item in slot.Extended) { if (item != null && !string.IsNullOrEmpty(item.SharedName) && item.GridX >= 0 && item.GridY >= 0) { ItemData itemAt = inventory.GetItemA