feat: ricochet visualizer

This commit is contained in:
tresabhi committed 2025-04-21 18:09:57 -05:00
1 parent a66c6ebb27
commit c7f781dbb2
6 files changed
+141 -18

No files matched your search

+4
View File
@@ -868,6 +868,10 @@
"hard": "Hard",
"medium": "Medium",
"soft": "Soft"
},
"ricochet": {
"max": "Max: %s1°"
}
},
Binary file not shown.

After

Width:  |  Height:  |  Size: 97 B

@@ -4,13 +4,13 @@ import type { TankCharacteristics } from '../../../../../../../core/blitzkit/tan
import { useLocale } from '../../../../../../../hooks/useLocale';
import './index.css';
interface HullTraverseVisualizerProps {
export interface VisualizerProps {
stats: TankCharacteristics;
}
type Terrain = 'Hard' | 'Medium' | 'Soft';
export function HullTraverseVisualizer({ stats }: HullTraverseVisualizerProps) {
export function HullTraverseVisualizer({ stats }: VisualizerProps) {
const hull = useRef<HTMLDivElement>(null);
const turret = useRef<HTMLImageElement>(null);
const [terrain, setTerrain] = useState<Terrain>('Hard');
@@ -0,0 +1,114 @@
import { asset } from '@blitzkit/core';
import { literals } from '@blitzkit/i18n';
import { Box, Card, Text } from '@radix-ui/themes';
import { Var } from '../../../../../../core/radix/var';
import { useLocale } from '../../../../../../hooks/useLocale';
import { Duel } from '../../../../../../stores/duel';
import type { VisualizerProps } from './HullTraverseVisualizer';
export function RicochetVisualizer({ stats }: VisualizerProps) {
const ricochet = stats.shellRicochet ?? 90;
const normalization = stats.shellNormalization;
const shell = Duel.use((state) => state.protagonist.shell);
const { strings } = useLocale();
return (
<Card
variant="classic"
style={{
aspectRatio: '2 / 1',
}}
mb="6"
>
<Box
width="100%"
height="calc(100% * 2 / 3)"
position="absolute"
top="0"
left="0"
style={{
backgroundColor: Var('gray-11'),
overflow: 'hidden',
}}
>
<Box
width="100%"
height="100%"
style={{
background: `
conic-gradient(
from -90deg at 25% 100%,
transparent 0deg ${90 - ricochet - normalization}deg,
${Var('jade-a1')} ${90 - ricochet - normalization}deg ${90 - ricochet - normalization}deg,
${Var('jade-11')} ${90 + ricochet}deg,
${Var('amber-9')} ${90 + ricochet}deg ${90 + ricochet + normalization}deg,
${Var('tomato-10')} ${90 + ricochet + normalization}deg,
${Var('tomato-11')} 180deg,
transparent 180deg
)
`,
}}
/>
<Box
position="absolute"
bottom="0"
left="25%"
width="3rem"
height="3rem"
style={{
transform: `translate(-50%, 50%) rotate(${ricochet + normalization}deg)`,
background: `radial-gradient(${Var('gray-a5')}, ${Var('gray-a11')})`,
borderRadius: '50%',
}}
>
<img
src={asset(`icons/shells/${shell.icon}.webp`)}
style={{
width: '2rem',
height: '2rem',
objectFit: 'contain',
transform: 'translate(-50%, -50%) rotate(135deg)',
position: 'absolute',
top: '-10rem',
left: '50%',
}}
/>
</Box>
</Box>
<Box
width="100%"
height="calc(100% / 3)"
position="absolute"
bottom="0"
left="0"
style={{
background: `linear-gradient(${Var('gray-a4')}, ${Var('gray-a1')})`,
}}
>
<Box
width="100%"
height="100%"
style={{
opacity: 2 ** -4,
backgroundImage: `url(/assets/images/tankopedia/visualizers/ricochet/armor-hash.png)`,
}}
/>
<Text
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
}}
color="gray"
>
{literals(strings.website.tools.tankopedia.visualizers.ricochet.max, [
(ricochet + normalization).toFixed(0),
])}
</Text>
</Box>
</Card>
);
}
@@ -34,6 +34,7 @@ import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral';
import { HullTraverseVisualizer } from './components/HullTraverseVisualizer';
import { Info } from './components/Info';
import { InfoWithDelta } from './components/InfoWithDelta';
import { RicochetVisualizer } from './components/RicochetVisuazlizer';
const [equipmentDefinitions, provisionDefinitions] = await Promise.all([
awaitableEquipmentDefinitions,
@@ -368,22 +369,26 @@ export function Characteristics() {
/>
)}
<InfoWithDelta stats={stats} decimals={0} unit="mm" value="caliber" />
<InfoWithDelta
stats={stats}
decimals={0}
unit="°"
noRanking
value="shellNormalization"
/>
{!isExplosive(shell.type) && (
<InfoWithDelta
stats={stats}
noRanking
decimals={0}
deltaType="lowerIsBetter"
unit="°"
value="shellRicochet"
/>
<>
<InfoWithDelta
stats={stats}
decimals={0}
unit="°"
noRanking
value="shellNormalization"
/>
<InfoWithDelta
stats={stats}
noRanking
decimals={0}
deltaType="lowerIsBetter"
unit="°"
value="shellRicochet"
/>
<RicochetVisualizer stats={stats} />
</>
)}
<InfoWithDelta
stats={stats}
@@ -41,7 +41,7 @@ export function MetaSection() {
style={{
background: `url(${asset(`flags/scratched/${protagonist.nation}.webp`)})`,
backgroundRepeat: 'no-repeat',
backgroundSize: '53rem',
backgroundSize: 'min(53rem, 80vw)',
backgroundPosition: '-8rem 50%',
}}
>