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);
}
}