mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: effective and persistent angle
This commit is contained in:
1 parent
bbe682fa73
commit
5b8da36fb8
11 files changed
+77
-33
No files matched your search
@@ -12,7 +12,8 @@
|
||||
"deg": "%s1°",
|
||||
"hp": "%s1hp",
|
||||
"x": "x%s1",
|
||||
"percentage": "%s1%"
|
||||
"percentage": "%s1%",
|
||||
"deg_s": "%s1°/s"
|
||||
},
|
||||
|
||||
"gun_types": {
|
||||
@@ -885,7 +886,8 @@
|
||||
"turret": "Turret",
|
||||
"hard": "Hard",
|
||||
"medium": "Medium",
|
||||
"soft": "Soft"
|
||||
"soft": "Soft",
|
||||
"effective": "Effective"
|
||||
},
|
||||
|
||||
"ricochet": {
|
||||
|
||||
+1
-1
@@ -7,9 +7,9 @@ import { awaitableProvisionDefinitions } from '../../../../../../core/awaitables
|
||||
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
||||
import { Duel } from '../../../../../../stores/duel';
|
||||
import type { StatsAcceptorProps } from './HullTraverseVisualizer';
|
||||
import { InfoWithDelta } from './InfoWithDelta';
|
||||
import { StatsTableWrapper } from './StatsTableWrapper';
|
||||
import type { StatsAcceptorProps } from './TraverseVisualizer';
|
||||
|
||||
const provisionDefinitions = await awaitableProvisionDefinitions;
|
||||
|
||||
|
||||
+1
-1
@@ -21,11 +21,11 @@ import { useEquipment } from '../../../../../../hooks/useEquipment';
|
||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
||||
import { useTankModelDefinition } from '../../../../../../hooks/useTankModelDefinition';
|
||||
import { Duel } from '../../../../../../stores/duel';
|
||||
import type { StatsAcceptorProps } from './HullTraverseVisualizer';
|
||||
import { Info } from './Info';
|
||||
import { InfoWithDelta } from './InfoWithDelta';
|
||||
import { RicochetVisualizer } from './RicochetVisualizer';
|
||||
import { StatsTableWrapper } from './StatsTableWrapper';
|
||||
import type { StatsAcceptorProps } from './TraverseVisualizer';
|
||||
|
||||
export function Firepower({ stats }: StatsAcceptorProps) {
|
||||
const mutateDuel = Duel.useMutation();
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: translate(-50%, -50%) rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate(-50%, -50%) rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.hull-traverse-visualizer {
|
||||
animation: spin linear infinite;
|
||||
}
|
||||
+5
-5
@@ -1,12 +1,12 @@
|
||||
import { Heading } from '@radix-ui/themes';
|
||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
||||
import {
|
||||
HullTraverseVisualizer,
|
||||
type StatsAcceptorProps,
|
||||
} from './HullTraverseVisualizer';
|
||||
import { Info } from './Info';
|
||||
import { InfoWithDelta } from './InfoWithDelta';
|
||||
import { StatsTableWrapper } from './StatsTableWrapper';
|
||||
import {
|
||||
TraverseVisualizer,
|
||||
type StatsAcceptorProps,
|
||||
} from './TraverseVisualizer';
|
||||
|
||||
export function Maneuverability({ stats }: StatsAcceptorProps) {
|
||||
const { strings } = useLocale();
|
||||
@@ -130,7 +130,7 @@ export function Maneuverability({ stats }: StatsAcceptorProps) {
|
||||
value="hullTraverseSoftTerrain"
|
||||
/>
|
||||
|
||||
<HullTraverseVisualizer stats={stats} />
|
||||
<TraverseVisualizer stats={stats} />
|
||||
</StatsTableWrapper>
|
||||
);
|
||||
}
|
||||
+1
-1
@@ -3,7 +3,7 @@ import type { QuicklimeCallback } from 'quicklime';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { reloadUpdate, type ReloadUpdateData } from '..';
|
||||
import { Var } from '../../../../../../../../core/radix/var';
|
||||
import type { StatsAcceptorProps } from '../../HullTraverseVisualizer';
|
||||
import type { StatsAcceptorProps } from '../../TraverseVisualizer';
|
||||
import { ShellBorder } from './ShellBorder';
|
||||
|
||||
interface ShellProps {
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { times } from 'lodash-es';
|
||||
import { Quicklime, type QuicklimeCallback } from 'quicklime';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Var } from '../../../../../../../core/radix/var';
|
||||
import type { StatsAcceptorProps } from '../HullTraverseVisualizer';
|
||||
import type { StatsAcceptorProps } from '../TraverseVisualizer';
|
||||
import { Shell } from './components/Shell';
|
||||
import { Target } from './components/Target';
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import { clamp, degToRad, radToDeg } from 'three/src/math/MathUtils.js';
|
||||
import { Var } from '../../../../../../../core/radix/var';
|
||||
import { useLocale } from '../../../../../../../hooks/useLocale';
|
||||
import { Duel } from '../../../../../../../stores/duel';
|
||||
import type { StatsAcceptorProps } from '../HullTraverseVisualizer';
|
||||
import type { StatsAcceptorProps } from '../TraverseVisualizer';
|
||||
import { ShellSwitcher } from './components/ShellSwitcher';
|
||||
|
||||
export function RicochetVisualizer({ stats }: StatsAcceptorProps) {
|
||||
|
||||
+1
-1
@@ -1,9 +1,9 @@
|
||||
import { Heading } from '@radix-ui/themes';
|
||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
||||
import type { StatsAcceptorProps } from './HullTraverseVisualizer';
|
||||
import { Info } from './Info';
|
||||
import { InfoWithDelta } from './InfoWithDelta';
|
||||
import { StatsTableWrapper } from './StatsTableWrapper';
|
||||
import type { StatsAcceptorProps } from './TraverseVisualizer';
|
||||
import { ViewRangeVisualizer } from './ViewRangeVisualizer';
|
||||
|
||||
export function Survivability({ stats }: StatsAcceptorProps) {
|
||||
|
||||
+61
-6
@@ -1,8 +1,8 @@
|
||||
import { Card, Checkbox, Flex, Tabs, Text } from '@radix-ui/themes';
|
||||
import { useRef, useState } from 'react';
|
||||
import { literals } from '@blitzkit/i18n';
|
||||
import { Card, Checkbox, Code, Flex, Tabs, Text } from '@radix-ui/themes';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import type { TankCharacteristics } from '../../../../../../../core/blitzkit/tankCharacteristics';
|
||||
import { useLocale } from '../../../../../../../hooks/useLocale';
|
||||
import './index.css';
|
||||
|
||||
export interface StatsAcceptorProps {
|
||||
stats: TankCharacteristics;
|
||||
@@ -10,7 +10,7 @@ export interface StatsAcceptorProps {
|
||||
|
||||
type Terrain = 'Hard' | 'Medium' | 'Soft';
|
||||
|
||||
export function HullTraverseVisualizer({ stats }: StatsAcceptorProps) {
|
||||
export function TraverseVisualizer({ stats }: StatsAcceptorProps) {
|
||||
const hull = useRef<HTMLDivElement>(null);
|
||||
const turret = useRef<HTMLImageElement>(null);
|
||||
const [terrain, setTerrain] = useState<Terrain>('Hard');
|
||||
@@ -19,12 +19,46 @@ export function HullTraverseVisualizer({ stats }: StatsAcceptorProps) {
|
||||
const { strings } = useLocale();
|
||||
const isTurretless =
|
||||
stats.azimuthLeft !== undefined || stats.azimuthRight !== undefined;
|
||||
const turretAngle = useRef(0);
|
||||
const hullAngle = useRef(0);
|
||||
const turretSpeedDeg = rotateTurret ? stats.turretTraverseSpeed : 0;
|
||||
const hullSpeedDeg = rotateHull ? stats[`hullTraverse${terrain}Terrain`] : 0;
|
||||
|
||||
useEffect(() => {
|
||||
let cancel = false;
|
||||
const turretSpeedRad = turretSpeedDeg * (Math.PI / 180);
|
||||
const hullTraverseRad = hullSpeedDeg * (Math.PI / 180);
|
||||
let lastT = Date.now() / 1000;
|
||||
|
||||
function frame() {
|
||||
if (!turret.current || !hull.current) return;
|
||||
|
||||
const t = Date.now() / 1000;
|
||||
const dt = t - lastT;
|
||||
lastT = t;
|
||||
|
||||
turretAngle.current =
|
||||
(turretAngle.current + turretSpeedRad * dt) % (2 * Math.PI);
|
||||
hullAngle.current =
|
||||
(hullAngle.current + hullTraverseRad * dt) % (2 * Math.PI);
|
||||
|
||||
turret.current.style.transform = `translate(-50%, -50%) rotate(${-turretAngle.current}rad)`;
|
||||
hull.current.style.transform = `translate(-50%, -50%) rotate(${-hullAngle.current}rad)`;
|
||||
|
||||
if (!cancel) requestAnimationFrame(frame);
|
||||
}
|
||||
|
||||
frame();
|
||||
|
||||
return () => {
|
||||
cancel = true;
|
||||
};
|
||||
}, [terrain, turretSpeedDeg, hullSpeedDeg]);
|
||||
|
||||
return (
|
||||
<Card variant="classic" style={{ aspectRatio: '1 / 1' }}>
|
||||
<div
|
||||
ref={hull}
|
||||
className="hull-traverse-visualizer"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
@@ -50,7 +84,6 @@ export function HullTraverseVisualizer({ stats }: StatsAcceptorProps) {
|
||||
<img
|
||||
draggable="false"
|
||||
ref={turret}
|
||||
className="hull-traverse-visualizer"
|
||||
style={{
|
||||
width: '27rem',
|
||||
height: '27rem',
|
||||
@@ -95,12 +128,34 @@ export function HullTraverseVisualizer({ stats }: StatsAcceptorProps) {
|
||||
</Tabs.Root>
|
||||
</Flex>
|
||||
|
||||
<Flex
|
||||
gap="2"
|
||||
position="absolute"
|
||||
left="50%"
|
||||
bottom="7"
|
||||
style={{
|
||||
transform: 'translateX(-50%)',
|
||||
}}
|
||||
>
|
||||
<Text color="gray" size="1">
|
||||
{strings.website.tools.tankopedia.visualizers.rotator.effective}
|
||||
</Text>
|
||||
<Code size="1" variant="ghost">
|
||||
{literals(strings.common.units.deg_s, [
|
||||
`${(turretSpeedDeg + hullSpeedDeg).toFixed(1)}`,
|
||||
])}
|
||||
</Code>
|
||||
</Flex>
|
||||
|
||||
{!isTurretless && (
|
||||
<Flex
|
||||
position="absolute"
|
||||
top="4"
|
||||
left="50%"
|
||||
width="100%"
|
||||
px="5"
|
||||
gap="5"
|
||||
justify="center"
|
||||
style={{
|
||||
transform: 'translateX(-50%)',
|
||||
userSelect: 'none',
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { Box, Card, Code, Flex, Slider, Tabs, Text } from '@radix-ui/themes';
|
||||
import { useRef, useState } from 'react';
|
||||
import { Var } from '../../../../../../core/radix/var';
|
||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
||||
import type { StatsAcceptorProps } from './HullTraverseVisualizer';
|
||||
import type { StatsAcceptorProps } from './TraverseVisualizer';
|
||||
|
||||
const maps = [
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user