From 40f5042896d8ebda92c316fb46f508f10237d583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Sat, 9 Aug 2025 13:30:53 -0500 Subject: [PATCH] feat: cursor --- packages/i18n/strings/en.json | 6 + .../GunFlexibilityVisualizer/index.tsx | 150 +++++++++++++++++- .../components/RicochetVisualizer/index.tsx | 127 ++++++--------- .../components/VisualizerCornerStat.tsx | 29 ++++ .../src/core/blitz/applyPitchYawLimits.ts | 2 +- .../website/src/core/blitzkit/hasEquipment.ts | 5 +- 6 files changed, 230 insertions(+), 89 deletions(-) create mode 100644 packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/VisualizerCornerStat.tsx diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json index 371b6e0da..ca1d3301c 100644 --- a/packages/i18n/strings/en.json +++ b/packages/i18n/strings/en.json @@ -913,6 +913,12 @@ "percentage": "%s1%", "ghost_factory": "Ghost Factory", "dead_rail": "Dead Rail" + }, + + "flexibility": { + "yaw": "Yaw", + "depression": "Depression", + "elevation": "Elevation" } }, diff --git a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/GunFlexibilityVisualizer/index.tsx b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/GunFlexibilityVisualizer/index.tsx index c3460eb95..1f1c006d0 100644 --- a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/GunFlexibilityVisualizer/index.tsx +++ b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/GunFlexibilityVisualizer/index.tsx @@ -1,7 +1,18 @@ +import { literals } from '@blitzkit/i18n'; +import { Box } from '@radix-ui/themes'; +import { useRef, useState } from 'react'; +import { radToDeg } from 'three/src/math/MathUtils.js'; import { awaitableModelDefinitions } from '../../../../../../../core/awaitables/modelDefinitions'; -import { DEFAULT_PITCH_TRANSITION } from '../../../../../../../core/blitz/applyPitchYawLimits'; +import { + applyPitchYawLimits, + DEFAULT_PITCH_TRANSITION, +} from '../../../../../../../core/blitz/applyPitchYawLimits'; +import { hasEquipment } from '../../../../../../../core/blitzkit/hasEquipment'; +import { Var } from '../../../../../../../core/radix/var'; +import { useLocale } from '../../../../../../../hooks/useLocale'; import { Duel } from '../../../../../../../stores/duel'; import { VisualizerCard } from '../VisualizerCard'; +import { VisualizerCornerStat } from '../VisualizerCornerStat'; const ANGLE_COEFFICIENT = 1 / 10; @@ -17,6 +28,17 @@ function c(thetaDeg: number, m = 1) { } export function GunFlexibilityVisualizer() { + const { strings } = useLocale(); + + const [yaw, setYaw] = useState(0); + const [minPitch, setMinPitch] = useState(0); + const [maxPitch, setMaxPitch] = useState(0); + + const container = useRef(null); + const highlighter = useRef(null); + const pointer = useRef(null); + + const duelStore = Duel.useStore(); const tank = Duel.use((state) => state.protagonist.tank); const turret = Duel.use((state) => state.protagonist.turret); const gun = Duel.use((state) => state.protagonist.gun); @@ -66,7 +88,6 @@ export function GunFlexibilityVisualizer() { } else if (b) { d += `A ${mo} ${mo} 0 0 0 ${c(-90 - b.range / 2 - t, mo)}`; } else { - console.log('this should log 0'); d += `A ${mo} ${mo} 0 0 0 ${c(-90, mo)}`; } @@ -125,7 +146,76 @@ export function GunFlexibilityVisualizer() { d += `Z`; return ( - + { + if (!container.current || !highlighter.current || !pointer.current) + return; + + const rect = container.current.getBoundingClientRect(); + const u = event.clientX - rect.left - rect.width / 2; + const v = event.clientY - rect.top - rect.height / 2; + const yaw = Math.atan2(u, -v); + + const { + equipmentMatrix, + tank: { equipment_preset }, + } = duelStore.getState().protagonist; + const hasImprovedVerticalStabilizer = hasEquipment( + 122, + equipment_preset, + equipmentMatrix, + ); + const hasDownImprovedVerticalStabilizer = hasEquipment( + 124, + equipment_preset, + equipmentMatrix, + ); + + const min = applyPitchYawLimits( + -Math.PI, + yaw, + p, + y, + hasImprovedVerticalStabilizer, + hasDownImprovedVerticalStabilizer, + ); + const max = applyPitchYawLimits( + Math.PI, + yaw, + p, + y, + hasImprovedVerticalStabilizer, + hasDownImprovedVerticalStabilizer, + ); + + setYaw(min[1]); + setMinPitch(min[0]); + setMaxPitch(max[0]); + }} + > + + + + + + + + + + + + + + ); } diff --git a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/RicochetVisualizer/index.tsx b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/RicochetVisualizer/index.tsx index e297a6c19..6e69c04cd 100644 --- a/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/RicochetVisualizer/index.tsx +++ b/packages/website/src/components/Tankopedia/CharacteristicsSection/components/Characteristics/components/RicochetVisualizer/index.tsx @@ -1,6 +1,6 @@ import { asset, isExplosive } from '@blitzkit/core'; import { literals } from '@blitzkit/i18n'; -import { Box, Code, Flex, Text } from '@radix-ui/themes'; +import { Box, Flex, Text } from '@radix-ui/themes'; import { useRef, useState } from 'react'; import { clamp, degToRad, radToDeg } from 'three/src/math/MathUtils.js'; import { Var } from '../../../../../../../core/radix/var'; @@ -8,6 +8,7 @@ import { useLocale } from '../../../../../../../hooks/useLocale'; import { Duel } from '../../../../../../../stores/duel'; import type { StatsAcceptorProps } from '../TraverseVisualizer'; import { VisualizerCard } from '../VisualizerCard'; +import { VisualizerCornerStat } from '../VisualizerCornerStat'; import { ShellSwitcher } from './components/ShellSwitcher'; export function RicochetVisualizer({ stats }: StatsAcceptorProps) { @@ -157,85 +158,51 @@ export function RicochetVisualizer({ stats }: StatsAcceptorProps) { /> - - - - {strings.website.tools.tankopedia.visualizers.ricochet.angle} - - - {literals(strings.common.units.deg, [ - radToDeg(Math.abs(angle)).toFixed(0), - ])} - - - - - - { - strings.website.tools.tankopedia.visualizers.ricochet - .normalization - } - - - {doesRicochet - ? '-' - : literals(strings.common.units.deg, [ - radToDeg(Math.min(normalization, Math.abs(angle))).toFixed( - 0, - ), - ])} - - - - - - - - { - strings.website.tools.tankopedia.visualizers.ricochet - .effective_angle - } - - - {doesRicochet - ? '-' - : literals(strings.common.units.deg, [ - radToDeg(Math.abs(effectiveAngle)).toFixed(0), - ])} - - - - - - {strings.website.tools.tankopedia.visualizers.ricochet.armor} - - - {doesRicochet - ? '-' - : literals(strings.common.units.percentage, [ - armorPercentage.toFixed(0), - ])} - - - + + + + {explodes && ( + + {label} + + + {value} + + + ); +} diff --git a/packages/website/src/core/blitz/applyPitchYawLimits.ts b/packages/website/src/core/blitz/applyPitchYawLimits.ts index b22bf92f2..e1b6e3bbf 100644 --- a/packages/website/src/core/blitz/applyPitchYawLimits.ts +++ b/packages/website/src/core/blitz/applyPitchYawLimits.ts @@ -86,5 +86,5 @@ export function applyPitchYawLimits( newPitch = clamp(newPitch, lowerPitch, upperPitch); - return [newPitch, newYaw]; + return [newPitch, newYaw] as const; } diff --git a/packages/website/src/core/blitzkit/hasEquipment.ts b/packages/website/src/core/blitzkit/hasEquipment.ts index cba049c4c..54cbfbcd0 100644 --- a/packages/website/src/core/blitzkit/hasEquipment.ts +++ b/packages/website/src/core/blitzkit/hasEquipment.ts @@ -1,12 +1,13 @@ import type { EquipmentMatrix } from '../../stores/duel'; import { awaitableEquipmentDefinitions } from '../awaitables/equipmentDefinitions'; -export async function hasEquipment( +const equipmentDefinitions = await awaitableEquipmentDefinitions; + +export function hasEquipment( id: number, equipmentPreset: string, equipmentMatrix: EquipmentMatrix, ) { - const equipmentDefinitions = await awaitableEquipmentDefinitions; const preset = equipmentDefinitions.presets[equipmentPreset]; return preset.slots.some((slot, index) => { const row = Math.floor(index / 3);