From caff7bb6d06be9ba516917443bdeba5f0762e54a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Tue, 12 Mar 2024 18:00:00 -0500 Subject: [PATCH] feat: improved vertical stablizer model compat --- .../[id]/components/Characteristics/index.tsx | 12 +++++++ .../tankopedia/[id]/components/Control.tsx | 7 +++- .../[id]/components/Model/TankSandbox.tsx | 6 ++++ .../components/Model/components/TankModel.tsx | 10 ++++-- .../[id]/components/QuickInputs/index.tsx | 3 ++ src/core/blitz/applyPitchYawLimits.ts | 35 +++++++++---------- 6 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx b/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx index 8a1846a10..48efd9cc0 100644 --- a/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx +++ b/src/app/tools/tankopedia/[id]/components/Characteristics/index.tsx @@ -4,6 +4,7 @@ import { debounce } from 'lodash'; import { use, useEffect, useRef, useState } from 'react'; import { lerp } from 'three/src/math/MathUtils'; import { ShellButton } from '../../../../../../components/ModuleButtons/ShellButton'; +import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits'; import { isExplosive } from '../../../../../../core/blitz/isExplosive'; import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration'; import { coefficient } from '../../../../../../core/blitzkrieg/coefficient'; @@ -219,6 +220,17 @@ export function Characteristics() { penetrationDistanceInput.current.value = `${penetrationDistance}`; } }, [penetrationDistance]); + useEffect(() => { + mutateDuel((draft) => { + [draft.protagonist!.pitch, draft.protagonist!.yaw] = applyPitchYawLimits( + draft.protagonist!.pitch, + draft.protagonist!.yaw, + gunModelDefinition.pitch, + turretModelDefinition.yaw, + hasImprovedVerticalStabilizer, + ); + }); + }, [hasImprovedVerticalStabilizer]); return ( diff --git a/src/app/tools/tankopedia/[id]/components/Control.tsx b/src/app/tools/tankopedia/[id]/components/Control.tsx index 8cef95e33..956c9815f 100644 --- a/src/app/tools/tankopedia/[id]/components/Control.tsx +++ b/src/app/tools/tankopedia/[id]/components/Control.tsx @@ -4,6 +4,7 @@ import { useEffect, useRef } from 'react'; import { Vector3 } from 'three'; import { OrbitControls as OrbitControlsClass } from 'three-stdlib'; import { applyPitchYawLimits } from '../../../../../core/blitz/applyPitchYawLimits'; +import { hasEquipment } from '../../../../../core/blitzkrieg/hasEquipment'; import { modelDefinitions } from '../../../../../core/blitzkrieg/modelDefinitions'; import { Pose, poseEvent } from '../../../../../core/blitzkrieg/pose'; import { useAwait } from '../../../../../hooks/useAwait'; @@ -67,7 +68,9 @@ export function Controls() { }, ); - function handlePoseEvent(event: Pose) { + async function handlePoseEvent(event: Pose) { + const hasImprovedVerticalStabilizer = await hasEquipment(122); + switch (event) { case Pose.HullDown: { const [pitch] = applyPitchYawLimits( @@ -75,6 +78,7 @@ export function Controls() { 0, protagonistGunModelDefinition.pitch, protagonistTurretModelDefinition.yaw, + hasImprovedVerticalStabilizer, ); camera.position @@ -106,6 +110,7 @@ export function Controls() { 0, protagonistGunModelDefinition.pitch, protagonistTurretModelDefinition.yaw, + hasImprovedVerticalStabilizer, ); camera.position diff --git a/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx b/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx index 3e077f02b..8d814b3ca 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx @@ -11,6 +11,7 @@ import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinit import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform'; import { Pose, poseEvent } from '../../../../../../core/blitzkrieg/pose'; import { tankIcon } from '../../../../../../core/blitzkrieg/tankIcon'; +import { useEquipment } from '../../../../../../hooks/useEquipment'; import { useWideFormat } from '../../../../../../hooks/useWideFormat'; import { mutateDuel, useDuel } from '../../../../../../stores/duel'; import mutateTankopediaPersistent, { @@ -29,6 +30,7 @@ import { TankModel } from './components/TankModel'; export function TankSandbox() { const canvas = useRef(null); + const hasImprovedVerticalStabilizer = useEquipment(122); const awaitedModelDefinitions = use(modelDefinitions); const canvasWrapper = useRef(null); const [isFullScreen, setIsFullScreen] = useState(false); @@ -70,6 +72,7 @@ export function TankSandbox() { 0, gunModelDefinition.pitch, turretModelDefinition.yaw, + hasImprovedVerticalStabilizer, ); modelTransformEvent.emit({ pitch, yaw }); @@ -87,6 +90,7 @@ export function TankSandbox() { 0, gunModelDefinition.pitch, turretModelDefinition.yaw, + hasImprovedVerticalStabilizer, ); modelTransformEvent.emit({ pitch, yaw }); @@ -104,6 +108,7 @@ export function TankSandbox() { 0, gunModelDefinition.pitch, turretModelDefinition.yaw, + hasImprovedVerticalStabilizer, ); modelTransformEvent.emit({ pitch, yaw }); @@ -131,6 +136,7 @@ export function TankSandbox() { draft.protagonist!.yaw, gunModelDefinition.pitch, turretModelDefinition.yaw, + hasImprovedVerticalStabilizer, ); }); }, [protagonist.gun, protagonist.turret]); diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx index e5253be2e..ac88d0f86 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/components/TankModel.tsx @@ -4,6 +4,7 @@ import { Euler, Group, Vector3 } from 'three'; import { degToRad } from 'three/src/math/MathUtils'; import { I_HAT, J_HAT, K_HAT } from '../../../../../../../constants/axis'; import { applyPitchYawLimits } from '../../../../../../../core/blitz/applyPitchYawLimits'; +import { hasEquipment } from '../../../../../../../core/blitzkrieg/hasEquipment'; import { jsxTree } from '../../../../../../../core/blitzkrieg/jsxTree'; import { modelDefinitions } from '../../../../../../../core/blitzkrieg/modelDefinitions'; import { @@ -106,7 +107,6 @@ export const TankModel = memo(() => { const turretModelDefinition = tankModelDefinition.turrets[protagonist.turret.id]; const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id]; - const { gltf } = useModel(protagonist.tank.id); const nodes = Object.values(gltf.nodes); @@ -161,12 +161,14 @@ export const TankModel = memo(() => { window.addEventListener('pointerup', handlePointerUp); } } - function handlePointerMove(event: PointerEvent) { + async function handlePointerMove(event: PointerEvent) { + const hasImprovedVerticalStabilizer = await hasEquipment(122); [pitch, yaw] = applyPitchYawLimits( pitch, yaw + event.movementX * (Math.PI / canvas.width), gunModelDefinition.pitch, turretModelDefinition.yaw, + hasImprovedVerticalStabilizer, ); modelTransformEvent.emit({ pitch, yaw }); } @@ -220,12 +222,14 @@ export const TankModel = memo(() => { window.addEventListener('pointermove', handlePointerMove); window.addEventListener('pointerup', handlePointerUp); } - function handlePointerMove(event: PointerEvent) { + async function handlePointerMove(event: PointerEvent) { + const hasImprovedVerticalStabilizer = await hasEquipment(122); [pitch, yaw] = applyPitchYawLimits( pitch - event.movementY * (Math.PI / canvas.height), yaw + event.movementX * (Math.PI / canvas.width), gunModelDefinition.pitch, turretModelDefinition.yaw, + hasImprovedVerticalStabilizer, ); modelTransformEvent.emit({ pitch, yaw }); } diff --git a/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx b/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx index 64e64ec3c..e827b1dc6 100644 --- a/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx +++ b/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx @@ -26,6 +26,7 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) { tankModelDefinition.turrets[protagonist.turret.id]; const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id]; const initialGunPitch = tankModelDefinition.turretRotation?.pitch ?? 0; + const hasImprovedVerticalStabilizer = useEquipment(122); useEffect(() => { turretYawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1); @@ -73,6 +74,7 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) { degToRad(Number(turretYawInput.current!.value)), gunModelDefinition.pitch, turretModelDefinition.yaw, + hasImprovedVerticalStabilizer, ); modelTransformEvent.emit({ pitch, yaw }); mutateDuel((state) => { @@ -122,6 +124,7 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) { protagonist.yaw, gunModelDefinition.pitch, turretModelDefinition.yaw, + hasImprovedVerticalStabilizer, ); modelTransformEvent.emit({ pitch, yaw }); mutateDuel((state) => { diff --git a/src/core/blitz/applyPitchYawLimits.ts b/src/core/blitz/applyPitchYawLimits.ts index 7565ac3bf..580e1f545 100644 --- a/src/core/blitz/applyPitchYawLimits.ts +++ b/src/core/blitz/applyPitchYawLimits.ts @@ -1,4 +1,5 @@ import { clamp } from 'lodash'; +import { degToRad } from 'three/src/math/MathUtils'; import { PitchLimits, YawLimits } from '../blitzkrieg/modelDefinitions'; import { normalizeAngleRad } from '../math/normalizeAngleRad'; @@ -7,33 +8,31 @@ export function applyPitchYawLimits( yaw: number, // rad pitchLimits: PitchLimits, // deg yawLimits?: YawLimits, // deg + verticalStabilizer = false, ) { let newPitch = pitch; let newYaw = yaw; if (yawLimits) { newYaw = normalizeAngleRad( - clamp( - newYaw, - -yawLimits.max * (Math.PI / 180), - -yawLimits.min * (Math.PI / 180), - ), + clamp(newYaw, -degToRad(yawLimits.max), -degToRad(yawLimits.min)), ); } - let lowerPitch = -pitchLimits.max * (Math.PI / 180); - let upperPitch = -pitchLimits.min * (Math.PI / 180); - const transition = (pitchLimits.transition ?? 10) * (Math.PI / 180); + const pitchBuff = verticalStabilizer ? degToRad(3) : 0; + let lowerPitch = -degToRad(pitchLimits.max) - pitchBuff; + let upperPitch = -degToRad(pitchLimits.min) + pitchBuff; + const transition = degToRad(pitchLimits.transition ?? 10); if (pitchLimits.back) { - const range = pitchLimits.back.range * (Math.PI / 180); + const range = degToRad(pitchLimits.back.range); const yawRotatedAbs = Math.abs(normalizeAngleRad(newYaw - Math.PI)); if (yawRotatedAbs <= range + transition) { if (yawRotatedAbs <= range) { // inside range - lowerPitch = -pitchLimits.back.max * (Math.PI / 180); - upperPitch = -pitchLimits.back.min * (Math.PI / 180); + lowerPitch = -degToRad(pitchLimits.back.max); + upperPitch = -degToRad(pitchLimits.back.min); } else { // inside transition const transitionProgress = (yawRotatedAbs - range) / transition; @@ -44,21 +43,21 @@ export function applyPitchYawLimits( (1 - transitionProgress) * pitchLimits.back.min + transitionProgress * pitchLimits.min; - lowerPitch = -maxInterpolatedPitch * (Math.PI / 180); - upperPitch = -minInterpolatedPitch * (Math.PI / 180); + lowerPitch = -degToRad(maxInterpolatedPitch); + upperPitch = -degToRad(minInterpolatedPitch); } } } if (pitchLimits.front) { - const range = pitchLimits.front.range * (Math.PI / 180); + const range = degToRad(pitchLimits.front.range); const yawAbs = Math.abs(normalizeAngleRad(newYaw)); if (yawAbs <= range + transition) { if (yawAbs <= range) { // inside range - lowerPitch = -pitchLimits.front.max * (Math.PI / 180); - upperPitch = -pitchLimits.front.min * (Math.PI / 180); + lowerPitch = -degToRad(pitchLimits.front.max); + upperPitch = -degToRad(pitchLimits.front.min); } else { // inside transition const transitionProgress = (yawAbs - range) / transition; @@ -69,8 +68,8 @@ export function applyPitchYawLimits( (1 - transitionProgress) * pitchLimits.front.min + transitionProgress * pitchLimits.min; - lowerPitch = -maxInterpolatedPitch * (Math.PI / 180); - upperPitch = -minInterpolatedPitch * (Math.PI / 180); + lowerPitch = -degToRad(maxInterpolatedPitch); + upperPitch = -degToRad(minInterpolatedPitch); } } }