Updated copsandcrims

This commit is contained in:
2025-09-09 19:53:04 +02:00
parent 1336a1787e
commit 3c466d81cf
4 changed files with 136 additions and 2 deletions

View File

@@ -8,6 +8,7 @@ import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats"
import CopsAndCrimsGeneralStats from "./stats"
import CopsAndCrimsStatTable from "./table"
import CopsAndCrimsWeaponStats from "./weapons"
export default function CopsAndCrimsStats({ stats }: { stats: NonNullStats["CopsAndCrims"] }) {
if (!stats) return null
@@ -55,6 +56,8 @@ export default function CopsAndCrimsStats({ stats }: { stats: NonNullStats["Cops
<Separator className="my-4" />
<CopsAndCrimsStatTable stats={stats} />
<Separator className="my-4" />
<CopsAndCrimsWeaponStats stats={stats} />
<Separator className="my-4" />
</AccordionContent>
</CardContent>
</Card>

View File

@@ -0,0 +1,62 @@
import {
getCopsAndCrimsGunName,
getCopsAndCrimsGunUgrade,
getCopsAndCrimsGunUgradeColor,
getCopsAndCrimsUpgardeName
} from "@/lib/hypixel/copsandcrims/general"
import { romanize } from "@/lib/hypixel/general"
import { NonNullStats } from "@/lib/schema/player"
import { GenericProgressNoTooltip } from "../../_components/GenericProgress"
export default function CopsAndCrimsWeaponStats({ stats }: { stats: NonNullable<NonNullStats["CopsAndCrims"]> }) {
return (
<div>
<h2 className="text-xl font-bold">Weapons</h2>
<div className="grid grid-cols-2 grid-rows-6 gap-4 pt-6">
<KnifeStats gunId="knife" stats={stats} />
<KnifeStats gunId="pistol" stats={stats} />
<KnifeStats gunId="handgun" stats={stats} />
<KnifeStats gunId="magnum" stats={stats} />
<KnifeStats gunId="sniper" stats={stats} />
<KnifeStats gunId="bullpup" stats={stats} />
<KnifeStats gunId="smg" stats={stats} />
<KnifeStats gunId="rifle" stats={stats} />
<KnifeStats gunId="carbine" stats={stats} />
<KnifeStats gunId="scoped_rifle" stats={stats} />
<KnifeStats gunId="shotgun" stats={stats} />
<KnifeStats gunId="auto_shotgun" stats={stats} />
</div>
</div>
)
}
function KnifeStats({ gunId, stats }: { gunId: Parameters<typeof getCopsAndCrimsGunName>[0], stats: NonNullable<NonNullStats["CopsAndCrims"]> }) {
const name = getCopsAndCrimsGunName(gunId)
const upgrades = getCopsAndCrimsGunUgrade(gunId, stats)
return (
<div>
<h3 className="pb-1 font-bold text-md">{name}</h3>
<div className="flex gap-2">
<div className="space-y-2">
{upgrades.map((u, i) => {
const upgrade = getCopsAndCrimsUpgardeName(u.upgradeId)
return <p key={i}>{upgrade}</p>
})}
</div>
<div className="flex-1 space-y-2">
{upgrades.map((u, i) => {
const color = getCopsAndCrimsGunUgradeColor(u.value)
const percent = u.value / 9 * 100
return (
<div key={i}>
{percent !== 0 ?
<GenericProgressNoTooltip percent={percent} text={romanize(u.value)} className={`bg-mc-${color}`} /> :
<div className="flex flex-1 justify-center rounded-md bg-background">-</div>}
</div>
)
})}
</div>
</div>
</div>
)
}

View File

@@ -1,7 +1,39 @@
import { MODES, SCORE } from "@/data/hypixel/copsandcrims"
import { GUNS, MODES, SCORE, UPGRADELEVELS, UPGRADES } from "@/data/hypixel/copsandcrims"
import { NonNullStats } from "@/lib/schema/player"
import { devide } from "../general"
export function getCopsAndCrimsGunUgradeColor(num: number) {
for (const upgradeLevel of UPGRADELEVELS.slice().reverse()) {
if (upgradeLevel.level <= num) return upgradeLevel.color
}
return UPGRADELEVELS.at(0)!.color
}
export function getCopsAndCrimsUpgardeName(upgradeId: typeof UPGRADES[number]["id"]) {
return UPGRADES.find(g => g.id === upgradeId)!.name
}
export function getCopsAndCrimsGunName(gunId: typeof GUNS[number]["id"]) {
return GUNS.find(g => g.id === gunId)!.name
}
export function getCopsAndCrimsGunUgrade(gunId: typeof GUNS[number]["id"], stats: NonNullable<NonNullStats["CopsAndCrims"]>) {
return UPGRADES.map(upgrade => {
if (upgrade.id === "charge_bonus") return -1
if (upgrade.id === "attack_delay") return -1
return { upgradeId: upgrade.id, value: stats[`${gunId}_${upgrade.id}`] }
}).filter(v => typeof v !== "number")
}
export function getCopsAndCrimsExtraUpgrade(stats: NonNullable<NonNullStats["CopsAndCrims"]>) {
return {
sniper: stats["sniper_charge_bonus"],
knife: stats["knife_attack_delay"]
}
}
export function getCopsAndCrimsModeName(modeId: typeof MODES[number]["id"]) {
return MODES.find(m => m.id === modeId)!.name
}

View File

@@ -660,6 +660,40 @@ export const megawallsStats = z.looseObject({
...megawallsModeStats()
})
function copsAndCrimsGunUpgrades() {
const ids = [
"knife",
"pistol",
"handgun",
"magnum",
"sniper",
"bullpup",
"smg",
"rifle",
"carbine",
"scoped_rifle",
"shotgun",
"auto_shotgun"
] as const
const upgrades = [
"damage_increase",
"recoil_reduction",
"reload_speed_reduction",
"cost_reduction"
] as const
const entries = new Map<string, z.ZodDefault<z.ZodNumber>>()
for (const id of ids) {
for (const upgrade of upgrades) {
entries.set(`${id}_${upgrade}`, z.number().default(0))
}
}
return Object.fromEntries(entries) as Record<`${typeof ids[number]}_${typeof upgrades[number]}`, z.ZodDefault<z.ZodNumber>>
}
export const copsAndCrimsStatsSchema = z.looseObject({
kills: z.number().default(0),
assists: z.number().default(0),
@@ -684,5 +718,8 @@ export const copsAndCrimsStatsSchema = z.looseObject({
shots_fired: z.number().default(0),
coins: z.number().default(0),
round_wins: z.number().default(0),
headshot_kills: z.number().default(0)
headshot_kills: z.number().default(0),
knife_attack_delay: z.number().default(0),
sniper_charge_bonus: z.number().default(0),
...copsAndCrimsGunUpgrades()
})