//::///////////////////////////////////////////////
//:: 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_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();
int GetIsGameRunning();
int GetBlackJackID(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 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, "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); break;
            case 5000: BlackJack_Join(oPC); break;
            case 6000: BlackJack_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();
	}
	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)
		{
			SpeakString(sPCName + ", you are in. Who else? Please say 'Start'.");
		}
		else
		{
			SpeakString("Checking dealer's cards for BlackJack..");
			
			// 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
			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("Dealer is showing an Ace"));
				}
				else
				{
					// Show Dealer's other card (no BlackJack)
					DelayCommand(1.0f, SpeakString("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
					fDelay = fDelay + 1.5f;
					DelayCommand(fDelay, SpeakString("BlackJack for " + GetName(oPlayer) + "!!!!"));
					DelayCommand(fDelay, Payout_Blackjack(oPlayer, 0.5f));
					
					// Last(only?) player
					if (nCurrentPlayer == nMaxPlayers)
					{
						SetLocalInt(OBJECT_SELF, "nNumPlayers", 0);
						SetLocalInt(OBJECT_SELF, "nCurrentPlayer", 0);
						oPlayer = OBJECT_INVALID;
					}
					else
					{
						// Get Next Player
						oPlayer = GetLocalObject(OBJECT_SELF, "Player"+IntToString(++nCurrentPlayer));
					}
				}
				
				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);
				}
			}
		}
	}
	else
	{
		// Not enough tokens to play - kick player
		SpeakString(sPCName + ", you don't have enough tokens to play this game! Get Lost!");
		if (nMaxPlayers > 1)
		{
			SetLocalInt(OBJECT_SELF, "nMaxPlayers", --nMaxPlayers);
		}
		else
		{
			// No more players - shut down game
			ExecuteScript("cas_bj_playtest3", OBJECT_SELF);
		}
	}
}
       
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
		string szPlayersHand = "";
		if (nBlackJackNextCard == 1)
		{
			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)
		{
			DelayCommand(1.5f, SpeakString("Sorry " + sPCName + ", that's a Bust. Better luck next time!"));
			SetLocalInt(oSpeaker, "nBusted", 1);
			
			//Check to see if this is the last PC and call CardCheck() if it is
			if (nPlayerNumber == nMaxPlayers)
			{
				DelayCommand(3.0f, DealerDrawRemainingCards());
				DelayCommand(4.5f, CardCheck());
			}
			else
			{
				//If its not - advance to the next player
				object oNextPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(++nPlayerNumber));
				DelayCommand(3.0f, DisplayPlayerCards(oNextPC));
				DelayCommand(4.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, "nMaxPlayers");
	
	// Go through list of failsafes before applying the 'Stand' 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
	{
		//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
		if (nPlayerNumber == nMaxPlayers)
		{
			//Loop for the dealer to get his remaining cards
			DelayCommand(1.5f, DealerDrawRemainingCards());
			DelayCommand(3.0f, CardCheck());
		}
		else
		{
			//if not all players have their cards - tell the next player that its their turn
			object oNextPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(++nPlayerNumber));
			DelayCommand(1.5f, DisplayPlayerCards(oNextPC));
			DelayCommand(3.0f, SpeakString("Ok " + GetName(oNextPC) + ", its 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, "nMaxPlayers");
	
	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
	{
		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 nMaxPlayers = GetLocalInt(OBJECT_SELF, "nMaxPlayers");
	int nPlayerNumber = GetBlackJackID(oSpeaker);
	
	// Ensure no game is currently running
	if (GetIsGameRunning())
	{
		SpeakString(sPCName+", please wait until after the current game.");
	}
	// Check if "Joined" or played at least 1 round..
	else if (GetLocalInt(oSpeaker, "nPlayingBlackJack") == 0 || nPlayerNumber == 0)
	{
		SpeakString(sPCName + ", you're not even in the group!");
	}
	// Only player in the game - Exit completely
	else if (nMaxPlayers == 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!");
		
		// Adjust variables from the player that is leaving
		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);
		}
		
		// Reduce maximum number of players and clear the variables
		SetLocalInt(OBJECT_SELF, "nMaxPlayers", --nMaxPlayers);
		ClearPlayerVariables(oSpeaker);
		
		// Last Player notice
		if (nMaxPlayers == 1)
		{
			sPCName = GetName(GetLocalObject(OBJECT_SELF, "Player1"));
			SpeakString(sPCName + ", you are the last player!");
		}
	}
}

void BlackJack_Join(object oSpeaker)
{
	// Declarations
	string sPCName = GetName(oSpeaker);
	int nMaxPlayers = GetLocalInt(OBJECT_SELF, "nMaxPlayers");
	
	// Ensure no game is currently running
	if (GetIsGameRunning())
	{
		SpeakString("Let the current game finish first.");
	}
	// Failsafe - you're already in the group
	else if (GetLocalInt(oSpeaker, "nPlayingBlackJack") == 1)
	{
		SpeakString("You're already a part of the group, " + sPCName + "!");
	}
	else
	{
		// Increase maximum players
		SetLocalInt(OBJECT_SELF, "nMaxPlayers", ++nMaxPlayers);
		SetLocalInt(oSpeaker, "nPlayingBlackJack", 1);
		
		// Now declare the player has joined
		SpeakString(sPCName + " has joined the group. Someone say 'Start' to begin.");
	}
}

void BlackJack_Reset()
{
    int i = 1;
	string sVariable = "Player1";
	object oPC = GetLocalObject(OBJECT_SELF, sVariable);
	while (GetIsObjectValid(oPC))
    {
        ClearPlayerVariables(oPC); 
		oPC = GetLocalObject(OBJECT_SELF, "Player" + IntToString(++i));
    }
    ClearDealerVariables();
    SpeakString("I think I caught The Bug *coughs*. Don't worry, I'm feeling better already!");
}

int GetIsGameRunning()
{
	int i; for (i = 1; i <= GetLocalInt(OBJECT_SELF, "nMaxPlayers"); i++)
	{
		object oPlayer = GetLocalObject(OBJECT_SELF, "Player" + IntToString(i));
		if (!GetIsObjectValid(oPlayer)) continue;
		
		if (GetLocalInt(oPlayer, "nGameOn") == 1)
		{
			return TRUE;
		}
	}
	return FALSE;
}

int GetBlackJackID(object oSpeaker)
{
	string sSpeakerName = GetName(oSpeaker);
	int i, nPlayerNumber = GetLocalInt(oSpeaker, "nBlackJackID");
	if (nPlayerNumber == 0)
	{
		for (i = 1; i <= GetLocalInt(OBJECT_SELF, "nMaxPlayers"); i++)
		{
			object oPlayer = GetLocalObject(OBJECT_SELF, "Player" + IntToString(i));
			if (GetName(oPlayer) == sSpeakerName)
			{
				return i;
			}
		}
	}
	return nPlayerNumber;
}

//*****************************************************************************************
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;
		}
		// We do not clear "nBlackJackID" or "nPlayingBlackJack", only "nGameOn"
		// so that the 'Quit' command is still available to them
        DeleteLocalInt(oPC, "nGameOn");

		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 + 1.5f;
    }
    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, "nPlayingBlackJack", 1); // "Group" tracking
	SetLocalInt(oPC, "nBlackJackID", nPlayerNumber); // for the 'Quit' and 'Join' commands
	SetLocalInt(oPC, "nGameOn", 1); // is "Active" (in a game)
}

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
		int 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;
		}
		// We do not clear "nBlackJackID" or "nPlayingBlackJack", only "nGameOn"
		// so that the 'Quit' command is still available to them
		DeleteLocalInt(oPC, "nGameOn");
		
		// 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 + 3.5f;
	}
	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, "nPlayingBlackJack");
	DeleteLocalInt(oPC, "nBlackJackID");
}

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");
}

// --- 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+2.0f, PlayVoiceChat(VOICE_CHAT_CHEER, oPC));
	DelayCommand(fDelay+1.5f, AdjustCasValues(oPC, 0, nReward));
	DelayCommand(fDelay+1.5f, SendMessageToPC(oPC, "You have won: " + IntToString(nReward) + " Tickets for a BlackJack!"));
	Log(sLogMessage, "cas");
	
	// Clear End of Round variables only
	DelayCommand(fDelay, DeleteLocalInt(oPC, "nBlackJack"));
	DelayCommand(fDelay, DeleteLocalInt(oPC, "nBusted"));
}

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"));
}

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"));
}

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"));
}
