Decompiled source of GloomwoodHardcore v1.0.0

BepInEx/Plugins/HardGloom.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("HardGloom")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HardGloom")]
[assembly: AssemblyTitle("HardGloom")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace GloomwoodHardcore;

[BepInPlugin("com.wanderan51.gloomwoodhardcore", "Gloomwood Hardcore", "1.0")]
public class HardcoreMod : BaseUnityPlugin
{
	[CompilerGenerated]
	private sealed class <ClearOverlayAfterDelay>d__17 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public HardcoreMod <>4__this;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <ClearOverlayAfterDelay>d__17(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			int num = <>1__state;
			HardcoreMod hardcoreMod = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
			{
				<>1__state = -1;
				float num2 = Mathf.Clamp(hardcoreMod.cfgDeathDelay.Value, 0.5f, 10f);
				<>2__current = (object)new WaitForSecondsRealtime(num2);
				<>1__state = 1;
				return true;
			}
			case 1:
				<>1__state = -1;
				hardcoreMod.showOverlay = false;
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	internal static ManualLogSource Log;

	private ConfigEntry<bool> cfgEnabled;

	private ConfigEntry<bool> cfgBackupSave;

	private ConfigEntry<bool> cfgShowWarning;

	private ConfigEntry<float> cfgDeathDelay;

	private bool inGame;

	private bool hardcoreTriggered;

	private float overlayAlpha;

	private bool showOverlay;

	private static readonly HashSet<string> GameplayScenes = new HashSet<string> { "Level_City_Hightown", "Level_City_Market", "Level_City_Market_Shop", "Level_City_Underport", "Level_City_Underport_Hive", "Level_Coast_Caves", "Level_Coast_Cliffside", "Level_Coast_Fishery", "Level_Coast_Tavern", "Level_Dimension_Mirror" };

	private static readonly HashSet<string> TitleScenes = new HashSet<string> { "Level_Splash", "Level_Title_Cliffside", "Level_Title_Fishery", "Level_Title_Hightown_Gate", "Level_Title_Underport_Powerstation" };

	private void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		cfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Hardcore", "Enabled", true, "Enable hardcore mode. Save is deleted on death.");
		cfgBackupSave = ((BaseUnityPlugin)this).Config.Bind<bool>("Hardcore", "BackupSave", true, "Keep a .hardcore_bak copy of the save when deleted.");
		cfgShowWarning = ((BaseUnityPlugin)this).Config.Bind<bool>("Hardcore", "ShowWarning", true, "Show a warning banner on the title screen.");
		cfgDeathDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Hardcore", "DeathDelay", 3f, "Seconds to show the death screen before returning to title (0.5-10).");
		SceneManager.sceneLoaded += OnSceneLoaded;
		Log.LogInfo((object)"═══════════════════════════════════════════");
		Log.LogInfo((object)"   GLOOMWOOD HARDCORE MODE 1.0");
		Log.LogInfo((object)$"   Enabled     : {cfgEnabled.Value}");
		Log.LogInfo((object)$"   Backup save : {cfgBackupSave.Value}");
		Log.LogInfo((object)$"   Death delay : {cfgDeathDelay.Value}s");
		Log.LogInfo((object)"═══════════════════════════════════════════");
		LogSavesFolder();
	}

	private string GetSavesFolder()
	{
		return Path.Combine(Path.GetDirectoryName(Application.dataPath), "Saves");
	}

	private void LogSavesFolder()
	{
		string savesFolder = GetSavesFolder();
		Log.LogInfo((object)("[HARDCORE] Saves folder: " + savesFolder));
		Log.LogInfo((object)$"[HARDCORE] Folder exists: {Directory.Exists(savesFolder)}");
		if (Directory.Exists(savesFolder))
		{
			string[] files = Directory.GetFiles(savesFolder, "*", SearchOption.AllDirectories);
			Log.LogInfo((object)$"[HARDCORE] Files found ({files.Length}):");
			string[] array = files;
			foreach (string text in array)
			{
				long length = new FileInfo(text).Length;
				Log.LogInfo((object)$"[HARDCORE]   {text}  ({length} bytes)");
			}
		}
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		string name = ((Scene)(ref scene)).name;
		Log.LogInfo((object)$"[HARDCORE] Scene: {name}  (inGame={inGame})");
		if (TitleScenes.Contains(name))
		{
			inGame = false;
			if (hardcoreTriggered && showOverlay)
			{
				((MonoBehaviour)this).StartCoroutine(ClearOverlayAfterDelay());
			}
			else
			{
				showOverlay = false;
				overlayAlpha = 0f;
			}
			hardcoreTriggered = false;
			Log.LogInfo((object)"[HARDCORE] Title — reset.");
		}
		else if (GameplayScenes.Contains(name))
		{
			if (!cfgEnabled.Value)
			{
				inGame = true;
			}
			else if (inGame && !hardcoreTriggered)
			{
				Log.LogInfo((object)"[HARDCORE] ══════════════════════");
				Log.LogInfo((object)"[HARDCORE]   DEATH — deleting save");
				Log.LogInfo((object)"[HARDCORE] ══════════════════════");
				hardcoreTriggered = true;
				showOverlay = true;
				DeleteSaveFiles();
				SceneManager.LoadScene("Level_Title_Fishery");
			}
			else
			{
				inGame = true;
				Log.LogInfo((object)("[HARDCORE] Now tracking '" + name + "'."));
			}
		}
	}

	private void DeleteSaveFiles()
	{
		string savesFolder = GetSavesFolder();
		if (!Directory.Exists(savesFolder))
		{
			Log.LogError((object)("[HARDCORE] Saves folder not found: " + savesFolder));
			return;
		}
		List<string> list = new List<string>();
		for (int i = 0; i <= 9; i++)
		{
			string text = Path.Combine(savesFolder, $"Slot_{i}");
			if (Directory.Exists(text))
			{
				list.Add(text);
			}
		}
		Log.LogInfo((object)($"[HARDCORE] Found {list.Count} save slot(s): " + string.Join(", ", list.ConvertAll((string d) => Path.GetFileName(d)))));
		if (list.Count == 0)
		{
			Log.LogWarning((object)("[HARDCORE] No Slot_0..9 folders found in " + savesFolder));
			return;
		}
		foreach (string item in list)
		{
			try
			{
				if (cfgBackupSave.Value)
				{
					string text2 = item + "_BACKUP";
					if (Directory.Exists(text2))
					{
						Directory.Delete(text2, recursive: true);
					}
					CopyDirectory(item, text2);
					Log.LogInfo((object)("[HARDCORE] Slot backed up -> " + text2));
				}
				string text3 = item + "_HARDCORE_DEAD";
				if (Directory.Exists(text3))
				{
					Directory.Delete(text3, recursive: true);
				}
				Directory.Move(item, text3);
				Log.LogInfo((object)("[HARDCORE] RENAMED: " + item));
				Log.LogInfo((object)("[HARDCORE]       -> " + text3));
				Log.LogInfo((object)"[HARDCORE] Save slot destroyed. Steam Cloud cannot restore to renamed path.");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[HARDCORE] Failed to rename slot '" + item + "': " + ex.Message));
			}
		}
	}

	private void CopyDirectory(string src, string dst)
	{
		Directory.CreateDirectory(dst);
		string[] files = Directory.GetFiles(src);
		foreach (string text in files)
		{
			File.Copy(text, Path.Combine(dst, Path.GetFileName(text)), overwrite: true);
		}
		files = Directory.GetDirectories(src);
		foreach (string text2 in files)
		{
			CopyDirectory(text2, Path.Combine(dst, Path.GetFileName(text2)));
		}
	}

	[IteratorStateMachine(typeof(<ClearOverlayAfterDelay>d__17))]
	private IEnumerator ClearOverlayAfterDelay()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ClearOverlayAfterDelay>d__17(0)
		{
			<>4__this = this
		};
	}

	private void Update()
	{
		if (showOverlay)
		{
			overlayAlpha = Mathf.MoveTowards(overlayAlpha, 1f, Time.unscaledDeltaTime * 1.2f);
		}
		else
		{
			overlayAlpha = Mathf.MoveTowards(overlayAlpha, 0f, Time.unscaledDeltaTime * 2f);
		}
	}

	private void OnGUI()
	{
		//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)
		if (!cfgEnabled.Value)
		{
			return;
		}
		if (cfgShowWarning.Value && !inGame)
		{
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (TitleScenes.Contains(name) && name != "Level_Splash")
			{
				DrawTitleBanner();
			}
		}
		if (inGame && !hardcoreTriggered)
		{
			DrawBadge();
		}
		if (overlayAlpha > 0.01f)
		{
			DrawDeathOverlay();
		}
	}

	private void DrawTitleBanner()
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: 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_007a: Expected O, but got Unknown
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Expected O, but got Unknown
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		float num = 330f;
		float num2 = 58f;
		Rect val = default(Rect);
		((Rect)(ref val))..ctor((float)Screen.width / 2f - num / 2f, (float)Screen.height - num2 - 22f, num, num2);
		GUI.color = new Color(0f, 0f, 0f, 0.8f);
		GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
		GUI.color = Color.white;
		GUIStyle val2 = new GUIStyle(GUI.skin.label);
		val2.fontSize = 16;
		val2.fontStyle = (FontStyle)1;
		val2.alignment = (TextAnchor)4;
		val2.normal.textColor = new Color(0.9f, 0.2f, 0.15f, 1f);
		GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 4f, ((Rect)(ref val)).width, 26f), "!! HARDCORE MODE ACTIVE !!", val2);
		GUIStyle val3 = new GUIStyle(GUI.skin.label);
		val3.fontSize = 12;
		val3.alignment = (TextAnchor)4;
		val3.normal.textColor = new Color(0.82f, 0.74f, 0.62f, 1f);
		GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + 30f, ((Rect)(ref val)).width, 22f), "Save will be deleted on death.", val3);
	}

	private void DrawBadge()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Expected O, but got Unknown
		//IL_0039: 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)
		GUIStyle val = new GUIStyle(GUI.skin.label);
		val.fontSize = 13;
		val.fontStyle = (FontStyle)1;
		val.normal.textColor = new Color(0.85f, 0.15f, 0.1f, 0.9f);
		GUI.Label(new Rect((float)Screen.width - 145f, 8f, 135f, 24f), "[ HARDCORE ]", val);
	}

	private void DrawDeathOverlay()
	{
		//IL_001d: 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_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		//IL_0092: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Expected O, but got Unknown
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		float num = overlayAlpha;
		GUI.color = new Color(0f, 0f, 0f, num * 0.75f);
		GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture);
		GUI.color = Color.white;
		GUIStyle val = new GUIStyle(GUI.skin.label);
		val.fontSize = 52;
		val.fontStyle = (FontStyle)1;
		val.alignment = (TextAnchor)4;
		val.normal.textColor = new Color(0.9f, 0.12f, 0.08f, num);
		GUI.Label(new Rect(0f, (float)Screen.height / 2f - 70f, (float)Screen.width, 80f), "YOU DIED", val);
		GUIStyle val2 = new GUIStyle(GUI.skin.label);
		val2.fontSize = 20;
		val2.alignment = (TextAnchor)4;
		val2.normal.textColor = new Color(0.82f, 0.74f, 0.62f, num);
		GUI.Label(new Rect(0f, (float)Screen.height / 2f + 22f, (float)Screen.width, 34f), "Your save has been deleted.", val2);
	}
}