added achievements for new steal logic
This commit is contained in:
@@ -15,7 +15,9 @@ const {
|
||||
} = require("../../utils/cookieEconomy");
|
||||
|
||||
const {
|
||||
trackProfileEvent
|
||||
trackProfileEvent,
|
||||
getProfileCollections,
|
||||
getDefaultStats
|
||||
} = require("../../utils/profileSystem");
|
||||
|
||||
const {
|
||||
@@ -235,12 +237,8 @@ async function steal(interaction) {
|
||||
});
|
||||
}
|
||||
|
||||
const {
|
||||
cookies,
|
||||
statsProfile
|
||||
} = getCookieCommandCollections({
|
||||
requireStatsProfile: true
|
||||
});
|
||||
const { cookies } = getCookieCommandCollections();
|
||||
const { stats: statsProfile } = getProfileCollections();
|
||||
|
||||
const now = new Date();
|
||||
const stealWindowCutoff = new Date(
|
||||
@@ -398,6 +396,27 @@ async function steal(interaction) {
|
||||
)
|
||||
: null;
|
||||
|
||||
/*
|
||||
* Ensure the victim has a complete profile document before heat state is
|
||||
* written. This avoids creating a sparse stats_profiles document when a
|
||||
* player is targeted before any other profile event has initialized them.
|
||||
*/
|
||||
await statsProfile.updateOne(
|
||||
{
|
||||
userId: target.id,
|
||||
guildId: interaction.guildId
|
||||
},
|
||||
{
|
||||
$setOnInsert: getDefaultStats(
|
||||
target.id,
|
||||
interaction.guildId
|
||||
)
|
||||
},
|
||||
{
|
||||
upsert: true
|
||||
}
|
||||
);
|
||||
|
||||
/*
|
||||
* Rolling heat protection.
|
||||
*
|
||||
@@ -407,7 +426,8 @@ async function steal(interaction) {
|
||||
*/
|
||||
await statsProfile.updateOne(
|
||||
{
|
||||
userId: target.id
|
||||
userId: target.id,
|
||||
guildId: interaction.guildId
|
||||
},
|
||||
{
|
||||
$pull: {
|
||||
@@ -428,7 +448,8 @@ async function steal(interaction) {
|
||||
*/
|
||||
const heatUpdateResult = await statsProfile.findOneAndUpdate(
|
||||
{
|
||||
userId: target.id
|
||||
userId: target.id,
|
||||
guildId: interaction.guildId
|
||||
},
|
||||
{
|
||||
$push: {
|
||||
@@ -439,7 +460,6 @@ async function steal(interaction) {
|
||||
}
|
||||
},
|
||||
{
|
||||
upsert: true,
|
||||
returnDocument: "before"
|
||||
}
|
||||
);
|
||||
@@ -451,6 +471,30 @@ async function steal(interaction) {
|
||||
const activeAttempts =
|
||||
targetProfile?.stealProtection?.attempts ?? [];
|
||||
|
||||
const uniqueAttackers = new Set([
|
||||
...activeAttempts.map(
|
||||
attempt => attempt.userId
|
||||
),
|
||||
user.id
|
||||
]).size;
|
||||
|
||||
/*
|
||||
* Achievement/event tracking for the victim. The current attempt is
|
||||
* included, while repeated attempts by the same user only count once
|
||||
* toward the unique-attacker total.
|
||||
*/
|
||||
await trackProfileEvent(
|
||||
interaction,
|
||||
target.id,
|
||||
{
|
||||
type: "steal_targeted",
|
||||
attackerUserId: user.id,
|
||||
uniqueAttackers,
|
||||
attemptsInWindow: activeAttempts.length + 1,
|
||||
windowSeconds: heatWindowMs / 1000
|
||||
}
|
||||
);
|
||||
|
||||
const heat = activeAttempts.reduce(
|
||||
(total, attempt) => {
|
||||
const timestamp = new Date(
|
||||
@@ -1111,9 +1155,7 @@ async function leaderboard(interaction) {
|
||||
* collection names for the two collections used by this command.
|
||||
*/
|
||||
|
||||
function getCookieCommandCollections({
|
||||
requireStatsProfile = false
|
||||
} = {}) {
|
||||
function getCookieCommandCollections() {
|
||||
const collections = getCollections();
|
||||
const database =
|
||||
collections.db ??
|
||||
@@ -1125,28 +1167,13 @@ function getCookieCommandCollections({
|
||||
collections.items_cookies ??
|
||||
database?.collection?.("items_cookies");
|
||||
|
||||
const statsProfile =
|
||||
collections.statsProfile ??
|
||||
collections.statsProfiles ??
|
||||
collections.stats_profile ??
|
||||
database?.collection?.("stats_profile");
|
||||
|
||||
if (!cookies) {
|
||||
throw new Error(
|
||||
"getCollections() must expose the items_cookies collection as cookies/itemsCookies/items_cookies, or expose a db handle."
|
||||
);
|
||||
}
|
||||
|
||||
if (requireStatsProfile && !statsProfile) {
|
||||
throw new Error(
|
||||
"getCollections() must expose the stats_profile collection as statsProfile/statsProfiles/stats_profile, or expose a db handle."
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
cookies,
|
||||
statsProfile
|
||||
};
|
||||
return { cookies };
|
||||
}
|
||||
|
||||
|
||||
|
||||
+17
-2
@@ -636,7 +636,7 @@ function getDefaultStats(userId, guildId) {
|
||||
allInRunItBack: 0,
|
||||
bankruptcyCount: 0,
|
||||
bankruptcyRecoveryBest: 0,
|
||||
|
||||
maxUniqueStealAttackers: 0,
|
||||
etTuCrumb: 0,
|
||||
noHardFeelings: 0,
|
||||
cookieLaundering: 0
|
||||
@@ -846,7 +846,22 @@ async function trackProfileEvent(
|
||||
}
|
||||
);
|
||||
break;
|
||||
|
||||
case "steal_targeted":
|
||||
await stats.updateOne(
|
||||
{
|
||||
userId,
|
||||
guildId
|
||||
},
|
||||
{
|
||||
$max: {
|
||||
"special.maxUniqueStealAttackers":
|
||||
Number(
|
||||
event.uniqueAttackers ?? 0
|
||||
)
|
||||
}
|
||||
}
|
||||
);
|
||||
break;
|
||||
case "steal_success":
|
||||
await stats.updateOne(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user