mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: ricochet visualizer
This commit is contained in:
1 parent
a66c6ebb27
commit
c7f781dbb2
6 files changed
+141
-18
No files matched your search
@@ -868,6 +868,10 @@
|
|||||||
"hard": "Hard",
|
"hard": "Hard",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"soft": "Soft"
|
"soft": "Soft"
|
||||||
|
},
|
||||||
|
|
||||||
|
"ricochet": {
|
||||||
|
"max": "Max: %s1°"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 97 B |
+2
-2
@@ -4,13 +4,13 @@ import type { TankCharacteristics } from '../../../../../../../core/blitzkit/tan
|
|||||||
import { useLocale } from '../../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../../hooks/useLocale';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
interface HullTraverseVisualizerProps {
|
export interface VisualizerProps {
|
||||||
stats: TankCharacteristics;
|
stats: TankCharacteristics;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Terrain = 'Hard' | 'Medium' | 'Soft';
|
type Terrain = 'Hard' | 'Medium' | 'Soft';
|
||||||
|
|
||||||
export function HullTraverseVisualizer({ stats }: HullTraverseVisualizerProps) {
|
export function HullTraverseVisualizer({ stats }: VisualizerProps) {
|
||||||
const hull = useRef<HTMLDivElement>(null);
|
const hull = useRef<HTMLDivElement>(null);
|
||||||
const turret = useRef<HTMLImageElement>(null);
|
const turret = useRef<HTMLImageElement>(null);
|
||||||
const [terrain, setTerrain] = useState<Terrain>('Hard');
|
const [terrain, setTerrain] = useState<Terrain>('Hard');
|
||||||
|
|||||||
+114
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
+20
-15
@@ -34,6 +34,7 @@ import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral';
|
|||||||
import { HullTraverseVisualizer } from './components/HullTraverseVisualizer';
|
import { HullTraverseVisualizer } from './components/HullTraverseVisualizer';
|
||||||
import { Info } from './components/Info';
|
import { Info } from './components/Info';
|
||||||
import { InfoWithDelta } from './components/InfoWithDelta';
|
import { InfoWithDelta } from './components/InfoWithDelta';
|
||||||
|
import { RicochetVisualizer } from './components/RicochetVisuazlizer';
|
||||||
|
|
||||||
const [equipmentDefinitions, provisionDefinitions] = await Promise.all([
|
const [equipmentDefinitions, provisionDefinitions] = await Promise.all([
|
||||||
awaitableEquipmentDefinitions,
|
awaitableEquipmentDefinitions,
|
||||||
@@ -368,22 +369,26 @@ export function Characteristics() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<InfoWithDelta stats={stats} decimals={0} unit="mm" value="caliber" />
|
<InfoWithDelta stats={stats} decimals={0} unit="mm" value="caliber" />
|
||||||
<InfoWithDelta
|
|
||||||
stats={stats}
|
|
||||||
decimals={0}
|
|
||||||
unit="°"
|
|
||||||
noRanking
|
|
||||||
value="shellNormalization"
|
|
||||||
/>
|
|
||||||
{!isExplosive(shell.type) && (
|
{!isExplosive(shell.type) && (
|
||||||
<InfoWithDelta
|
<>
|
||||||
stats={stats}
|
<InfoWithDelta
|
||||||
noRanking
|
stats={stats}
|
||||||
decimals={0}
|
decimals={0}
|
||||||
deltaType="lowerIsBetter"
|
unit="°"
|
||||||
unit="°"
|
noRanking
|
||||||
value="shellRicochet"
|
value="shellNormalization"
|
||||||
/>
|
/>
|
||||||
|
<InfoWithDelta
|
||||||
|
stats={stats}
|
||||||
|
noRanking
|
||||||
|
decimals={0}
|
||||||
|
deltaType="lowerIsBetter"
|
||||||
|
unit="°"
|
||||||
|
value="shellRicochet"
|
||||||
|
/>
|
||||||
|
<RicochetVisualizer stats={stats} />
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
<InfoWithDelta
|
<InfoWithDelta
|
||||||
stats={stats}
|
stats={stats}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export function MetaSection() {
|
|||||||
style={{
|
style={{
|
||||||
background: `url(${asset(`flags/scratched/${protagonist.nation}.webp`)})`,
|
background: `url(${asset(`flags/scratched/${protagonist.nation}.webp`)})`,
|
||||||
backgroundRepeat: 'no-repeat',
|
backgroundRepeat: 'no-repeat',
|
||||||
backgroundSize: '53rem',
|
backgroundSize: 'min(53rem, 80vw)',
|
||||||
backgroundPosition: '-8rem 50%',
|
backgroundPosition: '-8rem 50%',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in new issue
Block a user