User prompt
more down
User prompt
red and black bet buttons down to the roulet
User prompt
move "red" and "black" bet buttons up to the roulet
User prompt
move number bet keyboard left to the roulet
User prompt
make spin button same like back button
User prompt
move "back" and "spin" sign to the left
User prompt
put a number bet keyboard down to the bet sign
User prompt
Please fix the bug: 'Uncaught TypeError: this.flash is not a function' in or related to this line: 'this.flash(); // Flash the slot' Line Number: 653
User prompt
fix l653
User prompt
remove the number bet keyboard and players can bet numbers with clicking the numbers in roulet but keep splitt bet keyboard down
User prompt
move number bet keyboard down split keyboard up
User prompt
put split number keyboard down to bet sign and up to roulet wheel
User prompt
put single numbers under roulette put double numbers under roulette
User prompt
up to the roulet
User prompt
to up
User prompt
move split bet keyboard up to the wheel
User prompt
make spaces between bet numbers
User prompt
make roulette bet buttons smaller
User prompt
Leave spaces between roulette bet numbers and make the buttons small
User prompt
more up
User prompt
more more up
User prompt
more left and up
User prompt
little left and up
User prompt
write "@ahmet_db" to the right up with an instagram logo
User prompt
remove open account button
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// --- Blackjack Game Logic ---
var BlackjackGame = Container.expand(function () {
var self = Container.call(this);
// State
self.currentSeat = 0; // Track which seat is currently active
self.deck = [];
self.playerHand = [];
self.dealerHand = [];
self.playerCards = [];
self.dealerCards = [];
self.state = 'bet'; // 'bet', 'player', 'dealer', 'result', 'betBehind'
self.resultText = null;
self.buttons = [];
self.bet = betAmount;
self.betBehind = 0; // Amount bet behind
self.betBehindWin = 0; // Track bet behind win for this round
// Table background
var table = self.attachAsset('bjTable', {
width: 1400,
height: 900,
color: 0x2e8b57,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1200
});
// Deal new deck
self.newDeck = function () {
var suits = ['♠', '♥', '♦', '♣'];
var ranks = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
var deck = [];
for (var s = 0; s < 4; s++) {
for (var r = 0; r < 13; r++) {
deck.push({
rank: ranks[r],
suit: suits[s]
});
}
}
// Shuffle
for (var i = deck.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var t = deck[i];
deck[i] = deck[j];
deck[j] = t;
}
self.deck = deck;
};
// Draw a card
self.drawCard = function () {
if (self.deck.length === 0) self.newDeck();
return self.deck.pop();
};
// Calculate hand value
self.handValue = function (hand) {
var value = 0;
var aces = 0;
for (var i = 0; i < hand.length; i++) {
var r = hand[i].rank;
if (r === 'A') {
value += 11;
aces++;
} else if (r === 'K' || r === 'Q' || r === 'J') {
value += 10;
} else {
value += parseInt(r);
}
}
while (value > 21 && aces > 0) {
value -= 10;
aces--;
}
return value;
};
// Start a new round
self.startRound = function () {
self.state = 'player';
self.playerHand = [];
self.dealerHand = [];
self.clearCards();
self.resultText && self.resultText.destroy();
self.resultText = null;
// Bet
self.bet = betAmount;
self.betBehindWin = 0;
self.perfectPairWin = false; // Track perfect pair win for this round
if (playerBalance < self.bet) {
self.showResult('Not enough balance!', true);
return;
}
playerBalance -= self.bet;
updateBalance();
// Deal
// Deal cards with animation
self.playerHand.push(self.drawCard());
self.dealerHand.push(self.drawCard());
self.playerHand.push(self.drawCard());
self.dealerHand.push(self.drawCard());
self.clearCards();
// --- Perfect Pair Side Bet Logic ---
// If first two player cards are same rank and same suit, pay 25:1
self.perfectPairWin = false;
self.perfectPairPayout = 0;
if (self.playerHand.length === 2 && self.playerHand[0].rank === self.playerHand[1].rank && self.playerHand[0].suit === self.playerHand[1].suit) {
self.perfectPairWin = true;
self.perfectPairPayout = self.bet * 25;
playerBalance += self.perfectPairPayout;
updateBalance();
// Show a quick popup for perfect pair win
var pairText = new Text2('Perfect Pair! +$' + self.perfectPairPayout, {
size: 80,
fill: 0xFFE066
});
pairText.anchor.set(0.5, 0.5);
pairText.x = 2048 / 2;
pairText.y = 1550;
self.addChild(pairText);
tween(pairText, {
y: pairText.y - 120,
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
pairText.destroy();
}
});
}
// Card distribution animation
var px = 2048 / 2 - 200;
var py = 1700;
var dx = 2048 / 2 - 200;
var dy = 900;
var dealDelay = 200;
var dealDuration = 350;
var dealStartX = 2048 / 2;
var dealStartY = 1200;
self.playerCards = [];
self.dealerCards = [];
// Helper to animate a card to its position
function animateCard(card, toX, toY, delay, isPlayer) {
card.x = dealStartX;
card.y = dealStartY;
card.visible = true;
self.addChild(card);
tween(card, {
x: toX,
y: toY
}, {
duration: dealDuration,
easing: tween.cubicOut,
delay: delay
});
if (isPlayer) {
self.playerCards.push(card);
} else {
self.dealerCards.push(card);
}
}
// Create and animate cards in order: player1, dealer1, player2, dealer2
var playerCard1 = new Card();
playerCard1.setCard(self.playerHand[0].rank, self.playerHand[0].suit, true);
playerCard1.visible = false;
var dealerCard1 = new Card();
dealerCard1.setCard(self.dealerHand[0].rank, self.dealerHand[0].suit, true);
dealerCard1.visible = false;
var playerCard2 = new Card();
playerCard2.setCard(self.playerHand[1].rank, self.playerHand[1].suit, true);
playerCard2.visible = false;
var dealerCard2 = new Card();
dealerCard2.setCard(self.dealerHand[1].rank, self.dealerHand[1].suit, false);
dealerCard2.visible = false;
LK.setTimeout(function () {
animateCard(playerCard1, px, py, 0, true);
playerCard1.visible = true;
LK.setTimeout(function () {
animateCard(dealerCard1, dx, dy, 0, false);
dealerCard1.visible = true;
LK.setTimeout(function () {
animateCard(playerCard2, px + 120, py, 0, true);
playerCard2.visible = true;
LK.setTimeout(function () {
animateCard(dealerCard2, dx + 120, dy, 0, false);
dealerCard2.visible = true;
// After all cards are dealt, show buttons
LK.setTimeout(function () {
self.showButtons(['Hit', 'Stand']);
}, dealDuration);
}, dealDelay);
}, dealDelay);
}, dealDelay);
}, 0);
};
// Show cards on table
self.showHands = function (revealDealer) {
self.clearCards();
// Player
var px = 2048 / 2 - 200;
var py = 1700;
for (var i = 0; i < self.playerHand.length; i++) {
var c = new Card();
c.setCard(self.playerHand[i].rank, self.playerHand[i].suit, true);
c.x = px + i * 120;
c.y = py;
c.visible = true; // Player cards are visible
self.addChild(c);
self.playerCards.push(c);
}
// Dealer
var dx = 2048 / 2 - 200;
var dy = 900;
for (var i = 0; i < self.dealerHand.length; i++) {
var c = new Card();
var faceUp = i === 0 || revealDealer;
c.setCard(self.dealerHand[i].rank, self.dealerHand[i].suit, faceUp);
c.x = dx + i * 120;
c.y = dy;
c.visible = revealDealer ? true : false; // Show dealer cards only if revealDealer is true
self.addChild(c);
self.dealerCards.push(c);
}
};
// Remove card objects
self.clearCards = function () {
for (var i = 0; i < self.playerCards.length; i++) {
self.playerCards[i].destroy();
}
for (var i = 0; i < self.dealerCards.length; i++) {
self.dealerCards[i].destroy();
}
self.playerCards = [];
self.dealerCards = [];
};
// Show action buttons
self.showButtons = function (labels) {
for (var i = 0; i < self.buttons.length; i++) {
self.buttons[i].destroy();
}
self.buttons = [];
// If in player state, add Double if allowed (first move, enough balance, only 2 cards)
var showDouble = false;
if (self.state === 'player' && self.playerHand.length === 2 && playerBalance >= self.bet) {
showDouble = true;
if (labels.indexOf('Double') === -1) labels.push('Double');
}
// Add Bet Behind button if in 'bet' state and player has enough balance
if (self.state === 'bet' && playerBalance >= betAmount) {
labels.push('Bet Behind');
}
var startX = 2048 / 2 - (labels.length - 1) * 220;
for (var i = 0; i < labels.length; i++) {
var btn = new GameButton();
btn.setText(labels[i]);
btn.x = startX + i * 440;
btn.y = 2100;
btn.action = labels[i];
btn.down = function () {
this.flash();
if (this.action === 'Bet Behind') {
// Place bet behind
if (playerBalance >= betAmount) {
self.betBehind += betAmount;
playerBalance -= betAmount;
updateBalance();
// Show quick popup for bet behind placed
var bbText = new Text2('Bet Behind: $' + self.betBehind, {
size: 70,
fill: 0x66ffcc
});
bbText.anchor.set(0.5, 0.5);
bbText.x = 2048 / 2;
bbText.y = 2000;
self.addChild(bbText);
tween(bbText, {
y: bbText.y - 80,
alpha: 0
}, {
duration: 900,
onFinish: function onFinish() {
bbText.destroy();
}
});
}
} else {
self.handleAction(this.action);
}
};
self.addChild(btn);
self.buttons.push(btn);
}
};
// Handle player actions
self.handleAction = function (action) {
if (self.state !== 'player') return;
if (action === 'Hit') {
self.playerHand.push(self.drawCard());
self.showHands();
var val = self.handValue(self.playerHand);
if (val > 21) {
self.state = 'result';
self.showHands(true);
self.showResult('Bust! You lose.');
}
} else if (action === 'Stand') {
self.state = 'dealer';
self.showHands(true);
self.showButtons([]);
self.dealerTurn();
} else if (action === 'Double') {
// Double the bet, draw one card, then stand
if (playerBalance >= self.bet && self.playerHand.length === 2) {
playerBalance -= self.bet;
self.bet *= 2;
updateBalance();
self.playerHand.push(self.drawCard());
self.showHands();
var val = self.handValue(self.playerHand);
if (val > 21) {
self.state = 'result';
self.showHands(true);
self.showResult('Bust! You lose.');
} else {
self.state = 'dealer';
self.showHands(true);
self.showButtons([]);
self.dealerTurn();
}
}
}
};
// Dealer logic
self.dealerTurn = function () {
var self_ = self;
var dealerVal = self.handValue(self.dealerHand);
var playerVal = self.handValue(self.playerHand);
function dealerStep() {
dealerVal = self_.handValue(self_.dealerHand);
if (dealerVal < 17) {
self_.dealerHand.push(self_.drawCard());
self_.showHands(true);
LK.setTimeout(dealerStep, 700);
} else {
self_.state = 'result';
self_.showHands(true);
self_.showResult(self_.getResultText());
}
}
LK.setTimeout(dealerStep, 700);
};
// Determine result
self.getResultText = function () {
var playerVal = self.handValue(self.playerHand);
var dealerVal = self.handValue(self.dealerHand);
if (playerVal > 21) return 'Bust! You lose.';
// Dealer busts
if (dealerVal > 21) {
playerBalance += self.bet * 2;
// Bet behind wins if player hand not bust
if (self.betBehind > 0 && playerVal <= 21) {
self.betBehindWin = self.betBehind * 2;
playerBalance += self.betBehindWin;
}
updateBalance();
return 'Dealer busts! You win!' + (self.betBehindWin > 0 ? '\nBet Behind Win: $' + self.betBehindWin : '');
}
// Player wins
if (playerVal > dealerVal) {
// Check for natural 21 (Blackjack) on initial deal, no hit, and win
var isNatural21 = self.playerHand.length === 2 && self.handValue(self.playerHand) === 21 && typeof self.lastAction !== "string" // No action taken (no hit/double)
;
var winAmount = self.bet * 2;
if (isNatural21) {
// Award 50% more for natural 21 win without hit
var bonus = Math.floor(self.bet * 0.5);
winAmount += bonus;
}
playerBalance += winAmount;
// Bet behind wins if player hand not bust
if (self.betBehind > 0 && playerVal <= 21) {
self.betBehindWin = self.betBehind * 2;
playerBalance += self.betBehindWin;
}
updateBalance();
var winMsg = 'You win!' + (self.betBehindWin > 0 ? '\nBet Behind Win: $' + self.betBehindWin : '');
if (isNatural21) {
winMsg = 'Blackjack! +50% bonus\n' + winMsg;
}
return winMsg;
}
// Player loses
if (playerVal < dealerVal) {
// Bet behind lost
return 'You lose.' + (self.betBehind > 0 ? '\nBet Behind Lost: $' + self.betBehind : '');
}
// Push
playerBalance += self.bet;
if (self.betBehind > 0) {
playerBalance += self.betBehind; // Return bet behind on push
self.betBehindWin = self.betBehind;
}
updateBalance();
return 'Push!' + (self.betBehind > 0 ? '\nBet Behind Push: $' + self.betBehind : '');
};
// Show result and next round
self.showResult = function (txt, noNext) {
self.resultText && self.resultText.destroy();
// If perfect pair win, append to result text
if (self.perfectPairWin && txt && txt.indexOf('Perfect Pair!') === -1) {
txt = 'Perfect Pair! +$' + self.perfectPairPayout + '\n' + txt;
}
// --- Quest: Play 3 Blackjack rounds ---
if (typeof questEvent === "function") questEvent('blackjack_round');
// --- Quest: Win 2 Blackjack rounds ---
if (typeof questEvent === "function" && txt && txt.indexOf('win') !== -1 && txt.toLowerCase().indexOf('you win') !== -1) questEvent('blackjack_win');
// --- Quest: Double Down in Blackjack ---
if (typeof questEvent === "function" && self.lastAction === 'Double') questEvent('blackjack_double');
// --- Quest: Get Perfect Pair in Blackjack ---
if (typeof questEvent === "function" && self.perfectPairWin) questEvent('blackjack_perfect_pair');
self.resultText = new Text2(txt, {
size: 90,
fill: "#fff"
});
self.resultText.anchor.set(0.5, 0.5);
self.resultText.x = 2048 / 2;
self.resultText.y = 1450;
self.addChild(self.resultText);
self.showButtons(['New Round', 'Back']);
self.buttons[0].down = function () {
this.flash();
self.startRound();
};
self.buttons[1].down = function () {
this.flash();
self.destroy();
blackjack = null;
showModeSelect();
};
if (noNext) {
self.buttons[0].visible = false;
}
};
// Destroy
self.destroy = function () {
self.clearCards();
for (var i = 0; i < self.buttons.length; i++) {
self.buttons[i].destroy();
}
self.buttons = [];
self.resultText && self.resultText.destroy();
self.resultText = null;
self.perfectPairWin = false;
self.perfectPairPayout = 0;
self.betBehind = 0;
self.betBehindWin = 0;
if (self.parent) self.parent.removeChild(self);
};
// Start
self.newDeck();
self.startRound();
return self;
});
// Card class for Blackjack
var Card = Container.expand(function () {
var self = Container.call(this);
// Card properties
self.rank = null; // 2-10, J, Q, K, A
self.suit = null; // '♠', '♥', '♦', '♣'
self.faceUp = true;
// Card background
var cardBg = self.attachAsset('cardBg', {
width: 180,
height: 260,
color: 0xffffff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
// Card text
var cardText = new Text2('', {
size: 80,
fill: 0x222222
});
cardText.anchor.set(0.5, 0.5);
self.addChild(cardText);
// Set card value
self.setCard = function (rank, suit, faceUp) {
self.rank = rank;
self.suit = suit;
self.faceUp = faceUp !== false;
if (self.faceUp) {
cardText.setText(rank + suit);
cardText.visible = true;
cardBg.color = suit === '♥' || suit === '♦' ? 0xffeaea : 0xffffff;
} else {
cardText.setText('');
cardText.visible = false;
cardBg.color = 0x8888aa;
}
};
// Flip card
self.flip = function (up) {
self.faceUp = up;
self.setCard(self.rank, self.suit, up);
};
return self;
});
// Simple Button class
var GameButton = Container.expand(function () {
var self = Container.call(this);
var btnBg = self.attachAsset('btnBg', {
width: 420,
height: 120,
color: 0x333366,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
self.btnBg = btnBg; // <-- Fix: assign btnBg as a property for external access
var btnText = new Text2('', {
size: 60,
fill: 0xFFFFFF
});
btnText.anchor.set(0.5, 0.5);
self.addChild(btnText);
self.setText = function (txt) {
btnText.setText(txt);
};
// For touch feedback
self.flash = function () {
tween(btnBg, {
color: 0x6666cc
}, {
duration: 100,
onFinish: function onFinish() {
tween(btnBg, {
color: 0x333366
}, {
duration: 200
});
}
});
};
return self;
});
// --- Roulette Game Logic ---
var RouletteGame = Container.expand(function () {
var self = Container.call(this);
// State
self.state = 'bet'; // 'bet', 'spin', 'result'
self.betType = null; // 'red', 'black', 'even', 'odd', 'number'
self.betValue = null; // For number bet
self.resultText = null;
self.buttons = [];
self.rouletteWheel = null;
self.ball = null;
self.spinBtn = null;
self.backBtn = null;
self.betOptions = [];
self.selectedBetBtn = null;
// Table background
var table = self.attachAsset('bjTable', {
width: 1200,
height: 900,
color: 0x2e8b57,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1200
});
// Draw roulette wheel (simple circle with numbers)
var wheelRadius = 320;
var wheelCenterX = 2048 / 2;
var wheelCenterY = 1200;
var numbers = [];
for (var i = 0; i < 37; i++) numbers.push(i);
// Red/Black numbers (European roulette)
var reds = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36];
var blacks = [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35];
// Draw wheel
self.rouletteWheel = new Container();
self.rouletteWheel.x = wheelCenterX;
self.rouletteWheel.y = wheelCenterY;
self.addChild(self.rouletteWheel);
// Draw wheel numbers
for (var i = 0; i < 37; i++) {
var angle = i / 37 * Math.PI * 2 - Math.PI / 2;
var num = numbers[i];
// European roulette: 0 is green, reds as defined, rest are black
var color = 0x222222; // default black
if (num === 0) {
color = 0x1abc2c; // vivid green for 0
} else if (reds.indexOf(num) !== -1) {
color = 0xff0000; // red
}
var slot = self.rouletteWheel.attachAsset('cardBg', {
width: 60,
height: 60,
color: color,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: Math.cos(angle) * wheelRadius,
y: Math.sin(angle) * wheelRadius
});
var txt = new Text2(num + '', {
size: 32,
fill: "#fff"
});
txt.anchor.set(0.5, 0.5);
slot.addChild(txt);
}
// Ball
self.ball = self.rouletteWheel.attachAsset('centerCircle', {
width: 30,
height: 30,
color: 0xffffff,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5,
x: Math.cos(-Math.PI / 2) * (wheelRadius - 40),
y: Math.sin(-Math.PI / 2) * (wheelRadius - 40)
});
// Bet options
// Allow number bets (0-36) and split bets (adjacent numbers) in a compact grid below the wheel
// Arrange numbers 0-36 in a 4-row grid: 0 on its own, then 1-36 in 3 rows of 12
var betGridCols = 12;
var betGridRows = 4; // 0 in first row, 1-12 in second, 13-24 in third, 25-36 in fourth
var betBtnW = 100;
var betBtnH = 100;
var betGridStartX = 2048 / 2 - betGridCols * betBtnW / 2 + betBtnW / 2;
var betGridStartY = 1550;
self.betOptions = [];
self.splitBetOptions = []; // Store split bet buttons
// Helper to get grid position for a number
function getGridPos(num) {
if (num === 0) {
return {
col: 5.5,
row: 0
}; // Center 0 above the grid
}
var idx = num - 1;
return {
col: idx % betGridCols,
row: 1 + Math.floor(idx / betGridCols)
};
}
// Create number bet buttons
for (var i = 0; i < 37; i++) {
var btn = new GameButton();
btn.setText(i + '');
var pos = getGridPos(i);
btn.x = betGridStartX + pos.col * betBtnW;
btn.y = betGridStartY + pos.row * betBtnH;
btn.betType = 'number';
btn.betValue = i;
btn.down = function (numBtn) {
return function () {
this.flash();
// Unhighlight all bet buttons
for (var j = 0; j < self.betOptions.length; j++) {
if (self.betOptions[j].btnBg) self.betOptions[j].btnBg.color = 0x333366;
}
for (var j = 0; j < self.splitBetOptions.length; j++) {
if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366;
}
// Set bet type and value
self.betType = 'number';
self.betValue = numBtn.betValue;
self.selectedBetBtn = this;
self.showResult('Number bet: ' + self.betValue + ' ($' + Math.max(betAmount, 50) + ')', true);
// Highlight selected bet button
if (this.btnBg) this.btnBg.color = 0x6666cc;
// Show spin button when a bet is selected
if (self.state === 'bet') {
self.spinBtn.visible = true;
}
};
}(btn);
self.addChild(btn);
self.betOptions.push(btn);
}
// --- Add Red/Black bet buttons ---
var colorBetY = betGridStartY + betGridRows * betBtnH + 10;
var redBtn = new GameButton();
redBtn.setText('Red');
redBtn.x = 2048 / 2 - 120;
redBtn.y = colorBetY;
redBtn.betType = 'red';
redBtn.down = function () {
this.flash();
// Unhighlight all bet buttons
for (var j = 0; j < self.betOptions.length; j++) {
if (self.betOptions[j].btnBg) self.betOptions[j].btnBg.color = 0x333366;
}
for (var j = 0; j < self.splitBetOptions.length; j++) {
if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366;
}
if (self.blackBtn && self.blackBtn.btnBg) self.blackBtn.btnBg.color = 0x333366;
if (self.redBtn && self.redBtn.btnBg) self.redBtn.btnBg.color = 0x333366;
self.betType = 'red';
self.betValue = null;
self.selectedBetBtn = this;
self.showResult('Red bet ($' + Math.max(betAmount, 50) + ')', true);
if (this.btnBg) this.btnBg.color = 0xff0000;
if (self.state === 'bet') {
self.spinBtn.visible = true;
}
};
self.addChild(redBtn);
self.betOptions.push(redBtn);
self.redBtn = redBtn;
var blackBtn = new GameButton();
blackBtn.setText('Black');
blackBtn.x = 2048 / 2 + 120;
blackBtn.y = colorBetY;
blackBtn.betType = 'black';
blackBtn.down = function () {
this.flash();
// Unhighlight all bet buttons
for (var j = 0; j < self.betOptions.length; j++) {
if (self.betOptions[j].btnBg) self.betOptions[j].btnBg.color = 0x333366;
}
for (var j = 0; j < self.splitBetOptions.length; j++) {
if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366;
}
if (self.redBtn && self.redBtn.btnBg) self.redBtn.btnBg.color = 0x333366;
if (self.blackBtn && self.blackBtn.btnBg) self.blackBtn.btnBg.color = 0x333366;
self.betType = 'black';
self.betValue = null;
self.selectedBetBtn = this;
self.showResult('Black bet ($' + Math.max(betAmount, 50) + ')', true);
if (this.btnBg) this.btnBg.color = 0x222222;
if (self.state === 'bet') {
self.spinBtn.visible = true;
}
};
self.addChild(blackBtn);
self.betOptions.push(blackBtn);
self.blackBtn = blackBtn;
// Create split bet buttons (between adjacent numbers: right and below)
for (var i = 0; i < 37; i++) {
var pos = getGridPos(i);
// Split right (horizontal)
if (pos.col < betGridCols - 1 && i + 1 < 37) {
var splitBtn = new GameButton();
splitBtn.setText(i + '|' + (i + 1));
splitBtn.x = betGridStartX + pos.col * betBtnW + betBtnW / 2;
splitBtn.y = betGridStartY + pos.row * betBtnH;
splitBtn.width = 60;
splitBtn.height = 60;
splitBtn.betType = 'split';
splitBtn.betValue = [i, i + 1];
splitBtn.down = function (splitBtn) {
return function () {
this.flash();
// Unhighlight all bet buttons
for (var j = 0; j < self.betOptions.length; j++) {
if (self.betOptions[j].btnBg) self.betOptions[j].btnBg.color = 0x333366;
}
for (var j = 0; j < self.splitBetOptions.length; j++) {
if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366;
}
self.betType = 'split';
self.betValue = splitBtn.betValue;
self.selectedBetBtn = this;
self.showResult('Split bet: ' + splitBtn.betValue[0] + ' & ' + splitBtn.betValue[1] + ' ($' + Math.max(betAmount, 50) + ')', true);
if (this.btnBg) this.btnBg.color = 0x6666cc;
if (self.state === 'bet') {
self.spinBtn.visible = true;
}
};
}(splitBtn);
self.addChild(splitBtn);
self.splitBetOptions.push(splitBtn);
}
// Split below (vertical)
if (pos.row < betGridRows - 1 && i + betGridCols < 37) {
var splitBtn2 = new GameButton();
splitBtn2.setText(i + '\\' + (i + betGridCols));
splitBtn2.x = betGridStartX + pos.col * betBtnW;
splitBtn2.y = betGridStartY + pos.row * betBtnH + betBtnH / 2;
splitBtn2.width = 60;
splitBtn2.height = 60;
splitBtn2.betType = 'split';
splitBtn2.betValue = [i, i + betGridCols];
splitBtn2.down = function (splitBtn2) {
return function () {
this.flash();
// Unhighlight all bet buttons
for (var j = 0; j < self.betOptions.length; j++) {
if (self.betOptions[j].btnBg) self.betOptions[j].btnBg.color = 0x333366;
}
for (var j = 0; j < self.splitBetOptions.length; j++) {
if (self.splitBetOptions[j].btnBg) self.splitBetOptions[j].btnBg.color = 0x333366;
}
self.betType = 'split';
self.betValue = splitBtn2.betValue;
self.selectedBetBtn = this;
self.showResult('Split bet: ' + splitBtn2.betValue[0] + ' & ' + splitBtn2.betValue[1] + ' ($' + Math.max(betAmount, 50) + ')', true);
if (this.btnBg) this.btnBg.color = 0x6666cc;
if (self.state === 'bet') {
self.spinBtn.visible = true;
}
};
}(splitBtn2);
self.addChild(splitBtn2);
self.splitBetOptions.push(splitBtn2);
}
}
// Spin button
// Calculate betY for button positioning
var betY = betGridStartY + betGridRows * betBtnH + 40;
self.spinBtn = new GameButton();
self.spinBtn.setText('Spin');
self.spinBtn.x = 2048 / 2;
self.spinBtn.y = betY + 200;
self.spinBtn.visible = false; // Only show after bet selected
self.spinBtn.down = function () {
this.flash();
self.handleSpin();
};
self.addChild(self.spinBtn);
// Back button
self.backBtn = new GameButton();
self.backBtn.setText('Back');
self.backBtn.x = 2048 / 2;
self.backBtn.y = betY + 350;
self.backBtn.down = function () {
self.destroy();
roulette = null;
showModeSelect();
};
self.addChild(self.backBtn);
// Show result text
self.showResult = function (txt, noNext) {
self.resultText && self.resultText.destroy();
self.resultText = new Text2(txt, {
size: 90,
fill: "#fff"
});
self.resultText.anchor.set(0.5, 0.5);
self.resultText.x = 2048 / 2;
self.resultText.y = 1550;
self.addChild(self.resultText);
if (!noNext) {
// Show "New Round" button
var nextBtn = new GameButton();
nextBtn.setText('New Round');
nextBtn.x = 2048 / 2;
nextBtn.y = betY + 500;
nextBtn.down = function () {
this.flash();
self.reset();
};
self.addChild(nextBtn);
self.buttons.push(nextBtn);
}
};
// Handle spin
self.handleSpin = function () {
// Only allow spin if a bet is selected
if (!self.betType || self.betType === 'number' && (typeof self.betValue !== "number" || self.betValue < 0 || self.betValue > 36)) {
self.showResult('Select a bet first!', true);
return;
}
if (betAmount < 50) {
self.showResult('Minimum bet is $50!', true);
return;
}
if (self.state !== 'bet') {
self.showResult('You can only place one bet per round!', true);
return;
}
self.state = 'spin';
if (playerBalance < betAmount) {
self.showResult('Not enough balance!', true);
return;
}
playerBalance -= betAmount;
updateBalance();
self.state = 'spin';
self.spinBtn.visible = false;
for (var i = 0; i < self.betOptions.length; i++) self.betOptions[i].visible = false;
self.resultText && self.resultText.destroy();
// Animate ball spin
var winningNumber = Math.floor(Math.random() * 37);
var totalSpins = 3 + Math.floor(Math.random() * 2);
var frames = 60 * totalSpins;
var startAngle = -Math.PI / 2;
var endAngle = winningNumber / 37 * Math.PI * 2 - Math.PI / 2;
var currentFrame = 0;
function animateBall() {
var t = currentFrame / frames;
var angle = startAngle + (endAngle - startAngle) * t + Math.PI * 2 * (1 - t) * totalSpins;
self.ball.x = Math.cos(angle) * (wheelRadius - 40);
self.ball.y = Math.sin(angle) * (wheelRadius - 40);
currentFrame++;
if (currentFrame <= frames) {
LK.setTimeout(animateBall, 1000 / 60);
} else {
self.showSpinResult(winningNumber);
// After result, allow new bet
self.betType = null;
self.betValue = null;
if (self.selectedBetBtn && self.selectedBetBtn.btnBg) {
self.selectedBetBtn.btnBg.color = 0x333366;
}
self.selectedBetBtn = null;
// Show bet options for next round, but keep spin button hidden until bet is selected
self.spinBtn.visible = false;
for (var i = 0; i < self.betOptions.length; i++) self.betOptions[i].visible = true;
}
}
animateBall();
};
// Show spin result and payout
self.showSpinResult = function (winningNumber) {
var win = false;
var payout = 0;
var msg = '';
if (self.betType === 'red' && reds.indexOf(winningNumber) !== -1) {
win = true;
payout = betAmount * 2;
msg = 'Red wins!';
} else if (self.betType === 'black' && blacks.indexOf(winningNumber) !== -1) {
win = true;
payout = betAmount * 2;
msg = 'Black wins!';
} else if (self.betType === 'even' && winningNumber !== 0 && winningNumber % 2 === 0) {
win = true;
payout = betAmount * 2;
msg = 'Even wins!';
} else if (self.betType === 'odd' && winningNumber % 2 === 1) {
win = true;
payout = betAmount * 2;
msg = 'Odd wins!';
} else if (self.betType === 'number' && self.betValue === winningNumber) {
win = true;
payout = betAmount * 36;
msg = 'Number ' + winningNumber + ' wins!';
} else if (self.betType === 'split' && self.betValue && self.betValue.indexOf(winningNumber) !== -1) {
win = true;
payout = betAmount * 18; // Standard split bet payout is 17:1, so bet*18
msg = 'Split bet wins! Number ' + winningNumber + '!';
} else {
msg = 'Number ' + winningNumber + '. You lose.';
}
if (win) {
playerBalance += payout;
updateBalance();
msg += ' You win $' + payout + '!';
// --- Quest: Win $500 in Roulette ---
if (typeof questEvent === "function") questEvent('roulette_win', payout);
// --- Quest: Place 5 Roulette bets ---
if (typeof questEvent === "function") questEvent('roulette_bet');
// --- Quest: Win on a number bet in Roulette ---
if (typeof questEvent === "function" && self.betType === 'number' && self.betValue === winningNumber) questEvent('roulette_number_win');
// --- Quest: Win on Red/Black in Roulette ---
if (typeof questEvent === "function" && (self.betType === 'red' || self.betType === 'black')) questEvent('roulette_red_black_win');
} else {
// Even if lose, count bet for "Place 5 Roulette bets"
if (typeof questEvent === "function") questEvent('roulette_bet');
}
self.state = 'result';
self.showResult(msg);
};
// Reset for new round
self.reset = function () {
self.betType = null;
self.betValue = null;
self.state = 'bet';
self.resultText && self.resultText.destroy();
for (var i = 0; i < self.buttons.length; i++) self.buttons[i].destroy();
self.buttons = [];
self.spinBtn.visible = false;
for (var i = 0; i < self.betOptions.length; i++) {
self.betOptions[i].visible = true;
if (self.betOptions[i].btnBg) self.betOptions[i].btnBg.color = 0x333366;
}
for (var i = 0; i < (self.splitBetOptions ? self.splitBetOptions.length : 0); i++) {
self.splitBetOptions[i].visible = true;
if (self.splitBetOptions[i].btnBg) self.splitBetOptions[i].btnBg.color = 0x333366;
}
self.selectedBetBtn = null;
};
// Destroy
self.destroy = function () {
self.resultText && self.resultText.destroy();
for (var i = 0; i < self.betOptions.length; i++) self.betOptions[i].destroy();
self.betOptions = [];
if (self.splitBetOptions) {
for (var i = 0; i < self.splitBetOptions.length; i++) self.splitBetOptions[i].destroy();
self.splitBetOptions = [];
}
self.spinBtn && self.spinBtn.destroy();
self.backBtn && self.backBtn.destroy();
for (var i = 0; i < self.buttons.length; i++) self.buttons[i].destroy();
self.buttons = [];
self.rouletteWheel && self.rouletteWheel.destroy();
self.state = 'bet';
if (self.parent) self.parent.removeChild(self);
};
return self;
});
// --- Sweet Bonanza Game Logic ---
var SweetBonanzaGame = Container.expand(function () {
var self = Container.call(this);
// Slot config
var ROWS = 5;
var COLS = 6;
var SYMBOLS = [{
id: 'red',
color: 0xff4b5c,
payout: 10
}, {
id: 'blue',
color: 0x4b7bff,
payout: 8
}, {
id: 'green',
color: 0x4bff7b,
payout: 6
}, {
id: 'yellow',
color: 0xffe066,
payout: 4
}, {
id: 'purple',
color: 0xb266ff,
payout: 12
}, {
id: 'bomb',
color: 0xffffff,
payout: 0,
isBomb: true
}];
var symbolSize = 180;
var gridOffsetX = 2048 / 2 - COLS * symbolSize / 2;
var gridOffsetY = 900;
var grid = [];
var symbolNodes = [];
var spinBtn = null;
var resultText = null;
var canSpin = true;
// Draw slot background
var slotBg = self.attachAsset('bjTable', {
width: COLS * symbolSize + 40,
height: ROWS * symbolSize + 40,
color: 0xf7e6ff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: gridOffsetY + ROWS * symbolSize / 2
});
// Draw grid
function drawGrid() {
// Remove old
for (var i = 0; i < symbolNodes.length; i++) {
for (var j = 0; j < symbolNodes[i].length; j++) {
symbolNodes[i][j].destroy();
}
}
symbolNodes = [];
for (var row = 0; row < ROWS; row++) {
symbolNodes[row] = [];
for (var col = 0; col < COLS; col++) {
var sym = grid[row][col];
var node = self.attachAsset('cardBg', {
width: symbolSize - 10,
height: symbolSize - 10,
color: sym.color,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: gridOffsetX + col * symbolSize + symbolSize / 2,
y: gridOffsetY + row * symbolSize + symbolSize / 2
});
// Add symbol text
var txt = new Text2(sym.isBomb ? '💣' : '', {
size: 80,
fill: "#222"
});
txt.anchor.set(0.5, 0.5);
node.addChild(txt);
symbolNodes[row][col] = node;
}
}
}
// Generate random grid
function randomGrid() {
grid = [];
for (var row = 0; row < ROWS; row++) {
grid[row] = [];
for (var col = 0; col < COLS; col++) {
var sym = SYMBOLS[Math.floor(Math.random() * SYMBOLS.length)];
grid[row][col] = sym;
}
}
}
// Find clusters of 8+ matching symbols (Sweet Bonanza style)
function findClusters() {
var visited = [];
for (var i = 0; i < ROWS; i++) visited[i] = [];
var clusters = [];
function dfs(r, c, id, cluster) {
if (r < 0 || r >= ROWS || c < 0 || c >= COLS) return;
if (visited[r][c]) return;
if (grid[r][c].id !== id) return;
visited[r][c] = true;
cluster.push({
row: r,
col: c
});
dfs(r - 1, c, id, cluster);
dfs(r + 1, c, id, cluster);
dfs(r, c - 1, id, cluster);
dfs(r, c + 1, id, cluster);
}
for (var row = 0; row < ROWS; row++) {
for (var col = 0; col < COLS; col++) {
if (!visited[row][col] && !grid[row][col].isBomb) {
var cluster = [];
dfs(row, col, grid[row][col].id, cluster);
if (cluster.length >= 8) {
clusters.push({
id: grid[row][col].id,
cells: cluster,
payout: grid[row][col].payout
});
}
}
}
}
return clusters;
}
// Remove clusters and drop new symbols
function removeClusters(clusters) {
for (var i = 0; i < clusters.length; i++) {
var cells = clusters[i].cells;
for (var j = 0; j < cells.length; j++) {
var r = cells[j].row;
var c = cells[j].col;
grid[r][c] = null;
}
}
// Drop down
for (var col = 0; col < COLS; col++) {
var empty = [];
for (var row = ROWS - 1; row >= 0; row--) {
if (grid[row][col] === null) {
empty.push(row);
} else if (empty.length > 0) {
var target = empty.shift();
grid[target][col] = grid[row][col];
grid[row][col] = null;
empty.push(row);
}
}
// Fill empty with new
for (var k = 0; k < empty.length; k++) {
var r = empty[k];
var sym = SYMBOLS[Math.floor(Math.random() * SYMBOLS.length)];
grid[r][col] = sym;
}
}
}
// Check for bombs
function hasBomb() {
for (var row = 0; row < ROWS; row++) {
for (var col = 0; col < COLS; col++) {
if (grid[row][col].isBomb) return true;
}
}
return false;
}
// Spin logic
function spin() {
if (!canSpin) return;
if (playerBalance < betAmount) {
showResult('Not enough balance!');
return;
}
// --- Quest: Spin Sweet Bonanza 5 times ---
if (typeof questEvent === "function") questEvent('sweet_spin');
canSpin = false;
playerBalance -= betAmount;
updateBalance();
resultText && resultText.destroy();
resultText = null;
randomGrid();
drawGrid();
// Animate spin (simple delay)
LK.setTimeout(function () {
var clusters = findClusters();
var win = 0;
for (var i = 0; i < clusters.length; i++) {
win += clusters[i].payout * betAmount;
}
if (win > 0) {
playerBalance += win;
updateBalance();
showResult('Win! $' + win);
} else if (hasBomb()) {
showResult('💣 Bomb! Lose!');
} else {
showResult('No win');
}
// Remove clusters and drop new
if (clusters.length > 0) {
removeClusters(clusters);
drawGrid();
}
canSpin = true;
}, 700);
}
// Show result text
function showResult(txt) {
resultText && resultText.destroy();
resultText = new Text2(txt, {
size: 90,
fill: "#fff"
});
resultText.anchor.set(0.5, 0.5);
resultText.x = 2048 / 2;
resultText.y = gridOffsetY + ROWS * symbolSize + 120;
self.addChild(resultText);
}
// Spin button
spinBtn = new GameButton();
spinBtn.setText('Spin');
spinBtn.x = 2048 / 2;
spinBtn.y = gridOffsetY + ROWS * symbolSize + 250;
spinBtn.down = function () {
this.flash();
spin();
};
self.addChild(spinBtn);
// Back button
var backBtn = new GameButton();
backBtn.setText('Back');
backBtn.x = 2048 / 2;
backBtn.y = gridOffsetY + ROWS * symbolSize + 400;
backBtn.down = function () {
self.destroy();
sweetBonanza = null;
showModeSelect();
};
self.addChild(backBtn);
// Destroy
self.destroy = function () {
for (var i = 0; i < symbolNodes.length; i++) {
for (var j = 0; j < symbolNodes[i].length; j++) {
symbolNodes[i][j].destroy();
}
}
symbolNodes = [];
spinBtn && spinBtn.destroy();
backBtn && backBtn.destroy();
resultText && resultText.destroy();
if (self.parent) self.parent.removeChild(self);
};
// Init
randomGrid();
drawGrid();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// --- Global State ---
// --- Account System State ---
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
var accountState = {
loggedIn: false,
username: null
};
var accountPrompt = null;
var accountErrorText = null;
var accountNameInput = null;
var accountPasswordInput = null;
var accountNameValue = '';
var accountPasswordValue = '';
var accountMode = 'login'; // 'login' or 'register'
// Helper: get all accounts from storage
function getAllAccounts() {
// Use storage.getItem to retrieve accounts, fallback to empty object if not found
var accounts = storage.getItem && typeof storage.getItem === "function" ? storage.getItem("accounts") : storage.accounts;
if (!accounts || _typeof(accounts) !== "object") accounts = {};
return accounts;
}
// Helper: save all accounts to storage
function saveAllAccounts(accounts) {
// Use storage.setItem to persist accounts if available
if (storage.setItem && typeof storage.setItem === "function") {
storage.setItem("accounts", accounts);
}
storage.accounts = accounts;
}
// Helper: hash password (simple, not secure, but for demo)
function hashPassword(pw) {
// Ensure pw is a string to avoid errors on charCodeAt
if (pw === undefined || pw === null) pw = '';
pw = String(pw);
var h = 0;
for (var i = 0; i < pw.length; i++) {
// Defensive: check that pw is a string and pw[i] exists
var ch = typeof pw === "string" && pw.length > i ? pw.charAt(i) : '';
if (typeof ch === "string" && ch.length === 1) {
h += ch.charCodeAt(0) * (i + 17);
}
}
// Defensive: ensure h is a number before converting to string
if (typeof h !== "number" || isNaN(h)) h = 0;
// Always return as string, and never undefined/null
try {
// Defensive: if h is not a string or number, return empty string
if (typeof h === "string") return h;
if (typeof h === "number") return String(h);
// If h is not string or number, fallback to empty string
return '';
} catch (e) {
// In case of any error, always return empty string
return '';
}
// Final fallback: always return a string
if (typeof h === "undefined" || h === null) return '';
// Defensive: ensure return is always a string
try {
// Fix: Always return a string, never throw
if (typeof h === "string") return h;
if (typeof h === "number") return String(h);
return '';
} catch (e) {
return '';
}
// Absolute fallback
return '';
}
// Show account setup/login UI
function showAccountPrompt() {
// Remove old prompt if present
if (accountPrompt) {
accountPrompt.destroy();
accountPrompt = null;
}
accountPrompt = new Container();
game.addChild(accountPrompt);
// Background overlay
var overlay = accountPrompt.attachAsset('cardBg', {
width: 900,
height: 600,
color: 0x222244,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1200
});
// Title
var title = new Text2(accountMode === 'register' ? 'Create Account' : 'Login', {
size: 80,
fill: "#fff"
});
title.anchor.set(0.5, 0.5);
title.x = 2048 / 2;
title.y = 950;
accountPrompt.addChild(title);
// Username input
accountNameInput = new Text2('Name: ' + accountNameValue, {
size: 60,
fill: "#fff"
});
accountNameInput.anchor.set(0.5, 0.5);
accountNameInput.x = 2048 / 2;
accountNameInput.y = 1100;
accountPrompt.addChild(accountNameInput);
// Password input (show as ****)
var stars = '';
for (var i = 0; i < accountPasswordValue.length; i++) stars += '*';
accountPasswordInput = new Text2('Password: ' + stars, {
size: 60,
fill: "#fff"
});
accountPasswordInput.anchor.set(0.5, 0.5);
accountPasswordInput.x = 2048 / 2;
accountPasswordInput.y = 1200;
accountPrompt.addChild(accountPasswordInput);
function updateNameInputDisplay() {
accountNameInput.setText('Name: ' + accountNameValue);
if (accountErrorText) accountErrorText.setText('');
}
function updatePasswordInputDisplay() {
var stars = '';
for (var i = 0; i < accountPasswordValue.length; i++) stars += '*';
accountPasswordInput.setText('Password: ' + stars);
if (accountErrorText) accountErrorText.setText('');
}
function clearAccountInputs() {
accountNameValue = '';
accountPasswordValue = '';
updateNameInputDisplay();
updatePasswordInputDisplay();
}
// Error text
accountErrorText = new Text2('', {
size: 48,
fill: 0xFF4444
});
accountErrorText.anchor.set(0.5, 0.5);
accountErrorText.x = 2048 / 2;
accountErrorText.y = 1270;
accountPrompt.addChild(accountErrorText);
// Name pad (A-Z, backspace, next) - split left
var namePadStartX = 2048 / 2 - 500;
var namePadStartY = 1350;
var namePadLabels = [['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], ['K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'], ['U', 'V', 'W', 'X', 'Y', 'Z', '/', '_', '<-', 'OK']];
function updateNameInputDisplay() {
accountNameInput.setText('Name: ' + accountNameValue);
if (accountErrorText) accountErrorText.setText('');
}
function updatePasswordInputDisplay() {
var stars = '';
for (var i = 0; i < accountPasswordValue.length; i++) stars += '*';
accountPasswordInput.setText('Password: ' + stars);
if (accountErrorText) accountErrorText.setText('');
}
function clearAccountInputs() {
accountNameValue = '';
accountPasswordValue = '';
updateNameInputDisplay();
updatePasswordInputDisplay();
}
function tryAccountSubmit() {
var name = accountNameValue.trim();
var pw = accountPasswordValue;
if (name.length < 3) {
accountErrorText.setText('Name must be at least 3 characters.');
return;
}
if (pw.length < 6) {
accountErrorText.setText('Password must be at least 6 digits.');
return;
}
var accounts = getAllAccounts();
if (accountMode === 'register') {
if (accounts[name]) {
accountErrorText.setText('Name already taken!');
return;
}
// Only allow digits in password
if (!/^\d+$/.test(pw)) {
accountErrorText.setText('Password must be digits only.');
return;
}
// Register
accounts[name] = {
password: hashPassword(pw),
created: Date.now()
};
saveAllAccounts(accounts);
accountState.loggedIn = true;
accountState.username = name;
accountPasswordValue = ''; // Clear password after success
if (accountPrompt) {
accountPrompt.destroy();
accountPrompt = null;
}
showModeSelect();
} else {
// Login
if (!accounts[name]) {
accountErrorText.setText('Account not found.');
return;
}
if (accounts[name].password !== hashPassword(pw)) {
accountErrorText.setText('Incorrect password.');
return;
}
accountState.loggedIn = true;
accountState.username = name;
accountPasswordValue = ''; // Clear password after success
if (accountPrompt) {
accountPrompt.destroy();
accountPrompt = null;
}
showModeSelect();
}
}
function clearAccountInputs() {
accountNameValue = '';
accountPasswordValue = '';
updateNameInputDisplay();
updatePasswordInputDisplay();
}
var namePadStartY = 1350;
var namePadLabels = [['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], ['K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T'], ['U', 'V', 'W', 'X', 'Y', 'Z', '/', '_', '<-', 'OK']];
function updateNameInputDisplay() {
accountNameInput.setText('Name: ' + accountNameValue);
if (accountErrorText) accountErrorText.setText('');
}
function updatePasswordInputDisplay() {
var stars = '';
for (var i = 0; i < accountPasswordValue.length; i++) stars += '*';
accountPasswordInput.setText('Password: ' + stars);
if (accountErrorText) accountErrorText.setText('');
}
function tryAccountSubmit() {
var name = accountNameValue.trim();
var pw = accountPasswordValue;
if (name.length < 3) {
accountErrorText.setText('Name must be at least 3 characters.');
return;
}
if (pw.length < 6) {
accountErrorText.setText('Password must be at least 6 digits.');
return;
}
var accounts = getAllAccounts();
if (accountMode === 'register') {
if (accounts[name]) {
accountErrorText.setText('Name already taken!');
return;
}
// Only allow digits in password
if (!/^\d+$/.test(pw)) {
accountErrorText.setText('Password must be digits only.');
return;
}
// Register
accounts[name] = {
password: hashPassword(pw),
created: Date.now()
};
saveAllAccounts(accounts);
accountState.loggedIn = true;
accountState.username = name;
accountPasswordValue = ''; // Clear password after success
if (accountPrompt) {
accountPrompt.destroy();
accountPrompt = null;
}
showModeSelect();
} else {
// Login
if (!accounts[name]) {
accountErrorText.setText('Account not found.');
return;
}
if (accounts[name].password !== hashPassword(pw)) {
accountErrorText.setText('Incorrect password.');
return;
}
accountState.loggedIn = true;
accountState.username = name;
accountPasswordValue = ''; // Clear password after success
if (accountPrompt) {
accountPrompt.destroy();
accountPrompt = null;
}
showModeSelect();
}
}
function clearAccountInputs() {
accountNameValue = '';
accountPasswordValue = '';
updateNameInputDisplay();
updatePasswordInputDisplay();
}
// Draw name pad (letters only, left side)
for (var row = 0; row < namePadLabels.length; row++) {
for (var col = 0; col < namePadLabels[row].length; col++) {
var label = namePadLabels[row][col];
var btn = new GameButton();
btn.setText(label);
// Make buttons smaller and add more space between them
btn.btnBg.width = 54;
btn.btnBg.height = 54;
btn.x = namePadStartX + col * 74; // 54px button + 20px gap
btn.y = namePadStartY + row * 80; // 54px button + 26px gap
// Make text a bit larger for visibility
for (var t = 0; t < btn.children.length; t++) {
if (btn.children[t] && typeof btn.children[t].setText === "function") {
btn.children[t].style = btn.children[t].style || {};
btn.children[t].style.size = 36;
btn.children[t].setText(label);
}
}
if (label === '<-') btn.btnBg.color = 0xffcccc;
if (label === 'OK') btn.btnBg.color = 0xccffcc;
btn.down = function (lbl) {
return function () {
this.flash();
if (lbl === '<-') {
if (accountNameValue.length > 0) {
accountNameValue = accountNameValue.slice(0, -1);
updateNameInputDisplay();
}
} else if (lbl === 'OK') {
// Move to password input
// If already on password, try submit
if (accountPasswordValue.length < 6) {
accountErrorText.setText('Password must be at least 6 digits.');
return;
}
tryAccountSubmit();
} else {
if (accountNameValue.length < 12 && /^[A-Z_\/]$/.test(lbl)) {
accountNameValue += lbl;
updateNameInputDisplay();
}
}
};
}(label);
accountPrompt.addChild(btn);
}
}
// Number pad (digits 0-9, C, OK) - right side
var pwPadStartX = 2048 / 2 + 400;
var pwPadStartY = 1350;
var pwPadLabels = [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['C', '0', 'OK']];
for (var prow = 0; prow < 4; prow++) {
for (var pcol = 0; pcol < 3; pcol++) {
var plabel = pwPadLabels[prow][pcol];
var pbtn = new GameButton();
pbtn.setText(plabel);
// Make buttons smaller and add more space between them
pbtn.btnBg.width = 54;
pbtn.btnBg.height = 54;
pbtn.x = pwPadStartX + pcol * 74; // 54px button + 20px gap
pbtn.y = pwPadStartY + prow * 80; // 54px button + 26px gap
// Make text a bit larger for visibility
for (var t = 0; t < pbtn.children.length; t++) {
if (pbtn.children[t] && typeof pbtn.children[t].setText === "function") {
pbtn.children[t].style = pbtn.children[t].style || {};
pbtn.children[t].style.size = 36;
pbtn.children[t].setText(plabel);
}
}
if (plabel === 'C') pbtn.btnBg.color = 0xffcccc;
if (plabel === 'OK') pbtn.btnBg.color = 0xccffcc;
pbtn.down = function (lbl) {
return function () {
this.flash();
if (lbl === 'C') {
accountPasswordValue = '';
updatePasswordInputDisplay();
} else if (lbl === 'OK') {
tryAccountSubmit();
} else if (lbl.length === 1 && accountPasswordValue.length < 12 && /^\d$/.test(lbl)) {
accountPasswordValue += lbl;
updatePasswordInputDisplay();
}
};
}(plabel);
accountPrompt.addChild(pbtn);
}
}
// Switch mode button
var switchBtn = new GameButton();
switchBtn.setText(accountMode === 'register' ? 'Have account? Login' : 'No account? Register');
switchBtn.x = 2048 / 2;
switchBtn.y = 1800; // moved even further down
switchBtn.btnBg.width = 400;
switchBtn.btnBg.height = 70;
switchBtn.down = function () {
this.flash();
accountMode = accountMode === 'register' ? 'login' : 'register';
accountNameValue = '';
accountPasswordValue = '';
if (accountPrompt) {
accountPrompt.destroy();
accountPrompt = null;
}
showAccountPrompt();
};
accountPrompt.addChild(switchBtn);
}
// On game start, allow guest play by default
// Optionally, user can open account prompt from a button in the mode select screen
// --- Top Left Back Button ---
var topLeftBackBtn = null;
function showTopLeftBackBtn(onBack) {
// Remove if already present
if (topLeftBackBtn && topLeftBackBtn.parent) {
topLeftBackBtn.parent.removeChild(topLeftBackBtn);
topLeftBackBtn.destroy();
topLeftBackBtn = null;
}
topLeftBackBtn = new GameButton();
topLeftBackBtn.setText('Back');
// Place at (100,220) to avoid the reserved 100x100px area and move a little further down
topLeftBackBtn.x = 100 + 80; // 80px right of reserved area
topLeftBackBtn.y = 100 + 160; // 160px below reserved area (moved a little further down)
topLeftBackBtn.btnBg.width = 180;
topLeftBackBtn.btnBg.height = 80;
topLeftBackBtn.down = function () {
this.flash();
if (typeof onBack === "function") onBack();
};
game.addChild(topLeftBackBtn);
}
function hideTopLeftBackBtn() {
if (topLeftBackBtn && topLeftBackBtn.parent) {
topLeftBackBtn.parent.removeChild(topLeftBackBtn);
topLeftBackBtn.destroy();
topLeftBackBtn = null;
}
}
/****
* Casino Carnival - MVP
* Four-in-one casino game: Blackjack, Sweet Bonanza, Gates of Olympus, Sugar Rush
* MVP: Game selection, basic betting, and one playable mode (Blackjack)
****/
var MODES = [{
id: 'blackjack',
name: 'Blackjack'
}, {
id: 'roulette',
name: 'Roulette'
}];
var currentMode = null; // 'blackjack', etc.
var playerBalance = storage.balance || 1000;
var betAmount = 100;
var minBet = 50;
var maxBet = 5000;
// --- Single Seat State ---
var blackjack = null;
// UI elements
var modeButtons = [];
var betText = null;
var balanceText = null;
var playArea = null;
var blackjack = null;
// --- GUI: Balance and Bet ---
balanceText = new Text2('Balance: $' + playerBalance, {
size: 60,
fill: "#fff"
});
balanceText.anchor.set(0.5, 0);
LK.gui.top.addChild(balanceText);
betText = new Text2('Bet: $' + betAmount, {
size: 50,
fill: "#fff"
});
betText.anchor.set(0.5, 0);
LK.gui.top.addChild(betText);
// Position GUI elements
balanceText.y = 10;
betText.y = 80;
// --- Game Selection Screen ---
function showModeSelect() {
hideTopLeftBackBtn();
// Clear play area
if (playArea) {
playArea.destroy();
playArea = null;
}
if (blackjack) {
blackjack.destroy();
blackjack = null;
}
// Destroy blackjack instance if present
if (blackjack && blackjack.destroy) {
blackjack.destroy();
blackjack = null;
}
// Remove old mode buttons
for (var i = 0; i < modeButtons.length; i++) {
if (modeButtons[i].parent) modeButtons[i].parent.removeChild(modeButtons[i]);
}
modeButtons = [];
// Title
var title = new Text2('Casino Carnival', {
size: 120,
fill: 0xFFE066
});
title.anchor.set(0.5, 0.5);
title.x = 2048 / 2;
title.y = 350;
game.addChild(title);
// Mode buttons
var startY = 700;
var gapY = 200;
for (var i = 0; i < MODES.length; i++) {
var btn = new GameButton();
btn.setText(MODES[i].name);
// Adjust font size to fit the button for 'Blackjack' and 'Roulette'
if (MODES[i].name === 'Blackjack' || MODES[i].name === 'Roulette') {
// Find the Text2 child and set its size smaller to fit the red area
for (var j = 0; j < btn.children.length; j++) {
if (btn.children[j] && typeof btn.children[j].setText === "function") {
btn.children[j].style = btn.children[j].style || {};
btn.children[j].style.size = 48; // Reduce font size to fit
btn.children[j].setText(MODES[i].name);
}
}
}
btn.x = 2048 / 2;
btn.y = startY + i * gapY;
btn.modeId = MODES[i].id;
btn.down = function (x, y, obj) {
this.flash();
selectMode(this.modeId);
};
game.addChild(btn);
modeButtons.push(btn);
}
// Bet controls
var betMinus = new GameButton();
betMinus.setText('-');
betMinus.x = 2048 / 2 - 250;
betMinus.y = startY + MODES.length * gapY + 60;
betMinus.down = function () {
if (betAmount > minBet) {
betAmount -= 50;
betText.setText('Bet: $' + betAmount);
}
};
game.addChild(betMinus);
var betPlus = new GameButton();
betPlus.setText('+');
betPlus.x = 2048 / 2 + 250;
betPlus.y = startY + MODES.length * gapY + 60;
betPlus.down = function () {
if (betAmount < maxBet) {
betAmount += 50;
betText.setText('Bet: $' + betAmount);
}
};
game.addChild(betPlus);
// Store for later removal
// Store for later removal
modeButtons.push(title, betMinus, betPlus);
// Add Instagram handle
var instaHandle = new Text2('@ahmet_db', {
size: 40,
fill: 0xffffff
});
instaHandle.anchor.set(0, 0.5); // Align to the left middle
instaHandle.x = 2048 - 250; // Position slightly more left
instaHandle.y = 150; // Position slightly more up
game.addChild(instaHandle);
// Add Instagram logo
var instaLogo = LK.getAsset('instagramLogo', {
width: 50,
height: 50,
anchorX: 1,
// Align to the right
anchorY: 0.5,
// Align to the middle
x: instaHandle.x - 10,
// Position 10px to the left of the text
y: instaHandle.y
});
game.addChild(instaLogo);
// Add "Open Account" button
var openAccountBtn = new GameButton();
openAccountBtn.setText('Open Account');
openAccountBtn.x = 2048 / 2 + 750; // Position further to the right
openAccountBtn.y = 200; // Position further upwards
openAccountBtn.btnBg.width = 400;
openAccountBtn.btnBg.height = 80;
openAccountBtn.down = function () {
this.flash();
accountMode = 'register'; // Set mode to register
clearAccountInputs(); // Clear any previous input
showAccountPrompt();
};
}
// --- Mode Selection Handler ---
// Password UI state
var roulettePasswordPrompt = null;
var roulettePasswordInput = null;
var roulettePasswordError = null;
function showRoulettePasswordPrompt() {
showTopLeftBackBtn(function () {
if (roulettePasswordPrompt) {
roulettePasswordPrompt.destroy();
roulettePasswordPrompt = null;
}
showModeSelect();
});
// Remove any previous prompt
if (roulettePasswordPrompt) {
roulettePasswordPrompt.destroy();
roulettePasswordPrompt = null;
}
roulettePasswordPrompt = new Container();
game.addChild(roulettePasswordPrompt);
// Background overlay
var overlay = roulettePasswordPrompt.attachAsset('cardBg', {
width: 900,
height: 500,
color: 0x222244,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1200
});
// Title
var promptTitle = new Text2('Enter Roulette Password', {
size: 80,
fill: "#fff"
});
promptTitle.anchor.set(0.5, 0.5);
promptTitle.x = 2048 / 2;
promptTitle.y = 1050;
roulettePasswordPrompt.addChild(promptTitle);
// Password input (show as ****)
var passwordValue = '';
roulettePasswordInput = new Text2('Password: ', {
size: 60,
fill: "#fff"
});
roulettePasswordInput.anchor.set(0.5, 0.5);
roulettePasswordInput.x = 2048 / 2;
roulettePasswordInput.y = 1200;
roulettePasswordPrompt.addChild(roulettePasswordInput);
// Error text
roulettePasswordError = new Text2('', {
size: 48,
fill: 0xFF4444
});
roulettePasswordError.anchor.set(0.5, 0.5);
roulettePasswordError.x = 2048 / 2;
roulettePasswordError.y = 1270;
roulettePasswordPrompt.addChild(roulettePasswordError);
// Number pad
var padStartX = 2048 / 2 + 400; // moved even further right
var padStartY = 1320;
var padBtns = [];
function updateInputDisplay() {
var stars = '';
for (var i = 0; i < passwordValue.length; i++) stars += '*';
roulettePasswordInput.setText('Password: ' + stars);
if (roulettePasswordError) roulettePasswordError.setText('');
}
function clearInput() {
passwordValue = '';
updateInputDisplay();
}
function trySubmit() {
if (passwordValue === '1334') {
// Success
if (roulettePasswordPrompt) {
roulettePasswordPrompt.destroy();
roulettePasswordPrompt = null;
}
startRoulette();
} else {
// Error
if (roulettePasswordError) roulettePasswordError.setText('Incorrect password!');
clearInput();
}
}
// Password keypad layout: numbers in phone order
var keypadLabels = [['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9'], ['C', '0', 'OK']];
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 3; col++) {
var label = keypadLabels[row][col];
var btn = new GameButton();
btn.setText(label);
// Make buttons smaller and add more space between them
btn.btnBg.width = 54;
btn.btnBg.height = 54;
btn.x = padStartX + col * 74; // 54px button + 20px gap
btn.y = padStartY + row * 80; // 54px button + 26px gap
// Make the button text larger for visibility
for (var t = 0; t < btn.children.length; t++) {
if (btn.children[t] && typeof btn.children[t].setText === "function") {
btn.children[t].style = btn.children[t].style || {};
btn.children[t].style.size = 36;
btn.children[t].setText(label);
}
}
// Make the button background lighter for better contrast
if (!isNaN(parseInt(label))) {
if (label === '0') {
btn.btnBg.color = 0xeeeeee;
btn.setText(label);
} else {
btn.btnBg.color = 0xffffff;
btn.setText(label);
}
} else if (label === 'C') {
btn.btnBg.color = 0xffcccc;
} else if (label === 'OK') {
btn.btnBg.color = 0xccffcc;
}
btn.down = function (lbl) {
return function () {
this.flash();
if (lbl === 'C') {
clearInput();
} else if (lbl === 'OK') {
trySubmit();
} else if (lbl.length === 1 && passwordValue.length < 8) {
passwordValue += lbl;
updateInputDisplay();
}
};
}(label);
roulettePasswordPrompt.addChild(btn);
padBtns.push(btn);
}
}
updateInputDisplay();
}
function selectMode(modeId) {
currentMode = modeId;
// Remove mode select UI
for (var i = 0; i < modeButtons.length; i++) {
if (modeButtons[i].parent) modeButtons[i].parent.removeChild(modeButtons[i]);
}
modeButtons = [];
// Start selected mode
if (modeId === 'blackjack') {
startBlackjack();
} else if (modeId === 'roulette') {
showRoulettePasswordPrompt();
} else {
showComingSoon(modeId);
}
}
// --- Coming Soon Placeholder ---
function showComingSoon(modeId) {
showTopLeftBackBtn(function () {
if (playArea) playArea.destroy();
playArea = null;
showModeSelect();
});
if (playArea) playArea.destroy();
playArea = new Container();
game.addChild(playArea);
var txt = new Text2(MODES.filter(function (m) {
return m.id === modeId;
})[0].name + '\nComing Soon!', {
size: 100,
fill: "#fff"
});
txt.anchor.set(0.5, 0.5);
txt.x = 2048 / 2;
txt.y = 1200;
playArea.addChild(txt);
// Back button
var backBtn = new GameButton();
backBtn.setText('Back');
backBtn.x = 2048 / 2;
backBtn.y = 1800;
backBtn.down = function () {
playArea.destroy();
playArea = null;
showModeSelect();
};
playArea.addChild(backBtn);
}
// --- Start Blackjack ---
function startBlackjack() {
showTopLeftBackBtn(function () {
if (playArea) playArea.destroy();
playArea = null;
if (blackjack) {
blackjack.destroy();
blackjack = null;
}
showModeSelect();
});
if (playArea) playArea.destroy();
playArea = new Container();
game.addChild(playArea);
// Destroy old blackjack if any
if (blackjack && blackjack.destroy) {
blackjack.destroy();
blackjack = null;
}
blackjack = new BlackjackGame();
playArea.addChild(blackjack);
}
// (removed selectBlackjackSeat, not needed for single seat)
// --- Start Sweet Bonanza ---
function startSweetBonanza() {
if (playArea) playArea.destroy();
playArea = new Container();
game.addChild(playArea);
if (typeof sweetBonanza !== "undefined" && sweetBonanza && sweetBonanza.destroy) {
sweetBonanza.destroy();
}
sweetBonanza = new SweetBonanzaGame();
playArea.addChild(sweetBonanza);
}
// --- Start Roulette ---
function startRoulette() {
showTopLeftBackBtn(function () {
if (playArea) playArea.destroy();
playArea = null;
if (roulette) {
roulette.destroy();
roulette = null;
}
showModeSelect();
});
if (playArea) playArea.destroy();
playArea = new Container();
game.addChild(playArea);
if (typeof roulette !== "undefined" && roulette && roulette.destroy) {
roulette.destroy();
}
roulette = new RouletteGame();
playArea.addChild(roulette);
}
// --- Update Balance ---
function updateBalance() {
balanceText.setText('Balance: $' + playerBalance);
storage.balance = playerBalance;
}
// --- Auto Reward System ---
// Give +2000 every 10 minutes (600,000 ms)
var AUTO_REWARD_AMOUNT = 2000;
var AUTO_REWARD_INTERVAL = 600000; // 10 minutes in ms
var lastRewardTime = storage.lastRewardTime || Date.now();
// --- Auto Reward Counter UI ---
var autoRewardCounterText = new Text2('', {
size: 40,
fill: 0x66FFCC
});
autoRewardCounterText.anchor.set(0.5, 0);
// Place original counter in the center top (for legacy/compat)
autoRewardCounterText.x = 2048 / 2;
autoRewardCounterText.y = 160;
LK.gui.top.addChild(autoRewardCounterText);
// Add countdown timer to the top left
var autoRewardCounterTextLeft = new Text2('', {
size: 40,
fill: 0x66FFCC
});
autoRewardCounterTextLeft.anchor.set(0, 0); // left aligned, top
autoRewardCounterTextLeft.x = 120; // 20px right of reserved area (100px reserved)
autoRewardCounterTextLeft.y = 20; // 20px from top
LK.gui.topLeft.addChild(autoRewardCounterTextLeft);
// --- Quest System ---
// Daily quest pool (at least 8, so 5 can be picked randomly each day)
var QUEST_POOL = [{
id: 'bj_3rounds',
desc: 'Play 3 Blackjack rounds',
goal: 3,
reward: 500
}, {
id: 'roulette_win500',
desc: 'Win $500 in Roulette',
goal: 500,
reward: 1000
}, {
id: 'bj_blackjack_win2',
desc: 'Win 2 Blackjack rounds',
goal: 2,
reward: 600
}, {
id: 'roulette_bet5',
desc: 'Place 5 Roulette bets',
goal: 5,
reward: 400
}, {
id: 'bj_perfect_pair',
desc: 'Get 1 Perfect Pair in Blackjack',
goal: 1,
reward: 1200
}, {
id: 'roulette_number_win',
desc: 'Win on a number bet in Roulette',
goal: 1,
reward: 900
}, {
id: 'bj_double_down',
desc: 'Double Down 2 times in Blackjack',
goal: 2,
reward: 700
}, {
id: 'roulette_red_black',
desc: 'Win 3 times on Red or Black in Roulette',
goal: 3,
reward: 500
}];
// Helper to get a deterministic "random" set of 5 quests per day
function getDailyQuestIds() {
var now = new Date();
var daySeed = now.getFullYear() * 10000 + (now.getMonth() + 1) * 100 + now.getDate();
var ids = [];
var used = [];
for (var i = 0; i < QUEST_POOL.length; i++) used[i] = false;
var count = 0;
var poolLen = QUEST_POOL.length;
var seed = daySeed;
while (ids.length < 5 && count < 20) {
// Simple LCG for deterministic shuffle
seed = (seed * 9301 + 49297) % 233280;
var idx = Math.floor(seed / 233280 * poolLen);
if (!used[idx]) {
ids.push(QUEST_POOL[idx].id);
used[idx] = true;
}
count++;
}
return ids;
}
// Build today's QUESTS array
var QUESTS = [];
var dailyIds = getDailyQuestIds();
for (var i = 0; i < dailyIds.length; i++) {
for (var j = 0; j < QUEST_POOL.length; j++) {
if (QUEST_POOL[j].id === dailyIds[i]) {
// Clone quest object and add progress/complete
QUESTS.push({
id: QUEST_POOL[j].id,
desc: QUEST_POOL[j].desc,
goal: QUEST_POOL[j].goal,
reward: QUEST_POOL[j].reward,
progress: 0,
complete: false
});
break;
}
}
}
// Load quest progress from storage if available and if for today
if (storage.quests && storage.questsDay === new Date().toDateString()) {
for (var i = 0; i < QUESTS.length; i++) {
var q = QUESTS[i];
// Load from flat keys, e.g. quests.key_progress and quests.key_complete
var progressKey = q.id + '_progress';
var completeKey = q.id + '_complete';
if (typeof storage.quests[progressKey] !== "undefined") {
q.progress = storage.quests[progressKey];
}
if (typeof storage.quests[completeKey] !== "undefined") {
q.complete = storage.quests[completeKey];
}
}
} else {
// New day, reset quest progress and save today's date
// Initialize storage.quests as a flat object with only 1-level deep properties
storage.quests = {};
storage.questsDay = new Date().toDateString();
}
function saveQuests() {
var save = {};
for (var i = 0; i < QUESTS.length; i++) {
var q = QUESTS[i];
if (!storage.quests) storage.quests = {};
// Store as flat keys, e.g. quests.key_progress and quests.key_complete
storage.quests[q.id + '_progress'] = q.progress;
storage.quests[q.id + '_complete'] = q.complete;
}
storage.questsDay = new Date().toDateString();
}
// Quest UI (bottom left, separate area)
var questTextNodes = [];
function updateQuestUI() {
// Remove old
for (var i = 0; i < questTextNodes.length; i++) {
if (questTextNodes[i].parent) questTextNodes[i].parent.removeChild(questTextNodes[i]);
questTextNodes[i].destroy();
}
questTextNodes = [];
// Place quests in bottom left, avoid left 100px reserved area
var y = 40; // Padding from bottom
for (var i = 0; i < QUESTS.length; i++) {
var q = QUESTS[i];
var txt = new Text2((q.complete ? '✅ ' : '') + q.desc + ' [' + q.progress + '/' + q.goal + ']' + (q.complete ? ' (Claimed)' : ' Prize: $' + q.reward), {
size: 32,
fill: q.complete ? "#aaffaa" : "#fff"
});
txt.anchor.set(0, 1); // left aligned, bottom
txt.x = 120; // 20px right of reserved area
txt.y = -y; // negative y for bottom alignment in LK.gui.bottomLeft
LK.gui.bottomLeft.addChild(txt);
questTextNodes.push(txt);
y += 38;
}
}
updateQuestUI();
// --- Daily Quest Timer UI (bottom right) ---
var questTimerText = new Text2('', {
size: 38,
fill: 0xFFD700
});
questTimerText.anchor.set(1, 1); // right aligned, bottom
questTimerText.x = -40; // 40px from right edge in LK.gui.bottomRight
questTimerText.y = -40; // 40px from bottom
LK.gui.bottomRight.addChild(questTimerText);
function updateQuestTimer() {
// Calculate time left until midnight
var now = new Date();
var tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 0, 0);
var msLeft = tomorrow - now;
if (msLeft < 0) msLeft = 0;
var sec = Math.floor(msLeft / 1000) % 60;
var min = Math.floor(msLeft / 60000) % 60;
var hr = Math.floor(msLeft / 3600000);
var timeStr = (hr < 10 ? '0' : '') + hr + ':' + (min < 10 ? '0' : '') + min + ':' + (sec < 10 ? '0' : '') + sec;
questTimerText.setText('Daily quests reset in: ' + timeStr);
}
LK.setInterval(updateQuestTimer, 1000);
updateQuestTimer();
// Quest logic: call these when player does actions
function questEvent(event, value) {
var updated = false;
for (var i = 0; i < QUESTS.length; i++) {
var q = QUESTS[i];
if (q.complete) continue;
// Blackjack round played
if (event === 'blackjack_round' && q.id === 'bj_3rounds') {
q.progress++;
if (q.progress >= q.goal) {
q.progress = q.goal;
q.complete = true;
playerBalance += q.reward;
updateBalance();
showQuestRewardPopup(q.reward, q.desc);
}
updated = true;
}
// Win 2 Blackjack rounds
if (event === 'blackjack_win' && q.id === 'bj_blackjack_win2') {
q.progress++;
if (q.progress >= q.goal) {
q.progress = q.goal;
q.complete = true;
playerBalance += q.reward;
updateBalance();
showQuestRewardPopup(q.reward, q.desc);
}
updated = true;
}
// Double Down in Blackjack
if (event === 'blackjack_double' && q.id === 'bj_double_down') {
q.progress++;
if (q.progress >= q.goal) {
q.progress = q.goal;
q.complete = true;
playerBalance += q.reward;
updateBalance();
showQuestRewardPopup(q.reward, q.desc);
}
updated = true;
}
// Get Perfect Pair in Blackjack
if (event === 'blackjack_perfect_pair' && q.id === 'bj_perfect_pair') {
q.progress++;
if (q.progress >= q.goal) {
q.progress = q.goal;
q.complete = true;
playerBalance += q.reward;
updateBalance();
showQuestRewardPopup(q.reward, q.desc);
}
updated = true;
}
// Roulette win $500
if (event === 'roulette_win' && q.id === 'roulette_win500') {
q.progress += value;
if (q.progress >= q.goal) {
q.progress = q.goal;
q.complete = true;
playerBalance += q.reward;
updateBalance();
showQuestRewardPopup(q.reward, q.desc);
}
updated = true;
}
// Place 5 Roulette bets
if (event === 'roulette_bet' && q.id === 'roulette_bet5') {
q.progress++;
if (q.progress >= q.goal) {
q.progress = q.goal;
q.complete = true;
playerBalance += q.reward;
updateBalance();
showQuestRewardPopup(q.reward, q.desc);
}
updated = true;
}
// Win on a number bet in Roulette
if (event === 'roulette_number_win' && q.id === 'roulette_number_win') {
q.progress++;
if (q.progress >= q.goal) {
q.progress = q.goal;
q.complete = true;
playerBalance += q.reward;
updateBalance();
showQuestRewardPopup(q.reward, q.desc);
}
updated = true;
}
// Win on Red/Black in Roulette
if (event === 'roulette_red_black_win' && q.id === 'roulette_red_black') {
q.progress++;
if (q.progress >= q.goal) {
q.progress = q.goal;
q.complete = true;
playerBalance += q.reward;
updateBalance();
showQuestRewardPopup(q.reward, q.desc);
}
updated = true;
}
}
if (updated) {
saveQuests();
updateQuestUI();
}
}
function showQuestRewardPopup(amount, desc) {
var popup = new Text2('Quest Complete!\n' + desc + '\n+$' + amount, {
size: 70,
fill: 0xFFD700
});
popup.anchor.set(0.5, 0.5);
popup.x = 2048 / 2;
popup.y = 600;
game.addChild(popup);
tween(popup, {
y: popup.y - 80,
alpha: 0
}, {
duration: 1400,
onFinish: function onFinish() {
popup.destroy();
}
});
}
// Update auto reward counter as before
function updateAutoRewardCounter() {
var now = Date.now();
var msLeft = AUTO_REWARD_INTERVAL - (now - lastRewardTime) % AUTO_REWARD_INTERVAL;
if (msLeft < 0) msLeft = 0;
var sec = Math.floor(msLeft / 1000) % 60;
var min = Math.floor(msLeft / 60000);
var timeStr = (min < 10 ? '0' : '') + min + ':' + (sec < 10 ? '0' : '') + sec;
autoRewardCounterText.setText('Next Reward: +' + AUTO_REWARD_AMOUNT + ' in ' + timeStr);
autoRewardCounterTextLeft.setText('Next reward: ' + timeStr);
}
function checkAutoReward() {
var now = Date.now();
// If more than interval has passed, give reward (handle multiple missed intervals)
var intervals = Math.floor((now - lastRewardTime) / AUTO_REWARD_INTERVAL);
if (intervals > 0) {
var totalReward = intervals * AUTO_REWARD_AMOUNT;
playerBalance += totalReward;
updateBalance();
lastRewardTime += intervals * AUTO_REWARD_INTERVAL;
storage.lastRewardTime = lastRewardTime;
// Optionally show a quick popup for reward
var rewardText = new Text2('Auto Reward: +$' + totalReward, {
size: 70,
fill: 0x66ffcc
});
rewardText.anchor.set(0.5, 0.5);
rewardText.x = 2048 / 2;
rewardText.y = 400;
game.addChild(rewardText);
tween(rewardText, {
y: rewardText.y - 80,
alpha: 0
}, {
duration: 1200,
onFinish: function onFinish() {
rewardText.destroy();
}
});
}
updateAutoRewardCounter();
}
// Check auto reward every 10 seconds, and update counter every second
LK.setInterval(checkAutoReward, 10000);
LK.setInterval(updateAutoRewardCounter, 1000);
updateAutoRewardCounter();
// Check for new day and reset quests if needed
function checkQuestDay() {
var today = new Date().toDateString();
if (storage.questsDay !== today) {
// Force reload of page to reset quests (or you can re-run quest init logic here)
location.reload();
}
}
LK.setInterval(checkQuestDay, 60000); // check every minute
// --- Start Game ---
showModeSelect();
updateBalance();
// --- Touch Handling (for mobile) ---
game.move = function (x, y, obj) {
// No drag in this game
};
game.down = function (x, y, obj) {
// No drag in this game
};
game.up = function (x, y, obj) {
// No drag in this game
};
// --- Game Tick ---
game.update = function () {
// No per-frame logic needed for MVP
// Win/Lose system for all casino modes (except Blackjack, which already has it)
// Placeholder for future slot/other games:
if (currentMode === 'sweet') {
// Example: If playerBalance <= 0, show lose popup
if (playerBalance <= 0) {
LK.showGameOver();
}
// Example: If playerBalance >= 10000, show win popup
if (playerBalance >= 10000) {
LK.showYouWin();
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1864,9 +1864,9 @@
fill: 0xffffff
});
instaHandle.anchor.set(0, 0.5); // Align to the left middle
instaHandle.x = 2048 - 250; // Position slightly more left
- instaHandle.y = 180; // Position slightly more up
+ instaHandle.y = 150; // Position slightly more up
game.addChild(instaHandle);
// Add Instagram logo
var instaLogo = LK.getAsset('instagramLogo', {
width: 50,
empty card. In-Game asset. 2d. High contrast. No shadows
Metallic button frame, black snake patterns around, red middle of the button, metal gray frame. In-Game asset. 2d. High contrast. No shadows
instagram logo. In-Game asset. No shadows
more shiney , black areas are like night dark and lines are blood red
remove the cards and the other things make left just croupier
make it a blackjack table and make it fit with the fullscreen. In-Game asset. 2d. High contrast. No shadows