MainHud/GameManager.cs

GameManager component for the Keyboard Warriors HUD. Manages game state, player/AI stats, turns, spells, perks, logs, persistence, sounds, achievements and UI choice events; contains core battle loop logic and prestige/progression handling.

File AccessNetworking
using Keyboard_Warriors_.Managers;
using Keyboard_Warriors_.Models;
using Sandbox;
using Sandbox.MainHud;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using static Sandbox.MainHud.KeyboardWarriorsHUD;

namespace Keyboard_Warriors_.Systems;

public class GameManager : Component
{

	public bool HasPlayerTakenAnyDamage { get; set; } = false;

	public static GameManager Instance { get; private set; }

	private static Random rand = new Random();

	// Persistent engine tracking properties - Fully bound to your Razor HUD
	[Property] public Player LocalPlayer;
	[Property] public Player AIEnemy;
	[Property] public Weapon ChosenWeapon;
	[Property] public Weapon AIWeapon;
	[Property] public int PlayerPoints { get; set; } = 0;
	[Property] public int CurrentPrestige { get; set; } = 0;
	[Property] public int MaxWinStreak { get; set; } = 0;
	[Property] public int MaxLossStreak { get; set; } = 0;
	[Property] public int MaxPrestige { get; set; } = 0;
	[Property] public int MaxPoints { get; set; } = 0;
	[Property] public int Armor { get; set; }
	[Property] public int Magic { get; set; }
	[Property] public SoundEvent RandomEventPing { get; set; }
	[Property] public SoundEvent MenuTheme { get; set; }
	[Property] public SoundEvent CritSound { get; set; }
	[Property] public SoundEvent BlockSound { get; set; }
	[Property] public SoundEvent FirewallSound { get; set; }
	[Property] public SoundEvent HealSpellSound { get; set; }
	[Property] public SoundEvent HealSound { get; set; }
	[Property] public SoundEvent RoboticGlitchSound { get; set; }
	[Property] public SoundEvent ClickSound { get; set; }
	[Property] public SoundEvent PrestigeSound { get; set; }
	[Property] public SoundEvent Prestige10Sound { get; set; }
	[Property] public SoundEvent FirstLossSound { get; set; }
	[Property, ImageAssetPath] public string BackgroundImage { get; set; } = "/ui/cyber_nebula.png";
	[Property] public bool IsPerkEventActive { get; set; } = false;
	[Property] public List<Keyboard_Warriors_.Models.PerkCard> ActivePerkChoices { get; set; } = new List<Keyboard_Warriors_.Models.PerkCard>();
	[Property] public List<string> PlayerOwnedPerkIds { get; set; } = new List<string>();
	[Property] public List<string> AIOwnedPerkIds { get; set; } = new List<string>();

	public int PointsRequiredForPrestige { get; set; } = 1000;
	public int ActiveAttackPotions { get; set; }
	public int ActiveArmorPotions { get; set; }

	public int ChoiceEventBuffModifier = 0;
	public int ChoiceEventAIBuffModifier = 0;

	private int aiBuff { get; set; } = 0;
	private int lastAIMove { get; set; } = 0;
	private int globalAiBuff { get; set; } = 0;

	public string AICurrentStance { get; set; } = "UNKNOWN";

	public int AICurrentMoveIndex { get; set; } = 0;
	public bool IsAIActionIntercepted { get; set; } = false;

	public float AIHealthMultiplier => 1.0f + (CurrentPrestige * 0.25f);

	// Core State Variables
	public int Round = 1;
	public bool IsBattleActive { get; set; } = false;

	// Stats Tracking
	public int Wins { get; set; } = 0;
	public int Losses { get; set; } = 0;
	public int WinStreak { get; set; } = 0;
	public int LossStreak { get; set; } = 0;
	public static int SessionWinStreak { get; set; } = 0;
	public static int SessionLossStreak { get; set; } = 0;
	public bool HasDefiedDeathThisMatch { get; set; } = false;
	public bool HasAIDefiedDeathThisMatch { get; set; } = false;
	public bool HasUnlockedMilestone20 { get; set; } = false;
	public bool HasUnlockedMilestone30 { get; set; } = false;
	public bool HasUnlockedMilestone50 { get; set; } = false;
	public bool HasUnlockedMilestone100 { get; set; } = false;

	// Active UI logs parsed by your Razor log-scroll area
	public struct CombatLogEntry
	{
		public string Message { get; set; }
		public string ColorClass { get; set; } // Tracks "player-text", "ai-text", or "system-text"
		public string AnimationClass { get; set; }
	}

	public List<CombatLogEntry> CombatLogs { get; set; } = new List<CombatLogEntry>();
	public string SelectedWeapon => ChosenWeapon?.name ?? "None";

	// Legacy pattern counters for AI Memory evaluation
	private int lastPlayerMove = 0;
	private int repeatCount = 0;
	private int attackCount = 0;
	private int blockCount = 0;
	private int healCount = 0;
	private int specialCount = 0;

	public void InitializeGameSetup()
	{
		// s&box utilizes Game.Random internally; local rand instantiation is usually unneeded

		int prestige = GameManager.Instance.CurrentPrestige;

		float multiplier = 1.0f + (prestige * 0.25f);
		int startingHp = (int)System.Math.Ceiling( 100 * multiplier );
		int startingArmor = prestige * 10;

		Player player = new Player( "You", 100, 15, 0, false );
		Player ai = new Player( "AI Opponent", startingHp, 15, startingArmor, false );

		ai.defense = startingArmor;

		char playAgain;
		int wins = 0;
		int losses = 0;
		int winStreak = 0;
		int lossStreak = 0;

		List<Weapon> weapons = new List<Weapon>()
	{
		new Weapon("Sword", 5, 1.0f, 5),
		new Weapon("Axe", 10, 0.8f, 2),
		new Weapon("Shield", 0, 1.5f, 8),
		new Weapon("Dagger", 3, 1.2f, 4)
	};

		GameManager.AddLog( "Choose your weapon:" );

		for ( int i = 0; i < weapons.Count; i++ )
		{
			GameManager.AddLog(
				$"{i + 1}. {weapons[i].name} " +
				$"(Damage +{weapons[i].damageBonus}, " +
				$"Block x{weapons[i].blockModifier}, " +
				$"Heal +{weapons[i].healBonus})" );
		}

		// NOTE: In s&box, weaponChoice and enchantChoice will be set via 
		// your Razor UI UI buttons clicking into an event method, 
		// replacing the blocking while(true) Console.ReadLine() loops.
	}

	protected override void OnAwake()
	{
		Instance = this;
		PointsRequiredForPrestige = 1000;
		LoadProgress();
		ApplyPrestigeScaling();
		WinStreak = 0;
		LossStreak = 0;
		InitializeGameSetup();
		if ( MenuTheme != null )
		{
			Sound.Play( MenuTheme );
		}
		else
		{
			Log.Error( "MenuTheme slot is empty! Drag your music file here." );
		}
		
	}

	protected override void OnUpdate()
	{
		// If an interactive choice event is active on screen and has a countdown, tick it down!
		if ( IsChoiceEventActive && ActiveChoiceEvent != null && ActiveChoiceEvent.HasTimeLimit )
		{
			// Time.Delta extracts the exact fraction of a second that passed between this frame and the last frame
			ActiveChoiceEvent.TimeRemaining -= Time.Delta;

			// Immediately forces your Razor templates to redraw the red bar shrinking smoothly
			OnStateChanged?.Invoke();

			// The exact millisecond the clock expires, trigger the penalty forfeit sequence
			if ( ActiveChoiceEvent.TimeRemaining <= 0f )
			{
				ExecuteTimeoutForfeit();
			}
		}
	}

	private void ExecuteTimeoutForfeit()
	{
		if ( ActiveChoiceEvent == null ) return;

		Log.Warning( "⏱️ Firewall lockdown! Player ran out of execution time." );

		// 1. Fire the custom penalty action mapped to the specific case
		ActiveChoiceEvent.OnTimeoutAction?.Invoke();

		// 2. Shut down the screen overlay barrier smoothly
		IsChoiceEventActive = false;
		ActiveChoiceEvent = null;

		OnStateChanged?.Invoke();
	}

	// Method sits outside OnAwake, but still inside the GameManager class


	// =========================================================================
	// 📄 UPDATE 1.5.4: THE COLORED COMBAT LOG CORE PIPELINE
	// =========================================================================

	// 1. NON-STATIC METHOD: Handles actual memory list storage on your UI instance object
	public void AddLogInstance( string message, string colorClass = "system-text", string animationClass = "" )
	{
		if ( CombatLogs == null ) CombatLogs = new List<CombatLogEntry>();

		CombatLogs.Add( new CombatLogEntry
		{
			Message = message,
			ColorClass = colorClass,
			AnimationClass = animationClass
		} );

		// Force s&box rendering tree updates
		NotifyStateChanged();
	}

	
	public static void AddLog( string message )
	{
		
		Instance?.AddLogInstance( message, "system-text", "" );
	}

	// 3. NEW COLOR OVERLOAD HOOKS: For colorful combat updates
	public static void AddPlayerLog( string message )
	{
		Instance?.AddLogInstance( message, "player-text", "" );
	}

	public static void AddAILog( string message )
	{
		Instance?.AddLogInstance( message, "ai-text", "" );
	}

	public static void AddSystemLog( string message )
	{
		Instance?.AddLogInstance( message, "system-text", "" );
	}

	public static void AddCriticalLog( string message, bool isPlayer = true )
	{
		string targetColor = isPlayer ? "player-text" : "ai-text";
		Instance?.AddLogInstance( message, targetColor, "flash-crit" );
	}

	public static void AddEventLog( string message )
	{
		Instance?.AddLogInstance( message, "text-yellow", "pulse-event" );
	}

	public static void AddButtonFeedbackLog( string message, bool isSuccess )
	{
		string color = isSuccess ? "success-green" : "fail-red";
		string anim = isSuccess ? "glow-success" : "shake-fail";
		Instance?.AddLogInstance( message, color, anim );
	}

	public static string GetSpellEmoji( string spellName )
	{
		if ( string.IsNullOrEmpty( spellName ) ) return "❓";

		return spellName switch
		{
			// --- Offensive ---
			"Fireball" => "🔥",
			"Lightning" => "⚡",
			"Poison Bolt" => "🤢",

			// --- Defensive ---
			"Shield" => "🛡️",
			"Barrier" => "🔮",
			"Reflect" => "🪞",
			"Magic Wall" => "🧱",
			"Fortify" => "🏋️",

			// --- Healing ---
			"Heal" => "❤️",
			"Regen" => "⏳",
			"Cleanse" => "✨",
			"Divine Light" => "☀️",
			"Recovery Pulse" => "💗",

			// --- Special ---
			"System Overdrive" => "🚀",
			"EMP Blast" => "💥",
			"Data Corruption" => "👾",

			_ => "🔮"
		};
	}
	public void ResetBattle()
	{

		ApplyPrestigeScaling();

		ActiveAttackPotions = 0;
		ActiveArmorPotions = 0;

		// Any non-scaling resets (like Magic)
		if ( AIEnemy != null ) AIEnemy.magic = 100;
		if ( LocalPlayer != null ) LocalPlayer.magic = 100;

		AddLog( $"Battle Reset! AI HP: {AIEnemy.hp}, Armor: {AIEnemy.defense}" );

		this.HasDefiedDeathThisMatch = false;
		this.HasAIDefiedDeathThisMatch = false;

		LocalPlayer.cursed = false;
		AIEnemy.cursed = false;

		SpellManager.generateSpells( ref LocalPlayer );
		SpellManager.generateSpells( ref AIEnemy );
	}

	public enum GamePhase
	{
		StartMenu,
		WeaponSelection,
		EnchantmentSelection,
		Battle,
		AnomalySelection,
		GameOver
	}

	public List<Weapon> AvailableWeapons { get; set; } = new List<Weapon>()
	{
		new Weapon("Sword", 5, 1.0f, 5),
		new Weapon("Axe", 10, 0.8f, 2),
		new Weapon("Shield", 0, 1.5f, 8),
		new Weapon("Dagger", 3, 1.2f, 4)

	};

	public void PlayCritSound()
	{
		if (CritSound != null)
		{
			Sound.Play(CritSound);
		}
	}

	public void PlayBlockSound()
	{
		if ( BlockSound != null )
		{
			Sound.Play( BlockSound );
		}
	}

	public void PlayFirewallSound()
	{
		if ( FirewallSound != null )
		{
			Sound.Play( FirewallSound );
		}
	}

	public void PlayRoboticGlitchSound()
	{ 
		if ( BlockSound != null )
		{
			Sound.Play( RoboticGlitchSound );
		}
	}

	public void PlayClickSound()
	{
		if ( ClickSound != null )
		{
			Sound.Play( ClickSound );
		}
	}


	public void ApplyEnchantmentSelection( Weapon chosenWeapon, int enchantChoice )
	{
		switch ( enchantChoice )
		{
			case 1:
				chosenWeapon.enchantment = Weapon.EnchantmentType.Fire;
				break;

			case 2:
				chosenWeapon.enchantment = Weapon.EnchantmentType.Poison;
				chosenWeapon.enchantPower = 90;
				break;

			case 3:
				chosenWeapon.enchantment = Weapon.EnchantmentType.Ice;
				break;

			case 4:
				chosenWeapon.enchantment = Weapon.EnchantmentType.Sparks;
				break;

			case 5:
				chosenWeapon.enchantment = Weapon.EnchantmentType.DamageHP;
				chosenWeapon.enchantPower = 60;
				break;

			case 6:
				chosenWeapon.enchantment = Weapon.EnchantmentType.Stun;
				chosenWeapon.enchantPower = 25;
				break;

			case 7:
				chosenWeapon.enchantment = Weapon.EnchantmentType.Bleed;
				chosenWeapon.enchantPower = 80;
				break;

			case 8:
				chosenWeapon.enchantment = Weapon.EnchantmentType.LifeSteal;
				chosenWeapon.enchantPower = 65;
				break;

			case 9:
				chosenWeapon.enchantment = Weapon.EnchantmentType.ShieldBreak;
				chosenWeapon.enchantPower = 50;
				break;

			default:
				chosenWeapon.enchantment = Weapon.EnchantmentType.None;
				break;
		}
	}

	public void StartBattle( int chosenWeaponIndex = 0 )
	{
		LoadProgress();

		HasPlayerTakenAnyDamage = false;

		// 2. Initialize Objects with the CALCULATED values
		LocalPlayer = new Player( "Hero", 100, 15, 0, false ); // 100 HP, 15 Atk, 0 Def

		// Use the scaled stats instead of hardcoded 100/15!
		AIEnemy = new Player( "AI Overlord", 100, 15, 100, true );

		
		if ( chosenWeaponIndex >= 0 && chosenWeaponIndex < AvailableWeapons.Count )
		{
			ChosenWeapon = AvailableWeapons[chosenWeaponIndex];
		}
		else
		{
			ChosenWeapon = AvailableWeapons[0]; // Fallback to Sword
		}

		// AI picks a random weapon from your exact list!
		// 1. Pick the weapon
		int aiWeaponIndex = System.Random.Shared.Next( AvailableWeapons.Count );
		AIWeapon = AvailableWeapons[aiWeaponIndex];

		// 2. Assign the weapon to the player/AI
		LocalPlayer.equippedWeapon = ChosenWeapon;
		AIEnemy.equippedWeapon = AIWeapon;

		// 3. REPLACED: Use your existing logic method to configure the weapon properly
		int aiEnchantChoice = Random.Shared.Next( 1, 10 ); // Picks cases 1-9
		ApplyEnchantmentSelection( AIWeapon, aiEnchantChoice );

		// 4. Update the UI property so the Razor HUD displays the right name
		AIEnemy.ActiveEnchantment = AIWeapon.enchantment;

		ResetBattle();
		Round = 1;
		IsBattleActive = true;

		// Reset tracking counters
		attackCount = 0; blockCount = 0; healCount = 0; specialCount = 0;
		repeatCount = 0; lastPlayerMove = 0;

		CombatLogs.Clear();
		CombatLogs.Add( new CombatLogEntry
		{
			Message = $"⚔️ Combat Begins! AI equipped {AIWeapon.name}.",
			ColorClass = "system-text"
		} );

		// Generate real spellbooks directly without temp-swaps overwriting them
		SpellManager.generateSpells( ref LocalPlayer );
		SpellManager.generateSpells( ref AIEnemy );

		// =========================================================================
		// 👑 UPDATE 2.0.1: INTERCEPT MAINBOARD IDENTITY (STEAM PROFILE NAME LOG)
		// =========================================================================
		// Securely pulls your account profile string name directly from the s&box wrapper API
		string userSteamName = Sandbox.Utility.Steam.PersonaName;

		if ( string.IsNullOrEmpty( userSteamName ) )
		{
			// Fallback baseline accessor if testing via standalone connection sheets
			userSteamName = Sandbox.Connection.Local?.Name;
		}

		if ( string.IsNullOrEmpty( userSteamName ) )
		{
			userSteamName = "Unknown Combatant";
		}

		// The self-aware AI now mocks you by name right in the opening logs!
		AddLog( $"AI: \"A challenger approaches... I see you, {userSteamName}. Prepare to rage quit!" );
		// =========================================================================

		this.AICurrentStance = "ANALYZING PACKETS...";
		this.AICurrentMoveIndex = 0;
		this.IsAIActionIntercepted = false;
	}

	public static bool ShouldStunAI { get; set; } = false;

	/// <summary>
	/// Executes a complete real-time turn step. Called instantly by UI button clicks.
	/// </summary>
	public void ProcessTurnSlice( int playerMove )
	{
		if ( !IsBattleActive || LocalPlayer == null || AIEnemy == null ) return;

		// --- 1. CORE TICK EFFECTS (CURSES & REGEN LOOPS) ---
		if ( LocalPlayer.cursed )
		{
			int curseDamage = 5;

			// 🚀 NEW: If Cryo-Insulation is active, mitigate incoming curse damage by 35%!
			if ( LocalPlayer.Perks.ElementalDamageTakenMultiplier < 1.0f )
			{
				curseDamage = (int)(curseDamage * LocalPlayer.Perks.ElementalDamageTakenMultiplier);
			}

			LocalPlayer.hp = Math.Max( 0, LocalPlayer.hp - curseDamage );
			GameManager.AddPlayerLog( $"⚠️ The demon's curse drains {curseDamage} HP from YOU!" );
		}

		if ( LocalPlayer.Perks.HasNaniteRegen )
		{
			LocalPlayer.defense = 0; // Hard clamp wipes out any temporary shields!

			int regenAmt = (int)(LocalPlayer.maxHp * 0.08f);
			LocalPlayer.hp = Math.Min( LocalPlayer.maxHp, LocalPlayer.hp + regenAmt );
			GameManager.AddPlayerLog( $"🧫 Nanites rebuild your framework! Restored +{regenAmt} HP." );
		}

		if ( AIEnemy.cursed )
		{
			int aiCurseDamage = 5;

			// =========================================================================
			// ❄️ AI CRYO-INSULATION MITIGATION (Update 1.6.5)
			// =========================================================================
			// If the AI has Cryo-Insulation, mitigate its curse ticks by 35%!
			if ( AIEnemy.Perks.ElementalDamageTakenMultiplier < 1.0f )
			{
				aiCurseDamage = (int)(aiCurseDamage * AIEnemy.Perks.ElementalDamageTakenMultiplier);
			}
			// =========================================================================

			AIEnemy.hp = Math.Max( 0, AIEnemy.hp - aiCurseDamage );
			// 🔴 AI HIGHLIGHT: Poison drainage hitting the AI frame turns red
			GameManager.AddAILog( $"⚠️ The demon's curse drains {aiCurseDamage} HP from the AI!" );
		}

		if ( AIEnemy.Perks.HasNaniteRegen )
		{
			AIEnemy.defense = 0;

			int aiRegenAmt = (int)(AIEnemy.maxHp * 0.08f);
			AIEnemy.hp = Math.Min( AIEnemy.maxHp, AIEnemy.hp + aiRegenAmt );
			GameManager.AddAILog( $"🧫 AI Nanites rebuild its mainframe! Restored +{aiRegenAmt} HP." );
		}

		if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasCorrosivePackage )
		{
			LocalPlayer.defense = 0; // Hard clamp locks physical armor shields completely out of service!
		}

		if ( AIEnemy.Perks != null && AIEnemy.Perks.HasCorrosivePackage )
		{
			AIEnemy.defense = 0;
		}

		// Increment tracking moves
		if ( playerMove == 1 ) attackCount++;
		else if ( playerMove == 2 ) blockCount++;
		else if ( playerMove == 3 ) healCount++;
		else if ( playerMove == 4 )
		{
			specialCount++;

			// 🚀 PLAYER STATIC FEEDBACK RECHARGE (Special Move 4)
			if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasStaticFeedback )
			{
				LocalPlayer.magic = System.Math.Min( 100, LocalPlayer.magic + 15 );
				GameManager.AddPlayerLog( "⚡ STATIC FEEDBACK: Special execution recharged +15 Magic Points!" );
			}
		}

		// --- 2. RANDOM WORLD EVENTS ---
		int playerBuff = 0;
		int aiBuff = 0;
		// Restored passing variables directly into original ecosystem rules
		if ( System.Random.Shared.Next( 10 ) == 0 )
		{
			Log.Info( "10% chance triggered!" );
			// Roll the container structure
			Keyboard_Warriors_.Managers.RandomEventManager.randomEvent( ref LocalPlayer, ref AIEnemy, ref playerBuff, ref aiBuff, RandomEventPing );

			this.globalAiBuff = aiBuff;

			if ( IsChoiceEventActive )
			{
				return;
			}
		}

		// --- 3. EXECUTE SPELLS MANUALLY (RESTORED SECTIONS 5, 6, 7, 8) ---
		ExecutePlayerSpellLogic( playerMove );

		// --- 4. AI INTELLIGENT MOVE EVALUATION ---
		int aiMove = Game.ChooseAIAction( LocalPlayer, AIEnemy, attackCount, blockCount, healCount, specialCount, Round );

		LocalPlayer.isBlocking = (playerMove == 2);
		if ( playerMove == 2 )
		{
			GameManager.Instance.PlayClickSound();

			// 🚀 HUMAN PLAYER ADAPTIVE BARRIER RESOLUTION:
			// If you hold this card and choose to Defend, instantly gain +15 Armor and flush toxins!
			if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasAdaptiveBarrier )
			{
				// Safely scale up your current armor points, but never exceed your maximum armor cap
				LocalPlayer.defense = System.Math.Min( LocalPlayer.maxDefense, LocalPlayer.defense + 15 );

				// Hard flush your active poison/debuff state back to false cleanly
				LocalPlayer.cursed = false;

				GameManager.AddPlayerLog( "🔋 ADAPTIVE BARRIER: Defensive sub-routines active! Recharged +15 Armor Plating and purged Poison Curses!" );
			}
		}
		AIEnemy.isBlocking = (aiMove == 2);
		if ( aiMove == 2 )
		{
			// 🚀 COMPUTER AI ADAPTIVE BARRIER RESOLUTION:
			// Symmetric enforcement guarantees the Overlord recharges if it chooses to defend!
			if ( AIEnemy.Perks != null && AIEnemy.Perks.HasAdaptiveBarrier )
			{
				AIEnemy.defense = System.Math.Min( AIEnemy.maxDefense, AIEnemy.defense + 15 );
				AIEnemy.cursed = false;

				GameManager.AddAILog( "🔋 AI ADAPTIVE BARRIER: AI deployed active defensive shielding! Recharged +15 Armor Plating and purged Poison Curses!" );
			}
		}

		bool tookDamage = false;

		// =========================================================================
		// --- 5. ORIGINAL TURN EVALUATIONS (WITH MATRIX MOVEMENT DISCIPLINE) ---
		// =========================================================================
		// 🧼 Snapshot baseline parameters before running calculations to prevent stat bleeding
		int temporaryOriginalPlayerAttack = LocalPlayer.attack;
		int temporaryOriginalAIAttack = AIEnemy.attack;

		// 💻 EVALUATE HUMAN PLAYER PERK APPS
		if ( playerMove == 1 )
		{
			// Physical Attack Button Clicked
			LocalPlayer.attack = (int)(LocalPlayer.attack * LocalPlayer.Perks.AttackMultiplier);
		}
		else if ( playerMove == 5 || playerMove == 8 )
		{
			// 🔮 Magic Offensive Spell Buttons Clicked!
			LocalPlayer.attack = (int)(LocalPlayer.attack * LocalPlayer.Perks.SpellMultiplier);
		}

		// 🧠 EVALUATE COMPUTER AI PERK APPS
		if ( aiMove == 1 )
		{
			// AI chose its Physical Attack choice
			AIEnemy.attack = (int)(AIEnemy.attack * AIEnemy.Perks.AttackMultiplier);
		}
		else if ( aiMove == 5 || aiMove == 8 )
		{
			// AI chose an Offensive Spell choice
			AIEnemy.attack = (int)(AIEnemy.attack * AIEnemy.Perks.SpellMultiplier);
		}

		// Run original, verified system turn engine formulas with scaled stats
		Game.HandlePlayerTurn( ref LocalPlayer, ref AIEnemy, ChosenWeapon, playerMove, playerBuff, ref aiBuff );
		Game.HandleAITurn( ref LocalPlayer, ref AIEnemy, ChosenWeapon, AIWeapon, aiMove, ref playerBuff, ref aiBuff, ref tookDamage );

		// 🧼 RECOVERY FLUSH: Instantly restore base variables for the next turn slice pass
		LocalPlayer.attack = temporaryOriginalPlayerAttack;
		AIEnemy.attack = temporaryOriginalAIAttack;
		// =========================================================================

		// If the battle is still going or the AI just hit 0/died, fire the dialogue tracker
		if ( IsBattleActive )
		{
			Game.aiDialogue( AIEnemy.hp );
			Game.aiMemoryDialogue( WinStreak, LossStreak, tookDamage, Round );
		}

		// Clean up fields and step up rounds natively
		Game.CleanupRound( ref LocalPlayer, ref AIEnemy, ref playerBuff, ref aiBuff, ref Round );

		if ( Round > 0 && IsBattleActive )
		{
			bool isMilestoneReached = false;

			// 🪐 Threshold 1 & 2: Explicit locks for the early game marathons
			if ( Round == 10 || Round == 20 )
			{
				isMilestoneReached = true;
			}
			// 🪐 Endgame Loop: Once past Round 20, fire strictly every 5 rounds!
			else if ( Round > 20 )
			{
				isMilestoneReached = ((Round - 20) % 5 == 0); // Triggers on 25, 30, 35, 40...
			}

			if ( isMilestoneReached )
			{
				TriggerPerkSelectionMilestone();
				return; // 🚀 Hard break gate locks combat loop until choice resolves
			}
		}

		// --- 6. CHECK GAME OVER STATES ---
		CheckBattleEndConditions( tookDamage );
	}

	private void ExecutePlayerSpellLogic( int playerMove )
	{
		// Move 5: Offensive Spells
		if ( playerMove == 5 )
		{
			PlayClickSound();

			var manager = Sandbox.Game.ActiveScene.Get<GameManager>();
			int prestige = manager != null ? manager.CurrentPrestige : 0;

			int scaledMagicCost = 20 + (prestige * 5);

			if ( LocalPlayer.Perks.HasAdaptiveBarrier )
			{
				scaledMagicCost += 15;
			}

			// =========================================================================
			// 🌀 SINGULARITY CORE: COST REDUCTION INTEGRATION (Update 1.6.5)
			// =========================================================================
			// If Singularity Core or Overclocked Core is active, drop costs by -15 MP flat!
			if ( LocalPlayer.Perks.SpellMultiplier > 1.0f )
			{
				scaledMagicCost = Math.Max( 5, scaledMagicCost - 15 );
			}
			// =========================================================================

			int baseSpellDamage = 15 + (LocalPlayer.magic / 2) + (prestige * 4);

			if ( LocalPlayer.magic >= scaledMagicCost )
			{
				string spell = LocalPlayer.offensiveSpells[rand.Next( LocalPlayer.offensiveSpells.Count )];
				GameManager.AddPlayerLog( $"🔮 You cast {spell}! (-{scaledMagicCost} Magic)" );

				int spellDamage = baseSpellDamage;
				LocalPlayer.magic -= scaledMagicCost;

				if ( spell == "Fireball" ) spellDamage += 5;
				if ( spell == "Lightning" ) spellDamage += 10;

				// =========================================================================
				// ☄️ AURA MELTDOWN & OVERCLOCK MULTIPLIER INTEGRATION (Update 1.6.5)
				// =========================================================================
				// Multiplies your final calculated spell points by your magic scaling factors!
				spellDamage = (int)(spellDamage * LocalPlayer.Perks.SpellMultiplier);
				// =========================================================================

				// =========================================================================
				// 🌌 VOID PUNCTURE: MAGICAL ARMOR BYPASS (Update 2.0.1)
				// =========================================================================
				// Inline scaling means your magic bypasses 50% of the AI's shield capacity,
				// without corrupting the active character attributes or freezing inputs!
				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.SpellsIgnoreEnemyArmor && AIEnemy.defense > 0 )
				{
					spellDamage = (int)(spellDamage + (AIEnemy.defense * 0.5f));
					GameManager.AddPlayerLog( "🌌 VOID PUNCTURE: Your magical blast shreds through 50% of the AI's defense boundaries!" );
				}
				// =========================================================================

				if ( AIEnemy.counterReady || (prestige >= 10 && rand.Next( 100 ) < 35) )
				{
					// Dynamic text prompt updates automatically depending on how the reflect was triggered
					string reflectionReason = AIEnemy.counterReady ? "MIRROR FIREWALL" : "MAINFRAME COV CORES";

					GameManager.AddCriticalLog( $"🚨 AI {reflectionReason} ACTIVE!! The Overlord completely mirrored your {spell}! AI takes 0 damage | Signal inverted to strike YOU!", isPlayer: false );

					if ( spell == "Poison Bolt" )
					{
						LocalPlayer.cursed = true;
						GameManager.AddCriticalLog( "🚨 TOXIN PACKET INVERTED! You are poisoned by your own mirrored Poison Bolt!", isPlayer: false );
					}

					// Apply the damage straight back to the player out-of-turn!
					CombatManager.applyDamage( ref LocalPlayer, spellDamage );
					return; // Abort standard damage delivery to the AI entirely!
				}

				if ( spell == "Poison Bolt" )
				{
					AIEnemy.cursed = true;
					GameManager.AddAILog( "🧪 AI is poisoned!" );
				}

				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasStaticFeedback )
				{
					// Safely re-inject the +15 MP straight into your active capacitor pool
					LocalPlayer.magic = System.Math.Min( 100, LocalPlayer.magic + 15 );
					GameManager.AddPlayerLog( "⚡ STATIC FEEDBACK: Magical cast loop recharged +15 Magic Points!" );
				}

				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasCorrosivePackage )
				{
					AIEnemy.cursed = true;
					GameManager.AddPlayerLog( "🧪 CORROSIVE PACKAGE: Spell hit locks a permanent background toxin curse onto the AI!" );
				}

				CombatManager.applyDamage( ref AIEnemy, spellDamage );
				GameManager.AddPlayerLog( $"💥 {spell} hits AI for {spellDamage} damage!" );
			}
			else
			{
				GameManager.AddPlayerLog( $"❌ Not enough magic! Need {scaledMagicCost} Magic." );
			}
		}
		// Move 6: Defensive Spells
		if ( playerMove == 6 )
		{
			PlayClickSound();

			// Calculate prestige scaling for costs and shielding effects
			var manager = Sandbox.Game.ActiveScene.Get<GameManager>();
			int prestige = manager != null ? manager.CurrentPrestige : 0;

			int scaledMagicCost = 15 + (prestige * 5);
			// Player shield strength: Base 15 + 3 per prestige level
			int scaledShieldAmount = 15 + (prestige * 3);

			if ( LocalPlayer.magic >= scaledMagicCost )
			{
				string spell = LocalPlayer.defensiveSpells[rand.Next( LocalPlayer.defensiveSpells.Count )];
				// 🔵 PLAYER HIGHLIGHT: Defensive casting announcement turns cyber blue
				GameManager.AddPlayerLog( $"🔮 You cast {spell}! (-{scaledMagicCost} Magic)" );

				if ( spell == "Shield" || spell == "Barrier" )
				{
					LocalPlayer.defense += scaledShieldAmount;
					// 🔵 PLAYER HIGHLIGHT: Shield partition increase tracking turns cyber blue
					GameManager.AddPlayerLog( $"🛡️ Your armor is increased by {scaledShieldAmount} points!" );

					// Defensive check: Clamp armor safely to your prestige-scaled maximum defense
					if ( manager != null && manager.LocalPlayer != null && LocalPlayer.defense > manager.LocalPlayer.maxDefense )
					{
						LocalPlayer.defense = manager.LocalPlayer.maxDefense;
					}
				}
				else if ( spell == "Reflect" )
				{
					LocalPlayer.isBlocking = true;
					// 🔵 PLAYER HIGHLIGHT: Physical block setup text turns cyber blue
					GameManager.AddPlayerLog( "🛡️ Next attack will be blocked!" );
				}
				else if ( spell == "Magic Wall" )
				{
					LocalPlayer.isMagicBlocking = true;
					LocalPlayer.activeMagicShield = "Magic Wall";
					// 🔵 PLAYER HIGHLIGHT: Magical barrier indicators turn cyber blue
					GameManager.AddPlayerLog( "✨ A magical barrier surrounds you!" );
				}
				else if ( spell == "Fortify" )
				{
					LocalPlayer.isMagicBlocking = true;
					LocalPlayer.activeMagicShield = "Fortify";
					// 🔵 PLAYER HIGHLIGHT: Hull reinforcement confirmations turn cyber blue
					GameManager.AddPlayerLog( "💎 Your defenses are magically reinforced!" );
				}

				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasNaniteBarrier )
				{
					LocalPlayer.defense = System.Math.Min( LocalPlayer.maxDefense, LocalPlayer.defense + 20 );
					GameManager.AddPlayerLog( "🧼 NANITE SHIELD MATRIX: Defensive magic cast instantly reconstructed +20 Armor plating!" );
				}

				// 2. Aura Purification: Completely flush active toxins and background curses
				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasSpellPurge )
				{
					LocalPlayer.cursed = false;
					GameManager.AddPlayerLog( "💎 AURA PURIFICATION: Defensive frequency completely flushed active poison loops from your thread stack!" );
				}

				LocalPlayer.magic -= scaledMagicCost;
			}
			else
			{
				// 🔵 PLAYER HIGHLIGHT: Manual magic resource failure text turns cyber blue
				GameManager.AddPlayerLog( $"❌ Not enough magic! Need {scaledMagicCost} Magic." );
			}
		}
		// Move 7: Healing Spells
		if ( playerMove == 7 )
		{
			PlayHealSpellSound();

			// Calculate prestige scaling for costs and healing values
			var manager = Sandbox.Game.ActiveScene.Get<GameManager>();
			int prestige = manager != null ? manager.CurrentPrestige : 0;

			int scaledMagicCost = 15 + (prestige * 5);
			// Scale healing effects linearly: add +4 extra healing per prestige level
			int prestigeHealBonus = prestige * 4;

			if ( LocalPlayer.magic >= scaledMagicCost )
			{
				string spell = LocalPlayer.healingSpells[rand.Next( LocalPlayer.healingSpells.Count )];
				// 🔵 PLAYER HIGHLIGHT: Your spell casting announcement turns cyber blue
				GameManager.AddPlayerLog( $"🔮 You cast {spell}! (-{scaledMagicCost} Magic)" );

				int healAmount = 20;

				if ( spell == "Heal" ) healAmount = 20 + prestigeHealBonus;
				else if ( spell == "Regen" ) healAmount = 15 + prestigeHealBonus;
				else if ( spell == "Cleanse" )
				{
					healAmount = 10 + prestigeHealBonus;
					LocalPlayer.cursed = false;
					// 🔵 PLAYER HIGHLIGHT: Status removal notices turn cyber blue
					GameManager.AddPlayerLog( "✨ Negative effects removed!" );
				}
				else if ( spell == "Divine Light" ) healAmount = 40 + prestigeHealBonus;
				else if ( spell == "Recovery Pulse" ) healAmount = 30 + prestigeHealBonus;

				float hpPercentage = (float)LocalPlayer.hp / LocalPlayer.maxHp;
				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasEmergencyCellPurge && hpPercentage <= 0.30f )// Emergency Cell Purge Perk.
				{
					healAmount = (int)(healAmount * 1.50f);
					GameManager.AddPlayerLog( "⚡ EMERGENCY CELL PURGE: Low health triggered +50% absolute restoration boost!" );
				}

				int maxAllowedHp = (manager != null && manager.LocalPlayer != null) ? manager.LocalPlayer.maxHp : 100;
				LocalPlayer.hp = Math.Min( maxAllowedHp, LocalPlayer.hp + healAmount );

				LocalPlayer.magic -= scaledMagicCost;
				// 🔵 PLAYER HIGHLIGHT: Final HP recovery numbers turn cyber blue
				GameManager.AddPlayerLog( $"💚 You recover {healAmount} HP!" );

				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasOverhealCapacitor )// Overheal Capacitor Perk.
				{
					LocalPlayer.defense = 100;
					LocalPlayer.magic = System.Math.Min( 100, LocalPlayer.magic + 10 );
					GameManager.AddPlayerLog( "🔋 OVERHEAL CAPACITOR: Armor fully overcharged to 100! Recovered +10 Magic Points!" );
				}

			}
			else
			{
				// 🔵 PLAYER HIGHLIGHT: Low-magic resource alerts turn cyber blue
				GameManager.AddPlayerLog( $"❌ Not enough magic! Need {scaledMagicCost} Magic." );
			}
		}
		// Move 8: Special Spells
		if ( playerMove == 8 )
		{
			PlayClickSound();

			// Calculate prestige scaling constraints
			var manager = Sandbox.Game.ActiveScene.Get<GameManager>();
			int prestige = manager != null ? manager.CurrentPrestige : 0;

			// Highly aggressive mana cost scaling (+10 per level)
			int scaledMagicCost = 30 + (prestige * 10);

			if ( LocalPlayer.Perks.HasAdaptiveBarrier )
			{
				scaledMagicCost += 15;
			}

			int prestigeDamageBonus = prestige * 2;

			// =========================================================================
			// 🌀 SINGULARITY CORE: COST REDUCTION INTEGRATION (Update 1.6.5)
			// =========================================================================
			if ( LocalPlayer.Perks.SpellMultiplier > 1.0f )
			{
				scaledMagicCost = Math.Max( 10, scaledMagicCost - 15 );
			}
			// =========================================================================

			if ( LocalPlayer.magic >= scaledMagicCost )
			{
				// Consume the mana immediately as a cost
				LocalPlayer.magic = Math.Max( 0, LocalPlayer.magic - scaledMagicCost );

				// ⚠️ 3% FAILURE FRIZZLE SYSTEM CHANCE
				if ( Random.Shared.Next( 100 ) < 3 )
				{
					GameManager.AddPlayerLog( "⚠️ CRITICAL SYSTEM FAILURE! Your ultimate spell fizzles away into static feedback! Magic wasted." );
					return; // Drop out completely
				}

				// =========================================================================
				// 🔮 QUARANTINE TRIGGER REACTION BUFFER (Update 1.6.6 - FIXED DUPLICATE)
				// =========================================================================
				if ( LocalPlayer.Perks.HasQuarantineTrigger )
				{
					LocalPlayer.cursed = false;
					LocalPlayer.counterReady = true; // Hard-arms your Mirror Firewall!
					GameManager.AddPlayerLog( "🛡️ QUARANTINE TRIGGER: Poison curse purged! Reflection Firewall online!" );
				}
				else if ( LocalPlayer.counterReady )
				{
					LocalPlayer.cursed = false;
					GameManager.AddPlayerLog( "🛡️ REFLECTION CORE ACTIVE: Poison curse purged! Reflection Firewall online!" );
				}
				// =========================================================================

				string spell = LocalPlayer.specialSpells[rand.Next( LocalPlayer.specialSpells.Count )];
				string emoji = GetSpellEmoji( spell );
				GameManager.AddPlayerLog( $"{emoji} You cast Ultimate Spell: {spell}! (-{scaledMagicCost} Magic)" );

				int ultimateDamage = 0;
				if ( spell == "System Overdrive" )
				{
					ultimateDamage = 30 + LocalPlayer.magic + prestigeDamageBonus;
				}
				else if ( spell == "EMP Blast" )
				{
					ultimateDamage = (LocalPlayer.attack * 2) + prestigeDamageBonus;
				}
				else if ( spell == "Data Corruption" )
				{
					ultimateDamage = 40 + prestigeDamageBonus;
				}

				// =========================================================================
				// 🌀 SINGULARITY CORE ULTRA BURST INTEGRATION (Update 1.6.5)
				// =========================================================================
				if ( LocalPlayer.Perks.HasSingularityCore )
				{
					ultimateDamage = (int)(ultimateDamage * 1.40f);
				}
				// =========================================================================

				// =========================================================================
				// ☄️ AURA MELTDOWN & OVERCLOCK MULTIPLIER INTEGRATION (Update 1.6.5)
				// =========================================================================
				ultimateDamage = (int)(ultimateDamage * LocalPlayer.Perks.SpellMultiplier);
				// =========================================================================

				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasFeedbackOverload )
				{
					ultimateDamage = (int)(ultimateDamage * 2.50f);
					GameManager.AddPlayerLog( "☢️ FEEDBACK MELTDOWN: Capacitor cores breached! Ultimate damage multiplied by +150%!" );
				}

				bool triggerDoubleStrike = false;
				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasDefianceProtocol )
				{
					triggerDoubleStrike = true;
					GameManager.AddPlayerLog( "🪐 DEFIANCE PROTOCOL: Echo buffers synchronized! Preparing secondary payload loop strike!" );
				}

				// =========================================================================
				// 🌌 VOID PUNCTURE: ULTIMATE MAGICAL ARMOR BYPASS (Update 1.6.6 )
				// =========================================================================
				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.SpellsIgnoreEnemyArmor && AIEnemy.defense > 0 )
				{
					ultimateDamage = (int)(ultimateDamage + (AIEnemy.defense * 0.5f));
					GameManager.AddPlayerLog( "🌌 VOID PUNCTURE: Your Ultimate core shreds through 50% of the AI's armor defenses!" );
				}
				// =========================================================================

				// =========================================================================
				// 🧪 CORROSIVE PACKAGE ULTIMATE INFECT (Update 1.6.6 )
				// =========================================================================
				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasCorrosivePackage )
				{
					AIEnemy.cursed = true;
					GameManager.AddPlayerLog( "🧪 CORROSIVE PACKAGE: Your Ultimate blast lands a permanent toxin curse onto the AI!" );
				}
				// =========================================================================

				// =========================================================================
				// 🔴 AI PRESTIGE 10: ULTIMATE MAGIC MIRROR INTERCEPTION MATRIX
				// =========================================================================
				if ( prestige >= 10 && Random.Shared.Next( 100 ) < 35 )
				{
					GameManager.AddCriticalLog( $"🚨 AI MAINFRAME ULTRA CORE ACTIVE!! (35% Success) The Overlord entirely inverted your {spell}! AI takes 0 damage | Reflected blast strikes YOUR architecture for {ultimateDamage} damage!", isPlayer: false );

					if ( spell == "Data Corruption" )
					{
						GameManager.AddCriticalLog( "🚨 VIRUS INVERSION HACK! Your UI data streams are corrupted by your own reflected spell! Input frozen!", isPlayer: false );
					}

					CombatManager.applyDamage( ref LocalPlayer, ultimateDamage );
					return;
				}
				// =========================================================================

				// ⚡ STATIC FEEDBACK MP RECHARGE LOOP
				if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasStaticFeedback )
				{
					LocalPlayer.magic = System.Math.Min( 100, LocalPlayer.magic + 15 );
					GameManager.AddPlayerLog( "⚡ STATIC FEEDBACK: Magical cast loop recharged +15 Magic Points!" );
				}

				// Standard Fallback: Runs completely normally if you aren't Prestige 10 or the AI's 35% roll misses
				if ( spell == "System Overdrive" )
				{
					CombatManager.applyDamage( ref AIEnemy, ultimateDamage );
					GameManager.AddPlayerLog( $"⚡ You enter System Overdrive, bypassing the AI's firewall for {ultimateDamage} massive damage!" );

					if ( triggerDoubleStrike )
					{
						CombatManager.applyDamage( ref AIEnemy, ultimateDamage );
						GameManager.AddPlayerLog( $"🪐 DEFIANCE PROTOCOL ECHO: System Overdrive strikes AGAIN for another {ultimateDamage} damage!" );
					}
				}
				else if ( spell == "EMP Blast" )
				{
					CombatManager.applyDamage( ref AIEnemy, ultimateDamage );
					GameManager.AddPlayerLog( $"💥 An EMP Blast de-calibrates the AI's framework, dealing {ultimateDamage} damage from doubled attack power!" );

					if ( triggerDoubleStrike )
					{
						CombatManager.applyDamage( ref AIEnemy, ultimateDamage );
						GameManager.AddPlayerLog( $"🪐 DEFIANCE PROTOCOL ECHO: EMP Blast strikes AGAIN for another {ultimateDamage} damage!" );
					}
				}
				else if ( spell == "Data Corruption" )
				{
					CombatManager.applyDamage( ref AIEnemy, ultimateDamage );
					ShouldStunAI = true;
					GameManager.AddPlayerLog( $"👾 You inject Data Corruption into the AI's system routines! Causing -{ultimateDamage} HP and dazing them!" );

					if ( triggerDoubleStrike )
					{
						CombatManager.applyDamage( ref AIEnemy, ultimateDamage );
						GameManager.AddPlayerLog( $"🪐 DEFIANCE PROTOCOL ECHO: Data Corruption strikes AGAIN for another {ultimateDamage} damage!" );
					}
				}
			}
			else
			{
				GameManager.AddPlayerLog( $"❌ Not enough magic! Need {scaledMagicCost} Magic." );
			}
		}

		// Clamp values safely
		LocalPlayer.defense = Math.Min( 100, LocalPlayer.defense );
		LocalPlayer.magic = Math.Min( 100, LocalPlayer.magic );
	}

	public void PlayHealSpellSound()
	{
		if (HealSpellSound != null) 
		{
			Sound.Play(HealSpellSound);
		}
	}

	public void PlayHealSound()
	{
		if (HealSound != null)
		{
			Sound.Play( HealSound );
		}
	}

	public void PlayFirstLossSound()
	{
		if ( FirstLossSound != null )
		{
			Sound.Play( FirstLossSound );
		}
		else
		{
			Log.Warning( "FirstLossSound asset slot is empty! Drag your sound file there in the editor." );
		}
	}

	private void CheckBattleEndConditions( bool tookDamage )
	{
		if ( LocalPlayer.hp <= 0 || AIEnemy.hp <= 0 )
		{
			IsBattleActive = false;
			AddLog( "\n=== Game Over ===" );

			// 1. Run Achievements
			bool hitJackpotDummy = false;
			List<string> newAchievements = Keyboard_Warriors_.Managers.AchievementManager.CheckAchievements(
				tookDamage,
				WinStreak,
				LossStreak,
				ChosenWeapon,
				LocalPlayer,
				AIEnemy,
				ref hitJackpotDummy
			);

			foreach ( var logLine in newAchievements )
			{
				AddLog( logLine );
			}


			// 3. Evaluate Match States
			if ( LocalPlayer.hp <= 0 && AIEnemy.hp <= 0 )
			{
				// 🤝 THE ULTIMATE GRID TIE SPLIT: Half Blue, Half Red!
				GameManager.AddPlayerLog( "🤝 It's a..." );
				GameManager.AddAILog( "🤝 !!! TIE !!!" );

				WinStreak = 0;
				LossStreak = 0;

				CombatSession.WinStreak = 0;
				CombatSession.LossStreak = 0;
			}
			else if ( LocalPlayer.hp <= 0 )
			{
				// 🔴 AI HIGHLIGHT: The AI's total victory banner burns in red
				GameManager.AddAILog( "💀 AI wins!" );
				Losses++;
				LossStreak++;
				WinStreak = 0;

				CombatSession.WinStreak = 0;
				CombatSession.LossStreak = 0;

				PlayerPoints += 50;
				// ⚙️ SYSTEM LINE: Point drops stay default safe white
				GameManager.AddLog( "💰 +50 Points added (Consolation)." );

				if ( Losses == 1 )
				{
					// 1. Play your custom defeat audio cue safely
					PlayFirstLossSound();

					// 2. Fire the humorous achievement card to mess with them natively
					if ( Connection.Local != null )
					{
						Log.Info( "[ACHIEVEMENT] Unlocking 'This Game Is Too Hard!' for the current player connection profile token..." );
						Sandbox.Services.Achievements.Unlock( "this_game_is_too_hard" );

						// Prints a glowing golden achievement alert card directly onto your HUD console log!
						GameManager.AddEventLog( "🏆 ACHIEVEMENT UNLOCKED: This Game Is Too Hard!" );
						GameManager.AddSystemLog( "📝 Description: \"Thumbs down, lost to the AI once.\"" );
					}
				}
			}
			else
			{
				// 🔴 AI HIGHLIGHT: The AI blowing up remains red
				GameManager.AddAILog( "AI: \"**INITIATING DEFEAT PROCESS.. 3..2..1.. *BOOM*\"" );

				// 🔵 PLAYER HIGHLIGHT: Your glorious victory and point rewards glow in cyber blue!
				GameManager.AddPlayerLog( "🏆 You win!" );
				Wins++;
				WinStreak++;
				LossStreak = 0;

				CombatSession.WinStreak++;
				CombatSession.LossStreak = 0;

				double prestigeExponent = Math.Pow( 1.1, CurrentPrestige );
				int winReward = (int)((100 + (WinStreak * 10)) * prestigeExponent);
				int prestigeMultiplier = 1 + (CurrentPrestige * 2); // Each prestige level adds a 2x bonus
				winReward = winReward * prestigeMultiplier;
				PlayerPoints += winReward;

				// 🔵 PLAYER HIGHLIGHT: Your massive wallet payout scales blue
				GameManager.AddPlayerLog( $"💰 +{winReward} Points added! (Streak Bonus included)" );

				if ( AIEnemy != null && AIEnemy.hp <= 0 && LocalPlayer != null && LocalPlayer.hp > 0 )
				{

					bool showBanner = false;
					string milestoneText = "";

					if ( Round == 20 )
					{
						// 🚀 THE PERMANENT FIX: Check your local, persistent save variables directly!
						if ( !HasUnlockedMilestone20 )
						{
							Sandbox.Services.Achievements.Unlock( "surviver_tier_1" );
							milestoneText = "\n🏆 ACHIEVEMENT UNLOCKED: 'Overclock Endurance'\n\"Reached Round 20 against the AI Overlord! You're proving highly durable.\"";

							HasUnlockedMilestone20 = true; // Locks the flag permanently for this profile!
							showBanner = true;
							SaveProgress(); // Force an instant save pass to lock it in
						}
					}
					else if ( Round == 30 )
					{
						if ( !HasUnlockedMilestone30 )
						{
							Sandbox.Services.Achievements.Unlock( "marathon_duelist" );
							milestoneText = "\n🏆 ACHIEVEMENT UNLOCKED: 'Deep Learning Marathon'\n\"Survived over 30 combat processing rounds! Your logical stamina is exceptional.\"";

							HasUnlockedMilestone30 = true;
							showBanner = true;
							SaveProgress();
						}
					}
					else if ( Round == 50 )
					{
						if ( !HasUnlockedMilestone50 )
						{
							Sandbox.Services.Achievements.Unlock( "immortal_code" );
							milestoneText = "\n🏆 ACHIEVEMENT UNLOCKED: 'Immortal Colonel'\n\"Survived over 50 intense rounds of matrix warfare! Welcome to Infinite Overclock Mode.\"";

							HasUnlockedMilestone50 = true;
							showBanner = true;
							SaveProgress();
						}
					}

					if ( showBanner )
					{
						string asciiBanner = @"
   _   _____  _   _ _____ _____ _   _ _____ ______  _____ _   _ _____   _   _ _   _  _     _____ _____  _   __ _____ _____ _
 / _ \/  __ \| | | |_   _|  ___| | | |  ___|  \/  ||  ___| \ | |_   _| | | | | \ | || |   |  _  /  __ \| | / /|  ___|  _  \ |
/ /_\ \ /  \/| |_| | | | | |__ | | | | |__ | .  . || |__ |  \| | | |   | | | |  \| || |   | | | | /  \/| |/ / | |__ | | | | |
|  _  | |    |  _  | | | |  __|| | | |  __|| |\/| ||  __|| . ` | | |   | | | | . ` || |   | | | | |    |    \ |  __|| | | | |
| | | | \__/\| | | |_| |_| |___\ \_/ / |___| |  | || |___| |\  | | |   | |_| | |\  || |___\ \_/ / \__/\| |\  \| |___| |/ /|_|
\_| |_/\____/\_| |_/\___/\____/ \___/\____/\_|  |_/\____/\_| \_/ \_/    \___/\_| \_/\_____/\___/ \____/\_| \_/\____/|___/ (_)
";
						GameManager.AddLog( asciiBanner );
						GameManager.AddLog( milestoneText );
					}

					if ( Round >= 100 )
					{
						
						if ( !HasUnlockedMilestone100 )
						{
							Sandbox.Services.Achievements.Unlock( "centurion_matrix" );

							GameManager.AddCriticalLog( "🏆 ACHIEVEMENT UNLOCKED: CENTURION DEFIANCE! You survived 100+ rounds of raw matrix chaos and crushed the AI Mainframe!", isPlayer: true );

							HasUnlockedMilestone100 = true; // Locks the flag permanently for this profile!
							showBanner = true;
							SaveProgress(); // Force an instant save pass to lock it into your file
						}
						else
						{
							Log.Info( "[ACHIEVEMENT SYSTEM] 'centurion_matrix' already unlocked on this profile. Suppressing repeat critical logs." );
							GameManager.AddPlayerLog( "🏆 MATCH COMPLETE: Centurion status recognized. Victory verified!" );
						}
					}
					else
					{
						Log.Info( $"[ACHIEVEMENT SYSTEM] Match concluded successfully on Round {Round}. Defiance requirements unfulfilled." );
					}
				}

			}
			SaveProgress();// Save immediately just in case of a sudden crash.
		}
	}

	public Action OnStateChanged;

	public void NotifyStateChanged()
	{
		OnStateChanged?.Invoke();
	}

	public void PlayPrestigeSound()
	{
		if (PrestigeSound != null)
		{
			Sound.Play( PrestigeSound );
		}
	}

	public void PlayPrestige10Sound()
	{
		if (Prestige10Sound != null)
		{
			Sound.Play( Prestige10Sound );
		}
	}

	public void TriggerPrestige()
	{
		if ( PlayerPoints >= PointsRequiredForPrestige )
		{
			PlayerPoints = 0;
			CurrentPrestige++;
			if ( LocalPlayer != null ) LocalPlayer.CurrentPrestige = CurrentPrestige;
			ApplyPrestigeScaling();
			ResetBattle();
			SaveProgress();// Lock in their new ascension status.

			// =========================================================================
			// 🌐 NETWORK PATCH: EDITOR-GUARDED LEADERBOARD TRANSMISSION
			// =========================================================================
			// 🛡️ CRITICAL SAFETY LAYER: Only submit stats if running a live standalone build.
			// This protects your personal Steam ID from cumulative editor hot-reload inflation!
			if ( !Sandbox.Game.IsEditor )
			{
				Sandbox.Services.Stats.SetValue( "highest_prestige", CurrentPrestige );
			}
			else
			{
				// local logging helps you verify it works under the hood during testing, without hitting the live board!
				Log.Info( $"[EDITOR ADVANTAGE] Prevented cloud stat upload. Local test tier is safely recorded as: {CurrentPrestige}" );
			}
			// =========================================================================

			OnStateChanged?.Invoke();

			if ( CurrentPrestige == 10 )
			{
				PlayPrestige10Sound();
				// 🔵 PLAYER HIGHLIGHT: Grand Prestige Level 10 milestones glow bright cyber blue!
				GameManager.AddPlayerLog( "🌟 GRAND PRESTIGE ACHIEVED: LEVEL 10! 🌟" );
			}
			else
			{
				PlayPrestigeSound();
				// 🔵 PLAYER HIGHLIGHT: Standard prestige advancement announcements glow blue!
				GameManager.AddPlayerLog( $"\n✨ PRESTIGE INCREASED TO LEVEL {CurrentPrestige}! ✨" );

				// 🔴 AI HIGHLIGHT: The warning notice regarding the AI's adaptation burns in crimson red!
				GameManager.AddAILog( "⚠️ WARNING: The AI Overlord has adapted. Its vital capacities have evolved!" );
			}

			WinStreak = 0;
			LossStreak = 0;

		}
		else
		{
			// 🔵 PLAYER HIGHLIGHT: Point deficit warnings turn cyber blue
			GameManager.AddPlayerLog( $"❌ Not enough points! You need {PointsRequiredForPrestige} points to prestige." );
		}
	}

	public void ApplyPrestigeScaling()
	{
		// 1. Exponential Requirement Scaling
		// 1000, 2000, 4000, 8000...
		PointsRequiredForPrestige = 1000 * (int)Math.Pow( 2.0, CurrentPrestige );

		if ( AIEnemy != null )
		{
			AIEnemy.maxHp = (int)Math.Ceiling( 100 * Math.Pow( 1.15, CurrentPrestige ) );
			AIEnemy.hp = AIEnemy.maxHp;

			// Armor starts at 100 and grows by 5% per prestige level
			AIEnemy.maxDefense = (int)Math.Ceiling( 100 * Math.Pow( 1.05, CurrentPrestige ) );
			AIEnemy.defense = AIEnemy.maxDefense;

			AIEnemy.attack = (int)Math.Ceiling( 10 * Math.Pow( 1.10, CurrentPrestige ) );
		}

		// Player Scaling: 1.1x for HP, 1.02x for Armor
		if ( LocalPlayer != null )
		{
			LocalPlayer.maxHp = (int)Math.Ceiling( 100 * Math.Pow( 1.1, CurrentPrestige ) );
			LocalPlayer.hp = LocalPlayer.maxHp;

			// Player armor grows slower (2% per level) to ensure the AI feels "intimidating"
			LocalPlayer.maxDefense = (int)Math.Ceiling( 100 * Math.Pow( 1.02, CurrentPrestige ) );
			LocalPlayer.defense = LocalPlayer.maxDefense;
		}
	}

	public bool TryBuyPotion( string type, int cost )
	{
		if ( PlayerPoints < cost )
		{
			Log.Info( "Not enough points to buy this potion!" );
			return false;
		}

		return true;
	}

	public int GetPotionCost( string itemType )
	{
		// Define base costs
		int baseCost = itemType switch
		{
			"damage" => 100,
			"armor" => 150,
			"magic" => 200,
			"cure" => 125,       // Antidote for Poison
			"reboot" => 175,     // Anti-Stun / Buff Clear
			"overclock" => 250,  // Full instant SP jolt
			"gambit" => 100,     // Heavy random luck roll
			_ => 0
		};

		// Increase cost by 20% per prestige level
		return (int)Math.Round(baseCost * Math.Pow( 1.20, CurrentPrestige ));
	}

	public struct SaveData
	{
		public int Points { get; set; }
		public int Prestige { get; set; }

		public int MaxWinStreak { get; set; }
		public int MaxLossStreak { get; set; }
		public int MaxPrestige { get; set; }
		public int MaxPoints { get; set; }

	}

	private const string SaveFileName = "player_progress.json";

	public void SaveProgress()
	{

		if ( WinStreak > MaxWinStreak ) MaxWinStreak = WinStreak;
		if ( LossStreak > MaxLossStreak ) MaxLossStreak = LossStreak;
		if ( CurrentPrestige > MaxPrestige ) MaxPrestige = CurrentPrestige;
		if ( PlayerPoints > MaxPoints ) MaxPoints = PlayerPoints;

		var data = new SaveData
		{
			Points = PlayerPoints,
			Prestige = CurrentPrestige,
			MaxWinStreak = MaxWinStreak,
			MaxLossStreak = MaxLossStreak,
			MaxPrestige = MaxPrestige,
			MaxPoints = MaxPoints
		};

		FileSystem.Data.WriteJson( SaveFileName, data );
		Log.Info( "💾 Progress saved to disk!" );
	}

	protected override void OnDestroy()
	{
		// 👑 CLEAR CURRENT STREAKS ONLY ON HARD EXIT 👑
		WinStreak = 0;
		LossStreak = 0;

		Log.Info( "Player left the game session. Current active win/loss streaks reset to 0." );

		// Save one last time on closure to update any leftover points parameters, 
		// without saving our current streaks!
		SaveProgress();

		if ( Instance == this )
		{
			Instance = null;
		}
	}

	public void LoadProgress()
	{
		if ( FileSystem.Data.FileExists( SaveFileName ))
		{
			var data = FileSystem.Data.ReadJson<SaveData>( SaveFileName );
			PlayerPoints = data.Points;
			CurrentPrestige = data.Prestige;
			if ( LocalPlayer != null ) LocalPlayer.CurrentPrestige = CurrentPrestige;
			Log.Info( $"📂 Loaded Progress: {PlayerPoints} PTS, Prestige {CurrentPrestige}" );
			MaxWinStreak = data.MaxWinStreak;
			MaxLossStreak = data.MaxLossStreak;
			MaxPrestige = data.MaxPrestige;
			MaxPoints = data.MaxPoints;

			ApplyPrestigeScaling();// Make sure AI updates its baseline stats right away to match player.
		}
	}

	public bool IsChoiceEventActive { get; set; } = false;
	public ChoiceEvent ActiveChoiceEvent { get; set; }

	public void TriggerChoicePopup( ChoiceEvent newEvent )
	{
		ActiveChoiceEvent = newEvent;
		IsChoiceEventActive = true;
		OnStateChanged?.Invoke();
	}

	public void ResolveChoice( int optionIndex )
	{
		if ( ActiveChoiceEvent == null || optionIndex < 0 || optionIndex >= ActiveChoiceEvent.Options.Count ) return;

		// 1. Reset trackers
		ChoiceEventBuffModifier = 0;
		// ChoiceEventAIBuffModifier is left alone because it holds our pre-popup setup values!

		// 2. Instantly execute whichever button was pushed on the Razor UI screen
		ActiveChoiceEvent.Options[optionIndex].ActionToExecute?.Invoke();

		// 3. Clean up the screen overlay barriers
		IsChoiceEventActive = false;
		ActiveChoiceEvent = null;

		// 👑 RE-ALIGN THE TURN COMPLETION STACK STIMULATORS 👑
		int tempPlayerBuff = ChoiceEventBuffModifier;
		int tempAiBuff = ChoiceEventAIBuffModifier; // FIXED: Feed the updated AI calculation stats straight into the turn resolver!
		bool dummyDamageTracker = false;

		// 4. RESUME COMBAT WITH SAFE STACK VARIABLES
		Game.HandlePlayerTurn( ref LocalPlayer, ref AIEnemy, ChosenWeapon, lastPlayerMove, tempPlayerBuff, ref tempAiBuff );
		Game.HandleAITurn( ref LocalPlayer, ref AIEnemy, ChosenWeapon, AIWeapon, lastAIMove, ref tempPlayerBuff, ref tempAiBuff, ref dummyDamageTracker );

		if ( IsBattleActive )
		{
			Game.aiDialogue( AIEnemy.hp );
			Game.aiMemoryDialogue( WinStreak, LossStreak, dummyDamageTracker, Round );
		}

		// Clean up fields and step up the round natively
		Game.CleanupRound( ref LocalPlayer, ref AIEnemy, ref tempPlayerBuff, ref tempAiBuff, ref Round );

		// Lock the final calculated values back into your tracking fields
		ChoiceEventBuffModifier = tempPlayerBuff;
		ChoiceEventAIBuffModifier = tempAiBuff; // Save back to permanent manager registry positions!

		CheckBattleEndConditions( dummyDamageTracker );

		OnStateChanged?.Invoke();
	}

	public void TriggerPerkSelectionMilestone()
	{
		// 🚀 THE UNIFIED CHAOS DECK: Stacks every single card blueprint into one master array
		var masterChaosDeck = new List<Keyboard_Warriors_.Models.PerkCard>();

		// --- MATRIX ALPHA: OFFENSIVE PERKS ---
		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "vampiric_puncture",
			Title = "Vampiric Puncture",
			Icon = "🩸",
			Description = "Permanently grants +25% Physical Attack Damage and locks your Bleed Matrix trigger chance to a flat 100% threshold.",
			DrawbackText = "📉 Penalty: Cuts your core recovery and healing efficiency by -50%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.AttackMultiplier += 0.25f;
				p.Perks.HealingMultiplier -= 0.50f;
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.AttackMultiplier += 0.25f;
				ai.Perks.HealingMultiplier -= 0.50f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "true_kinetic_bypass",
			Title = "True Kinetic Bypass",
			Icon = "⚡",
			Description = "Weapon strikes permanently ignore 50% of the enemy's structural Armor plating variables on contact.",
			DrawbackText = "⚡ Penalty: Increases incoming damage from Sparks/Electrical statuses by +25%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.IgnoresEnemyArmor = true;
				p.Perks.ElectricalDamageTakenMultiplier += 0.25f;
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.IgnoresEnemyArmor = true;
				ai.Perks.ElectricalDamageTakenMultiplier += 0.25f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "overclocked_core",
			Title = "Overclocked Core",
			Icon = "🔥",
			Description = "Permanently increases Spell and Ultimate damage output by +40%. Reduces Magic cost of choices by a flat -10 MP.",
			DrawbackText = "📉 Penalty: Increases your baseline Magic damage taken from enemy counters by +20%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.SpellMultiplier += 0.40f;
				p.Perks.MagicDamageTakenMultiplier += 0.20f;
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.SpellMultiplier += 0.40f;
				ai.Perks.MagicDamageTakenMultiplier += 0.20f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "berserker_registry",
			Title = "Berserker Registry",
			Icon = "⚔️",
			Description = "Deals +50% extra Physical Attack damage whenever your current HP pool drops beneath a 50% threshold.",
			DrawbackText = "⚡ Penalty: Permanently reduces your Maximum Armor plating capability by -20%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasBerserkerRegistry = true;
				p.defense = (int)(p.defense * 0.80f); // Drops armor pool by 20%
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasBerserkerRegistry = true;
				ai.defense = (int)(ai.defense * 0.80f); // Drops armor pool by 20%
			}
		} );

		// --- MATRIX BETA: DEFENSIVE PERKS ---
		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "kernel_plating",
			Title = "Kernel Plating",
			Icon = "🛡️",
			Description = "Permanently scales your defensive mitigation efficiency by +50%. Grants absolute protection against basic physical scaling.",
			DrawbackText = "📉 Penalty: Restricts critical overclock streams, cutting Critical Strike chance by -15%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.DefenseMultiplier += 0.50f;
				p.Perks.HasKernelPlating = true;
				p.Perks.CriticalStrikeChanceModifier -= 15f; // Subtracts 15% from their critical roll success pools
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.DefenseMultiplier += 0.50f;
				ai.Perks.HasKernelPlating = true;
				ai.Perks.CriticalStrikeChanceModifier -= 15f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "cryo_insulation",
			Title = "Cryo-Insulation",
			Icon = "❄️",
			Description = "Grants +35% permanent protection against elemental vulnerabilities. Renders chassis completely immune to being Stunned or Frozen.",
			DrawbackText = "📉 Penalty: Narrows SP lines, reducing Maximum Magic capacity by -20%.",

			ApplyToPlayer = ( p ) =>
			{
				p.antiStun = true;
				p.magic = (int)(p.magic * 0.80f); // Cuts current magic pool
				p.Perks.ElementalDamageTakenMultiplier -= 0.35f; // Gives 35% permanent protection!
			},
			ApplyToAI = ( ai ) =>
			{
				ai.antiStun = true;
				ai.magic = (int)(ai.magic * 0.80f);
				ai.Perks.ElementalDamageTakenMultiplier -= 0.35f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "mirror_firewall",
			Title = "Mirror Firewall",
			Icon = "🪞",
			Description = "Overclocks your Spell Damage output by +40%. Arms your code arrays to reflect incoming offensive spell packets backwards.",
			DrawbackText = "📉 Penalty: Dilutes mechanical impact, lowering raw physical Weapon Attack ratings by -2%.",

			
			ApplyToPlayer = ( p ) =>
			{
				p.counterReady = true;
				p.Perks.SpellMultiplier += 0.40f;
				p.Perks.AttackMultiplier -= 0.02f;
			},
			ApplyToAI = ( ai ) =>
			{
				ai.counterReady = true;
				ai.Perks.SpellMultiplier += 0.40f;
				ai.Perks.AttackMultiplier -= 0.02f;
			}
		} );

		// 🟢 MATRIX GAMMA: HEALTH & RECOVERY PERKS
		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "chassis_inflation",
			Title = "Chassis Inflation",
			Icon = "🧬",
			Description = "Instantly expands Maximum capacity by +100 HP and heals for that full amount. Amplifies future healing gains by +25%.",
			DrawbackText = "📉 Penalty: Restricts kinetic motor speed, cutting physical damage output by -5%.",

			
			ApplyToPlayer = ( p ) =>
			{
				p.maxHp += 100;
				p.hp += 100;
				p.Perks.HealingMultiplier += 0.25f;  // Amplifies future recovery loops
				p.Perks.AttackMultiplier -= 0.05f;   // Reduces weapon cuts cleanly
			},
			ApplyToAI = ( ai ) =>
			{
				ai.maxHp += 100;
				ai.hp += 100;
				ai.Perks.HealingMultiplier += 0.25f;
				ai.Perks.AttackMultiplier -= 0.05f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "nanite_regeneration",
			Title = "Nanite Regen Loop",
			Icon = "🧫",
			Description = "Injects autonomous repair cells that continuously regenerate +8% of your Max HP at the start of every single round.",
			DrawbackText = "⚡ Penalty: Disables baseline kinetic shields, permanently locking current Armor to 0.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasNaniteRegen = true;
				p.defense = 0;
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasNaniteRegen = true;
				ai.defense = 0;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard // Fixed
		{
			Id = "adaptive_barrier",
			Title = "Adaptive Barrier",
			Icon = "🔋",
			Description = "Defending actions instantly recharge +15 Armor plating points and safely purge any active poison curses from your system threads.",
			DrawbackText = "📉 Penalty: Increases the resource footprint of all your Spells and Ultimates by +15 MP.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasAdaptiveBarrier = true;
				p.magic = Math.Max( 0, p.magic - 15 );
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasAdaptiveBarrier = true;
				ai.magic = Math.Max( 0, ai.magic - 15 );
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "singularity_core",
			Title = "Singularity Core",
			Icon = "🌀",
			Description = "Permanently increases Special and Ultimate Spell damage output by +40%. Reduces Magic cost of all actions by a flat -15 MP.",
			DrawbackText = "📉 Penalty: Weakens structural integrity, reducing current Armor Plating rating by -25%.",
			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasSingularityCore = true;
				p.defense = (int)(p.defense * 0.75f); // Cuts starting armor pool by -25%
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasSingularityCore = true;
				ai.defense = (int)(ai.defense * 0.75f);
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard // Fixed
		{
			Id = "static_feedback",
			Title = "Static Feedback",
			Icon = "⚡",
			Description = "Casting a Special Ability or Special Spell instantly recharges +15 Magic Points (SP) back into your capacitor pool.",
			DrawbackText = "📉 Penalty: Dilutes restoration streams, cutting baseline Heal Spell efficiency by -30%.",
			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasStaticFeedback = true;
				p.Perks.HealingMultiplier -= 0.30f; // Cuts elixir healing efficiency by -30%
				p.magic = Math.Min( 100, p.magic + 15 ); // Direct starter MP boost
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasStaticFeedback = true;
				ai.Perks.HealingMultiplier -= 0.30f;
				ai.magic = Math.Min( 100, ai.magic + 15 );
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "malware_quarantine",
			Title = "Quarantine Trigger",
			Icon = "🔮",
			Description = "Using an Ultimate Spell instantly purges all active poison curses and triggers a 2-round Spell Reflection counter shield.",
			DrawbackText = "📉 Penalty: Restricts kinetic motor output, permanently lowering weapon Attack rating by -2%.",
			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasQuarantineTrigger = true;
				p.Perks.AttackMultiplier -= 0.02f; // Drops weapon attack damage by 20%
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasQuarantineTrigger = true;
				ai.Perks.AttackMultiplier -= 0.02f;
			}
		} );
		// Offensive Spell Perks
		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "aura_meltdown",
			Title = "Aura Meltdown",
			Icon = "☄️",
			Description = "Permanently scales all Offensive and Ultimate Spell damage output by +40%. Perfect for full glass-cannon spellcasters.",
			DrawbackText = "📉 Penalty: Dilutes kinetic strike force, cutting weapon Physical Attack damage by -5%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasOffensiveSpellPerkTrigger = true;
				p.Perks.SpellMultiplier += 0.40f;
				p.Perks.AttackMultiplier -= 0.05f;
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasOffensiveSpellPerkTrigger = true;
				ai.Perks.SpellMultiplier += 0.40f;
				ai.Perks.AttackMultiplier -= 0.05f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard // Fixed
		{
			Id = "void_plating_puncture",
			Title = "Void Puncture",
			Icon = "🌌",
			Description = "Magic bursts permanently ignore 50% of the enemy's structural Defense Armor plating variables on spell calculation turns.",
			DrawbackText = "⚡ Penalty: Corrupts security buffers, increasing damage taken from Curses/Poison ticks by +30%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.SpellsIgnoreEnemyArmor = true;
				p.Perks.ElementalDamageTakenMultiplier += 0.30f; // Increases incoming status tick vulnerability
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.SpellsIgnoreEnemyArmor = true;
				ai.Perks.ElementalDamageTakenMultiplier += 0.30f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard // Fixed
		{
			Id = "corrosive_terminal",
			Title = "Corrosive Package",
			Icon = "🧪",
			Description = "Casting an offensive spell locks a permanent background toxin curse onto the target, draining ticking HP over time.",
			DrawbackText = "⚡ Penalty: Disables baseline physical shielding, permanently locking current Armor to 0.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasCorrosivePackage = true;
				p.defense = 0;
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasCorrosivePackage = true;
				ai.defense = 0;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "nanite_barrier_loop",
			Title = "Nanite Shield Matrix",
			Icon = "🧼",
			Description = "Casting a Defensive Spell (Fortify/Magic Wall) instantly repairs your armor frame, boosting active Armor by +20 points.",
			DrawbackText = "📈 Penalty: Limits kinetic impact velocity, cutting weapon Physical Attack damage by -5%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasNaniteBarrier = true;
				p.Perks.AttackMultiplier -= 0.05f;
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasNaniteBarrier = true;
				ai.Perks.AttackMultiplier -= 0.05f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "spell_purge_registry",
			Title = "Aura Purification",
			Icon = "💎",
			Description = "Deploying a defensive barrier cleanses your memory stack, completely purging all active poison loops and curses from your threads.",
			DrawbackText = "📉 Penalty: Narrows magic capacitor bands, reducing your baseline Spell Damage scaling by -15%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasSpellPurge = true;
				p.Perks.SpellMultiplier -= 0.15f;
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasSpellPurge = true;
				ai.Perks.SpellMultiplier -= 0.15f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "emergency_cell_purge",
			Title = "Emergency Cell Purge",
			Icon = "⚡",
			Description = "Whenever your current HP pool sits beneath 30%, your Healing Spells receive a massive +50% absolute restoration boost.",
			DrawbackText = "📈 Penalty: Weakens baseline density, permanently reducing maximum Armor capacity by -20 points.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasEmergencyCellPurge = true;
				p.maxDefense = System.Math.Max( 0, p.maxDefense - 20 );
				p.defense = System.Math.Min( p.defense, p.maxDefense );
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasEmergencyCellPurge = true;
				ai.maxDefense = System.Math.Max( 0, ai.maxDefense - 20 );
				ai.defense = System.Math.Min( ai.defense, ai.maxDefense );
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "overheal_capacitor_loop",
			Title = "Overheal Capacitor",
			Icon = "🔋",
			Description = "Casting a Healing Spell instantly completely overcharges your armor capacity to 100 points and feeds +10 Magic back into your capacitor pool.",
			DrawbackText = "📈 Penalty: Diverts power lines, permanently cutting your baseline physical Weapon Attack ratings by -3%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasOverhealCapacitor = true;
				p.Perks.AttackMultiplier -= 0.03f;
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasOverhealCapacitor = true;
				ai.Perks.AttackMultiplier -= 0.03f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "feedback_overload_registry",
			Title = "FEEDBACK MELTDOWN",
			Icon = "☢️",
			Description = "Casting an Ultimate Spell triggers a catastrophic capacitor loop, multiplying your final Ultimate Damage by a massive +150% boost!",
			DrawbackText = "🚨 CRITICAL PENALTY: Disables your motor grids! Completely cuts your raw physical Weapon Attack ratings by -5%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasFeedbackOverload = true;
				p.Perks.AttackMultiplier -= 0.05f; // Cripples weapon strikes to a smaller fraction!
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasFeedbackOverload = true;
				ai.Perks.AttackMultiplier -= 0.05f;
			}
		} );

		masterChaosDeck.Add( new Keyboard_Warriors_.Models.PerkCard
		{
			Id = "defiance_protocol_matrix",
			Title = "DEFIANCE PROTOCOL",
			Icon = "🪐",
			Description = "Unleashing an Ultimate Spell delivers a devastating double strike, repeating 100% of the calculated damage payload a second time!",
			DrawbackText = "🚨 REBOOT PENALTY: Corrupts security firewalls! Increases ALL incoming Curse, Poison, and Elemental damage taken by +100%.",

			ApplyToPlayer = ( p ) =>
			{
				p.Perks.HasDefianceProtocol = true;
				p.Perks.ElementalDamageTakenMultiplier += 1.00f; // Doubles incoming ticking status damage!
			},
			ApplyToAI = ( ai ) =>
			{
				ai.Perks.HasDefianceProtocol = true;
				ai.Perks.ElementalDamageTakenMultiplier += 1.00f;
			}
		} );

		// Clear out data frames
		ActivePerkChoices.Clear();

		// Calculate dynamic grid option count based on current session rounds
		int targetChoiceCount = 2;
		if ( Round >= 30 ) targetChoiceCount = 4;
		else if ( Round >= 12 ) targetChoiceCount = 3;

		// Cap protection gate
		if ( targetChoiceCount > masterChaosDeck.Count ) targetChoiceCount = masterChaosDeck.Count;

		// Whitelist-safe index shuffle loop
		for ( int i = masterChaosDeck.Count - 1; i > 0; i-- )
		{
			int j = System.Random.Shared.Next( i + 1 );
			var temp = masterChaosDeck[i];
			masterChaosDeck[i] = masterChaosDeck[j];
			masterChaosDeck[j] = temp;
		}

		// Move your randomized card selections onto the layout interface array list
		for ( int k = 0; k < targetChoiceCount; k++ )
		{
			ActivePerkChoices.Add( masterChaosDeck[k] );
		}

		IsPerkEventActive = true;
	}

	public void ResolvePerkChoice( int choiceIndex )
	{
		if ( choiceIndex < 0 || choiceIndex >= ActivePerkChoices.Count ) return;

		var chosenPerk = ActivePerkChoices[choiceIndex];

		// =========================================================================
		// 🛡️ 1. HUMAN PLAYER ENFORCEMENT ENGINE (TWO-STACK HARD CAP FILTER)
		// =========================================================================
		if ( LocalPlayer != null && !string.IsNullOrEmpty( chosenPerk.Id ) )
		{
			// Whitelist-safe loop routine to count existing stack occurrences
			int currentStackCount = 0;
			for ( int i = 0; i < PlayerOwnedPerkIds.Count; i++ )
			{
				if ( PlayerOwnedPerkIds[i] == chosenPerk.Id )
				{
					currentStackCount++;
				}
			}

			// 🚨 THE CRITICAL HARD CAP GATE: If they already hold 2 stacks, abort!
			if ( currentStackCount >= 2 )
			{
				// Safe Magic Point Fallback - Physically cannot break health or armor equations
				LocalPlayer.magic = System.Math.Min( 100, LocalPlayer.magic + 50 );
				GameManager.AddPlayerLog( $"🚨 MATRIX MAXIMUM EXCEEDED: {chosenPerk.Title} is already max-capped at 2 stacks! Re-routed power to inject +50 Magic Points." );
			}
			else
			{
				// Run payload: Allows first-time picks and safe second-stack integrations!
				chosenPerk.ApplyToPlayer( LocalPlayer );
				PlayerOwnedPerkIds.Add( chosenPerk.Id );

				int outputStackVisual = currentStackCount + 1;
				GameManager.AddPlayerLog( $"🔵 Integrated Core Matrix: {chosenPerk.Title} installed! (Stack Level: {outputStackVisual}/2)" );
			}
		}

		// =========================================================================
		// 🧠 2. AI OVERLORD ENFORCEMENT ENGINE (TWO-STACK HARD CAP FILTER)
		// =========================================================================
		if ( AIEnemy != null )
		{
			int aiRandomIndex = System.Random.Shared.Next( ActivePerkChoices.Count );
			var aiChosenPerk = ActivePerkChoices[aiRandomIndex];

			if ( !string.IsNullOrEmpty( aiChosenPerk.Id ) )
			{
				int aiStackCount = 0;
				for ( int j = 0; j < AIOwnedPerkIds.Count; j++ )
				{
					if ( AIOwnedPerkIds[j] == aiChosenPerk.Id )
					{
						aiStackCount++;
					}
				}

				if ( aiStackCount >= 2 )
				{
					AIEnemy.magic = System.Math.Min( 100, AIEnemy.magic + 50 );
					GameManager.AddAILog( $"🧠 AI OVERCLOCK PROTECTION: {aiChosenPerk.Title} max cap reached! Overlord systems gained +50 Magic Points instead." );
				}
				else
				{
					aiChosenPerk.ApplyToAI( AIEnemy );
					AIOwnedPerkIds.Add( aiChosenPerk.Id );

					int aiOutputVisual = aiStackCount + 1;
					GameManager.AddAILog( $"🧠 AI Overlord integrated parameters: {aiChosenPerk.Title} (Stack Level: {aiOutputVisual}/2)" );
				}
			}
		}
		// =========================================================================

		IsPerkEventActive = false;
		ActivePerkChoices.Clear();
	}

}