MainHud/BlackjackEventRunner.cs
using Keyboard_Warriors_.Models;
using Keyboard_Warriors_.Systems;
using Sandbox;
using System;
namespace Keyboard_Warriors_.Managers;
public static class BlackjackEventRunner
{
private static Player cachedPlayer;
private static Player cachedAI;
private static int secretAITotal;
// =========================================================================
// 🌐 MULTIPLAYER NETWORK HAND REGISTERS
// =========================================================================
private static int p1HandTotal = 0;
private static int p2HandTotal = 0;
private static bool isPlayerOneFinished = false;
private static bool isPlayerTwoFinished = false;
private static bool isMatchResolved = 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 ) return;
bool isMultiplayer = manager.CurrentMode == GameManager.PlayMode.Multiplayer;
cachedPlayer = player;
cachedAI = ai;
if ( isMultiplayer )
{
GameManager.AddLog( "** A symmetrical game of CYBER BLACKJACK begins! **" );
// Reset and deal clean initial two-card packet totals for both humans
p1HandTotal = DrawCard() + DrawCard();
p2HandTotal = DrawCard() + DrawCard();
isPlayerOneFinished = false;
isPlayerTwoFinished = false;
isMatchResolved = false;
GameManager.AddLog( $"📡 [NET] Deal packets complete. {cachedPlayer.name} is up first to configure their array!" );
// Player 1 (Host) starts the hit/stand cycle first
RunMultiplayerLoop( true );
}
else
{
// 🤖 SINGLE PLAYER MODE: Your exact original un-edited career loop setup
GameManager.AddLog( "** A game of BLACKJACK begins! **" );
int currentScalePlayerTotal = DrawCard() + DrawCard();
secretAITotal = DrawCard() + DrawCard();
GameManager.AddLog( $"You are dealt cards totaling: {currentScalePlayerTotal}" );
GameManager.AddLog( $"AI is showing: {secretAITotal / 2} (one card hidden)" );
GameManager.AddLog( "⚠️ AWAITING HIT/STAND PROTOCOL CHOICE..." );
RunBlackjackTurnLoop( currentScalePlayerTotal );
}
}
// =========================================================================
// 👥 MULTIPLAYER SEQUENTIAL HIT/STAND TURN MATRIX
// =========================================================================
private static void RunMultiplayerLoop( bool isPlayerOneActive )
{
var manager = GetManager();
if ( manager == null ) return;
int currentHandTotal = isPlayerOneActive ? p1HandTotal : p2HandTotal;
string activeName = isPlayerOneActive ? cachedPlayer.name : cachedAI.name;
// Immediate bust gating if an additional card packet overclocks the 21 threshold
if ( currentHandTotal > 21 )
{
GameManager.AddLog( $"💥 {activeName} total: {currentHandTotal} - BUSTED!" );
if ( isPlayerOneActive ) isPlayerOneFinished = true;
else isPlayerTwoFinished = true;
AdvanceMultiplayerTurnPhase( isPlayerOneActive );
return;
}
// Immediate baseline lock if they hit an un-bustable natural 21 metric
if ( currentHandTotal == 21 )
{
GameManager.AddLog( $"🃏 {activeName} hit a perfect 21 structural stack!" );
if ( isPlayerOneActive ) isPlayerOneFinished = true;
else isPlayerTwoFinished = true;
AdvanceMultiplayerTurnPhase( isPlayerOneActive );
return;
}
// Enforce local display screens correctly based on machine connection identity tokens
bool shouldDrawPopup = (isPlayerOneActive && Networking.IsHost) || (!isPlayerOneActive && !Networking.IsHost);
if ( shouldDrawPopup )
{
var blackjackEvent = new ChoiceEvent
{
Title = "🃏 CYBER BLACKJACK EMULATION",
PromptText = $"Your current card array value sits at: {currentHandTotal}. Will you request an additional data card packet (HIT) or lock this calculation down (STAND)?",
};
blackjackEvent.Options.Add( new EventOption
{
ButtonText = "➕ REQUEST CARD (HIT)",
ActionToExecute = async () =>
{
int freshCard = DrawCard();
if ( isPlayerOneActive ) p1HandTotal += freshCard;
else p2HandTotal += freshCard;
GameManager.AddLog( $"🃏 {activeName} draws a {freshCard}. Total: {currentHandTotal + freshCard}" );
await GameTask.Delay( 50 );
RunMultiplayerLoop( isPlayerOneActive );
}
} );
blackjackEvent.Options.Add( new EventOption
{
ButtonText = "🔒 STAND WITH TOTAL",
ActionToExecute = () =>
{
GameManager.AddLog( $"🔒 {activeName} stands with a solid total of {currentHandTotal}." );
if ( isPlayerOneActive ) isPlayerOneFinished = true;
else isPlayerTwoFinished = true;
AdvanceMultiplayerTurnPhase( isPlayerOneActive );
}
} );
manager.TriggerChoicePopup( blackjackEvent );
}
else
{
// Clean text tracker overlay updates for the player currently waiting
if ( manager.IsChoiceEventActive ) manager.IsChoiceEventActive = false;
GameManager.AddLog( $"⏳ Waiting for {activeName} to finish executing their card configuration loop..." );
}
}
private static void AdvanceMultiplayerTurnPhase( bool wasPlayerOneActive )
{
var manager = GetManager();
if ( wasPlayerOneActive && !isPlayerTwoFinished )
{
// Player 1 finished their choices -> dynamically unlock Player 2's prompt screen
RunMultiplayerLoop( false );
}
else if ( isPlayerOneFinished && isPlayerTwoFinished && !isMatchResolved )
{
isMatchResolved = true;
GameManager.AddLog( $"\n📊 [BLACKJACK REVELATION MATRIX]" );
GameManager.AddLog( $"➡️ {cachedPlayer.name} Final Total: {p1HandTotal} | {cachedAI.name} Final Total: {p2HandTotal}" );
// Evaluate competitive baseline rules side-by-side
if ( p1HandTotal > 21 && p2HandTotal > 21 )
{
GameManager.AddLog( "🤝 BOTH PLAYERS BUSTED! Symmetrical data wipe: -10 HP each." );
CombatManager.applyDamage( ref cachedPlayer, 10 );
CombatManager.applyDamage( ref cachedAI, 10 );
}
else if ( p1HandTotal > 21 )
{
GameManager.AddLog( $"🏆 {cachedAI.name} WINS! {cachedPlayer.name} busted. -25 HP to {cachedPlayer.name}!" );
CombatManager.applyDamage( ref cachedPlayer, 25 );
}
else if ( p2HandTotal > 21 )
{
GameManager.AddLog( $"🏆 {cachedPlayer.name} WINS! {cachedAI.name} busted. -25 HP to {cachedAI.name}!" );
CombatManager.applyDamage( ref cachedAI, 25 );
}
else if ( p1HandTotal > p2HandTotal )
{
int dmg = (p1HandTotal == 21) ? 40 : 25;
string winMsg = (p1HandTotal == 21) ? $"🏆 {cachedPlayer.name} LANDS NATURAL BLACKJACK!" : $"🏆 {cachedPlayer.name} out-calculated the array!";
GameManager.AddLog( $"{winMsg} {cachedAI.name} suffers -{dmg} HP!" );
CombatManager.applyDamage( ref cachedAI, dmg );
}
else if ( p2HandTotal > p1HandTotal )
{
int dmg = (p2HandTotal == 21) ? 40 : 25;
string winMsg = (p2HandTotal == 21) ? $"🏆 {cachedAI.name} LANDS NATURAL BLACKJACK!" : $"🏆 {cachedAI.name} out-calculated the array!";
GameManager.AddLog( $"{winMsg} {cachedPlayer.name} suffers -{dmg} HP!" );
CombatManager.applyDamage( ref cachedPlayer, dmg );
}
else
{
GameManager.AddLog( $"🤝 Absolute deadlock tie score! Both lose -10 HP." );
CombatManager.applyDamage( ref cachedPlayer, 10 );
CombatManager.applyDamage( ref cachedAI, 10 );
}
GameManager.AddLog( $"{cachedPlayer.name} | HP: {cachedPlayer.hp} | Armor: {cachedPlayer.defense}" );
GameManager.AddLog( $"{cachedAI.name} | HP: {cachedAI.hp} | Armor: {cachedAI.defense}" );
if ( manager != null ) manager.IsChoiceEventActive = false;
}
}
// =========================================================================
private static void RunBlackjackTurnLoop( int runningPlayerTotal )
{
var manager = Sandbox.Game.ActiveScene?.Get<GameManager>();
int prestige = manager != null ? manager.CurrentPrestige : 0;
int scaledWinDamage = 25 + (prestige * 3);
if ( runningPlayerTotal > 21 )
{
GameManager.AddLog( $"** Total: {runningPlayerTotal} - You BUST! AI wins automatically. -{scaledWinDamage} HP. **" );
CombatManager.applyDamage( ref cachedPlayer, scaledWinDamage );
GameManager.AddLog( $"{cachedPlayer.name} | HP: {cachedPlayer.hp} | Armor: {cachedPlayer.defense}" );
return;
}
var blackjackEvent = new ChoiceEvent
{
Title = "🃏 CYBER BLACKJACK EMULATION",
PromptText = $"Your current hand value sits at: {runningPlayerTotal}. The AI is presenting a split risk window. Will you request an additional card packet or lock this calculation down?",
};
blackjackEvent.Options.Add( new EventOption
{
ButtonText = "➕ REQUEST CARD (HIT)",
ActionToExecute = async () =>
{
int freshCard = DrawCard();
int updatedTotal = runningPlayerTotal + freshCard;
GameManager.AddLog( $"You draw a {freshCard}. Total: {updatedTotal}" );
await GameTask.Delay( 50 );
RunBlackjackTurnLoop( updatedTotal );
}
} );
blackjackEvent.Options.Add( new EventOption
{
ButtonText = "🔒 STAND WITH TOTAL",
ActionToExecute = () =>
{
ResolveDealerAndMatch( runningPlayerTotal );
}
} );
GameManager.Instance.TriggerChoicePopup( blackjackEvent );
}
private static void ResolveDealerAndMatch( int finalPlayerTotal )
{
var manager = Sandbox.Game.ActiveScene?.Get<GameManager>();
int prestige = manager != null ? manager.CurrentPrestige : 0;
int scaledBlackjackDamage = 40 + (prestige * 5);
int scaledWinDamage = 25 + (prestige * 3);
int scaledTieDamage = 10 + (prestige * 2);
if ( finalPlayerTotal == 21 )
{
GameManager.AddLog( $"** BLACKJACK!! AI loses -{scaledBlackjackDamage} HP! **" );
CombatManager.applyDamage( ref cachedAI, scaledBlackjackDamage );
return;
}
GameManager.AddLog( $"You stand with {finalPlayerTotal}." );
GameManager.AddLog( $"AI reveals hidden total: {secretAITotal}" );
int aiRunningTotal = secretAITotal;
while ( aiRunningTotal < 17 )
{
int card = DrawCard();
aiRunningTotal += card;
GameManager.AddLog( $"AI draws a {card}. Total: {aiRunningTotal}" );
}
if ( aiRunningTotal == 21 )
{
GameManager.AddLog( $"** AI hits 21! You lose {scaledBlackjackDamage} HP! **" );
CombatManager.applyDamage( ref cachedPlayer, scaledBlackjackDamage );
}
else if ( aiRunningTotal > 21 || finalPlayerTotal > aiRunningTotal )
{
GameManager.AddLog( $"** You win with {finalPlayerTotal} vs {aiRunningTotal}! AI loses {scaledWinDamage} HP! **" );
CombatManager.applyDamage( ref cachedAI, scaledWinDamage );
}
else if ( aiRunningTotal > finalPlayerTotal )
{
GameManager.AddLog( $"** AI wins with {aiRunningTotal} vs {finalPlayerTotal}! You lose {scaledWinDamage} HP! **" );
CombatManager.applyDamage( ref cachedPlayer, scaledWinDamage );
}
else
{
GameManager.AddLog( $"** 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}" );
}
}