/* Blackjack NUI Game Created By: Daz */ #include "inc_nui" // CONFIGURATION const int BJ_MAX_BET = 500; const int BJ_DOUBLE_DOWN_MIN_POINTS = 9; const int BJ_DOUBLE_DOWN_MAX_POINTS = 11; const int BJ_DOUBLE_DOWN_EXCEED_MAX_BET = TRUE; const int BJ_DEALER_STAND_VALUE = 17; const float BJ_DEALER_TURN_DELAY_MIN = 0.75f; const int BJ_DEALER_TURN_DELAY_RANDOM = 75; const int BJ_HAND_NUM_CARDS = 6; // ***** const string BJ_WINDOW_ID = "BJ_GAME"; const string BJ_WINDOW_JSON = "BJ_WINDOW_JSON"; const string BJ_WINDOW_GEOMETRY = "BJ_WINDOW_GEOMETRY"; const float BJ_WINDOW_MINIMUM_WIDTH = 100.0f; const float BJ_WINDOW_HEIGHT = 600.0f; const float BJ_BUTTON_WIDTH = 125.0f; const float BJ_CARD_WIDTH = 100.0f; const float BJ_CARD_HEIGHT = 145.0f; const int BJ_BLACKJACK_VALUE = 21; const int BJ_DRAW_CARD_RANDOM = -1; const int BJ_DRAW_CARD_TOP = 0; const string BJ_DECK_JSON = "BJ_DECK_JSON"; const string BJ_PLAYER_HAND = "player"; const string BJ_DEALER_HAND = "dealer"; const string BJ_CARD_BACK = "pc_back"; const string BJ_CARD_BLANK = "pc_blank"; const string BJ_PLAYER_CARD_PREFIX = "pcard_"; const string BJ_DEALER_CARD_PREFIX = "dcard_"; const string BJ_ID_BUTTON_HIT = "btn_hit"; const string BJ_ID_BUTTON_DEAL = "btn_deal"; const string BJ_ID_BUTTON_STAND = "btn_stand"; const string BJ_ID_BUTTON_BET = "btn_bet"; const string BJ_ID_BUTTON_DOUBLE_DOWN = "btn_doubledown"; const string BJ_BIND_DEALER_NAME = "dealer_name"; const string BJ_BIND_DEALER_POINTS = "dealer_points"; const string BJ_BIND_PLAYER_NAME = "player_name"; const string BJ_BIND_PLAYER_POINTS = "player_points"; const string BJ_BIND_INFO_TEXT = "info_text"; const string BJ_BIND_BET_AMOUNT = "bet_amount"; const string BJ_BIND_BET_AMOUNT_VISIBLE = "bet_amount_v"; const string BJ_BIND_GOLD_RESULT = "gold_result"; const string BJ_BIND_CURRENT_BET = "current_bet"; const string BJ_BIND_STATS_TOOLTIP = "stats"; const string BJ_PLAYER_STATS = "BJ_PLAYER_STATS"; const int BJ_STATS_TYPE_TOTAL = 0; const int BJ_STATS_TYPE_WINS = 1; const int BJ_STATS_TYPE_DRAWS = 2; const int BJ_STATS_TYPE_LOSSES = 3; const string BJ_BIND_BUTTON_VISIBLE_HIT = "btn_hit_v"; const string BJ_BIND_BUTTON_VISIBLE_DEAL = "btn_deal_v"; const string BJ_BIND_BUTTON_VISIBLE_STAND = "btn_stand_v"; const string BJ_BIND_BUTTON_VISIBLE_BET = "btn_bet_v"; const string BJ_BIND_BUTTON_VISIBLE_DOUBLE_DOWN = "btn_doubledown_v"; const string BJ_BIND_BUTTON_ENABLED_HIT = "btn_hit_e"; const string BJ_BIND_BUTTON_ENABLED_DEAL = "btn_deal_e"; const string BJ_BIND_BUTTON_ENABLED_STAND = "btn_stand_e"; const string BJ_BIND_BUTTON_ENABLED_BET = "btn_bet_e"; const string BJ_BIND_BUTTON_ENABLED_DOUBLE_DOWN = "btn_doubledown_e"; const string BJ_GAME_STATE = "BJ_GAME_STATE"; const int BJ_GAME_STATE_NONE = 0; const int BJ_GAME_STATE_DEAL_CARDS = 1; const int BJ_GAME_STATE_PLAYER_TURN = 2; const int BJ_GAME_STATE_DEALER_TURN = 3; const int BJ_GAME_STATE_GAME_OVER = 4; const int BJ_DEALER_TURN_NONE = 0; const int BJ_DEALER_TURN_REVEAL_CARD = 1; const int BJ_DEALER_TURN_DRAW_CARD = 2; const int BJ_DEALER_TURN_CHECK_POINTS = 3; const int BJ_DEAL_CARDS_START = 0; const int BJ_DEAL_CARDS_PEEK = 5; json BJ_NuiCard(string sPrefix, int nCard); json BJ_GetWindowJson(); int BJ_GetWindowId(object oPlayer); json BJ_GetUserData(object oPlayer); void BJ_SetUserData(object oPlayer, string sKey, json jData); void BJ_DeleteUserData(object oPlayer, string sKey); void BJ_ToggleButton(object oPlayer, string sButton, int bEnabled); void BJ_SetDealer(object oPlayer, object oDealer); object BJ_GetDealer(object oPlayer); string BJ_GetDealerName(object oPlayer); json BJ_CreateDeck(); void BJ_SetDeck(object oPlayer, json jDeck); json BJ_GetDeck(object oPlayer); void BJ_DeleteDeck(object oPlayer); void BJ_ShuffleDeck(object oPlayer); void BJ_SetHand(object oPlayer, string sHand, json jHand); json BJ_GetHand(object oPlayer, string sHand); void BJ_DeleteHand(object oPlayer, string sHand); void BJ_InsertCardIntoHand(object oPlayer, string sHand, json jCard); void BJ_SetHandAces(object oPlayer, string sHand, int nAces); int BJ_GetHandAces(object oPlayer, string sHand); void BJ_DeleteHandAces(object oPlayer, string sHand); void BJ_IncreaseHandAces(object oPlayer, string sHand); void BJ_ResetHands(object oPlayer); string BJ_GetCardImage(json jCard); int BJ_GetCardIsAce(json jCard); int BJ_GetHandIsBlackjack(object oPlayer, string sHand); json BJ_GetCardFromDeck(object oPlayer, int nIndex); void BJ_DrawCard(object oPlayer, string sHand); int BJ_CreateGameWindow(object oPlayer); void BJ_SetPlayerName(object oPlayer, int nToken, string sName); void BJ_SetPlayerPoints(object oPlayer, int nToken, int nPoints); void BJ_SetDealerName(object oPlayer, int nToken, string sName); void BJ_SetDealerPoints(object oPlayer, int nTokenn, int nPoints); void BJ_SetInfoText(object oPlayer, int nToken, string sText); void BJ_SetGoldResultText(object oPlayer, int nToken, string sResult); void BJ_SetCurrentBetText(object oPlayer, int nToken, string sCurrentBet); void BJ_SetCard(object oPlayer, int nToken, string sPrefix, int nCard, string sImage); void BJ_BlankCards(object oPlayer, int nToken); void BJ_StartGame(object oPlayer, object oDealer); void BJ_EndGame(object oPlayer); void BJ_HandleNUIEvents(object oPlayer, int nToken, string sType, string sElement, int nArrayIndex, json jPayload); void BJ_SetGameState(object oPlayer, int nState, string sInfoText = "", float fBetResultMultiplier = 0.0f); int BJ_GetGameState(object oPlayer); void BJ_DeleteGameState(object oPlayer); float BJ_GetDealerTurnDelay(); void BJ_HandleDealerTurn(object oPlayer, int nToken, int nCurrentState); void BJ_HandleDealCards(object oPlayer, int nToken, int nCurrentState); void BJ_UpdateCards(object oPlayer, int nToken); int BJ_GetCardValue(json jCard); int BJ_GetHandPoints(object oPlayer, string sHand); void BJ_UpdatePoints(object oPlayer, int nToken); void BJ_ToggleBetInput(object oPlayer, int nToken, int bVisible); int BJ_GetBet(object oPlayer); void BJ_SetBet(object oPlayer, int nBet); void BJ_DeleteBet(object oPlayer); void BJ_IncreaseBet(object oPlayer, int nIncrease); void BJ_SettleBet(object oPlayer, int nToken, float fMultiplier); void BJ_PlaySound(object oPlayer, string sSound); int BJ_GetPlayerCanDoubleDown(object oPlayer); json BJ_CreateStatsObject(); json BJ_GetStats(object oPlayer); void BJ_SetStats(object oPlayer, json jStats); void BJ_UpdateStats(object oPlayer, int nType); void BJ_UpdateStatsTooltip(object oPlayer, int nToken); json BJ_NuiCard(string sPrefix, int nCard) { string sCard = sPrefix + IntToString(nCard); json jImage = NuiImage(NuiBind(sCard), JsonInt(NUI_ASPECT_EXACTSCALED), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE)); jImage = NuiWidth(jImage, BJ_CARD_WIDTH); jImage = NuiHeight(jImage, BJ_CARD_HEIGHT); return jImage; } json BJ_GetWindowJson() { json jWindow = GetLocalJson(GetModule(), BJ_WINDOW_JSON); if (!JsonGetType(jWindow)) { json jCol; json jRow; jCol = JsonArray(); jRow = JsonArray(); { json jDealerPoints = NuiHeader(NuiBind(BJ_BIND_DEALER_POINTS), 30.0f, 30.0f); jDealerPoints = NuiTooltip(jDealerPoints, JsonString("Dealer Points")); jRow = JsonArrayInsert(jRow, jDealerPoints); json jDealerName = NuiHeader(NuiBind(BJ_BIND_DEALER_NAME), 30.0f); jRow = JsonArrayInsert(jRow, jDealerName); } jCol = NuiInsertRow(jCol, jRow); jRow = JsonArray(); { jRow = JsonArrayInsert(jRow, NuiSpacer()); int nCard; for (nCard = 0; nCard < BJ_HAND_NUM_CARDS; nCard++) { jRow = JsonArrayInsert(jRow, BJ_NuiCard(BJ_DEALER_CARD_PREFIX, nCard)); } jRow = JsonArrayInsert(jRow, NuiSpacer()); } jCol = NuiInsertRow(jCol, jRow); jCol = NuiInsertRow(jCol, JsonArrayInsert(JsonArray(), NuiSpacer())); jRow = JsonArray(); { jRow = JsonArrayInsert(jRow, NuiLabel(NuiBind(BJ_BIND_INFO_TEXT), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE))); } jCol = NuiInsertRow(jCol, jRow); jRow = JsonArray(); { jRow = JsonArrayInsert(jRow, NuiLabel(NuiBind(BJ_BIND_GOLD_RESULT), JsonInt(NUI_HALIGN_CENTER), JsonInt(NUI_VALIGN_MIDDLE))); } jCol = NuiInsertRow(jCol, jRow); jRow = JsonArray(); { jRow = JsonArrayInsert(jRow, NuiSpacer()); json jBetInput = NuiTextEdit(JsonString("Amount..."), NuiBind(BJ_BIND_BET_AMOUNT), GetStringLength(IntToString(BJ_MAX_BET)), FALSE); jBetInput = NuiVisible(jBetInput, NuiBind(BJ_BIND_BET_AMOUNT_VISIBLE)); jBetInput = NuiWidth(jBetInput, 100.0f); jBetInput = NuiHeight(jBetInput, 30.0f); jRow = JsonArrayInsert(jRow, jBetInput); json jBetButton = NuiButton(JsonString("Bet")); jBetButton = NuiTooltip(jBetButton, JsonString("Max " + IntToString(BJ_MAX_BET) + " gold, all bets are final!")); jBetButton = NuiId(jBetButton, BJ_ID_BUTTON_BET); jBetButton = NuiEnabled(jBetButton, NuiBind(BJ_BIND_BUTTON_ENABLED_BET)); jBetButton = NuiVisible(jBetButton, NuiBind(BJ_BIND_BUTTON_VISIBLE_BET)); jBetButton = NuiWidth(jBetButton, 100.0f); jBetButton = NuiHeight(jBetButton, 30.0f); jRow = JsonArrayInsert(jRow, jBetButton); jRow = JsonArrayInsert(jRow, NuiSpacer()); } jCol = NuiInsertRow(jCol, jRow); jCol = NuiInsertRow(jCol, JsonArrayInsert(JsonArray(), NuiSpacer())); jRow = JsonArray(); { jRow = JsonArrayInsert(jRow, NuiSpacer()); int nCard; for (nCard = 0; nCard < BJ_HAND_NUM_CARDS; nCard++) { jRow = JsonArrayInsert(jRow, BJ_NuiCard(BJ_PLAYER_CARD_PREFIX, nCard)); } jRow = JsonArrayInsert(jRow, NuiSpacer()); } jCol = NuiInsertRow(jCol, jRow); jRow = JsonArray(); { json jPlayerPoints = NuiHeader(NuiBind(BJ_BIND_PLAYER_POINTS), 30.0f, 30.0f); jPlayerPoints = NuiTooltip(jPlayerPoints, JsonString("Player Points")); jRow = JsonArrayInsert(jRow, jPlayerPoints); json jPlayerName = NuiHeader(NuiBind(BJ_BIND_PLAYER_NAME), 30.0f); jPlayerName = NuiTooltip(jPlayerName, NuiBind(BJ_BIND_STATS_TOOLTIP)); jRow = JsonArrayInsert(jRow, jPlayerName); json jPlayerBet = NuiHeader(NuiBind(BJ_BIND_CURRENT_BET), 30.0f, 125.0f); jRow = JsonArrayInsert(jRow, jPlayerBet); } jCol = NuiInsertRow(jCol, jRow); jRow = JsonArray(); { jRow = JsonArrayInsert(jRow, NuiSpacer()); json jDealButton = NuiButton(JsonString("Deal")); jDealButton = NuiId(jDealButton, BJ_ID_BUTTON_DEAL); jDealButton = NuiEnabled(jDealButton, NuiBind(BJ_BIND_BUTTON_ENABLED_DEAL)); jDealButton = NuiVisible(jDealButton, NuiBind(BJ_BIND_BUTTON_VISIBLE_DEAL)); jDealButton = NuiWidth(jDealButton, BJ_BUTTON_WIDTH); jDealButton = NuiHeight(jDealButton, 30.0f); jRow = JsonArrayInsert(jRow, jDealButton); jRow = JsonArrayInsert(jRow, NuiSpacer()); json jHitButton = NuiButton(JsonString("Hit")); jHitButton = NuiId(jHitButton, BJ_ID_BUTTON_HIT); jHitButton = NuiEnabled(jHitButton, NuiBind(BJ_BIND_BUTTON_ENABLED_HIT)); jHitButton = NuiVisible(jHitButton, NuiBind(BJ_BIND_BUTTON_VISIBLE_HIT)); jHitButton = NuiWidth(jHitButton, BJ_BUTTON_WIDTH); jHitButton = NuiHeight(jHitButton, 30.0f); jRow = JsonArrayInsert(jRow, jHitButton); json jDoubleDownButton = NuiButton(JsonString("Double Down")); jDoubleDownButton = NuiId(jDoubleDownButton, BJ_ID_BUTTON_DOUBLE_DOWN); jDoubleDownButton = NuiEnabled(jDoubleDownButton, NuiBind(BJ_BIND_BUTTON_ENABLED_DOUBLE_DOWN)); jDoubleDownButton = NuiVisible(jDoubleDownButton, NuiBind(BJ_BIND_BUTTON_VISIBLE_DOUBLE_DOWN)); jDoubleDownButton = NuiWidth(jDoubleDownButton, BJ_BUTTON_WIDTH); jDoubleDownButton = NuiHeight(jDoubleDownButton, 30.0f); jRow = JsonArrayInsert(jRow, jDoubleDownButton); json jStandButton = NuiButton(JsonString("Stand")); jStandButton = NuiId(jStandButton, BJ_ID_BUTTON_STAND); jStandButton = NuiEnabled(jStandButton, NuiBind(BJ_BIND_BUTTON_ENABLED_STAND)); jStandButton = NuiVisible(jStandButton, NuiBind(BJ_BIND_BUTTON_VISIBLE_STAND)); jStandButton = NuiWidth(jStandButton, BJ_BUTTON_WIDTH); jStandButton = NuiHeight(jStandButton, 30.0f); jRow = JsonArrayInsert(jRow, jStandButton); jRow = JsonArrayInsert(jRow, NuiSpacer()); } jCol = NuiInsertRow(jCol, jRow); json jRoot = NuiCol(jCol); jWindow = NuiWindow(jRoot, JsonString("Blackjack"), NuiBind(NUI_WINDOW_GEOMETRY_BIND), JsonBool(FALSE), JsonNull(), JsonBool(TRUE), JsonBool(FALSE), JsonBool(TRUE)); SetLocalJson(GetModule(), BJ_WINDOW_JSON, jWindow); PrintString(JsonDump(jWindow)); } return jWindow; } json BJ_CreateDeck() { json jDeck = GetLocalJson(GetModule(), BJ_DECK_JSON); if (!JsonGetType(jDeck)) { jDeck = JsonArray(); json jSuits = JsonArray(); jSuits = JsonArrayInsert(jSuits, JsonString("clubs")); jSuits = JsonArrayInsert(jSuits, JsonString("diamonds")); jSuits = JsonArrayInsert(jSuits, JsonString("hearts")); jSuits = JsonArrayInsert(jSuits, JsonString("spades")); json jValues = JsonArray(); jValues = JsonArrayInsert(jValues, JsonString("2")); jValues = JsonArrayInsert(jValues, JsonString("3")); jValues = JsonArrayInsert(jValues, JsonString("4")); jValues = JsonArrayInsert(jValues, JsonString("5")); jValues = JsonArrayInsert(jValues, JsonString("6")); jValues = JsonArrayInsert(jValues, JsonString("7")); jValues = JsonArrayInsert(jValues, JsonString("8")); jValues = JsonArrayInsert(jValues, JsonString("9")); jValues = JsonArrayInsert(jValues, JsonString("10")); jValues = JsonArrayInsert(jValues, JsonString("j")); jValues = JsonArrayInsert(jValues, JsonString("q")); jValues = JsonArrayInsert(jValues, JsonString("k")); jValues = JsonArrayInsert(jValues, JsonString("a")); int nSuit, nNumSuits = JsonGetLength(jSuits); int nValue, nNumValues = JsonGetLength(jValues); for (nSuit = 0; nSuit < nNumSuits; nSuit++) { for (nValue = 0; nValue < nNumValues; nValue++) { json jCard = JsonObject(); jCard = JsonObjectSet(jCard, "suit", JsonArrayGet(jSuits, nSuit)); jCard = JsonObjectSet(jCard, "value", JsonArrayGet(jValues, nValue)); jDeck = JsonArrayInsert(jDeck, jCard); } } SetLocalJson(GetModule(), BJ_DECK_JSON, jDeck); } return jDeck; } int BJ_GetWindowId(object oPlayer) { return NuiFindWindow(oPlayer, BJ_WINDOW_ID); } json BJ_GetUserData(object oPlayer) { json jUserData = NuiGetUserData(oPlayer, NuiFindWindow(oPlayer, BJ_WINDOW_ID)); return !JsonGetType(jUserData) ? JsonObject() : jUserData; } void BJ_SetUserData(object oPlayer, string sKey, json jData) { NuiSetUserData(oPlayer, NuiFindWindow(oPlayer, BJ_WINDOW_ID), JsonObjectSet(BJ_GetUserData(oPlayer), sKey, jData)); } void BJ_DeleteUserData(object oPlayer, string sKey) { NuiSetUserData(oPlayer, NuiFindWindow(oPlayer, BJ_WINDOW_ID), JsonObjectDel(BJ_GetUserData(oPlayer), sKey)); } void BJ_ToggleButton(object oPlayer, string sButton, int bEnabled) { NuiSetBind(oPlayer, BJ_GetWindowId(oPlayer), sButton + "_e", JsonBool(bEnabled)); NuiSetBind(oPlayer, BJ_GetWindowId(oPlayer), sButton + "_v", JsonBool(bEnabled)); } void BJ_SetDealer(object oPlayer, object oDealer) { BJ_SetUserData(oPlayer, "dealer", JsonString(ObjectToString(oDealer))); } object BJ_GetDealer(object oPlayer) { return StringToObject(JsonGetString(JsonObjectGet(BJ_GetUserData(oPlayer), "dealer"))); } string BJ_GetDealerName(object oPlayer) { return GetName(BJ_GetDealer(oPlayer)); } void BJ_SetDeck(object oPlayer, json jDeck) { BJ_SetUserData(oPlayer, "deck", jDeck); } json BJ_GetDeck(object oPlayer) { return JsonObjectGet(BJ_GetUserData(oPlayer), "deck"); } void BJ_DeleteDeck(object oPlayer) { BJ_DeleteUserData(oPlayer, "deck"); } void BJ_ShuffleDeck(object oPlayer) { json jDeck = JsonArray(); int nCard, nNumCards = JsonGetLength(BJ_GetDeck(oPlayer)); for (nCard = 0; nCard < nNumCards; nCard++) { jDeck = JsonArrayInsert(jDeck, BJ_GetCardFromDeck(oPlayer, BJ_DRAW_CARD_RANDOM)); } BJ_SetDeck(oPlayer, jDeck); } void BJ_SetHand(object oPlayer, string sHand, json jHand) { BJ_SetUserData(oPlayer, "hand_" + sHand, jHand); } json BJ_GetHand(object oPlayer, string sHand) { json jHand = JsonObjectGet(BJ_GetUserData(oPlayer), "hand_" + sHand); return !JsonGetType(jHand) ? JsonArray() : jHand; } void BJ_DeleteHand(object oPlayer, string sHand) { BJ_DeleteUserData(oPlayer, "hand_" + sHand); } void BJ_InsertCardIntoHand(object oPlayer, string sHand, json jCard) { json jHand = BJ_GetHand(oPlayer, sHand); jHand = JsonArrayInsert(jHand, jCard); BJ_SetHand(oPlayer, sHand, jHand); } void BJ_SetHandAces(object oPlayer, string sHand, int nAces) { BJ_SetUserData(oPlayer, "aces_" + sHand, JsonInt(nAces)); } int BJ_GetHandAces(object oPlayer, string sHand) { return JsonGetInt(JsonObjectGet(BJ_GetUserData(oPlayer), "aces_" + sHand)); } void BJ_DeleteHandAces(object oPlayer, string sHand) { BJ_DeleteUserData(oPlayer, "aces_" + sHand); } void BJ_IncreaseHandAces(object oPlayer, string sHand) { BJ_SetHandAces(oPlayer, sHand, BJ_GetHandAces(oPlayer, sHand) + 1); } void BJ_ResetHands(object oPlayer) { BJ_DeleteHand(oPlayer, BJ_PLAYER_HAND); BJ_DeleteHand(oPlayer, BJ_DEALER_HAND); BJ_DeleteHandAces(oPlayer, BJ_PLAYER_HAND); BJ_DeleteHandAces(oPlayer, BJ_DEALER_HAND); } string BJ_GetCardImage(json jCard) { return "pc_" + JsonGetString(JsonObjectGet(jCard, "value")) + "_" + JsonGetString(JsonObjectGet(jCard, "suit")); } int BJ_GetCardIsAce(json jCard) { return JsonGetString(JsonObjectGet(jCard, "value")) == "a"; } int BJ_GetHandIsBlackjack(object oPlayer, string sHand) { json jHand = BJ_GetHand(oPlayer, sHand); if (JsonGetLength(jHand) != 2) return FALSE; return (BJ_GetCardValue(JsonArrayGet(jHand, 0)) + BJ_GetCardValue(JsonArrayGet(jHand, 1))) == BJ_BLACKJACK_VALUE; } json BJ_GetCardFromDeck(object oPlayer, int nDrawType) { json jDeck = BJ_GetDeck(oPlayer); int nCard = nDrawType == BJ_DRAW_CARD_RANDOM ? Random(JsonGetLength(jDeck)) : 0; json jCard = JsonArrayGet(jDeck, nCard); BJ_SetDeck(oPlayer, JsonArrayDel(jDeck, nCard)); return jCard; } void BJ_DrawCard(object oPlayer, string sHand) { json jCard = BJ_GetCardFromDeck(oPlayer, BJ_DRAW_CARD_TOP); BJ_InsertCardIntoHand(oPlayer, sHand, jCard); if (BJ_GetCardIsAce(jCard)) BJ_IncreaseHandAces(oPlayer, sHand); BJ_PlaySound(oPlayer, "it_paper"); } int BJ_CreateGameWindow(object oPlayer) { int nToken = NuiCreate(oPlayer, BJ_GetWindowJson(), BJ_WINDOW_ID); json jGeometry = GetLocalJson(oPlayer, BJ_WINDOW_GEOMETRY); if (!JsonGetType(jGeometry)) jGeometry = NuiGetCenteredGeometryRect(oPlayer, BJ_WINDOW_MINIMUM_WIDTH + (BJ_HAND_NUM_CARDS * BJ_CARD_WIDTH), BJ_WINDOW_HEIGHT); NuiSetBindWatch(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, TRUE); NuiSetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND, jGeometry); return nToken; } void BJ_SetPlayerName(object oPlayer, int nToken, string sName) { NuiSetBind(oPlayer, nToken, BJ_BIND_PLAYER_NAME, JsonString(sName)); } void BJ_SetPlayerPoints(object oPlayer, int nToken, int nPoints) { NuiSetBind(oPlayer, nToken, BJ_BIND_PLAYER_POINTS, JsonString(IntToString(nPoints))); } void BJ_SetDealerName(object oPlayer, int nToken, string sName) { NuiSetBind(oPlayer, nToken, BJ_BIND_DEALER_NAME, JsonString(sName)); } void BJ_SetDealerPoints(object oPlayer, int nToken, int nPoints) { NuiSetBind(oPlayer, nToken, BJ_BIND_DEALER_POINTS, JsonString(IntToString(nPoints))); } void BJ_SetInfoText(object oPlayer, int nToken, string sText) { NuiSetBind(oPlayer, nToken, BJ_BIND_INFO_TEXT, JsonString(sText)); } void BJ_SetGoldResultText(object oPlayer, int nToken, string sResult) { NuiSetBind(oPlayer, nToken, BJ_BIND_GOLD_RESULT, JsonString(sResult)); } void BJ_SetCurrentBetText(object oPlayer, int nToken, string sCurrentBet) { NuiSetBind(oPlayer, nToken, BJ_BIND_CURRENT_BET, JsonString(sCurrentBet)); } void BJ_SetCard(object oPlayer, int nToken, string sPrefix, int nCard, string sImage) { NuiSetBind(oPlayer, nToken, sPrefix + IntToString(nCard), JsonString(sImage)); } void BJ_BlankCards(object oPlayer, int nToken) { int nCard; for (nCard = 0; nCard < BJ_HAND_NUM_CARDS; nCard++) { BJ_SetCard(oPlayer, nToken, BJ_PLAYER_CARD_PREFIX, nCard, BJ_CARD_BLANK); BJ_SetCard(oPlayer, nToken, BJ_DEALER_CARD_PREFIX, nCard, BJ_CARD_BLANK); } } void BJ_StartGame(object oPlayer, object oDealer) { int nToken = BJ_GetWindowId(oPlayer); if (nToken) return; SetGuiPanelDisabled(oPlayer, GUI_PANEL_GOLD_INVENTORY, TRUE); SetGuiPanelDisabled(oPlayer, GUI_PANEL_GOLD_BARTER, TRUE); nToken = BJ_CreateGameWindow(oPlayer); BJ_SetDealer(oPlayer, oDealer); BJ_SetDealerName(oPlayer, nToken, BJ_GetDealerName(oPlayer)); BJ_SetPlayerName(oPlayer, nToken, GetName(oPlayer)); BJ_SetGameState(oPlayer, BJ_GAME_STATE_NONE, "Click the Deal button to play Blackjack!"); } void BJ_EndGame(object oPlayer) { SetGuiPanelDisabled(oPlayer, GUI_PANEL_GOLD_INVENTORY, FALSE); SetGuiPanelDisabled(oPlayer, GUI_PANEL_GOLD_BARTER, FALSE); } void BJ_HandleNUIEvents(object oPlayer, int nToken, string sType, string sElement, int nArrayIndex, json jPayload) { if (sType == NUI_EVENT_CLICK) { int nGameState = BJ_GetGameState(oPlayer); if (sElement == BJ_ID_BUTTON_HIT) { if (nGameState != BJ_GAME_STATE_PLAYER_TURN) return; BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_DOUBLE_DOWN, FALSE); BJ_DrawCard(oPlayer, BJ_PLAYER_HAND); if (BJ_GetHandPoints(oPlayer, BJ_PLAYER_HAND) > BJ_BLACKJACK_VALUE) { BJ_SetGameState(oPlayer, BJ_GAME_STATE_GAME_OVER, "Bust! You lose!", 0.0f); } else { BJ_UpdateCards(oPlayer, nToken); BJ_UpdatePoints(oPlayer, nToken); } } else if (sElement == BJ_ID_BUTTON_STAND) { if (nGameState != BJ_GAME_STATE_PLAYER_TURN) return; BJ_SetGameState(oPlayer, BJ_GAME_STATE_DEALER_TURN); } else if (sElement == BJ_ID_BUTTON_DEAL) { if (nGameState != BJ_GAME_STATE_NONE && nGameState != BJ_GAME_STATE_GAME_OVER) return; BJ_SetGameState(oPlayer, BJ_GAME_STATE_DEAL_CARDS); } else if (sElement == BJ_ID_BUTTON_BET) { if (nGameState != BJ_GAME_STATE_NONE && nGameState != BJ_GAME_STATE_GAME_OVER) return; int nAmount = StringToInt(JsonGetString(NuiGetBind(oPlayer, nToken, BJ_BIND_BET_AMOUNT))); if (nAmount > 0) { int nGold = GetGold(oPlayer); int nMaxBetLeft = BJ_MAX_BET - BJ_GetBet(oPlayer); nAmount = nAmount > nGold ? nGold : nAmount; nAmount = nAmount > BJ_MAX_BET ? BJ_MAX_BET : nAmount; nAmount = nAmount > nMaxBetLeft ? nMaxBetLeft : nAmount; if (nAmount > 0) { AssignCommand(oPlayer, TakeGoldFromCreature(nAmount, oPlayer, TRUE)); BJ_IncreaseBet(oPlayer, nAmount); } } NuiSetBind(oPlayer, nToken, BJ_BIND_BET_AMOUNT, JsonString("")); } else if (sElement == BJ_ID_BUTTON_DOUBLE_DOWN) { if (nGameState != BJ_GAME_STATE_PLAYER_TURN || !BJ_GetPlayerCanDoubleDown(oPlayer)) return; BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_DOUBLE_DOWN, FALSE); int nBet = BJ_GetBet(oPlayer); BJ_IncreaseBet(oPlayer, nBet); AssignCommand(oPlayer, TakeGoldFromCreature(nBet, oPlayer, TRUE)); BJ_DrawCard(oPlayer, BJ_PLAYER_HAND); if (BJ_GetHandPoints(oPlayer, BJ_PLAYER_HAND) > BJ_BLACKJACK_VALUE) BJ_SetGameState(oPlayer, BJ_GAME_STATE_GAME_OVER, "Bust! You lose!", 0.0f); else BJ_SetGameState(oPlayer, BJ_GAME_STATE_DEALER_TURN); } } else if (sType == NUI_EVENT_CLOSE) { if (sElement == NUI_WINDOW_ROOT_GROUP) { BJ_EndGame(oPlayer); } } else if (sType == NUI_EVENT_WATCH) { if (sElement == NUI_WINDOW_GEOMETRY_BIND) { SetLocalJson(oPlayer, BJ_WINDOW_GEOMETRY, NuiGetBind(oPlayer, nToken, NUI_WINDOW_GEOMETRY_BIND)); } } } void BJ_SetGameState(object oPlayer, int nState, string sInfoText = "", float fBetResultMultiplier = 0.0f) { BJ_SetUserData(oPlayer, "gamestate", JsonInt(nState)); int nToken = BJ_GetWindowId(oPlayer); BJ_SetInfoText(oPlayer, nToken, sInfoText); switch (nState) { case BJ_GAME_STATE_NONE: { BJ_BlankCards(oPlayer, nToken); BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_DEAL, TRUE); BJ_SetBet(oPlayer, 0); BJ_ToggleBetInput(oPlayer, nToken, TRUE); BJ_UpdatePoints(oPlayer, nToken); BJ_UpdateStatsTooltip(oPlayer, nToken); break; } case BJ_GAME_STATE_DEAL_CARDS: { BJ_HandleDealCards(oPlayer, nToken, BJ_DEAL_CARDS_START); break; } case BJ_GAME_STATE_PLAYER_TURN: { BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_DEAL, FALSE); BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_HIT, TRUE); BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_STAND, TRUE); if (BJ_GetPlayerCanDoubleDown(oPlayer)) BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_DOUBLE_DOWN, TRUE); break; } case BJ_GAME_STATE_DEALER_TURN: { BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_DEAL, FALSE); BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_HIT, FALSE); BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_STAND, FALSE); BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_DOUBLE_DOWN, FALSE); DelayCommand(BJ_GetDealerTurnDelay(), BJ_HandleDealerTurn(oPlayer, nToken, BJ_DEALER_TURN_REVEAL_CARD)); break; } case BJ_GAME_STATE_GAME_OVER: { BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_DEAL, TRUE); BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_HIT, FALSE); BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_STAND, FALSE); BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_DOUBLE_DOWN, FALSE); BJ_SettleBet(oPlayer, nToken, fBetResultMultiplier); BJ_SetBet(oPlayer, 0); BJ_ToggleBetInput(oPlayer, nToken, TRUE); BJ_UpdateCards(oPlayer, nToken); BJ_UpdatePoints(oPlayer, nToken); int nStatsType = fBetResultMultiplier == 1.0f ? BJ_STATS_TYPE_DRAWS : fBetResultMultiplier == 0.0f ? BJ_STATS_TYPE_LOSSES : BJ_STATS_TYPE_WINS; BJ_UpdateStats(oPlayer, nStatsType); BJ_UpdateStatsTooltip(oPlayer, nToken); break; } } } int BJ_GetGameState(object oPlayer) { return JsonGetInt(JsonObjectGet(BJ_GetUserData(oPlayer), "gamestate")); } void BJ_DeleteGameState(object oPlayer) { BJ_DeleteUserData(oPlayer, "gamestate"); } float BJ_GetDealerTurnDelay() { return BJ_DEALER_TURN_DELAY_MIN + (IntToFloat(Random(BJ_DEALER_TURN_DELAY_RANDOM)) / 100.0f); } void BJ_HandleDealerTurn(object oPlayer, int nToken, int nCurrentState) { if (BJ_GetGameState(oPlayer) != BJ_GAME_STATE_DEALER_TURN || BJ_GetWindowId(oPlayer) != nToken) return; int nNextState = BJ_DEALER_TURN_NONE; if (nCurrentState == BJ_DEALER_TURN_REVEAL_CARD) { BJ_UpdateCards(oPlayer, nToken); BJ_UpdatePoints(oPlayer, nToken); nNextState = BJ_GetHandPoints(oPlayer, BJ_DEALER_HAND) < BJ_DEALER_STAND_VALUE ? BJ_DEALER_TURN_DRAW_CARD : BJ_DEALER_TURN_CHECK_POINTS; } else if (nCurrentState == BJ_DEALER_TURN_DRAW_CARD) { BJ_DrawCard(oPlayer, BJ_DEALER_HAND); BJ_UpdateCards(oPlayer, nToken); BJ_UpdatePoints(oPlayer, nToken); nNextState = BJ_GetHandPoints(oPlayer, BJ_DEALER_HAND) < BJ_DEALER_STAND_VALUE ? BJ_DEALER_TURN_DRAW_CARD : BJ_DEALER_TURN_CHECK_POINTS; } else if (nCurrentState == BJ_DEALER_TURN_CHECK_POINTS) { int nDealerPoints = BJ_GetHandPoints(oPlayer, BJ_DEALER_HAND); if (nDealerPoints > BJ_BLACKJACK_VALUE) { BJ_SetGameState(oPlayer, BJ_GAME_STATE_GAME_OVER, BJ_GetDealerName(oPlayer) + " busts! You win!", 2.0f); } else { int nPlayerPoints = BJ_GetHandPoints(oPlayer, BJ_PLAYER_HAND); if (nDealerPoints == nPlayerPoints) { BJ_SetGameState(oPlayer, BJ_GAME_STATE_GAME_OVER, "Push! Nobody wins or loses!", 1.0f); } else if (nDealerPoints > nPlayerPoints) { BJ_SetGameState(oPlayer, BJ_GAME_STATE_GAME_OVER, BJ_GetDealerName(oPlayer) + " wins!", 0.0f); } else { BJ_SetGameState(oPlayer, BJ_GAME_STATE_GAME_OVER, "You win!", 2.0f); } } } if (nNextState) DelayCommand(BJ_GetDealerTurnDelay(), BJ_HandleDealerTurn(oPlayer, nToken, nNextState)); } void BJ_HandleDealCards(object oPlayer, int nToken, int nCurrentState) { if (BJ_GetGameState(oPlayer) != BJ_GAME_STATE_DEAL_CARDS || BJ_GetWindowId(oPlayer) != nToken) return; switch (nCurrentState) { case BJ_DEAL_CARDS_START: { BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_DEAL, FALSE); BJ_ToggleBetInput(oPlayer, nToken, FALSE); BJ_BlankCards(oPlayer, nToken); BJ_SetGoldResultText(oPlayer, nToken, ""); BJ_SetDeck(oPlayer, BJ_CreateDeck()); BJ_ShuffleDeck(oPlayer); BJ_ResetHands(oPlayer); break; } case 1: case 2: case 3: case 4: { string sHand = nCurrentState > 2 ? BJ_DEALER_HAND : BJ_PLAYER_HAND; BJ_DrawCard(oPlayer, sHand); BJ_UpdateCards(oPlayer, nToken); BJ_UpdatePoints(oPlayer, nToken); break; } case BJ_DEAL_CARDS_PEEK: { float fDelay = 0.0f; if (BJ_GetHandPoints(oPlayer, BJ_DEALER_HAND) >= 10) { fDelay = BJ_GetDealerTurnDelay() + 0.5f; string sDealerName = BJ_GetDealerName(oPlayer); BJ_SetInfoText(oPlayer, nToken, sDealerName + " peeks at their card..."); if (BJ_GetHandIsBlackjack(oPlayer, BJ_DEALER_HAND)) { if (BJ_GetHandIsBlackjack(oPlayer, BJ_PLAYER_HAND)) DelayCommand(fDelay, BJ_SetGameState(oPlayer, BJ_GAME_STATE_GAME_OVER, "Push! Nobody wins or loses!", 1.0f)); else DelayCommand(fDelay, BJ_SetGameState(oPlayer, BJ_GAME_STATE_GAME_OVER, sDealerName + " has a Blackjack! You lose!", 0.0f)); return; } } if (BJ_GetHandIsBlackjack(oPlayer, BJ_PLAYER_HAND)) { if (fDelay > 0.0f) DelayCommand(fDelay, BJ_SetGameState(oPlayer, BJ_GAME_STATE_GAME_OVER, "Blackjack! You win!", 2.5f)); else BJ_SetGameState(oPlayer, BJ_GAME_STATE_GAME_OVER, "Blackjack! You win!", 2.5f); } else { if (fDelay > 0.0f) DelayCommand(fDelay, BJ_SetGameState(oPlayer, BJ_GAME_STATE_PLAYER_TURN)); else BJ_SetGameState(oPlayer, BJ_GAME_STATE_PLAYER_TURN); } return; } } if (nCurrentState < BJ_DEAL_CARDS_PEEK) DelayCommand(BJ_GetDealerTurnDelay(), BJ_HandleDealCards(oPlayer, nToken, ++nCurrentState)); } void BJ_UpdateCards(object oPlayer, int nToken) { int nGameState = BJ_GetGameState(oPlayer); json jPlayerHand = BJ_GetHand(oPlayer, BJ_PLAYER_HAND); json jDealerHand = BJ_GetHand(oPlayer, BJ_DEALER_HAND); int nCard, nNumCards = JsonGetLength(jPlayerHand); for (nCard = 0; nCard < nNumCards; nCard++) { BJ_SetCard(oPlayer, nToken, BJ_PLAYER_CARD_PREFIX, nCard, BJ_GetCardImage(JsonArrayGet(jPlayerHand, nCard))); } nNumCards = JsonGetLength(jDealerHand); for (nCard = 0; nCard < nNumCards; nCard++) { if (nCard > 0 && (nGameState == BJ_GAME_STATE_DEAL_CARDS || nGameState == BJ_GAME_STATE_PLAYER_TURN)) BJ_SetCard(oPlayer, nToken, BJ_DEALER_CARD_PREFIX, nCard, BJ_CARD_BACK); else BJ_SetCard(oPlayer, nToken, BJ_DEALER_CARD_PREFIX, nCard, BJ_GetCardImage(JsonArrayGet(jDealerHand, nCard))); } } int BJ_GetCardValue(json jCard) { string sValue = JsonGetString(JsonObjectGet(jCard, "value")); if (sValue == "a") return 11; else if (sValue == "k" || sValue == "q" || sValue == "j") return 10; else return StringToInt(sValue); } int BJ_GetHandPoints(object oPlayer, string sHand) { int nGameState = BJ_GetGameState(oPlayer); json jHand = BJ_GetHand(oPlayer, sHand); if (sHand == BJ_DEALER_HAND && (nGameState == BJ_GAME_STATE_DEAL_CARDS || nGameState == BJ_GAME_STATE_PLAYER_TURN)) { return BJ_GetCardValue(JsonArrayGet(jHand, 0)); } int nPoints = 0, nCard, nNumCards = JsonGetLength(jHand); for (nCard = 0; nCard < nNumCards; nCard++) { nPoints += BJ_GetCardValue(JsonArrayGet(jHand, nCard)); } int nNumAces = BJ_GetHandAces(oPlayer, sHand); while (nNumAces > 0 && nPoints > BJ_BLACKJACK_VALUE) { nPoints -= 10; nNumAces--; } return nPoints; } void BJ_UpdatePoints(object oPlayer, int nToken) { BJ_SetPlayerPoints(oPlayer, nToken, BJ_GetHandPoints(oPlayer, BJ_PLAYER_HAND)); BJ_SetDealerPoints(oPlayer, nToken, BJ_GetHandPoints(oPlayer, BJ_DEALER_HAND)); } void BJ_ToggleBetInput(object oPlayer, int nToken, int bVisible) { if (bVisible) bVisible = GetGold(oPlayer); BJ_ToggleButton(oPlayer, BJ_ID_BUTTON_BET, bVisible); NuiSetBind(oPlayer, nToken, BJ_BIND_BET_AMOUNT_VISIBLE, JsonBool(bVisible)); } int BJ_GetBet(object oPlayer) { return JsonGetInt(JsonObjectGet(BJ_GetUserData(oPlayer), "bet")); } void BJ_SetBet(object oPlayer, int nBet) { BJ_SetUserData(oPlayer, "bet", JsonInt(nBet)); BJ_SetCurrentBetText(oPlayer, BJ_GetWindowId(oPlayer), "Bet: " + IntToString(nBet)); } void BJ_DeleteBet(object oPlayer) { BJ_DeleteUserData(oPlayer, "bet"); } void BJ_IncreaseBet(object oPlayer, int nIncrease) { BJ_SetBet(oPlayer, BJ_GetBet(oPlayer) + nIncrease); } void BJ_SettleBet(object oPlayer, int nToken, float fMultiplier) { int nBet = BJ_GetBet(oPlayer); if (nBet > 0) { int nResult = FloatToInt(nBet * fMultiplier); if (nResult) { BJ_SetGoldResultText(oPlayer, nToken, "Gold: +" + IntToString(nResult)); GiveGoldToCreature(oPlayer, nResult); BJ_PlaySound(oPlayer, "it_coins"); } else { BJ_SetGoldResultText(oPlayer, nToken, "Gold: -" + IntToString(nBet)); } } } void BJ_PlaySound(object oPlayer, string sSound) { AssignCommand(oPlayer, PlaySound(sSound)); } int BJ_GetPlayerCanDoubleDown(object oPlayer) { int nBet = BJ_GetBet(oPlayer); int nHandValue = BJ_GetHandPoints(oPlayer, BJ_PLAYER_HAND); int nGold = GetGold(oPlayer); return nBet > 0 && nGold >= nBet && (nHandValue >= BJ_DOUBLE_DOWN_MIN_POINTS && nHandValue <= BJ_DOUBLE_DOWN_MAX_POINTS) && (BJ_DOUBLE_DOWN_EXCEED_MAX_BET || ((nBet * 2) <= BJ_MAX_BET)); } json BJ_CreateStatsObject() { json jStats = JsonArray(); jStats = JsonArrayInsert(jStats, JsonInt(0)); jStats = JsonArrayInsert(jStats, JsonInt(0)); jStats = JsonArrayInsert(jStats, JsonInt(0)); jStats = JsonArrayInsert(jStats, JsonInt(0)); return jStats; } json BJ_GetStats(object oPlayer) { json jStats = GetCampaignJson("BJ_" + GetPCPublicCDKey(oPlayer, TRUE), BJ_PLAYER_STATS); return !JsonGetType(jStats) ? BJ_CreateStatsObject() : jStats; } void BJ_SetStats(object oPlayer, json jStats) { SetCampaignJson("BJ_" + GetPCPublicCDKey(oPlayer, TRUE), BJ_PLAYER_STATS, jStats); } void BJ_UpdateStats(object oPlayer, int nType) { json jStats = BJ_GetStats(oPlayer); jStats = JsonArraySet(jStats, BJ_STATS_TYPE_TOTAL, JsonInt(JsonGetInt(JsonArrayGet(jStats, BJ_STATS_TYPE_TOTAL)) + 1)); jStats = JsonArraySet(jStats, nType, JsonInt(JsonGetInt(JsonArrayGet(jStats, nType)) + 1)); BJ_SetStats(oPlayer, jStats); } void BJ_UpdateStatsTooltip(object oPlayer, int nToken) { json jStats = BJ_GetStats(oPlayer); int nTotal = JsonGetInt(JsonArrayGet(jStats, BJ_STATS_TYPE_TOTAL)); int nWins = JsonGetInt(JsonArrayGet(jStats, BJ_STATS_TYPE_WINS)); int nDraws = JsonGetInt(JsonArrayGet(jStats, BJ_STATS_TYPE_DRAWS)); int nLosses = JsonGetInt(JsonArrayGet(jStats, BJ_STATS_TYPE_LOSSES)); string sStats = "Total: 0 | Wins: 0 (0.00%) | Draws: 0 (0.00%) | Losses: 0 (0.00%)"; if (nTotal) { sStats = "Total: " + IntToString(nTotal) + " | Wins: " + IntToString(nWins) + " (" + FloatToString((IntToFloat(nWins) / IntToFloat(nTotal)) * 100.0f , 0, 2) + "%)" + " | Draws: " + IntToString(nDraws) + " (" + FloatToString((IntToFloat(nDraws) / IntToFloat(nTotal)) * 100.0f , 0, 2) + "%)" + " | Losses: " + IntToString(nLosses) + " (" + FloatToString((IntToFloat(nLosses) / IntToFloat(nTotal)) * 100.0f , 0, 2) + "%)"; } NuiSetBind(oPlayer, nToken, BJ_BIND_STATS_TOOLTIP, JsonString(sStats)); }