mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
feat: improved vertical stablizer model compat
This commit is contained in:
1 parent
01c491aee0
commit
caff7bb6d0
6 files changed
+51
-22
No files matched your search
@@ -4,6 +4,7 @@ import { debounce } from 'lodash';
|
|||||||
import { use, useEffect, useRef, useState } from 'react';
|
import { use, useEffect, useRef, useState } from 'react';
|
||||||
import { lerp } from 'three/src/math/MathUtils';
|
import { lerp } from 'three/src/math/MathUtils';
|
||||||
import { ShellButton } from '../../../../../../components/ModuleButtons/ShellButton';
|
import { ShellButton } from '../../../../../../components/ModuleButtons/ShellButton';
|
||||||
|
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||||
import { isExplosive } from '../../../../../../core/blitz/isExplosive';
|
import { isExplosive } from '../../../../../../core/blitz/isExplosive';
|
||||||
import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration';
|
import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration';
|
||||||
import { coefficient } from '../../../../../../core/blitzkrieg/coefficient';
|
import { coefficient } from '../../../../../../core/blitzkrieg/coefficient';
|
||||||
@@ -219,6 +220,17 @@ export function Characteristics() {
|
|||||||
penetrationDistanceInput.current.value = `${penetrationDistance}`;
|
penetrationDistanceInput.current.value = `${penetrationDistance}`;
|
||||||
}
|
}
|
||||||
}, [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 (
|
return (
|
||||||
<Flex direction="column" gap="8" style={{ width: '100%' }}>
|
<Flex direction="column" gap="8" style={{ width: '100%' }}>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useEffect, useRef } from 'react';
|
|||||||
import { Vector3 } from 'three';
|
import { Vector3 } from 'three';
|
||||||
import { OrbitControls as OrbitControlsClass } from 'three-stdlib';
|
import { OrbitControls as OrbitControlsClass } from 'three-stdlib';
|
||||||
import { applyPitchYawLimits } from '../../../../../core/blitz/applyPitchYawLimits';
|
import { applyPitchYawLimits } from '../../../../../core/blitz/applyPitchYawLimits';
|
||||||
|
import { hasEquipment } from '../../../../../core/blitzkrieg/hasEquipment';
|
||||||
import { modelDefinitions } from '../../../../../core/blitzkrieg/modelDefinitions';
|
import { modelDefinitions } from '../../../../../core/blitzkrieg/modelDefinitions';
|
||||||
import { Pose, poseEvent } from '../../../../../core/blitzkrieg/pose';
|
import { Pose, poseEvent } from '../../../../../core/blitzkrieg/pose';
|
||||||
import { useAwait } from '../../../../../hooks/useAwait';
|
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) {
|
switch (event) {
|
||||||
case Pose.HullDown: {
|
case Pose.HullDown: {
|
||||||
const [pitch] = applyPitchYawLimits(
|
const [pitch] = applyPitchYawLimits(
|
||||||
@@ -75,6 +78,7 @@ export function Controls() {
|
|||||||
0,
|
0,
|
||||||
protagonistGunModelDefinition.pitch,
|
protagonistGunModelDefinition.pitch,
|
||||||
protagonistTurretModelDefinition.yaw,
|
protagonistTurretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
|
|
||||||
camera.position
|
camera.position
|
||||||
@@ -106,6 +110,7 @@ export function Controls() {
|
|||||||
0,
|
0,
|
||||||
protagonistGunModelDefinition.pitch,
|
protagonistGunModelDefinition.pitch,
|
||||||
protagonistTurretModelDefinition.yaw,
|
protagonistTurretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
|
|
||||||
camera.position
|
camera.position
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinit
|
|||||||
import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform';
|
import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform';
|
||||||
import { Pose, poseEvent } from '../../../../../../core/blitzkrieg/pose';
|
import { Pose, poseEvent } from '../../../../../../core/blitzkrieg/pose';
|
||||||
import { tankIcon } from '../../../../../../core/blitzkrieg/tankIcon';
|
import { tankIcon } from '../../../../../../core/blitzkrieg/tankIcon';
|
||||||
|
import { useEquipment } from '../../../../../../hooks/useEquipment';
|
||||||
import { useWideFormat } from '../../../../../../hooks/useWideFormat';
|
import { useWideFormat } from '../../../../../../hooks/useWideFormat';
|
||||||
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
|
import { mutateDuel, useDuel } from '../../../../../../stores/duel';
|
||||||
import mutateTankopediaPersistent, {
|
import mutateTankopediaPersistent, {
|
||||||
@@ -29,6 +30,7 @@ import { TankModel } from './components/TankModel';
|
|||||||
|
|
||||||
export function TankSandbox() {
|
export function TankSandbox() {
|
||||||
const canvas = useRef<HTMLCanvasElement>(null);
|
const canvas = useRef<HTMLCanvasElement>(null);
|
||||||
|
const hasImprovedVerticalStabilizer = useEquipment(122);
|
||||||
const awaitedModelDefinitions = use(modelDefinitions);
|
const awaitedModelDefinitions = use(modelDefinitions);
|
||||||
const canvasWrapper = useRef<HTMLDivElement>(null);
|
const canvasWrapper = useRef<HTMLDivElement>(null);
|
||||||
const [isFullScreen, setIsFullScreen] = useState(false);
|
const [isFullScreen, setIsFullScreen] = useState(false);
|
||||||
@@ -70,6 +72,7 @@ export function TankSandbox() {
|
|||||||
0,
|
0,
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
|
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
@@ -87,6 +90,7 @@ export function TankSandbox() {
|
|||||||
0,
|
0,
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
|
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
@@ -104,6 +108,7 @@ export function TankSandbox() {
|
|||||||
0,
|
0,
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
|
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
@@ -131,6 +136,7 @@ export function TankSandbox() {
|
|||||||
draft.protagonist!.yaw,
|
draft.protagonist!.yaw,
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}, [protagonist.gun, protagonist.turret]);
|
}, [protagonist.gun, protagonist.turret]);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Euler, Group, Vector3 } from 'three';
|
|||||||
import { degToRad } from 'three/src/math/MathUtils';
|
import { degToRad } from 'three/src/math/MathUtils';
|
||||||
import { I_HAT, J_HAT, K_HAT } from '../../../../../../../constants/axis';
|
import { I_HAT, J_HAT, K_HAT } from '../../../../../../../constants/axis';
|
||||||
import { applyPitchYawLimits } from '../../../../../../../core/blitz/applyPitchYawLimits';
|
import { applyPitchYawLimits } from '../../../../../../../core/blitz/applyPitchYawLimits';
|
||||||
|
import { hasEquipment } from '../../../../../../../core/blitzkrieg/hasEquipment';
|
||||||
import { jsxTree } from '../../../../../../../core/blitzkrieg/jsxTree';
|
import { jsxTree } from '../../../../../../../core/blitzkrieg/jsxTree';
|
||||||
import { modelDefinitions } from '../../../../../../../core/blitzkrieg/modelDefinitions';
|
import { modelDefinitions } from '../../../../../../../core/blitzkrieg/modelDefinitions';
|
||||||
import {
|
import {
|
||||||
@@ -106,7 +107,6 @@ export const TankModel = memo(() => {
|
|||||||
const turretModelDefinition =
|
const turretModelDefinition =
|
||||||
tankModelDefinition.turrets[protagonist.turret.id];
|
tankModelDefinition.turrets[protagonist.turret.id];
|
||||||
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
||||||
|
|
||||||
const { gltf } = useModel(protagonist.tank.id);
|
const { gltf } = useModel(protagonist.tank.id);
|
||||||
const nodes = Object.values(gltf.nodes);
|
const nodes = Object.values(gltf.nodes);
|
||||||
|
|
||||||
@@ -161,12 +161,14 @@ export const TankModel = memo(() => {
|
|||||||
window.addEventListener('pointerup', handlePointerUp);
|
window.addEventListener('pointerup', handlePointerUp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handlePointerMove(event: PointerEvent) {
|
async function handlePointerMove(event: PointerEvent) {
|
||||||
|
const hasImprovedVerticalStabilizer = await hasEquipment(122);
|
||||||
[pitch, yaw] = applyPitchYawLimits(
|
[pitch, yaw] = applyPitchYawLimits(
|
||||||
pitch,
|
pitch,
|
||||||
yaw + event.movementX * (Math.PI / canvas.width),
|
yaw + event.movementX * (Math.PI / canvas.width),
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
}
|
}
|
||||||
@@ -220,12 +222,14 @@ export const TankModel = memo(() => {
|
|||||||
window.addEventListener('pointermove', handlePointerMove);
|
window.addEventListener('pointermove', handlePointerMove);
|
||||||
window.addEventListener('pointerup', handlePointerUp);
|
window.addEventListener('pointerup', handlePointerUp);
|
||||||
}
|
}
|
||||||
function handlePointerMove(event: PointerEvent) {
|
async function handlePointerMove(event: PointerEvent) {
|
||||||
|
const hasImprovedVerticalStabilizer = await hasEquipment(122);
|
||||||
[pitch, yaw] = applyPitchYawLimits(
|
[pitch, yaw] = applyPitchYawLimits(
|
||||||
pitch - event.movementY * (Math.PI / canvas.height),
|
pitch - event.movementY * (Math.PI / canvas.height),
|
||||||
yaw + event.movementX * (Math.PI / canvas.width),
|
yaw + event.movementX * (Math.PI / canvas.width),
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
|
|||||||
tankModelDefinition.turrets[protagonist.turret.id];
|
tankModelDefinition.turrets[protagonist.turret.id];
|
||||||
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
||||||
const initialGunPitch = tankModelDefinition.turretRotation?.pitch ?? 0;
|
const initialGunPitch = tankModelDefinition.turretRotation?.pitch ?? 0;
|
||||||
|
const hasImprovedVerticalStabilizer = useEquipment(122);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
turretYawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1);
|
turretYawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1);
|
||||||
@@ -73,6 +74,7 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
|
|||||||
degToRad(Number(turretYawInput.current!.value)),
|
degToRad(Number(turretYawInput.current!.value)),
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
mutateDuel((state) => {
|
mutateDuel((state) => {
|
||||||
@@ -122,6 +124,7 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
|
|||||||
protagonist.yaw,
|
protagonist.yaw,
|
||||||
gunModelDefinition.pitch,
|
gunModelDefinition.pitch,
|
||||||
turretModelDefinition.yaw,
|
turretModelDefinition.yaw,
|
||||||
|
hasImprovedVerticalStabilizer,
|
||||||
);
|
);
|
||||||
modelTransformEvent.emit({ pitch, yaw });
|
modelTransformEvent.emit({ pitch, yaw });
|
||||||
mutateDuel((state) => {
|
mutateDuel((state) => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { clamp } from 'lodash';
|
import { clamp } from 'lodash';
|
||||||
|
import { degToRad } from 'three/src/math/MathUtils';
|
||||||
import { PitchLimits, YawLimits } from '../blitzkrieg/modelDefinitions';
|
import { PitchLimits, YawLimits } from '../blitzkrieg/modelDefinitions';
|
||||||
import { normalizeAngleRad } from '../math/normalizeAngleRad';
|
import { normalizeAngleRad } from '../math/normalizeAngleRad';
|
||||||
|
|
||||||
@@ -7,33 +8,31 @@ export function applyPitchYawLimits(
|
|||||||
yaw: number, // rad
|
yaw: number, // rad
|
||||||
pitchLimits: PitchLimits, // deg
|
pitchLimits: PitchLimits, // deg
|
||||||
yawLimits?: YawLimits, // deg
|
yawLimits?: YawLimits, // deg
|
||||||
|
verticalStabilizer = false,
|
||||||
) {
|
) {
|
||||||
let newPitch = pitch;
|
let newPitch = pitch;
|
||||||
let newYaw = yaw;
|
let newYaw = yaw;
|
||||||
|
|
||||||
if (yawLimits) {
|
if (yawLimits) {
|
||||||
newYaw = normalizeAngleRad(
|
newYaw = normalizeAngleRad(
|
||||||
clamp(
|
clamp(newYaw, -degToRad(yawLimits.max), -degToRad(yawLimits.min)),
|
||||||
newYaw,
|
|
||||||
-yawLimits.max * (Math.PI / 180),
|
|
||||||
-yawLimits.min * (Math.PI / 180),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lowerPitch = -pitchLimits.max * (Math.PI / 180);
|
const pitchBuff = verticalStabilizer ? degToRad(3) : 0;
|
||||||
let upperPitch = -pitchLimits.min * (Math.PI / 180);
|
let lowerPitch = -degToRad(pitchLimits.max) - pitchBuff;
|
||||||
const transition = (pitchLimits.transition ?? 10) * (Math.PI / 180);
|
let upperPitch = -degToRad(pitchLimits.min) + pitchBuff;
|
||||||
|
const transition = degToRad(pitchLimits.transition ?? 10);
|
||||||
|
|
||||||
if (pitchLimits.back) {
|
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));
|
const yawRotatedAbs = Math.abs(normalizeAngleRad(newYaw - Math.PI));
|
||||||
|
|
||||||
if (yawRotatedAbs <= range + transition) {
|
if (yawRotatedAbs <= range + transition) {
|
||||||
if (yawRotatedAbs <= range) {
|
if (yawRotatedAbs <= range) {
|
||||||
// inside range
|
// inside range
|
||||||
lowerPitch = -pitchLimits.back.max * (Math.PI / 180);
|
lowerPitch = -degToRad(pitchLimits.back.max);
|
||||||
upperPitch = -pitchLimits.back.min * (Math.PI / 180);
|
upperPitch = -degToRad(pitchLimits.back.min);
|
||||||
} else {
|
} else {
|
||||||
// inside transition
|
// inside transition
|
||||||
const transitionProgress = (yawRotatedAbs - range) / transition;
|
const transitionProgress = (yawRotatedAbs - range) / transition;
|
||||||
@@ -44,21 +43,21 @@ export function applyPitchYawLimits(
|
|||||||
(1 - transitionProgress) * pitchLimits.back.min +
|
(1 - transitionProgress) * pitchLimits.back.min +
|
||||||
transitionProgress * pitchLimits.min;
|
transitionProgress * pitchLimits.min;
|
||||||
|
|
||||||
lowerPitch = -maxInterpolatedPitch * (Math.PI / 180);
|
lowerPitch = -degToRad(maxInterpolatedPitch);
|
||||||
upperPitch = -minInterpolatedPitch * (Math.PI / 180);
|
upperPitch = -degToRad(minInterpolatedPitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pitchLimits.front) {
|
if (pitchLimits.front) {
|
||||||
const range = pitchLimits.front.range * (Math.PI / 180);
|
const range = degToRad(pitchLimits.front.range);
|
||||||
const yawAbs = Math.abs(normalizeAngleRad(newYaw));
|
const yawAbs = Math.abs(normalizeAngleRad(newYaw));
|
||||||
|
|
||||||
if (yawAbs <= range + transition) {
|
if (yawAbs <= range + transition) {
|
||||||
if (yawAbs <= range) {
|
if (yawAbs <= range) {
|
||||||
// inside range
|
// inside range
|
||||||
lowerPitch = -pitchLimits.front.max * (Math.PI / 180);
|
lowerPitch = -degToRad(pitchLimits.front.max);
|
||||||
upperPitch = -pitchLimits.front.min * (Math.PI / 180);
|
upperPitch = -degToRad(pitchLimits.front.min);
|
||||||
} else {
|
} else {
|
||||||
// inside transition
|
// inside transition
|
||||||
const transitionProgress = (yawAbs - range) / transition;
|
const transitionProgress = (yawAbs - range) / transition;
|
||||||
@@ -69,8 +68,8 @@ export function applyPitchYawLimits(
|
|||||||
(1 - transitionProgress) * pitchLimits.front.min +
|
(1 - transitionProgress) * pitchLimits.front.min +
|
||||||
transitionProgress * pitchLimits.min;
|
transitionProgress * pitchLimits.min;
|
||||||
|
|
||||||
lowerPitch = -maxInterpolatedPitch * (Math.PI / 180);
|
lowerPitch = -degToRad(maxInterpolatedPitch);
|
||||||
upperPitch = -minInterpolatedPitch * (Math.PI / 180);
|
upperPitch = -degToRad(minInterpolatedPitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user