using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("TwoRelics")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TwoRelics")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("880eb189-aa99-447c-aed4-d980ee9251c9")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("com.mozam.tworelics", "Two Relics Mod", "1.0.0")]
public class TwoRelicsPlugin : BaseUnityPlugin
{
public static Dictionary<int, string> secondRelicDict = new Dictionary<int, string>();
private Harmony harmony;
private void Awake()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
harmony = new Harmony("com.mozam.tworelics");
harmony.PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)"Two Relics Mod loaded - patches applied.");
}
}
[HarmonyPatch(typeof(RelicChestUI), "Update")]
public static class RelicChestUI_Update_SecondRelicKey_Patch
{
private static readonly FieldInfo currentPlayerField = typeof(RelicChestUI).GetField("currentPlayer", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo currentFocusField = typeof(RelicChestUI).GetField("currentFocus", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo currentSelectionListField = typeof(RelicChestUI).GetField("currentSelectionList", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo currentStartIndexField = typeof(RelicChestUI).GetField("currentStartIndex", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo currentSelectionIndexField = typeof(RelicChestUI).GetField("currentSelectionIndex", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo currentIDField = typeof(RelicChestUI).GetField("currentID", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo activationPositionField = typeof(RelicChestUI).GetField("activationPosition", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo maxDistanceField = typeof(RelicChestUI).GetField("maxDistance", BindingFlags.Instance | BindingFlags.NonPublic);
private static void Postfix(RelicChestUI __instance)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Invalid comparison between Unknown and I4
if (!__instance.isActive || GameUI.pauseMenu.paused)
{
return;
}
Player val = (Player)currentPlayerField.GetValue(__instance);
if ((Object)(object)val == (Object)null)
{
return;
}
Vector2 val2 = (Vector2)activationPositionField.GetValue(__instance);
float num = (float)maxDistanceField.GetValue(__instance);
if (Vector2.Distance(Vector2.op_Implicit(((Component)val).transform.position), val2) > num || PlayerUIBase.GetLock("RelicChestUI" + val.playerID))
{
return;
}
RCFocus val3 = (RCFocus)currentFocusField.GetValue(__instance);
if ((int)val3 != 1 || !Input.GetKeyDown((KeyCode)50))
{
return;
}
List<string> list = (List<string>)currentSelectionListField.GetValue(__instance);
int num2 = (int)currentStartIndexField.GetValue(__instance);
int num3 = (int)currentSelectionIndexField.GetValue(__instance);
string text = list[num2 + num3];
if (!Item.IsUnlocked(text, false))
{
SoundManager.PlayAudio("MenuError", 1f, false, -1f, -1f);
return;
}
int playerID = val.playerID;
if (TwoRelicsPlugin.secondRelicDict.TryGetValue(playerID, out var value) && !string.IsNullOrEmpty(value))
{
((Entity)val).inventory.RemoveItem(value, false, false);
}
TwoRelicsPlugin.secondRelicDict[playerID] = text;
TwoRelicsSaveData.Save();
((Entity)val).inventory.AddItem(text, false, false);
GameDataManager.Save(true, true);
((Entity)val).health.RestoreHealth(9999, false, false, true, true);
currentIDField.SetValue(__instance, text);
SoundManager.PlayAudio("WoodPickUp", 1f, false, -1f, -1f);
__instance.SetFocus((RCFocus)0, false, false);
}
}
internal class SecondRelicUIRefs
{
public Image icon;
public Text text;
}
internal static class SecondRelicUI
{
private static readonly Dictionary<RelicChestUI, SecondRelicUIRefs> cache = new Dictionary<RelicChestUI, SecondRelicUIRefs>();
private static readonly FieldInfo rcRefField = typeof(RelicChestUI).GetField("rcRef", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly Type rcObjRefType = typeof(RelicChestUI).GetNestedType("RelicChestObjRef", BindingFlags.NonPublic);
private static readonly FieldInfo typePageTransField = rcObjRefType?.GetField("typePageTrans");
private static readonly Vector2 secondRelicOffset = new Vector2(0f, -40f);
public static SecondRelicUIRefs GetOrCreate(RelicChestUI instance)
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
if (cache.TryGetValue(instance, out var value))
{
return value;
}
object value2 = rcRefField.GetValue(instance);
Transform val = (Transform)typePageTransField.GetValue(value2);
Transform val2 = val.Find("CurrentRelic");
GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, val);
((Object)val3).name = "CurrentRelic (Second)";
RectTransform component = val3.GetComponent<RectTransform>();
if ((Object)(object)component != (Object)null)
{
component.anchoredPosition += secondRelicOffset;
}
DisableChildIfPresent(val3.transform, "ConfirmIcon");
DisableChildIfPresent(val3.transform, "CancelIcon");
DisableChildIfPresent(val3.transform, "ConfirmText");
DisableChildIfPresent(val3.transform, "CancelText");
Transform val4 = val3.transform.Find("Icon");
Transform val5 = val3.transform.Find("Text");
SecondRelicUIRefs secondRelicUIRefs = new SecondRelicUIRefs
{
icon = ((Component)val4).GetComponent<Image>(),
text = ((Component)val5).GetComponent<Text>()
};
cache.Add(instance, secondRelicUIRefs);
return secondRelicUIRefs;
}
private static void DisableChildIfPresent(Transform parent, string childName)
{
Transform val = parent.Find(childName);
if ((Object)(object)val != (Object)null)
{
((Component)val).gameObject.SetActive(false);
}
}
}
internal static class SlotHintUI
{
private static readonly Dictionary<RelicChestUI, bool> created = new Dictionary<RelicChestUI, bool>();
private static readonly FieldInfo rcRefField = typeof(RelicChestUI).GetField("rcRef", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly Type rcObjRefType = typeof(RelicChestUI).GetNestedType("RelicChestObjRef", BindingFlags.NonPublic);
private static readonly FieldInfo selectPageTransField = rcObjRefType?.GetField("selectPageTrans");
private static readonly Vector2 hintOffset = new Vector2(0f, -25f);
public static void EnsureCreated(RelicChestUI instance)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
if (!created.ContainsKey(instance))
{
object value = rcRefField.GetValue(instance);
Transform val = (Transform)selectPageTransField.GetValue(value);
Transform val2 = val.Find("Info/BGImage/ConfirmText");
GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, val2.parent);
((Object)val3).name = "SlotTwoHintText";
RectTransform component = val3.GetComponent<RectTransform>();
if ((Object)(object)component != (Object)null)
{
component.anchoredPosition += hintOffset;
}
Text component2 = val3.GetComponent<Text>();
if ((Object)(object)component2 != (Object)null)
{
component2.text = "2: Equip Slot 2";
}
created[instance] = true;
}
}
}
[HarmonyPatch(typeof(RelicChestUI), "LoadSelectionPage")]
public static class RelicChestUI_LoadSelectionPage_SlotHint_Patch
{
private static void Postfix(RelicChestUI __instance)
{
SlotHintUI.EnsureCreated(__instance);
}
}
[HarmonyPatch(typeof(RelicChestUI), "LoadTypePage")]
public static class RelicChestUI_LoadTypePage_SecondRelicDisplay_Patch
{
private static readonly FieldInfo currentPlayerField = typeof(RelicChestUI).GetField("currentPlayer", BindingFlags.Instance | BindingFlags.NonPublic);
private static void Postfix(RelicChestUI __instance)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Expected O, but got Unknown
SecondRelicUIRefs orCreate = SecondRelicUI.GetOrCreate(__instance);
if (orCreate == null || (Object)(object)orCreate.icon == (Object)null || (Object)(object)orCreate.text == (Object)null)
{
return;
}
Player val = (Player)currentPlayerField.GetValue(__instance);
if (!((Object)(object)val == (Object)null))
{
TwoRelicsPlugin.secondRelicDict.TryGetValue(val.playerID, out var value);
if (string.IsNullOrEmpty(value))
{
((Behaviour)orCreate.icon).enabled = false;
orCreate.text.text = string.Empty;
}
else
{
((Behaviour)orCreate.icon).enabled = true;
orCreate.icon.sprite = IconManager.GetItemIcon(value);
orCreate.text.text = TextManager.GetItemName(value);
}
}
}
}
[HarmonyPatch(typeof(Player), "Start")]
public static class Player_Start_RestoreSecondRelic_Patch
{
private static void Postfix(Player __instance)
{
if (!Globals.IsMuseum && !Globals.IsPvPScene && TwoRelicsPlugin.secondRelicDict.TryGetValue(__instance.playerID, out var value) && !string.IsNullOrEmpty(value))
{
((Entity)__instance).inventory.AddItem(value, false, false);
}
}
}
[HarmonyPatch(typeof(GameDataManager), "LoadInitial")]
public static class GameDataManager_LoadInitial_Patch
{
private static void Postfix()
{
TwoRelicsSaveData.Load();
}
}
[HarmonyPatch(typeof(GameDataManager), "ResetAllData")]
public static class GameDataManager_ResetAllData_Patch
{
private static void Postfix()
{
TwoRelicsSaveData.DeleteAll();
}
}
internal static class TwoRelicsSaveData
{
private const string fileName = "TwoRelicsData.txt";
private static string FilePath => Application.persistentDataPath + "/" + GameDataManager.steamIDStr + "TwoRelicsData.txt";
public static void Save()
{
try
{
List<string> list = new List<string>();
foreach (KeyValuePair<int, string> item in TwoRelicsPlugin.secondRelicDict)
{
if (!string.IsNullOrEmpty(item.Value))
{
list.Add(item.Key + "|" + item.Value);
}
}
File.WriteAllLines(FilePath, list.ToArray());
}
catch (Exception ex)
{
Debug.LogWarning((object)("[TwoRelics] Failed to save second relic data: " + ex));
}
}
public static void Load()
{
try
{
TwoRelicsPlugin.secondRelicDict.Clear();
if (!File.Exists(FilePath))
{
return;
}
string[] array = File.ReadAllLines(FilePath);
foreach (string text in array)
{
string[] array2 = text.Split(new char[1] { '|' });
if (array2.Length == 2 && int.TryParse(array2[0], out var result))
{
TwoRelicsPlugin.secondRelicDict[result] = array2[1];
}
}
}
catch (Exception ex)
{
Debug.LogWarning((object)("[TwoRelics] Failed to load second relic data: " + ex));
}
}
public static void DeleteAll()
{
try
{
TwoRelicsPlugin.secondRelicDict.Clear();
if (File.Exists(FilePath))
{
File.Delete(FilePath);
}
}
catch (Exception ex)
{
Debug.LogWarning((object)("[TwoRelics] Failed to delete second relic data: " + ex));
}
}
}