From 870f7d799b2189586b21ef98b59261e5e05631b4 Mon Sep 17 00:00:00 2001 From: tresabhi <43380238+tresabhi@users.noreply.github.com> Date: Sun, 4 Oct 2026 17:22:23 -0500 Subject: [PATCH] applyReactiveArmor --- .../website/src/config/characteristics.ts | 12 +++- .../src/core/blitzkit/tankCharacteristics.ts | 17 ++--- .../website/src/hooks/useCharacteristics.ts | 72 ++++++++++++------- packages/website/src/hooks/useEquipment.ts | 4 +- .../[...locale]/tanks/[slug]/_index.tsx | 2 +- packages/website/src/types/characteristics.ts | 7 +- 6 files changed, 71 insertions(+), 43 deletions(-) diff --git a/packages/website/src/config/characteristics.ts b/packages/website/src/config/characteristics.ts index 4e083c9d6..3cf8d123a 100644 --- a/packages/website/src/config/characteristics.ts +++ b/packages/website/src/config/characteristics.ts @@ -1,4 +1,5 @@ import { blitzkitToBlitzShellKind } from "@blitzkit/core"; +import { ShellType } from "@blitzkit/protos"; import { CharacteristicType, type Characteristic, @@ -32,7 +33,7 @@ export const characteristics = { if (environment.equalize) coefficient *= equalizer.damage; - script("TungstenTip", (effect) => { + script("protagonist", "TungstenTip", (effect) => { coefficient *= (effect.minDamageFactor + effect.maxDamageFactor) / 2; }); @@ -45,10 +46,15 @@ export const characteristics = { compute({ shell, script }) { let coefficient = 1; - script("TungstenTip", (effect) => { + script("protagonist", "TungstenTip", (effect) => { coefficient *= (effect.minDamageFactor + effect.maxDamageFactor) / 2; }); + script("antagonist", "ShieldKit", (effect) => { + if (shell.type === ShellType.SHELL_TYPE_HE) return; + coefficient *= 1 - effect.shieldCoef; + }); + return coefficient * shell.module_damage; }, }, @@ -58,7 +64,7 @@ export const characteristics = { compute({ shell, script }) { let coefficient = 1; - script("CalibratedShells", (effect) => { + script("protagonist", "CalibratedShells", (effect) => { coefficient *= 1 + effect.piercingFactors![blitzkitToBlitzShellKind[shell.type]] / 100; diff --git a/packages/website/src/core/blitzkit/tankCharacteristics.ts b/packages/website/src/core/blitzkit/tankCharacteristics.ts index 5d1844bd8..5552eb89f 100644 --- a/packages/website/src/core/blitzkit/tankCharacteristics.ts +++ b/packages/website/src/core/blitzkit/tankCharacteristics.ts @@ -168,16 +168,13 @@ export function tankCharacteristics( const intraClipCoefficient = coefficient([hasShellReloadBoost, -0.3]); const burstShells = gun.burst?.count ?? 1; const burstInterShell = gun.burst?.interval; - const armorDamageCoefficient = - coefficient([hasTungsten, 0.15]) * - coefficient( - [applyReactiveArmor && shell.type !== ShellType.SHELL_TYPE_HE, -0.27], - [applyDynamicArmor, -0.1], - [ - applySpallLiner && shell.type === ShellType.SHELL_TYPE_HE, - SPALL_LINER_HE_DAMAGE_DELTA, - ], - ); + const armorDamageCoefficient = coefficient( + [applyDynamicArmor, -0.1], + [ + applySpallLiner && shell.type === ShellType.SHELL_TYPE_HE, + SPALL_LINER_HE_DAMAGE_DELTA, + ], + ); const assaultDamageCoefficient = gun.assault_ranges && gun.assault_ranges.types.includes(shell.type) ? (gun.assault_ranges.ranges.find( diff --git a/packages/website/src/hooks/useCharacteristics.ts b/packages/website/src/hooks/useCharacteristics.ts index cdab34cf3..b904bbb06 100644 --- a/packages/website/src/hooks/useCharacteristics.ts +++ b/packages/website/src/hooks/useCharacteristics.ts @@ -9,51 +9,65 @@ import type { CharacteristicName, ComputedCharacteristics, } from "../types/characteristics"; -import type { DuelSide } from "./useEquipment"; +import { duelSides, type DuelSide } from "./useEquipment"; const tanks = await api.tanks(); const scripts = await api.scripts(); const equipment = await api.equipment(); -export function useCharacteristics(side: DuelSide) { - const state = Tankopedia.use((state) => state[side]); +export function useCharacteristics() { + const protagonist = Tankopedia.use((state) => state.protagonist); + const antagonist = Tankopedia.use((state) => state.antagonist); const environment = Tankopedia.use((state) => state.environment); - return computeCharacteristics(state, environment); + return computeCharacteristics({ protagonist, antagonist }, environment); } export function computeCharacteristics( - state: TankState, + states: Record, environment: TankEnvironment, ) { const computed: ComputedCharacteristics = new Map(); - const tank = tanks.tanks[state.tank]; - const engine = tank.engines.find((engine) => engine.id === state.engine)!; - const track = tank.tracks.find((track) => track.id === state.track)!; - const turret = tank.turrets.find((turret) => turret.id === state.turret)!; - const gun = turret.guns.find((gun) => gun.id === state.gun)!; - const shell = gun.shells.find((shell) => shell.id === state.shell)!; + const tank = tanks.tanks[states.protagonist.tank]; + const engine = tank.engines.find( + (engine) => engine.id === states.protagonist.engine, + )!; + const track = tank.tracks.find( + (track) => track.id === states.protagonist.track, + )!; + const turret = tank.turrets.find( + (turret) => turret.id === states.protagonist.turret, + )!; + const gun = turret.guns.find((gun) => gun.id === states.protagonist.gun)!; + const shell = gun.shells.find( + (shell) => shell.id === states.protagonist.shell, + )!; const equipmentPreset = equipment.presets[tank.equipment_preset]; - const scriptsMap = new Map(); + const scriptsMap: Record> = { + protagonist: new Map(), + antagonist: new Map(), + }; - for (const id of state.consumables) { - if (!(id in scripts.consumables)) continue; + for (const side of duelSides) { + for (const id of states[side].consumables) { + if (!(id in scripts.consumables)) continue; - const script = scripts.consumables[id]; - scriptsMap.set(script["#text"], script); - } + const script = scripts.consumables[id]; + scriptsMap.protagonist.set(script["#text"], script); + } - for (const index in state.equipment) { - const choice = state.equipment[index]; - const id = equipmentPreset.slots[index].options[choice]; + for (const index in states[side].equipment) { + const choice = states[side].equipment[index]; + const id = equipmentPreset.slots[index].options[choice]; - if (!(id in scripts.equipment)) continue; + if (!(id in scripts.equipment)) continue; - const script = scripts.equipment[id]; - scriptsMap.set(script["#text"], script); + const script = scripts.equipment[id]; + scriptsMap.protagonist.set(script["#text"], script); + } } function characteristic(name: CharacteristicName) { @@ -66,13 +80,17 @@ export function computeCharacteristics( console.log(scriptsMap); - function script(name: string, callback: (effect: BlitzEffectScript) => void) { - if (!scriptsMap.has(name)) return; - callback(scriptsMap.get(name)!); + function script( + side: DuelSide, + name: string, + callback: (effect: BlitzEffectScript) => void, + ) { + if (!scriptsMap[side].has(name)) return; + callback(scriptsMap[side].get(name)!); } const context = { - state, + state: states.protagonist, environment, equalizer: tank.equalizer ?? defaultEqualizer, diff --git a/packages/website/src/hooks/useEquipment.ts b/packages/website/src/hooks/useEquipment.ts index 41ec4eb58..cc6fe6136 100644 --- a/packages/website/src/hooks/useEquipment.ts +++ b/packages/website/src/hooks/useEquipment.ts @@ -5,7 +5,9 @@ import { Tankopedia } from "../stores/tankopedia"; const equipment = await api.equipment(); const tanks = await api.tanks(); -export type DuelSide = "protagonist" | "antagonist"; +export const duelSides = ["protagonist", "antagonist"] as const; + +export type DuelSide = (typeof duelSides)[number]; export function useEquipment(side: DuelSide, id: number) { const member = Tankopedia.use((state) => state[side]); diff --git a/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx b/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx index f9fffff87..67f6f637d 100644 --- a/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx +++ b/packages/website/src/pages/[...chunk_default]/[...locale]/tanks/[slug]/_index.tsx @@ -27,7 +27,7 @@ export const Page = withErrorWrapper( const protagonist = Tankopedia.use((state) => state.protagonist); const equalize = Tankopedia.use((state) => state.environment.equalize); - const characteristics = useCharacteristics("protagonist"); + const characteristics = useCharacteristics(); const thicknessRange = useMemo(() => { const entries = Object.values(tanks.tanks); diff --git a/packages/website/src/types/characteristics.ts b/packages/website/src/types/characteristics.ts index 8ad8972b8..66c79e3bc 100644 --- a/packages/website/src/types/characteristics.ts +++ b/packages/website/src/types/characteristics.ts @@ -11,6 +11,7 @@ import type { } from "@blitzkit/protos"; import type { ReactNode } from "react"; import { characteristics } from "../config/characteristics"; +import type { DuelSide } from "../hooks/useEquipment"; import type { TankEnvironment } from "../stores/tankopedia"; import type { TankState } from "../tankopedia/tankState"; @@ -44,7 +45,11 @@ export interface CharacteristicContext { name: CharacteristicName, ): ReturnType; - script(name: string, effect: (effect: BlitzEffectScript) => void): void; + script( + side: DuelSide, + name: string, + effect: (effect: BlitzEffectScript) => void, + ): void; } export enum CharacteristicType {