feat: turretless support

This commit is contained in:
tresabhi committed 2025-04-22 13:10:01 -05:00
1 parent 9c027b3dde
commit 2443ecde2f
7 files changed
+116 -63

No files matched your search

+1
View File
@@ -184,6 +184,7 @@
"TEXCOORD", "TEXCOORD",
"tresabhi", "tresabhi",
"tungstentip", "tungstentip",
"Turretless",
"TYPELESS", "TYPELESS",
"ubjson", "ubjson",
"Unicum", "Unicum",
+2 -2
View File
@@ -871,8 +871,8 @@
}, },
"ricochet": { "ricochet": {
"safe": "Safe %s1°", "safe": "Safe <%s1°",
"unsafe": "Unsafe %s1°" "unsafe": "Unsafe ≥%s1°"
} }
}, },
Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

@@ -15,7 +15,7 @@ export function MissingShellIcon(props: ComponentProps<'svg'>) {
stroke="currentColor" stroke="currentColor"
strokeWidth="4" strokeWidth="4"
strokeLinecap="round" strokeLinecap="round"
stroke-linejoin="round" strokeLinejoin="round"
/> />
</svg> </svg>
); );
@@ -17,6 +17,8 @@ export function HullTraverseVisualizer({ stats }: VisualizerProps) {
const [rotateHull, setRotateHull] = useState(true); const [rotateHull, setRotateHull] = useState(true);
const [rotateTurret, setRotateTurret] = useState(true); const [rotateTurret, setRotateTurret] = useState(true);
const { strings } = useLocale(); const { strings } = useLocale();
const isTurretless =
stats.azimuthLeft !== undefined || stats.azimuthRight !== undefined;
return ( return (
<Card variant="classic" style={{ aspectRatio: '1 / 1' }}> <Card variant="classic" style={{ aspectRatio: '1 / 1' }}>
@@ -35,32 +37,34 @@ export function HullTraverseVisualizer({ stats }: VisualizerProps) {
> >
<img <img
style={{ style={{
width: '12rem', width: isTurretless ? '22rem' : '12rem',
height: '12rem', height: isTurretless ? '22rem' : '12rem',
objectFit: 'contain', objectFit: 'contain',
filter: 'drop-shadow(0px 0px 4px black)', filter: 'drop-shadow(0px 0px 4px black)',
}} }}
src="/assets/images/tankopedia/visualizers/hull-traverse/hull.png" src={`/assets/images/tankopedia/visualizers/hull-traverse/hull${isTurretless ? '-only' : ''}.png`}
/> />
<img {!isTurretless && (
ref={turret} <img
className="hull-traverse-visualizer" ref={turret}
style={{ className="hull-traverse-visualizer"
width: '27rem', style={{
height: '27rem', width: '27rem',
objectFit: 'contain', height: '27rem',
position: 'absolute', objectFit: 'contain',
top: '50%', position: 'absolute',
left: '50%', top: '50%',
filter: 'drop-shadow(0px 0px 4px black)', left: '50%',
transform: 'translate(-50%, -50%)', filter: 'drop-shadow(0px 0px 4px black)',
animationDuration: `${ transform: 'translate(-50%, -50%)',
rotateTurret ? 1 / (stats.turretTraverseSpeed / 360) : 0 animationDuration: `${
}s`, rotateTurret ? 1 / (stats.turretTraverseSpeed / 360) : 0
}} }s`,
src="/assets/images/tankopedia/visualizers/hull-traverse/turret.png" }}
/> src="/assets/images/tankopedia/visualizers/hull-traverse/turret.png"
/>
)}
</div> </div>
<Flex <Flex
@@ -89,40 +93,42 @@ export function HullTraverseVisualizer({ stats }: VisualizerProps) {
</Tabs.Root> </Tabs.Root>
</Flex> </Flex>
<Flex {!isTurretless && (
position="absolute"
top="4"
left="50%"
gap="5"
style={{
transform: 'translateX(-50%)',
userSelect: 'none',
}}
>
<Flex <Flex
align="center" position="absolute"
gap="2" top="4"
onClick={() => setRotateHull((state) => !state)} left="50%"
style={{ cursor: 'pointer' }} gap="5"
style={{
transform: 'translateX(-50%)',
userSelect: 'none',
}}
> >
<Checkbox variant="classic" checked={rotateHull} /> <Flex
<Text size="2"> align="center"
{strings.website.tools.tankopedia.visualizers.rotator.hull} gap="2"
</Text> onClick={() => setRotateHull((state) => !state)}
</Flex> style={{ cursor: 'pointer' }}
>
<Checkbox variant="classic" checked={rotateHull} />
<Text size="2">
{strings.website.tools.tankopedia.visualizers.rotator.hull}
</Text>
</Flex>
<Flex <Flex
align="center" align="center"
gap="2" gap="2"
onClick={() => setRotateTurret((state) => !state)} onClick={() => setRotateTurret((state) => !state)}
style={{ cursor: 'pointer' }} style={{ cursor: 'pointer' }}
> >
<Checkbox variant="classic" checked={rotateTurret} /> <Checkbox variant="classic" checked={rotateTurret} />
<Text size="2"> <Text size="2">
{strings.website.tools.tankopedia.visualizers.rotator.turret} {strings.website.tools.tankopedia.visualizers.rotator.turret}
</Text> </Text>
</Flex>
</Flex> </Flex>
</Flex> )}
</Card> </Card>
); );
} }
@@ -9,7 +9,7 @@
} }
.ricochet-visualizer-penetrating-shell { .ricochet-visualizer-penetrating-shell {
animation: penetrating-shell-slide 3s infinite; animation: penetrating-shell-slide infinite;
} }
@keyframes ricocheting-shell-slide { @keyframes ricocheting-shell-slide {
@@ -44,11 +44,11 @@
} }
.ricochet-visualizer-ricocheting-shell { .ricochet-visualizer-ricocheting-shell {
animation: ricocheting-shell-slide 3s infinite; animation: ricocheting-shell-slide infinite;
} }
.ricochet-visualizer-ricocheting-shell-container { .ricochet-visualizer-ricocheting-shell-container {
animation: ricocheting-shell-slide-container 3s infinite; animation: ricocheting-shell-slide-container infinite;
} }
@keyframes surface-impact { @keyframes surface-impact {
@@ -72,7 +72,7 @@
} }
.ricochet-visualizer-surface-impact { .ricochet-visualizer-surface-impact {
animation: surface-impact 3s linear infinite; animation: surface-impact linear infinite;
} }
@keyframes puncture { @keyframes puncture {
@@ -94,5 +94,41 @@
} }
.ricochet-visualizer-puncture { .ricochet-visualizer-puncture {
animation: puncture 3s infinite; animation: puncture infinite;
}
@keyframes safe {
0% {
opacity: 0;
}
5%,
28% {
opacity: 1;
}
33%,
100% {
opacity: 0;
}
}
.ricochet-visualizer-safe {
animation: safe infinite;
}
@keyframes unsafe {
0%,
33% {
opacity: 0;
}
38%,
95% {
opacity: 1;
}
100% {
opacity: 0;
}
}
.ricochet-visualizer-unsafe {
animation: unsafe infinite;
} }
@@ -11,6 +11,7 @@ export function RicochetVisualizer({ stats }: VisualizerProps) {
const ricochet = stats.shellRicochet ?? 90; const ricochet = stats.shellRicochet ?? 90;
const shell = Duel.use((state) => state.protagonist.shell); const shell = Duel.use((state) => state.protagonist.shell);
const { strings } = useLocale(); const { strings } = useLocale();
const animationDuration = '6s';
return ( return (
<Card <Card
@@ -54,6 +55,7 @@ export function RicochetVisualizer({ stats }: VisualizerProps) {
height="6rem" height="6rem"
style={{ style={{
background: `linear-gradient(${Var('gray-1')}, ${Var('gray-a1')})`, background: `linear-gradient(${Var('gray-1')}, ${Var('gray-a1')})`,
animationDuration,
}} }}
/> />
</Box> </Box>
@@ -77,7 +79,7 @@ export function RicochetVisualizer({ stats }: VisualizerProps) {
conic-gradient( conic-gradient(
from -90deg at 25% 100%, from -90deg at 25% 100%,
transparent ${90 - ricochet}deg, transparent ${90 - ricochet}deg,
${Var('jade-a3')} ${90 - ricochet}deg, ${Var('jade-a7')} ${90 - ricochet}deg,
${Var('jade-9')} ${90 + ricochet}deg, ${Var('jade-9')} ${90 + ricochet}deg,
${Var('tomato-8')} ${90 + ricochet}deg, ${Var('tomato-8')} ${90 + ricochet}deg,
${Var('tomato-a3')} 180deg, ${Var('tomato-a3')} 180deg,
@@ -121,7 +123,7 @@ export function RicochetVisualizer({ stats }: VisualizerProps) {
style={{ style={{
transformOrigin: 'bottom center', transformOrigin: 'bottom center',
transform: `translateX(-50%) rotate(-${ricochet}deg)`, transform: `translateX(-50%) rotate(-${ricochet}deg)`,
background: `repeating-linear-gradient(${Var('gray-10')}, ${Var('gray-a3')} 15px, transparent 15px, transparent 30px)`, background: `repeating-linear-gradient(${Var('gray-11')}, ${Var('gray-a3')} 15px, transparent 15px, transparent 30px)`,
}} }}
/> />
@@ -134,6 +136,7 @@ export function RicochetVisualizer({ stats }: VisualizerProps) {
transform: `translate(-50%, 50%) rotate(${ricochet}deg)`, transform: `translate(-50%, 50%) rotate(${ricochet}deg)`,
background: `radial-gradient(${Var('gray-a2')}, ${Var('gray-a9')})`, background: `radial-gradient(${Var('gray-a2')}, ${Var('gray-a9')})`,
borderRadius: '50%', borderRadius: '50%',
animationDuration,
}} }}
/> />
@@ -157,6 +160,7 @@ export function RicochetVisualizer({ stats }: VisualizerProps) {
width: '100%', width: '100%',
height: '100%', height: '100%',
position: 'absolute', position: 'absolute',
animationDuration,
}} }}
/> />
</Box> </Box>
@@ -170,6 +174,7 @@ export function RicochetVisualizer({ stats }: VisualizerProps) {
bottom="0" bottom="0"
style={{ style={{
transformOrigin: 'bottom center', transformOrigin: 'bottom center',
animationDuration,
}} }}
> >
<img <img
@@ -181,6 +186,7 @@ export function RicochetVisualizer({ stats }: VisualizerProps) {
width: '100%', width: '100%',
height: '100%', height: '100%',
position: 'absolute', position: 'absolute',
animationDuration,
}} }}
/> />
</Box> </Box>
@@ -192,11 +198,13 @@ export function RicochetVisualizer({ stats }: VisualizerProps) {
left: '30%', left: '30%',
bottom: '40%', bottom: '40%',
transform: 'translateX(-50%)', transform: 'translateX(-50%)',
animationDuration,
}} }}
className="ricochet-visualizer-safe"
> >
{literals( {literals(
strings.website.tools.tankopedia.visualizers.ricochet.safe, strings.website.tools.tankopedia.visualizers.ricochet.safe,
[(2 * ricochet).toFixed(0)], [ricochet.toFixed(0)],
)} )}
</Text> </Text>
@@ -206,11 +214,13 @@ export function RicochetVisualizer({ stats }: VisualizerProps) {
position: 'absolute', position: 'absolute',
right: '5%', right: '5%',
bottom: '12%', bottom: '12%',
animationDuration,
}} }}
className="ricochet-visualizer-unsafe"
> >
{literals( {literals(
strings.website.tools.tankopedia.visualizers.ricochet.unsafe, strings.website.tools.tankopedia.visualizers.ricochet.unsafe,
[(90 - ricochet).toFixed(0)], [ricochet.toFixed(0)],
)} )}
</Text> </Text>
</Box> </Box>