added runtiback and allin
This commit is contained in:
+401
-70
@@ -29,62 +29,33 @@ const ROULETTE_BETS = [
|
||||
|
||||
const ROULETTE_CHOICES = {
|
||||
Red: {
|
||||
name:
|
||||
"Red",
|
||||
|
||||
emoji:
|
||||
"🔴",
|
||||
|
||||
multiplier:
|
||||
2
|
||||
name: "Red",
|
||||
emoji: "🔴",
|
||||
multiplier: 2
|
||||
},
|
||||
|
||||
|
||||
Black: {
|
||||
name:
|
||||
"Black",
|
||||
|
||||
emoji:
|
||||
"⚫",
|
||||
|
||||
multiplier:
|
||||
2
|
||||
name: "Black",
|
||||
emoji: "⚫",
|
||||
multiplier: 2
|
||||
},
|
||||
|
||||
|
||||
Odd: {
|
||||
name:
|
||||
"Odd",
|
||||
|
||||
emoji:
|
||||
"🔢",
|
||||
|
||||
multiplier:
|
||||
2
|
||||
name: "Odd",
|
||||
emoji: "🔢",
|
||||
multiplier: 2
|
||||
},
|
||||
|
||||
|
||||
Even: {
|
||||
name:
|
||||
"Even",
|
||||
|
||||
emoji:
|
||||
"2️⃣",
|
||||
|
||||
multiplier:
|
||||
2
|
||||
name: "Even",
|
||||
emoji: "2️⃣",
|
||||
multiplier: 2
|
||||
},
|
||||
|
||||
|
||||
Zero: {
|
||||
name:
|
||||
"Zero",
|
||||
|
||||
emoji:
|
||||
"🟢",
|
||||
|
||||
multiplier:
|
||||
36
|
||||
name: "Zero",
|
||||
emoji: "🟢",
|
||||
multiplier: 36
|
||||
}
|
||||
};
|
||||
|
||||
@@ -156,19 +127,21 @@ async function showRoulette(
|
||||
.setTitle(
|
||||
"🎡 Crumb Saucer Roulette"
|
||||
)
|
||||
|
||||
.setDescription(
|
||||
[
|
||||
"European Roulette — **0 to 36**.",
|
||||
"",
|
||||
"Choose your wager.",
|
||||
"",
|
||||
"🔴 **Red** — ×2",
|
||||
"⚫ **Black** — ×2",
|
||||
"🔢 **Odd** — ×2",
|
||||
"2️⃣ **Even** — ×2",
|
||||
"🟢 **Zero** — ×36"
|
||||
"🔴 **Red** — x2",
|
||||
"⚫ **Black** — x2",
|
||||
"🔢 **Odd** — x2",
|
||||
"2️⃣ **Even** — x2",
|
||||
"🟢 **Zero** — x36"
|
||||
].join("\n")
|
||||
)
|
||||
|
||||
.addFields({
|
||||
name:
|
||||
"Your Vault",
|
||||
@@ -176,6 +149,7 @@ async function showRoulette(
|
||||
value:
|
||||
`**${balance.toLocaleString()} 🍪**`
|
||||
})
|
||||
|
||||
.setFooter({
|
||||
text:
|
||||
`crumbRouletteMenu:${interaction.user.id}`
|
||||
@@ -195,7 +169,7 @@ async function showRoulette(
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* CHOOSE WAGER
|
||||
* CHOOSE NORMAL WAGER
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
@@ -238,6 +212,114 @@ async function chooseRouletteBet(
|
||||
}
|
||||
|
||||
|
||||
return showRouletteChoices(
|
||||
interaction,
|
||||
bet
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* ALL IN
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
async function startRouletteAllIn(
|
||||
interaction
|
||||
) {
|
||||
const ownerId =
|
||||
getRouletteSessionOwner(
|
||||
interaction
|
||||
);
|
||||
|
||||
|
||||
if (
|
||||
ownerId !==
|
||||
interaction.user.id
|
||||
) {
|
||||
return temporaryEphemeralReply(
|
||||
interaction,
|
||||
{
|
||||
content:
|
||||
"This isn't your Roulette table."
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resolve the balance at click time.
|
||||
*/
|
||||
|
||||
const balance =
|
||||
await getCookieBalance(
|
||||
interaction.user.id
|
||||
);
|
||||
|
||||
|
||||
if (
|
||||
balance <=
|
||||
0
|
||||
) {
|
||||
return temporaryEphemeralReply(
|
||||
interaction,
|
||||
{
|
||||
content:
|
||||
"You don't have any Cookies to go All In with."
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* All In only selects the wager.
|
||||
*
|
||||
* Nothing is transferred until the player
|
||||
* chooses Red / Black / Odd / Even / Zero.
|
||||
*/
|
||||
|
||||
return showRouletteChoices(
|
||||
interaction,
|
||||
balance
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* SHOW CHOICE MENU
|
||||
* ============================================================
|
||||
*
|
||||
* Shared by:
|
||||
*
|
||||
* - normal wager buttons
|
||||
* - All In
|
||||
* - Run It Back
|
||||
*/
|
||||
|
||||
async function showRouletteChoices(
|
||||
interaction,
|
||||
bet
|
||||
) {
|
||||
if (
|
||||
!Number.isSafeInteger(
|
||||
bet
|
||||
)
|
||||
||
|
||||
bet <=
|
||||
0
|
||||
) {
|
||||
return temporaryEphemeralReply(
|
||||
interaction,
|
||||
{
|
||||
content:
|
||||
"That Roulette wager isn't valid."
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const balance =
|
||||
await getCookieBalance(
|
||||
interaction.user.id
|
||||
@@ -263,19 +345,29 @@ async function chooseRouletteBet(
|
||||
.setTitle(
|
||||
"🎡 Crumb Saucer Roulette"
|
||||
)
|
||||
|
||||
.setDescription(
|
||||
[
|
||||
`Wager: **${bet.toLocaleString()} 🍪**`,
|
||||
"",
|
||||
"Where do you want to place your Cookies?",
|
||||
"",
|
||||
"🔴 **Red** — ×2",
|
||||
"⚫ **Black** — ×2",
|
||||
"🔢 **Odd** — ×2",
|
||||
"2️⃣ **Even** — ×2",
|
||||
"🟢 **Zero** — ×36"
|
||||
"🔴 **Red** — x2",
|
||||
"⚫ **Black** — x2",
|
||||
"🔢 **Odd** — x2",
|
||||
"2️⃣ **Even** — x2",
|
||||
"🟢 **Zero** — x36"
|
||||
].join("\n")
|
||||
)
|
||||
|
||||
.addFields({
|
||||
name:
|
||||
"Your Vault",
|
||||
|
||||
value:
|
||||
`**${balance.toLocaleString()} 🍪**`
|
||||
})
|
||||
|
||||
.setFooter({
|
||||
text:
|
||||
`crumbRouletteBet:${interaction.user.id}:${bet}`
|
||||
@@ -293,6 +385,105 @@ async function chooseRouletteBet(
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* RUN IT BACK
|
||||
* ============================================================
|
||||
*
|
||||
* Remembers ONLY the previous wager.
|
||||
*
|
||||
* It does NOT remember Red / Black / Odd / Even / Zero.
|
||||
*/
|
||||
|
||||
async function runRouletteBack(
|
||||
interaction
|
||||
) {
|
||||
const footer =
|
||||
interaction.message
|
||||
?.embeds?.[0]
|
||||
?.footer
|
||||
?.text;
|
||||
|
||||
|
||||
const parts =
|
||||
footer?.split(":")
|
||||
??
|
||||
[];
|
||||
|
||||
|
||||
/*
|
||||
* Expected:
|
||||
*
|
||||
* crumbRouletteResult:<userId>:<bet>
|
||||
*/
|
||||
|
||||
if (
|
||||
parts[0] !==
|
||||
"crumbRouletteResult"
|
||||
) {
|
||||
return temporaryEphemeralReply(
|
||||
interaction,
|
||||
{
|
||||
content:
|
||||
"This Roulette result can no longer be replayed."
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const ownerId =
|
||||
parts[1];
|
||||
|
||||
|
||||
const bet =
|
||||
Number(
|
||||
parts[2]
|
||||
);
|
||||
|
||||
|
||||
if (
|
||||
ownerId !==
|
||||
interaction.user.id
|
||||
) {
|
||||
return temporaryEphemeralReply(
|
||||
interaction,
|
||||
{
|
||||
content:
|
||||
"This isn't your Roulette session."
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
!Number.isSafeInteger(
|
||||
bet
|
||||
)
|
||||
||
|
||||
bet <=
|
||||
0
|
||||
) {
|
||||
return temporaryEphemeralReply(
|
||||
interaction,
|
||||
{
|
||||
content:
|
||||
"The previous wager is no longer valid."
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Same wager, fresh choice.
|
||||
*/
|
||||
|
||||
return showRouletteChoices(
|
||||
interaction,
|
||||
bet
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* PLAY ROULETTE
|
||||
@@ -322,7 +513,7 @@ async function playRoulette(
|
||||
|
||||
const footer =
|
||||
interaction.message
|
||||
.embeds[0]
|
||||
?.embeds?.[0]
|
||||
?.footer
|
||||
?.text;
|
||||
|
||||
@@ -371,10 +562,22 @@ async function playRoulette(
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* IMPORTANT:
|
||||
*
|
||||
* Do NOT require ROULETTE_BETS.includes(bet) here.
|
||||
*
|
||||
* All In and Run It Back may legitimately use
|
||||
* amounts outside the predefined wager buttons.
|
||||
*/
|
||||
|
||||
if (
|
||||
!ROULETTE_BETS.includes(
|
||||
!Number.isSafeInteger(
|
||||
bet
|
||||
)
|
||||
||
|
||||
bet <=
|
||||
0
|
||||
) {
|
||||
return temporaryEphemeralReply(
|
||||
interaction,
|
||||
@@ -409,6 +612,11 @@ async function playRoulette(
|
||||
]);
|
||||
|
||||
|
||||
/*
|
||||
* Balance may have changed while the player
|
||||
* was choosing their bet type.
|
||||
*/
|
||||
|
||||
if (
|
||||
playerBalance <
|
||||
bet
|
||||
@@ -424,11 +632,17 @@ async function playRoulette(
|
||||
|
||||
|
||||
/*
|
||||
* Worst payout is Zero at x36.
|
||||
* Worst payout depends on the selected wager.
|
||||
*
|
||||
* Once the player's wager is transferred to the house,
|
||||
* the house must still be able to cover the remaining
|
||||
* potential payout.
|
||||
* Red / Black / Odd / Even:
|
||||
* x2
|
||||
*
|
||||
* Zero:
|
||||
* x36
|
||||
*
|
||||
* The player's wager is transferred to the house
|
||||
* before payout, so houseBalance + bet is available
|
||||
* after accepting the wager.
|
||||
*/
|
||||
|
||||
const maximumPayout =
|
||||
@@ -452,7 +666,9 @@ async function playRoulette(
|
||||
|
||||
|
||||
/*
|
||||
* Take wager.
|
||||
* ========================================================
|
||||
* TAKE WAGER
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
try {
|
||||
@@ -545,8 +761,9 @@ async function playRoulette(
|
||||
|
||||
|
||||
/*
|
||||
* The real result is only generated after
|
||||
* the animation completes.
|
||||
* ========================================================
|
||||
* ACTUAL RESULT
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
const result =
|
||||
@@ -567,6 +784,12 @@ async function playRoulette(
|
||||
: 0;
|
||||
|
||||
|
||||
/*
|
||||
* ========================================================
|
||||
* PAYOUT
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
if (
|
||||
payout >
|
||||
0
|
||||
@@ -591,9 +814,15 @@ async function playRoulette(
|
||||
.setTitle(
|
||||
"🎡 Roulette Error"
|
||||
)
|
||||
|
||||
.setDescription(
|
||||
"The wheel resolved, but the payout failed. Please contact an administrator."
|
||||
)
|
||||
|
||||
.setFooter({
|
||||
text:
|
||||
`crumbRouletteResult:${playerId}:${bet}`
|
||||
})
|
||||
],
|
||||
|
||||
components:
|
||||
@@ -630,6 +859,7 @@ async function playRoulette(
|
||||
? "🎉 Roulette Winner!"
|
||||
: "🎡 Roulette"
|
||||
)
|
||||
|
||||
.setDescription(
|
||||
[
|
||||
"## The ball lands on...",
|
||||
@@ -643,6 +873,7 @@ async function playRoulette(
|
||||
: "The house takes this one."
|
||||
].join("\n")
|
||||
)
|
||||
|
||||
.addFields(
|
||||
{
|
||||
name:
|
||||
@@ -699,9 +930,17 @@ async function playRoulette(
|
||||
true
|
||||
}
|
||||
)
|
||||
|
||||
/*
|
||||
* Remember only:
|
||||
*
|
||||
* owner
|
||||
* wager
|
||||
*/
|
||||
|
||||
.setFooter({
|
||||
text:
|
||||
`crumbRouletteResult:${interaction.user.id}`
|
||||
`crumbRouletteResult:${playerId}:${bet}`
|
||||
});
|
||||
|
||||
|
||||
@@ -728,6 +967,7 @@ function didRouletteBetWin(
|
||||
) {
|
||||
switch (choice) {
|
||||
case "Red":
|
||||
|
||||
return (
|
||||
number !==
|
||||
0
|
||||
@@ -739,6 +979,7 @@ function didRouletteBetWin(
|
||||
|
||||
|
||||
case "Black":
|
||||
|
||||
return (
|
||||
number !==
|
||||
0
|
||||
@@ -750,6 +991,7 @@ function didRouletteBetWin(
|
||||
|
||||
|
||||
case "Odd":
|
||||
|
||||
return (
|
||||
number !==
|
||||
0
|
||||
@@ -761,6 +1003,7 @@ function didRouletteBetWin(
|
||||
|
||||
|
||||
case "Even":
|
||||
|
||||
return (
|
||||
number !==
|
||||
0
|
||||
@@ -772,6 +1015,7 @@ function didRouletteBetWin(
|
||||
|
||||
|
||||
case "Zero":
|
||||
|
||||
return (
|
||||
number ===
|
||||
0
|
||||
@@ -779,6 +1023,7 @@ function didRouletteBetWin(
|
||||
|
||||
|
||||
default:
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -800,6 +1045,7 @@ function buildSpinEmbed(
|
||||
.setTitle(
|
||||
"🎡 Crumb Saucer Roulette"
|
||||
)
|
||||
|
||||
.setDescription(
|
||||
[
|
||||
"## 🎡 Spinning...",
|
||||
@@ -809,6 +1055,7 @@ function buildSpinEmbed(
|
||||
`**${status}**`
|
||||
].join("\n")
|
||||
)
|
||||
|
||||
.addFields(
|
||||
{
|
||||
name:
|
||||
@@ -861,7 +1108,7 @@ function formatRouletteNumber(
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* BUTTON BUILDERS
|
||||
* WAGER BUTTONS
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
@@ -875,12 +1122,15 @@ function buildBetButtons() {
|
||||
.setCustomId(
|
||||
`crumbRouletteBet${bet}`
|
||||
)
|
||||
|
||||
.setLabel(
|
||||
bet.toLocaleString()
|
||||
)
|
||||
|
||||
.setEmoji(
|
||||
"🍪"
|
||||
)
|
||||
|
||||
.setStyle(
|
||||
bet >=
|
||||
500
|
||||
@@ -892,6 +1142,20 @@ function buildBetButtons() {
|
||||
|
||||
new ActionRowBuilder()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId(
|
||||
"crumbRouletteAllIn"
|
||||
)
|
||||
.setLabel(
|
||||
"All In"
|
||||
)
|
||||
.setEmoji(
|
||||
"🔥"
|
||||
)
|
||||
.setStyle(
|
||||
ButtonStyle.Danger
|
||||
),
|
||||
|
||||
new ButtonBuilder()
|
||||
.setCustomId(
|
||||
"crumbSaucerBack"
|
||||
@@ -910,6 +1174,12 @@ function buildBetButtons() {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* CHOICE BUTTONS
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function buildChoiceButtons() {
|
||||
return [
|
||||
new ActionRowBuilder()
|
||||
@@ -999,16 +1269,46 @@ function buildChoiceButtons() {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* RESULT BUTTONS
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function buildResultButtons() {
|
||||
return [
|
||||
new ActionRowBuilder()
|
||||
.addComponents(
|
||||
/*
|
||||
* Same wager.
|
||||
*
|
||||
* Player chooses Red/Black/etc again.
|
||||
*/
|
||||
|
||||
new ButtonBuilder()
|
||||
.setCustomId(
|
||||
"crumbRouletteRunItBack"
|
||||
)
|
||||
.setLabel(
|
||||
"Run It Back"
|
||||
)
|
||||
.setEmoji(
|
||||
"🔁"
|
||||
)
|
||||
.setStyle(
|
||||
ButtonStyle.Success
|
||||
),
|
||||
|
||||
/*
|
||||
* Return to wager selection.
|
||||
*/
|
||||
|
||||
new ButtonBuilder()
|
||||
.setCustomId(
|
||||
"crumbSaucerRoulette"
|
||||
)
|
||||
.setLabel(
|
||||
"Play Again"
|
||||
"Change Bet"
|
||||
)
|
||||
.setEmoji(
|
||||
"🎡"
|
||||
@@ -1017,6 +1317,10 @@ function buildResultButtons() {
|
||||
ButtonStyle.Primary
|
||||
),
|
||||
|
||||
/*
|
||||
* Main Crumb Saucer.
|
||||
*/
|
||||
|
||||
new ButtonBuilder()
|
||||
.setCustomId(
|
||||
"crumbSaucerBack"
|
||||
@@ -1046,7 +1350,7 @@ function getRouletteSessionOwner(
|
||||
) {
|
||||
const footer =
|
||||
interaction.message
|
||||
.embeds[0]
|
||||
?.embeds?.[0]
|
||||
?.footer
|
||||
?.text;
|
||||
|
||||
@@ -1060,6 +1364,7 @@ function getRouletteSessionOwner(
|
||||
/*
|
||||
* Main Saucer
|
||||
*/
|
||||
|
||||
if (
|
||||
parts[0] ===
|
||||
"crumbSaucer"
|
||||
@@ -1071,6 +1376,7 @@ function getRouletteSessionOwner(
|
||||
/*
|
||||
* Roulette wager menu
|
||||
*/
|
||||
|
||||
if (
|
||||
parts[0] ===
|
||||
"crumbRouletteMenu"
|
||||
@@ -1080,8 +1386,21 @@ function getRouletteSessionOwner(
|
||||
|
||||
|
||||
/*
|
||||
* Roulette result
|
||||
* Roulette choice menu.
|
||||
*/
|
||||
|
||||
if (
|
||||
parts[0] ===
|
||||
"crumbRouletteBet"
|
||||
) {
|
||||
return parts[1];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Roulette result.
|
||||
*/
|
||||
|
||||
if (
|
||||
parts[0] ===
|
||||
"crumbRouletteResult"
|
||||
@@ -1121,8 +1440,20 @@ function sleep(
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ============================================================
|
||||
* EXPORTS
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
showRoulette,
|
||||
|
||||
chooseRouletteBet,
|
||||
playRoulette
|
||||
startRouletteAllIn,
|
||||
showRouletteChoices,
|
||||
|
||||
playRoulette,
|
||||
|
||||
runRouletteBack
|
||||
};
|
||||
Reference in New Issue
Block a user