MainHud/MontyHallEventRunner.cs
using Keyboard_Warriors_.Models;
using Keyboard_Warriors_.Systems;
using Sandbox;
using System;
namespace Keyboard_Warriors_.Managers;
public static class MontyHallEventRunner
{
private static int prizeDoor;
private static int aiChoice;
// =========================================================================
// 🌐 MULTIPLAYER NETWORK STATE MATRIX
// =========================================================================
private static int mpPrizeDoor;
private static int p1InitialChoice = 0;
private static int p2InitialChoice = 0;
private static int p1FinalChoice = 0;
private static int p2FinalChoice = 0;
private static bool isP1Done = false;
private static bool isP2Done = false;
private static bool isMontyResolved = false;
// =========================================================================
private static int DrawCard() => Random.Shared.Next( 1, 12 );
private static GameManager GetManager()
{
return Sandbox.Game.ActiveScene?.Get<GameManager>();
}
public static void StartEvent( Player player, Player ai )
{
var manager = GetManager();
if ( manager == null )
{
Log.Error( "[MONTY HALL CRITICAL] Failed to resolve GameManager instance from active scene loop parameters!" );
return;
}
bool isMultiplayer = manager.CurrentMode == GameManager.PlayMode.Multiplayer;
if ( isMultiplayer )
{
GameManager.AddLog( "** Welcome to the Live Symmetrical Monty Hall Challenge! **" );
GameManager.AddLog( "Three closed mainframe firewall doors stand before both combatants. Select your initial gateway entry:" );
// Hard-initialize network registers cleanly
mpPrizeDoor = Random.Shared.Next( 1, 4 );
p1InitialChoice = 0;
p2InitialChoice = 0;
p1FinalChoice = 0;
p2FinalChoice = 0;
isP1Done = false;
isP2Done = false;
isMontyResolved = false;
// Draw the opening selection panel cleanly on both machines simultaneously
var initialDoorEvent = new ChoiceEvent
{
Title = "🚪 SYSTEM ENTRY PATHWAY",
PromptText = "Three firewall doors stand before your terminal cursor. Select your starting gateway entry:",
};
Action<int, bool> handleInitialSelection = ( doorIndex, isHost ) =>
{
if ( isHost ) p1InitialChoice = doorIndex;
else p2InitialChoice = doorIndex;
string selectorName = isHost ? player.name : ai.name;
GameManager.AddLog( $"📡 [NET] {selectorName} locked their initial gateway entry path!" );
// Advance to the switch or stay overlay phase when both cards are logged
if ( p1InitialChoice > 0 && p2InitialChoice > 0 )
{
RunMultiplayerSwitchPhase( player, ai );
}
};
initialDoorEvent.Options.Add( new EventOption { ButtonText = "🚪 PICK DOOR #1", ActionToExecute = () => handleInitialSelection( 1, Networking.IsHost ) } );
initialDoorEvent.Options.Add( new EventOption { ButtonText = "🚪 PICK DOOR #2", ActionToExecute = () => handleInitialSelection( 2, Networking.IsHost ) } );
initialDoorEvent.Options.Add( new EventOption { ButtonText = "🚪 PICK DOOR #3", ActionToExecute = () => handleInitialSelection( 3, Networking.IsHost ) } );
manager.TriggerChoicePopup( initialDoorEvent );
}
else
{
// 🤖 SINGLE PLAYER MODE: Your exact un-edited career loop setup
GameManager.AddLog( "** Welcome to the Monty Hall Challenge! **" );
GameManager.AddLog( "Three doors stand before you. Behind one is VICTORY, behind the other is FAILURE." );
GameManager.AddLog( "⚠️ AWAITING INITIAL SELECTION PATHWAY..." );
prizeDoor = Random.Shared.Next( 1, 4 );
aiChoice = Random.Shared.Next( 1, 4 );
var initialDoorEvent = new ChoiceEvent
{
Title = "🚪 THE SYSTEM ENTRY PATHWAY",
PromptText = "Three closed mainframe firewall doors stand before your terminal cursor. Select your starting gateway entry:",
};
initialDoorEvent.Options.Add( new EventOption { ButtonText = "🚪 PICK DOOR #1", ActionToExecute = () => { GameManager.AddLog( "Player picks Door #1." ); PromptSwitchOrStay( 1 ); } } );
initialDoorEvent.Options.Add( new EventOption { ButtonText = "🚪 PICK DOOR #2", ActionToExecute = () => { GameManager.AddLog( "Player picks Door #2." ); PromptSwitchOrStay( 2 ); } } );
initialDoorEvent.Options.Add( new EventOption { ButtonText = "🚪 PICK DOOR #3", ActionToExecute = () => { GameManager.AddLog( "Player picks Door #3." ); PromptSwitchOrStay( 3 ); } } );
manager.TriggerChoicePopup( initialDoorEvent );
}
}
// =========================================================================
// 👥 MULTIPLAYER INTERACTIVE SWITCH/STAY CONTROL PASS
// =========================================================================
private static void RunMultiplayerSwitchPhase( Player player, Player ai )
{
var manager = GetManager();
if ( manager == null ) return;
bool isHost = Networking.IsHost;
int initialChoice = isHost ? p1InitialChoice : p2InitialChoice;
string myName = isHost ? player.name : ai.name;
// 1. Reveal a losing door that is NEITHER the prize door NOR this player's choice
int revealDoor = 1;
for ( int i = 1; i <= 3; i++ )
{
if ( i != mpPrizeDoor && i != initialChoice )
{
revealDoor = i;
break;
}
}
// 2. Calculate the exact remaining door for switching
int remainingOtherDoor = 1;
for ( int j = 1; j <= 3; j++ )
{
if ( j != initialChoice && j != revealDoor )
{
remainingOtherDoor = j;
break;
}
}
GameManager.AddLog( $"Host reveals Door #{revealDoor} for {myName}... it's a dead FAILURE sector!" );
var switchOrStayMpEvent = new ChoiceEvent
{
Title = "🔀 THE MONTY HALL PARADOX",
PromptText = $"You initially selected Door #{initialChoice}. Host has revealed Door #{revealDoor} is offline. Will you switch or stay?",
};
Action<int, bool> submitFinalChoice = ( finalChoice, isHostNode ) =>
{
if ( isHostNode )
{
p1FinalChoice = finalChoice;
isP1Done = true;
}
else
{
p2FinalChoice = finalChoice;
isP2Done = true;
}
string finisherName = isHostNode ? player.name : ai.name;
GameManager.AddLog( $"📡 [NET] {finisherName} completed their Monty Hall confirmation! Awaiting opponent..." );
CheckMultiplayerResolution( player, ai );
};
switchOrStayMpEvent.Options.Add( new EventOption
{
ButtonText = $"🔄 SWITCH TO DOOR #{remainingOtherDoor}",
ActionToExecute = () => { GameManager.AddLog( $"{myName} decides to SWITCH to Door #{remainingOtherDoor}!" ); submitFinalChoice( remainingOtherDoor, isHost ); }
} );
switchOrStayMpEvent.Options.Add( new EventOption
{
ButtonText = $"🔒 STAY WITH DOOR #{initialChoice}",
ActionToExecute = () => { GameManager.AddLog( $"{myName} decides to STAY with Door #{initialChoice}." ); submitFinalChoice( initialChoice, isHost ); }
} );
manager.TriggerChoicePopup( switchOrStayMpEvent );
}
private static void CheckMultiplayerResolution( Player player, Player ai )
{
var manager = GetManager();
if ( isP1Done && isP2Done && !isMontyResolved )
{
isMontyResolved = true;
GameManager.AddLog( $"\n📊 [MONTY HALL METRICS OVERCLOCK]" );
GameManager.AddLog( $"➡️ Core Gateway Prize Door was hidden behind: Door #{mpPrizeDoor}" );
// Evaluate Player 1
if ( p1FinalChoice == mpPrizeDoor )
{
GameManager.AddPlayerLog( $"🏆 SUCCESS! {player.name} guessed correctly! {ai.name} takes -35 HP damage!" );
CombatManager.applyDamage( ref ai, 35 );
}
else
{
GameManager.AddPlayerLog( $"❌ MISFIRE! {player.name} hit an offline sector! Taking -35 HP damage!" );
CombatManager.applyDamage( ref player, 35 );
}
// Evaluate Player 2
if ( p2FinalChoice == mpPrizeDoor )
{
GameManager.AddAILog( $"🏆 SUCCESS! {ai.name} guessed correctly! {player.name} takes -35 HP damage!" );
CombatManager.applyDamage( ref player, 35 );
}
else
{
GameManager.AddAILog( $"❌ MISFIRE! {ai.name} hit an offline sector! Taking -35 HP damage!" );
CombatManager.applyDamage( ref ai, 35 );
}
if ( player.hp < 0 ) player.hp = 0;
if ( ai.hp < 0 ) ai.hp = 0;
GameManager.AddLog( $"📊 CURRENT MATRIX STANDINGS ➔ {player.name} HP: {player.hp} | {ai.name} HP: {ai.hp}" );
if ( manager != null ) manager.IsChoiceEventActive = false;
}
}
// =========================================================================
private static void PromptSwitchOrStay( int initialPlayerChoice )
{
var manager = GetManager();
if ( manager == null ) return;
int revealDoorPlayer = 1;
for ( int i = 1; i <= 3; i++ )
{
if ( i != prizeDoor && i != initialPlayerChoice )
{
revealDoorPlayer = i;
break;
}
}
int remainingOtherDoor = 1;
for ( int j = 1; j <= 3; j++ )
{
if ( j != initialPlayerChoice && j != revealDoorPlayer )
{
remainingOtherDoor = j;
break;
}
}
GameManager.AddLog( $"Host reveals Door #{revealDoorPlayer} for you... it's FAILURE!" );
GameManager.AddLog( $"⚠️ SYSTEM UPDATE: You can stick with your choice or re-route parameters to the remaining door." );
var switchOrStayEvent = new ChoiceEvent
{
Title = "🔀 THE MONTY HALL PARADOX",
PromptText = $"You initially selected Door #{initialPlayerChoice}. Host has revealed Door #{revealDoorPlayer} is a dead sector. Will you switch or stay?",
};
switchOrStayEvent.Options.Add( new EventOption
{
ButtonText = $"🔄 SWITCH TO DOOR #{remainingOtherDoor}",
ActionToExecute = () =>
{
GameManager.AddLog( $"You decide to SWITCH to Door #{remainingOtherDoor}!" );
ResolveFinalMontyHallMatch( remainingOtherDoor );
}
} );
switchOrStayEvent.Options.Add( new EventOption
{
ButtonText = $"🔒 STAY WITH DOOR #{initialPlayerChoice}",
ActionToExecute = () =>
{
GameManager.AddLog( $"You decide to STAY with Door #{initialPlayerChoice}." );
ResolveFinalMontyHallMatch( initialPlayerChoice );
}
} );
manager.TriggerChoicePopup( switchOrStayEvent );
}
private static void ResolveFinalMontyHallMatch( int finalChoicePlayer )
{
var manager = GetManager();
if ( manager == null || manager.LocalPlayer == null || manager.AIEnemy == null )
{
Log.Error( "[MONTY HALL ERROR] Core player reference instances could not be retrieved during final evaluation pass!" );
return;
}
int prestige = manager.CurrentPrestige;
int scaledMatchDamage = 35 + (prestige * 4);
GameManager.AddLog( $"AI picks Door #{aiChoice}." );
int revealDoorAI;
do
{
revealDoorAI = Random.Shared.Next( 1, 4 );
}
while ( revealDoorAI == prizeDoor || revealDoorAI == aiChoice );
GameManager.AddLog( $"Host reveals Door #{revealDoorAI} for AI... it's FAILURE!" );
bool aiSwitch = Random.Shared.Next( 0, 2 ) == 1;
int finalChoiceAI = aiChoice;
if ( aiSwitch )
{
for ( int i = 1; i <= 3; i++ )
{
if ( i != aiChoice && i != revealDoorAI )
{
finalChoiceAI = i;
break;
}
}
GameManager.AddLog( $"AI decides to SWITCH to Door #{finalChoiceAI}!" );
}
else
{
GameManager.AddLog( $"AI decides to STAY with Door #{finalChoiceAI}." );
}
Player livePlayer = manager.LocalPlayer;
Player liveAI = manager.AIEnemy;
if ( finalChoicePlayer == prizeDoor )
{
GameManager.AddPlayerLog( $"🏆 SUCCESS! The prize was behind Door #{prizeDoor}! You guessed correctly! AI takes -{scaledMatchDamage} HP damage!" );
CombatManager.applyDamage( ref liveAI, scaledMatchDamage );
}
else
{
GameManager.AddPlayerLog( $"❌ MISFIRE! The prize was behind Door #{prizeDoor}! Your choice was a dead sector! You take -{scaledMatchDamage} HP damage!" );
CombatManager.applyDamage( ref livePlayer, scaledMatchDamage );
}
if ( finalChoiceAI == prizeDoor )
{
GameManager.AddAILog( $"🤖 AI OVERLORD SUCCESS! The prize was behind Door #{prizeDoor}! Overlord systems dealt -{scaledMatchDamage} HP to you!" );
CombatManager.applyDamage( ref livePlayer, scaledMatchDamage );
}
else
{
GameManager.AddAILog( $"🛡️ AI OVERLORD MISFIRE! The prize was behind Door #{prizeDoor}! Overlord systems take -{scaledMatchDamage} HP damage!" );
CombatManager.applyDamage( ref liveAI, scaledMatchDamage );
}
manager.LocalPlayer = livePlayer;
manager.AIEnemy = liveAI;
GameManager.AddLog( $"📊 CURRENT MATRIX STANDINGS ➔ {manager.LocalPlayer.name} HP: {manager.LocalPlayer.hp} | {manager.AIEnemy.name} HP: {manager.AIEnemy.hp}" );
}
}