import { literals } from "@blitzkit/i18n/src/literals"; import { Card, Flex, Inset, Separator, Text, type CardProps, } from "@radix-ui/themes"; import type { ComponentProps } from "react"; import { radToDeg } from "three/src/math/MathUtils.js"; import { useLocale } from "../hooks/useLocale"; import type { Shot, ShotLayer } from "../stores/tankopedia"; import { shotStatusColors } from "./ShotDisplay"; import { ArmorType } from "./SpacedArmorScene"; export const layerTypeNames = { [ArmorType.Primary]: "primary", [ArmorType.Spaced]: "spaced", [ArmorType.External]: "external", null: "gap", } as const; function LayerEntry({ layerIndex, shotStatusColor, layerName, layer, angle, }: { layerIndex?: string; shotStatusColor: ComponentProps["color"]; layerName: string; layer: ShotLayer; angle?: number; }) { const { locale, strings } = useLocale(); return ( {layerIndex} {layerName} {layer.type === null && ( {literals(strings.common.units.mm, { value: Math.round(layer.distance * 1000).toLocaleString(locale), })} )} {layer.type === ArmorType.External && ( {literals(strings.common.units.mm, { value: Math.round(layer.thickness).toLocaleString(locale), })} )} {(layer.type === ArmorType.Primary || layer.type === ArmorType.Spaced) && ( {angle === undefined ? literals(strings.common.units.mm, { value: Math.round(layer.thicknessAngled).toLocaleString( locale ), }) : literals( strings.website.tools.tankopedia.sandbox.dynamic.shot_card .stats.thickness_and_angle, { thickness: Math.round(layer.thicknessAngled).toLocaleString( locale ), angle: radToDeg(angle ?? 0).toFixed(0), } )} )} {layer.type === null && ( {literals( strings.website.tools.tankopedia.sandbox.dynamic.shot_card.stats .ricochet_loss, { loss: Math.max(-100, -50 * layer.distance).toFixed(0) } )} )} {(layer.type === ArmorType.Primary || layer.type === ArmorType.Spaced) && ( {literals( strings.website.tools.tankopedia.sandbox.dynamic.shot_card.stats .nominal, { thickness: Math.round(layer.thickness).toLocaleString(locale) } )} )} ); } interface ShotDisplayCardProps extends CardProps { shot: Shot; } export function ShotDisplayCard({ shot, ...props }: ShotDisplayCardProps) { const { locale, strings } = useLocale(); if (!shot) return null; const outTitleColor = shot.out ? shotStatusColors[shot.out.status] : undefined; const inTitleColor = shotStatusColors[shot.in.status]; const hasOutLayers = shot.out !== undefined && shot.out.layers.length > 0; const penetrationChance = shot.penetrationChance !== undefined && ( {literals(strings.common.units.percentage, { value: (shot.penetrationChance * 100).toFixed(0), })} ); return ( {literals( strings.website.tools.tankopedia.sandbox.dynamic.shot_card .status[shot.in.status], { damage: Math.round(shot.damage).toLocaleString(locale) } )} {!hasOutLayers && penetrationChance} {shot.in.layers.map((layer, index) => { const layerName = strings.website.tools.tankopedia.sandbox.dynamic.shot_card .element[ layer.type === ArmorType.External ? layer.variant : layerTypeNames[`${layer.type}`] ]; const layerIndex = layer.type === null ? undefined : `${(shot.containsGaps ? index / 2 : index) + 1}.`; const shotStatusColor = shot.in.status === "splash" ? shotStatusColors.splash : shotStatusColors[layer.status]; return ( ); })}
{shot.out && shot.out.layers.length > 0 && ( <> ricochet (-25% penetration) {literals( strings.website.tools.tankopedia.sandbox.dynamic.shot_card .status[shot.out.status], { damage: Math.round(shot.damage).toLocaleString(locale) } )} {penetrationChance} {shot.out.layers.map((layer, index) => { const layerName = strings.website.tools.tankopedia.sandbox.dynamic.shot_card .element[ layer.type === ArmorType.External ? layer.variant : layerTypeNames[`${layer.type}`] ]; const shiftedIndex = index + shot.out!.layers.length; const layerIndex = layer.type === null ? undefined : `${ (shot.containsGaps ? shiftedIndex / 2 : shiftedIndex) + 1 }.`; const shotStatusColor = shot.out!.status === "splash" ? shotStatusColors.splash : shotStatusColors[layer.status]; return ( ); })} )}
); }