MainHud/DiceDuelEventRunner.cs

A static manager that runs a two-dice duel event between a Player and an AI. It rolls dice, shows a choice popup letting the player keep or reroll dice, simulates an AI reroll decision, resolves win/tie/loss, logs results to GameManager and applies damage via CombatManager.

Networking
using Keyboard_Warriors_.Models;
using Keyboard_Warriors_.Systems;
using Sandbox;
using System;

namespace Keyboard_Warriors_.Managers;

public static class DiceDuelEventRunner
{
	private static Player cachedPlayer;
	private static Player cachedAI;
	private static int p1;
	private static int p2;

	private static int RollDie() => Random.Shared.Next( 1, 7 );

	// FIX: Safe helper method to fetch the GameManager directly from the scene context hierarchy
	private static GameManager GetManager()
	{
		return Sandbox.Game.ActiveScene?.Get<GameManager>();
	}

	public static void StartEvent( Player player, Player ai )
	{
		// FIX: Defensive validation step ensures the game manager exists before drawing panels
		var manager = GetManager();
		if ( manager == null )
		{
			Log.Error( "[DICE DUEL CRITICAL] Failed to resolve GameManager from active scene tree setup!" );
			return;
		}

		GameManager.AddLog( "\n=== High Dice Duel Begins! ===" );

		cachedPlayer = player;
		cachedAI = ai;

		// Roll your initial state
		p1 = RollDie();
		p2 = RollDie();

		GameManager.AddLog( $"You rolled: [{p1}] [{p2}] (Total: {p1 + p2})" );
		GameManager.AddLog( "⚠️ AWAITING RE-ROLL DATA VECTOR INPUT..." );

		var diceEvent = new ChoiceEvent
		{
			Title = "🎲 HIGH DICE SYSTEM DUEL",
			PromptText = $"You rolled a [{p1}] and a [{p2}] (Current Total: {p1 + p2}). The AI is waiting for your final confirmation. Will you lock this score or execute a re-roll sub-routine?",
		};

		// --- BUTTON 1: KEEP CURRENT ROLL ---
		diceEvent.Options.Add( new EventOption
		{
			ButtonText = "🔒 KEEP CURRENT ROLL",
			ActionToExecute = () =>
			{
				GameManager.AddLog( "You choose to keep your current roll." );
				ResolveDiceDuel( p1, p2 );
			}
		} );

		// --- BUTTON 2: REROLL DIE 1 ---
		diceEvent.Options.Add( new EventOption
		{
			ButtonText = "🎲 RE-ROLL DIE 1 ONLY",
			ActionToExecute = () =>
			{
				int newP1 = RollDie();
				GameManager.AddLog( $"Re-rolling Die 1... New roll: [{newP1}] [{p2}] (Total: {newP1 + p2})" );
				ResolveDiceDuel( newP1, p2 );
			}
		} );

		// --- BUTTON 3: REROLL DIE 2 ---
		diceEvent.Options.Add( new EventOption
		{
			ButtonText = "🎲 RE-ROLL DIE 2 ONLY",
			ActionToExecute = () =>
			{
				int newP2 = RollDie();
				GameManager.AddLog( $"Re-rolling Die 2... New roll: [{p1}] [{newP2}] (Total: {p1 + newP2})" );
				ResolveDiceDuel( p1, newP2 );
			}
		} );

		// --- BUTTON 4: REROLL BOTH DICE ---
		diceEvent.Options.Add( new EventOption
		{
			ButtonText = "💥 RE-ROLL BOTH DICE",
			ActionToExecute = () =>
			{
				int newP1 = RollDie();
				int newP2 = RollDie();
				GameManager.AddLog( $"Re-rolling both dice... New roll: [{newP1}] [{newP2}] (Total: {newP1 + newP2})" );
				ResolveDiceDuel( newP1, newP2 );
			}
		} );

		// FIX: Use the securely found scene reference instead of the unstable global Instance shortcut
		manager.TriggerChoicePopup( diceEvent );
	}

	private static void ResolveDiceDuel( int finalP1, int finalP2 )
	{
		var manager = GetManager();
		int prestige = manager != null ? manager.CurrentPrestige : 0;

		// Lineally scale your payout variables (+3 for standard wins, +2 for ties per level)
		int scaledWinDamage = 25 + (prestige * 3);
		int scaledTieDamage = 15 + (prestige * 2);

		int playerTotal = finalP1 + finalP2;

		int a1 = RollDie();
		int a2 = RollDie();
		GameManager.AddLog( $"AI rolled: [{a1}] [{a2}] (Total: {a1 + a2})" );

		bool aiReroll = false;
		int currentAITotal = a1 + a2;

		if ( currentAITotal <= 6 )
			aiReroll = Random.Shared.Next( 1, 101 ) <= 70;
		else if ( currentAITotal <= 8 )
			aiReroll = Random.Shared.Next( 1, 101 ) <= 40;
		else
			aiReroll = Random.Shared.Next( 1, 101 ) <= 10;

		if ( aiReroll )
		{
			int rerollChoice = Random.Shared.Next( 1, 4 );

			if ( rerollChoice == 1 )
				a1 = RollDie();
			else if ( rerollChoice == 2 )
				a2 = RollDie();
			else
			{
				a1 = RollDie();
				a2 = RollDie();
			}

			GameManager.AddLog( $"AI re-rolled! Final roll: [{a1}] [{a2}] (Total: {a1 + a2})" );
		}
		else
		{
			GameManager.AddLog( "AI keeps its roll." );
		}

		int aiTotal = a1 + a2;

		if ( playerTotal > aiTotal )
		{
			GameManager.AddLog( $"You WIN the duel! AI loses {scaledWinDamage} HP." );
			CombatManager.applyDamage( ref cachedAI, scaledWinDamage );
		}
		else if ( aiTotal > playerTotal )
		{
			GameManager.AddLog( $"AI wins the duel! You lose {scaledWinDamage} HP." );
			CombatManager.applyDamage( ref cachedPlayer, scaledWinDamage );
		}
		else
		{
			GameManager.AddLog( $"It's a tie! Both lose {scaledTieDamage} HP." );
			CombatManager.applyDamage( ref cachedPlayer, scaledTieDamage );
			CombatManager.applyDamage( ref cachedAI, scaledTieDamage );
		}

		GameManager.AddLog( $"{cachedPlayer.name} | HP: {cachedPlayer.hp} | Armor: {cachedPlayer.defense}" );
		GameManager.AddLog( $"{cachedAI.name} | HP: {cachedAI.hp} | Armor: {cachedAI.defense}" );
	}
}