new games snapshot

This commit is contained in:
DeSqBlocki
2026-08-18 18:57:24 +02:00
parent 8bdd6868e8
commit 24d5b395ca
16 changed files with 4989 additions and 735 deletions
+230
View File
@@ -0,0 +1,230 @@
const {
getCollections,
getUnixTime
} = require("../utils/cookieEconomy");
const {
activateBoss,
failBoss,
cancelBossAndRefund
} = require("../utils/cookieBoss");
/*
* How often we check persistent boss timers.
*
* Discord timestamps handle the visible countdown,
* so checking once per minute is plenty.
*/
const CHECK_INTERVAL = 60 * 1000;
/*
* Your index.js automatically loads every file
* inside /handlers and passes the Discord client:
*
* require(`./handlers/${handler}`)(client)
*/
module.exports = (client) => {
/*
* Run shortly after startup.
*
* This catches boss events whose timers expired
* while ShaiBot was offline/restarting.
*/
setTimeout(() => {
processBossEvents(client);
}, 5000);
/*
* Persistent boss event watcher.
*/
setInterval(() => {
processBossEvents(client);
}, CHECK_INTERVAL);
console.log(
"[CookieBoss] Boss event watcher initialized"
);
};
/*
* Check all currently pending Cookie Boss events.
*/
async function processBossEvents(client) {
try {
const {
db
} = getCollections();
const events =
db.collection(
"items_events"
);
const now =
getUnixTime();
/*
* ==========================================
* JOINING PHASE
* ==========================================
*
* Recruitment lasts for 30 minutes.
*
* If 5+ players joined:
* start the battle automatically.
*
* If fewer than 5 joined:
* cancel the boss and refund everyone.
*/
const joiningEvents =
await events
.find({
eventType:
"CookieBoss",
state:
"Joining",
joinUntil: {
$lte: now
}
})
.toArray();
for (
const event
of joiningEvents
) {
const participantCount =
Object.keys(
event.participants ?? {}
).length;
console.log(
`[CookieBoss] Recruitment expired for ${event.eventId} ` +
`(${participantCount}/${event.minimumParticipants} players)`
);
/*
* Enough players joined.
*
* Start the fight automatically.
*/
if (
participantCount >=
event.minimumParticipants
) {
const started =
await activateBoss(
client,
event.eventId
);
if (started) {
console.log(
`[CookieBoss] Battle ${event.eventId} started automatically`
);
}
continue;
}
/*
* Not enough players.
*
* Nobody actually entered combat,
* so refund all committed Cookies.
*/
await cancelBossAndRefund(
client,
event.eventId
);
console.log(
`[CookieBoss] Battle ${event.eventId} cancelled and refunded`
);
}
/*
* ==========================================
* ACTIVE BATTLES
* ==========================================
*
* If the battle timer expires while the
* boss still has HP remaining, the raid fails.
*
* All Cookies held in the encounter escrow
* are transferred to the ShaiBot vault.
*/
const activeEvents =
await events
.find({
eventType:
"CookieBoss",
state:
"Active",
battleEndsAt: {
$lte: now
},
"boss.health": {
$gt: 0
}
})
.toArray();
for (
const event
of activeEvents
) {
console.log(
`[CookieBoss] Battle ${event.eventId} expired ` +
`with ${event.boss.health}/${event.boss.maxHealth} HP remaining`
);
await failBoss(
client,
event.eventId
);
console.log(
`[CookieBoss] Battle ${event.eventId} failed`
);
}
} catch (error) {
/*
* Never let an exception kill the interval.
*
* The next watcher tick will simply try again.
*/
console.error(
"[CookieBoss] Boss watcher error:",
error
);
}
}