//::///////////////////////////////////////////////
//:: Default: BLACK JACK USER DEFINED
//:://////////////////////////////////////////////
/*
    Determines the course of action to be taken
    by the Black Jack dealer during the course of a game
*/
//:://////////////////////////////////////////////
//:: Created By: Keith Warner
//:: Created On: July 15, 2002
//:://////////////////////////////////////////////
#include "cas_casinoinc"

void CardCheck();
void AceCheck(int nCard, object oPC);
void InitialDeal(object oPC, int nPlayerNumber);
void DealerDrawRemainingCards();

// Added functions -DarkSorcerer (July 23 2026)
void BlackJack_Start(object oSpeaker);
void BlackJack_Deal();
void BlackJack_HitMe(object oSpeaker, int nPlayerNumber);
void BlackJack_Stand(object oSpeaker, int nPlayerNumber);
void BlackJack_Total(object oSpeaker, int nPlayerNumber);
void BlackJack_Quit(object oSpeaker);
void BlackJack_Join(object oSpeaker);
void BlackJack_Reset(object oSpeaker);
int DealerBlackJackCheck(int nCard1, int nCard2);
void DisplayPlayerCards(object oPC);
void CheckBlackJackPushes();
void ClearPlayerVariables(object oPC);
void ClearDealerVariables();
void Payout_Blackjack(object oPC, float fDelay=0.0f);
void Payout_Win(object oPC, float fDelay=0.0f);
void Payout_Push(object oPC, float fDelay=0.0f);
void Payout_None(object oPC, float fDelay=0.0f);
void AdjustVariables(object oSpeaker, int nPlayerNumber, int nMaxPlayers);
// -----------------------------------------------------------

void main()
{
    object oPC = GetLastSpeaker();
	int nEventNumber = GetUserDefinedEventNumber();
	int nPattern = GetListenPatternNumber();
	
	// on Spawn in - this should run
    // Set the words that the dealer is 'listening' for and give each an event number
    if (nEventNumber == 5000)
    {
        SetListenPattern(OBJECT_SELF, "Start", 500);
        SetListenPattern(OBJECT_SELF, "Hit", 1000);
        SetListenPattern(OBJECT_SELF, "Stand", 2000);
        SetListenPattern(OBJECT_SELF, "Total", 3000);
        SetListenPattern(OBJECT_SELF, "Quit", 4000);
        SetListenPattern(OBJECT_SELF, "Join", 5000);
        SetListenPattern(OBJECT_SELF, "End", 6000);
        SetListening(OBJECT_SELF, FALSE);
    }
	
    // on Dialog event - this should fire
	// - Check if Dealer is listening and the one speaking is a PC
    if (nEventNumber == 1004 && GetIsListening(OBJECT_SELF) && GetIsPC(oPC))
    {
		// Get the active player's ID (failsafe checks)
		int nPlayerNumber = GetLocalInt(OBJECT_SELF, "nCurrentPlayer");
		switch (nPattern)
		{
			case 500:  BlackJack_Start(oPC); break;
			case 1000: BlackJack_HitMe(oPC, nPlayerNumber); break;
			case 2000: BlackJack_Stand(oPC, nPlayerNumber); break;
			case 3000: BlackJack_Total(oPC, nPlayerNumber); break;
            case 4000: BlackJack_Quit(oPC); break;
            case 5000: BlackJack_Join(oPC); break;
            case 6000: BlackJack_Reset(oPC); break;
		}
	}
}

// --- Functions ----------------------------------------------------------------
void BlackJack_Start(object oSpeaker)
{
	// Declarations
	string sPCName = GetName(oSpeaker);
	int nNumPlayers = GetLocalInt(OBJECT_SELF, "nNumPlayers");
	
	// Failsafe - Speaker isn't an Initiator
	if (GetLocalInt(oSpeaker, "nPlayingBlackJack") == 0)
	{
		SpeakString("Only the initiator may 'Start' the game. Others may say 'Join' up to a maximum of 4 players.");
		return;
	}
	// Failsafe - Ensure game is not already in progress for this player
	if (GetLocalInt(oSpeaker, "nGameOn") == 1)
	{
		SpeakString("What are you trying to pull, " + sPCName + ", you've already started!");
		return;
	}
	
	// Ensure the player has the token pouch
	EnsureTokenPouch(oSpeaker);

	// Fetch the token pouch and check the nCAS_TOKEN value
	object oTokenPouch = GetItemPossessedBy(oSpeaker, "I_CAS_CASINOHANDLE");
	int nCasTokens = GetLocalInt(oTokenPouch, "nCAS_TOKEN");
	int nWager = GetLocalInt(OBJECT_SELF, "nWager");
	
	// Compare the nWager with the nCAS_TOKEN value
	if (nCasTokens >= nWager)
	{
		// Deduct the wager from the player's tokens
		AdjustCasValues(oSpeaker, -nWager, 0);
		
		// Clear variables and deal initial hand (doesn't show yet)
		ClearPlayerVariables(oSpeaker);
		InitialDeal(oSpeaker, 1);
		
		// Start the game (prevents any out-of-turn commands)
		SetLocalInt(OBJECT_SELF, "nCurrentPlayer", 1);
		
		// Deals the cards (checks Dealer for BlackJack first before handling players)
		BlackJack_Deal();
	}
	else
	{
		// Not enough tokens to play - kick player
		SpeakString(sPCName + ", you don't have enough tokens to play this game! Get Lost!");
		
		// If there are other players, hand off the Initiator to player 2 - otherwise End Game
		if (nNumPlayers > 1)
		{
			// Adjust variables from the player that is leaving
			AdjustVariables(oSpeaker, 1, nNumPlayers);
			
			// Reduce number of players and clear variables
			SetLocalInt(OBJECT_SELF, "nNumPlayers", --nNumPlayers);
			
			// Last Player notice
			if (nNumPlayers == 1)
			{
				sPCName = GetName(GetLocalObject(OBJECT_SELF, "Player1"));
				DelayCommand(1.5f, SpeakString(sPCName + ", you are the last player! Say 'Start' to begin or wait for others to say 'Join'."));
			}
		}
		else 
		{
			ExecuteScript("cas_bj_playtest3", OBJECT_SELF);
		}
	}
}

void BlackJack_Deal()
{
	// Draw Dealer's cards
	int nDealerCard1 = Random(10) + 1;
	int nDealerCard2 = Random(10) + 1;
	AceCheck(nDealerCard1, OBJECT_SELF);
	AceCheck(nDealerCard2, OBJECT_SELF);
	
	// Pre-Define the cards for end-game drawing
	SetLocalInt(OBJECT_SELF, "nDealerCard1", nDealerCard1);
	SetLocalInt(OBJECT_SELF, "nDealerCard2", nDealerCard2);
	SetLocalInt(OBJECT_SELF, "nDealerTotal", nDealerCard1 + nDealerCard2);

	// If Dealer has Blackjack: Game Over (check players for Blackjacks as well)
	// * Players Push if they have BlackJack; otherwise they lose
	SpeakString("Checking dealer's cards for BlackJack..");
	if (DealerBlackJackCheck(nDealerCard1, nDealerCard2))
	{
		DelayCommand(1.0f, SpeakString("Dealer has BlackJack!!"));
		DelayCommand(2.5f, CheckBlackJackPushes());
	}
	else
	{
		// No BlackJack for dealer, show up-card instead
		if (GetLocalInt(OBJECT_SELF, "nDealerCard1") == 1)
		{
			// If Dealer has an Ace (no BlackJack)
			DelayCommand(1.0f, SpeakString("No BlackJack. Dealer is showing an Ace"));
		}
		else
		{
			// Show Dealer's other card (no BlackJack)
			DelayCommand(1.0f, SpeakString("No BlackJack. Dealer is showing a " + IntToString(nDealerCard1)));
		}
		// Show player cards and get their input (or auto-payout if BlackJack)
		object oPlayer = GetLocalObject(OBJECT_SELF, "Player1");
		int nCurrentPlayer = 1;
		float fDelay = 2.5f;
		DelayCommand(fDelay, DisplayPlayerCards(oPlayer));
		
		// Player has BlackJack (they win!)
		while (GetLocalInt(oPlayer, "nBlackJack") == 1)
		{
			// Automatic payout and move on
			DelayCommand(fDelay+1.5f, SpeakString("BlackJack for " + GetName(oPlayer) + "!!!!"));
			DelayCommand(fDelay+1.5f, Payout_Blackjack(oPlayer, 0.5f));
			
			// Last(only?) player
			if (nCurrentPlayer == GetLocalInt(OBJECT_SELF, "nMaxPlayers"))
			{
				SetLocalInt(OBJECT_SELF, "nCurrentPlayer", 0);
				oPlayer = OBJECT_INVALID;
			}
			else
			{
				// Get Next Player
				fDelay = fDelay + 2.5f;
				oPlayer = GetLocalObject(OBJECT_SELF, "Player"+IntToString(++nCurrentPlayer));
				DelayCommand(fDelay, DisplayPlayerCards(oPlayer));
			}
		}
		
		// If there's any other players that don't have BlackJack
		if (GetIsObjectValid(oPlayer))
		{
			// No BlackJack - receive player's input instead
			DelayCommand(fDelay+1.5f, SpeakString("What do you want to do, " + GetName(oPlayer) + "?"));
			SetLocalInt(OBJECT_SELF, "nCurrentPlayer", nCurrentPlayer);
		}
	}
}
       
void BlackJack_HitMe(object oSpeaker, int nPlayerNumber)
{
	object oPlayer = GetLocalObject(OBJECT_SELF, "Player" + IntToString(nPlayerNumber));
	string sPCName = GetName(oSpeaker);
	string sPlayerName = GetName(oPlayer);
	int nMaxPlayers = GetLocalInt(OBJECT_SELF, "nNumPlayers");
	
	// Go through list of failsafes before applying the 'Hit Me' action
	if (nPlayerNumber == 0)
	{
		SpeakString("The game hasn't even started!");
	}
	else if (GetLocalInt(oSpeaker, "nGameOn") != 1)
	{
		SpeakString("What are you trying to pull, " + sPCName + ", you're not even in the game!");
	}
	else if (sPCName != sPlayerName)
	{
		SpeakString("Hold up, " + sPCName + ", its not your turn. Its " + sPlayerName + "'s turn");
	}
	else
	{
		//Draw a card and check for an Ace
		int nBlackJackNextCard = Random(10) + 1;
		AceCheck(nBlackJackNextCard, oSpeaker);
		//Save the variable and update total
		int nBlackJackTotal = GetLocalInt(oSpeaker, "nBlackJackTotal") + nBlackJackNextCard;
		SetLocalInt(oSpeaker, "nBlackJackNextCard", nBlackJackNextCard);
		SetLocalInt(oSpeaker, "nBlackJackTotal", nBlackJackTotal);
		//Display the player's new card as a combined string
		string szPlayersHand = "";
		if (nBlackJackNextCard == 1)
		{
			//Say something different if PC has an Ace
			szPlayersHand = sPCName+", you've been dealt an Ace. ";
		}
		else
		{
			//Otherwise just say the total
			szPlayersHand = sPCName+", you've been dealt a " + IntToString(nBlackJackNextCard) + ". ";
		}
		//If the PC has any Aces - we may have to give him the option of adding ten to his total
		if (GetLocalInt(oSpeaker, "nAceCount") > 0)
		{
			int nTempTotal = nBlackJackTotal + 10;
			if (nTempTotal > 21)
			{
				//If adding 10 would make it greater than 21 - then he can't use his ace
				szPlayersHand = szPlayersHand + "For a total of " + IntToString(nBlackJackTotal) + ".";
			}
			else
			{
				//otherwise, he may have two totals since aces can be 1 or 11
				szPlayersHand = szPlayersHand + "For a total of " + IntToString(nBlackJackTotal) + " or " + IntToString(nTempTotal) + ".";
			}
		}
		else
		{
			szPlayersHand = szPlayersHand + "For a total of " + IntToString(nBlackJackTotal) + ".";
		}
		SpeakString(szPlayersHand);
		
		//If the PCs true total is greater than 21 then they busted
		if (nBlackJackTotal > 21)
		{
			SetLocalInt(oSpeaker, "nBusted", 1);
			DelayCommand(1.5f, SpeakString(sPCName + " busts!"));
			
			//Check to see if this is the last (or only) PC and call CardCheck() if it is
			float fDelay = 3.0f;
			if (nPlayerNumber == nMaxPlayers)
			{
				DelayCommand(fDelay, DealerDrawRemainingCards());
				DelayCommand(fDelay+1.5f, CardCheck());
			}
			else
			{
				//If its not - advance to the next player
				object oNextPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(++nPlayerNumber));
				DelayCommand(fDelay, DisplayPlayerCards(oNextPC));
				
				while (GetLocalInt(oNextPC, "nBlackJack") == 1)
				{
					// Automatic payout and move on
					DelayCommand(fDelay+1.5f, SpeakString("BlackJack for " + GetName(oNextPC) + "!!!!"));
					DelayCommand(fDelay+1.5f, Payout_Blackjack(oNextPC, 0.5f));
					
					// Last player?
					if (nPlayerNumber == nMaxPlayers)
					{
						SetLocalInt(OBJECT_SELF, "nCurrentPlayer", 0);
						oNextPC = OBJECT_INVALID;
					}
					else
					{
						// Get Next Player
						fDelay = fDelay + 2.5f;
						oNextPC = GetLocalObject(OBJECT_SELF, "Player"+IntToString(++nPlayerNumber));
						DelayCommand(fDelay, DisplayPlayerCards(oNextPC));
					}
				}
				
				if (GetIsObjectValid(oNextPC))
				{
					DelayCommand(fDelay+1.5f, SpeakString("What do you want to do, " + GetName(oNextPC) + "?"));
					SetLocalInt(OBJECT_SELF, "nCurrentPlayer", nPlayerNumber);
				}
			}
		}
		else
		{
			DelayCommand(1.5f, SpeakString("What do you want to do, " + sPCName + "?"));
		}
	}
}

void BlackJack_Stand(object oSpeaker, int nPlayerNumber)
{
	object oPlayer = GetLocalObject(OBJECT_SELF, "Player" + IntToString(nPlayerNumber));
	string sPCName = GetName(oSpeaker);
	string sPlayerName = GetName(oPlayer);
	int nMaxPlayers = GetLocalInt(OBJECT_SELF, "nNumPlayers");
	
	// Go through list of failsafes before applying the 'Stand' action
	if (nPlayerNumber == 0)
	{
		SpeakString("The game hasn't even started!");
	}
	else if (GetLocalInt(oSpeaker, "nGameOn") != 1)
	{
		SpeakString("What are you trying to pull, " + sPCName + ", you're not even in the game!");
	}
	else if (sPCName != sPlayerName)
	{
		SpeakString("Hold up, " + sPCName + ", its not your turn. Its " + sPlayerName + "'s turn");
	}
	else
	{
		//Confirm the player's action to 'Stand'
		SpeakString(sPCName + " stands.");
		
		//Calculate the Players true total (using Aces) and save it as his total
		if (GetLocalInt(oSpeaker, "nAceCount") > 0)
		{
			int nTempTotal = GetLocalInt(oSpeaker, "nBlackJackTotal") + 10;
			if (nTempTotal < 22)
			{
				// Update the total if within the limits (21 or less)
				SetLocalInt(oSpeaker, "nBlackJackTotal", nTempTotal);
			}
		}

		//Check to see if all PCs have their cards, if so then the dealer can take his
		float fDelay = 1.5f;
		if (nPlayerNumber == nMaxPlayers)
		{
			//Loop for the dealer to get his remaining cards
			DelayCommand(fDelay, DealerDrawRemainingCards());
			DelayCommand(fDelay+1.5f, CardCheck());
		}
		else
		{
			//if not all players have their cards - check other players
			object oNextPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(++nPlayerNumber));
			DelayCommand(fDelay, DisplayPlayerCards(oNextPC));
			
			while (GetLocalInt(oNextPC, "nBlackJack") == 1)
			{
				// Automatic payout and move on
				DelayCommand(fDelay+1.5f, SpeakString("BlackJack for " + GetName(oNextPC) + "!!!!"));
				DelayCommand(fDelay+1.5f, Payout_Blackjack(oNextPC, 0.5f));
				
				// Last player?
				if (nPlayerNumber == nMaxPlayers)
				{
					SetLocalInt(OBJECT_SELF, "nCurrentPlayer", 0);
					oNextPC = OBJECT_INVALID;
				}
				else
				{
					// Get Next Player
					fDelay = fDelay + 2.5f;
					oNextPC = GetLocalObject(OBJECT_SELF, "Player"+IntToString(++nPlayerNumber));
					DelayCommand(fDelay, DisplayPlayerCards(oNextPC));
				}
			}
			
			if (GetIsObjectValid(oNextPC))
			{
				DelayCommand(fDelay+1.5f, SpeakString("Ok " + GetName(oNextPC) + ", it's your turn"));
				SetLocalInt(OBJECT_SELF, "nCurrentPlayer", nPlayerNumber);
			}
		}
	}
}

void BlackJack_Total(object oSpeaker, int nPlayerNumber)
{
	object oPlayer = GetLocalObject(OBJECT_SELF, "Player" + IntToString(nPlayerNumber));
	string sPCName = GetName(oSpeaker);	
	string sPlayerName = GetName(oPlayer);
	int nMaxPlayers = GetLocalInt(OBJECT_SELF, "nNumPlayers");
	
	// Check failsafes before performing the 'Total' action
	if (nPlayerNumber == 0)
	{
		SpeakString("The game hasn't even started!");
	}
	else if (GetLocalInt(oSpeaker, "nGameOn") != 1)
	{
		SpeakString("What are you trying to pull, " + sPCName + "! You're not even in the game!");
	}
	else if (sPCName != sPlayerName)
	{
		SpeakString("Hold up, " + sPCName + ", its not your turn. Its " + sPlayerName + "'s turn");
	}
	else
	{
		int nBlackJackTotal = GetLocalInt(oSpeaker, "nBlackJackTotal");
		if (GetLocalInt(oSpeaker, "nAceCount") > 0)
		{
			int nTempTotal = nBlackJackTotal + 10;
			if (nTempTotal < 22)
			{
				SpeakString(sPCName + ", your total is " + IntToString(nBlackJackTotal) + " or " + IntToString(nTempTotal));
			}
			else
			{
				SpeakString(sPCName + ", your total is " + IntToString(nBlackJackTotal));
			}
		}
		else
		{
			SpeakString(sPCName + ", your total is " + IntToString(nBlackJackTotal));
		}
	}
}

void BlackJack_Quit(object oSpeaker)
{
	// Declarations
	string sPCName = GetName(oSpeaker);
	int nNumPlayers = GetLocalInt(OBJECT_SELF, "nNumPlayers");
	int nPlayerNumber = GetLocalInt(oSpeaker, "nBlackJackID");
	
	// Ensure no game is currently running
	if (GetLocalInt(OBJECT_SELF, "nCurrentPlayer") > 0)
	{
		SpeakString(sPCName+", please wait until after the current game.");
	}
	// Check if "Joined" or played at least 1 round..
	else if (nPlayerNumber == 0)
	{
		SpeakString(sPCName + ", you're not even in the group!");
	}
	// Only player in the game - Exit completely
	else if (nNumPlayers == 1)
	{
		// Message and Exit (exiting game clears variables)
		SpeakString("Do come back if you fancy another game!");
		ExecuteScript("cas_bj_playtest3", OBJECT_SELF);
	}
	else
	{				
		// A friendly message
		SpeakString(sPCName+", do come back if you fancy another game!");
		DelayCommand(1.5f, SpeakString("A seat has just opened up. Say 'Join' if you want in on the action!"));
		
		// Adjust variables from the player that is leaving
		AdjustVariables(oSpeaker, nPlayerNumber, nNumPlayers);
		
		// Reduce number of players and clear variables
		SetLocalInt(OBJECT_SELF, "nNumPlayers", --nNumPlayers);
		ClearPlayerVariables(oSpeaker);
		
		// Last Player notice
		if (nNumPlayers == 1)
		{
			sPCName = GetName(GetLocalObject(OBJECT_SELF, "Player1"));
			DelayCommand(3.0f, SpeakString(sPCName + ", you are the last player! Say 'Start' to begin or wait for others to say 'Join'."));
		}
	}
}

void BlackJack_Join(object oSpeaker)
{
	// Declarations
	string sPCName = GetName(oSpeaker);
	int nNumPlayers = GetLocalInt(OBJECT_SELF, "nNumPlayers");
	int nWager = GetLocalInt(OBJECT_SELF, "nWager");
	
	// Ensure no game is currently running
	if (GetLocalInt(OBJECT_SELF, "nCurrentPlayer") > 0)
	{
		SpeakString(sPCName + ", please let the current game finish first.");
	}
	// Failsafe - you're the Initiator
	else if (GetLocalInt(oSpeaker, "nPlayingBlackJack") == 1)
	{
		SpeakString(sPCName + ". You're the initiator - Say 'Start' to begin a game.");
	}
	// Failsafe - you're already in the game
	else if (GetLocalInt(oSpeaker, "nGameOn") == 1)
	{
		SpeakString("What are you trying to pull, " + sPCName + ", you've already started!");
	}
	// Failsafe - no more room
	else if (nNumPlayers == 4)
	{
		SpeakString("Sorry " + sPCName + ", there's no more room at this table!");
	}
	else
	{
		// Clear self-variables - also ensure they have a token pouch
		ClearPlayerVariables(oSpeaker);
		EnsureTokenPouch(oSpeaker);

		// Fetch the token pouch and check the nCAS_TOKEN value
		object oTokenPouch = GetItemPossessedBy(oSpeaker, "I_CAS_CASINOHANDLE");
		int nCasTokens = GetLocalInt(oTokenPouch, "nCAS_TOKEN");
		int nWager = GetLocalInt(OBJECT_SELF, "nWager");
		
		// Compare the nWager with the nCAS_TOKEN value
		if (nCasTokens >= nWager)
		{
			// Deduct the wager from the player's tokens
			AdjustCasValues(oSpeaker, -nWager, 0);

			// Add one to the number of players variable on the Dealer
			SetLocalInt(OBJECT_SELF, "nNumPlayers", ++nNumPlayers);
			
			// Deal the player their cards (but are not yet displayed until later)
			InitialDeal(oSpeaker, nNumPlayers);
			
			// Notify - if any others can join, say so.
			string sRemaining = IntToString(4 - nNumPlayers);
			string sFirstPlayer = GetName(GetLocalObject(OBJECT_SELF, "Player1"));
			string szTempString = ".";
			if ((4 - nNumPlayers) > 0)
			{
				szTempString = szTempString + " Others may say 'Join' to get in on the action!";
			}
			SpeakString(sPCName + " has joined. There are " + sRemaining + " seats that remain" + szTempString);
			DelayCommand(1.5f, SpeakString(sFirstPlayer + ", say 'Start' when you're ready."));
		}
		else
		{
			// Not enough tokens to play
			SpeakString(sPCName + ", you don't have enough tokens to play this game! Get Lost!");
		}
	}
}

void BlackJack_Reset(object oSpeaker)
{
	if (GetLocalInt(oSpeaker, "nPlayingBlackJack") == 0)
	{
		SpeakString("Only the Initiator may restart the game.");
	}
	else if (GetLocalInt(OBJECT_SELF, "nCurrentPlayer") > 0)
	{
		SpeakString("Please wait until the current game finishes.");
	}
	else
	{
		SpeakString("Game Over! Come talk to me if you want to start a new game!");
		ExecuteScript("cas_bj_playtest3", OBJECT_SELF);
	}
}

//*****************************************************************************************
void CardCheck()
{
	float fDelay = 0.0f;
    int nCount, nMaxPlayers = GetLocalInt(OBJECT_SELF, "nMaxPlayers");
    for (nCount = 1; nCount <= nMaxPlayers; nCount++)
    {
		object oPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(nCount));
		if (!GetIsObjectValid(oPC)) 
		{
			SpeakString("Uh oh, Player " + IntToString(nCount) + " doesn't exist?");
			continue;
		}
		// Player was already paid out - skip
		if (GetLocalInt(oPC, "nGameOn") == 0) continue;

		string sCharacterName = GetName(oPC);
		int nBlackJackTotal = GetLocalInt(oPC, "nBlackJackTotal");
		int nDealerTotal = GetLocalInt(OBJECT_SELF, "nDealerTotal");
        if (GetLocalInt(oPC, "nBusted") == 1)
        {
			DelayCommand(fDelay, SpeakString(sCharacterName + ", you busted! Better luck next time."));
			DelayCommand(fDelay, Payout_None(oPC, 0.5f));
        }/* -- Disabled (Player BlackJack handled on their turn) -- DarkSorcerer (July 25 2026)
        else if (GetLocalInt(oPC, "nBlackJack") == 1)
        {
			nReward = nWager * 4;
			DeleteLocalInt(oPC, "nBlackJack");
            DelayCommand(fDelay, SpeakString("BlackJack for " + sCharacterName + "!!!!"));
            DelayCommand(fDelay, AssignCommand(oPC, PlaySound("as_mg_telepin1")));
			DelayCommand(fDelay+1.5f, PlayVoiceChat(VOICE_CHAT_CHEER, oPC));
			DelayCommand(fDelay+2.0f, AdjustCasValues(oPC, 0, nReward));
            DelayCommand(fDelay+2.0f, SendMessageToPC(oPC, "You have won: " + IntToString(nReward) + " Tickets!"));
			sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") won " + IntToString(nReward) + " tickets for Blackjack.";
        }*/
        else if (GetLocalInt(OBJECT_SELF, "nBusted") == 1)
        {
			DelayCommand(fDelay, AssignCommand(oPC, PlaySound("as_mg_telepin1")));
			DelayCommand(fDelay, SpeakString("I busted, so you win, " + sCharacterName + "!!!!"));
			DelayCommand(fDelay, Payout_Win(oPC, 0.5f));
		}
		else if (nDealerTotal > nBlackJackTotal)
		{
			DelayCommand(fDelay, AssignCommand(oPC, PlaySound("as_mg_telepout1")));
			DelayCommand(fDelay, SpeakString(sCharacterName + ", you lost this round. Maybe next time!"));
			DelayCommand(fDelay, Payout_None(oPC, 0.5f));
		}
		else if (nDealerTotal < nBlackJackTotal)
		{
			DelayCommand(fDelay, AssignCommand(oPC, PlaySound("as_mg_telepin1")));
			DelayCommand(fDelay, SpeakString(sCharacterName + ", you win!!!!"));
			DelayCommand(fDelay, Payout_Win(oPC, 0.5f));
		}
		else
		{
			DelayCommand(fDelay, SpeakString(sCharacterName + ", we push!!!!"));
			DelayCommand(fDelay, Payout_Push(oPC, 0.5f));
		}
		fDelay = fDelay + 2.0f;
    }
    SetLocalInt(OBJECT_SELF, "nNumPlayers", 0);
	SetLocalInt(OBJECT_SELF, "nBusted", 0);
	SetLocalInt(OBJECT_SELF, "nCurrentPlayer", 0);
}

// check to see if the card passed in is an Ace, if so - set a variable on that PC
void AceCheck(int nCard, object oPC)
{
    if (nCard == 1)
    {
        SetLocalInt(oPC, "nAceCount", GetLocalInt(oPC, "nAceCount") + 1);
    }
}

void InitialDeal(object oPC, int nPlayerNumber)
{
	//Deal random cards to the Player and check for Aces (either 1 or 11)
	int nBlackJackCard1 = Random(10) + 1;
	int nBlackJackCard2 = Random(10) + 1;
    AceCheck(nBlackJackCard1, oPC);
	AceCheck(nBlackJackCard2, oPC);
	
	//Save card values and the Total
	SetLocalInt(oPC, "nBlackJackCard1", nBlackJackCard1);
	SetLocalInt(oPC, "nBlackJackCard2", nBlackJackCard2);
	SetLocalInt(oPC, "nBlackJackTotal", nBlackJackCard1 + nBlackJackCard2);
	
	//Check for BlackJack
	int nTempTotal = GetLocalInt(oPC, "nBlackJackTotal");
	if (GetLocalInt(oPC, "nAceCount") > 0)
	{
		nTempTotal = nTempTotal + 10;
		if (nTempTotal == 21)
		{
			// BlackJack! (to be checked and called later)
			SetLocalInt(oPC, "nBlackJack", 1);
		}
	}
	
	//Set PCs as local objects (easier to obtain the object in searches)
	SetLocalObject(OBJECT_SELF, "Player" + IntToString(nPlayerNumber), oPC);
	
	//Set this player as "active" for the game (for checks)
	SetLocalInt(oPC, "nBlackJackID", nPlayerNumber);
	SetLocalInt(oPC, "nGameOn", 1);
}

void DealerDrawRemainingCards()
{
	string szDealerHand = "Dealer's second card is ";
	int nDealerCard1 = GetLocalInt(OBJECT_SELF, "nDealerCard1");
	int nDealerNextCard = GetLocalInt(OBJECT_SELF, "nDealerCard2");
	int nDealerTotal = nDealerCard1 + nDealerNextCard;
	int nTempTotal = nDealerTotal + 10;
	// Check first draw (before the while-loop)
	if (nDealerNextCard == 1)
	{
		szDealerHand = szDealerHand + "an Ace. ";
	}
	else 
	{
		szDealerHand = szDealerHand + "a " + IntToString(nDealerNextCard) + ". ";
	}
	// Update total (if applicable)
	if (GetLocalInt(OBJECT_SELF, "nAceCount") > 0 && nTempTotal < 22)
	{
		nDealerTotal = nTempTotal;
	}
	//Draw cards for the dealer as long as the dealers total is less than 17 - Dealer stands on 17
	while (nDealerTotal < 17)
    {
		// Draw new card and check for an Ace
		nDealerNextCard = Random(10) + 1;
		AceCheck(nDealerNextCard, OBJECT_SELF);
		nDealerTotal = nDealerTotal + nDealerNextCard;
		if (nDealerNextCard == 1)
		{
			szDealerHand = szDealerHand + "Dealer draws an Ace. ";
		}
		else 
		{
			szDealerHand = szDealerHand + "Dealer draws a " + IntToString(nDealerNextCard) + ". ";
		}
		// Update-Check for Aces
		if (nDealerNextCard == 1)
		{
			nTempTotal = nDealerTotal + 10;
			if (nTempTotal < 22)
			{
				nDealerTotal = nTempTotal;
			}
		}
	}
	//Update current total (for calls later)
	SetLocalInt(OBJECT_SELF, "nDealerTotal", nDealerTotal);
    
	//Check to see if the Dealer has gone over 21 and Busted
    if (nDealerTotal > 21)
    {
        DelayCommand(1.0f, PlayVoiceChat(VOICE_CHAT_CUSS, OBJECT_SELF));
        SetLocalInt(OBJECT_SELF, "nBusted", 1);
    }
    
	//Display what the dealer has drawn - Best timing seemed to be to say everything at once rather
    //than speaking each time the dealer drew a card.
    SpeakString(szDealerHand + "(Total: " + IntToString(nDealerTotal) + ")");
}

void DisplayPlayerCards(object oPC)
{
	string szPlayersHand, szTempString = ".";
	string sPCName = GetName(oPC);
	int nBlackJackCard1 = GetLocalInt(oPC, "nBlackJackCard1");
	int nBlackJackCard2 = GetLocalInt(oPC, "nBlackJackCard2");
	int nBlackJackTotal = GetLocalInt(oPC, "nBlackJackTotal");
	
	if (nBlackJackCard1 == 1)
	{
		if (nBlackJackCard2 == 1)
		{
			szPlayersHand = sPCName + ", you've been dealt an Ace and another Ace. ";
		}
		else
		{
			szPlayersHand = sPCName + ", you've been dealt an Ace and a " + IntToString(nBlackJackCard2) + ". ";
		}
	}
	else if (nBlackJackCard2 == 1)
	{
		szPlayersHand = sPCName + ", you've been dealt a " + IntToString(nBlackJackCard1) + " and an Ace. ";
	}
	else
	{
		szPlayersHand = sPCName + ", you've been dealt a " + IntToString(nBlackJackCard1) + " and a " + IntToString(nBlackJackCard2) + ". ";
	}
	
	// Tack on the end or an alternate (if showing an Ace)
	if (GetLocalInt(oPC, "nAceCount") > 0)
	{
		int nTempTotal = nBlackJackTotal + 10;
		if (nTempTotal < 22)
		{
			szTempString = " or " + IntToString(nTempTotal) + ".";
		}
	}

	//Check for BlackJack
	if (GetLocalInt(oPC, "nBlackJack") == 1)
	{
		AssignCommand(oPC, PlaySound("as_cv_bell2"));
		DelayCommand(1.0f, SpeakString(sPCName + ", you've got BlackJack!!"));
	}
	else 
	{
		szPlayersHand = szPlayersHand + "For a total of " + IntToString(nBlackJackTotal) + szTempString;
	}
	SpeakString(szPlayersHand);
}

int DealerBlackJackCheck(int nCard1, int nCard2)
{
    int nTempTotal = nCard1 + nCard2;
	if (GetLocalInt(OBJECT_SELF, "nAceCount") > 0) 
	{
		nTempTotal = nTempTotal + 10;
	}
	// does dealer have a blackjack?
	return nTempTotal == 21 ? TRUE : FALSE;
}

void CheckBlackJackPushes()
{
	// Checks each player for a BlackJack(push) or they lose
	float fDelay = 0.0f;
	int i; for (i = 1; i <= GetLocalInt(OBJECT_SELF, "nMaxPlayers"); i++)
	{
		object oPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(i));
		if (!GetIsObjectValid(oPC)) 
		{
			DelayCommand(fDelay, SpeakString("Whoops, Player " + IntToString(i) + " does not exist?"));
			continue;
		}
		// Player already paid out - skip
		if (GetLocalInt(oPC, "nGameOn") == 0) continue;
		
		// Reveal the player's cards
		DelayCommand(fDelay, DisplayPlayerCards(oPC));
		if (GetLocalInt(oPC, "nBlackJack") == 1)
		{
			// Push
			DelayCommand(fDelay, SpeakString(GetName(oPC) + ", we push!!!!"));
			DelayCommand(fDelay, Payout_Push(oPC, 1.5f));
		}
		else
		{
			// Lose
			DelayCommand(fDelay, AssignCommand(oPC, PlaySound("as_mg_telepout1")));
			DelayCommand(fDelay, SpeakString(GetName(oPC) + ", you lose. Better luck next time!"));
			DelayCommand(fDelay, Payout_None(oPC, 0.5f));
		}
		fDelay = fDelay + 2.0f;
	}
	SetLocalInt(OBJECT_SELF, "nNumPlayers", 0);
	SetLocalInt(OBJECT_SELF, "nCurrentPlayer", 0);
}

void ClearPlayerVariables(object oPC)
{
	DeleteLocalInt(oPC, "nAceCount");
	DeleteLocalInt(oPC, "nBlackJack");
	DeleteLocalInt(oPC, "nBlackJackCard1");
	DeleteLocalInt(oPC, "nBlackJackCard2");
	DeleteLocalInt(oPC, "nBlackJackNextCard");
	DeleteLocalInt(oPC, "nBlackJackTotal");
	DeleteLocalInt(oPC, "nBusted");
	DeleteLocalInt(oPC, "nGameOn");
	DeleteLocalInt(oPC, "nBlackJackID");
}

void ClearDealerVariables()
{
	// Only up to 4 maximum players (so clear all 4 slots)
	int i; (for i = 1; i <= 4; i++)
	{
		DeleteLocalObject(OBJECT_SELF, "Player" + IntToString(i));
	}
	DeleteLocalInt(OBJECT_SELF, "nAceCount");
	DeleteLocalInt(OBJECT_SELF, "nBusted");
	DeleteLocalInt(OBJECT_SELF, "nDealerCard1");
	DeleteLocalInt(OBJECT_SELF, "nDealerCard2");
	DeleteLocalInt(OBJECT_SELF, "nDealerTotal");
}

// --- Payout Functions (for easy organization)
void Payout_Blackjack(object oPC, float fDelay=0.0f)
{
	int nReward = GetLocalInt(OBJECT_SELF, "nWager") * 4;
	string sCharacterName = GetName(oPC);
	string sPlayerUsername = GetPCPlayerName(oPC);
	string sPCId = IntToString(PLAYER_GetId(oPC));
	string sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") won " + IntToString(nReward) + " tickets for Blackjack.";
	DelayCommand(fDelay, AssignCommand(oPC, PlaySound("as_mg_telepin1")));
	DelayCommand(fDelay+1.5f, AdjustCasValues(oPC, 0, nReward));
	DelayCommand(fDelay+1.5f, SendMessageToPC(oPC, "You have won: " + IntToString(nReward) + " Tickets for a BlackJack!"));
	DelayCommand(fDelay+2.0f, PlayVoiceChat(VOICE_CHAT_CHEER, oPC));
	Log(sLogMessage, "cas");
	
	// Clear End of Round variables only
	DelayCommand(fDelay, DeleteLocalInt(oPC, "nBlackJack"));
	DelayCommand(fDelay, DeleteLocalInt(oPC, "nBusted"));
	DeleteLocalInt(oPC, "nGameOn");
}

void Payout_Win(object oPC, float fDelay=0.0f)
{
	int nReward = GetLocalInt(OBJECT_SELF, "nWager") * 3;
	string sCharacterName = GetName(oPC);
	string sPlayerUsername = GetPCPlayerName(oPC);
	string sPCId = IntToString(PLAYER_GetId(oPC));
	string sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") won " + IntToString(nReward) + " tickets as dealer busted or had a lesser value.";
	DelayCommand(fDelay+1.5f, AdjustCasValues(oPC, 0, nReward));
	DelayCommand(fDelay+1.5f, SendMessageToPC(oPC, "You won: " + IntToString(nReward) + " tickets!"));
	DelayCommand(fDelay+2.0f, PlayVoiceChat(VOICE_CHAT_CHEER, oPC));
	Log(sLogMessage, "cas");
	
	// Clear End of Round variables only
	DelayCommand(fDelay, DeleteLocalInt(oPC, "nBlackJack"));
	DelayCommand(fDelay, DeleteLocalInt(oPC, "nBusted"));
	DeleteLocalInt(oPC, "nGameOn");
}

void Payout_Push(object oPC, float fDelay=0.0f)
{
	int nReward = GetLocalInt(OBJECT_SELF, "nWager");
	string sCharacterName = GetName(oPC);
	string sPlayerUsername = GetPCPlayerName(oPC);
	string sPCId = IntToString(PLAYER_GetId(oPC));
	string sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") pushed with dealer. They got" + IntToString(nReward) + "tickets.";
	DelayCommand(fDelay+1.5f, AdjustCasValues(oPC, 0, nReward));
	DelayCommand(fDelay+1.5f, SendMessageToPC(oPC, "You will get " + IntToString(nReward) + " Tickets for the push."));
	DelayCommand(fDelay+2.0f, PlayVoiceChat(VOICE_CHAT_TAUNT, oPC));
	Log(sLogMessage, "cas");
	
	// Clear End of Round variables only
	DelayCommand(fDelay, DeleteLocalInt(oPC, "nBlackJack"));
	DelayCommand(fDelay, DeleteLocalInt(oPC, "nBusted"));
	DeleteLocalInt(oPC, "nGameOn");
}

void Payout_None(object oPC, float fDelay=0.0f)
{
	int nWager = GetLocalInt(OBJECT_SELF, "nWager");
	string sCharacterName = GetName(oPC);
	string sPlayerUsername = GetPCPlayerName(oPC);
	string sPCId = IntToString(PLAYER_GetId(oPC));
	string sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") lost " + IntToString(nWager) + " tokens because they busted or dealer had a higher value.";
	DelayCommand(fDelay+2.0f, PlayVoiceChat(VOICE_CHAT_CUSS, oPC));
	Log(sLogMessage, "cas");
	
	// Clear End of Round variables only
	DelayCommand(fDelay, DeleteLocalInt(oPC, "nBlackJack"));
	DelayCommand(fDelay, DeleteLocalInt(oPC, "nBusted"));
	DeleteLocalInt(oPC, "nGameOn");
}

void AdjustVariables(object oSpeaker, int nPlayerNumber, int nMaxPlayers)
{
	int i; for (i = nPlayerNumber; i < nMaxPlayers; i++)
	{
		object oNextPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(i+1));
		SetLocalObject(OBJECT_SELF, "Player" + IntToString(i), oNextPC);
		SetLocalInt(oNextPC, "nBlackJackID", i);
		// If the "Initiator" left, we set next player as the new one
		if (i == 1)
		{
			SetLocalInt(oNextPC, "nPlayingBlackJack", 1);
			DeleteLocalInt(oSpeaker, "nPlayingBlackJack");
		}
	}
}
