MainHud/GameManager.cs

Central game manager for a turn-based cyber RPG duel game. Holds player and AI state, weapons, perks, rounds, combat logs, sounds, multiplayer turn sync, achievements and saved progress.

Messy CodeProcess ExecutionFile Access
🐞 PlayRoboticGlitchSound null-checks BlockSound, so the sound is skipped when BlockSound is unset and Sound.Play is called with a possibly null RoboticGlitchSound when it is set.
using Keyboard_Warriors_.Managers;
using Keyboard_Warriors_.Models;
using Sandbox;
using Sandbox.MainHud;
using System;
using System.Collections.Generic;
using System.Data;
using System.Numerics;
using System.Text;
using static Sandbox.MainHud.KeyboardWarriorsHUD;
using static Sandbox.Streamer;

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;

	// Multiplayer Mode 
	public enum PlayMode { SinglePlayer, Multiplayer }
	[Property, Sync] public PlayMode CurrentMode { get; set; } = PlayMode.SinglePlayer;

	// Symmetrical multiplayer player registers
	[Property, Sync] public Player PlayerOne { get; set; }
	[Property, Sync] public Player PlayerTwo { get; set; }

	// ⏱️ 10-SECOND ACTIVE ACTION TIMER REGISTERS
	[Property, Sync] public float TurnCountdownClock { get; set; } = 10.0f;
	[Property, Sync] public bool IsWaitingForClientInput { get; set; } = false;
	// If true, Player 1 (Host) is choosing. If false, Player 2 (Client) is choosing.
	[Property, Sync] public bool IsPlayerOneActiveTurn { get; set; } = true;

	// Track if the current active turn has submitted a move selection packet
	[Property, Sync] public bool IsTurnMoveCached { get; set; } = false;

	// Preserving streak states without global point overhead
	[Property, Sync] public int PlayerWinStreak { get; set; } = 0;
	[Property, Sync] public int PlayerLossStreak { get; set; } = 0;
	// To have the player 2 select their own moves.
	[Property, Sync] public int NetworkedPlayerTwoMove { get; set; } = 1;
	// Chat messaging between players
	[Property, Sync] public List<string> ChatMessages { get; set; } = new List<string>();
	// Network move caches
	[Property, Sync] public int PlayerOneStoredMove { get; set; } = 0; // 0 = Awaiting Choice
	[Property, Sync] public int PlayerTwoStoredMove { get; set; } = 0;
	public ref Player LocalPlayerTwo => ref AIEnemy;
	[Property, Sync] public bool IsPlayerOneDazed { get; set; } = false;
	[Property, Sync] public bool IsPlayerTwoDazed { get; set; } = false;


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

		// Only calculate countdown tick marks if a live multiplayer battle is active
		if ( CurrentMode != PlayMode.Multiplayer || !IsBattleActive || !IsWaitingForClientInput ) return;

		// Natively subtract frame delta time from your clock register
		TurnCountdownClock -= RealTime.Delta;

		if ( TurnCountdownClock <= 0f )
		{
			TurnCountdownClock = 10.0f; // Recharge the timer capacitor instantly
			Log.Warning( "[NET TIMER] Turn countdown hit zero! Force-submitting fallback attack index 1." );

			if ( Sandbox.Connection.Local != null )
			{
				// The server host submits on behalf of whoever timed out to keep network states completely synced
				if ( Sandbox.Networking.IsHost )
				{
					SubmitNetworkMove( IsPlayerOneActiveTurn, 1 );
				}
			}
		}
	}

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

		if ( CurrentMode == PlayMode.Multiplayer )
		{
			if ( LocalPlayer != null )
			{
				LocalPlayer.maxHp = 100;
				LocalPlayer.hp = 100;
				LocalPlayer.maxDefense = 100;
				LocalPlayer.defense = 100;
				LocalPlayer.magic = 100; // Starts match with empty MP capacitors
			}

			if ( AIEnemy != null )
			{
				AIEnemy.maxHp = 100;
				AIEnemy.hp = 100;
				AIEnemy.maxDefense = 100;
				AIEnemy.defense = 100;
				AIEnemy.magic = 100;
			}

			Log.Info( "⚙️ [RESET SYSTEM] Multiplayer override hard-flushed bars to 100/100!" );
		}
	}

	public enum GamePhase
	{
		MainMenu,
		StartMenu,
		WeaponSelection,
		EnchantmentSelection,
		Battle,
		MultiplayerLobby,
		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 )
	{
		if ( CurrentMode == PlayMode.SinglePlayer )
		{
			LoadProgress();

			HasPlayerTakenAnyDamage = false;

			LocalPlayer = new Player( "Hero", 100, 15, 0, false ); // 100 HP, 15 Atk, 0 Def. For single player mode with the AI Overlord.
			AIEnemy = new Player( "AI Overlord", 100, 15, 100, true );
		}
		else
		{
			HasPlayerTakenAnyDamage = false;
			// 🚀 MULTIPLAYER: Search s&box connections to find your opponent's Steam name handle!
			string opponentName = "Unknown Challenger";

			// Look across connections to find the non-host user
			foreach ( var conn in Sandbox.Connection.All )
			{
				if ( conn != Sandbox.Connection.Local )
				{
					opponentName = conn.Name; // Extracts their true network nickname handle!
					break;
				}
			}

			// Symmetrical 100 HP and 100 Armor allocations right out of the box
			LocalPlayer = new Player( "Hero", 100, 15, 100, false );
			LocalPlayer.maxHp = 100;
			LocalPlayer.maxDefense = 100;

			AIEnemy = new Player( opponentName, 100, 15, 100, false );
			AIEnemy.maxHp = 100;
			AIEnemy.maxDefense = 100;
		}

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

		if ( CurrentMode == PlayMode.SinglePlayer )
		{
			CombatLogs.Add( new CombatLogEntry
			{
				Message = $"⚔️ Combat Begins! AI equipped {AIWeapon.name}.",
				ColorClass = "system-text"
			} );
		}
		else
		{
			// Symmetrical Multiplayer startup announcement
			CombatLogs.Add( new CombatLogEntry
			{
				Message = $"📡 PVP ARENA ACTIVE: Host ({LocalPlayer.name}) vs Challenger ({AIEnemy.name})!",
				ColorClass = "system-text"
			} );
		}

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

		// =========================================================================
		// 👑 INTERCEPT MAINBOARD IDENTITY (STEAM PROFILE NAME LOG)
		// =========================================================================
		if ( CurrentMode == PlayMode.SinglePlayer )
		{
			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!" );
		}
		else
		{
			// Clean, competitive network notification for Multiplayer instead of bot logs
			AddLog( "📡 [SYSTEM] Handshake finalized. Symmetrical network synchronization engine online." );
		}

		// =========================================================================
		// ⏱️ ASYMMETRICAL SPEED-CHESS TIMING AND CACHE INJECTIONS 
		// =========================================================================
		if ( CurrentMode == PlayMode.Multiplayer )
		{
			this.PlayerOneStoredMove = 0;
			this.PlayerTwoStoredMove = 0;
			this.IsPlayerOneActiveTurn = true; // Player 1 (Host) takes the absolute opening shot
			this.IsTurnMoveCached = false;

			this.TurnCountdownClock = 10.0f; // Hard pre-charge the 10-second tactical countdown
			this.IsWaitingForClientInput = true;
		}
		// =========================================================================

		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 )
	{

		int playerTwoMove = (CurrentMode == PlayMode.Multiplayer) ? this.PlayerTwoStoredMove : 1;

		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. Mode Isolation Move Evaluation (Update 3.0.0) ---
		int aiMove = playerTwoMove;// Fallback stock container slot.
		if (this.CurrentMode == PlayMode.SinglePlayer)
		{
			aiMove = Game.ChooseAIAction( LocalPlayer, AIEnemy, attackCount, blockCount, healCount, specialCount, Round );
		}
		else
		{
			aiMove = this.NetworkedPlayerTwoMove;// Reads directly from networked player two moves!
		}

		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
		// 🧼 CRITICAL OVERRIDE: Strip prestige bonuses out entirely if multiplayer is running!
		int currentPrestigeScaler = (CurrentMode == PlayMode.Multiplayer) ? 0 : CurrentPrestige;
		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 && CurrentMode == PlayMode.SinglePlayer )// Strict singleplayer for ai dialogue only
		{
			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;
			bool isMultiplayer = manager != null && manager.CurrentMode == GameManager.PlayMode.Multiplayer;

			int scaledMagicCost = 20 + (isMultiplayer ? 0 : (prestige * 5));

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

			// =========================================================================
			// 🌀 SINGULARITY CORE: COST REDUCTION INTEGRATION (Gated for Single-Player)
			// =========================================================================
			if ( !isMultiplayer && LocalPlayer.Perks.SpellMultiplier > 1.0f )
			{
				scaledMagicCost = Math.Max( 5, scaledMagicCost - 15 );
			}
			// =========================================================================

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

			if ( LocalPlayer.magic >= scaledMagicCost )
			{
				string spell = LocalPlayer.offensiveSpells[rand.Next( LocalPlayer.offensiveSpells.Count )];

				// =========================================================================
				// 🚀 MULTIPLAYER RESOLUTION MATRIX: SPELL CAST ANNOUNCEMENT
				// =========================================================================
				if ( isMultiplayer )
				{
					GameManager.AddPlayerLog( $"🔮 {LocalPlayer.name} casts {spell}! (-{scaledMagicCost} Magic)" );
				}
				else
				{
					GameManager.AddPlayerLog( $"🔮 You cast {spell}! (-{scaledMagicCost} Magic)" );
				}
				// =========================================================================

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

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

				if ( !isMultiplayer )
				{
					// Multiplies your final calculated spell points by your magic scaling factors!
					spellDamage = (int)(spellDamage * LocalPlayer.Perks.SpellMultiplier);

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

				// =========================================================================
				// 🚀 MULTIPLAYER RESOLUTION MATRIX: PAYLOAD DELIVERY
				// =========================================================================
				if ( isMultiplayer )
				{
					if ( spell == "Poison Bolt" )
					{
						AIEnemy.cursed = true;
						GameManager.AddAILog( $"🧪 {AIEnemy.name} is poisoned!" );
					}

					CombatManager.applyDamage( ref AIEnemy, spellDamage );
					GameManager.AddPlayerLog( $"💥 {spell} hits {AIEnemy.name} for {spellDamage} damage!" );
				}
				else
				{
					// 🤖 SINGLE PLAYER MODE: Your original un-edited AI Overlord math rules
					if ( AIEnemy.counterReady || (prestige >= 10 && rand.Next( 100 ) < 35) )
					{
						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 );
						}

						CombatManager.applyDamage( ref LocalPlayer, spellDamage );
						return;
					}

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

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

					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
			{
				if ( isMultiplayer ) GameManager.AddPlayerLog( $"❌ Not enough magic! {LocalPlayer.name} needs {scaledMagicCost} Magic." );
				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;
			bool isMultiplayer = manager != null && manager.CurrentMode == GameManager.PlayMode.Multiplayer;

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

			if ( LocalPlayer.magic >= scaledMagicCost )
			{
				string spell = LocalPlayer.defensiveSpells[rand.Next( LocalPlayer.defensiveSpells.Count )];

				// =========================================================================
				// 🚀 Symmetrical Defensive Casting Announcement
				// =========================================================================
				if ( isMultiplayer )
				{
					GameManager.AddPlayerLog( $"🔮 {LocalPlayer.name} casts {spell}! (-{scaledMagicCost} Magic)" );
				}
				else
				{
					GameManager.AddPlayerLog( $"🔮 You cast {spell}! (-{scaledMagicCost} Magic)" );
				}
				// =========================================================================

				if ( spell == "Shield" || spell == "Barrier" )
				{
					LocalPlayer.defense += scaledShieldAmount;

					// =========================================================================
					// 🚀 Symmetrical Armor Plating Increase Tracking
					// =========================================================================
					if ( isMultiplayer )
					{
						GameManager.AddPlayerLog( $"🛡️ {LocalPlayer.name}'s armor is increased by {scaledShieldAmount} points!" );
					}
					else
					{
						GameManager.AddPlayerLog( $"🛡️ Your armor is increased by {scaledShieldAmount} points!" );
					}
					// =========================================================================

					// Defensive check: Clamp armor safely to your maximum defense
					int activeMaxDefense = isMultiplayer ? 100 : (manager?.LocalPlayer?.maxDefense ?? 100);
					if ( LocalPlayer.defense > activeMaxDefense )
					{
						LocalPlayer.defense = activeMaxDefense;
					}
				}
				else if ( spell == "Reflect" )
				{
					LocalPlayer.isBlocking = true;

					// =========================================================================
					// 🚀 Symmetrical Physical Block Setup Notification
					// =========================================================================
					if ( isMultiplayer )
					{
						GameManager.AddPlayerLog( $"🛡️ {LocalPlayer.name} prepares to block the next attack!" );
					}
					else
					{
						GameManager.AddPlayerLog( "🛡️ Next attack will be blocked!" );
					}
					// =========================================================================
				}
				else if ( spell == "Magic Wall" )
				{
					LocalPlayer.isMagicBlocking = true;
					LocalPlayer.activeMagicShield = "Magic Wall";

					// =========================================================================
					// 🚀 Symmetrical Magical Barrier Indicator
					// =========================================================================
					if ( isMultiplayer )
					{
						GameManager.AddPlayerLog( $"✨ A magical barrier surrounds {LocalPlayer.name}!" );
					}
					else
					{
						GameManager.AddPlayerLog( "✨ A magical barrier surrounds you!" );
					}
					// =========================================================================
				}
				else if ( spell == "Fortify" )
				{
					LocalPlayer.isMagicBlocking = true;
					LocalPlayer.activeMagicShield = "Fortify";

					// =========================================================================
					// 🚀 Symmetrical Hull Reinforcement Confirmation
					// =========================================================================
					if ( isMultiplayer )
					{
						GameManager.AddPlayerLog( $"💎 {LocalPlayer.name}'s defenses are magically reinforced!" );
					}
					else
					{
						GameManager.AddPlayerLog( "💎 Your defenses are magically reinforced!" );
					}
					// =========================================================================
				}

				if ( !isMultiplayer )
				{
					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
			{
				if ( isMultiplayer ) GameManager.AddPlayerLog( $"❌ Not enough magic! {LocalPlayer.name} needs {scaledMagicCost} Magic." );
				else 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;
			bool isMultiplayer = manager != null && manager.CurrentMode == GameManager.PlayMode.Multiplayer;

			int scaledMagicCost = 15 + (isMultiplayer ? 0 : (prestige * 5));
			// Scale healing effects linearly: add +4 extra healing per prestige level (Gated for Single-Player)
			int prestigeHealBonus = isMultiplayer ? 0 : prestige * 4;

			if ( LocalPlayer.magic >= scaledMagicCost )
			{
				string spell = LocalPlayer.healingSpells[rand.Next( LocalPlayer.healingSpells.Count )];

				// =========================================================================
				// 🚀 Symmetrical Healing Casting Announcements
				// =========================================================================
				if ( isMultiplayer )
				{
					GameManager.AddPlayerLog( $"🔮 {LocalPlayer.name} casts {spell}! (-{scaledMagicCost} Magic)" );
				}
				else
				{
					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;

					// =========================================================================
					// 🚀 Symmetrical Condition Cure Announcements
					// =========================================================================
					if ( isMultiplayer )
					{
						GameManager.AddPlayerLog( $"✨ {LocalPlayer.name}'s negative effects were removed!" );
					}
					else
					{
						GameManager.AddPlayerLog( "✨ Negative effects removed!" );
					}
					// =========================================================================
				}
				else if ( spell == "Divine Light" ) healAmount = 40 + prestigeHealBonus;
				else if ( spell == "Recovery Pulse" ) healAmount = 30 + prestigeHealBonus;

				if ( !isMultiplayer )
				{
					float hpPercentage = (float)LocalPlayer.hp / LocalPlayer.maxHp;
					if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasEmergencyCellPurge && hpPercentage <= 0.30f )
					{
						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;

				// =========================================================================
				// 🚀 Symmetrical HP Recovery Indicators
				// =========================================================================
				if ( isMultiplayer )
				{
					GameManager.AddPlayerLog( $"💚 {LocalPlayer.name} recovers {healAmount} HP!" );
				}
				else
				{
					GameManager.AddPlayerLog( $"💚 You recover {healAmount} HP!" );
				}
				// =========================================================================

				if ( !isMultiplayer )
				{
					if ( LocalPlayer.Perks != null && LocalPlayer.Perks.HasOverhealCapacitor )
					{
						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
			{
				if ( isMultiplayer ) GameManager.AddPlayerLog( $"❌ Not enough magic! {LocalPlayer.name} needs {scaledMagicCost} Magic." );
				else 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;
			bool isMultiplayer = manager != null && manager.CurrentMode == GameManager.PlayMode.Multiplayer;

			// Highly aggressive mana cost scaling (+10 per level) (Gated for Single-Player)
			int scaledMagicCost = 30 + (isMultiplayer ? 0 : (prestige * 10));

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

			int prestigeDamageBonus = isMultiplayer ? 0 : prestige * 2;

			// =========================================================================
			// 🌀 SINGULARITY CORE: COST REDUCTION INTEGRATION (Gated for Single-Player)
			// =========================================================================
			if ( !isMultiplayer && 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 )
				{
					// =========================================================================
					// 🚀 Symmetrical Ultimate Cast Failure Messages
					// =========================================================================
					if ( isMultiplayer )
					{
						GameManager.AddPlayerLog( $"⚠️ CRITICAL SYSTEM FAILURE! {LocalPlayer.name}'s ultimate spell fizzles away into static feedback! Magic wasted." );
					}
					else
					{
						GameManager.AddPlayerLog( "⚠️ CRITICAL SYSTEM FAILURE! Your ultimate spell fizzles away into static feedback! Magic wasted." );
					}
					// =========================================================================
					return; // Drop out completely
				}

				// =========================================================================
				// 🔮 QUARANTINE TRIGGER REACTION BUFFER (Gated for Single-Player)
				// =========================================================================
				if ( !isMultiplayer )
				{
					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 );

				// =========================================================================
				// 🚀 Symmetrical Ultimate Spell Announcements
				// =========================================================================
				if ( isMultiplayer )
				{
					GameManager.AddPlayerLog( $"{emoji} {LocalPlayer.name} casts Ultimate Spell: {spell}! (-{scaledMagicCost} Magic)" );
				}
				else
				{
					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;
				}

				if ( !isMultiplayer )
				{
					// =========================================================================
					// 🌀 SINGULARITY CORE ULTRA BURST INTEGRATION (Gated for Single-Player)
					// =========================================================================
					if ( LocalPlayer.Perks.HasSingularityCore )
					{
						ultimateDamage = (int)(ultimateDamage * 1.40f);
					}
					// =========================================================================

					// =========================================================================
					// ☄️ AURA MELTDOWN & OVERCLOCK MULTIPLIER INTEGRATION (Gated for Single-Player)
					// =========================================================================
					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 ( !isMultiplayer && LocalPlayer.Perks != null && LocalPlayer.Perks.HasDefianceProtocol )
				{
					triggerDoubleStrike = true;
					GameManager.AddPlayerLog( "🪐 DEFIANCE PROTOCOL: Echo buffers synchronized! Preparing secondary payload loop strike!" );
				}

				if ( !isMultiplayer )
				{
					// =========================================================================
					// 🌌 VOID PUNCTURE: ULTIMATE MAGICAL ARMOR BYPASS (Gated for Single-Player)
					// =========================================================================
					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 (Gated for Single-Player)
					// =========================================================================
					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!" );
					}
				}

				// =========================================================================
				// 🚀 MULTIPLAYER RESOLUTION MATRIX: PAYLOAD DELIVERY & CHASSIS INTERLOCK
				// =========================================================================
				if ( isMultiplayer )
				{
					if ( spell == "System Overdrive" )
					{
						CombatManager.applyDamage( ref AIEnemy, ultimateDamage );
						GameManager.AddPlayerLog( $"⚡ {LocalPlayer.name} enters System Overdrive, bypassing the firewall for {ultimateDamage} massive damage onto {AIEnemy.name}!" );
					}
					else if ( spell == "EMP Blast" )
					{
						CombatManager.applyDamage( ref AIEnemy, ultimateDamage );
						GameManager.AddPlayerLog( $"💥 An EMP Blast de-calibrates {AIEnemy.name}'s framework, dealing {ultimateDamage} damage from doubled attack power!" );
					}
					else if ( spell == "Data Corruption" )
					{
						CombatManager.applyDamage( ref AIEnemy, ultimateDamage );
						if ( manager != null ) manager.IsPlayerTwoDazed = true; // Hard-arms Player 2's speed chess skip flag!
						GameManager.AddPlayerLog( $"👾 {LocalPlayer.name} injects Data Corruption into {AIEnemy.name}'s system routines! Causing -{ultimateDamage} HP and freezing their inputs!" );
					}
				}
				else
				{
					// 🤖 SINGLE PLAYER: Runs completely normally for the AI Overlord fallback branches
					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
			{
				if ( isMultiplayer ) GameManager.AddPlayerLog( $"❌ Not enough magic! {LocalPlayer.name} needs {scaledMagicCost} Magic." );
				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 ( CurrentMode != PlayMode.SinglePlayer )
		{
			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 ) =>
			{
				if ( p.Perks.HealthCardCount < 2 )
				{
					p.maxHp += 100;
					p.hp += 100;
					p.Perks.HealingMultiplier += 0.25f;  // Amplifies future recovery loops
					p.Perks.AttackMultiplier -= 0.05f;   // Reduces weapon cuts cleanly
					p.Perks.HealthCardCount++;
				}
			},
			ApplyToAI = ( ai ) =>
			{
				if ( ai.Perks.HealthCardCount < 2 )
				{
					ai.maxHp += 100;
					ai.hp += 100;
					ai.Perks.HealingMultiplier += 0.25f;
					ai.Perks.AttackMultiplier -= 0.05f;
					ai.Perks.HealthCardCount++;
				}
			}
		} );

		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 ) =>
			{
				if ( p.Perks.HealthCardCount < 2 )
				{
					p.Perks.HasOverhealCapacitor = true;
					p.Perks.AttackMultiplier -= 0.03f;
					p.Perks.HealthCardCount++;
				}
			},
			ApplyToAI = ( ai ) =>
			{
				if ( ai.Perks.HealthCardCount < 2 )
				{

					ai.Perks.HasOverhealCapacitor = true;
					ai.Perks.AttackMultiplier -= 0.03f;
					ai.Perks.HealthCardCount++;
				}
			}
		} );

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

	// 💬 BROADCAST CHAT HANDLER INTERCEPT
	// Reaching out across network pipes to push raw text data lines to both terminals
	[Rpc.Broadcast]
	public void SendNetworkChatMessage( string senderName, string rawTextMessage )
	{
		if ( string.IsNullOrEmpty( rawTextMessage ) ) return;

		string formattedLogLine = $"[💬 CHAT] {senderName.ToUpper()}: {rawTextMessage}";

		if ( ChatMessages == null ) ChatMessages = new List<string>();
		ChatMessages.Add( formattedLogLine );

		GameManager.AddLog( formattedLogLine );
	}

	// 🎮 NETWORK MOVE AUTHORIZATION PROTOCOL
	// Receives turn inputs from clients and routes them safely into your core simulation loop
	[Rpc.Broadcast]
	public void SubmitNetworkMove( bool isHostChoice, int chosenMoveIndex )
	{
		// 👤 STEP 1: IT IS PLAYER 1'S TURN AND THE HOST MAKES A SELECTION
		if ( IsPlayerOneActiveTurn && isHostChoice )
		{
			if ( IsPlayerOneDazed )
			{
				chosenMoveIndex = 0;      // Assign an Idle/Skip index so no damage calculations fire
				IsPlayerOneDazed = false; // Consume the daze flag for this round pass
				GameManager.AddLog( $"😵 [SYSTEM] {LocalPlayer.name} is dazed from an electrical overload! Action skipped." );
			}
			PlayerOneStoredMove = chosenMoveIndex;
			IsPlayerOneActiveTurn = false; // 🔄 DYNAMIC SWITCH: Hand the active clock to Player 2!

			TurnCountdownClock = 10.0f; // Recharge the full 10-second capacitor for Player 2
			GameManager.AddLog( "📡 [SYSTEM] Player 1 locked their action! Player 2 terminal unlocked..." );
			return;
		}

		// 👥 STEP 2: IT IS PLAYER 2'S TURN AND THE CLIENT RESPONDS
		if ( !IsPlayerOneActiveTurn && !isHostChoice )
		{
			if ( IsPlayerTwoDazed )
			{
				chosenMoveIndex = 0;      // Assign an Idle/Skip index so no damage calculations fire
				IsPlayerTwoDazed = false; // Consume the daze flag for this round pass
				GameManager.AddLog( $"😵 [SYSTEM] {AIEnemy.name} is dazed from an electrical overload! Action skipped." );
			}
			PlayerTwoStoredMove = chosenMoveIndex;
			IsWaitingForClientInput = false; // Freeze countdown ticks immediately during round processing

			// Pass Player 1's move natively into your core player vs player math simulation loop
			ProcessTurnSlice( PlayerOneStoredMove );

			// 🧼 POST-ROUND FLUSH: Reset the buffers and hand the opening turn of the next round back to Player 1
			PlayerOneStoredMove = 0;
			PlayerTwoStoredMove = 0;
			IsPlayerOneActiveTurn = true;

			TurnCountdownClock = 10.0f; // Recharge the 10-second clock for Player 1's next turn
			IsWaitingForClientInput = true;
		}
	}

}