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 easy checkpoints v0.0.1
silgsong_checkpoint-mod.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GlobalEnums; using HarmonyLib; using TeamCherry.SharedUtils; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("silgsong_checkpoint-mod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+76311ddc742297d098e756f857f84c74f8d7a050")] [assembly: AssemblyProduct("silgsong_checkpoint-mod")] [assembly: AssemblyTitle("silgsong_checkpoint-mod")] [assembly: AssemblyVersion("1.0.0.0")] namespace silgsong_checkpoint_mod; internal sealed class CheckpointHotkeys : MonoBehaviour { private const float MessageSeconds = 2.5f; private const float FadeSeconds = 0.5f; private static ConfigEntry<KeyCode> hotKey; private string message; private float messageUntil; private GUIStyle messageStyle; private Texture2D background; public static void Bind(ConfigFile config) { hotKey = config.Bind<KeyCode>("Controls", "HotKey", (KeyCode)112, "Клавиша: нажать — поставить точку возрождения здесь, с Shift — удалить её."); } private void Update() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (WasKeyPressed(EasyModeManager.HotKey)) { bool flag = EasyModeManager.Toggle(HeroController.instance); ShowMessage(flag ? "Легкий режим: ВКЛ" : "Легкий режим: ВЫКЛ"); } if (WasKeyPressed(hotKey.Value)) { if (IsShiftHeld()) { ClearCheckpoint(); } else { SetCheckpointHere(); } } } private void OnDestroy() { if ((Object)(object)background != (Object)null) { Object.Destroy((Object)(object)background); } } private void SetCheckpointHere() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) GameManager instance = GameManager.instance; HeroController instance2 = HeroController.instance; if (!((Object)(object)instance != (Object)null) || !((Object)(object)instance2 != (Object)null) || (int)instance.GameState != 4 || instance2.cState.dead || string.IsNullOrEmpty(instance.GetSceneNameString())) { ShowMessage("Точку можно поставить только в обычной игре"); return; } CustomCheckpoint.Set(instance.GetSceneNameString(), Vector2.op_Implicit(((Component)instance2).transform.position), instance2.cState.facingRight); ShowMessage("Точка возрождения поставлена здесь"); } private void ClearCheckpoint() { if (!CustomCheckpoint.IsSet) { ShowMessage("Точка возрождения не задана"); return; } CustomCheckpoint.Clear(); ShowMessage("Точка возрождения удалена — возрождение как в ванилле"); } private void ShowMessage(string text) { message = text; messageUntil = Time.unscaledTime + 2.5f; } private void OnGUI() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00b5: 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) float num = messageUntil - Time.unscaledTime; if (!string.IsNullOrEmpty(message) && !(num <= 0f)) { EnsureStyles(); GUIContent val = new GUIContent(message); float num2 = Mathf.Min(messageStyle.CalcSize(val).x + 40f, (float)Screen.width - 40f); float num3 = messageStyle.CalcHeight(val, num2) + 20f; Rect val2 = new Rect(((float)Screen.width - num2) * 0.5f, (float)Screen.height * 0.1f, num2, num3); Color color = GUI.color; GUI.color = new Color(1f, 1f, 1f, Mathf.Clamp01(num / 0.5f)); GUI.Label(val2, val, messageStyle); GUI.color = color; } } private void EnsureStyles() { //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) //IL_001e: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00ab: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (messageStyle == null) { background = new Texture2D(1, 1) { hideFlags = (HideFlags)61 }; background.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.75f)); background.Apply(); messageStyle = new GUIStyle(GUI.skin.label) { fontSize = Mathf.Clamp(Mathf.RoundToInt(18f * (float)Screen.height / 1080f), 16, 32), alignment = (TextAnchor)4, wordWrap = true, padding = new RectOffset(20, 20, 10, 10) }; messageStyle.normal.background = background; messageStyle.normal.textColor = Color.white; } } private static bool IsShiftHeld() { try { Keyboard current = Keyboard.current; if (current != null) { return ((ButtonControl)current.leftShiftKey).isPressed || ((ButtonControl)current.rightShiftKey).isPressed; } } catch (Exception) { } try { return Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); } catch (Exception) { return false; } } private unsafe static bool WasKeyPressed(KeyCode key) { //IL_0020: 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_0024: Unknown result type (might be due to invalid IL or missing references) try { Keyboard current = Keyboard.current; if (current != null && Enum.TryParse<Key>(((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(), ignoreCase: true, out Key result) && (int)result != 0) { KeyControl val = current[result]; if (val != null) { return ((ButtonControl)val).wasPressedThisFrame; } } } catch (Exception) { } try { return Input.GetKeyDown(key); } catch (Exception) { return false; } } } internal static class CustomCheckpoint { public const string MarkerName = "S2E Custom Respawn Marker"; private static ConfigEntry<string> scene; private static ConfigEntry<float> posX; private static ConfigEntry<float> posY; private static ConfigEntry<bool> facingRight; public static bool IsSet => !string.IsNullOrEmpty(scene.Value); public static string Scene => scene.Value; public static Vector2 Position => new Vector2(posX.Value, posY.Value); public static bool FacingRight => facingRight.Value; public static void Bind(ConfigFile config) { scene = config.Bind<string>("Checkpoint", "Scene", "", "Сцена пользовательской точки возрождения. Пусто — точка не задана, возрождение полностью ванильное."); posX = config.Bind<float>("Checkpoint", "X", 0f, "Координата X точки возрождения."); posY = config.Bind<float>("Checkpoint", "Y", 0f, "Координата Y точки возрождения."); facingRight = config.Bind<bool>("Checkpoint", "FacingRight", true, "В какую сторону смотрит герой после возрождения."); } public static void Set(string sceneName, Vector2 position, bool isFacingRight) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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) scene.Value = sceneName; posX.Value = position.x; posY.Value = position.y; facingRight.Value = isFacingRight; ModEntry.Log.LogInfo((object)$"Точка возрождения поставлена: {sceneName} ({position.x:0.##}, {position.y:0.##})."); } public static void Clear() { scene.Value = ""; posX.Value = 0f; posY.Value = 0f; DestroyMarker(); ModEntry.Log.LogInfo((object)"Точка возрождения удалена, возрождение снова ванильное."); } public static Transform GetOrCreateMarker(Vector2 position, bool isFacingRight) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0057: 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_0032: Expected O, but got Unknown RespawnMarker val = FindMarker(); if ((Object)(object)val == (Object)null) { val = new GameObject("S2E Custom Respawn Marker").AddComponent<RespawnMarker>(); } if (val.customFadeDuration == null) { val.customFadeDuration = new OverrideFloat(); } val.customWakeUp = false; val.respawnFacingRight = isFacingRight; ((Component)val).transform.position = new Vector3(position.x, position.y, 0f); return ((Component)val).transform; } private static RespawnMarker FindMarker() { List<RespawnMarker> markers = RespawnMarker.Markers; if (markers == null) { return null; } foreach (RespawnMarker item in markers) { if ((Object)(object)item != (Object)null && ((Object)item).name == "S2E Custom Respawn Marker") { return item; } } return null; } private static void DestroyMarker() { RespawnMarker val = FindMarker(); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } internal static class EasyModeManager { private static ConfigEntry<KeyCode> hotKey; private static ConfigEntry<bool> isEnabledConfig; private static readonly Dictionary<HeroController, float> fractionalDamageMap = new Dictionary<HeroController, float>(); private static bool isEnabled; public static KeyCode HotKey { get { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (hotKey == null) { return (KeyCode)108; } return hotKey.Value; } } public static void Bind(ConfigFile config) { hotKey = config.Bind<KeyCode>("Controls", "EasyModeHotKey", (KeyCode)108, "Клавиша для переключения Легкого режима (Easy Mode)."); isEnabledConfig = config.Bind<bool>("EasyMode", "Enabled", false, "Включен ли легкий режим по умолчанию."); isEnabled = isEnabledConfig.Value; } public static bool IsEnabled(HeroController hero = null) { return isEnabled; } public static bool Toggle(HeroController hero = null) { isEnabled = !isEnabled; if (isEnabledConfig != null) { isEnabledConfig.Value = isEnabled; } ResetFractionalDamage(hero); ModEntry.Log.LogInfo((object)("Легкий режим (Easy Mode) " + (isEnabled ? "ВКЛЮЧЕН" : "ВЫКЛЮЧЕН") + ".")); return isEnabled; } public static int CalculateIncomingDamage(HeroController hero, int rawDamage) { if (rawDamage <= 0) { return 0; } float fractionalDamage = GetFractionalDamage(hero); float num = (float)rawDamage * 0.5f; float num2 = fractionalDamage + num; int num3 = Mathf.FloorToInt(num2); float num4 = num2 - (float)num3; SetFractionalDamage(hero, num4); ModEntry.Log.LogDebug((object)$"[EasyMode] Входящий урон: {rawDamage} -> Получено: {num3} (Дробный остаток: {num4:0.0})"); return num3; } public static void ResetFractionalDamage(HeroController hero = null) { if ((Object)(object)hero != (Object)null) { fractionalDamageMap.Remove(hero); } else { fractionalDamageMap.Clear(); } } public static bool IsHeroAttack(HitInstance hitInstance) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0036: 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_0076: 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) if (!isEnabled) { return false; } if (hitInstance.IsHeroDamage) { return true; } if ((Object)(object)hitInstance.Source != (Object)null) { if (hitInstance.Source.CompareTag("Player") || ((Component)hitInstance.Source.transform.root).CompareTag("Player")) { return true; } if ((Object)(object)hitInstance.Source.GetComponentInParent<HeroController>() != (Object)null) { return true; } if ((Object)(object)HeroController.instance != (Object)null && ((Object)(object)hitInstance.Source == (Object)(object)((Component)HeroController.instance).gameObject || hitInstance.Source.transform.IsChildOf(((Component)HeroController.instance).transform))) { return true; } } return false; } private static float GetFractionalDamage(HeroController hero) { if ((Object)(object)hero != (Object)null && fractionalDamageMap.TryGetValue(hero, out var value)) { return value; } return 0f; } private static void SetFractionalDamage(HeroController hero, float val) { if ((Object)(object)hero != (Object)null) { if (val > 0.001f) { fractionalDamageMap[hero] = val; } else { fractionalDamageMap.Remove(hero); } } } } [HarmonyPatch] internal static class EasyModePatches { private static bool isHandlingTakeHealth; [HarmonyPatch(typeof(PlayerData), "TakeHealth")] [HarmonyPrefix] private static void PlayerDataTakeHealthPrefix(PlayerData __instance, ref int amount) { if (isHandlingTakeHealth || amount <= 0 || !EasyModeManager.IsEnabled()) { return; } try { isHandlingTakeHealth = true; amount = EasyModeManager.CalculateIncomingDamage(HeroController.instance, amount); } finally { isHandlingTakeHealth = false; } } [HarmonyPatch(typeof(HeroController), "StartRecoil")] [HarmonyPrefix] private static void HeroStartRecoilPrefix(HeroController __instance, ref CollisionSide impactSide) { if (EasyModeManager.IsEnabled(__instance)) { impactSide = (CollisionSide)4; } } [HarmonyPatch(typeof(HealthManager), "Hit")] [HarmonyPrefix] private static void HealthManagerHitPrefix(ref HitInstance hitInstance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (EasyModeManager.IsHeroAttack(hitInstance)) { hitInstance.DamageDealt *= 2; } } [HarmonyPatch(typeof(HealthManager), "ApplyExtraDamage", new Type[] { typeof(HitInstance) })] [HarmonyPrefix] private static void HealthManagerApplyExtraDamagePrefix(ref HitInstance hitInstance) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (EasyModeManager.IsHeroAttack(hitInstance)) { hitInstance.DamageDealt *= 2; } } [HarmonyPatch(typeof(HeroController), "HeroRespawned")] [HarmonyPostfix] private static void HeroRespawnedPostfix(HeroController __instance) { EasyModeManager.ResetFractionalDamage(__instance); } [HarmonyPatch(typeof(HeroController), "Die")] [HarmonyPostfix] private static void HeroDiePostfix(HeroController __instance) { EasyModeManager.ResetFractionalDamage(__instance); } } [BepInPlugin("silksong.checkpoint.mod", "Silksong Checkpoint Mod", "1.0.0")] public sealed class ModEntry : BaseUnityPlugin { public const string Guid = "silksong.checkpoint.mod"; public const string Name = "Silksong Checkpoint Mod"; public const string Version = "1.0.0"; private Harmony harmony; internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; CustomCheckpoint.Bind(((BaseUnityPlugin)this).Config); CheckpointHotkeys.Bind(((BaseUnityPlugin)this).Config); EasyModeManager.Bind(((BaseUnityPlugin)this).Config); harmony = new Harmony("silksong.checkpoint.mod"); harmony.PatchAll(typeof(RespawnPatches)); harmony.PatchAll(typeof(EasyModePatches)); ((Component)this).gameObject.AddComponent<CheckpointHotkeys>(); Log.LogInfo((object)("Silksong Checkpoint Mod 1.0.0 загружен. Точка возрождения: " + (CustomCheckpoint.IsSet ? CustomCheckpoint.Scene : "не задана") + ". Легкий режим: " + (EasyModeManager.IsEnabled() ? "ВКЛ" : "ВЫКЛ") + ".")); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } [HarmonyPatch] internal static class RespawnPatches { private static bool loadingSavedGame; private static bool overrideArmed; private static string armedScene; private static Vector2 armedPosition; private static bool armedFacingRight; [HarmonyPatch(typeof(GameManager), "ReadyForRespawn")] [HarmonyPrefix] private static void ReadyForRespawnPrefix(bool isFirstLevelForPlayer) { loadingSavedGame = isFirstLevelForPlayer; } [HarmonyPatch(typeof(GameManager), "ReadyForRespawn")] [HarmonyFinalizer] private static void ReadyForRespawnFinalizer() { loadingSavedGame = false; } [HarmonyPatch(typeof(GameManager), "GetRespawnInfo")] [HarmonyPostfix] private static void GetRespawnInfoPostfix(ref string scene, ref string marker) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!loadingSavedGame && CustomCheckpoint.IsSet) { scene = CustomCheckpoint.Scene; marker = "S2E Custom Respawn Marker"; overrideArmed = true; armedScene = CustomCheckpoint.Scene; armedPosition = CustomCheckpoint.Position; armedFacingRight = CustomCheckpoint.FacingRight; } } [HarmonyPatch(typeof(HeroController), "LocateSpawnPoint")] [HarmonyPostfix] private static void LocateSpawnPointPostfix(ref Transform __result) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (overrideArmed && (IsArmedScene() || !((Object)(object)__result != (Object)null))) { Transform orCreateMarker = CustomCheckpoint.GetOrCreateMarker(armedPosition, armedFacingRight); if (!((Object)(object)orCreateMarker == (Object)null)) { __result = orCreateMarker; overrideArmed = false; } } } private static bool IsArmedScene() { //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) GameManager instance = GameManager.instance; if ((Object)(object)instance != (Object)null && instance.GetSceneNameString() == armedScene) { return true; } Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name == armedScene; } }