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 AuricAegis v1.1.2
AuricAegis.dll
Decompiled 9 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using HutongGames.PlayMaker; using HutongGames.PlayMaker.Actions; using Microsoft.CodeAnalysis; using Silksong.FsmUtil; using TeamCherry.Localization; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("AuricAegis")] [assembly: AssemblyDescription("Auric Aegis")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Astrum Nova")] [assembly: AssemblyProduct("Auric Aegis")] [assembly: AssemblyCopyright("Copyright \ufffd 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("d13a3b2c-1a23-4c45-9123-7f5a7b8e9abc")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Silksong.Mods.PrimedSentinel { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.astrumnova.auricaegis", "Auric Aegis", "0.0.1")] [BepInProcess("Hollow Knight Silksong.exe")] public class PrimedSentinel : BaseUnityPlugin { private static int INITIAL_HP = 1800; private static int PHASE_2_THRESHOLD = 1500; private static int PARRY_DAMAGE = 2; private static int STUN_QUOTA = 100; private static int PARRY_SILK_GAIN_MULTIPLIER = 1; private static int stunCounter; private static GameObject gameObj; public static PlayMakerFSM control; private static HealthManager healthManager; private static bool enable; private static bool phase2; private static bool risingSlashedOnce; private static bool diveFollowUpSelected; private static bool risingSlashing; private static bool windSlashedOnce; private static bool dashStabbedOnce = true; private static bool isCrossStitching; private static readonly string[] stunStates = new string[5] { "Stun Start", "Stun Air", "Stun Land", "Stunned", "Stun Damage" }; private static readonly ManualLogSource logger = Logger.CreateLogSource("Auric Aegis"); public static void log(string msg) { logger.LogInfo((object)msg); } private void Awake() { INITIAL_HP = ((BaseUnityPlugin)this).Config.Bind<int>("Boss Settings", "Initial HP", 1800, "The total HP the boss starts with at the beginning of the fight.").Value; PHASE_2_THRESHOLD = ((BaseUnityPlugin)this).Config.Bind<int>("Boss Settings", "Phase 2 Threshold", 1500, "When HP drops to this value, the next stun will trigger Phase 2.").Value; PARRY_DAMAGE = ((BaseUnityPlugin)this).Config.Bind<int>("Boss Settings", "Parry Damage", 2, "Amount of damage dealt to the boss each frame the player parries.").Value; STUN_QUOTA = ((BaseUnityPlugin)this).Config.Bind<int>("Boss Settings", "Stun Quota", 100, "How many parried frames are required to stun the boss.").Value; PARRY_SILK_GAIN_MULTIPLIER = ((BaseUnityPlugin)this).Config.Bind<int>("Boss Settings", "Parry Silk Gain Multiplier", 1, "Multiplier for parry silk gain, by default it does nothing since its set to 1.").Value; Harmony.CreateAndPatchAll(typeof(PrimedSentinel), (string)null); Harmony.CreateAndPatchAll(typeof(Patch_SpawnObjectFromGlobalPool_OnEnter), (string)null); ((MonoBehaviour)this).StartCoroutine(WaitAndPatch()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"com.astrumnova.auricaegis loaded and initialized!"); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayMakerFSM), "OnEnable")] private static void OnFsmEnabled(PlayMakerFSM __instance) { //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) if ((Object)(object)control == (Object)null && __instance.FsmName == "Control") { Scene scene = ((Component)__instance).gameObject.scene; if (((Scene)(ref scene)).name == "Hang_17b" && ((IEnumerable<FsmState>)__instance.FsmStates).FirstOrDefault((Func<FsmState, bool>)((FsmState state) => state.Name == "First Idle")) != null) { PlayerData.instance.encounteredSongChevalierBoss = true; enable = true; control = __instance; gameObj = ((Component)__instance).gameObject; healthManager = gameObj.GetComponent<HealthManager>(); healthManager.hp = INITIAL_HP; removeEventFromState("Target Check", "NEEDOLIN"); removeEventFromState("Rising Slash Followup", "FALL"); removeEventFromState("Rising Slash Followup", "STEP"); removeEventFromState("WJ Cross Slash", "CANCEL"); removeEventFromState("Jump Rise", "LAND"); FsmUtil.GetFirstActionOfType<SetVelocityByScale>(control, "Rising Slash").speed = FsmFloat.op_Implicit(-60f); FsmUtil.GetFirstActionOfType<SetVelocityAsAngle>(control, "Dive").speed = FsmFloat.op_Implicit(120f); FsmUtil.GetFirstActionOfType<SetVelocityByScale>(control, "DashStab Dash").speed = FsmFloat.op_Implicit(-100f); FsmUtil.GetFirstActionOfType<SetFloatValue>(control, "Windslash G").floatValue = FsmFloat.op_Implicit(-70f); FsmUtil.GetFirstActionOfType<SetVelocity2d>(control, "Windslash G").y = FsmFloat.op_Implicit(40f); FsmUtil.GetFirstActionOfType<SetFloatValue>(control, "Windslash A").floatValue = FsmFloat.op_Implicit(-70f); FsmUtil.GetLastActionOfType<SetFloatValue>(control, "Windslash A").floatValue = FsmFloat.op_Implicit(-40f); FsmUtil.GetLastActionOfType<SetVelocityByScale>(control, "CrossSlash Recoil").speed = FsmFloat.op_Implicit(15f); FsmUtil.GetFirstActionOfType<Wait>(control, "Idle").time = FsmFloat.op_Implicit(-1f); FsmUtil.GetFirstActionOfType<ConvertBoolToFloat>(control, "Idle").floatVariable = FsmFloat.op_Implicit(0f); FsmUtil.GetFirstActionOfType<ConvertBoolToFloat>(control, "Idle").falseValue = FsmFloat.op_Implicit(0f); FsmUtil.GetLastActionOfType<FaceObjectV2>(control, "Dive Dir").pauseBetweenTurns = 0f; FsmUtil.GetLastActionOfType<Wait>(control, "CS Antic").time = FsmFloat.op_Implicit(0.25f); } } } [HarmonyPostfix] [HarmonyPatch(typeof(FsmState), "OnEnter")] private static void OnFSMStateEntered(FsmState __instance) { //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_058d: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_04b7: Unknown result type (might be due to invalid IL or missing references) //IL_0562: Unknown result type (might be due to invalid IL or missing references) //IL_05e2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)control == (Object)null) { enable = false; return; } switch (__instance.Name) { case "Battle Start": stunCounter = 0; phase2 = false; risingSlashedOnce = false; diveFollowUpSelected = false; risingSlashing = false; windSlashedOnce = false; dashStabbedOnce = true; isCrossStitching = false; healthManager.IsInvincible = true; break; case "Stun Recover": case "Damage Recover": stunCounter = 0; if (healthManager.hp <= PHASE_2_THRESHOLD && !phase2) { healthManager.hp = PHASE_2_THRESHOLD; phase2 = true; Object.Destroy((Object)(object)FSMUtility.LocateMyFSM(gameObj, "Stun Control")); control.SetState("Rising Slash Antic"); } break; case "Rising Slash Antic": { risingSlashing = true; float x = ((Component)control).transform.position.x; FsmUtil.GetFirstActionOfType<SetVelocityByScale>(control, "Rising Slash").speed = FsmFloat.op_Implicit(-60f); ChangeTelegraphy(__instance, "FINISHED", 0.6f); if (phase2) { FsmUtil.GetFirstActionOfType<SetVelocityByScale>(control, "Rising Slash").ySpeed = FsmFloat.op_Implicit(13.70306f); ((MonoBehaviour)control).StartCoroutine(FixRisingSlash(1.39f, x)); ChangeTelegraphy(__instance, "FINISHED", 1.4f); } else { FsmUtil.GetFirstActionOfType<SetVelocityByScale>(control, "Rising Slash").ySpeed = FsmFloat.op_Implicit(((Component)HeroController.instance).transform.position.y * 3f); } break; } case "Rising Slash Followup": if (phase2) { if (!risingSlashedOnce) { risingSlashedOnce = true; control.SetState("Near Air Attack"); } else { risingSlashedOnce = false; control.SetState("Far Air Attack"); } } break; case "Dive Antic": ChangeTelegraphy(__instance, "FINISHED", 0.3f); ((MonoBehaviour)control).StartCoroutine(diveTurnAround(((Component)control).transform.position.x)); break; case "Dive Land": if (phase2 && !diveFollowUpSelected) { diveFollowUpSelected = true; string[] array2 = new string[3] { "Rapid Slash Dash", "Dash Slash 1", "Windslash G" }; ((MonoBehaviour)control).StartCoroutine(scheduleNextState(0.2f, Extensions.GetRandomElement<string>(array2), disableDiveFollowup: true)); } if (risingSlashing) { risingSlashing = false; } break; case "WindSlash Type": FsmUtil.GetLastActionOfType<SetFloatValue>(control, "Windslash A").floatValue = FsmFloat.op_Implicit(0f - (60f - ((Component)HeroController.instance).transform.position.y * 3f)); break; case "WindSlash Antic": if (((Component)control).transform.position.y < 7f) { ChangeTelegraphy(__instance, "FINISHED", 0.4f); } else if (phase2) { ChangeTelegraphy(__instance, "FINISHED", 0.6f); } break; case "WindSlash": { bool flag = ((Component)control).transform.position.y > 10f; if (phase2 && windSlashedOnce) { windSlashedOnce = false; ((MonoBehaviour)control).StartCoroutine(scheduleNextState(0.2f, flag ? "Dive Dir" : "DashStab Antic")); } else if (flag && !windSlashedOnce) { windSlashedOnce = true; } break; } case "DashStab Antic": if (phase2) { if (dashStabbedOnce) { ChangeTelegraphy(__instance, "FINISHED", 0.5f); FsmUtil.GetFirstActionOfType<SetVelocityByScale>(control, "DashStab Dash").speed = FsmFloat.op_Implicit(-200f); } else { ChangeTelegraphy(__instance, "FINISHED", 0.1f); FsmUtil.GetFirstActionOfType<SetVelocityByScale>(control, "DashStab Dash").speed = FsmFloat.op_Implicit(-150f); } } else { ChangeTelegraphy(__instance, "FINISHED", 0.5f); } break; case "DashStab Dash": ChangeTelegraphy(__instance, "FINISHED", phase2 ? 0.02f : 0.05f); break; case "Stab 1": if (phase2) { ((MonoBehaviour)control).StartCoroutine(delayedTurnAround(0.15f)); if (dashStabbedOnce) { ((MonoBehaviour)control).StartCoroutine(scheduleNextState(0.2f, "DashStab Antic")); dashStabbedOnce = false; } else { dashStabbedOnce = true; } } break; case "CrossSlash Recoil": { string[] array = new string[2] { "Dive Dir", "Windslash A" }; if (!risingSlashing) { ((MonoBehaviour)control).StartCoroutine(scheduleNextState(phase2 ? 0.2f : 0.1f, Extensions.GetRandomElement<string>(array))); } if (!phase2 && risingSlashing) { risingSlashing = false; } break; } case "Hornet Dead": if ((Object)(object)control != (Object)null) { deathReset(); } break; case "Parry Clash": isCrossStitching = true; if (phase2) { healthManager.IsInvincible = true; } ((MonoBehaviour)control).StartCoroutine(disableInvincibility()); break; } } public void FixedUpdate() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_005a: 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_0092: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) if (!enable) { return; } if (risingSlashing) { Vector3 position = ((Component)HeroController.instance).transform.position; if ((double)position.x > 51.62) { ((Component)HeroController.instance).transform.position = new Vector3(51.61f, position.y, position.z); } if ((double)position.x < 27.51) { ((Component)HeroController.instance).transform.position = new Vector3(27.525f, position.y, position.z); } } if (HeroController.instance.IsParrying() && !isCrossStitching && HeroController.instance.silkSpecialFSM.ActiveStateName != "Parry Stance") { if (stunCounter % 10 == 0 && stunCounter != 0) { HeroController.instance.AddSilk(PARRY_SILK_GAIN_MULTIPLIER, true); } if (healthManager.hp > PARRY_DAMAGE) { HealthManager obj = healthManager; obj.hp -= PARRY_DAMAGE; } else { healthManager.hp = 1; } stunCounter += PARRY_DAMAGE; if (stunCounter >= STUN_QUOTA && !phase2 && ((Component)control).transform.position.y < 8f && !risingSlashing) { control.SendEvent("STUN"); } healthManager.SpriteFlash.FlashEnemyHit(); } if (!phase2) { if (stunStates.Contains(control.ActiveStateName) && healthManager.IsInvincible) { healthManager.IsInvincible = false; } else if (!stunStates.Contains(control.ActiveStateName) && !healthManager.IsInvincible) { healthManager.IsInvincible = true; } } else if (healthManager.hp <= 0) { deathReset(); } } private static void ChangeTelegraphy(FsmState state, string eventName, float delay) { ((MonoBehaviour)control).StartCoroutine(ForceNextState(state, eventName, delay)); } private static void removeEventFromState(string stateName, string eventName) { FsmState val = ((IEnumerable<FsmState>)control.FsmStates).FirstOrDefault((Func<FsmState, bool>)((FsmState state) => state.Name == stateName)); val.Transitions = val.Transitions.Where((FsmTransition t) => t.EventName != eventName).ToArray(); } private static void deathReset() { gameObj = null; enable = false; control = null; healthManager = null; stunCounter = 0; phase2 = false; risingSlashedOnce = false; diveFollowUpSelected = false; risingSlashing = false; windSlashedOnce = false; dashStabbedOnce = true; isCrossStitching = false; } private static IEnumerator WaitAndPatch() { yield return (object)new WaitForSeconds(2f); Harmony.CreateAndPatchAll(typeof(Language_Get_Patch), (string)null); } private static IEnumerator disableInvincibility() { yield return (object)new WaitForSeconds(1.5f); isCrossStitching = false; if (phase2) { healthManager.IsInvincible = false; } } private static IEnumerator ForceNextState(FsmState state, string eventName, float delay) { yield return (object)new WaitForSeconds(delay); FsmTransition transition = ((IEnumerable<FsmTransition>)state.Transitions).FirstOrDefault((Func<FsmTransition, bool>)((FsmTransition t) => t.EventName == eventName)); if (transition != null) { control.SetState(transition.ToState); } } private static IEnumerator scheduleNextState(float delay, string state, bool disableDiveFollowup = false) { yield return (object)new WaitForSeconds(delay); control.SetState(state); if (disableDiveFollowup) { diveFollowUpSelected = false; } } private static IEnumerator FixRisingSlash(float delay, float startingX) { yield return (object)new WaitForSeconds(delay); float knightX = ((Component)control).transform.position.x; float hornetX = ((Component)HeroController.instance).transform.position.x; int sign = ((!((knightX - hornetX) * (knightX - startingX) > 0f)) ? 1 : (-1)); FsmUtil.GetFirstActionOfType<SetVelocityByScale>(control, "Rising Slash").speed = FsmFloat.op_Implicit(60f * (float)sign); } private static IEnumerator diveTurnAround(float startingX) { yield return (object)new WaitForSeconds(0.5f); float knightX = ((Component)control).transform.position.x; float hornetX = ((Component)HeroController.instance).transform.position.x; if (knightX > startingX) { if (hornetX < knightX) { Extensions.FlipLocalScale(((Component)control).transform, true, false, false); } } else if (hornetX > knightX) { Extensions.FlipLocalScale(((Component)control).transform, true, false, false); } } private static IEnumerator delayedTurnAround(float delay) { yield return (object)new WaitForSeconds(delay); Extensions.FlipLocalScale(((Component)control).transform, true, false, false); } } [HarmonyPatch(typeof(SpawnObjectFromGlobalPool), "OnEnter")] public static class Patch_SpawnObjectFromGlobalPool_OnEnter { private static readonly Vector3 CROSSSLASH = new Vector3(2.5f, 2.5f, 1f); private static readonly Vector3 PROJECTILE = new Vector3(2.25f, 2.2f, 1f); [HarmonyPostfix] private static void Postfix(SpawnObjectFromGlobalPool __instance) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)PrimedSentinel.control == (Object)null || (Object)(object)__instance.storeObject.Value == (Object)null) { return; } GameObject gameObject = __instance.storeObject.Value.gameObject; if (!((Object)(object)gameObject == (Object)null)) { Transform transform = gameObject.transform; if (((Object)transform).name.StartsWith("Song Knight CrossSlash")) { transform.localScale = CROSSSLASH; MakeProjectileRenderAboveWalls(__instance.storeObject.Value.gameObject); } else if (((Object)transform).name.StartsWith("Song Knight Projectile")) { transform.localScale = PROJECTILE; __instance.storeObject.Value.gameObject.GetComponent<Collider2D>().isTrigger = true; MakeProjectileIgnoreEnvironment(__instance.storeObject.Value.gameObject); RemoveProjectileWallEvents(__instance.storeObject.Value.gameObject); MakeProjectileRenderAboveWalls(__instance.storeObject.Value.gameObject); } } } private static void MakeProjectileIgnoreEnvironment(GameObject projectile) { Collider2D[] componentsInChildren = projectile.GetComponentsInChildren<Collider2D>(true); if (componentsInChildren == null || componentsInChildren.Length == 0) { return; } Collider2D[] array = componentsInChildren; foreach (Collider2D val in array) { int num = LayerMask.NameToLayer("Terrain"); if (num >= 0) { Physics2D.IgnoreLayerCollision(projectile.layer, num, true); } val.isTrigger = true; } } private static void MakeProjectileRenderAboveWalls(GameObject projectile) { tk2dSprite[] componentsInChildren = projectile.GetComponentsInChildren<tk2dSprite>(true); tk2dSprite[] array = componentsInChildren; foreach (tk2dSprite val in array) { ((tk2dBaseSprite)val).SortingOrder = 1000; } } private static void RemoveProjectileWallEvents(GameObject projectile) { PlayMakerFSM val = FSMUtility.LocateMyFSM(projectile, "Control"); FsmState[] fsmStates = val.FsmStates; foreach (FsmState val2 in fsmStates) { FsmTransition[] array = val2.Transitions.Where((FsmTransition t) => !t.EventName.Equals("WALL", StringComparison.OrdinalIgnoreCase)).ToArray(); if (array.Length != val2.Transitions.Length) { val2.Transitions = array; } } string[] array2 = new string[2] { "Wall End", "Floor?" }; foreach (string text in array2) { FsmState state = FsmUtil.GetState(val, text); if (state != null) { state.Transitions = Array.Empty<FsmTransition>(); state.Actions = Array.Empty<FsmStateAction>(); } } } } [HarmonyPatch(typeof(Language), "Get")] [HarmonyPatch(new Type[] { typeof(string), typeof(string) })] public static class Language_Get_Patch { private static void Postfix(string key, string sheetTitle, ref string __result) { if (key == "SONG_KNIGHT_SUPER") { __result = "The Last Sentinel"; } if (key == "SONG_KNIGHT_MAIN") { __result = "Auric Aegis"; } } } }