From 0e08c1ab1dcb886af80dc243a9079c478f6d8377 Mon Sep 17 00:00:00 2001
From: Taken
Date: Thu, 18 Sep 2025 20:08:49 +0200
Subject: [PATCH] Added warlords stats card
---
src/app/(stats)/player/[ign]/_client.tsx | 4 +-
.../player/[ign]/_stats/warlords/stats.tsx | 39 ++++++
.../player/[ign]/_stats/warlords/warlords.tsx | 44 +++++++
src/data/hypixel/warlords.ts | 114 ++++++++++++++++++
src/lib/hypixel/warlords/general.ts | 24 ++++
src/lib/schema/player.ts | 7 +-
src/lib/schema/stats/warlords.ts | 25 ++++
7 files changed, 254 insertions(+), 3 deletions(-)
create mode 100644 src/app/(stats)/player/[ign]/_stats/warlords/stats.tsx
create mode 100644 src/app/(stats)/player/[ign]/_stats/warlords/warlords.tsx
create mode 100644 src/data/hypixel/warlords.ts
create mode 100644 src/lib/hypixel/warlords/general.ts
create mode 100644 src/lib/schema/stats/warlords.ts
diff --git a/src/app/(stats)/player/[ign]/_client.tsx b/src/app/(stats)/player/[ign]/_client.tsx
index 8334240..4979beb 100644
--- a/src/app/(stats)/player/[ign]/_client.tsx
+++ b/src/app/(stats)/player/[ign]/_client.tsx
@@ -26,6 +26,7 @@ import SmashHerosStats from "./_stats/smashheros/smashheros"
import SpeedUHCStats from "./_stats/speeduhc/speeduhc"
import TNTGamesStats from "./_stats/tnt-games/tnt-games"
import UHCStats from "./_stats/uhc/uhc"
+import WarlordsStats from "./_stats/warlords/warlords"
import WoolGamesStats from "./_stats/woolgames/woolgames"
export function PlayerPageLoadText() {
@@ -96,7 +97,8 @@ export function PlayerStats(
"blitz": ,
"arcade": ,
"speeduhc": ,
- "smashheros":
+ "smashheros": ,
+ "warlords":
} as const
const defaultOrder = Object.keys(statsComponents)
diff --git a/src/app/(stats)/player/[ign]/_stats/warlords/stats.tsx b/src/app/(stats)/player/[ign]/_stats/warlords/stats.tsx
new file mode 100644
index 0000000..c5055a4
--- /dev/null
+++ b/src/app/(stats)/player/[ign]/_stats/warlords/stats.tsx
@@ -0,0 +1,39 @@
+import { formatNumber } from "@/lib/formatters"
+import { devide } from "@/lib/hypixel/general"
+import { getWarlordsLosses } from "@/lib/hypixel/warlords/general"
+import { NonNullStats } from "@/lib/schema/player"
+import { BasicStat } from "../../_components/Stats"
+
+export default function WarlordsGeneralStats({ stats }: { stats: NonNullable }) {
+ const losses = getWarlordsLosses(stats)
+ const wl = formatNumber(devide(stats.wins, losses))
+ const kd = formatNumber(devide(stats.kills, stats.deaths))
+ const ak = formatNumber(devide(stats.assists, stats.kills))
+ return (
+
+ )
+}
diff --git a/src/app/(stats)/player/[ign]/_stats/warlords/warlords.tsx b/src/app/(stats)/player/[ign]/_stats/warlords/warlords.tsx
new file mode 100644
index 0000000..74579fc
--- /dev/null
+++ b/src/app/(stats)/player/[ign]/_stats/warlords/warlords.tsx
@@ -0,0 +1,44 @@
+import { Separator } from "@/components/ui/separator"
+import { formatNumber } from "@/lib/formatters"
+import { devide } from "@/lib/hypixel/general"
+import { getWarlordsLosses, getWarlordsMostPlayedClass } from "@/lib/hypixel/warlords/general"
+import { NonNullStats } from "@/lib/schema/player"
+import GeneralStats from "../GeneralStats"
+import WarlordsGeneralStats from "./stats"
+
+export default function WarlordsStats({ stats }: { stats: NonNullStats["Warlords"] }) {
+ if (!stats) return null
+
+ const losses = getWarlordsLosses(stats)
+ const kd = formatNumber(devide(stats.kills, stats.deaths))
+ const wl = formatNumber(devide(stats.wins, losses))
+ const mostPlayed = getWarlordsMostPlayedClass(stats)
+
+ return (
+ Main
,
+ stat: {mostPlayed !== null ? mostPlayed.name : "Unknown"}
+ },
+ {
+ title: KD
,
+ stat: {kd}
+ },
+ {
+ title: Wins
,
+ stat: {formatNumber(stats.wins)}
+ },
+ {
+ title: WL
,
+ stat: {wl}
+ }
+ ]}
+ >
+
+
+
+ )
+}
diff --git a/src/data/hypixel/warlords.ts b/src/data/hypixel/warlords.ts
new file mode 100644
index 0000000..d30eec9
--- /dev/null
+++ b/src/data/hypixel/warlords.ts
@@ -0,0 +1,114 @@
+export const CLASSES = [
+ { id: "mage", name: "Mage" },
+ { id: "paladin", name: "Paladin" },
+ { id: "shaman", name: "Shaman" },
+ { id: "warrior", name: "Warrior" },
+ { id: "", name: "Overall" }
+] as const
+export const MODES = [
+ { id: "capturetheflag", name: "Capture the Flag" },
+ { id: "domination", name: "Domination" },
+ { id: "teamdeathmatch", name: "Team Deathmatch" },
+ { id: "", name: "Overall" }
+] as const
+export const RARITIES = [
+ { id: "common", name: "Common", color: "green" },
+ { id: "rare", name: "Rare", color: "blue" },
+ { id: "epic", name: "Epic", color: "purple" },
+ { id: "legendary", name: "Legendary", color: "gold" }
+] as const
+export const UPGRADES = [
+ { id: "cooldown", name: "Cooldown" },
+ { id: "critchance", name: "Crit Chance" },
+ { id: "critmultiplier", name: "Crit Multiplier" },
+ { id: "energy", name: "Energy" },
+ { id: "health", name: "Health" },
+ { id: "skill1", name: "First Skill" },
+ { id: "skill2", name: "Second Skill" },
+ { id: "skill3", name: "Third Skill" },
+ { id: "skill4", name: "Fourth Skill" },
+ { id: "skill5", name: "Ultimate SKill" }
+] as const
+export const MATERIALS = {
+ "WOOD_AXE": "Steel Sword",
+ "STONE_AXE": "Training Sword",
+ "IRON_AXE": "Demonblade",
+ "GOLD_AXE": "Venomstrike",
+ "DIAMOND_AXE": "Diamondspark",
+ "WOOD_HOE": "Zweireaper",
+ "STONE_HOE": "Runeblade",
+ "IRON_HOE": "Elven Greatsword",
+ "GOLD_HOE": "Hatchet",
+ "DIAMOND_HOE": "Gem Axe",
+ "WOOD_SPADE": "Nomegusta",
+ "STONE_SPADE": "Drakefang",
+ "IRON_SPADE": "Hammer",
+ "GOLD_SPADE": "Stone Mallet",
+ "DIAMOND_SPADE": "Gemcrusher",
+ "WOOD_PICKAXE": "Abbadon",
+ "STONE_PICKAXE": "Walking Stick",
+ "IRON_PICKAXE": "World Tree Branch",
+ "GOLD_PICKAXE": "Flameweaver",
+ "DIAMOND_PICKAXE": "Void Twig",
+ "SALMON": "Scimitar",
+ "PUFFERFISH": "Golden Gladius",
+ "CLOWNFISH": "Magmasword",
+ "COD": "Frostbite",
+ "ROTTEN_FLESH": "Pike",
+ "POTATO": "Halberd",
+ "MELON": "Divine Reach",
+ "POISONOUS_POTATO": "Ruby Thorn",
+ "STRING": "Hammer of Light",
+ "RAW_CHICKEN": "Nethersteel Katana",
+ "MUTTON": "Claws",
+ "PORK": "Mandibles",
+ "RAW_BEEF": "Katar",
+ "APPLE": "Enderfist",
+ "PUMPKIN_PIE": "Orc Axe",
+ "COOKED_COD": "Doubleaxe",
+ "BREAD": "Runic Axe",
+ "MUSHROOM_STEW": "Lunar Relic",
+ "RABBIT_STEW": "Bludgeon",
+ "COOKED_RABBIT": "Cudgel",
+ "COOKED_CHICKEN": "Tenderizer",
+ "BAKED_POTATO": "Broccomace",
+ "COOKED_SALMON": "Felflame Blade",
+ "COOKED_MUTTON": "Amaranth",
+ "COOKED_BEEF": "Armblade",
+ "GRILLED_PORK": "Gemini",
+ "COOKED_PORKCHOP": "Gemini",
+ "GOLDEN_CARROT": "Void Edge"
+} as const
+export const PLAYERCLASSES = {
+ mage: ["Pyromancer", "Cryomancer", "Aquamancer"],
+ warrior: ["Berserker", "Defender", "Revenant"],
+ paladin: ["Avenger", "Crusader", "Protector"],
+ shaman: ["Thunderlord", "Earthwarden", "Spiritguard"]
+} as const
+export const SCORES = {
+ COMMON: [
+ { score: 276, prefix: "Crumbly" },
+ { score: 302, prefix: "Flimsy" },
+ { score: 327, prefix: "Rough" },
+ { score: 352, prefix: "Honed" },
+ { score: 378, prefix: "Refined" },
+ { score: 403, prefix: "Balanced" }
+ ],
+ RARE: [
+ { score: 359, prefix: "Savage" },
+ { score: 400, prefix: "Vicious" },
+ { score: 440, prefix: "Deadly" },
+ { score: 481, prefix: "Perfect" }
+ ],
+ EPIC: [
+ { score: 450, prefix: "Fierce" },
+ { score: 489, prefix: "Mighty" },
+ { score: 527, prefix: "Brutal" },
+ { score: 566, prefix: "Gladiator's" }
+ ],
+ LEGENDARY: [
+ { score: 595, prefix: "Vanquisher's" },
+ { score: 665, prefix: "Champion's" },
+ { score: 735, prefix: "Warlord's" }
+ ]
+} as const
diff --git a/src/lib/hypixel/warlords/general.ts b/src/lib/hypixel/warlords/general.ts
new file mode 100644
index 0000000..8fd39fe
--- /dev/null
+++ b/src/lib/hypixel/warlords/general.ts
@@ -0,0 +1,24 @@
+import { CLASSES } from "@/data/hypixel/warlords"
+import { NonNullStats } from "@/lib/schema/player"
+
+export function getWarlordsLosses(stats: NonNullable) {
+ return stats.mage_plays + stats.paladin_plays + stats.shaman_plays + stats.warrior_plays - stats.wins
+}
+
+export function getWarlordsMostPlayedClass(stats: NonNullable) {
+ let mostPlayedClass: typeof CLASSES[number] | null = null
+ let maxPlays = 0
+
+ for (const classObj of CLASSES) {
+ if (classObj.id === "") continue
+
+ const plays = stats[`${classObj.id}_plays`]
+
+ if (plays > maxPlays) {
+ maxPlays = plays
+ mostPlayedClass = classObj
+ }
+ }
+
+ return mostPlayedClass
+}
diff --git a/src/lib/schema/player.ts b/src/lib/schema/player.ts
index 5a78654..6092b31 100644
--- a/src/lib/schema/player.ts
+++ b/src/lib/schema/player.ts
@@ -13,6 +13,7 @@ import { smashHerosStats } from "./stats/smashheros"
import { speedUhcStatsSchema } from "./stats/speeduhc"
import { tntGamesStatsSchema } from "./stats/tnt-games"
import { uhcSchema } from "./stats/uhc"
+import { warlordsStatsSchema } from "./stats/warlords"
import { woolGamesStatsSchema } from "./stats/woolgames"
export const playerSchema = z.looseObject({
@@ -42,13 +43,15 @@ export const playerSchema = z.looseObject({
HungerGames: blitzStatsSchema.optional(),
Arcade: arcadeStatsSchema.optional(),
SpeedUHC: speedUhcStatsSchema.optional(),
- SuperSmash: smashHerosStats.optional()
- }).transform(({ Walls3, MCGO, HungerGames, SuperSmash, ...rest }) => {
+ SuperSmash: smashHerosStats.optional(),
+ Battleground: warlordsStatsSchema.optional()
+ }).transform(({ Walls3, MCGO, HungerGames, SuperSmash, Battleground, ...rest }) => {
return {
MegaWalls: Walls3,
CopsAndCrims: MCGO,
Blitz: HungerGames,
SmashHeros: SuperSmash,
+ Warlords: Battleground,
...rest
}
}).optional(),
diff --git a/src/lib/schema/stats/warlords.ts b/src/lib/schema/stats/warlords.ts
new file mode 100644
index 0000000..4dc3b3a
--- /dev/null
+++ b/src/lib/schema/stats/warlords.ts
@@ -0,0 +1,25 @@
+import z from "zod"
+
+export const warlordsStatsSchema = z.object({
+ kills: z.number().default(0),
+ assists: z.number().default(0),
+ deaths: z.number().default(0),
+ wins: z.number().default(0),
+ coins: z.number().default(0),
+ magic_dust: z.number().default(0),
+ void_shards: z.number().default(0),
+ flag_conquer_self: z.number().default(0),
+ flag_returns: z.number().default(0),
+ mage_plays: z.number().default(0),
+ paladin_plays: z.number().default(0),
+ shaman_plays: z.number().default(0),
+ warrior_plays: z.number().default(0),
+ mage_wins: z.number().default(0),
+ paladin_wins: z.number().default(0),
+ shaman_wins: z.number().default(0),
+ warrior_wins: z.number().default(0),
+ mage_losses: z.number().default(0),
+ paladin_losses: z.number().default(0),
+ shaman_losses: z.number().default(0),
+ warrior_losses: z.number().default(0)
+})