mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +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°",
|
"deg": "%s1°",
|
||||||
"hp": "%s1hp",
|
"hp": "%s1hp",
|
||||||
"x": "x%s1",
|
"x": "x%s1",
|
||||||
"percentage": "%s1%"
|
"percentage": "%s1%",
|
||||||
|
"deg_s": "%s1°/s"
|
||||||
},
|
},
|
||||||
|
|
||||||
"gun_types": {
|
"gun_types": {
|
||||||
@@ -885,7 +886,8 @@
|
|||||||
"turret": "Turret",
|
"turret": "Turret",
|
||||||
"hard": "Hard",
|
"hard": "Hard",
|
||||||
"medium": "Medium",
|
"medium": "Medium",
|
||||||
"soft": "Soft"
|
"soft": "Soft",
|
||||||
|
"effective": "Effective"
|
||||||
},
|
},
|
||||||
|
|
||||||
"ricochet": {
|
"ricochet": {
|
||||||
|
|||||||
+1
-1
@@ -7,9 +7,9 @@ import { awaitableProvisionDefinitions } from '../../../../../../core/awaitables
|
|||||||
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
||||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../hooks/useLocale';
|
||||||
import { Duel } from '../../../../../../stores/duel';
|
import { Duel } from '../../../../../../stores/duel';
|
||||||
import type { StatsAcceptorProps } from './HullTraverseVisualizer';
|
|
||||||
import { InfoWithDelta } from './InfoWithDelta';
|
import { InfoWithDelta } from './InfoWithDelta';
|
||||||
import { StatsTableWrapper } from './StatsTableWrapper';
|
import { StatsTableWrapper } from './StatsTableWrapper';
|
||||||
|
import type { StatsAcceptorProps } from './TraverseVisualizer';
|
||||||
|
|
||||||
const provisionDefinitions = await awaitableProvisionDefinitions;
|
const provisionDefinitions = await awaitableProvisionDefinitions;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -21,11 +21,11 @@ import { useEquipment } from '../../../../../../hooks/useEquipment';
|
|||||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../hooks/useLocale';
|
||||||
import { useTankModelDefinition } from '../../../../../../hooks/useTankModelDefinition';
|
import { useTankModelDefinition } from '../../../../../../hooks/useTankModelDefinition';
|
||||||
import { Duel } from '../../../../../../stores/duel';
|
import { Duel } from '../../../../../../stores/duel';
|
||||||
import type { StatsAcceptorProps } from './HullTraverseVisualizer';
|
|
||||||
import { Info } from './Info';
|
import { Info } from './Info';
|
||||||
import { InfoWithDelta } from './InfoWithDelta';
|
import { InfoWithDelta } from './InfoWithDelta';
|
||||||
import { RicochetVisualizer } from './RicochetVisualizer';
|
import { RicochetVisualizer } from './RicochetVisualizer';
|
||||||
import { StatsTableWrapper } from './StatsTableWrapper';
|
import { StatsTableWrapper } from './StatsTableWrapper';
|
||||||
|
import type { StatsAcceptorProps } from './TraverseVisualizer';
|
||||||
|
|
||||||
export function Firepower({ stats }: StatsAcceptorProps) {
|
export function Firepower({ stats }: StatsAcceptorProps) {
|
||||||
const mutateDuel = Duel.useMutation();
|
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 { Heading } from '@radix-ui/themes';
|
||||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../hooks/useLocale';
|
||||||
import {
|
|
||||||
HullTraverseVisualizer,
|
|
||||||
type StatsAcceptorProps,
|
|
||||||
} from './HullTraverseVisualizer';
|
|
||||||
import { Info } from './Info';
|
import { Info } from './Info';
|
||||||
import { InfoWithDelta } from './InfoWithDelta';
|
import { InfoWithDelta } from './InfoWithDelta';
|
||||||
import { StatsTableWrapper } from './StatsTableWrapper';
|
import { StatsTableWrapper } from './StatsTableWrapper';
|
||||||
|
import {
|
||||||
|
TraverseVisualizer,
|
||||||
|
type StatsAcceptorProps,
|
||||||
|
} from './TraverseVisualizer';
|
||||||
|
|
||||||
export function Maneuverability({ stats }: StatsAcceptorProps) {
|
export function Maneuverability({ stats }: StatsAcceptorProps) {
|
||||||
const { strings } = useLocale();
|
const { strings } = useLocale();
|
||||||
@@ -130,7 +130,7 @@ export function Maneuverability({ stats }: StatsAcceptorProps) {
|
|||||||
value="hullTraverseSoftTerrain"
|
value="hullTraverseSoftTerrain"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HullTraverseVisualizer stats={stats} />
|
<TraverseVisualizer stats={stats} />
|
||||||
</StatsTableWrapper>
|
</StatsTableWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
+1
-1
@@ -3,7 +3,7 @@ import type { QuicklimeCallback } from 'quicklime';
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { reloadUpdate, type ReloadUpdateData } from '..';
|
import { reloadUpdate, type ReloadUpdateData } from '..';
|
||||||
import { Var } from '../../../../../../../../core/radix/var';
|
import { Var } from '../../../../../../../../core/radix/var';
|
||||||
import type { StatsAcceptorProps } from '../../HullTraverseVisualizer';
|
import type { StatsAcceptorProps } from '../../TraverseVisualizer';
|
||||||
import { ShellBorder } from './ShellBorder';
|
import { ShellBorder } from './ShellBorder';
|
||||||
|
|
||||||
interface ShellProps {
|
interface ShellProps {
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ import { times } from 'lodash-es';
|
|||||||
import { Quicklime, type QuicklimeCallback } from 'quicklime';
|
import { Quicklime, type QuicklimeCallback } from 'quicklime';
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { Var } from '../../../../../../../core/radix/var';
|
import { Var } from '../../../../../../../core/radix/var';
|
||||||
import type { StatsAcceptorProps } from '../HullTraverseVisualizer';
|
import type { StatsAcceptorProps } from '../TraverseVisualizer';
|
||||||
import { Shell } from './components/Shell';
|
import { Shell } from './components/Shell';
|
||||||
import { Target } from './components/Target';
|
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 { Var } from '../../../../../../../core/radix/var';
|
||||||
import { useLocale } from '../../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../../hooks/useLocale';
|
||||||
import { Duel } from '../../../../../../../stores/duel';
|
import { Duel } from '../../../../../../../stores/duel';
|
||||||
import type { StatsAcceptorProps } from '../HullTraverseVisualizer';
|
import type { StatsAcceptorProps } from '../TraverseVisualizer';
|
||||||
import { ShellSwitcher } from './components/ShellSwitcher';
|
import { ShellSwitcher } from './components/ShellSwitcher';
|
||||||
|
|
||||||
export function RicochetVisualizer({ stats }: StatsAcceptorProps) {
|
export function RicochetVisualizer({ stats }: StatsAcceptorProps) {
|
||||||
|
|||||||
+1
-1
@@ -1,9 +1,9 @@
|
|||||||
import { Heading } from '@radix-ui/themes';
|
import { Heading } from '@radix-ui/themes';
|
||||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../hooks/useLocale';
|
||||||
import type { StatsAcceptorProps } from './HullTraverseVisualizer';
|
|
||||||
import { Info } from './Info';
|
import { Info } from './Info';
|
||||||
import { InfoWithDelta } from './InfoWithDelta';
|
import { InfoWithDelta } from './InfoWithDelta';
|
||||||
import { StatsTableWrapper } from './StatsTableWrapper';
|
import { StatsTableWrapper } from './StatsTableWrapper';
|
||||||
|
import type { StatsAcceptorProps } from './TraverseVisualizer';
|
||||||
import { ViewRangeVisualizer } from './ViewRangeVisualizer';
|
import { ViewRangeVisualizer } from './ViewRangeVisualizer';
|
||||||
|
|
||||||
export function Survivability({ stats }: StatsAcceptorProps) {
|
export function Survivability({ stats }: StatsAcceptorProps) {
|
||||||
|
|||||||
+61
-6
@@ -1,8 +1,8 @@
|
|||||||
import { Card, Checkbox, Flex, Tabs, Text } from '@radix-ui/themes';
|
import { literals } from '@blitzkit/i18n';
|
||||||
import { useRef, useState } from 'react';
|
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 type { TankCharacteristics } from '../../../../../../../core/blitzkit/tankCharacteristics';
|
||||||
import { useLocale } from '../../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../../hooks/useLocale';
|
||||||
import './index.css';
|
|
||||||
|
|
||||||
export interface StatsAcceptorProps {
|
export interface StatsAcceptorProps {
|
||||||
stats: TankCharacteristics;
|
stats: TankCharacteristics;
|
||||||
@@ -10,7 +10,7 @@ export interface StatsAcceptorProps {
|
|||||||
|
|
||||||
type Terrain = 'Hard' | 'Medium' | 'Soft';
|
type Terrain = 'Hard' | 'Medium' | 'Soft';
|
||||||
|
|
||||||
export function HullTraverseVisualizer({ stats }: StatsAcceptorProps) {
|
export function TraverseVisualizer({ stats }: StatsAcceptorProps) {
|
||||||
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');
|
||||||
@@ -19,12 +19,46 @@ export function HullTraverseVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
const { strings } = useLocale();
|
const { strings } = useLocale();
|
||||||
const isTurretless =
|
const isTurretless =
|
||||||
stats.azimuthLeft !== undefined || stats.azimuthRight !== undefined;
|
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 (
|
return (
|
||||||
<Card variant="classic" style={{ aspectRatio: '1 / 1' }}>
|
<Card variant="classic" style={{ aspectRatio: '1 / 1' }}>
|
||||||
<div
|
<div
|
||||||
ref={hull}
|
ref={hull}
|
||||||
className="hull-traverse-visualizer"
|
|
||||||
style={{
|
style={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: '50%',
|
top: '50%',
|
||||||
@@ -50,7 +84,6 @@ export function HullTraverseVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
<img
|
<img
|
||||||
draggable="false"
|
draggable="false"
|
||||||
ref={turret}
|
ref={turret}
|
||||||
className="hull-traverse-visualizer"
|
|
||||||
style={{
|
style={{
|
||||||
width: '27rem',
|
width: '27rem',
|
||||||
height: '27rem',
|
height: '27rem',
|
||||||
@@ -95,12 +128,34 @@ export function HullTraverseVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
</Tabs.Root>
|
</Tabs.Root>
|
||||||
</Flex>
|
</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 && (
|
{!isTurretless && (
|
||||||
<Flex
|
<Flex
|
||||||
position="absolute"
|
position="absolute"
|
||||||
top="4"
|
top="4"
|
||||||
left="50%"
|
left="50%"
|
||||||
|
width="100%"
|
||||||
|
px="5"
|
||||||
gap="5"
|
gap="5"
|
||||||
|
justify="center"
|
||||||
style={{
|
style={{
|
||||||
transform: 'translateX(-50%)',
|
transform: 'translateX(-50%)',
|
||||||
userSelect: 'none',
|
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 { useRef, useState } from 'react';
|
||||||
import { Var } from '../../../../../../core/radix/var';
|
import { Var } from '../../../../../../core/radix/var';
|
||||||
import { useLocale } from '../../../../../../hooks/useLocale';
|
import { useLocale } from '../../../../../../hooks/useLocale';
|
||||||
import type { StatsAcceptorProps } from './HullTraverseVisualizer';
|
import type { StatsAcceptorProps } from './TraverseVisualizer';
|
||||||
|
|
||||||
const maps = [
|
const maps = [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user