Merge branch 'main' of https://git.desq-gaming.de/admin_rb/ShaiBot
This commit is contained in:
@@ -9,7 +9,9 @@ module.exports = {
|
|||||||
name:
|
name:
|
||||||
"crumbSaucerBlackjack",
|
"crumbSaucerBlackjack",
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
return showBlackjack(
|
return showBlackjack(
|
||||||
interaction
|
interaction
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
const {
|
||||||
|
startBlackjackAllIn
|
||||||
|
} = require(
|
||||||
|
"../../utils/crumbBlackjack"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"crumbBlackjackAllIn",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
return startBlackjackAllIn(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -9,7 +9,9 @@ module.exports = {
|
|||||||
name:
|
name:
|
||||||
"crumbBlackjackDouble",
|
"crumbBlackjackDouble",
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
return doubleBlackjack(
|
return doubleBlackjack(
|
||||||
interaction
|
interaction
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ module.exports = {
|
|||||||
name:
|
name:
|
||||||
"crumbBlackjackHit",
|
"crumbBlackjackHit",
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
return hitBlackjack(
|
return hitBlackjack(
|
||||||
interaction
|
interaction
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
const {
|
||||||
|
runBlackjackBack
|
||||||
|
} = require(
|
||||||
|
"../../utils/crumbBlackjack"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"crumbBlackjackRunItBack",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
return runBlackjackBack(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -9,7 +9,9 @@ module.exports = {
|
|||||||
name:
|
name:
|
||||||
"crumbBlackjackStand",
|
"crumbBlackjackStand",
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
return standBlackjack(
|
return standBlackjack(
|
||||||
interaction
|
interaction
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
const {
|
||||||
|
startRouletteAllIn
|
||||||
|
} = require(
|
||||||
|
"../../utils/crumbRoulette"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"crumbRouletteAllIn",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
return startRouletteAllIn(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
const {
|
||||||
|
runRouletteBack
|
||||||
|
} = require(
|
||||||
|
"../../utils/crumbRoulette"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name:
|
||||||
|
"crumbRouletteRunItBack",
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
return runRouletteBack(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -193,7 +193,7 @@ async function collect(interaction) {
|
|||||||
let amount =
|
let amount =
|
||||||
randomInteger(
|
randomInteger(
|
||||||
1,
|
1,
|
||||||
20
|
200
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+54
-23
@@ -91,7 +91,7 @@ async function resolveCookieHeist(
|
|||||||
|
|
||||||
const footer =
|
const footer =
|
||||||
interaction.message
|
interaction.message
|
||||||
.embeds[0]
|
?.embeds?.[0]
|
||||||
?.footer
|
?.footer
|
||||||
?.text;
|
?.text;
|
||||||
|
|
||||||
@@ -101,12 +101,16 @@ async function resolveCookieHeist(
|
|||||||
ownerId
|
ownerId
|
||||||
] =
|
] =
|
||||||
footer?.split(":")
|
footer?.split(":")
|
||||||
?? [];
|
??
|
||||||
|
[];
|
||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
type !== "cookieHeist" ||
|
type !==
|
||||||
ownerId !== interaction.user.id
|
"cookieHeist"
|
||||||
|
||
|
||||||
|
ownerId !==
|
||||||
|
interaction.user.id
|
||||||
) {
|
) {
|
||||||
return temporaryEphemeralReply(
|
return temporaryEphemeralReply(
|
||||||
interaction,
|
interaction,
|
||||||
@@ -143,16 +147,6 @@ async function resolveCookieHeist(
|
|||||||
* ========================================================
|
* ========================================================
|
||||||
* SHARED HEIST COOLDOWN
|
* SHARED HEIST COOLDOWN
|
||||||
* ========================================================
|
* ========================================================
|
||||||
*
|
|
||||||
* IMPORTANT:
|
|
||||||
*
|
|
||||||
* This is intentionally always "heist".
|
|
||||||
*
|
|
||||||
* It does NOT use:
|
|
||||||
*
|
|
||||||
* heistSneak
|
|
||||||
* heistHack
|
|
||||||
* heistSmash
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const cooldown =
|
const cooldown =
|
||||||
@@ -164,7 +158,9 @@ async function resolveCookieHeist(
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
if (!cooldown.claimed) {
|
if (
|
||||||
|
!cooldown.claimed
|
||||||
|
) {
|
||||||
return temporaryEphemeralReply(
|
return temporaryEphemeralReply(
|
||||||
interaction,
|
interaction,
|
||||||
{
|
{
|
||||||
@@ -178,9 +174,6 @@ async function resolveCookieHeist(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Lock this Heist interaction immediately.
|
* Lock this Heist interaction immediately.
|
||||||
*
|
|
||||||
* Prevents selecting another approach from
|
|
||||||
* the same message.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
await interaction.update({
|
await interaction.update({
|
||||||
@@ -194,6 +187,10 @@ async function resolveCookieHeist(
|
|||||||
methodName
|
methodName
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.setFooter({
|
||||||
|
text:
|
||||||
|
`cookieHeist:${interaction.user.id}`
|
||||||
|
})
|
||||||
],
|
],
|
||||||
|
|
||||||
components: []
|
components: []
|
||||||
@@ -203,6 +200,7 @@ async function resolveCookieHeist(
|
|||||||
const playerId =
|
const playerId =
|
||||||
interaction.user.id;
|
interaction.user.id;
|
||||||
|
|
||||||
|
|
||||||
const vaultId =
|
const vaultId =
|
||||||
interaction.client.user.id;
|
interaction.client.user.id;
|
||||||
|
|
||||||
@@ -228,8 +226,11 @@ async function resolveCookieHeist(
|
|||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
playerCookies < 1 ||
|
playerCookies <
|
||||||
vaultCookies < 1
|
1
|
||||||
|
||
|
||||||
|
vaultCookies <
|
||||||
|
1
|
||||||
) {
|
) {
|
||||||
return interaction.editReply({
|
return interaction.editReply({
|
||||||
embeds: [
|
embeds: [
|
||||||
@@ -247,6 +248,10 @@ async function resolveCookieHeist(
|
|||||||
value:
|
value:
|
||||||
`<t:${cooldown.next}:R>`
|
`<t:${cooldown.next}:R>`
|
||||||
})
|
})
|
||||||
|
.setFooter({
|
||||||
|
text:
|
||||||
|
`cookieHeist:${playerId}`
|
||||||
|
})
|
||||||
],
|
],
|
||||||
|
|
||||||
components:
|
components:
|
||||||
@@ -349,6 +354,10 @@ async function resolveCookieHeist(
|
|||||||
value:
|
value:
|
||||||
`<t:${cooldown.next}:R>`
|
`<t:${cooldown.next}:R>`
|
||||||
})
|
})
|
||||||
|
.setFooter({
|
||||||
|
text:
|
||||||
|
`cookieHeist:${playerId}`
|
||||||
|
})
|
||||||
],
|
],
|
||||||
|
|
||||||
components:
|
components:
|
||||||
@@ -476,7 +485,12 @@ async function resolveCookieHeist(
|
|||||||
inline:
|
inline:
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
|
||||||
|
.setFooter({
|
||||||
|
text:
|
||||||
|
`cookieHeist:${playerId}`
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
return interaction.editReply({
|
return interaction.editReply({
|
||||||
@@ -551,6 +565,10 @@ async function resolveCookieHeist(
|
|||||||
value:
|
value:
|
||||||
`<t:${cooldown.next}:R>`
|
`<t:${cooldown.next}:R>`
|
||||||
})
|
})
|
||||||
|
.setFooter({
|
||||||
|
text:
|
||||||
|
`cookieHeist:${playerId}`
|
||||||
|
})
|
||||||
],
|
],
|
||||||
|
|
||||||
components:
|
components:
|
||||||
@@ -678,7 +696,12 @@ async function resolveCookieHeist(
|
|||||||
inline:
|
inline:
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
|
||||||
|
.setFooter({
|
||||||
|
text:
|
||||||
|
`cookieHeist:${playerId}`
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
return interaction.editReply({
|
return interaction.editReply({
|
||||||
@@ -894,7 +917,9 @@ function getFailureText(
|
|||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function sleep(ms) {
|
function sleep(
|
||||||
|
ms
|
||||||
|
) {
|
||||||
return new Promise(
|
return new Promise(
|
||||||
resolve =>
|
resolve =>
|
||||||
setTimeout(
|
setTimeout(
|
||||||
@@ -905,6 +930,12 @@ function sleep(ms) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* EXPORTS
|
||||||
|
* ============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
resolveCookieHeist,
|
resolveCookieHeist,
|
||||||
HEIST_COOLDOWN
|
HEIST_COOLDOWN
|
||||||
|
|||||||
+522
-177
File diff suppressed because it is too large
Load Diff
+401
-70
@@ -29,62 +29,33 @@ const ROULETTE_BETS = [
|
|||||||
|
|
||||||
const ROULETTE_CHOICES = {
|
const ROULETTE_CHOICES = {
|
||||||
Red: {
|
Red: {
|
||||||
name:
|
name: "Red",
|
||||||
"Red",
|
emoji: "🔴",
|
||||||
|
multiplier: 2
|
||||||
emoji:
|
|
||||||
"🔴",
|
|
||||||
|
|
||||||
multiplier:
|
|
||||||
2
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
Black: {
|
Black: {
|
||||||
name:
|
name: "Black",
|
||||||
"Black",
|
emoji: "⚫",
|
||||||
|
multiplier: 2
|
||||||
emoji:
|
|
||||||
"⚫",
|
|
||||||
|
|
||||||
multiplier:
|
|
||||||
2
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
Odd: {
|
Odd: {
|
||||||
name:
|
name: "Odd",
|
||||||
"Odd",
|
emoji: "🔢",
|
||||||
|
multiplier: 2
|
||||||
emoji:
|
|
||||||
"🔢",
|
|
||||||
|
|
||||||
multiplier:
|
|
||||||
2
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
Even: {
|
Even: {
|
||||||
name:
|
name: "Even",
|
||||||
"Even",
|
emoji: "2️⃣",
|
||||||
|
multiplier: 2
|
||||||
emoji:
|
|
||||||
"2️⃣",
|
|
||||||
|
|
||||||
multiplier:
|
|
||||||
2
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
Zero: {
|
Zero: {
|
||||||
name:
|
name: "Zero",
|
||||||
"Zero",
|
emoji: "🟢",
|
||||||
|
multiplier: 36
|
||||||
emoji:
|
|
||||||
"🟢",
|
|
||||||
|
|
||||||
multiplier:
|
|
||||||
36
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -156,19 +127,21 @@ async function showRoulette(
|
|||||||
.setTitle(
|
.setTitle(
|
||||||
"🎡 Crumb Saucer Roulette"
|
"🎡 Crumb Saucer Roulette"
|
||||||
)
|
)
|
||||||
|
|
||||||
.setDescription(
|
.setDescription(
|
||||||
[
|
[
|
||||||
"European Roulette — **0 to 36**.",
|
"European Roulette — **0 to 36**.",
|
||||||
"",
|
"",
|
||||||
"Choose your wager.",
|
"Choose your wager.",
|
||||||
"",
|
"",
|
||||||
"🔴 **Red** — ×2",
|
"🔴 **Red** — x2",
|
||||||
"⚫ **Black** — ×2",
|
"⚫ **Black** — x2",
|
||||||
"🔢 **Odd** — ×2",
|
"🔢 **Odd** — x2",
|
||||||
"2️⃣ **Even** — ×2",
|
"2️⃣ **Even** — x2",
|
||||||
"🟢 **Zero** — ×36"
|
"🟢 **Zero** — x36"
|
||||||
].join("\n")
|
].join("\n")
|
||||||
)
|
)
|
||||||
|
|
||||||
.addFields({
|
.addFields({
|
||||||
name:
|
name:
|
||||||
"Your Vault",
|
"Your Vault",
|
||||||
@@ -176,6 +149,7 @@ async function showRoulette(
|
|||||||
value:
|
value:
|
||||||
`**${balance.toLocaleString()} 🍪**`
|
`**${balance.toLocaleString()} 🍪**`
|
||||||
})
|
})
|
||||||
|
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text:
|
text:
|
||||||
`crumbRouletteMenu:${interaction.user.id}`
|
`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 =
|
const balance =
|
||||||
await getCookieBalance(
|
await getCookieBalance(
|
||||||
interaction.user.id
|
interaction.user.id
|
||||||
@@ -263,19 +345,29 @@ async function chooseRouletteBet(
|
|||||||
.setTitle(
|
.setTitle(
|
||||||
"🎡 Crumb Saucer Roulette"
|
"🎡 Crumb Saucer Roulette"
|
||||||
)
|
)
|
||||||
|
|
||||||
.setDescription(
|
.setDescription(
|
||||||
[
|
[
|
||||||
`Wager: **${bet.toLocaleString()} 🍪**`,
|
`Wager: **${bet.toLocaleString()} 🍪**`,
|
||||||
"",
|
"",
|
||||||
"Where do you want to place your Cookies?",
|
"Where do you want to place your Cookies?",
|
||||||
"",
|
"",
|
||||||
"🔴 **Red** — ×2",
|
"🔴 **Red** — x2",
|
||||||
"⚫ **Black** — ×2",
|
"⚫ **Black** — x2",
|
||||||
"🔢 **Odd** — ×2",
|
"🔢 **Odd** — x2",
|
||||||
"2️⃣ **Even** — ×2",
|
"2️⃣ **Even** — x2",
|
||||||
"🟢 **Zero** — ×36"
|
"🟢 **Zero** — x36"
|
||||||
].join("\n")
|
].join("\n")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
.addFields({
|
||||||
|
name:
|
||||||
|
"Your Vault",
|
||||||
|
|
||||||
|
value:
|
||||||
|
`**${balance.toLocaleString()} 🍪**`
|
||||||
|
})
|
||||||
|
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text:
|
text:
|
||||||
`crumbRouletteBet:${interaction.user.id}:${bet}`
|
`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
|
* PLAY ROULETTE
|
||||||
@@ -322,7 +513,7 @@ async function playRoulette(
|
|||||||
|
|
||||||
const footer =
|
const footer =
|
||||||
interaction.message
|
interaction.message
|
||||||
.embeds[0]
|
?.embeds?.[0]
|
||||||
?.footer
|
?.footer
|
||||||
?.text;
|
?.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 (
|
if (
|
||||||
!ROULETTE_BETS.includes(
|
!Number.isSafeInteger(
|
||||||
bet
|
bet
|
||||||
)
|
)
|
||||||
|
||
|
||||||
|
bet <=
|
||||||
|
0
|
||||||
) {
|
) {
|
||||||
return temporaryEphemeralReply(
|
return temporaryEphemeralReply(
|
||||||
interaction,
|
interaction,
|
||||||
@@ -409,6 +612,11 @@ async function playRoulette(
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Balance may have changed while the player
|
||||||
|
* was choosing their bet type.
|
||||||
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
playerBalance <
|
playerBalance <
|
||||||
bet
|
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,
|
* Red / Black / Odd / Even:
|
||||||
* the house must still be able to cover the remaining
|
* x2
|
||||||
* potential payout.
|
*
|
||||||
|
* Zero:
|
||||||
|
* x36
|
||||||
|
*
|
||||||
|
* The player's wager is transferred to the house
|
||||||
|
* before payout, so houseBalance + bet is available
|
||||||
|
* after accepting the wager.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const maximumPayout =
|
const maximumPayout =
|
||||||
@@ -452,7 +666,9 @@ async function playRoulette(
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Take wager.
|
* ========================================================
|
||||||
|
* TAKE WAGER
|
||||||
|
* ========================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -545,8 +761,9 @@ async function playRoulette(
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The real result is only generated after
|
* ========================================================
|
||||||
* the animation completes.
|
* ACTUAL RESULT
|
||||||
|
* ========================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const result =
|
const result =
|
||||||
@@ -567,6 +784,12 @@ async function playRoulette(
|
|||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ========================================================
|
||||||
|
* PAYOUT
|
||||||
|
* ========================================================
|
||||||
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
payout >
|
payout >
|
||||||
0
|
0
|
||||||
@@ -591,9 +814,15 @@ async function playRoulette(
|
|||||||
.setTitle(
|
.setTitle(
|
||||||
"🎡 Roulette Error"
|
"🎡 Roulette Error"
|
||||||
)
|
)
|
||||||
|
|
||||||
.setDescription(
|
.setDescription(
|
||||||
"The wheel resolved, but the payout failed. Please contact an administrator."
|
"The wheel resolved, but the payout failed. Please contact an administrator."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
.setFooter({
|
||||||
|
text:
|
||||||
|
`crumbRouletteResult:${playerId}:${bet}`
|
||||||
|
})
|
||||||
],
|
],
|
||||||
|
|
||||||
components:
|
components:
|
||||||
@@ -630,6 +859,7 @@ async function playRoulette(
|
|||||||
? "🎉 Roulette Winner!"
|
? "🎉 Roulette Winner!"
|
||||||
: "🎡 Roulette"
|
: "🎡 Roulette"
|
||||||
)
|
)
|
||||||
|
|
||||||
.setDescription(
|
.setDescription(
|
||||||
[
|
[
|
||||||
"## The ball lands on...",
|
"## The ball lands on...",
|
||||||
@@ -643,6 +873,7 @@ async function playRoulette(
|
|||||||
: "The house takes this one."
|
: "The house takes this one."
|
||||||
].join("\n")
|
].join("\n")
|
||||||
)
|
)
|
||||||
|
|
||||||
.addFields(
|
.addFields(
|
||||||
{
|
{
|
||||||
name:
|
name:
|
||||||
@@ -699,9 +930,17 @@ async function playRoulette(
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remember only:
|
||||||
|
*
|
||||||
|
* owner
|
||||||
|
* wager
|
||||||
|
*/
|
||||||
|
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text:
|
text:
|
||||||
`crumbRouletteResult:${interaction.user.id}`
|
`crumbRouletteResult:${playerId}:${bet}`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -728,6 +967,7 @@ function didRouletteBetWin(
|
|||||||
) {
|
) {
|
||||||
switch (choice) {
|
switch (choice) {
|
||||||
case "Red":
|
case "Red":
|
||||||
|
|
||||||
return (
|
return (
|
||||||
number !==
|
number !==
|
||||||
0
|
0
|
||||||
@@ -739,6 +979,7 @@ function didRouletteBetWin(
|
|||||||
|
|
||||||
|
|
||||||
case "Black":
|
case "Black":
|
||||||
|
|
||||||
return (
|
return (
|
||||||
number !==
|
number !==
|
||||||
0
|
0
|
||||||
@@ -750,6 +991,7 @@ function didRouletteBetWin(
|
|||||||
|
|
||||||
|
|
||||||
case "Odd":
|
case "Odd":
|
||||||
|
|
||||||
return (
|
return (
|
||||||
number !==
|
number !==
|
||||||
0
|
0
|
||||||
@@ -761,6 +1003,7 @@ function didRouletteBetWin(
|
|||||||
|
|
||||||
|
|
||||||
case "Even":
|
case "Even":
|
||||||
|
|
||||||
return (
|
return (
|
||||||
number !==
|
number !==
|
||||||
0
|
0
|
||||||
@@ -772,6 +1015,7 @@ function didRouletteBetWin(
|
|||||||
|
|
||||||
|
|
||||||
case "Zero":
|
case "Zero":
|
||||||
|
|
||||||
return (
|
return (
|
||||||
number ===
|
number ===
|
||||||
0
|
0
|
||||||
@@ -779,6 +1023,7 @@ function didRouletteBetWin(
|
|||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -800,6 +1045,7 @@ function buildSpinEmbed(
|
|||||||
.setTitle(
|
.setTitle(
|
||||||
"🎡 Crumb Saucer Roulette"
|
"🎡 Crumb Saucer Roulette"
|
||||||
)
|
)
|
||||||
|
|
||||||
.setDescription(
|
.setDescription(
|
||||||
[
|
[
|
||||||
"## 🎡 Spinning...",
|
"## 🎡 Spinning...",
|
||||||
@@ -809,6 +1055,7 @@ function buildSpinEmbed(
|
|||||||
`**${status}**`
|
`**${status}**`
|
||||||
].join("\n")
|
].join("\n")
|
||||||
)
|
)
|
||||||
|
|
||||||
.addFields(
|
.addFields(
|
||||||
{
|
{
|
||||||
name:
|
name:
|
||||||
@@ -861,7 +1108,7 @@ function formatRouletteNumber(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* ============================================================
|
* ============================================================
|
||||||
* BUTTON BUILDERS
|
* WAGER BUTTONS
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -875,12 +1122,15 @@ function buildBetButtons() {
|
|||||||
.setCustomId(
|
.setCustomId(
|
||||||
`crumbRouletteBet${bet}`
|
`crumbRouletteBet${bet}`
|
||||||
)
|
)
|
||||||
|
|
||||||
.setLabel(
|
.setLabel(
|
||||||
bet.toLocaleString()
|
bet.toLocaleString()
|
||||||
)
|
)
|
||||||
|
|
||||||
.setEmoji(
|
.setEmoji(
|
||||||
"🍪"
|
"🍪"
|
||||||
)
|
)
|
||||||
|
|
||||||
.setStyle(
|
.setStyle(
|
||||||
bet >=
|
bet >=
|
||||||
500
|
500
|
||||||
@@ -892,6 +1142,20 @@ function buildBetButtons() {
|
|||||||
|
|
||||||
new ActionRowBuilder()
|
new ActionRowBuilder()
|
||||||
.addComponents(
|
.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId(
|
||||||
|
"crumbRouletteAllIn"
|
||||||
|
)
|
||||||
|
.setLabel(
|
||||||
|
"All In"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"🔥"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Danger
|
||||||
|
),
|
||||||
|
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId(
|
.setCustomId(
|
||||||
"crumbSaucerBack"
|
"crumbSaucerBack"
|
||||||
@@ -910,6 +1174,12 @@ function buildBetButtons() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* CHOICE BUTTONS
|
||||||
|
* ============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
function buildChoiceButtons() {
|
function buildChoiceButtons() {
|
||||||
return [
|
return [
|
||||||
new ActionRowBuilder()
|
new ActionRowBuilder()
|
||||||
@@ -999,16 +1269,46 @@ function buildChoiceButtons() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* RESULT BUTTONS
|
||||||
|
* ============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
function buildResultButtons() {
|
function buildResultButtons() {
|
||||||
return [
|
return [
|
||||||
new ActionRowBuilder()
|
new ActionRowBuilder()
|
||||||
.addComponents(
|
.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()
|
new ButtonBuilder()
|
||||||
.setCustomId(
|
.setCustomId(
|
||||||
"crumbSaucerRoulette"
|
"crumbSaucerRoulette"
|
||||||
)
|
)
|
||||||
.setLabel(
|
.setLabel(
|
||||||
"Play Again"
|
"Change Bet"
|
||||||
)
|
)
|
||||||
.setEmoji(
|
.setEmoji(
|
||||||
"🎡"
|
"🎡"
|
||||||
@@ -1017,6 +1317,10 @@ function buildResultButtons() {
|
|||||||
ButtonStyle.Primary
|
ButtonStyle.Primary
|
||||||
),
|
),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main Crumb Saucer.
|
||||||
|
*/
|
||||||
|
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId(
|
.setCustomId(
|
||||||
"crumbSaucerBack"
|
"crumbSaucerBack"
|
||||||
@@ -1046,7 +1350,7 @@ function getRouletteSessionOwner(
|
|||||||
) {
|
) {
|
||||||
const footer =
|
const footer =
|
||||||
interaction.message
|
interaction.message
|
||||||
.embeds[0]
|
?.embeds?.[0]
|
||||||
?.footer
|
?.footer
|
||||||
?.text;
|
?.text;
|
||||||
|
|
||||||
@@ -1060,6 +1364,7 @@ function getRouletteSessionOwner(
|
|||||||
/*
|
/*
|
||||||
* Main Saucer
|
* Main Saucer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
parts[0] ===
|
parts[0] ===
|
||||||
"crumbSaucer"
|
"crumbSaucer"
|
||||||
@@ -1071,6 +1376,7 @@ function getRouletteSessionOwner(
|
|||||||
/*
|
/*
|
||||||
* Roulette wager menu
|
* Roulette wager menu
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
parts[0] ===
|
parts[0] ===
|
||||||
"crumbRouletteMenu"
|
"crumbRouletteMenu"
|
||||||
@@ -1080,8 +1386,21 @@ function getRouletteSessionOwner(
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Roulette result
|
* Roulette choice menu.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (
|
||||||
|
parts[0] ===
|
||||||
|
"crumbRouletteBet"
|
||||||
|
) {
|
||||||
|
return parts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Roulette result.
|
||||||
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
parts[0] ===
|
parts[0] ===
|
||||||
"crumbRouletteResult"
|
"crumbRouletteResult"
|
||||||
@@ -1121,8 +1440,20 @@ function sleep(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* EXPORTS
|
||||||
|
* ============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
showRoulette,
|
showRoulette,
|
||||||
|
|
||||||
chooseRouletteBet,
|
chooseRouletteBet,
|
||||||
playRoulette
|
startRouletteAllIn,
|
||||||
|
showRouletteChoices,
|
||||||
|
|
||||||
|
playRoulette,
|
||||||
|
|
||||||
|
runRouletteBack
|
||||||
};
|
};
|
||||||
+348
-120
@@ -14,7 +14,9 @@ const {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* ============================================================
|
||||||
* SLOT CONFIG
|
* SLOT CONFIG
|
||||||
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const SLOT_BETS = [
|
const SLOT_BETS = [
|
||||||
@@ -98,6 +100,40 @@ const SLOT_OUTCOMES = [
|
|||||||
async function showCrumbSaucer(
|
async function showCrumbSaucer(
|
||||||
interaction
|
interaction
|
||||||
) {
|
) {
|
||||||
|
/*
|
||||||
|
* If this is being called from a button,
|
||||||
|
* verify that the player owns the current
|
||||||
|
* Crumb Saucer / game session.
|
||||||
|
*
|
||||||
|
* This prevents another user from pressing
|
||||||
|
* "Crumb Saucer" / "Back" on somebody else's
|
||||||
|
* game message and taking over their session.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (
|
||||||
|
interaction.isButton()
|
||||||
|
) {
|
||||||
|
const ownerId =
|
||||||
|
getCrumbSaucerSessionOwner(
|
||||||
|
interaction
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if (
|
||||||
|
ownerId !==
|
||||||
|
interaction.user.id
|
||||||
|
) {
|
||||||
|
return temporaryEphemeralReply(
|
||||||
|
interaction,
|
||||||
|
{
|
||||||
|
content:
|
||||||
|
"This isn't your Crumb Saucer session."
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const balance =
|
const balance =
|
||||||
await getCookieBalance(
|
await getCookieBalance(
|
||||||
interaction.user.id
|
interaction.user.id
|
||||||
@@ -116,11 +152,8 @@ async function showCrumbSaucer(
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Slash command:
|
|
||||||
* reply normally.
|
|
||||||
*
|
|
||||||
* Button:
|
* Button:
|
||||||
* update existing menu message.
|
* update existing menu/game message.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -136,6 +169,11 @@ async function showCrumbSaucer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slash command:
|
||||||
|
* create a new Crumb Saucer.
|
||||||
|
*/
|
||||||
|
|
||||||
return interaction.reply({
|
return interaction.reply({
|
||||||
embeds: [
|
embeds: [
|
||||||
embed
|
embed
|
||||||
@@ -145,51 +183,13 @@ async function showCrumbSaucer(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSlotsSessionOwner(
|
|
||||||
interaction
|
|
||||||
) {
|
|
||||||
const footer =
|
|
||||||
interaction.message
|
|
||||||
.embeds[0]
|
|
||||||
?.footer
|
|
||||||
?.text;
|
|
||||||
|
|
||||||
|
|
||||||
const parts =
|
|
||||||
footer?.split(":")
|
|
||||||
??
|
|
||||||
[];
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Main Crumb Saucer
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
parts[0] ===
|
|
||||||
"crumbSaucer"
|
|
||||||
) {
|
|
||||||
return parts[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Slots menu/result
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
parts[0] ===
|
|
||||||
"crumbSaucerSlots"
|
|
||||||
) {
|
|
||||||
return parts[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* ============================================================
|
* ============================================================
|
||||||
* SLOT MENU
|
* SLOT MENU
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async function showSlots(
|
async function showSlots(
|
||||||
interaction
|
interaction
|
||||||
) {
|
) {
|
||||||
@@ -224,19 +224,21 @@ async function showSlots(
|
|||||||
.setTitle(
|
.setTitle(
|
||||||
"🎰 Crumb Saucer Slots"
|
"🎰 Crumb Saucer Slots"
|
||||||
)
|
)
|
||||||
|
|
||||||
.setDescription(
|
.setDescription(
|
||||||
[
|
[
|
||||||
"Welcome to the Cookie reels.",
|
"Welcome to the Cookie reels.",
|
||||||
"",
|
"",
|
||||||
"Choose your wager below.",
|
"Choose your wager below.",
|
||||||
"",
|
"",
|
||||||
"🍋 **Triple Lemon** — ×1.5",
|
"🍋 **Triple Lemon** — x1.5",
|
||||||
"🍒 **Triple Cherry** — ×2",
|
"🍒 **Triple Cherry** — x2",
|
||||||
"🍪 **Triple Cookie** — ×3",
|
"🍪 **Triple Cookie** — x3",
|
||||||
"⭐ **Triple Star** — ×5",
|
"⭐ **Triple Star** — x5",
|
||||||
"💎 **Jackpot** — ×10"
|
"💎 **Jackpot** — x10"
|
||||||
].join("\n")
|
].join("\n")
|
||||||
)
|
)
|
||||||
|
|
||||||
.addFields({
|
.addFields({
|
||||||
name:
|
name:
|
||||||
"Your Vault",
|
"Your Vault",
|
||||||
@@ -244,6 +246,7 @@ async function showSlots(
|
|||||||
value:
|
value:
|
||||||
`**${balance.toLocaleString()} 🍪**`
|
`**${balance.toLocaleString()} 🍪**`
|
||||||
})
|
})
|
||||||
|
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text:
|
text:
|
||||||
`crumbSaucerSlots:${interaction.user.id}`
|
`crumbSaucerSlots:${interaction.user.id}`
|
||||||
@@ -260,6 +263,7 @@ async function showSlots(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ============================================================
|
* ============================================================
|
||||||
* PLAY SLOTS
|
* PLAY SLOTS
|
||||||
@@ -271,7 +275,7 @@ async function playSlots(
|
|||||||
bet
|
bet
|
||||||
) {
|
) {
|
||||||
const ownerId =
|
const ownerId =
|
||||||
getSlotsOwner(
|
getSlotsSessionOwner(
|
||||||
interaction
|
interaction
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -308,6 +312,7 @@ async function playSlots(
|
|||||||
const playerId =
|
const playerId =
|
||||||
interaction.user.id;
|
interaction.user.id;
|
||||||
|
|
||||||
|
|
||||||
const vaultId =
|
const vaultId =
|
||||||
interaction.client.user.id;
|
interaction.client.user.id;
|
||||||
|
|
||||||
@@ -388,6 +393,7 @@ async function playSlots(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,11 +415,6 @@ async function playSlots(
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A few slow edits give a slot-machine feel
|
|
||||||
* without hammering the Discord API.
|
|
||||||
*/
|
|
||||||
|
|
||||||
await sleep(
|
await sleep(
|
||||||
700
|
700
|
||||||
);
|
);
|
||||||
@@ -478,13 +479,11 @@ async function playSlots(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* House pays winnings.
|
* House pays winnings.
|
||||||
*
|
|
||||||
* The original stake was already transferred
|
|
||||||
* to the house, so x2 means a total payout of 2x.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
payout > 0
|
payout >
|
||||||
|
0
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
await transferCookies(
|
await transferCookies(
|
||||||
@@ -509,6 +508,10 @@ async function playSlots(
|
|||||||
.setDescription(
|
.setDescription(
|
||||||
"The reels stopped, but the payout system had a problem. Please contact an administrator."
|
"The reels stopped, but the payout system had a problem. Please contact an administrator."
|
||||||
)
|
)
|
||||||
|
.setFooter({
|
||||||
|
text:
|
||||||
|
`crumbSaucerSlotsResult:${playerId}:${bet}`
|
||||||
|
})
|
||||||
],
|
],
|
||||||
|
|
||||||
components:
|
components:
|
||||||
@@ -543,6 +546,7 @@ async function playSlots(
|
|||||||
.setTitle(
|
.setTitle(
|
||||||
"🎰 Crumb Saucer Slots"
|
"🎰 Crumb Saucer Slots"
|
||||||
)
|
)
|
||||||
|
|
||||||
.setDescription(
|
.setDescription(
|
||||||
[
|
[
|
||||||
buildSlotDisplay(
|
buildSlotDisplay(
|
||||||
@@ -552,6 +556,7 @@ async function playSlots(
|
|||||||
`### ${getSlotResultName(outcome)}`
|
`### ${getSlotResultName(outcome)}`
|
||||||
].join("\n")
|
].join("\n")
|
||||||
)
|
)
|
||||||
|
|
||||||
.addFields(
|
.addFields(
|
||||||
{
|
{
|
||||||
name:
|
name:
|
||||||
@@ -569,7 +574,7 @@ async function playSlots(
|
|||||||
"Multiplier",
|
"Multiplier",
|
||||||
|
|
||||||
value:
|
value:
|
||||||
`×${outcome.multiplier}`,
|
`x${outcome.multiplier}`,
|
||||||
|
|
||||||
inline:
|
inline:
|
||||||
true
|
true
|
||||||
@@ -619,9 +624,17 @@ async function playSlots(
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store owner + previous wager.
|
||||||
|
*
|
||||||
|
* Run It Back can now replay the exact
|
||||||
|
* same wager without opening the bet menu.
|
||||||
|
*/
|
||||||
|
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text:
|
text:
|
||||||
`crumbSaucerSlots:${interaction.user.id}`
|
`crumbSaucerSlotsResult:${playerId}:${bet}`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -636,6 +649,88 @@ async function playSlots(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* RUN IT BACK
|
||||||
|
* ============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
async function runSlotsBack(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
const footer =
|
||||||
|
interaction.message
|
||||||
|
?.embeds?.[0]
|
||||||
|
?.footer
|
||||||
|
?.text;
|
||||||
|
|
||||||
|
|
||||||
|
const parts =
|
||||||
|
footer?.split(":")
|
||||||
|
??
|
||||||
|
[];
|
||||||
|
|
||||||
|
|
||||||
|
if (
|
||||||
|
parts[0] !==
|
||||||
|
"crumbSaucerSlotsResult"
|
||||||
|
) {
|
||||||
|
return temporaryEphemeralReply(
|
||||||
|
interaction,
|
||||||
|
{
|
||||||
|
content:
|
||||||
|
"This Slots result can no longer be replayed."
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const ownerId =
|
||||||
|
parts[1];
|
||||||
|
|
||||||
|
|
||||||
|
const bet =
|
||||||
|
Number(
|
||||||
|
parts[2]
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if (
|
||||||
|
ownerId !==
|
||||||
|
interaction.user.id
|
||||||
|
) {
|
||||||
|
return temporaryEphemeralReply(
|
||||||
|
interaction,
|
||||||
|
{
|
||||||
|
content:
|
||||||
|
"These aren't your slots."
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (
|
||||||
|
!SLOT_BETS.includes(
|
||||||
|
bet
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return temporaryEphemeralReply(
|
||||||
|
interaction,
|
||||||
|
{
|
||||||
|
content:
|
||||||
|
"The previous wager is no longer available."
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return playSlots(
|
||||||
|
interaction,
|
||||||
|
bet
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ============================================================
|
* ============================================================
|
||||||
* MAIN MENU EMBED
|
* MAIN MENU EMBED
|
||||||
@@ -650,6 +745,7 @@ function buildMainMenuEmbed(
|
|||||||
.setTitle(
|
.setTitle(
|
||||||
"🎰 The Crumb Saucer"
|
"🎰 The Crumb Saucer"
|
||||||
)
|
)
|
||||||
|
|
||||||
.setDescription(
|
.setDescription(
|
||||||
[
|
[
|
||||||
`Welcome, ${user}!`,
|
`Welcome, ${user}!`,
|
||||||
@@ -672,6 +768,7 @@ function buildMainMenuEmbed(
|
|||||||
"*More attractions coming soon... make a lala offering or buy me a white monster*"
|
"*More attractions coming soon... make a lala offering or buy me a white monster*"
|
||||||
].join("\n")
|
].join("\n")
|
||||||
)
|
)
|
||||||
|
|
||||||
.addFields({
|
.addFields({
|
||||||
name:
|
name:
|
||||||
"Your Vault",
|
"Your Vault",
|
||||||
@@ -679,6 +776,7 @@ function buildMainMenuEmbed(
|
|||||||
value:
|
value:
|
||||||
`**${balance.toLocaleString()} 🍪**`
|
`**${balance.toLocaleString()} 🍪**`
|
||||||
})
|
})
|
||||||
|
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text:
|
text:
|
||||||
`crumbSaucer:${user.id}`
|
`crumbSaucer:${user.id}`
|
||||||
@@ -688,7 +786,7 @@ function buildMainMenuEmbed(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* ============================================================
|
* ============================================================
|
||||||
* BUTTONS
|
* MAIN MENU BUTTONS
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -755,6 +853,13 @@ function buildMainMenuButtons() {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* SLOT BET BUTTONS
|
||||||
|
* ============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
function buildSlotBetButtons() {
|
function buildSlotBetButtons() {
|
||||||
return [
|
return [
|
||||||
new ActionRowBuilder()
|
new ActionRowBuilder()
|
||||||
@@ -850,16 +955,44 @@ function buildSlotBetButtons() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* SLOT RESULT BUTTONS
|
||||||
|
* ============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
function buildResultButtons() {
|
function buildResultButtons() {
|
||||||
return [
|
return [
|
||||||
new ActionRowBuilder()
|
new ActionRowBuilder()
|
||||||
.addComponents(
|
.addComponents(
|
||||||
|
/*
|
||||||
|
* Exact same wager immediately.
|
||||||
|
*/
|
||||||
|
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId(
|
||||||
|
"crumbSaucerSlotsRunItBack"
|
||||||
|
)
|
||||||
|
.setLabel(
|
||||||
|
"Run It Back"
|
||||||
|
)
|
||||||
|
.setEmoji(
|
||||||
|
"🔁"
|
||||||
|
)
|
||||||
|
.setStyle(
|
||||||
|
ButtonStyle.Success
|
||||||
|
),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return to wager selection.
|
||||||
|
*/
|
||||||
|
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId(
|
.setCustomId(
|
||||||
"crumbSaucerSlots"
|
"crumbSaucerSlots"
|
||||||
)
|
)
|
||||||
.setLabel(
|
.setLabel(
|
||||||
"Play Again"
|
"Change Bet"
|
||||||
)
|
)
|
||||||
.setEmoji(
|
.setEmoji(
|
||||||
"🎰"
|
"🎰"
|
||||||
@@ -868,6 +1001,10 @@ function buildResultButtons() {
|
|||||||
ButtonStyle.Primary
|
ButtonStyle.Primary
|
||||||
),
|
),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main Saucer.
|
||||||
|
*/
|
||||||
|
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId(
|
.setCustomId(
|
||||||
"crumbSaucerBack"
|
"crumbSaucerBack"
|
||||||
@@ -920,7 +1057,8 @@ function rollSlotOutcome() {
|
|||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
roll <= 0
|
roll <=
|
||||||
|
0
|
||||||
) {
|
) {
|
||||||
return outcome;
|
return outcome;
|
||||||
}
|
}
|
||||||
@@ -959,10 +1097,6 @@ function generateOutcomeGrid(
|
|||||||
generateRandomGrid();
|
generateRandomGrid();
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Winning middle row.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
outcome.type ===
|
outcome.type ===
|
||||||
"triple"
|
"triple"
|
||||||
@@ -978,10 +1112,6 @@ function generateOutcomeGrid(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pair.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
outcome.type ===
|
outcome.type ===
|
||||||
"pair"
|
"pair"
|
||||||
@@ -1002,14 +1132,11 @@ function generateOutcomeGrid(
|
|||||||
);
|
);
|
||||||
|
|
||||||
} while (
|
} while (
|
||||||
other === symbol
|
other ===
|
||||||
|
symbol
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Randomize the location of the odd symbol.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const oddPosition =
|
const oddPosition =
|
||||||
Math.floor(
|
Math.floor(
|
||||||
Math.random() *
|
Math.random() *
|
||||||
@@ -1034,11 +1161,6 @@ function generateOutcomeGrid(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loss:
|
|
||||||
* ensure all three center symbols differ.
|
|
||||||
*/
|
|
||||||
|
|
||||||
let line;
|
let line;
|
||||||
|
|
||||||
|
|
||||||
@@ -1095,6 +1217,7 @@ function buildSpinningEmbed(
|
|||||||
.setTitle(
|
.setTitle(
|
||||||
"🎰 Crumb Saucer Slots"
|
"🎰 Crumb Saucer Slots"
|
||||||
)
|
)
|
||||||
|
|
||||||
.setDescription(
|
.setDescription(
|
||||||
[
|
[
|
||||||
buildSlotDisplay(
|
buildSlotDisplay(
|
||||||
@@ -1104,6 +1227,7 @@ function buildSpinningEmbed(
|
|||||||
`**${status}**`
|
`**${status}**`
|
||||||
].join("\n")
|
].join("\n")
|
||||||
)
|
)
|
||||||
|
|
||||||
.addFields({
|
.addFields({
|
||||||
name:
|
name:
|
||||||
"Bet",
|
"Bet",
|
||||||
@@ -1139,18 +1263,23 @@ function getSlotResultName(
|
|||||||
case "🍋":
|
case "🍋":
|
||||||
return "🍋 Triple Lemon!";
|
return "🍋 Triple Lemon!";
|
||||||
|
|
||||||
|
|
||||||
case "🍒":
|
case "🍒":
|
||||||
return "🍒 Triple Cherry!";
|
return "🍒 Triple Cherry!";
|
||||||
|
|
||||||
|
|
||||||
case "🍪":
|
case "🍪":
|
||||||
return "🍪 Triple Cookie!";
|
return "🍪 Triple Cookie!";
|
||||||
|
|
||||||
|
|
||||||
case "⭐":
|
case "⭐":
|
||||||
return "⭐ Triple Star!";
|
return "⭐ Triple Star!";
|
||||||
|
|
||||||
|
|
||||||
case "💎":
|
case "💎":
|
||||||
return "💎 JACKPOT! 💎";
|
return "💎 JACKPOT! 💎";
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "Winner!";
|
return "Winner!";
|
||||||
}
|
}
|
||||||
@@ -1159,75 +1288,166 @@ function getSlotResultName(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* ============================================================
|
* ============================================================
|
||||||
* OWNER RESOLUTION
|
* SESSION OWNER RESOLUTION
|
||||||
|
* ============================================================
|
||||||
|
*
|
||||||
|
* This intentionally understands every Crumb Saucer
|
||||||
|
* screen that can navigate back to the main menu.
|
||||||
|
*
|
||||||
|
* That prevents another player from pressing the
|
||||||
|
* Back / Crumb Saucer button on somebody else's
|
||||||
|
* public interaction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getCrumbSaucerSessionOwner(
|
||||||
|
interaction
|
||||||
|
) {
|
||||||
|
const footer =
|
||||||
|
interaction.message
|
||||||
|
?.embeds?.[0]
|
||||||
|
?.footer
|
||||||
|
?.text;
|
||||||
|
|
||||||
|
|
||||||
|
const parts =
|
||||||
|
footer?.split(":")
|
||||||
|
??
|
||||||
|
[];
|
||||||
|
|
||||||
|
|
||||||
|
switch (
|
||||||
|
parts[0]
|
||||||
|
) {
|
||||||
|
/*
|
||||||
|
* Main menu
|
||||||
|
*/
|
||||||
|
case "crumbSaucer":
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slots wager menu
|
||||||
|
*/
|
||||||
|
case "crumbSaucerSlots":
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slots completed result
|
||||||
|
*/
|
||||||
|
case "crumbSaucerSlotsResult":
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Blackjack wager/result menu
|
||||||
|
*/
|
||||||
|
case "crumbSaucerBlackjack":
|
||||||
|
|
||||||
|
case "crumbSaucerBlackjackResult":
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Roulette
|
||||||
|
*/
|
||||||
|
case "crumbRouletteMenu":
|
||||||
|
|
||||||
|
case "crumbRouletteBet":
|
||||||
|
|
||||||
|
case "crumbRouletteResult":
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Heist
|
||||||
|
*/
|
||||||
|
case "crumbSaucerHeist":
|
||||||
|
|
||||||
|
case "cookieHeist":
|
||||||
|
|
||||||
|
return parts[1];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Active Blackjack footer:
|
||||||
|
*
|
||||||
|
* crumbBlackjack:<gameId>:<userId>
|
||||||
|
*/
|
||||||
|
|
||||||
|
case "crumbBlackjack":
|
||||||
|
|
||||||
|
return parts[2];
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* SLOT OWNER RESOLUTION
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function getMenuOwner(
|
function getSlotsSessionOwner(
|
||||||
interaction
|
interaction
|
||||||
) {
|
) {
|
||||||
const footer =
|
const footer =
|
||||||
interaction.message
|
interaction.message
|
||||||
.embeds[0]
|
?.embeds?.[0]
|
||||||
?.footer
|
?.footer
|
||||||
?.text;
|
?.text;
|
||||||
|
|
||||||
|
|
||||||
const [
|
const parts =
|
||||||
type,
|
footer?.split(":")
|
||||||
userId
|
|
||||||
] =
|
|
||||||
footer
|
|
||||||
?.split(":")
|
|
||||||
??
|
??
|
||||||
[];
|
[];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main Crumb Saucer.
|
||||||
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
type !==
|
parts[0] ===
|
||||||
"crumbSaucer"
|
"crumbSaucer"
|
||||||
) {
|
) {
|
||||||
return null;
|
return parts[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return userId;
|
/*
|
||||||
}
|
* Slots wager menu.
|
||||||
|
*/
|
||||||
|
|
||||||
function getSlotsOwner(
|
|
||||||
interaction
|
|
||||||
) {
|
|
||||||
const footer =
|
|
||||||
interaction.message
|
|
||||||
.embeds[0]
|
|
||||||
?.footer
|
|
||||||
?.text;
|
|
||||||
|
|
||||||
|
|
||||||
const [
|
|
||||||
type,
|
|
||||||
userId
|
|
||||||
] =
|
|
||||||
footer
|
|
||||||
?.split(":")
|
|
||||||
??
|
|
||||||
[];
|
|
||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
type !==
|
parts[0] ===
|
||||||
"crumbSaucerSlots"
|
"crumbSaucerSlots"
|
||||||
) {
|
) {
|
||||||
return null;
|
return parts[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return userId;
|
/*
|
||||||
|
* Completed Slots result.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (
|
||||||
|
parts[0] ===
|
||||||
|
"crumbSaucerSlotsResult"
|
||||||
|
) {
|
||||||
|
return parts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function sleep(ms) {
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* SLEEP
|
||||||
|
* ============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
function sleep(
|
||||||
|
ms
|
||||||
|
) {
|
||||||
return new Promise(
|
return new Promise(
|
||||||
resolve =>
|
resolve =>
|
||||||
setTimeout(
|
setTimeout(
|
||||||
@@ -1238,8 +1458,16 @@ function sleep(ms) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ============================================================
|
||||||
|
* EXPORTS
|
||||||
|
* ============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
showCrumbSaucer,
|
showCrumbSaucer,
|
||||||
|
|
||||||
showSlots,
|
showSlots,
|
||||||
playSlots
|
playSlots,
|
||||||
|
runSlotsBack
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user