feat: localize tankopedia sandbox

This commit is contained in:
tresabhi committed 2025-01-13 20:56:30 -06:00
1 parent ade6ec8af1
commit e0c897025e
6 files changed
+398 -208

No files matched your search

+90 -1
View File
@@ -6,6 +6,20 @@
},
"common": {
"units_suffix": {
"m": "%s1m",
"mm": "%s1mm",
"deg": "%s1°",
"hp": "%s1hp"
},
"shells": {
"ap": "AP",
"apcr": "APCR",
"heat": "HEAT",
"he": "HE"
},
"player_count_period": {
"total": "Total",
"d_120": "Past 120 days",
@@ -812,7 +826,82 @@
"description": "Blitz tank encyclopedia",
"seo_description": "Statistics, armor, and more for all tanks in World of Tanks Blitz",
"tank_seo_title": "%s1 - Tier %s2 %s3 %s4 | %s5 Tankopedia | World of Tanks Blitz (WoTB)",
"tank_seo_description": "%s1 armor, statistics, equipment, provisions, and more. %s2 DPM, %s3hp alpha, %s4mm penetration, %s5kph top speed, %s6hp health."
"tank_seo_description": "%s1 armor, statistics, equipment, provisions, and more. %s2 DPM, %s3hp alpha, %s4mm penetration, %s5kph top speed, %s6hp health.",
"sandbox": {
"poses": {
"hull_down": "Hull down",
"face_hug": "Face hug",
"default": "Default"
},
"settings": {
"armor": "Armor",
"green_penetration": "Green penetration",
"hide_model_under_armor": "Hide model under armor",
"opaque": "Opaque",
"dev_wireframe": "DEV: wireframe",
"environment": "Environment",
"show_grid": "Show grid"
},
"screenshot": {
"download": "Download",
"copy": "Copy"
},
"model": {
"name": "Model"
},
"dynamic": {
"name": "Dynamic armor",
"custom_shell": {
"type": "Type",
"caliber": "Caliber",
"penetration": "Penetration",
"normalization": "Normalization",
"ricochet": "Ricochet",
"explosion_radius": "Explosion radius",
"exit": "Exit",
"reset": "Reset"
},
"advanced": "Advanced highlighting",
"shooter": "Shooter:",
"shot_card": {
"element": {
"primary": "Primary",
"spaced": "Spaced",
"external": "External",
"gap": "Gap",
"gun": "Gun",
"track": "Tracks"
},
"status": {
"penetration": "%s1hp penetration",
"blocked": "Blocked",
"ricochet": "Ricochet",
"splash": "%s1hp splash"
},
"stats": {
"thickness_and_angle": "%s1mm %s2°",
"nominal": "%s1mm nominal",
"ricochet_loss": "%s1% penetration"
}
}
},
"static": {
"name": "Static armor",
"primary": "Primary",
"spaced": "Spaced",
"external": "External",
"edit": {
"label": "Edit",
"reset": "Reset"
}
}
}
},
"compare": {
"name": "Compare",
@@ -16,6 +16,7 @@ import {
Path,
Quaternion,
} from 'three';
import { LocaleProvider, useLocale } from '../../../hooks/useLocale';
import {
TankopediaEphemeral,
type ShotLayerNonExternal,
@@ -45,6 +46,7 @@ export function ShotDisplay() {
const splashRadiusWrapper = useRef<Group>(null);
const splashRadiusMaterial = useRef<MeshBasicMaterial>(null);
let animationStartTime: number | null = null;
const { locale } = useLocale();
useEffect(() => {
if (shot?.splashRadius !== undefined) {
@@ -180,7 +182,9 @@ export function ShotDisplay() {
mt={tracerGoingUp ? '9' : '0'}
pt={tracerGoingUp ? '4' : '0'}
>
<ShotDisplayCard shot={shot} />
<LocaleProvider locale={locale}>
<ShotDisplayCard shot={shot} />
</LocaleProvider>
</Box>
</Html>
@@ -8,34 +8,18 @@ import {
} from '@radix-ui/themes';
import type { ComponentProps } from 'react';
import { radToDeg } from 'three/src/math/MathUtils.js';
import { literals } from '../../../core/i18n/literals';
import { useLocale } from '../../../hooks/useLocale';
import type {
Shot,
ShotLayer,
ShotStatus,
} from '../../../stores/tankopediaEphemeral';
import type { Shot, ShotLayer } from '../../../stores/tankopediaEphemeral';
import { shotStatusColors } from './ShotDisplay';
import { ArmorType } from './SpacedArmorScene';
import type { ExternalModuleVariant } from './SpacedArmorSceneComponent';
export const layerTypeNames: Record<ArmorType | 'null', string> = {
[ArmorType.Primary]: 'Primary',
[ArmorType.Spaced]: 'Spaced',
[ArmorType.External]: 'External',
null: 'Gap',
};
const externalLayerNames: Record<ExternalModuleVariant, string> = {
gun: 'Gun',
track: 'Tracks',
};
const shotStatusNames: Record<ShotStatus, string> = {
blocked: 'Blocked',
ricochet: 'Ricochet',
penetration: 'penetration',
splash: 'splash',
};
export const layerTypeNames = {
[ArmorType.Primary]: 'primary',
[ArmorType.Spaced]: 'spaced',
[ArmorType.External]: 'external',
null: 'gap',
} as const;
function LayerEntry({
layerIndex,
@@ -50,7 +34,7 @@ function LayerEntry({
layer: ShotLayer;
angle?: number;
}) {
const { locale } = useLocale();
const { locale, strings } = useLocale();
return (
<Flex align="center" gap="2">
@@ -64,20 +48,26 @@ function LayerEntry({
{layer.type === null && (
<>
<Text size="2" color={shotStatusColor} style={{ width: 64 }}>
{Math.round(layer.distance * 1000).toLocaleString(locale)}
<Text size="1">mm</Text>
{literals(strings.common.units_suffix.mm, [
Math.round(layer.distance * 1000).toLocaleString(locale),
])}
</Text>
<Text size="2" color="gray">
{Math.max(-100, Math.round(-50 * layer.distance))}% penetration
{literals(
strings.website.tools.tankopedia.sandbox.dynamic.shot_card.stats
.ricochet_loss,
[Math.max(-100, -50 * layer.distance).toFixed(0)],
)}
</Text>
</>
)}
{layer.type === ArmorType.External && (
<Text size="2" color={shotStatusColor} style={{ width: 64 }}>
{Math.round(layer.thickness).toLocaleString(locale)}
<Text size="1">mm</Text>
{literals(strings.common.units_suffix.mm, [
Math.round(layer.thickness).toLocaleString(locale),
])}
</Text>
)}
@@ -85,15 +75,24 @@ function LayerEntry({
layer.type === ArmorType.Spaced) && (
<>
<Text size="2" color={shotStatusColor} style={{ width: 80 }}>
{Math.round(layer.thicknessAngled).toLocaleString(locale)}
<Text size="1">{`mm${
angle === undefined ? '' : ` ${Math.round(radToDeg(angle))}°`
}`}</Text>
{literals(
angle === undefined
? strings.common.units_suffix.mm
: strings.website.tools.tankopedia.sandbox.dynamic.shot_card
.stats.thickness_and_angle,
[
Math.round(layer.thicknessAngled).toLocaleString(locale),
radToDeg(angle ?? 0).toFixed(0),
],
)}
</Text>
<Text size="2" color="gray">
{Math.round(layer.thickness).toLocaleString(locale)}
<Text size="1">mm</Text> nominal
{literals(
strings.website.tools.tankopedia.sandbox.dynamic.shot_card.stats
.nominal,
[Math.round(layer.thickness).toLocaleString(locale)],
)}
</Text>
</>
)}
@@ -106,7 +105,7 @@ interface ShotDisplayCardProps extends CardProps {
}
export function ShotDisplayCard({ shot, ...props }: ShotDisplayCardProps) {
const { locale } = useLocale();
const { locale, strings } = useLocale();
if (!shot) return null;
@@ -120,21 +119,23 @@ export function ShotDisplayCard({ shot, ...props }: ShotDisplayCardProps) {
<Flex direction="column" gap="2">
<Flex direction="column" gap="1">
<Text color={inTitleColor} weight="bold">
{shot.in.status !== 'blocked' && shot.in.status !== 'ricochet' && (
<>
{Math.round(shot.damage).toLocaleString(locale)}
<Text size="1">hp</Text>
</>
{literals(
strings.website.tools.tankopedia.sandbox.dynamic.shot_card.status[
shot.in.status
],
[Math.round(shot.damage).toLocaleString(locale)],
)}
{` ${shotStatusNames[shot.in.status]} `}
</Text>
<Flex direction="column">
{shot.in.layers.map((layer, index) => {
const layerName =
layer.type === ArmorType.External
? externalLayerNames[layer.variant]
: layerTypeNames[`${layer.type}`];
strings.website.tools.tankopedia.sandbox.dynamic.shot_card
.element[
layer.type === ArmorType.External
? layer.variant
: layerTypeNames[`${layer.type}`]
];
const layerIndex =
layer.type === null
? undefined
@@ -184,22 +185,22 @@ export function ShotDisplayCard({ shot, ...props }: ShotDisplayCardProps) {
</Inset>
<Text color={outTitleColor} weight="bold">
{shot.out.status !== 'blocked' &&
shot.out.status !== 'ricochet' && (
<>
{Math.round(shot.damage).toLocaleString(locale)}
<Text size="1">hp</Text>
</>
)}
{` ${shotStatusNames[shot.out.status]} `}
{literals(
strings.website.tools.tankopedia.sandbox.dynamic.shot_card
.status[shot.out.status],
[Math.round(shot.damage).toLocaleString(locale)],
)}
</Text>
<Flex direction="column">
{shot.out.layers.map((layer, index) => {
const layerName =
layer.type === ArmorType.External
? externalLayerNames[layer.variant]
: layerTypeNames[`${layer.type}`];
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
@@ -11,6 +11,8 @@ import {
} from '@radix-ui/themes';
import { throttle } from 'lodash-es';
import { type ChangeEvent } from 'react';
import { literals } from '../../../../../../core/i18n/literals';
import { useLocale } from '../../../../../../hooks/useLocale';
import { Duel } from '../../../../../../stores/duel';
import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral';
@@ -19,6 +21,7 @@ export function CustomShellButton() {
const gun = Duel.use((state) => state.protagonist.gun);
const antagonistShell = Duel.use((state) => state.antagonist.shell);
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
const { strings } = useLocale();
return (
<Popover.Root
@@ -49,13 +52,16 @@ export function CustomShellButton() {
</Popover.Trigger>
<Popover.Content>
{/* <Popover.Title>Custom shell</Popover.Title> */}
{customShell && (
<>
<Flex direction="column" gap="2">
<Flex align="center" justify="between" gap="4">
<Text>Type</Text>
<Text>
{
strings.website.tools.tankopedia.sandbox.dynamic
.custom_shell.type
}
</Text>
<Select.Root
value={`${customShell.type}`}
onValueChange={(value) => {
@@ -99,16 +105,29 @@ export function CustomShellButton() {
<Select.Trigger />
<Select.Content>
<Select.Item value={`${ShellType.AP}`}>AP</Select.Item>
<Select.Item value={`${ShellType.APCR}`}>APCR</Select.Item>
<Select.Item value={`${ShellType.HEAT}`}>HEAT</Select.Item>
<Select.Item value={`${ShellType.HE}`}>HE</Select.Item>
<Select.Item value={`${ShellType.AP}`}>
{strings.common.shells.ap}
</Select.Item>
<Select.Item value={`${ShellType.APCR}`}>
{strings.common.shells.apcr}
</Select.Item>
<Select.Item value={`${ShellType.HEAT}`}>
{strings.common.shells.heat}
</Select.Item>
<Select.Item value={`${ShellType.HE}`}>
{strings.common.shells.he}
</Select.Item>
</Select.Content>
</Select.Root>
</Flex>
<Flex align="center" justify="between" gap="4">
<Text>Caliber</Text>
<Text>
{
strings.website.tools.tankopedia.sandbox.dynamic
.custom_shell.caliber
}
</Text>
<TextField.Root
style={{ maxWidth: '6rem' }}
defaultValue={customShell.caliber}
@@ -131,12 +150,19 @@ export function CustomShellButton() {
}
}}
>
<TextField.Slot side="right">mm</TextField.Slot>
<TextField.Slot side="right">
{literals(strings.common.units_suffix.mm, [''])}
</TextField.Slot>
</TextField.Root>
</Flex>
<Flex align="center" justify="between" gap="4">
<Text>Penetration</Text>
<Text>
{
strings.website.tools.tankopedia.sandbox.dynamic
.custom_shell.penetration
}
</Text>
<TextField.Root
style={{ maxWidth: '6rem' }}
defaultValue={customShell.penetration.near}
@@ -160,7 +186,9 @@ export function CustomShellButton() {
}
}}
>
<TextField.Slot side="right">mm</TextField.Slot>
<TextField.Slot side="right">
{literals(strings.common.units_suffix.mm, [''])}
</TextField.Slot>
</TextField.Root>
</Flex>
@@ -168,7 +196,12 @@ export function CustomShellButton() {
customShell.type === ShellType.APCR) && (
<>
<Flex align="center" justify="between" gap="4" py="1">
<Text>Normalization</Text>
<Text>
{
strings.website.tools.tankopedia.sandbox.dynamic
.custom_shell.normalization
}
</Text>
<Flex
align="center"
@@ -178,7 +211,9 @@ export function CustomShellButton() {
minWidth="8rem"
>
<Text color="gray">
{Math.round(customShell.normalization ?? 0)}°
{literals(strings.common.units_suffix.deg, [
(customShell.normalization ?? 0).toFixed(0),
])}
</Text>
<Slider
min={0}
@@ -197,11 +232,18 @@ export function CustomShellButton() {
</Flex>
<Flex align="center" justify="between" gap="4" py="1">
<Text>Ricochet</Text>
<Text>
{
strings.website.tools.tankopedia.sandbox.dynamic
.custom_shell.ricochet
}
</Text>
<Flex align="center" gap="2" flexGrow="1" maxWidth="15rem">
<Text color="gray">
{Math.round(customShell.ricochet ?? 90)}°
{literals(strings.common.units_suffix.deg, [
(customShell.ricochet ?? 90).toFixed(0),
])}
</Text>
<Slider
min={0}
@@ -254,7 +296,10 @@ export function CustomShellButton() {
<Flex justify="end" mt="6" gap="2">
<Popover.Close>
<Button color="red" variant="outline">
Exit
{
strings.website.tools.tankopedia.sandbox.dynamic
.custom_shell.exit
}
</Button>
</Popover.Close>
<Button
@@ -265,7 +310,10 @@ export function CustomShellButton() {
});
}}
>
Reset
{
strings.website.tools.tankopedia.sandbox.dynamic.custom_shell
.reset
}
</Button>
</Flex>
</>
@@ -1,6 +1,8 @@
import { EyeClosedIcon, EyeOpenIcon, ReloadIcon } from '@radix-ui/react-icons';
import { Box, Button, Checkbox, Flex, Text } from '@radix-ui/themes';
import { Button, Checkbox, Flex, Text } from '@radix-ui/themes';
import { Suspense } from 'react';
import { literals } from '../../../../../../core/i18n/literals';
import { useLocale } from '../../../../../../hooks/useLocale';
import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral';
import { TankopediaPersistent } from '../../../../../../stores/tankopediaPersistent';
import type { ThicknessRange } from '../../../../../Armor/components/StaticArmor';
@@ -24,6 +26,7 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) {
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
const editStatic = TankopediaEphemeral.use((state) => state.editStatic);
const tankopediaEphemeralStore = TankopediaEphemeral.useStore();
const { strings } = useLocale();
return (
<Flex
@@ -33,112 +36,144 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) {
mr="4"
style={{ transform: 'translateY(-50%)', userSelect: 'none' }}
direction="column"
gap="2"
gap="5"
align="end"
>
<Flex
height="64px"
gap="2"
style={{ opacity: showPrimaryArmor ? 1 : 0.5, cursor: 'pointer' }}
onClick={() => {
mutateTankopediaPersistent((draft) => {
draft.showPrimaryArmor = !draft.showPrimaryArmor;
});
mutateTankopediaEphemeral((draft) => {
draft.highlightArmor = undefined;
});
}}
>
<Flex direction="column" align="end" justify="between">
<Text color="gray" size="1">
{(thicknessRange.value * 1.5).toFixed(0)}
</Text>
<Flex gap="1">
<Flex direction="column" align="end" gap="3">
<Flex
height="64px"
gap="2"
style={{ opacity: showPrimaryArmor ? 1 : 0.5, cursor: 'pointer' }}
onClick={() => {
mutateTankopediaPersistent((draft) => {
draft.showPrimaryArmor = !draft.showPrimaryArmor;
});
mutateTankopediaEphemeral((draft) => {
draft.highlightArmor = undefined;
});
}}
>
<Flex direction="column" align="end" justify="between">
<Text color="gray" size="1">
{literals(strings.common.units_suffix.mm, [
(thicknessRange.value * 1.5).toFixed(0),
])}
</Text>
<Text size="1">
{strings.website.tools.tankopedia.sandbox.static.primary}
</Text>
<Text color="gray" size="1">
{literals(strings.common.units_suffix.mm, ['0'])}
</Text>
</Flex>
<Flex
align="center"
width="1rem"
style={{
borderRadius: 'var(--radius-full)',
overflow: 'hidden',
background: `linear-gradient(rgb(64, 0, 0), rgb(255, 0, 0) 33%, rgb(255, 255, 0) 66%, rgb(0, 255, 0))`,
color: 'black',
}}
>
{showPrimaryArmor ? <EyeOpenIcon /> : <EyeClosedIcon />}
<Text size="1">Primary</Text>
</Flex>
<Text color="gray" size="1">
0
</Text>
</Flex>
<Box
width="16px"
style={{
borderRadius: 'var(--radius-full)',
overflow: 'hidden',
background: `linear-gradient(rgb(64, 0, 0), rgb(255, 0, 0) 33%, rgb(255, 255, 0) 66%, rgb(0, 255, 0))`,
<Flex
height="64px"
gap="2"
style={{ opacity: showSpacedArmor ? 1 : 0.5, cursor: 'pointer' }}
onClick={() => {
mutateTankopediaPersistent((draft) => {
draft.showSpacedArmor = !draft.showSpacedArmor;
});
mutateTankopediaEphemeral((draft) => {
draft.highlightArmor = undefined;
});
}}
/>
</Flex>
>
<Flex direction="column" align="end" justify="between">
<Text color="gray" size="1">
{literals(strings.common.units_suffix.mm, [
thicknessRange.value.toFixed(0),
])}
</Text>
<Text size="1">
{strings.website.tools.tankopedia.sandbox.static.spaced}
</Text>
<Text color="gray" size="1">
{literals(strings.common.units_suffix.mm, ['0'])}
</Text>
</Flex>
<Flex
height="64px"
gap="2"
style={{ opacity: showSpacedArmor ? 1 : 0.5, cursor: 'pointer' }}
onClick={() => {
mutateTankopediaPersistent((draft) => {
draft.showSpacedArmor = !draft.showSpacedArmor;
});
mutateTankopediaEphemeral((draft) => {
draft.highlightArmor = undefined;
});
}}
>
<Flex direction="column" align="end" justify="between">
<Text color="gray" size="1">
{thicknessRange.value.toFixed(0)}
</Text>
<Flex gap="1">
<Flex
align="center"
width="1rem"
style={{
borderRadius: 'var(--radius-full)',
overflow: 'hidden',
background: `linear-gradient(rgb(32, 0, 225), rgb(255, 0, 255))`,
}}
>
{showSpacedArmor ? <EyeOpenIcon /> : <EyeClosedIcon />}
<Text size="1">Spaced</Text>
</Flex>
<Text color="gray" size="1">
0
</Text>
</Flex>
<Box
width="16px"
style={{
borderRadius: 'var(--radius-full)',
overflow: 'hidden',
background: `linear-gradient(rgb(32, 0, 225), rgb(255, 0, 255))`,
<Flex
gap="2"
style={{ opacity: showExternalModules ? 1 : 0.5, cursor: 'pointer' }}
onClick={() => {
mutateTankopediaPersistent((draft) => {
draft.showExternalModules = !draft.showExternalModules;
});
mutateTankopediaEphemeral((draft) => {
draft.highlightArmor = undefined;
});
}}
/>
</Flex>
>
<Flex direction="column" align="end" justify="between">
<Text size="1">
{strings.website.tools.tankopedia.sandbox.static.external}
</Text>
</Flex>
<Flex
gap="2"
style={{ opacity: showExternalModules ? 1 : 0.5, cursor: 'pointer' }}
onClick={() => {
mutateTankopediaPersistent((draft) => {
draft.showExternalModules = !draft.showExternalModules;
});
mutateTankopediaEphemeral((draft) => {
draft.highlightArmor = undefined;
});
}}
>
<Flex direction="column" align="end" justify="between">
<Flex gap="1">
<Flex
justify="center"
width="1rem"
height="1rem"
style={{
borderRadius: 'var(--radius-full)',
overflow: 'hidden',
backgroundColor: '#c0c0c0',
color: 'black',
}}
>
{showExternalModules ? <EyeOpenIcon /> : <EyeClosedIcon />}
<Text size="1">External</Text>
</Flex>
</Flex>
</Flex>
<Flex direction="column" align="end" gap="2">
<Flex align="center" gap="2">
<Flex
gap="2"
style={{ cursor: 'pointer' }}
onClick={() => {
mutateTankopediaEphemeral((draft) => {
draft.editStatic = !draft.editStatic;
draft.highlightArmor = undefined;
});
}}
>
<Text size="1">
{strings.website.tools.tankopedia.sandbox.static.edit.label}
</Text>
<Checkbox size="2" checked={editStatic} />
</Flex>
</Flex>
<Box
width="16px"
height="16px"
style={{
borderRadius: 'var(--radius-full)',
overflow: 'hidden',
backgroundColor: '#c0c0c0',
}}
/>
</Flex>
<Flex align="center" gap="2" mt="2">
<Button
color="red"
size="1"
@@ -151,22 +186,8 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) {
}}
>
<ReloadIcon />
Reset
{strings.website.tools.tankopedia.sandbox.static.edit.reset}
</Button>
<Flex
gap="2"
style={{ cursor: 'pointer' }}
onClick={() => {
mutateTankopediaEphemeral((draft) => {
draft.editStatic = !draft.editStatic;
draft.highlightArmor = undefined;
});
}}
>
<Text size="1">Edit</Text>
<Checkbox size="2" checked={editStatic} />
</Flex>
</Flex>
<Suspense>
@@ -30,9 +30,11 @@ import {
} from '@radix-ui/themes';
import { Suspense, useState, type RefObject } from 'react';
import { Pose, poseEvent } from '../../../../../core/blitzkit/pose';
import { literals } from '../../../../../core/i18n/literals';
import { useEquipment } from '../../../../../hooks/useEquipment';
import { useFullScreen } from '../../../../../hooks/useFullScreen';
import { useFullscreenAvailability } from '../../../../../hooks/useFullscreenAvailability';
import { useLocale } from '../../../../../hooks/useLocale';
import { App } from '../../../../../stores/app';
import { Duel } from '../../../../../stores/duel';
import {
@@ -87,6 +89,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
const antagonistUniqueGuns = uniqueGuns(antagonistTank.turrets);
const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
const { strings } = useLocale();
return (
<>
@@ -124,13 +127,14 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
>
{!hasCustomShell && (
<Text color="gray" size={{ initial: '1', sm: '2' }}>
{(
resolvePenetrationCoefficient(
hasCalibratedShells,
antagonistShell.type,
) * antagonistShell.penetration.near
).toFixed(0)}
mm
{literals(strings.common.units_suffix.mm, [
(
resolvePenetrationCoefficient(
hasCalibratedShells,
antagonistShell.type,
) * antagonistShell.penetration.near
).toFixed(0),
])}
</Text>
)}
{antagonistUniqueGuns.length > 1 && (
@@ -198,10 +202,11 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
}
secondaryDiscriminator={
<Text style={{ fontSize: '0.75em' }}>
{Math.round(
gun.gun_type!.value.base.shells[0].caliber,
)}
mm
{literals(strings.common.units_suffix.mm, [
gun.gun_type!.value.base.shells[0].caliber.toFixed(
0,
),
])}
</Text>
}
/>
@@ -341,13 +346,13 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
>
<Checkbox checked={advancedHighlighting} />
<Text color="gray" size="2">
Advanced highlighting
{strings.website.tools.tankopedia.sandbox.dynamic.advanced}
</Text>
</Flex>
<Flex align="center" gap="2">
<Text color="gray" size="2">
Shooter:
{strings.website.tools.tankopedia.sandbox.dynamic.shooter}
</Text>
<Dialog.Root
open={antagonistSelectorOpen}
@@ -403,21 +408,27 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
}}
>
<SegmentedControl.Item value={`${TankopediaDisplay.Model}`}>
<Tooltip content="Model">
<Tooltip
content={strings.website.tools.tankopedia.sandbox.model.name}
>
<Flex height="100%" align="center">
<img src={imgur('jAdYf0m')} style={{ height: '1.25em' }} />
</Flex>
</Tooltip>
</SegmentedControl.Item>
<SegmentedControl.Item value={`${TankopediaDisplay.DynamicArmor}`}>
<Tooltip content="Dynamic armor">
<Tooltip
content={strings.website.tools.tankopedia.sandbox.dynamic.name}
>
<Flex height="100%" align="center">
<img src={imgur('oe4Cq0g')} style={{ height: '1.25em' }} />
</Flex>
</Tooltip>
</SegmentedControl.Item>
<SegmentedControl.Item value={`${TankopediaDisplay.StaticArmor}`}>
<Tooltip content="Static armor">
<Tooltip
content={strings.website.tools.tankopedia.sandbox.static.name}
>
<Flex height="100%" align="center">
<img src={imgur('VQ4uDno')} style={{ height: '1.25em' }} />
</Flex>
@@ -441,15 +452,15 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
<DropdownMenu.Content>
<DropdownMenu.Item onClick={() => poseEvent.emit(Pose.HullDown)}>
Hull down
{strings.website.tools.tankopedia.sandbox.poses.hull_down}
</DropdownMenu.Item>
<DropdownMenu.Item onClick={() => poseEvent.emit(Pose.FaceHug)}>
Face hug
{strings.website.tools.tankopedia.sandbox.poses.face_hug}
</DropdownMenu.Item>
<DropdownMenu.Item onClick={() => poseEvent.emit(Pose.Default)}>
Default
{strings.website.tools.tankopedia.sandbox.poses.default}
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
@@ -464,7 +475,9 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
<DropdownMenu.Content>
{display === TankopediaDisplay.DynamicArmor && (
<>
<DropdownMenu.Label>Armor</DropdownMenu.Label>
<DropdownMenu.Label>
{strings.website.tools.tankopedia.sandbox.settings.armor}
</DropdownMenu.Label>
<DropdownMenu.CheckboxItem
checked={greenPenetration}
@@ -474,7 +487,10 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
});
}}
>
Green penetration
{
strings.website.tools.tankopedia.sandbox.settings
.green_penetration
}
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
@@ -485,7 +501,10 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
});
}}
>
Hide tank model under armor
{
strings.website.tools.tankopedia.sandbox.settings
.hide_model_under_armor
}
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
@@ -496,7 +515,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
});
}}
>
Opaque
{strings.website.tools.tankopedia.sandbox.settings.opaque}
</DropdownMenu.CheckboxItem>
{developerMode && (
@@ -508,13 +527,18 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
});
}}
>
<b>DEV:</b> Wireframe
{
strings.website.tools.tankopedia.sandbox.settings
.dev_wireframe
}
</DropdownMenu.CheckboxItem>
)}
</>
)}
<DropdownMenu.Label>Environment</DropdownMenu.Label>
<DropdownMenu.Label>
{strings.website.tools.tankopedia.sandbox.settings.environment}
</DropdownMenu.Label>
<DropdownMenu.CheckboxItem
checked={showGrid}
@@ -524,7 +548,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
});
}}
>
Show grid
{strings.website.tools.tankopedia.sandbox.settings.show_grid}
</DropdownMenu.CheckboxItem>
</DropdownMenu.Content>
</DropdownMenu.Root>
@@ -557,7 +581,10 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
}}
>
<DownloadIcon />
Download
{
strings.website.tools.tankopedia.sandbox.screenshot
.download
}
</Button>
</Popover.Close>
<Popover.Close>
@@ -576,7 +603,7 @@ export function Options({ thicknessRange, canvas }: OptionsProps) {
}}
>
<CopyIcon />
Copy
{strings.website.tools.tankopedia.sandbox.screenshot.copy}
</Button>
</Popover.Close>
</Flex>