//::///////////////////////////////////////////////
//:: 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 RefundPlayers(int nLastPlayer);
void BlackJack_Start(object oSpeaker);
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, int nPlayerNumber);
void BlackJack_Join(object oSpeaker, int nPlayerNumber);
int DealerBlackJackCheck(int nCard1, int nCard2);
void DisplayPlayerCards(object oPC);
void CheckBlackJackPushes();
void ClearPlayerVariables(object oPC);
void ClearDealerVariables();

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); //NOT IMPLEMENTED YET
        SetListenPattern(OBJECT_SELF, "Join", 5000); //NOT IMPLEMENTED YET
        SetListenPattern(OBJECT_SELF, "Reset", 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, nPlayerNumber); break; // WIP
            case 5000: BlackJack_Join(oPC, nPlayerNumber); break; // WIP
            case 6000: 
                ClearDealerVariables();
                ClearPlayerVariables(oPC); 
                SpeakString("DEBUG :: BlackJack :: Variables have been reset");
                break;
		}
	}
}

// --- Functions ----------------------------------------------------------------
void BlackJack_Start(object oSpeaker)
{
	// Declarations
	string sPCName = GetName(oSpeaker);
	int nPlayerNumber = GetLocalInt(OBJECT_SELF, "nNumPlayers") + 1;
	int nMaxPlayers = GetLocalInt(OBJECT_SELF, "nMaxPlayers");
	
	// 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;
	}
	
	// No Active Players (NEW GAME or ROUND) - Clear Variables
	if (GetLocalInt(OBJECT_SELF, "nNumPlayers") == 0)
	{
		ClearDealerVariables();
	}
	
	// Always clear player variables when starting a game
	ClearPlayerVariables(oSpeaker);
	
	// 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);

		// Add one to the number of players variable on the Dealer
		SetLocalInt(OBJECT_SELF, "nNumPlayers", nPlayerNumber);
		
		// Deal the player their hand, and only on the final joining player do we also give 
		// the dealer their hand and start the game.
		// * Description edited -DarkSorcerer (July 22, 2026)
		InitialDeal(oSpeaker, nPlayerNumber);
		
		if (nPlayerNumber < nMaxPlayers)
		{
			DelayCommand(2.0f, SpeakString(sPCName + ", you are in. Who else? Please say 'Start'."));
		}
		else
		{
			// Draw Dealer's cards
			int nDealerCard1 = Random(10) + 1;
			int nDealerCard2 = Random(10) + 1;
			AceCheck(nDealerCard1, OBJECT_SELF);
			AceCheck(nDealerCard2, OBJECT_SELF);
			SetLocalInt(OBJECT_SELF, "nDealerCard1", nDealerCard1);
			SetLocalInt(OBJECT_SELF, "nDealerCard2", nDealerCard2);
			SetLocalInt(OBJECT_SELF, "nDealerTotal", nDealerCard1);

			// If Dealer has Blackjack: Game Over (check players for Blackjacks as well)
			// * Players Push if they have a Blackjack; otherwise they lose
			if (DealerBlackJackCheck(nDealerCard1, nDealerCard2))
			{
				DelayCommand(2.0f, SpeakString("Dealer has BlackJack!"));
				DelayCommand(4.0f, CheckBlackJackPushes());
			}
			else 
			{
				// Show players their cards first - then decide on the Dealer's shown card
				DelayCommand(2.0f, DisplayPlayerCards(oSpeaker));
				float fDelay = GetLocalInt(oSpeaker, "nBlackJack") == 1 ? 4.0f : 6.0f;
				
				if (GetLocalInt(OBJECT_SELF, "nDealerTotal") == 1)
				{
					// If Dealer has an Ace
					DelayCommand(fDelay, SpeakString("Dealer is showing an Ace"));
				}
				else
				{
					// Else just say what the dealer has
					DelayCommand(fDelay, SpeakString("Dealer is showing a " + IntToString(nDealerCard1)));
				}

				// Make the Player Counter point to the first player - only they will be able to speak to the Dealer
				// Ask the first player what they want to do
				string sFirstPlayer = GetName(GetLocalObject(OBJECT_SELF, "Player1"));
				DelayCommand(fDelay+2.0f, SpeakString("What do you want to do, " + sFirstPlayer + "?"));
				SetLocalInt(OBJECT_SELF, "nCurrentPlayer", 1);					
			}
		}
	}
	else
	{
		// Not enough tokens to play
		SpeakString(sPCName + ", you don't have enough tokens to play this game! Get Lost! Game Over!!");
		SetListening(OBJECT_SELF, FALSE);
		SetLocalInt(OBJECT_SELF, "nPlayingBlackJack", 0);
		RefundPlayers(nPlayerNumber);
	}
}

// This function is to ensure in a multiplayer game, that the players 
// before "nLastPlayer" aren't losing out on their tokens because nLastPlayer
// didn't have enough (thus ending the game)
// - Added by DarkSorcerer(July 24 2026)
void RefundPlayers(int nLastPlayer)
{
	int i, nWager = GetLocalInt(OBJECT_SELF, "nWager");
	for (i = 1; i < nLastPlayer; i++)
	{
		object oPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(i));
		SpeakString(GetName(oPC) + ". You've been refunded " + IntToString(nWager) + " Tokens!");
		AdjustCasValues(oPC, nWager, 0);
	}
}
       
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, "nMaxPlayers");
	
	// Go through list of failsafes before applying the 'Hit Me' action
	if (GetLocalInt(OBJECT_SELF, "nNumPlayers") < nMaxPlayers)
	{
		SpeakString("Hold your horses! Not everyone is in yet.");
	}
	else if (sPCName != sPlayerName)
	{
		SpeakString("Hold up, " + sPCName + ", its not your turn. Its " + sPlayerName + "'s turn");
	}
	else if (GetLocalInt(oSpeaker, "nGameOn") != 1)
	{
		SpeakString("What are you trying to pull, " + sPCName + ", you're not even in the game!");
	}
	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);
		//Say something different if PC has an Ace
		if (nBlackJackNextCard == 1)
		{
			SpeakString(sPCName+". You've been dealt an Ace");
		}
		else
		{
			//Otherwise just say the total
			SpeakString(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
				DelayCommand(2.0f, SpeakString("That gives you a total of " + IntToString(nBlackJackTotal)));
			}
			else
			{
				//otherwise, he may have two totals since aces can be 1 or 11
				DelayCommand(2.0f, SpeakString("That gives you a total of " + IntToString(nBlackJackTotal) + " or " + IntToString(nTempTotal)));
			}
		}
		else
		{
			DelayCommand(2.0f, SpeakString("That gives you a total of " + IntToString(nBlackJackTotal)));
		}
		//If the PCs true total is greater than 21 then they busted
		if (nBlackJackTotal > 21)
		{
			DelayCommand(3.0f, SpeakString(sPCName + " has Busted. Better luck next time!"));
			SetLocalInt(oSpeaker, "nBusted", 1);
			
			//DelayCommand(1.0f,AssignCommand(oSpeaker,PlaySound("as_pl_laughingm2")));
			//AssignCommand(OBJECT_SELF,PlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING,1.0,1.0));
			//AssignCommand(OBJECT_SELF,ActionSit(GetObjectByTag("DealerChair")));
			// * This is just mean (and irritating to players) - DarkSorcerer (07/16/2026)
			
			//Check to see if this is the last PC and call CardCheck() if it is
			int nCurrentPlayer = GetLocalInt(OBJECT_SELF, "nCurrentPlayer");
			if (nCurrentPlayer == nMaxPlayers)
			{
				DelayCommand(5.0f, DealerDrawRemainingCards());
				DelayCommand(8.0f, CardCheck());
			}
			else
			{
				//If its not - advance to the next player
				SetLocalInt(OBJECT_SELF, "nCurrentPlayer", ++nCurrentPlayer);
				string sNextPlayer = GetName(GetLocalObject(OBJECT_SELF, "Player"+IntToString(nCurrentPlayer)));
				DelayCommand(5.0f, SpeakString("What do you want to do, " + sNextPlayer + "?"));
			}
		}
		else
		{
			DelayCommand(3.0f, SpeakString("What do you want to do, " + sPlayerName + "?"));
		}
	}
}

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, "nMaxPlayers");
	
	// Failsafe - Ensure everyone has entered the game (up to MaxPlayers)
	if (GetLocalInt(OBJECT_SELF, "nNumPlayers") < nMaxPlayers)
	{
		SpeakString("Hold your horses! Not everyone is in yet.");
	}
	else if (sPCName != sPlayerName)
	{
		SpeakString("Hold up, " + sPCName + ", its not your turn. Its " + sPlayerName + "'s turn");
	}
	else if (GetLocalInt(oSpeaker, "nGameOn") != 1)
	{
		SpeakString("What are you trying to pull, " + sPCName + ", you're not even in the game!");
	}
	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)
			{
				SetLocalInt(oSpeaker, "nBlackJackTotal", nTempTotal);
			}
		}

		//Check to see if all PCs have their cards, if so then the dealer can take his
		int nNextPlayer = nPlayerNumber + 1;
		if (nNextPlayer > nMaxPlayers)
		{
			//Loop for the dealer to get his remaining cards
			DelayCommand(2.0f, DealerDrawRemainingCards());
			DelayCommand(4.0f, CardCheck());
		}
		else
		{
			//if not all players have their cards - tell the next player that its their turn
			string sNextPlayer = GetName(GetLocalObject(OBJECT_SELF, "Player"+IntToString(nNextPlayer)));
			DelayCommand(2.0f, SpeakString("Ok, " + sNextPlayer + ", its your turn"));
			SetLocalInt(OBJECT_SELF, "nCurrentPlayer", nNextPlayer);
		}
	}
}

void BlackJack_Total(object oSpeaker, int nPlayerNumber)
{
	object oPlayer = GetLocalObject(OBJECT_SELF, "Player" + IntToString(nPlayerNumber));
	string sPCName = GetName(oSpeaker);
	string sPlayerName = GetName(oPlayer);
	int nBlackJackTotal = GetLocalInt(oSpeaker," nBlackJackTotal");
	if (GetLocalInt(OBJECT_SELF, "nNumPlayers") < GetLocalInt(OBJECT_SELF, "nMaxPlayers"))
	{
		SpeakString("Hold your horses! Not everyone is in yet.");
	}
	else if (sPCName != sPlayerName)
	{
		SpeakString("Hold up, " + sPCName + ", its not your turn. Its " + sPlayerName + "'s turn");
	}
	else if (GetLocalInt(oSpeaker, "nGameOn") != 1)
	{
		SpeakString("What are you trying to pull, " + sPCName + "! We haven't even started yet!");
	}
	else 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, int nPlayerNumber)
{
	// ToDo
    SpeakString("This command is a Work In Progress..");
}

void BlackJack_Join(object oSpeaker, int nPlayerNumber)
{
	// ToDo
    SpeakString("This command is a Work In Progress..");
}

//*****************************************************************************************
void CardCheck()
{
    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;
		}
        DeleteLocalInt(oPC, "nGameOn");

        string sLogMessage;
        string sCharacterName = GetName(oPC);
        string sPlayerUsername = GetPCPlayerName(oPC);
        string sPCId = IntToString(PLAYER_GetId(oPC));
		int nBlackJackTotal = GetLocalInt(oPC, "nBlackJackTotal");
		int nDealerTotal = GetLocalInt(OBJECT_SELF, "nDealerTotal");
        int nWager = GetLocalInt(OBJECT_SELF, "nWager");
        int nReward = 0;

        if (GetLocalInt(oPC, "nBusted") == 1)
        {
            DeleteLocalInt(oPC, "nBusted");
			SpeakString(sCharacterName + ", you busted! Better luck next time.");
            DelayCommand(1.5f, PlayVoiceChat(VOICE_CHAT_CUSS, oPC));
            sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") lost " + IntToString(nWager) + " tokens for busting.";
        }
        else if (GetLocalInt(oPC, "nBlackJack") == 1)
        {
			nReward = nWager * 4;
			DeleteLocalInt(oPC, "nBlackJack");
            SpeakString("BlackJack for " + sCharacterName + "!!!!");
            AssignCommand(oPC, PlaySound("as_mg_telepin1"));
			DelayCommand(1.5f, PlayVoiceChat(VOICE_CHAT_CHEER, oPC));
			DelayCommand(2.0f, AdjustCasValues(oPC, 0, nReward));
            DelayCommand(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)
        {
			nReward = nWager * 3;
			AssignCommand(oPC, PlaySound("as_mg_telepin1"));
			SpeakString("I busted, so you win, " + sCharacterName + "!!!!");
			DelayCommand(1.5f, PlayVoiceChat(VOICE_CHAT_CHEER, oPC));
			DelayCommand(2.0f, AdjustCasValues(oPC, 0, nReward));
			DelayCommand(2.0f, SendMessageToPC(oPC, "You won: " + IntToString(nReward) + " tickets!"));
			sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") won " + IntToString(nReward) + " tickets as dealer busted.";
		}
		else if (nDealerTotal > nBlackJackTotal)
		{
			AssignCommand(oPC, PlaySound("as_mg_telepout1"));
			SpeakString(sCharacterName + ", you lost this round. Maybe next time!");
			DelayCommand(1.5f, PlayVoiceChat(VOICE_CHAT_CUSS, oPC));
			sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") lost " + IntToString(nWager) + " tokens.";
		}
		else if (nDealerTotal < nBlackJackTotal)
		{
			nReward = nWager * 3;
			AssignCommand(oPC, PlaySound("as_mg_telepin1"));
			SpeakString(sCharacterName + ", you win!!!!");
			DelayCommand(1.5f, PlayVoiceChat(VOICE_CHAT_CHEER, oPC));
			DelayCommand(2.0f, AdjustCasValues(oPC, 0, nReward));
			DelayCommand(2.0f, SendMessageToPC(oPC, "You have won: " + IntToString(nReward) + " Tickets!"));
			sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") won " + IntToString(nReward) + " tickets.";
		}
		else
		{
			nReward = nWager;
			SpeakString(sCharacterName + ", we push!!!!");
			DelayCommand(1.5f, PlayVoiceChat(VOICE_CHAT_TAUNT, oPC));
			DelayCommand(2.0f, AdjustCasValues(oPC, 0, nReward));
			DelayCommand(2.0f, SendMessageToPC(oPC, "You will get " + IntToString(nReward) + " Tickets for the push."));
			sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") pushed with dealer. They got" + IntToString(nReward) + "tickets.";
		}
        Log(sLogMessage, "cas");
    }
    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, "nGameOn", 1);
}

void DealerDrawRemainingCards()
{
    string szTempString = "";
	// Update Total (from having pre-dealt the 2 cards to the Dealer for Blackjack checks)
	// * DarkSorcerer (07/16/2026)
	int nDealerTotal = GetLocalInt(OBJECT_SELF, "nDealerTotal") + GetLocalInt(OBJECT_SELF, "nDealerCard2");
    //Draw cards for the dealer as long as the dealers total is less than 17 - Dealer stands on 17
	while (nDealerTotal < 17)
    {
		//Draw another card and update the total
		int nDealerNextCard = Random(10) + 1;
		AceCheck(nDealerNextCard, OBJECT_SELF);
		nDealerTotal = nDealerTotal + nDealerNextCard;
        //If dealer drew an Ace - say so - calculate the total with any aces the Dealer may have
        if (nDealerNextCard == 1)
        {
            int nTempTotal = nDealerTotal + 10;
            if (nTempTotal > 21)
            {
                szTempString = szTempString + "Dealer draws an Ace for a total of " + IntToString(nDealerTotal) + ". ";
            }
            else if (nTempTotal > 16)
			{
				nDealerTotal = nTempTotal;
				szTempString = szTempString + "Dealer draws an Ace for a total of " + IntToString(nTempTotal)+ ". ";
			}
			else 
			{
                szTempString = szTempString + "Dealer draws an Ace for a total of " + IntToString(nTempTotal)+ ". ";
            }
        }
        else
        {
            szTempString = szTempString + "Dealer draws a " + IntToString(nDealerNextCard) + " for a total of " + IntToString(nDealerTotal) + ". ";
        }
    }
    //Check to see if the Dealer has gone over 21 and Busted
    if (nDealerTotal > 21)
    {
        DelayCommand(3.0f, PlayVoiceChat(VOICE_CHAT_CUSS, OBJECT_SELF));
        SetLocalInt(OBJECT_SELF, "nBusted", 1);
    }
	//Save current total (for calls later)
	SetLocalInt(OBJECT_SELF, "nDealerTotal", nDealerTotal);
    //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.
    DelayCommand(2.0f, SpeakString(szTempString));
}

void DisplayPlayerCards()
{
    int i; for (i = 1; i <= GetLocalInt(OBJECT_SELF, "nMaxPlayers"); i++)
    {
        object oPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(i));
               string sPCName = GetName(oPC);
        int nBlackJackCard1 = GetLocalInt(oPC, "nBlackJackCard1");
        int nBlackJackCard2 = GetLocalInt(oPC, "nBlackJackCard2");
        int nBlackJackTotal = GetLocalInt(oPC, "nBlackJackTotal");
        
        //Check for BlackJack (already checked for in InitialDeal)
        if (GetLocalInt(oPC, "nBlackJack") == 1)
        {
            AssignCommand(oPC, PlaySound("as_cv_bell2"));
            SpeakString(sPCName + ". You've got BlackJack!!");
            return;
        }
        
        if (nBlackJackCard1 == 1)
        {
            if (nBlackJackCard2 == 1)
            {
                SpeakString(sPCName + ", you've been dealt an Ace and another Ace");
            }
            else
            {
                SpeakString(sPCName + ", you've been dealt an Ace and a " + IntToString(nBlackJackCard2));
            }
        }
        else if (nBlackJackCard2 == 1)
        {
            SpeakString(sPCName + ", you've been dealt a " + IntToString(nBlackJackCard1) + " and an Ace.");
        }
        else
        {
            SpeakString(sPCName + ", you've been dealt a " + IntToString(nBlackJackCard1) + " and a " + IntToString(nBlackJackCard2));
        }
        string szTempString = ".";
        if (GetLocalInt(oPC, "nAceCount") > 0)
        {
            int nTempTotal = nBlackJackTotal + 10;
            if (nTempTotal < 22)
            {
                szTempString = " or " + IntToString(nTempTotal);
            }
        }
        DelayCommand(2.0f,SpeakString("This gives you a total of " + IntToString(nBlackJackTotal) + szTempString));
    }
}

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()
{
	string sLogMessage;
	int nMaxPlayers = GetLocalInt(OBJECT_SELF, "nMaxPlayers");
	int nReward = GetLocalInt(OBJECT_SELF, "nWager");
	
	// Checks each player for a Black Jack(push) or they lose
	int i; for (i = 1; i <= nMaxPlayers; i++)
	{
		object oPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(i));
		if (!GetIsObjectValid(oPC)) 
		{
			SpeakString("Whoops, player " + IntToString(i) + " does not exist?");
			continue;
		}
		
		string sCharacterName = GetName(oPC);
		string sPlayerUsername = GetPCPlayerName(oPC);
		string sPCId = IntToString(PLAYER_GetId(oPC));
		
		if (GetLocalInt(oPC, "nBlackJack") == 1)
		{
			// Push
			DeleteLocalInt(oPC, "nBlackJack");
			SpeakString(sCharacterName + " also has BlackJack, we push!!!!");
			DelayCommand(1.5f, PlayVoiceChat(VOICE_CHAT_TAUNT, oPC));
			DelayCommand(2.0f, AdjustCasValues(oPC, 0, nReward));
			DelayCommand(2.0f, SendMessageToPC(oPC, "You will get " + IntToString(nReward) + " Tickets for the push."));
			sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") pushed with dealer. They got" + IntToString(nReward) + "tickets.";
		}
		else
		{
			// Lose
			SpeakString(sCharacterName + ", you lose. Better luck next time!");
			AssignCommand(oPC, PlaySound("as_mg_telepout1"));
			DelayCommand(1.5f, PlayVoiceChat(VOICE_CHAT_CUSS, oPC));
			sLogMessage = "Character: " + sCharacterName + ", Player Name: " + sPlayerUsername + " (" + sPCId + ") lost " + IntToString(nReward) + " tokens.";
		}
		Log(sLogMessage, "cas");
	}
	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");
}

void ClearDealerVariables()
{
	int i = 1;
	string sVariable = "Player1";
	while (GetIsObjectValid(GetLocalObject(OBJECT_SELF, sVariable)))
	{
		DeleteLocalObject(OBJECT_SELF, sVariable);
		sVariable = "Player" + IntToString(++i);
	}
	DeleteLocalInt(OBJECT_SELF, "nAceCount");
	DeleteLocalInt(OBJECT_SELF, "nBusted");
	DeleteLocalInt(OBJECT_SELF, "nDealerCard1");
	DeleteLocalInt(OBJECT_SELF, "nDealerCard2");
	DeleteLocalInt(OBJECT_SELF, "nDealerTotal");
}