From ef00a343fbcb6e4a6c0dd16a2da08891d3caf4a5 Mon Sep 17 00:00:00 2001 From: Cody Date: Wed, 10 Jun 2026 23:40:32 -0600 Subject: [PATCH 1/4] feat(stats): add miscellaneous stats --- .../src/commands/arcade/modes/dropper.tsx | 4 +- .../src/commands/arcade/modes/galaxy-wars.tsx | 3 + .../src/commands/arcade/modes/zombies.tsx | 7 +- .../src/commands/bedwars/bedwars.profile.tsx | 8 +- .../copsandcrims/copsandcrims.profile.tsx | 4 +- .../src/commands/duels/duels.profile.tsx | 5 +- .../src/commands/general/general.profile.tsx | 10 ++ .../murdermystery/murdermystery.profile.tsx | 6 +- .../src/commands/parkour/parkour.profile.tsx | 4 +- .../src/commands/pit/pit.profile.tsx | 8 ++ .../src/commands/quake/quake.profile.tsx | 10 +- .../commands/rankings/rankings.command.tsx | 4 +- .../commands/rankings/rankings.profile.tsx | 5 + .../commands/tntgames/tntgames.profile.tsx | 9 +- .../commands/warlords/warlords.profile.tsx | 6 +- .../woolgames/capture-the-wool.table.tsx | 8 +- locales/en-US/default.json | 6 + .../src/player/gamemodes/arcade/mode.ts | 18 ++- .../src/player/gamemodes/bedwars/index.ts | 120 +++++++++++++++++- .../src/player/gamemodes/duels/mode.ts | 4 +- .../src/player/gamemodes/general/index.ts | 6 + .../player/gamemodes/murdermystery/mode.ts | 6 +- .../src/player/gamemodes/parkour/index.ts | 3 +- .../schemas/src/player/gamemodes/pit/index.ts | 18 +++ .../schemas/src/player/gamemodes/pit/util.ts | 13 ++ .../src/player/gamemodes/quake/mode.ts | 10 +- .../src/player/gamemodes/tntgames/index.ts | 6 +- .../src/player/gamemodes/tntgames/mode.ts | 7 +- .../gamemodes/woolgames/capture-the-wool.ts | 8 +- packages/schemas/src/player/stats.ts | 52 ++++++++ 30 files changed, 336 insertions(+), 42 deletions(-) diff --git a/apps/discord-bot/src/commands/arcade/modes/dropper.tsx b/apps/discord-bot/src/commands/arcade/modes/dropper.tsx index 4e06ca84b..3aa32ecfd 100644 --- a/apps/discord-bot/src/commands/arcade/modes/dropper.tsx +++ b/apps/discord-bot/src/commands/arcade/modes/dropper.tsx @@ -12,6 +12,8 @@ import { arrayGroup, formatRaceTime, formatTime } from "@statsify/util"; import type { LocalizeFunction } from "@statsify/discord"; import type { ProfileTime } from "#commands/base.hypixel-command"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + interface DropperTableProps { stats: Dropper; submode: SubModeForMode; @@ -34,7 +36,7 @@ export const DropperTable = ({ stats, submode, t, time }: DropperTableProps) => 0}> - + diff --git a/apps/discord-bot/src/commands/arcade/modes/galaxy-wars.tsx b/apps/discord-bot/src/commands/arcade/modes/galaxy-wars.tsx index 0ae58b7fd..d6fb3bd6c 100644 --- a/apps/discord-bot/src/commands/arcade/modes/galaxy-wars.tsx +++ b/apps/discord-bot/src/commands/arcade/modes/galaxy-wars.tsx @@ -27,5 +27,8 @@ export const GalaxyWarsTable = ({ stats, t }: GalaxyWarsTableProps) => ( + + + ); diff --git a/apps/discord-bot/src/commands/arcade/modes/zombies.tsx b/apps/discord-bot/src/commands/arcade/modes/zombies.tsx index 78dc6a714..0a3dcc8e1 100644 --- a/apps/discord-bot/src/commands/arcade/modes/zombies.tsx +++ b/apps/discord-bot/src/commands/arcade/modes/zombies.tsx @@ -21,12 +21,13 @@ interface ZombiesMapColumnProps { const ZombiesMapColumn = ({ title, stats, t, time }: ZombiesMapColumnProps) => { const mapStat = stats.wins >= 1 ? - [t("stats.fastestWin"), stats.fastestWin ? formatTime(stats.fastestWin) : "N/A"] : + [t("stats.fastestWin"), stats.fastestWin ? formatTime(stats.fastestWin, { entries: 3 }) : "N/A"] : [t("stats.bestRound"), t(stats.bestRound)]; return ( + @@ -50,6 +51,8 @@ export const ZombiesTable = ({ stats, t, time }: ZombiesTableProps) => { + + @@ -89,7 +92,7 @@ export const ZombiesMapDifficultyTable = ({ stats, t, time }: ZombiesMapDifficul - + diff --git a/apps/discord-bot/src/commands/bedwars/bedwars.profile.tsx b/apps/discord-bot/src/commands/bedwars/bedwars.profile.tsx index e680c86bc..4f8909814 100644 --- a/apps/discord-bot/src/commands/bedwars/bedwars.profile.tsx +++ b/apps/discord-bot/src/commands/bedwars/bedwars.profile.tsx @@ -34,7 +34,11 @@ export const BedWarsProfile = ({ time, }: BedWarsProfileProps) => { const { bedwars } = player.stats; - const stats = bedwars[mode.api]; + const modeKey = mode.submode?.api ?? mode.api; + const formattedMode = mode.submode?.api === mode.api || !mode.submode ? + mode.formatted : + `${mode.formatted} ${mode.submode.formatted}`; + const stats = bedwars[modeKey]; const sidebar: SidebarItem[] = [ [t("stats.tokens"), t(bedwars.tokens), "§2"], @@ -64,7 +68,7 @@ export const BedWarsProfile = ({ name={player.prefixName} badge={badge} sidebar={sidebar} - title={`§l${FormattedGame.BEDWARS} §fStats §r(${mode.formatted})`} + title={`§l${FormattedGame.BEDWARS} §fStats §r(${formattedMode})`} description={`§7${t("stats.level")}: ${ bedwars.levelFormatted }\n${formatProgression({ diff --git a/apps/discord-bot/src/commands/copsandcrims/copsandcrims.profile.tsx b/apps/discord-bot/src/commands/copsandcrims/copsandcrims.profile.tsx index 2dc1e0cf7..0f78882ab 100644 --- a/apps/discord-bot/src/commands/copsandcrims/copsandcrims.profile.tsx +++ b/apps/discord-bot/src/commands/copsandcrims/copsandcrims.profile.tsx @@ -11,6 +11,8 @@ import { CopsAndCrimsModes, FormattedGame, type GameMode } from "@statsify/schem import { formatTime } from "@statsify/util"; import type { BaseProfileProps } from "#commands/base.hypixel-command"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + export interface CopsAndCrimsProfileProps extends BaseProfileProps { mode: GameMode; } @@ -106,7 +108,7 @@ export const CopsAndCrimsProfile = ({ diff --git a/apps/discord-bot/src/commands/duels/duels.profile.tsx b/apps/discord-bot/src/commands/duels/duels.profile.tsx index d45cfdd5a..d6f2cedc3 100644 --- a/apps/discord-bot/src/commands/duels/duels.profile.tsx +++ b/apps/discord-bot/src/commands/duels/duels.profile.tsx @@ -19,6 +19,8 @@ import { formatTime, prettify } from "@statsify/util"; import type { BaseProfileProps, ProfileTime } from "#commands/base.hypixel-command"; import type { DuelsModeIcons } from "./duels.command.js"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + export type DuelsProfileProps = Omit & { mode: GameMode; time: T; @@ -42,6 +44,7 @@ export const DuelsProfile = ({ const sidebar: SidebarItem[] = [ [t("stats.tokens"), t(duels.tokens), "§2"], [t("stats.pingRange"), `${t(duels.pingRange)}ms`, "§a"], + [t("stats.gamesPlayed"), t(duels.overall.wins + duels.overall.losses), "§e"], [t("stats.blocksPlaced"), t(duels.overall.blocksPlaced), "§9"], ]; @@ -61,7 +64,7 @@ export const DuelsProfile = ({ if (mode.api === "parkour") { sidebar.push( - [t("stats.bestTime"), duels.parkour.bestTime === 0 ? "N/A" : formatTime(duels.parkour.bestTime), "§d"], + [t("stats.bestTime"), duels.parkour.bestTime === 0 ? "N/A" : formatTimeWithSeconds(duels.parkour.bestTime), "§d"], [t("stats.checkpoints"), t(duels.parkour.checkpoints), "§5"] ); } diff --git a/apps/discord-bot/src/commands/general/general.profile.tsx b/apps/discord-bot/src/commands/general/general.profile.tsx index 60361afd2..338d420a4 100644 --- a/apps/discord-bot/src/commands/general/general.profile.tsx +++ b/apps/discord-bot/src/commands/general/general.profile.tsx @@ -111,6 +111,16 @@ export const GeneralProfile = ({ value={t(challenges.total)} color="§a" /> + + diff --git a/apps/discord-bot/src/commands/murdermystery/murdermystery.profile.tsx b/apps/discord-bot/src/commands/murdermystery/murdermystery.profile.tsx index 4251fa621..91cff1f5b 100644 --- a/apps/discord-bot/src/commands/murdermystery/murdermystery.profile.tsx +++ b/apps/discord-bot/src/commands/murdermystery/murdermystery.profile.tsx @@ -22,6 +22,8 @@ import { import { formatTime } from "@statsify/util"; import type { BaseProfileProps } from "#commands/base.hypixel-command"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + export interface MurderMysteryProfileProps extends BaseProfileProps { mode: GameMode; } @@ -199,7 +201,7 @@ export const MurderMysteryProfile = ({ title={t("stats.fastestMurdererWin")} value={ stats.fastestMurdererWin ? - formatTime(stats.fastestMurdererWin) : + formatTimeWithSeconds(stats.fastestMurdererWin) : "N/A" } color="§c" @@ -208,7 +210,7 @@ export const MurderMysteryProfile = ({ title={t("stats.fastestDetectiveWin")} value={ stats.fastestDetectiveWin ? - formatTime(stats.fastestDetectiveWin) : + formatTimeWithSeconds(stats.fastestDetectiveWin) : "N/A" } color="§b" diff --git a/apps/discord-bot/src/commands/parkour/parkour.profile.tsx b/apps/discord-bot/src/commands/parkour/parkour.profile.tsx index b5c9d185a..9d0bd739e 100644 --- a/apps/discord-bot/src/commands/parkour/parkour.profile.tsx +++ b/apps/discord-bot/src/commands/parkour/parkour.profile.tsx @@ -12,6 +12,8 @@ import { formatTime } from "@statsify/util"; import type { BaseProfileProps } from "#commands/base.hypixel-command"; import type { Image } from "skia-canvas"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + interface ParkourProfileProps extends BaseProfileProps { gameIcons: Record; } @@ -29,7 +31,7 @@ export const ParkourProfile = ({ const times: [GameId, any][] = Object.entries(parkour) .sort((a, b) => (a[1] || Number.MAX_VALUE) - (b[1] || Number.MAX_VALUE)) - .map(([field, time]) => [field as GameId, time ? formatTime(time) : "N/A"]); + .map(([field, time]) => [field as GameId, time ? formatTimeWithSeconds(time) : "N/A"]); return ( diff --git a/apps/discord-bot/src/commands/pit/pit.profile.tsx b/apps/discord-bot/src/commands/pit/pit.profile.tsx index 76d5a5d9a..d243ddfb6 100644 --- a/apps/discord-bot/src/commands/pit/pit.profile.tsx +++ b/apps/discord-bot/src/commands/pit/pit.profile.tsx @@ -33,6 +33,7 @@ export const PitProfile = ({ const sidebar: SidebarItem[] = [ [t("stats.gold"), t(pit.gold), "§6"], + [t("stats.totalExp"), t(pit.exp), "§b"], [t("stats.contracts"), t(pit.contractsCompleted), "§a"], [t("stats.renown"), t(pit.renown), "§e"], [t("stats.lifetimeRenown"), t(pit.lifetimeRenown), "§b"], @@ -54,6 +55,13 @@ export const PitProfile = ({ currentLevel: pit.levelFormatted, nextLevel: pit.nextLevelFormatted, showLevel: true, + })}\n${formatProgression({ + t, + label: t("stats.progression.gold"), + progression: pit.goldProgression, + currentLevel: pit.levelFormatted, + nextLevel: pit.nextLevelFormatted, + showLevel: false, })}`} sidebar={sidebar} badge={badge} diff --git a/apps/discord-bot/src/commands/quake/quake.profile.tsx b/apps/discord-bot/src/commands/quake/quake.profile.tsx index b47eca731..e903caf72 100644 --- a/apps/discord-bot/src/commands/quake/quake.profile.tsx +++ b/apps/discord-bot/src/commands/quake/quake.profile.tsx @@ -41,6 +41,7 @@ export const QuakeProfile = ({ [t("stats.godlikes"), t(quake.godlikes), "§3"], [t("stats.trigger"), `${quake.trigger}s`, "§b"], [t("stats.highestKillstreak"), t(quake.highestKillstreak), "§4"], + [t("stats.blocksTravelled"), t(quake[mode.api].blocksTravelled), "§b"], ]; return ( @@ -78,10 +79,17 @@ export const QuakeProfile = ({ value={t(stats.shotsFired)} color="§a" /> - + + + + diff --git a/apps/discord-bot/src/commands/rankings/rankings.command.tsx b/apps/discord-bot/src/commands/rankings/rankings.command.tsx index 15966236e..2bfdfa04d 100644 --- a/apps/discord-bot/src/commands/rankings/rankings.command.tsx +++ b/apps/discord-bot/src/commands/rankings/rankings.command.tsx @@ -347,7 +347,7 @@ export class RankingsCommand { return scrollingPagination( context, groups.map( - (group) => () => + (group, page) => () => render( , getTheme(user) ) diff --git a/apps/discord-bot/src/commands/rankings/rankings.profile.tsx b/apps/discord-bot/src/commands/rankings/rankings.profile.tsx index 26d4b7941..bdb9c314c 100644 --- a/apps/discord-bot/src/commands/rankings/rankings.profile.tsx +++ b/apps/discord-bot/src/commands/rankings/rankings.profile.tsx @@ -44,6 +44,8 @@ const formatStat = (stat: PostLeaderboardRankingsResponse, game?: string) => { export interface RankingsProfileProps extends Omit { data: PostLeaderboardRankingsResponse[]; game?: string; + page: number; + pageCount: number; } export const RankingsProfile = ({ @@ -56,6 +58,8 @@ export const RankingsProfile = ({ skin, game, badge, + page, + pageCount, }: RankingsProfileProps) => { const listTitles = ["Statistic", "Pos", "Value"]; if (!game) listTitles.unshift("Game"); @@ -102,6 +106,7 @@ export const RankingsProfile = ({ skin={skin} time="LIVE" title={`§l§bLeaderboard Positions §r(§l${formattedGame}§r)`} + description={`§7Page ${t(page + 1)} / ${t(pageCount)}`} badge={badge} /> {titles}, ...items]} /> diff --git a/apps/discord-bot/src/commands/tntgames/tntgames.profile.tsx b/apps/discord-bot/src/commands/tntgames/tntgames.profile.tsx index 7e1f9d466..e998f1005 100644 --- a/apps/discord-bot/src/commands/tntgames/tntgames.profile.tsx +++ b/apps/discord-bot/src/commands/tntgames/tntgames.profile.tsx @@ -11,6 +11,8 @@ import { FormattedGame, type GameMode, type TNTGamesModes } from "@statsify/sche import { formatTime, prettify } from "@statsify/util"; import type { BaseProfileProps } from "#commands/base.hypixel-command"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + export interface TNTGamesProfileProps extends BaseProfileProps { mode: GameMode; } @@ -31,6 +33,7 @@ export const TNTGamesProfile = ({ const sidebar: SidebarItem[] = [ [t("stats.coins"), t(tntgames.coins), "§6"], [t("stats.overallWins"), t(tntgames.wins), "§e"], + [t("stats.playtime"), formatTime(tntgames.playtime), "§a"], ]; let table; @@ -47,7 +50,7 @@ export const TNTGamesProfile = ({ [ [t("stats.wins"), t(tntgames.tntRun.wins)], [t("stats.wlr"), t(tntgames.tntRun.wlr)], - [t("stats.bestTime"), formatTime(tntgames.tntRun.record)], + [t("stats.bestTime"), formatTimeWithSeconds(tntgames.tntRun.record)], ] : [ [t("stats.wins"), t(tntgames.tntRun.wins)], @@ -104,7 +107,7 @@ export const TNTGamesProfile = ({ - + @@ -124,7 +127,7 @@ export const TNTGamesProfile = ({ - + diff --git a/apps/discord-bot/src/commands/warlords/warlords.profile.tsx b/apps/discord-bot/src/commands/warlords/warlords.profile.tsx index 82d410c24..4561f703c 100644 --- a/apps/discord-bot/src/commands/warlords/warlords.profile.tsx +++ b/apps/discord-bot/src/commands/warlords/warlords.profile.tsx @@ -42,7 +42,11 @@ export const WarlordsProfile = ({ sidebar.push([t("stats.class"), prettify(warlords.class), "§e"]); const clazz = warlords.class as "mage" | "warrior" | "paladin" | "shaman"; // Verify that the cast is correct and the class is a valid class - if (clazz in warlords && typeof warlords[clazz] === "object") sidebar.push([t("stats.spec"), prettify(warlords[clazz].specification), "§a"]); + if (clazz in warlords && typeof warlords[clazz] === "object") + sidebar.push( + [t("stats.spec"), prettify(warlords[clazz].specification), "§a"], + [t("stats.level"), t(warlords[clazz].level), "§a"] + ); } let table: JSX.Element; diff --git a/apps/discord-bot/src/commands/woolgames/capture-the-wool.table.tsx b/apps/discord-bot/src/commands/woolgames/capture-the-wool.table.tsx index 3514b8815..4fd0ac318 100644 --- a/apps/discord-bot/src/commands/woolgames/capture-the-wool.table.tsx +++ b/apps/discord-bot/src/commands/woolgames/capture-the-wool.table.tsx @@ -12,6 +12,8 @@ import type { CaptureTheWool } from "@statsify/schemas"; import type { LocalizeFunction } from "@statsify/discord"; import type { ProfileTime } from "#commands/base.hypixel-command"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + interface CaptureTheWoolTableProps { captureTheWool: CaptureTheWool; t: LocalizeFunction; @@ -54,21 +56,21 @@ export const CaptureTheWoolTable = ({ captureTheWool, t, time }: CaptureTheWoolT 0}> 0}> 0}> diff --git a/locales/en-US/default.json b/locales/en-US/default.json index b66f3e884..ca7a7b4ee 100644 --- a/locales/en-US/default.json +++ b/locales/en-US/default.json @@ -576,6 +576,7 @@ "blocksBroken": "Blocks Broken", "blocksPlaced": "Blocks Placed", "blocksRan": "Blocks Ran", + "blocksTravelled": "Blocks Travelled", "bombsDefused": "Bombs Defused", "bombsPlanted": "Bombs Planted", "bounty": "Bounty", @@ -629,6 +630,7 @@ "goldEarned": "Gold Earned", "goldPickedUp": "Gold Picked Up", "goldRate": "Gold Rate", + "goldRequirement": "Gold Requirement", "goldSpent": "Gold Spent", "goldTrophies": "Gold Trophies", "grandPrixTokens": "GP Tokens", @@ -728,10 +730,12 @@ "powerupActivations": "Power-Up Activations", "powerups": "Power-Ups", "prefix": "Prefix", + "prestigeGold": "Prestige Gold", "prevent": "Prevent", "progression": { "exp": "EXP Progress", "gexp": "GEXP Progress", + "gold": "Gold Progress", "goldTrophy": "Gold Trophy Progress", "kill": "Kill Progress", "score": "Score Progress", @@ -769,7 +773,9 @@ "title": "Title", "tokens": "Tokens", "total": "Total", + "totalKills": "Total Kills", "totalSlumberTickets": "Total Slumber Tickets", + "totalWins": "Total Wins", "totalTrophies": "Total Trophies", "trail": "Trail", "transfusion": "Transfusion", diff --git a/packages/schemas/src/player/gamemodes/arcade/mode.ts b/packages/schemas/src/player/gamemodes/arcade/mode.ts index e2dd5a1a2..d1bac2a7f 100644 --- a/packages/schemas/src/player/gamemodes/arcade/mode.ts +++ b/packages/schemas/src/player/gamemodes/arcade/mode.ts @@ -16,6 +16,8 @@ import { import { Field } from "#metadata"; import { add, deepAdd, deepSub, ratio, sub } from "@statsify/math"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + export class BlockingDead { @Field() public wins: number; @@ -733,7 +735,7 @@ export class Dropper { @Field() public flawlessGames: number; - @Field({ leaderboard: { formatter: formatTime, sort: "ASC" } }) + @Field({ leaderboard: { formatter: formatTimeWithSeconds, sort: "ASC" } }) public bestTime: number; @Field({ leaderboard: { name: "Maps:" } }) @@ -863,6 +865,9 @@ export class GalaxyWars { @Field() public rebelKills: number; + @Field() + public shotsFired: number; + public constructor(data: APIData) { this.wins = data.sw_game_wins; this.kills = data.sw_kills; @@ -870,6 +875,7 @@ export class GalaxyWars { this.kdr = ratio(this.kills, this.deaths); this.empireKills = data.sw_empire_kills; this.rebelKills = data.sw_rebel_kills; + this.shotsFired = data.sw_shots_fired; } } @@ -1370,19 +1376,22 @@ export class ZombiesMapDifficulty { @Field({ leaderboard: { sort: "ASC", - formatter: formatTime, + formatter: formatTimeWithSeconds, additionalFields: ["this.wins"], }, historical: { enabled: false }, }) public fastestWin: number; - @Field({ leaderboard: { enabled: false } }) + @Field({ leaderboard: { additionalFields: ["this.deaths", "this.kdr"] } }) public kills: number; - @Field({ leaderboard: { enabled: false } }) + @Field({ leaderboard: { additionalFields: ["this.kills", "this.kdr"] } }) public deaths: number; + @Field({ leaderboard: { additionalFields: ["this.kills", "this.deaths"] } }) + public kdr: number; + @Field({ leaderboard: { enabled: false } }) public bestRound: number; @@ -1399,6 +1408,7 @@ export class ZombiesMapDifficulty { this.fastestWin = (data[`fastest_time_30_zombies${mode}`] ?? 0) * 1000; this.kills = data[`zombie_kills_zombies${mode}`]; this.deaths = data[`deaths_zombies${mode}`]; + this.kdr = ratio(this.kills, this.deaths); this.bestRound = data[`best_round_zombies${mode}`]; this.doorsOpened = data[`doors_opened_zombies${mode}`]; this.totalRounds = data[`total_rounds_survived_zombies${mode}`]; diff --git a/packages/schemas/src/player/gamemodes/bedwars/index.ts b/packages/schemas/src/player/gamemodes/bedwars/index.ts index 69aa8947c..13d8c97d6 100644 --- a/packages/schemas/src/player/gamemodes/bedwars/index.ts +++ b/packages/schemas/src/player/gamemodes/bedwars/index.ts @@ -37,14 +37,63 @@ export const BEDWARS_MODES = new GameModes([ { api: "threes", hypixel: "BEDWARS_FOUR_THREE" }, { api: "fours", hypixel: "BEDWARS_FOUR_FOUR" }, { api: "4v4", hypixel: "BEDWARS_TWO_FOUR" }, - { api: "armed" }, + { + api: "armed", + submodes: [ + { api: "armed", formatted: "Overall" }, + { api: "armedDoubles", formatted: "Doubles" }, + { api: "armedFours", formatted: "Fours" }, + ], + }, { api: "castle", hypixel: "BEDWARS_CASTLE" }, - { api: "lucky" }, - { api: "rush" }, - { api: "swap" }, - { api: "ultimate" }, - { api: "underworld" }, - { api: "voidless" }, + { + api: "lucky", + submodes: [ + { api: "lucky", formatted: "Overall" }, + { api: "luckyDoubles", formatted: "Doubles" }, + { api: "luckyFours", formatted: "Fours" }, + ], + }, + { + api: "rush", + submodes: [ + { api: "rush", formatted: "Overall" }, + { api: "rushDoubles", formatted: "Doubles" }, + { api: "rushFours", formatted: "Fours" }, + ], + }, + { + api: "swap", + submodes: [ + { api: "swap", formatted: "Overall" }, + { api: "swapDoubles", formatted: "Doubles" }, + { api: "swapFours", formatted: "Fours" }, + ], + }, + { + api: "ultimate", + submodes: [ + { api: "ultimate", formatted: "Overall" }, + { api: "ultimateDoubles", formatted: "Doubles" }, + { api: "ultimateFours", formatted: "Fours" }, + ], + }, + { + api: "underworld", + submodes: [ + { api: "underworld", formatted: "Overall" }, + { api: "underworldDoubles", formatted: "Doubles" }, + { api: "underworldFours", formatted: "Fours" }, + ], + }, + { + api: "voidless", + submodes: [ + { api: "voidless", formatted: "Overall" }, + { api: "voidlessDoubles", formatted: "Doubles" }, + { api: "voidlessFours", formatted: "Fours" }, + ], + }, { api: "oneBlock", hypixel: "BEDWARS_EIGHT_ONE_ONEBLOCK" }, { api: "challenges" }, @@ -167,6 +216,48 @@ export class BedWars { @Field() public oneBlock: BedWarsMode; + @Field() + public armedDoubles: BedWarsMode; + + @Field() + public armedFours: BedWarsMode; + + @Field() + public luckyDoubles: BedWarsMode; + + @Field() + public luckyFours: BedWarsMode; + + @Field() + public rushDoubles: BedWarsMode; + + @Field() + public rushFours: BedWarsMode; + + @Field() + public swapDoubles: BedWarsMode; + + @Field() + public swapFours: BedWarsMode; + + @Field() + public ultimateDoubles: BedWarsMode; + + @Field() + public ultimateFours: BedWarsMode; + + @Field() + public underworldDoubles: BedWarsMode; + + @Field() + public underworldFours: BedWarsMode; + + @Field() + public voidlessDoubles: BedWarsMode; + + @Field() + public voidlessFours: BedWarsMode; + @Field() public challenges: BedWarsModeChallenges; @@ -250,6 +341,21 @@ export class BedWars { this.voidless = DreamsBedWarsMode.new(data, "voidless"); this.oneBlock = new BedWarsMode(data, "eight_one_oneblock"); + this.armedDoubles = new BedWarsMode(data, "eight_two_armed"); + this.armedFours = new BedWarsMode(data, "four_four_armed"); + this.luckyDoubles = new BedWarsMode(data, "eight_two_lucky"); + this.luckyFours = new BedWarsMode(data, "four_four_lucky"); + this.rushDoubles = new BedWarsMode(data, "eight_two_rush"); + this.rushFours = new BedWarsMode(data, "four_four_rush"); + this.swapDoubles = new BedWarsMode(data, "eight_two_swap"); + this.swapFours = new BedWarsMode(data, "four_four_swap"); + this.ultimateDoubles = new BedWarsMode(data, "eight_two_ultimate"); + this.ultimateFours = new BedWarsMode(data, "four_four_ultimate"); + this.underworldDoubles = new BedWarsMode(data, "eight_two_underworld"); + this.underworldFours = new BedWarsMode(data, "four_four_underworld"); + this.voidlessDoubles = new BedWarsMode(data, "eight_two_voidless"); + this.voidlessFours = new BedWarsMode(data, "four_four_voidless"); + this.core = deepSub(this.overall, this["4v4"]); BedWarsMode.applyRatios(this.core); diff --git a/packages/schemas/src/player/gamemodes/duels/mode.ts b/packages/schemas/src/player/gamemodes/duels/mode.ts index 9f218a630..bdda67cd6 100644 --- a/packages/schemas/src/player/gamemodes/duels/mode.ts +++ b/packages/schemas/src/player/gamemodes/duels/mode.ts @@ -12,6 +12,8 @@ import { Progression } from "#progression"; import { TitleRequirement, getTitleAndProgression } from "./util.js"; import { add, deepAdd, ratio } from "@statsify/math"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + export class BaseDuelsGameMode { @Field() public bestWinstreak: number; @@ -649,7 +651,7 @@ export class ParkourDuels extends SingleDuelsGameMode { @Field() public checkpoints: number; - @Field({ leaderboard: { formatter: formatTime, sort: "ASC" } }) + @Field({ leaderboard: { formatter: formatTimeWithSeconds, sort: "ASC" } }) public bestTime: number; public constructor(data: APIData) { diff --git a/packages/schemas/src/player/gamemodes/general/index.ts b/packages/schemas/src/player/gamemodes/general/index.ts index f3e6dd85e..e6920dd44 100644 --- a/packages/schemas/src/player/gamemodes/general/index.ts +++ b/packages/schemas/src/player/gamemodes/general/index.ts @@ -20,6 +20,12 @@ export class General { @Field() public achievementPoints: number; + @Field() + public totalWins: number; + + @Field() + public totalKills: number; + @Field() public giftsSent: number; diff --git a/packages/schemas/src/player/gamemodes/murdermystery/mode.ts b/packages/schemas/src/player/gamemodes/murdermystery/mode.ts index 3fe4ad413..a30e537b1 100644 --- a/packages/schemas/src/player/gamemodes/murdermystery/mode.ts +++ b/packages/schemas/src/player/gamemodes/murdermystery/mode.ts @@ -11,6 +11,8 @@ import { Field } from "#metadata"; import { Progression } from "#progression"; import { ratio } from "@statsify/math"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + export class BaseMurderMysteryMode { @Field() public wins: number; @@ -98,13 +100,13 @@ export class OverallMurderMysteryMode extends StandardMurderMysteryMode { export class ClassicMurderMysteryMode extends StandardMurderMysteryMode { @Field({ - leaderboard: { sort: "ASC", formatter: formatTime }, + leaderboard: { sort: "ASC", formatter: formatTimeWithSeconds }, historical: { enabled: false }, }) public fastestDetectiveWin: number; @Field({ - leaderboard: { sort: "ASC", formatter: formatTime }, + leaderboard: { sort: "ASC", formatter: formatTimeWithSeconds }, historical: { enabled: false }, }) public fastestMurdererWin: number; diff --git a/packages/schemas/src/player/gamemodes/parkour/index.ts b/packages/schemas/src/player/gamemodes/parkour/index.ts index 8936c32f9..ff57df798 100644 --- a/packages/schemas/src/player/gamemodes/parkour/index.ts +++ b/packages/schemas/src/player/gamemodes/parkour/index.ts @@ -14,7 +14,8 @@ export const PARKOUR_MODES = new GameModes([{ api: "overall" }] as const); export type ParkourModes = ExtractGameModes; -const fieldOptions = { sort: "ASC", formatter: formatTime, fieldName: "Time" }; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); +const fieldOptions = { sort: "ASC", formatter: formatTimeWithSeconds, fieldName: "Time" }; const historical = { enabled: false }; export class Parkour { diff --git a/packages/schemas/src/player/gamemodes/pit/index.ts b/packages/schemas/src/player/gamemodes/pit/index.ts index b647ec65c..2e19f934f 100644 --- a/packages/schemas/src/player/gamemodes/pit/index.ts +++ b/packages/schemas/src/player/gamemodes/pit/index.ts @@ -16,6 +16,7 @@ import { getLevel, getLevelFormatted, getPrestige, + getPrestigeGoldReq, getPrestigeReq, getRenownShopCost, } from "./util.js"; @@ -79,6 +80,15 @@ export class Pit { }) public goldEarned: number; + @Field({ leaderboard: { enabled: false }, historical: { enabled: false } }) + public prestigeGold: number; + + @Field({ leaderboard: { enabled: false }, historical: { enabled: false } }) + public goldRequirement: number; + + @Field({ leaderboard: { enabled: false }, historical: { enabled: false } }) + public goldProgression: Progression; + @Field({ historical: { enabled: false } }) public renown: number; @@ -162,11 +172,19 @@ export class Pit { this.trueLevel = prestige * 120 + level; const lastPrestigeReq = getPrestigeReq(prestige - 1); + const prestigeGoldReq = getPrestigeGoldReq(prestige); + + this.prestigeGold = profile[`cash_during_prestige_${prestige}`] ?? 0; + this.goldRequirement = prestigeGoldReq; this.progression = new Progression( this.exp - lastPrestigeReq, Math.min(getPrestigeReq(prestige) - lastPrestigeReq, 11_787_293_080) ); + this.goldProgression = new Progression( + this.prestigeGold, + Math.max(prestigeGoldReq, 0) + ); this.levelFormatted = getLevelFormatted(level, prestige); this.nextLevelFormatted = diff --git a/packages/schemas/src/player/gamemodes/pit/util.ts b/packages/schemas/src/player/gamemodes/pit/util.ts index e7f5dc1d8..b9d6e16c2 100644 --- a/packages/schemas/src/player/gamemodes/pit/util.ts +++ b/packages/schemas/src/player/gamemodes/pit/util.ts @@ -29,6 +29,16 @@ const PRESTIGE_XP_REQUIREMENTS = [ 11_787_293_080, ]; +const PRESTIGE_GOLD_REQUIREMENTS = [ + 10_000, 20_000, 20_000, 20_000, 30_000, 35_000, 40_000, 45_000, 50_000, + 60_000, 70_000, 80_000, 90_000, 100_000, 125_000, 150_000, 175_000, 200_000, + 250_000, 300_000, 350_000, 400_000, 500_000, 600_000, 700_000, 800_000, + 900_000, 1_000_000, 1_000_000, 1_000_000, 1_000_000, 1_000_000, 1_000_000, + 1_000_000, 1_000_000, 2_000_000, 2_000_000, 2_000_000, 2_000_000, 2_000_000, + 2_000_000, 2_000_000, 2_000_000, 2_000_000, 2_000_000, 2_000_000, 2_000_000, + 2_000_000, 2_000_000, 2_000_000, -1, +]; + const PRESTIGE_COLORS = [ "7", "9", @@ -82,6 +92,9 @@ export const getPrestige = (xp: number) => { export const getPrestigeReq = (prestige: number) => prestige > -1 ? PRESTIGE_XP_REQUIREMENTS[prestige] : 0; +export const getPrestigeGoldReq = (prestige: number) => + prestige > -1 ? PRESTIGE_GOLD_REQUIREMENTS[prestige] : 0; + export const getLevel = (pres: number, xp: number) => { let level = 120; if ( diff --git a/packages/schemas/src/player/gamemodes/quake/mode.ts b/packages/schemas/src/player/gamemodes/quake/mode.ts index f0bf2a5cd..44737571a 100644 --- a/packages/schemas/src/player/gamemodes/quake/mode.ts +++ b/packages/schemas/src/player/gamemodes/quake/mode.ts @@ -29,9 +29,12 @@ export class QuakeMode { @Field() public killstreaks: number; - @Field({ leaderboard: { enabled: false } }) + @Field() public shotsFired: number; + @Field({ leaderboard: { fieldName: "Blocks Travelled", name: "Blocks Travelled" } }) + public blocksTravelled: number; + @Field({ leaderboard: { fieldName: "2017+ Kills", name: "2017+ Kills" } }) public postUpdateKills: number; @@ -41,6 +44,9 @@ export class QuakeMode { @Field({ leaderboard: { enabled: false } }) public quakeShotAccuracy: number; + @Field({ leaderboard: { enabled: false } }) + public headshotAccuracy: number; + public constructor(data: APIData, mode: string) { mode = mode ? `_${mode}` : mode; @@ -50,6 +56,7 @@ export class QuakeMode { this.headshots = data[`headshots${mode}`]; this.killstreaks = data[`killstreaks${mode}`]; this.shotsFired = data[`shots_fired${mode}`]; + this.blocksTravelled = data[`distance_travelled${mode}`]; this.postUpdateKills = data[`kills_since_update_feb_2017${mode}`]; QuakeMode.applyRatios(this); } @@ -58,5 +65,6 @@ export class QuakeMode { data.kdr = ratio(data.kills, data.deaths); data.kwr = ratio(data.kills, data.wins); data.quakeShotAccuracy = ratio(data.postUpdateKills, data.shotsFired, 100); + data.headshotAccuracy = ratio(data.headshots, data.postUpdateKills, 100); } } diff --git a/packages/schemas/src/player/gamemodes/tntgames/index.ts b/packages/schemas/src/player/gamemodes/tntgames/index.ts index c8edc3e91..04f272373 100644 --- a/packages/schemas/src/player/gamemodes/tntgames/index.ts +++ b/packages/schemas/src/player/gamemodes/tntgames/index.ts @@ -6,10 +6,10 @@ * https://github.com/Statsify/statsify/blob/main/LICENSE */ +import { type APIData, formatTime } from "@statsify/util"; import { BowSpleef, PVPRun, TNTRun, TNTTag, Wizards } from "./mode.js"; import { type ExtractGameModes, GameModes } from "#game"; import { Field } from "#metadata"; -import type { APIData } from "@statsify/util"; export const TNT_GAMES_MODES = new GameModes([ { api: "overall" }, @@ -45,6 +45,9 @@ export class TNTGames { @Field() public wins: number; + @Field({ leaderboard: { formatter: formatTime }, historical: { enabled: false } }) + public playtime: number; + @Field({ leaderboard: { fieldName: "TNT Run", extraDisplay: "this.tntRun.naturalPrefix" }, }) @@ -65,6 +68,7 @@ export class TNTGames { public constructor(data: APIData, ap: APIData) { this.coins = data.coins; this.wins = data.wins; + this.playtime = (ap.tntgames_tnt_triathlon ?? 0) * 60_000; this.tntRun = new TNTRun(data, ap); this.pvpRun = new PVPRun(data); diff --git a/packages/schemas/src/player/gamemodes/tntgames/mode.ts b/packages/schemas/src/player/gamemodes/tntgames/mode.ts index abb824ba2..85782ce89 100644 --- a/packages/schemas/src/player/gamemodes/tntgames/mode.ts +++ b/packages/schemas/src/player/gamemodes/tntgames/mode.ts @@ -12,6 +12,8 @@ import { type GamePrefix, createPrefixProgression, cycleColors, defaultPrefix, g import { Progression } from "#progression"; import { ratio } from "@statsify/math"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + const tntgamesRainbow = (text: string) => cycleColors(text, ["c", "6", "e", "a", "b", "d", "5"]); // Prefixes for TNT Run, PVP Run and Bow Spleef @@ -95,7 +97,7 @@ export class PVPRun { @Field() public kdr: number; - @Field({ leaderboard: { formatter: formatTime }, historical: { enabled: false } }) + @Field({ leaderboard: { formatter: formatTimeWithSeconds }, historical: { enabled: false } }) public record: number; @Field() @@ -149,7 +151,7 @@ export class TNTRun { @Field() public wlr: number; - @Field({ leaderboard: { formatter: formatTime }, historical: { enabled: false } }) + @Field({ leaderboard: { formatter: formatTimeWithSeconds }, historical: { enabled: false } }) public record: number; @Field() @@ -413,4 +415,3 @@ export class Wizards { this.arcaneWizard = new WizardsClass(data, "arcane_wizard"); } } - diff --git a/packages/schemas/src/player/gamemodes/woolgames/capture-the-wool.ts b/packages/schemas/src/player/gamemodes/woolgames/capture-the-wool.ts index 477c45511..92cee381c 100644 --- a/packages/schemas/src/player/gamemodes/woolgames/capture-the-wool.ts +++ b/packages/schemas/src/player/gamemodes/woolgames/capture-the-wool.ts @@ -10,6 +10,8 @@ import { type APIData, formatTime } from "@statsify/util"; import { Field } from "#metadata"; import { ratio } from "@statsify/math"; +const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); + export class CaptureTheWool { @Field() public wins: number; @@ -44,7 +46,7 @@ export class CaptureTheWool { @Field({ leaderboard: { sort: "ASC", - formatter: formatTime, + formatter: formatTimeWithSeconds, additionalFields: ["this.wins"], }, historical: { enabled: false }, @@ -54,7 +56,7 @@ export class CaptureTheWool { @Field({ leaderboard: { sort: "ASC", - formatter: formatTime, + formatter: formatTimeWithSeconds, additionalFields: ["this.woolCaptured"], }, historical: { enabled: false }, @@ -62,7 +64,7 @@ export class CaptureTheWool { public fastestWoolCapture: number; @Field({ - leaderboard: { formatter: formatTime }, + leaderboard: { formatter: formatTimeWithSeconds }, historical: { enabled: false }, }) public longestGame: number; diff --git a/packages/schemas/src/player/stats.ts b/packages/schemas/src/player/stats.ts index 60fa3b0e6..b24b1821c 100644 --- a/packages/schemas/src/player/stats.ts +++ b/packages/schemas/src/player/stats.ts @@ -36,6 +36,7 @@ import { } from "./gamemodes/index.js"; import { Field } from "#metadata"; import { FormattedGame } from "#game"; +import { add } from "@statsify/math"; import type { APIData } from "@statsify/util"; export class PlayerStats { @@ -253,5 +254,56 @@ export class PlayerStats { this.walls = new Walls(stats.Walls ?? {}, legacy); this.warlords = new Warlords(stats.Battleground ?? {}); this.woolgames = new WoolGames(stats.WoolGames ?? {}, achievements); + + this.general.totalWins = add( + this.arcade.wins, + this.arenabrawl.overall.wins, + this.bedwars.overall.wins, + this.blitzsg.overall.wins, + this.buildbattle.overall.wins, + this.copsandcrims.overall.wins, + this.duels.overall.wins, + this.megawalls.overall.wins, + this.murdermystery.overall.wins, + this.paintball.wins, + this.quake.overall.wins, + this.skywars.overall.wins, + this.smashheroes.overall.wins, + this.speeduhc.overall.wins, + this.tntgames.wins, + this.uhc.overall.wins, + this.vampirez.overallWins, + this.walls.wins, + this.warlords.wins, + this.woolgames.wins + ); + + this.general.totalKills = add( + this.arenabrawl.overall.kills, + this.bedwars.overall.kills, + this.blitzsg.overall.kills, + this.copsandcrims.overall.kills, + this.duels.overall.kills, + this.megawalls.overall.kills, + this.murdermystery.overall.kills, + this.paintball.kills, + this.pit.kills, + this.quake.overall.kills, + this.skywars.overall.kills, + this.smashheroes.overall.kills, + this.speeduhc.overall.kills, + this.tntgames.pvpRun.kills, + this.tntgames.tntTag.kills, + this.tntgames.wizards.kills, + this.uhc.overall.kills, + this.vampirez.human.kills, + this.vampirez.vampire.kills, + this.vampirez.zombieKills, + this.walls.kills, + this.warlords.kills, + this.woolgames.woolwars.overall.kills, + this.woolgames.sheepwars.kills, + this.woolgames.captureTheWool.kills + ); } } From a58fb198db2d6e9dd4be700ec7aa4e04e27d1526 Mon Sep 17 00:00:00 2001 From: Cody Date: Tue, 16 Jun 2026 02:05:24 -0600 Subject: [PATCH 2/4] refactor(stats): replace formatTime with formatTimeWithSeconds * Updated various game mode profiles to use formatTimeWithSeconds for consistency * Removed redundant formatTimeWithSeconds function definitions * Enhanced time formatting across multiple components --- .../src/commands/arcade/modes/dropper.tsx | 4 +- .../src/commands/bedwars/bedwars.profile.tsx | 3 +- .../copsandcrims/copsandcrims.profile.tsx | 4 +- .../src/commands/duels/duels.profile.tsx | 4 +- .../murdermystery/murdermystery.profile.tsx | 4 +- .../src/commands/parkour/parkour.profile.tsx | 4 +- .../commands/tntgames/tntgames.profile.tsx | 4 +- .../woolgames/capture-the-wool.table.tsx | 4 +- .../src/player/gamemodes/arcade/mode.ts | 4 +- .../src/player/gamemodes/bedwars/index.ts | 127 +++++------------- .../src/player/gamemodes/bedwars/mode.ts | 28 ++-- .../src/player/gamemodes/duels/mode.ts | 4 +- .../player/gamemodes/murdermystery/mode.ts | 4 +- .../src/player/gamemodes/parkour/index.ts | 3 +- .../src/player/gamemodes/tntgames/mode.ts | 4 +- .../gamemodes/woolgames/capture-the-wool.ts | 4 +- packages/schemas/src/player/stats.ts | 2 + packages/util/src/util.ts | 3 + 18 files changed, 72 insertions(+), 142 deletions(-) diff --git a/apps/discord-bot/src/commands/arcade/modes/dropper.tsx b/apps/discord-bot/src/commands/arcade/modes/dropper.tsx index 3aa32ecfd..f245e3529 100644 --- a/apps/discord-bot/src/commands/arcade/modes/dropper.tsx +++ b/apps/discord-bot/src/commands/arcade/modes/dropper.tsx @@ -8,12 +8,10 @@ import { type ArcadeModes, type Dropper, DropperMaps, type SubModeForMode, scanMetadata } from "@statsify/schemas"; import { Historical, If, Table } from "#components"; -import { arrayGroup, formatRaceTime, formatTime } from "@statsify/util"; +import { arrayGroup, formatRaceTime, formatTimeWithSeconds } from "@statsify/util"; import type { LocalizeFunction } from "@statsify/discord"; import type { ProfileTime } from "#commands/base.hypixel-command"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - interface DropperTableProps { stats: Dropper; submode: SubModeForMode; diff --git a/apps/discord-bot/src/commands/bedwars/bedwars.profile.tsx b/apps/discord-bot/src/commands/bedwars/bedwars.profile.tsx index 4f8909814..cc325258a 100644 --- a/apps/discord-bot/src/commands/bedwars/bedwars.profile.tsx +++ b/apps/discord-bot/src/commands/bedwars/bedwars.profile.tsx @@ -34,11 +34,10 @@ export const BedWarsProfile = ({ time, }: BedWarsProfileProps) => { const { bedwars } = player.stats; - const modeKey = mode.submode?.api ?? mode.api; const formattedMode = mode.submode?.api === mode.api || !mode.submode ? mode.formatted : `${mode.formatted} ${mode.submode.formatted}`; - const stats = bedwars[modeKey]; + const stats = mode.submode ? bedwars[mode.api][mode.submode.api] : bedwars[mode.api]; const sidebar: SidebarItem[] = [ [t("stats.tokens"), t(bedwars.tokens), "§2"], diff --git a/apps/discord-bot/src/commands/copsandcrims/copsandcrims.profile.tsx b/apps/discord-bot/src/commands/copsandcrims/copsandcrims.profile.tsx index 0f78882ab..6628eb53e 100644 --- a/apps/discord-bot/src/commands/copsandcrims/copsandcrims.profile.tsx +++ b/apps/discord-bot/src/commands/copsandcrims/copsandcrims.profile.tsx @@ -8,11 +8,9 @@ import { Container, Footer, Header, Historical, SidebarItem, Table, formatProgression } from "#components"; import { CopsAndCrimsModes, FormattedGame, type GameMode } from "@statsify/schemas"; -import { formatTime } from "@statsify/util"; +import { formatTimeWithSeconds } from "@statsify/util"; import type { BaseProfileProps } from "#commands/base.hypixel-command"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - export interface CopsAndCrimsProfileProps extends BaseProfileProps { mode: GameMode; } diff --git a/apps/discord-bot/src/commands/duels/duels.profile.tsx b/apps/discord-bot/src/commands/duels/duels.profile.tsx index d6f2cedc3..a28ed3a93 100644 --- a/apps/discord-bot/src/commands/duels/duels.profile.tsx +++ b/apps/discord-bot/src/commands/duels/duels.profile.tsx @@ -15,12 +15,10 @@ import { } from "./tables/index.js"; import { Container, Footer, Header, SidebarItem, formatProgression } from "#components"; import { DuelsModes, FormattedGame, type GameMode } from "@statsify/schemas"; -import { formatTime, prettify } from "@statsify/util"; +import { formatTimeWithSeconds, prettify } from "@statsify/util"; import type { BaseProfileProps, ProfileTime } from "#commands/base.hypixel-command"; import type { DuelsModeIcons } from "./duels.command.js"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - export type DuelsProfileProps = Omit & { mode: GameMode; time: T; diff --git a/apps/discord-bot/src/commands/murdermystery/murdermystery.profile.tsx b/apps/discord-bot/src/commands/murdermystery/murdermystery.profile.tsx index 91cff1f5b..46f291353 100644 --- a/apps/discord-bot/src/commands/murdermystery/murdermystery.profile.tsx +++ b/apps/discord-bot/src/commands/murdermystery/murdermystery.profile.tsx @@ -19,11 +19,9 @@ import { type GameMode, MurderMysteryModes, } from "@statsify/schemas"; -import { formatTime } from "@statsify/util"; +import { formatTimeWithSeconds } from "@statsify/util"; import type { BaseProfileProps } from "#commands/base.hypixel-command"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - export interface MurderMysteryProfileProps extends BaseProfileProps { mode: GameMode; } diff --git a/apps/discord-bot/src/commands/parkour/parkour.profile.tsx b/apps/discord-bot/src/commands/parkour/parkour.profile.tsx index 9d0bd739e..9e1fc10ed 100644 --- a/apps/discord-bot/src/commands/parkour/parkour.profile.tsx +++ b/apps/discord-bot/src/commands/parkour/parkour.profile.tsx @@ -8,12 +8,10 @@ import { Container, Footer, GameList, Header } from "#components"; import { FormattedGame, GameId } from "@statsify/schemas"; -import { formatTime } from "@statsify/util"; +import { formatTimeWithSeconds } from "@statsify/util"; import type { BaseProfileProps } from "#commands/base.hypixel-command"; import type { Image } from "skia-canvas"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - interface ParkourProfileProps extends BaseProfileProps { gameIcons: Record; } diff --git a/apps/discord-bot/src/commands/tntgames/tntgames.profile.tsx b/apps/discord-bot/src/commands/tntgames/tntgames.profile.tsx index e998f1005..5e90f7bd7 100644 --- a/apps/discord-bot/src/commands/tntgames/tntgames.profile.tsx +++ b/apps/discord-bot/src/commands/tntgames/tntgames.profile.tsx @@ -8,11 +8,9 @@ import { Container, Footer, Header, Historical, SidebarItem, Table, formatProgression } from "#components"; import { FormattedGame, type GameMode, type TNTGamesModes } from "@statsify/schemas"; -import { formatTime, prettify } from "@statsify/util"; +import { formatTime, formatTimeWithSeconds, prettify } from "@statsify/util"; import type { BaseProfileProps } from "#commands/base.hypixel-command"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - export interface TNTGamesProfileProps extends BaseProfileProps { mode: GameMode; } diff --git a/apps/discord-bot/src/commands/woolgames/capture-the-wool.table.tsx b/apps/discord-bot/src/commands/woolgames/capture-the-wool.table.tsx index 4fd0ac318..5396ce4d0 100644 --- a/apps/discord-bot/src/commands/woolgames/capture-the-wool.table.tsx +++ b/apps/discord-bot/src/commands/woolgames/capture-the-wool.table.tsx @@ -7,13 +7,11 @@ */ import { Historical, If, Table } from "#components"; -import { formatTime } from "@statsify/util"; +import { formatTimeWithSeconds } from "@statsify/util"; import type { CaptureTheWool } from "@statsify/schemas"; import type { LocalizeFunction } from "@statsify/discord"; import type { ProfileTime } from "#commands/base.hypixel-command"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - interface CaptureTheWoolTableProps { captureTheWool: CaptureTheWool; t: LocalizeFunction; diff --git a/packages/schemas/src/player/gamemodes/arcade/mode.ts b/packages/schemas/src/player/gamemodes/arcade/mode.ts index d1bac2a7f..5dbc1b908 100644 --- a/packages/schemas/src/player/gamemodes/arcade/mode.ts +++ b/packages/schemas/src/player/gamemodes/arcade/mode.ts @@ -6,7 +6,7 @@ * https://github.com/Statsify/statsify/blob/main/LICENSE */ -import { type APIData, formatRaceTime, formatTime } from "@statsify/util"; +import { type APIData, formatRaceTime, formatTime, formatTimeWithSeconds } from "@statsify/util"; import { EasterSimulator, GrinchSimulator, @@ -16,8 +16,6 @@ import { import { Field } from "#metadata"; import { add, deepAdd, deepSub, ratio, sub } from "@statsify/math"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - export class BlockingDead { @Field() public wins: number; diff --git a/packages/schemas/src/player/gamemodes/bedwars/index.ts b/packages/schemas/src/player/gamemodes/bedwars/index.ts index 13d8c97d6..85d6a76dd 100644 --- a/packages/schemas/src/player/gamemodes/bedwars/index.ts +++ b/packages/schemas/src/player/gamemodes/bedwars/index.ts @@ -40,58 +40,58 @@ export const BEDWARS_MODES = new GameModes([ { api: "armed", submodes: [ - { api: "armed", formatted: "Overall" }, - { api: "armedDoubles", formatted: "Doubles" }, - { api: "armedFours", formatted: "Fours" }, + { api: "overall" }, + { api: "doubles" }, + { api: "fours" }, ], }, { api: "castle", hypixel: "BEDWARS_CASTLE" }, { api: "lucky", submodes: [ - { api: "lucky", formatted: "Overall" }, - { api: "luckyDoubles", formatted: "Doubles" }, - { api: "luckyFours", formatted: "Fours" }, + { api: "overall" }, + { api: "doubles" }, + { api: "fours" }, ], }, { api: "rush", submodes: [ - { api: "rush", formatted: "Overall" }, - { api: "rushDoubles", formatted: "Doubles" }, - { api: "rushFours", formatted: "Fours" }, + { api: "overall" }, + { api: "doubles" }, + { api: "fours" }, ], }, { api: "swap", submodes: [ - { api: "swap", formatted: "Overall" }, - { api: "swapDoubles", formatted: "Doubles" }, - { api: "swapFours", formatted: "Fours" }, + { api: "overall" }, + { api: "doubles" }, + { api: "fours" }, ], }, { api: "ultimate", submodes: [ - { api: "ultimate", formatted: "Overall" }, - { api: "ultimateDoubles", formatted: "Doubles" }, - { api: "ultimateFours", formatted: "Fours" }, + { api: "overall" }, + { api: "doubles" }, + { api: "fours" }, ], }, { api: "underworld", submodes: [ - { api: "underworld", formatted: "Overall" }, - { api: "underworldDoubles", formatted: "Doubles" }, - { api: "underworldFours", formatted: "Fours" }, + { api: "overall" }, + { api: "doubles" }, + { api: "fours" }, ], }, { api: "voidless", submodes: [ - { api: "voidless", formatted: "Overall" }, - { api: "voidlessDoubles", formatted: "Doubles" }, - { api: "voidlessFours", formatted: "Fours" }, + { api: "overall" }, + { api: "doubles" }, + { api: "fours" }, ], }, { api: "oneBlock", hypixel: "BEDWARS_EIGHT_ONE_ONEBLOCK" }, @@ -190,74 +190,32 @@ export class BedWars { public "4v4": BedWarsMode; @Field() - public armed: BedWarsMode; + public armed: DreamsBedWarsMode; @Field() public castle: BedWarsMode; @Field() - public lucky: BedWarsMode; + public lucky: DreamsBedWarsMode; @Field() - public rush: BedWarsMode; + public rush: DreamsBedWarsMode; @Field() - public swap: BedWarsMode; + public swap: DreamsBedWarsMode; @Field() - public ultimate: BedWarsMode; + public ultimate: DreamsBedWarsMode; @Field() - public underworld: BedWarsMode; + public underworld: DreamsBedWarsMode; @Field() - public voidless: BedWarsMode; + public voidless: DreamsBedWarsMode; @Field() public oneBlock: BedWarsMode; - @Field() - public armedDoubles: BedWarsMode; - - @Field() - public armedFours: BedWarsMode; - - @Field() - public luckyDoubles: BedWarsMode; - - @Field() - public luckyFours: BedWarsMode; - - @Field() - public rushDoubles: BedWarsMode; - - @Field() - public rushFours: BedWarsMode; - - @Field() - public swapDoubles: BedWarsMode; - - @Field() - public swapFours: BedWarsMode; - - @Field() - public ultimateDoubles: BedWarsMode; - - @Field() - public ultimateFours: BedWarsMode; - - @Field() - public underworldDoubles: BedWarsMode; - - @Field() - public underworldFours: BedWarsMode; - - @Field() - public voidlessDoubles: BedWarsMode; - - @Field() - public voidlessFours: BedWarsMode; - @Field() public challenges: BedWarsModeChallenges; @@ -332,30 +290,15 @@ export class BedWars { this.castle = new BedWarsMode(data, "castle"); - this.armed = DreamsBedWarsMode.new(data, "armed"); - this.lucky = DreamsBedWarsMode.new(data, "lucky"); - this.rush = DreamsBedWarsMode.new(data, "rush"); - this.swap = DreamsBedWarsMode.new(data, "swap"); - this.ultimate = DreamsBedWarsMode.new(data, "ultimate"); - this.underworld = DreamsBedWarsMode.new(data, "underworld"); - this.voidless = DreamsBedWarsMode.new(data, "voidless"); + this.armed = new DreamsBedWarsMode(data, "armed"); + this.lucky = new DreamsBedWarsMode(data, "lucky"); + this.rush = new DreamsBedWarsMode(data, "rush"); + this.swap = new DreamsBedWarsMode(data, "swap"); + this.ultimate = new DreamsBedWarsMode(data, "ultimate"); + this.underworld = new DreamsBedWarsMode(data, "underworld"); + this.voidless = new DreamsBedWarsMode(data, "voidless"); this.oneBlock = new BedWarsMode(data, "eight_one_oneblock"); - this.armedDoubles = new BedWarsMode(data, "eight_two_armed"); - this.armedFours = new BedWarsMode(data, "four_four_armed"); - this.luckyDoubles = new BedWarsMode(data, "eight_two_lucky"); - this.luckyFours = new BedWarsMode(data, "four_four_lucky"); - this.rushDoubles = new BedWarsMode(data, "eight_two_rush"); - this.rushFours = new BedWarsMode(data, "four_four_rush"); - this.swapDoubles = new BedWarsMode(data, "eight_two_swap"); - this.swapFours = new BedWarsMode(data, "four_four_swap"); - this.ultimateDoubles = new BedWarsMode(data, "eight_two_ultimate"); - this.ultimateFours = new BedWarsMode(data, "four_four_ultimate"); - this.underworldDoubles = new BedWarsMode(data, "eight_two_underworld"); - this.underworldFours = new BedWarsMode(data, "four_four_underworld"); - this.voidlessDoubles = new BedWarsMode(data, "eight_two_voidless"); - this.voidlessFours = new BedWarsMode(data, "four_four_voidless"); - this.core = deepSub(this.overall, this["4v4"]); BedWarsMode.applyRatios(this.core); diff --git a/packages/schemas/src/player/gamemodes/bedwars/mode.ts b/packages/schemas/src/player/gamemodes/bedwars/mode.ts index 67a6fde56..da06657a5 100644 --- a/packages/schemas/src/player/gamemodes/bedwars/mode.ts +++ b/packages/schemas/src/player/gamemodes/bedwars/mode.ts @@ -104,16 +104,24 @@ export class BedWarsMode { } } -export class DreamsBedWarsMode extends BedWarsMode { - public static new(data: APIData, mode: string) { - const stats = deepAdd( - new BedWarsMode(data, `eight_two_${mode}`), - new BedWarsMode(data, `four_four_${mode}`), - ); - - BedWarsMode.applyRatios(stats); - stats.winstreak = 0; - return stats; +export class DreamsBedWarsMode { + @Field() + public overall: BedWarsMode; + + @Field() + public doubles: BedWarsMode; + + @Field() + public fours: BedWarsMode; + + public constructor(data: APIData, mode: string) { + this.doubles = new BedWarsMode(data, `eight_two_${mode}`); + this.fours = new BedWarsMode(data, `four_four_${mode}`); + + this.overall = deepAdd(this.doubles, this.fours); + + BedWarsMode.applyRatios(this.overall); + this.overall.winstreak = 0; } } diff --git a/packages/schemas/src/player/gamemodes/duels/mode.ts b/packages/schemas/src/player/gamemodes/duels/mode.ts index bdda67cd6..bd8393535 100644 --- a/packages/schemas/src/player/gamemodes/duels/mode.ts +++ b/packages/schemas/src/player/gamemodes/duels/mode.ts @@ -6,14 +6,12 @@ * https://github.com/Statsify/statsify/blob/main/LICENSE */ -import { type APIData, formatTime } from "@statsify/util"; +import { type APIData, formatTimeWithSeconds } from "@statsify/util"; import { Field } from "#metadata"; import { Progression } from "#progression"; import { TitleRequirement, getTitleAndProgression } from "./util.js"; import { add, deepAdd, ratio } from "@statsify/math"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - export class BaseDuelsGameMode { @Field() public bestWinstreak: number; diff --git a/packages/schemas/src/player/gamemodes/murdermystery/mode.ts b/packages/schemas/src/player/gamemodes/murdermystery/mode.ts index a30e537b1..9cea5db60 100644 --- a/packages/schemas/src/player/gamemodes/murdermystery/mode.ts +++ b/packages/schemas/src/player/gamemodes/murdermystery/mode.ts @@ -6,13 +6,11 @@ * https://github.com/Statsify/statsify/blob/main/LICENSE */ -import { type APIData, formatTime, prettify } from "@statsify/util"; +import { type APIData, formatTimeWithSeconds, prettify } from "@statsify/util"; import { Field } from "#metadata"; import { Progression } from "#progression"; import { ratio } from "@statsify/math"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - export class BaseMurderMysteryMode { @Field() public wins: number; diff --git a/packages/schemas/src/player/gamemodes/parkour/index.ts b/packages/schemas/src/player/gamemodes/parkour/index.ts index ff57df798..f34a22f23 100644 --- a/packages/schemas/src/player/gamemodes/parkour/index.ts +++ b/packages/schemas/src/player/gamemodes/parkour/index.ts @@ -6,7 +6,7 @@ * https://github.com/Statsify/statsify/blob/main/LICENSE */ -import { type APIData, formatTime } from "@statsify/util"; +import { type APIData, formatTimeWithSeconds } from "@statsify/util"; import { type ExtractGameModes, FormattedGame, GameModes } from "#game"; import { Field } from "#metadata"; @@ -14,7 +14,6 @@ export const PARKOUR_MODES = new GameModes([{ api: "overall" }] as const); export type ParkourModes = ExtractGameModes; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); const fieldOptions = { sort: "ASC", formatter: formatTimeWithSeconds, fieldName: "Time" }; const historical = { enabled: false }; diff --git a/packages/schemas/src/player/gamemodes/tntgames/mode.ts b/packages/schemas/src/player/gamemodes/tntgames/mode.ts index 85782ce89..f429dc006 100644 --- a/packages/schemas/src/player/gamemodes/tntgames/mode.ts +++ b/packages/schemas/src/player/gamemodes/tntgames/mode.ts @@ -6,14 +6,12 @@ * https://github.com/Statsify/statsify/blob/main/LICENSE */ -import { type APIData, formatTime } from "@statsify/util"; +import { type APIData, formatTime, formatTimeWithSeconds } from "@statsify/util"; import { Field } from "#metadata"; import { type GamePrefix, createPrefixProgression, cycleColors, defaultPrefix, getFormattedPrefix } from "#prefixes"; import { Progression } from "#progression"; import { ratio } from "@statsify/math"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - const tntgamesRainbow = (text: string) => cycleColors(text, ["c", "6", "e", "a", "b", "d", "5"]); // Prefixes for TNT Run, PVP Run and Bow Spleef diff --git a/packages/schemas/src/player/gamemodes/woolgames/capture-the-wool.ts b/packages/schemas/src/player/gamemodes/woolgames/capture-the-wool.ts index 92cee381c..14aa402ed 100644 --- a/packages/schemas/src/player/gamemodes/woolgames/capture-the-wool.ts +++ b/packages/schemas/src/player/gamemodes/woolgames/capture-the-wool.ts @@ -6,12 +6,10 @@ * https://github.com/Statsify/statsify/blob/main/LICENSE */ -import { type APIData, formatTime } from "@statsify/util"; +import { type APIData, formatTimeWithSeconds } from "@statsify/util"; import { Field } from "#metadata"; import { ratio } from "@statsify/math"; -const formatTimeWithSeconds = (time: number) => formatTime(time, { entries: 3 }); - export class CaptureTheWool { @Field() public wins: number; diff --git a/packages/schemas/src/player/stats.ts b/packages/schemas/src/player/stats.ts index b24b1821c..0965ce92f 100644 --- a/packages/schemas/src/player/stats.ts +++ b/packages/schemas/src/player/stats.ts @@ -261,6 +261,7 @@ export class PlayerStats { this.bedwars.overall.wins, this.blitzsg.overall.wins, this.buildbattle.overall.wins, + this.buildbattle.speedBuilders.wins, this.copsandcrims.overall.wins, this.duels.overall.wins, this.megawalls.overall.wins, @@ -271,6 +272,7 @@ export class PlayerStats { this.smashheroes.overall.wins, this.speeduhc.overall.wins, this.tntgames.wins, + this.turbokartracers.gold, this.uhc.overall.wins, this.vampirez.overallWins, this.walls.wins, diff --git a/packages/util/src/util.ts b/packages/util/src/util.ts index 064aef4f3..97941ee4c 100644 --- a/packages/util/src/util.ts +++ b/packages/util/src/util.ts @@ -177,6 +177,9 @@ export const formatTime = ( .join(", "); }; +export const formatTimeWithSeconds = (time: number) => + formatTime(time, { entries: 3 }); + export const relativeTime = (time: number) => `${formatTime(Date.now() - time)} ago`; From 9c1a4e2c97382e1d3bae97c83252da62f7485f54 Mon Sep 17 00:00:00 2001 From: Cody Date: Tue, 16 Jun 2026 03:09:39 -0600 Subject: [PATCH 3/4] fix(stats): correct spelling of 'Travelled' to 'Traveled' * Update localization strings for consistency * Remove historical tracking for prestigeGold and goldRequirement fields * Clean up formatting in leaderboard field definitions --- locales/en-US/default.json | 6 +-- .../schemas/src/player/gamemodes/pit/index.ts | 53 +++++++++++++------ .../src/player/gamemodes/quake/mode.ts | 6 +-- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/locales/en-US/default.json b/locales/en-US/default.json index ca7a7b4ee..6621d71b3 100644 --- a/locales/en-US/default.json +++ b/locales/en-US/default.json @@ -576,7 +576,7 @@ "blocksBroken": "Blocks Broken", "blocksPlaced": "Blocks Placed", "blocksRan": "Blocks Ran", - "blocksTravelled": "Blocks Travelled", + "blocksTraveled": "Blocks Traveled", "bombsDefused": "Bombs Defused", "bombsPlanted": "Bombs Planted", "bounty": "Bounty", @@ -730,7 +730,6 @@ "powerupActivations": "Power-Up Activations", "powerups": "Power-Ups", "prefix": "Prefix", - "prestigeGold": "Prestige Gold", "prevent": "Prevent", "progression": { "exp": "EXP Progress", @@ -823,7 +822,8 @@ "airTime": "Air Time", "potionsSplashed": "Potions Splashed", "powerOrbs": "Power Orbs", - "grenadeKills": "Grenade Kills" + "grenadeKills": "Grenade Kills", + "headshotAccuracy": "Headshot Accuracy" }, "tips": { "discord": "$t(emojis:socials.discord) Join our **$t(socials.discord)** and get **20% lower cooldowns** $t(emojis:heart)", diff --git a/packages/schemas/src/player/gamemodes/pit/index.ts b/packages/schemas/src/player/gamemodes/pit/index.ts index 2e19f934f..f39666998 100644 --- a/packages/schemas/src/player/gamemodes/pit/index.ts +++ b/packages/schemas/src/player/gamemodes/pit/index.ts @@ -80,13 +80,13 @@ export class Pit { }) public goldEarned: number; - @Field({ leaderboard: { enabled: false }, historical: { enabled: false } }) + @Field({ leaderboard: { enabled: false } }) public prestigeGold: number; - @Field({ leaderboard: { enabled: false }, historical: { enabled: false } }) + @Field({ leaderboard: { enabled: false } }) public goldRequirement: number; - @Field({ leaderboard: { enabled: false }, historical: { enabled: false } }) + @Field({ leaderboard: { enabled: false } }) public goldProgression: Progression; @Field({ historical: { enabled: false } }) @@ -114,26 +114,41 @@ export class Pit { public assists: number; @Field({ - leaderboard: { name: "Tier I Mystics Enchanted", fieldName: "Mystics Enchanted" }, + leaderboard: { + name: "Tier I Mystics Enchanted", + fieldName: "Mystics Enchanted", + }, }) public tier1MysticsEnchanted: number; @Field({ - leaderboard: { name: "Tier II Mystics Enchanted", fieldName: "Mystics Enchanted" }, + leaderboard: { + name: "Tier II Mystics Enchanted", + fieldName: "Mystics Enchanted", + }, }) public tier2MysticsEnchanted: number; @Field({ - leaderboard: { name: "Tier III Mystics Enchanted", fieldName: "Mystics Enchanted" }, + leaderboard: { + name: "Tier III Mystics Enchanted", + fieldName: "Mystics Enchanted", + }, }) public tier3MysticsEnchanted: number; @Field({ - leaderboard: { name: "Total Mystics Enchanted", fieldName: "Mystics Enchanted" }, + leaderboard: { + name: "Total Mystics Enchanted", + fieldName: "Mystics Enchanted", + }, }) public totalMysticsEnchanted: number; - @Field({ leaderboard: { formatter: formatTime }, historical: { enabled: false } }) + @Field({ + leaderboard: { formatter: formatTime }, + historical: { enabled: false }, + }) public playtime: number; @Field({ historical: { enabled: false } }) @@ -161,8 +176,14 @@ export class Pit { const darkPantsCreated = data.dark_pants_crated ?? 0; const renownUnlocks = (profile.renown_unlocks ?? []) as RenownUnlock[]; - const renownShopCost = getRenownShopCost(renownUnlocks.filter((unlock) => unlock.key !== "unlock_golden_pickaxe")); - this.lifetimeRenown = add(renownShopCost, this.renown, 2 * darkPantsCreated); + const renownShopCost = getRenownShopCost( + renownUnlocks.filter((unlock) => unlock.key !== "unlock_golden_pickaxe"), + ); + this.lifetimeRenown = add( + renownShopCost, + this.renown, + 2 * darkPantsCreated, + ); this.bounty = getBounty(profile.bounties); @@ -179,18 +200,18 @@ export class Pit { this.progression = new Progression( this.exp - lastPrestigeReq, - Math.min(getPrestigeReq(prestige) - lastPrestigeReq, 11_787_293_080) + Math.min(getPrestigeReq(prestige) - lastPrestigeReq, 11_787_293_080), ); this.goldProgression = new Progression( this.prestigeGold, - Math.max(prestigeGoldReq, 0) + Math.max(prestigeGoldReq, 0), ); this.levelFormatted = getLevelFormatted(level, prestige); this.nextLevelFormatted = - prestige === 50 ? - getLevelFormatted(120, prestige) : - getLevelFormatted(1, prestige + 1); + prestige === 50 + ? getLevelFormatted(120, prestige) + : getLevelFormatted(1, prestige + 1); this.contractsCompleted = data.contracts_completed; @@ -207,7 +228,7 @@ export class Pit { this.totalMysticsEnchanted = add( this.tier1MysticsEnchanted, this.tier2MysticsEnchanted, - this.tier3MysticsEnchanted + this.tier3MysticsEnchanted, ); this.goldEarned = data.cash_earned; diff --git a/packages/schemas/src/player/gamemodes/quake/mode.ts b/packages/schemas/src/player/gamemodes/quake/mode.ts index 44737571a..ce59104a1 100644 --- a/packages/schemas/src/player/gamemodes/quake/mode.ts +++ b/packages/schemas/src/player/gamemodes/quake/mode.ts @@ -32,8 +32,8 @@ export class QuakeMode { @Field() public shotsFired: number; - @Field({ leaderboard: { fieldName: "Blocks Travelled", name: "Blocks Travelled" } }) - public blocksTravelled: number; + @Field() + public blocksTraveled: number; @Field({ leaderboard: { fieldName: "2017+ Kills", name: "2017+ Kills" } }) public postUpdateKills: number; @@ -56,7 +56,7 @@ export class QuakeMode { this.headshots = data[`headshots${mode}`]; this.killstreaks = data[`killstreaks${mode}`]; this.shotsFired = data[`shots_fired${mode}`]; - this.blocksTravelled = data[`distance_travelled${mode}`]; + this.blocksTraveled = data[`distance_travelled${mode}`]; this.postUpdateKills = data[`kills_since_update_feb_2017${mode}`]; QuakeMode.applyRatios(this); } From b89e38fe54f8a5abf9ced5768707dc6daf71eea2 Mon Sep 17 00:00:00 2001 From: Cody Date: Tue, 16 Jun 2026 03:28:56 -0600 Subject: [PATCH 4/4] fix(quake): correct spelling of 'Travelled' to 'Traveled' --- apps/discord-bot/src/commands/quake/quake.profile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/discord-bot/src/commands/quake/quake.profile.tsx b/apps/discord-bot/src/commands/quake/quake.profile.tsx index e903caf72..5333a930b 100644 --- a/apps/discord-bot/src/commands/quake/quake.profile.tsx +++ b/apps/discord-bot/src/commands/quake/quake.profile.tsx @@ -41,7 +41,7 @@ export const QuakeProfile = ({ [t("stats.godlikes"), t(quake.godlikes), "§3"], [t("stats.trigger"), `${quake.trigger}s`, "§b"], [t("stats.highestKillstreak"), t(quake.highestKillstreak), "§4"], - [t("stats.blocksTravelled"), t(quake[mode.api].blocksTravelled), "§b"], + [t("stats.blocksTraveled"), t(quake[mode.api].blocksTraveled), "§b"], ]; return (