A static manager that runs a Monty Hall style minigame between a player and an AI. It creates choice popups via GameManager, logs progress, randomly assigns prize and choices, and applies damage via CombatManager based on outcomes.
using Keyboard_Warriors_.Models;
using Keyboard_Warriors_.Systems;
using Sandbox;
using System;
namespace Keyboard_Warriors_.Managers;
public static class MontyHallEventRunner
{
private static Player cachedPlayer;
private static Player cachedAI;
private static int prizeDoor;
private static int aiChoice;
private static int DrawCard() => Random.Shared.Next( 1, 12 );
// FIX: Safe helper method to fetch the GameManager directly from the active engine layout
private static GameManager GetManager()
{
return Sandbox.Game.ActiveScene?.Get<GameManager>();
}
public static void StartEvent( Player player, Player ai )
{
// FIX: Defensive guard assertion prevents UI initialization crashes
var manager = GetManager();
if ( manager == null )
{
Log.Error( "[MONTY HALL CRITICAL] Failed to resolve GameManager instance from active scene loop parameters!" );
return;
}
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..." );
cachedPlayer = player;
cachedAI = ai;
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 ); }
} );
// FIX: Execute popup utilizing the secure local manager link profile
manager.TriggerChoicePopup( initialDoorEvent );
}
private static void PromptSwitchOrStay( int initialPlayerChoice )
{
var manager = GetManager();
if ( manager == null ) return;
int revealDoorPlayer;
do
{
revealDoorPlayer = Random.Shared.Next( 1, 4 );
}
while ( revealDoorPlayer == prizeDoor || revealDoorPlayer == initialPlayerChoice );
GameManager.AddLog( $"Host reveals Door #{revealDoorPlayer} for you... it's FAILURE!" );
GameManager.AddLog( "⚠️ AWAITING STRATEGIC RE-ROUTE SYSTEM CONFIRMATION..." );
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 OTHER OPEN DOOR",
ActionToExecute = () =>
{
int finalChoicePlayer = initialPlayerChoice;
for ( int i = 1; i <= 3; i++ )
{
if ( i != initialPlayerChoice && i != revealDoorPlayer )
{
finalChoicePlayer = i;
break;
}
}
GameManager.AddLog( $"You decide to SWITCH to Door #{finalChoicePlayer}!" );
ResolveFinalMontyHallMatch( finalChoicePlayer );
}
} );
switchOrStayEvent.Options.Add( new EventOption
{
ButtonText = "🔒 STAY WITH ORIGINAL SELECTION",
ActionToExecute = () =>
{
GameManager.AddLog( $"You decide to STAY with Door #{initialPlayerChoice}." );
ResolveFinalMontyHallMatch( initialPlayerChoice );
}
} );
// FIX: Execute popup utilizing the secure local manager link profile
manager.TriggerChoicePopup( switchOrStayEvent );
}
private static void ResolveFinalMontyHallMatch( int finalChoicePlayer )
{
var manager = GetManager();
int prestige = manager != null ? manager.CurrentPrestige : 0;
// Lineally scale your outcome damage vector (+4 per prestige level)
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}." );
}
if ( finalChoicePlayer == prizeDoor )
{
GameManager.AddLog( $"** YOU WIN! The prize was behind Door #{prizeDoor}! AI loses {scaledMatchDamage} HP! **" );
CombatManager.applyDamage( ref cachedAI, scaledMatchDamage );
}
else
{
GameManager.AddLog( $"** YOU LOSE! The prize was behind Door #{prizeDoor}! You lose {scaledMatchDamage} HP! **" );
CombatManager.applyDamage( ref cachedPlayer, scaledMatchDamage );
}
if ( finalChoiceAI == prizeDoor )
{
GameManager.AddLog( $"** AI WINS! The prize was behind Door #{prizeDoor}! You take {scaledMatchDamage} HP damage! **" );
CombatManager.applyDamage( ref cachedPlayer, scaledMatchDamage );
}
else
{
GameManager.AddLog( $"** AI LOSES! The prize was behind Door #{prizeDoor}! AI takes {scaledMatchDamage} HP damage! **" );
CombatManager.applyDamage( ref cachedAI, scaledMatchDamage );
}
GameManager.AddLog( $"{cachedPlayer.name} | HP: {cachedPlayer.hp} | Armor: {cachedPlayer.defense}" );
GameManager.AddLog( $"{cachedAI.name} | HP: {cachedAI.hp} | Armor: {cachedAI.defense}" );
}
}