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