using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using GlassSol.Patches;
using HarmonyLib;
using I2.Loc;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using _3_Script.UI.SaveUI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("GlassSol")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("GlassSol")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("35405476-8ed7-4539-a7d7-6d6506f009e5")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace GlassSol
{
internal static class Difficulty
{
public const int GlassSol = 2;
public const int TrueGlassSol = 3;
public static int Current()
{
PlayerGamePlayData instance = PlayerGamePlayData.Instance;
if ((Object)(object)instance == (Object)null || (Object)(object)instance.gameMode == (Object)null)
{
return -1;
}
return ((AbstractScriptableData<FlagFieldInt, int>)(object)instance.gameMode).CurrentValue;
}
public static bool IsTrueGlassSol()
{
return Current() == 3;
}
public static bool IsOneShot()
{
int num = Current();
if (num != 2)
{
return num == 3;
}
return true;
}
public static string Phrase(string russian, string english)
{
string currentLanguageCode = LocalizationManager.CurrentLanguageCode;
if (!string.IsNullOrEmpty(currentLanguageCode) && currentLanguageCode.StartsWith("ru", StringComparison.OrdinalIgnoreCase))
{
return russian;
}
string currentLanguage = LocalizationManager.CurrentLanguage;
if (currentLanguage == "Russian" || currentLanguage == "Русский")
{
return russian;
}
return english;
}
}
[BepInPlugin("flyingRozenbaum.GlassSol", "GlassSol", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
private const string ModGuid = "flyingRozenbaum.GlassSol";
internal static ManualLogSource Log;
private void Awake()
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected O, but got Unknown
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Expected O, but got Unknown
//IL_0077: Expected O, but got Unknown
Log = Logger.CreateLogSource("flyingRozenbaum.GlassSol");
Log.LogInfo((object)"Starting Glass Sol");
Harmony val = new Harmony("flyingRozenbaum.GlassSol");
Patch(val, typeof(PlayerHealthPatch));
Patch(val, typeof(ModeMenuPatch));
Patch(val, typeof(NewGameModeSavePatch));
Patch(val, typeof(SaveModeLabelPatch));
Patch(val, typeof(GameplaySettingPatch));
Log.LogInfo((object)"Finished loading Glass Sol");
}
private static void Patch(Harmony harmony, Type type)
{
try
{
harmony.PatchAll(type);
Log.LogInfo((object)("Patched " + type.Name));
}
catch (Exception ex)
{
Log.LogError((object)("Patch failed for " + type.Name + ": " + ex));
}
}
}
}
namespace GlassSol.Patches
{
internal static class InternalKillSetting
{
public static bool InMemory()
{
PlayerGamePlayData instance = PlayerGamePlayData.Instance;
if ((Object)(object)instance != (Object)null && (Object)(object)instance.memoryMode != (Object)null)
{
return instance.memoryMode.CurrentValue;
}
return false;
}
public static bool Shown()
{
if (!Difficulty.IsOneShot())
{
return InMemory();
}
return true;
}
public static bool Kills()
{
int num = ((!InMemory() && Difficulty.Current() == 3) ? 1 : 0);
return PlayerPrefs.GetInt(Key(), num) == 1;
}
public static void Set(bool kills)
{
PlayerPrefs.SetInt(Key(), kills ? 1 : 0);
}
private static string Key()
{
if (InMemory())
{
return "GlassSol.InternalKills.memory";
}
return "GlassSol.InternalKills." + Difficulty.Current();
}
}
internal static class NohitSetting
{
public static bool Enabled()
{
return PlayerPrefs.GetInt("GlassSol.Nohit", 0) == 1;
}
public static void Set(bool enabled)
{
PlayerPrefs.SetInt("GlassSol.Nohit", enabled ? 1 : 0);
}
public static bool Active()
{
if (Enabled())
{
return InternalKillSetting.InMemory();
}
return false;
}
}
internal static class GameplaySettingPatch
{
private const string OptionName = "InternalKillOption";
private const string NohitOptionName = "NohitOption";
internal const string TitleRu = "Внутренний урон убивает";
internal const string TitleEn = "Internal damage kills";
internal const string NohitTitleRu = "Включить ноухит";
internal const string NohitTitleEn = "Enable Nohit";
[HarmonyPostfix]
[HarmonyPatch(typeof(GamePreferenceManager), "Start")]
private static void AddOption(GamePreferenceManager __instance)
{
((MonoBehaviour)__instance).StartCoroutine(Watch());
}
private static IEnumerator Watch()
{
while (true)
{
Transform[] array = Resources.FindObjectsOfTypeAll<Transform>();
foreach (Transform val in array)
{
if ((Object)(object)val == (Object)null || ((Object)val).name != "Show HUD")
{
continue;
}
Scene scene = ((Component)val).gameObject.scene;
if (((Scene)(ref scene)).IsValid() && !((Object)(object)val.parent == (Object)null) && !(((Object)val.parent).name != "Layout"))
{
Transform val2 = val.parent.Find("InternalKillOption");
if ((Object)(object)val2 == (Object)null)
{
AddRow(val, nohit: false);
}
else
{
((Component)val2).gameObject.SetActive(InternalKillSetting.Shown());
}
Transform val3 = val.parent.Find("NohitOption");
if ((Object)(object)val3 == (Object)null)
{
AddRow(val, nohit: true);
}
else
{
((Component)val3).gameObject.SetActive(InternalKillSetting.InMemory());
}
}
}
yield return (object)new WaitForSecondsRealtime(0.5f);
}
}
private static void AddRow(Transform row, bool nohit)
{
bool activeSelf = ((Component)row).gameObject.activeSelf;
((Component)row).gameObject.SetActive(false);
Transform transform = Object.Instantiate<GameObject>(((Component)row).gameObject, row.parent).transform;
((Component)row).gameObject.SetActive(activeSelf);
((Object)transform).name = (nohit ? "NohitOption" : "InternalKillOption");
transform.SetSiblingIndex(row.GetSiblingIndex() + ((!nohit) ? 1 : 2));
Component val = null;
MonoBehaviour[] componentsInChildren = ((Component)transform).GetComponentsInChildren<MonoBehaviour>(true);
foreach (MonoBehaviour val2 in componentsInChildren)
{
if ((Object)(object)val2 == (Object)null)
{
continue;
}
Type type = ((object)val2).GetType();
while (type != null)
{
if (type.Name == "MultipleOptionSelector" || type.Name.StartsWith("ListRotateSelector"))
{
val = (Component)(object)val2;
break;
}
type = type.BaseType;
}
if ((Object)(object)val != (Object)null)
{
break;
}
}
if ((Object)(object)val == (Object)null)
{
Plugin.Log.LogError((object)"Show HUD has no selector");
return;
}
object obj = null;
Type type2 = ((object)val).GetType();
while (type2 != null)
{
FieldInfo field = type2.GetField("entry", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (!(field == null))
{
obj = field.GetValue(val);
break;
}
type2 = type2.BaseType;
}
obj.GetType().GetField("flagBase").SetValue(obj, null);
((Component)transform).gameObject.SetActive(true);
TMP_Text val3 = null;
Transform[] componentsInChildren2 = ((Component)transform).GetComponentsInChildren<Transform>(true);
foreach (Transform val4 in componentsInChildren2)
{
if (!(((Object)val4).name != "Label"))
{
val3 = ((Component)val4).GetComponent<TMP_Text>() ?? ((Component)val4).GetComponentInChildren<TMP_Text>(true);
break;
}
}
if ((Object)(object)val3 != (Object)null)
{
DestroyLocalization(((Component)val3).gameObject);
val3.text = (nohit ? Difficulty.Phrase("Включить ноухит", "Enable Nohit") : Difficulty.Phrase("Внутренний урон убивает", "Internal damage kills"));
}
UIControlButton obj2 = ((Component)transform).GetComponent<UIControlButton>() ?? ((Component)transform).GetComponentInChildren<UIControlButton>(true);
RetargetLocal(obj2, transform);
obj2.RefreshState();
object value = ((object)val).GetType().GetField("list", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(val);
PropertyInfo? property = value.GetType().GetProperty("Count");
PropertyInfo property2 = value.GetType().GetProperty("Item");
int yesIndex = 1;
int num = (int)property.GetValue(value, null);
for (int j = 0; j < num; j++)
{
string text = property2.GetValue(value, new object[1] { j })?.ToString();
if (text == "Да" || text == "Yes")
{
yesIndex = j;
break;
}
}
if (nohit)
{
((Component)transform).gameObject.AddComponent<NohitOption>().Setup(val, obj, yesIndex, val3);
}
else
{
((Component)transform).gameObject.AddComponent<InternalKillOption>().Setup(val, obj, yesIndex, val3);
}
SelectableNavigationProvider componentInParent = ((Component)transform).GetComponentInParent<SelectableNavigationProvider>();
if ((Object)(object)componentInParent != (Object)null)
{
componentInParent.AutoNavigateBindForAll();
}
Plugin.Log.LogInfo((object)(nohit ? "Added nohit setting" : "Added internal damage setting"));
}
private static void RetargetLocal(UIControlButton control, Transform root)
{
FieldInfo[] fields = typeof(UIControlButton).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (fieldInfo.FieldType == typeof(RectTransform) || !typeof(Component).IsAssignableFrom(fieldInfo.FieldType) || fieldInfo.Name == "belongGroup" || fieldInfo.Name == "provider" || fieldInfo.Name == "instructionPanelProvider")
{
continue;
}
object? value = fieldInfo.GetValue(control);
Component val = (Component)((value is Component) ? value : null);
if (!((Object)(object)val != (Object)null) || (!((Object)(object)val.transform == (Object)(object)root) && !val.transform.IsChildOf(root)))
{
Component val2 = ((Component)control).GetComponent(fieldInfo.FieldType) ?? ((Component)control).GetComponentInChildren(fieldInfo.FieldType, true);
if ((Object)(object)val2 != (Object)null)
{
fieldInfo.SetValue(control, val2);
}
}
}
}
internal static void DestroyLocalization(GameObject root)
{
MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true);
foreach (MonoBehaviour val in componentsInChildren)
{
if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == "Localize")
{
Object.DestroyImmediate((Object)(object)val);
}
}
}
}
internal class InternalKillOption : MonoBehaviour
{
private Component selector;
private object entry;
private int yesIndex;
private TMP_Text title;
public void Setup(Component selector, object entry, int yesIndex, TMP_Text title)
{
this.selector = selector;
this.entry = entry;
this.yesIndex = yesIndex;
this.title = title;
}
private void OnEnable()
{
if (!InternalKillSetting.Shown())
{
((Component)this).gameObject.SetActive(false);
return;
}
ApplyTitle();
Value(InternalKillSetting.Kills() ? yesIndex : ((yesIndex == 0) ? 1 : 0));
((object)selector).GetType().GetMethod("UpdateView").Invoke(selector, null);
ApplyTitle();
}
private void LateUpdate()
{
if (InternalKillSetting.Shown())
{
bool flag = Value() == yesIndex;
if (flag != InternalKillSetting.Kills())
{
InternalKillSetting.Set(flag);
}
ApplyTitle();
}
}
private void ApplyTitle()
{
if (!((Object)(object)title == (Object)null))
{
GameplaySettingPatch.DestroyLocalization(((Component)title).gameObject);
title.text = Difficulty.Phrase("Внутренний урон убивает", "Internal damage kills");
}
}
private int Value(int? next = null)
{
object obj = entry.GetType().GetMethod("get_field").Invoke(entry, null);
if (!next.HasValue)
{
return (int)obj.GetType().GetMethod("get_CurrentValue").Invoke(obj, null);
}
obj.GetType().GetMethod("set_CurrentValue").Invoke(obj, new object[1] { next.Value });
return next.Value;
}
}
internal class NohitOption : MonoBehaviour
{
private Component selector;
private object entry;
private int yesIndex;
private TMP_Text title;
public void Setup(Component selector, object entry, int yesIndex, TMP_Text title)
{
this.selector = selector;
this.entry = entry;
this.yesIndex = yesIndex;
this.title = title;
}
private void OnEnable()
{
if (!InternalKillSetting.InMemory())
{
((Component)this).gameObject.SetActive(false);
return;
}
ApplyTitle();
Value(NohitSetting.Enabled() ? yesIndex : ((yesIndex == 0) ? 1 : 0));
((object)selector).GetType().GetMethod("UpdateView").Invoke(selector, null);
ApplyTitle();
}
private void LateUpdate()
{
bool flag = Value() == yesIndex;
if (flag != NohitSetting.Enabled())
{
NohitSetting.Set(flag);
}
ApplyTitle();
}
private void ApplyTitle()
{
if (!((Object)(object)title == (Object)null))
{
GameplaySettingPatch.DestroyLocalization(((Component)title).gameObject);
title.text = Difficulty.Phrase("Включить ноухит", "Enable Nohit");
}
}
private int Value(int? next = null)
{
object obj = entry.GetType().GetMethod("get_field").Invoke(entry, null);
if (!next.HasValue)
{
return (int)obj.GetType().GetMethod("get_CurrentValue").Invoke(obj, null);
}
obj.GetType().GetMethod("set_CurrentValue").Invoke(obj, new object[1] { next.Value });
return next.Value;
}
}
internal static class ModeMenuPatch
{
internal const string GlassSolName = "Стеклянный Сол";
internal const string GlassSolNameEn = "Glass Sol";
internal const string TrueGlassSolName = "Истинный Стеклянный Сол";
internal const string TrueGlassSolNameEn = "True Glass Sol";
private const string GlassSolDescription = "Повышенная сложность Nine Sols.\nПрямой урон вас мгновенно убивает. Ваше сохранение при этом остается целым.";
private const string GlassSolDescriptionEn = "An increased difficulty for Nine Sols.\nDirect damage kills you instantly. Your save remains intact.";
private const string TrueGlassSolDescription = "Наивысшая сложность Nine Sols.\nЛюбой полученный вами урон фатальный, второго шанса не дается.";
private const string TrueGlassSolDescriptionEn = "The highest difficulty for Nine Sols.\nAny damage you take is fatal. There is no second chance.";
private static Image glassArt;
private static Image trueArt;
private static int shownMode = 1;
private static UIControlButton soundButton;
[HarmonyPostfix]
[HarmonyPatch(typeof(StartMenuLogic), "Start")]
private static void AddDifficultyButtons(StartMenuLogic __instance)
{
((MonoBehaviour)__instance).StartCoroutine(AddWhenReady(__instance));
}
[HarmonyPostfix]
[HarmonyPatch(typeof(UIControlButton), "OnSelect")]
private static void ShowPlaceholder(UIControlButton __instance)
{
Transform val = OptionsOf(((Component)__instance).transform);
if (!((Object)(object)val == (Object)null))
{
ReleaseOthers(val, __instance);
int num = ModeOf(((Component)__instance).transform, val);
if ((Object)(object)glassArt != (Object)null && num >= 0)
{
shownMode = num;
ApplyArt();
}
Transform val2 = val.Find("GlassSolMode");
if ((Object)(object)val2 != (Object)null)
{
((Component)val2.Find("ActionText")).GetComponent<TMP_Text>().text = Difficulty.Phrase("Стеклянный Сол", "Glass Sol");
}
Transform val3 = val.Find("TrueGlassSolMode");
if ((Object)(object)val3 != (Object)null)
{
((Component)val3.Find("ActionText")).GetComponent<TMP_Text>().text = Difficulty.Phrase("Истинный Стеклянный Сол", "True Glass Sol");
}
if (IsCustom(((Component)__instance).transform))
{
PlaySelectSound();
Transform obj = val.Find("Selected Description");
DestroyLocalization(((Component)obj).gameObject);
((Component)obj).GetComponentInChildren<TMP_Text>(true).text = (IsTrue(((Component)__instance).transform) ? Difficulty.Phrase("Наивысшая сложность Nine Sols.\nЛюбой полученный вами урон фатальный, второго шанса не дается.", "The highest difficulty for Nine Sols.\nAny damage you take is fatal. There is no second chance.") : Difficulty.Phrase("Повышенная сложность Nine Sols.\nПрямой урон вас мгновенно убивает. Ваше сохранение при этом остается целым.", "An increased difficulty for Nine Sols.\nDirect damage kills you instantly. Your save remains intact."));
}
}
}
private static int ModeOf(Transform transform, Transform options)
{
if (IsTrue(transform))
{
return 3;
}
if (IsCustom(transform) && !IsTrue(transform))
{
return 2;
}
Transform val = transform;
while ((Object)(object)val.parent != (Object)null && (Object)(object)val.parent != (Object)(object)options)
{
val = val.parent;
}
int num = 0;
for (int i = 0; i < options.childCount; i++)
{
if (((Object)options.GetChild(i)).name.Contains("Start Game"))
{
if ((Object)(object)options.GetChild(i) == (Object)(object)val)
{
return num;
}
num++;
}
}
return -1;
}
internal static void ApplyArt()
{
if (!((Object)(object)glassArt == (Object)null))
{
((Component)glassArt).gameObject.SetActive(shownMode == 2);
((Component)trueArt).gameObject.SetActive(shownMode == 3);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(UIControlButton), "OnDeselect")]
private static void Release(UIControlButton __instance)
{
if (IsCustom(((Component)__instance).transform))
{
((MonoBehaviour)__instance).StartCoroutine(ClearWhenLeft(__instance));
}
}
private static IEnumerator ClearWhenLeft(UIControlButton button)
{
yield return null;
button.RefreshState();
}
private static IEnumerator AddWhenReady(StartMenuLogic menu)
{
for (int i = 0; i < 40; i++)
{
if (TryAdd(menu))
{
yield return null;
Rebind(FindOptionsRoot());
break;
}
yield return (object)new WaitForSecondsRealtime(0.25f);
}
}
private static bool TryAdd(StartMenuLogic menu)
{
Transform val = FindOptionsRoot();
if ((Object)(object)val == (Object)null)
{
return false;
}
if ((Object)(object)val.Find("TrueGlassSolMode") != (Object)null)
{
return true;
}
Transform val2 = FindChild(val, "Start Game");
soundButton = ((Component)val2).GetComponent<UIControlButton>() ?? ((Component)val2).GetComponentInChildren<UIControlButton>(true);
CreateArts(val);
Transform child = val.GetChild(val2.GetSiblingIndex() + 1);
TryAddMode(menu, val, val2, child, 2, "GlassSolMode", Difficulty.Phrase("Стеклянный Сол", "Glass Sol"));
TryAddMode(menu, val, val2, child, 3, "TrueGlassSolMode", Difficulty.Phrase("Истинный Стеклянный Сол", "True Glass Sol"));
Rebind(val);
return (Object)(object)val.Find("TrueGlassSolMode") != (Object)null;
}
private static void Rebind(Transform root)
{
SelectableNavigationProvider val = ((Component)root).GetComponent<SelectableNavigationProvider>();
if ((Object)(object)val == (Object)null)
{
val = ((Component)root).GetComponentInParent<SelectableNavigationProvider>();
}
if ((Object)(object)val != (Object)null)
{
val.AutoNavigateBindForAll();
}
}
private static void TryAddMode(StartMenuLogic menu, Transform root, Transform template, Transform padding, int mode, string objectName, string title)
{
try
{
AddMode(menu, root, template, padding, mode, objectName, title);
}
catch (Exception ex)
{
Plugin.Log.LogError((object)(objectName + ": " + ex));
}
}
private static void AddMode(StartMenuLogic menu, Transform root, Transform template, Transform padding, int mode, string objectName, string title)
{
if (!((Object)(object)root.Find(objectName) != (Object)null))
{
int num = InsertIndex(root);
bool activeSelf = ((Component)template).gameObject.activeSelf;
((Component)template).gameObject.SetActive(false);
Transform transform = Object.Instantiate<GameObject>(((Component)template).gameObject, root).transform;
((Component)template).gameObject.SetActive(activeSelf);
transform.SetParent(root, false);
((Object)transform).name = objectName;
transform.SetSiblingIndex(num);
DetachStandardMode(((Component)transform).gameObject);
PointArt(transform, (mode == 3) ? trueArt : glassArt);
Transform transform2 = Object.Instantiate<GameObject>(((Component)padding).gameObject, root).transform;
transform2.SetParent(root, false);
transform2.SetSiblingIndex(num + 1);
((Component)transform).gameObject.SetActive(true);
DestroyLocalization(((Component)transform).gameObject);
((Component)transform.Find("ActionText")).GetComponent<TMP_Text>().text = title;
UIControlButton val = ((Component)transform).GetComponent<UIControlButton>();
if ((Object)(object)val == (Object)null)
{
val = ((Component)transform).GetComponentInChildren<UIControlButton>(true);
}
RetargetLocal(val, transform);
val.RefreshState();
BindDirectStart(menu, val, mode);
}
}
private static void PointArt(Transform button, Image art)
{
FieldInfo fieldInfo = null;
MonoBehaviour[] componentsInChildren = ((Component)button).GetComponentsInChildren<MonoBehaviour>(true);
foreach (MonoBehaviour val in componentsInChildren)
{
if (!((Object)(object)val == (Object)null) && !(((object)val).GetType().Name != "AnimatorColorControlNode"))
{
if (fieldInfo == null)
{
fieldInfo = ((object)val).GetType().GetField("imageTarget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
fieldInfo.SetValue(val, art);
}
}
}
private static void DetachStandardMode(GameObject button)
{
MonoBehaviour[] componentsInChildren = button.GetComponentsInChildren<MonoBehaviour>(true);
foreach (MonoBehaviour val in componentsInChildren)
{
if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == "CreateGameAction")
{
Object.DestroyImmediate((Object)(object)val);
}
}
}
private static void RetargetLocal(UIControlButton control, Transform root)
{
FieldInfo[] fields = typeof(UIControlButton).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo fieldInfo in fields)
{
if (fieldInfo.FieldType == typeof(RectTransform) || !typeof(Component).IsAssignableFrom(fieldInfo.FieldType) || fieldInfo.Name == "belongGroup" || fieldInfo.Name == "provider" || fieldInfo.Name == "instructionPanelProvider")
{
continue;
}
object? value = fieldInfo.GetValue(control);
Component val = (Component)((value is Component) ? value : null);
if (!((Object)(object)val != (Object)null) || (!((Object)(object)val.transform == (Object)(object)root) && !val.transform.IsChildOf(root)))
{
Component val2 = ((Component)control).GetComponent(fieldInfo.FieldType) ?? ((Component)control).GetComponentInChildren(fieldInfo.FieldType, true);
if ((Object)(object)val2 != (Object)null)
{
fieldInfo.SetValue(control, val2);
}
}
}
}
private static int InsertIndex(Transform root)
{
int num = 0;
for (int i = 0; i < root.childCount; i++)
{
string name = ((Object)root.GetChild(i)).name;
if (name.Contains("Start Game") || name == "GlassSolMode" || name == "TrueGlassSolMode")
{
num = i;
}
}
int num2 = num + 1;
if (num2 < root.childCount && ((Object)root.GetChild(num2)).name.StartsWith("Pedding"))
{
num2++;
}
return num2;
}
private static Transform FindOptionsRoot()
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
Transform[] array = Resources.FindObjectsOfTypeAll<Transform>();
foreach (Transform val in array)
{
if (((Object)val).name == "UIOptions")
{
Scene scene = ((Component)val).gameObject.scene;
if (((Scene)(ref scene)).IsValid() && (Object)(object)FindChild(val, "Start Game") != (Object)null)
{
return val;
}
}
}
return null;
}
private static Transform FindChild(Transform root, string namePart)
{
for (int i = 0; i < root.childCount; i++)
{
Transform child = root.GetChild(i);
if (((Object)child).name.Contains(namePart))
{
return child;
}
}
return null;
}
private static bool IsCustom(Transform transform)
{
while ((Object)(object)transform != (Object)null && ((Object)transform).name != "UIOptions")
{
if (((Object)transform).name == "GlassSolMode" || ((Object)transform).name == "TrueGlassSolMode")
{
return true;
}
transform = transform.parent;
}
return false;
}
private static bool IsTrue(Transform transform)
{
while ((Object)(object)transform != (Object)null && ((Object)transform).name != "UIOptions")
{
if (((Object)transform).name == "TrueGlassSolMode")
{
return true;
}
transform = transform.parent;
}
return false;
}
private static void CreateArts(Transform options)
{
if ((Object)(object)glassArt != (Object)null)
{
return;
}
Transform val = options;
while ((Object)(object)val != (Object)null && (Object)(object)val.Find("BG") == (Object)null)
{
val = val.parent;
}
Transform val2 = val.Find("BG");
Image source = null;
int num = 0;
for (int i = 0; i < val2.childCount; i++)
{
if (!(((Object)val2.GetChild(i)).name != "BG Image"))
{
num++;
if (num == 2)
{
source = ((Component)val2.GetChild(i)).GetComponent<Image>();
break;
}
}
}
glassArt = CopyArt(source, "GlassSolArt", "GlassSol.png");
trueArt = CopyArt(source, "TrueGlassSolArt", "TrueGlassSol.png");
if ((Object)(object)((Component)val2).GetComponent<ModeArtKeep>() == (Object)null)
{
((Component)val2).gameObject.AddComponent<ModeArtKeep>();
}
}
private static Image CopyArt(Image source, string name, string fileName)
{
//IL_0053: 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_0066: Unknown result type (might be due to invalid IL or missing references)
bool activeSelf = ((Component)source).gameObject.activeSelf;
((Component)source).gameObject.SetActive(false);
Image component = Object.Instantiate<GameObject>(((Component)source).gameObject, ((Component)source).transform.parent).GetComponent<Image>();
((Component)source).gameObject.SetActive(activeSelf);
((Object)component).name = name;
component.sprite = LoadArt(fileName);
Color color = ((Graphic)component).color;
color.a = 1f;
((Graphic)component).color = color;
Animator component2 = ((Component)component).GetComponent<Animator>();
if ((Object)(object)component2 != (Object)null)
{
((Behaviour)component2).enabled = false;
}
((Component)component).transform.SetSiblingIndex(((Component)source).transform.GetSiblingIndex() + 1);
((Component)component).gameObject.SetActive(false);
return component;
}
private static Sprite LoadArt(string fileName)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("GlassSol." + fileName);
byte[] array = new byte[stream.Length];
stream.Read(array, 0, array.Length);
Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
ImageConversion.LoadImage(val, array);
return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
}
private static void PlaySelectSound()
{
object value = AccessTools.Field(typeof(UIControlButton), "_buttonSoundGroup").GetValue(soundButton);
AccessTools.Method(value.GetType(), "PlaySelectSound", (Type[])null, (Type[])null).Invoke(value, null);
}
private static Transform OptionsOf(Transform transform)
{
while ((Object)(object)transform != (Object)null && ((Object)transform).name != "UIOptions")
{
transform = transform.parent;
}
return transform;
}
private static void ReleaseOthers(Transform options, UIControlButton current)
{
ReleaseIfOther(options.Find("GlassSolMode"), current);
ReleaseIfOther(options.Find("TrueGlassSolMode"), current);
}
private static void ReleaseIfOther(Transform row, UIControlButton current)
{
if (!((Object)(object)row == (Object)null) && !((Component)current).transform.IsChildOf(row) && !((Object)(object)((Component)current).transform == (Object)(object)row))
{
(((Component)row).GetComponent<UIControlButton>() ?? ((Component)row).GetComponentInChildren<UIControlButton>(true)).RefreshState();
}
}
private static void BindDirectStart(StartMenuLogic menu, UIControlButton button, int mode)
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Expected O, but got Unknown
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
FieldInfo fieldInfo = AccessTools.Field(typeof(UIControlButton), "_onSubmitActions");
Type elementType = fieldInfo.FieldType.GetElementType();
fieldInfo.SetValue(button, Array.CreateInstance(elementType, 0));
AccessTools.Field(typeof(UIControlButton), "clickToShowGroup").SetValue(button, null);
if (button.onSubmit == null)
{
button.onSubmit = new UnityEvent();
}
button.onSubmit.AddListener((UnityAction)delegate
{
menu.CreateNewGame(mode);
});
}
internal static void DestroyLocalization(GameObject root)
{
MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true);
foreach (MonoBehaviour val in componentsInChildren)
{
if ((Object)(object)val != (Object)null && ((object)val).GetType().FullName == "I2.Loc.Localize")
{
Object.DestroyImmediate((Object)(object)val);
}
}
}
}
internal static class SaveModeLabelPatch
{
[HarmonyPostfix]
[HarmonyPatch(typeof(RCGAbstractUILabel<int>), "UpdateText")]
private static void WriteCustomMode(RCGAbstractUILabel<int> __instance)
{
if (!(AccessTools.Field(((object)__instance).GetType(), "propertyName").GetValue(__instance) as string != "gameMode") && AccessTools.Method(((object)__instance).GetType(), "GetValueOfData", (Type[])null, (Type[])null).Invoke(__instance, null) is int num && (num == 2 || num == 3))
{
ModeMenuPatch.DestroyLocalization(((Component)__instance).gameObject);
object? value = AccessTools.Field(typeof(RCGAbstractUILabel<int>), "text").GetValue(__instance);
((TMP_Text)((value is TMP_Text) ? value : null)).text = ((num == 3) ? Difficulty.Phrase("Истинный Стеклянный Сол", "True Glass Sol") : Difficulty.Phrase("Стеклянный Сол", "Glass Sol"));
}
}
}
internal class ModeArtKeep : MonoBehaviour
{
private void LateUpdate()
{
ModeMenuPatch.ApplyArt();
}
}
internal static class NewGameModeSavePatch
{
private static int pendingMode = -1;
private static StartMenuLogic menu;
[HarmonyPostfix]
[HarmonyPatch(typeof(StartMenuLogic), "CreateNewGame")]
private static void RememberMode(StartMenuLogic __instance, int mode)
{
menu = __instance;
pendingMode = mode;
Apply(mode);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(StartMenuLogic), "CreateOrLoadSaveSlotAndPlay")]
private static void ClearOnContinue()
{
pendingMode = -1;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(A0_S6_IntroVideo), "Start")]
private static bool SkipIntro(A0_S6_IntroVideo __instance)
{
if (pendingMode != 3)
{
return true;
}
AccessTools.Method(typeof(A0_S6_IntroVideo), "ChangeToStartScene", (Type[])null, (Type[])null).Invoke(__instance, null);
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ApplicationCore), "ChangeSceneClean")]
private static void SaveMode(string sceneName)
{
if (!(sceneName != "A0_S6_Intro_Video"))
{
Apply(pendingMode);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerGamePlayData), "SaveMetaData")]
private static void StampSave(SaveSlotMetaData __result)
{
if (__result != null && (pendingMode == 2 || pendingMode == 3))
{
__result.gameMode = pendingMode;
}
}
private static void Apply(int mode)
{
if (mode == 2 || mode == 3)
{
if ((Object)(object)menu != (Object)null)
{
((AbstractScriptableData<FlagFieldInt, int>)(object)menu.gameModeFlag).CurrentValue = mode;
}
PlayerGamePlayData instance = PlayerGamePlayData.Instance;
if ((Object)(object)instance != (Object)null && (Object)(object)instance.gameMode != (Object)null)
{
((AbstractScriptableData<FlagFieldInt, int>)(object)instance.gameMode).CurrentValue = mode;
}
}
}
}
internal static class PlayerHealthPatch
{
private static void Kill(PlayerHealth health)
{
if (!((Health)health).IsDead && (Difficulty.IsOneShot() || NohitSetting.Active()))
{
if (Difficulty.IsTrueGlassSol())
{
DeleteSaveAndReturnToMenu();
}
else
{
PlayDeath(health);
}
}
}
private static bool InternalShouldKill()
{
if (InternalKillSetting.Shown())
{
return InternalKillSetting.Kills();
}
return false;
}
private static void KeepAlive(PlayerHealth health)
{
float num = ((Health)health).maxHealth.Value * 0.01f;
if (num < 1f)
{
num = 1f;
}
if (((Health)health).currentValue < num)
{
((Health)health).currentValue = num;
}
}
private static void PlayDeath(PlayerHealth health)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected O, but got Unknown
Player i = Player.i;
((Health)health).currentValue = 0f;
((Health)health).Die();
if ((Object)(object)i != (Object)null && (Object)(object)i.health == (Object)(object)health)
{
i.DeadCheck(true);
}
GameObject val = new GameObject("GlassSolDeathAnim");
Object.DontDestroyOnLoad((Object)val);
val.AddComponent<DeathAnim>();
}
internal static void DeleteSaveAndReturnToMenu()
{
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Expected O, but got Unknown
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
SaveManager instance = SingletonBehaviour<SaveManager>.Instance;
int num = (int)AccessTools.Field(typeof(SaveManager), "currentSlotIndex").GetValue(instance);
if (num >= 0)
{
AccessTools.Method(typeof(SaveManager), "DeleteSave", (Type[])null, (Type[])null).Invoke(instance, new object[1] { num });
}
Time.timeScale = 1f;
ApplicationUIGroupManager instance2 = SingletonBehaviour<ApplicationUIGroupManager>.Instance;
if ((Object)(object)instance2 != (Object)null && (Object)(object)instance2.blackCover != (Object)null)
{
Color color = ((Graphic)instance2.blackCover).color;
color.a = 0f;
((Graphic)instance2.blackCover).color = color;
((Component)instance2.blackCover).gameObject.SetActive(false);
}
GameObject val = new GameObject("GlassSolRevealMenu");
Object.DontDestroyOnLoad((Object)val);
val.AddComponent<RevealMenu>();
SingletonBehaviour<ApplicationCore>.Instance.QuitToMenu();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(PlayerAbilityData), "get_IsActivated")]
private static bool DisableJades(PlayerAbilityData __instance, ref bool __result)
{
if (!Difficulty.IsOneShot())
{
return true;
}
Player i = Player.i;
if ((Object)(object)i == (Object)null)
{
return true;
}
PlayerMainAbilityCollection mainAbilities = i.mainAbilities;
if ((Object)(object)__instance != (Object)(object)mainAbilities.ReviveJade.AbilityData && (Object)(object)__instance != (Object)(object)mainAbilities.EndureFooExplodeJade)
{
return true;
}
__result = false;
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerHealth), "ReceiveDamage")]
private static void ReceiveDamage(PlayerHealth __instance, DamageDealer damageDealer, bool __result)
{
if (__result && !((Health)__instance).IsInvincible && !((Object)(object)damageDealer == (Object)null) && !(damageDealer.DamageAmount <= 0f))
{
Kill(__instance);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerHealth), "ReceiveDOT_Damage")]
private static void ReceiveDotDamage(PlayerHealth __instance, float damageValue)
{
if (!((Health)__instance).IsInvincible && !(damageValue <= 0f))
{
Kill(__instance);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerHealth), "ReceiveRecoverableDamage")]
private static void ReceiveRecoverableDamage(PlayerHealth __instance, float damage)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Expected O, but got Unknown
if (damage <= 0f || ((Health)__instance).IsDead)
{
return;
}
if (!InternalShouldKill())
{
if (Difficulty.IsOneShot())
{
KeepAlive(__instance);
}
return;
}
PlayDeath(__instance);
if (Difficulty.IsTrueGlassSol())
{
GameObject val = new GameObject("GlassSolInternalDeath");
Object.DontDestroyOnLoad((Object)val);
val.AddComponent<InternalDeathWipe>();
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerHealth), "CoughHurt")]
private static void CoughHurt(PlayerHealth __instance, float damageValue)
{
if (!(damageValue <= 0f))
{
Kill(__instance);
}
}
}
internal class DeathAnim : MonoBehaviour
{
private bool played;
private int frames = 8;
private void LateUpdate()
{
Player i = Player.i;
if ((Object)(object)i != (Object)null && (Object)(object)((Actor)i).animator != (Object)null)
{
((Actor)i).animator.SetLayerWeight(1, 0f);
if (!played)
{
((Actor)i).animator.Play("Die", 0, 0f);
played = true;
}
}
frames--;
if (frames <= 0)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
}
internal class InternalDeathWipe : MonoBehaviour
{
private float left = 1.4f;
private void Update()
{
left -= Time.unscaledDeltaTime;
if (!(left > 0f))
{
PlayerHealthPatch.DeleteSaveAndReturnToMenu();
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
}
internal class RevealMenu : MonoBehaviour
{
private int left = 90;
private void LateUpdate()
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: 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)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
Time.timeScale = 1f;
Scene activeScene = SceneManager.GetActiveScene();
if (!(((Scene)(ref activeScene)).name != "TitleScreenMenu") || !((Object)(object)Object.FindObjectOfType<StartMenuLogic>() == (Object)null))
{
ApplicationUIGroupManager instance = SingletonBehaviour<ApplicationUIGroupManager>.Instance;
if ((Object)(object)instance != (Object)null && (Object)(object)instance.blackCover != (Object)null)
{
Color color = ((Graphic)instance.blackCover).color;
color.a = 0f;
((Graphic)instance.blackCover).color = color;
((Graphic)instance.blackCover).raycastTarget = false;
((Component)instance.blackCover).gameObject.SetActive(false);
}
left--;
if (left <= 0)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
}
}
}
}
}