refactored and moved

This commit is contained in:
DeSqBlocki
2026-08-18 20:07:41 +02:00
parent b9a887259a
commit 0f48f09bd9
34 changed files with 3218 additions and 2943 deletions
File diff suppressed because it is too large Load Diff
+417
View File
@@ -0,0 +1,417 @@
const {
SlashCommandBuilder,
EmbedBuilder,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
MessageFlags
} = require("discord.js");
const {
randomUUID
} = require("node:crypto");
const {
getCollections,
getCookieBalance,
transferCookies,
getUnixTime
} = require("../../utils/cookieEconomy");
const SPAWN_COST =
500;
const JOIN_DURATION =
30 * 60;
const MINIMUM_PLAYERS =
5;
module.exports = {
data: new SlashCommandBuilder()
.setName("crumblestrike")
.setDescription(
"Cooperative Cookie boss encounters."
)
.addSubcommand(subcommand =>
subcommand
.setName("spawn")
.setDescription(
`Summon the Crumbbound Behemoth for ${SPAWN_COST} Cookies.`
)
),
async execute(interaction) {
switch (
interaction.options.getSubcommand()
) {
case "spawn":
return spawnCrumbleStrike(
interaction
);
default:
return interaction.reply({
content:
"Unknown Crumble Strike command.",
flags:
MessageFlags.Ephemeral
});
}
}
};
async function spawnCrumbleStrike(
interaction
) {
if (!interaction.guild) {
return interaction.reply({
content:
"Crumble Strike can only be started inside a server.",
flags:
MessageFlags.Ephemeral
});
}
const {
db
} =
getCollections();
const events =
db.collection(
"items_events"
);
const existing =
await events.findOne({
eventType:
"CrumbleStrike",
guildId:
interaction.guildId,
state: {
$in: [
"Joining",
"Starting",
"Active",
"Resolving"
]
}
});
if (existing) {
return interaction.reply({
content:
"There is already an active Crumble Strike encounter in this server.",
flags:
MessageFlags.Ephemeral
});
}
const balance =
await getCookieBalance(
interaction.user.id
);
if (
balance <
SPAWN_COST
) {
return interaction.reply({
content:
`You need **${SPAWN_COST.toLocaleString()} Cookies** to summon the boss.`,
flags:
MessageFlags.Ephemeral
});
}
const eventId =
randomUUID();
const escrowId =
`crumblestrike:${eventId}`;
const now =
getUnixTime();
const joinUntil =
now +
JOIN_DURATION;
try {
await transferCookies(
interaction.user.id,
escrowId,
SPAWN_COST
);
} catch (error) {
if (
error.message ===
"INSUFFICIENT_COOKIES"
) {
return interaction.reply({
content:
"Your Cookie balance changed before the boss could be summoned.",
flags:
MessageFlags.Ephemeral
});
}
throw error;
}
const embed =
new EmbedBuilder()
.setTitle(
"🍪 Crumble Strike"
)
.setDescription(
[
"## The Crumbbound Behemoth",
"",
"*Drawn by the scent of an irresponsibly large Cookie Vault,*",
"*the beast has lumbered into Shaiwase.*",
"",
`**Summoner:** ${interaction.user}`,
`**Recruitment ends:** <t:${joinUntil}:R>`,
`**Minimum adventurers:** ${MINIMUM_PLAYERS}`,
`**Participants:** 0/${MINIMUM_PLAYERS}`,
`**Reward Pool:** ${SPAWN_COST.toLocaleString()} 🍪`,
"",
"Choose your role below to begin preparing for battle.",
"",
"⚔️ **DPS** — Specializes in offensive actions.",
"🛡️ **Tank** — Specializes in mitigating boss attacks.",
"❤️ **Healer** — Specializes in restoring party HP.",
"",
"Once enough players have joined, the summoner may start the battle early."
].join("\n")
)
.setFooter({
text:
`crumbleStrike:${eventId}`
});
const roles =
new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId(
"crumbleStrikeRoleDPS"
)
.setLabel(
"DPS"
)
.setEmoji(
"⚔️"
)
.setStyle(
ButtonStyle.Danger
),
new ButtonBuilder()
.setCustomId(
"crumbleStrikeRoleTank"
)
.setLabel(
"Tank"
)
.setEmoji(
"🛡️"
)
.setStyle(
ButtonStyle.Primary
),
new ButtonBuilder()
.setCustomId(
"crumbleStrikeRoleHealer"
)
.setLabel(
"Healer"
)
.setEmoji(
"❤️"
)
.setStyle(
ButtonStyle.Success
)
);
const start =
new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId(
"crumbleStrikeStart"
)
.setLabel(
"Start Battle"
)
.setEmoji(
"⚔️"
)
.setStyle(
ButtonStyle.Secondary
)
);
let message;
try {
message =
await interaction.reply({
embeds: [
embed
],
components: [
roles,
start
],
fetchReply:
true
});
} catch (error) {
await safeRefund(
escrowId,
interaction.user.id,
SPAWN_COST
);
throw error;
}
try {
await events.insertOne({
eventType:
"CrumbleStrike",
eventId,
escrowId,
guildId:
interaction.guildId,
channelId:
interaction.channelId,
messageId:
message.id,
creatorId:
interaction.user.id,
state:
"Joining",
createdAt:
now,
joinUntil,
battleStartedAt:
null,
battleEndsAt:
null,
minimumParticipants:
MINIMUM_PLAYERS,
rewardPool:
SPAWN_COST,
boss: {
bossId:
"crumbbound-behemoth",
name:
"The Crumbbound Behemoth",
health:
15000,
maxHealth:
15000,
limitGauge:
0,
actionGauge:
0
},
participants:
{}
});
} catch (error) {
try {
await message.delete();
} catch {}
await safeRefund(
escrowId,
interaction.user.id,
SPAWN_COST
);
throw error;
}
}
async function safeRefund(
from,
to,
amount
) {
try {
await transferCookies(
from,
to,
amount
);
} catch (error) {
console.error(
"CRITICAL: Crumble Strike refund failed:",
error
);
}
}