mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 18:57:03 +02:00
Merge pull request #94 from tresabhi/1.16.3
This commit is contained in:
14 files changed
+173
-78
No files matched your search
Vendored
+1
@@ -73,6 +73,7 @@
|
||||
"lods",
|
||||
"metallicness",
|
||||
"minitelrose",
|
||||
"Minotauro",
|
||||
"MIPMAPCOUNT",
|
||||
"modeltransform",
|
||||
"MURICA",
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# Blitzkrieg 1.16.2
|
||||
|
||||
¡Hola desde el mundo del español!
|
||||
|
||||
## Features
|
||||
|
||||
- Added translations for Spanish to the bot
|
||||
- Your language will be inferred automatically from your Discord settings
|
||||
- Any untranslated languages and words we forgot to translate will be left in English
|
||||
- If you have your language set to Spanish and see English in any places, please let us know on [the official Discord server](https://discord.gg/nDt7AjGJQH)
|
||||
- All `/about` commands except for `commands` remain in English
|
||||
- Tank names are still in English
|
||||
- The website remains unchanged
|
||||
- The title bar (featured as the big text on top of most commands) has now been made more compact
|
||||
|
||||
## Changes
|
||||
|
||||
- "Tank type" is now called "tank class"
|
||||
- Removed `/player-achievements` and `search-tanks`
|
||||
- They will be reintroduced in the future in a far better way
|
||||
- Also removed a `SKLLD` server exclusive `/eligible` command
|
||||
- This will be generalized for all clans in the future
|
||||
|
||||
## Fixes
|
||||
|
||||
- Fixed the red glowing floor underneath the tank sandbox
|
||||
- This has been replaced with a static image
|
||||
- The refresh button is now properly removed when lacking permissions
|
||||
- Tank names that start with a number are now properly inferred from command inputs
|
||||
|
||||
## Technical Changes
|
||||
|
||||
- Command registration is now error tolerant meaning that if a single command fails to initiate, it will be discarded until the next restart
|
||||
- We are currently looking into how we can allow the command to retry registration after a fixed amount of time
|
||||
- Due to the implications of the code added which can be very easily exploited by hackers, a single file has been added to the repository as a closed source submodule and will remain closed unless a third party open-source implementation is made public
|
||||
- Removed preview commands
|
||||
@@ -0,0 +1,21 @@
|
||||
# Blitzkrieg 1.16.3
|
||||
|
||||
Further polishing and corrections for the Tankopedia.
|
||||
|
||||
## Features
|
||||
|
||||
- Added a few more stats to view for the Tankopedia
|
||||
- Added the count of shells in the magazine for auto-reloaders
|
||||
- The optimal shell index was moved below this stats
|
||||
- Shell reloads for auto-reloaders now abide crew stats
|
||||
- Intra-clip is now also shown for auto-reloaders
|
||||
- Added 1 more decimal place worth of precision when viewing and changing gun pitch and yaw
|
||||
|
||||
## Fixes
|
||||
|
||||
- "Inter-clip" is now correctly spelled as "intra-clip"
|
||||
- Tanks with initial gun pitches (like the Minotauro) are now handled correctly
|
||||
- The stats now reflect the fact that the gun is naturally pitched downwards
|
||||
- The view model now compensates for the natural pitch
|
||||
- Tanks with the improved vertical stabilizer equipment are now handled correctly
|
||||
- The view model now allows you to pitch the gun further as intended when the equipment is on
|
||||
@@ -674,7 +674,7 @@ export async function definitions(production: boolean) {
|
||||
: turretGunEntry.reloadTime;
|
||||
const gunClipCount =
|
||||
gunType === 'regular' ? undefined : turretGunEntry.clip!.count;
|
||||
const gunInterClip =
|
||||
const gunIntraClip =
|
||||
gunType === 'regular'
|
||||
? undefined
|
||||
: 60 / turretGunEntry.clip!.rate;
|
||||
@@ -722,7 +722,7 @@ export async function definitions(production: boolean) {
|
||||
type: gunType,
|
||||
reload: gunReload,
|
||||
count: gunClipCount,
|
||||
interClip: gunInterClip,
|
||||
intraClip: gunIntraClip,
|
||||
camouflageLoss:
|
||||
typeof turretGunEntry.invisibilityFactorAtShot === 'number'
|
||||
? turretGunEntry.invisibilityFactorAtShot
|
||||
|
||||
@@ -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';
|
||||
@@ -56,6 +57,7 @@ export function Characteristics() {
|
||||
turretModelDefinition.boundingBox,
|
||||
),
|
||||
);
|
||||
const gunDefaultPitch = tankModelDefinition.turretRotation?.pitch ?? 0;
|
||||
const weight =
|
||||
tank.weight + engine.weight + track.weight + turret.weight + gun.weight;
|
||||
const weightTons = weight / 1000;
|
||||
@@ -113,7 +115,7 @@ export function Characteristics() {
|
||||
// TODO: add max rolls
|
||||
[hasTungsten, 0.15],
|
||||
);
|
||||
const interClipCoefficient = coefficient([hasShellReloadBoost, -0.3]);
|
||||
const intraClipCoefficient = coefficient([hasShellReloadBoost, -0.3]);
|
||||
const shellVelocityCoefficient = coefficient(
|
||||
[hasSupercharger, 0.3],
|
||||
[hasImprovedGunPowder, 0.3],
|
||||
@@ -210,7 +212,7 @@ export function Characteristics() {
|
||||
shell,
|
||||
damageCoefficient,
|
||||
reloadCoefficient,
|
||||
interClipCoefficient,
|
||||
intraClipCoefficient,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -218,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 (
|
||||
<Flex direction="column" gap="8" style={{ width: '100%' }}>
|
||||
@@ -255,7 +268,7 @@ export function Characteristics() {
|
||||
<>
|
||||
<InfoWithDelta decimals={0} indent name="Maximum" unit="hp / min">
|
||||
{gun.reload.at(-1)! < gun.reload.at(-2)!
|
||||
? (shell.damage.armor / (gun.reload.at(-1)! + gun.interClip)) *
|
||||
? (shell.damage.armor / (gun.reload.at(-1)! + gun.intraClip)) *
|
||||
60
|
||||
: (shell.damage.armor / gun.reload[0]) * 60}
|
||||
</InfoWithDelta>
|
||||
@@ -266,12 +279,12 @@ export function Characteristics() {
|
||||
unit="hp / min"
|
||||
>
|
||||
{gun.reload.at(-1)! < gun.reload.at(-2)!
|
||||
? (shell.damage.armor / (gun.reload.at(-1)! + gun.interClip)) *
|
||||
? (shell.damage.armor / (gun.reload.at(-1)! + gun.intraClip)) *
|
||||
(60 -
|
||||
(gun.reload.slice(0, -1).length - 1) * gun.interClip) +
|
||||
(gun.reload.slice(0, -1).length - 1) * gun.intraClip) +
|
||||
shell.damage.armor * gun.reload.slice(0, -1).length
|
||||
: (shell.damage.armor / (gun.reload[0] + gun.interClip)) *
|
||||
(60 - (gun.reload.slice(1).length - 1) * gun.interClip) +
|
||||
: (shell.damage.armor / (gun.reload[0] + gun.intraClip)) *
|
||||
(60 - (gun.reload.slice(1).length - 1) * gun.intraClip) +
|
||||
shell.damage.armor * gun.reload.slice(1).length}
|
||||
</InfoWithDelta>
|
||||
<Info
|
||||
@@ -285,14 +298,15 @@ export function Characteristics() {
|
||||
</a>
|
||||
}
|
||||
/>
|
||||
<Info indent name="Optimal shell index">
|
||||
{gun.reload.at(-1)! < gun.reload.at(-2)! ? gun.reload.length : 1}
|
||||
</Info>
|
||||
</>
|
||||
)}
|
||||
{gun.type === 'autoReloader' ? (
|
||||
<>
|
||||
<Info name="Reload" unit="s" />
|
||||
<InfoWithDelta name="Shells">{gun.reload.length}</InfoWithDelta>
|
||||
<Info indent name="Most optimal">
|
||||
{gun.reload.at(-1)! < gun.reload.at(-2)! ? gun.reload.length : 1}
|
||||
</Info>
|
||||
<Info name="Shell reloads" unit="s" />
|
||||
{gun.reload.map((reload, index) => (
|
||||
<InfoWithDelta
|
||||
key={index}
|
||||
@@ -301,7 +315,7 @@ export function Characteristics() {
|
||||
decimals={2}
|
||||
deltaType="lowerIsBetter"
|
||||
>
|
||||
{reload}
|
||||
{reload * reloadCoefficient}
|
||||
</InfoWithDelta>
|
||||
))}
|
||||
</>
|
||||
@@ -315,17 +329,18 @@ export function Characteristics() {
|
||||
{gun.reload * reloadCoefficient}
|
||||
</InfoWithDelta>
|
||||
)}
|
||||
{gun.type === 'autoLoader' && (
|
||||
<InfoWithDelta
|
||||
indent
|
||||
decimals={2}
|
||||
name="Inter-clip reload"
|
||||
unit="s"
|
||||
deltaType="lowerIsBetter"
|
||||
>
|
||||
{gun.interClip * interClipCoefficient}
|
||||
</InfoWithDelta>
|
||||
)}
|
||||
{gun.type === 'autoLoader' ||
|
||||
(gun.type === 'autoReloader' && (
|
||||
<InfoWithDelta
|
||||
indent
|
||||
decimals={2}
|
||||
name="Intra-clip"
|
||||
unit="s"
|
||||
deltaType="lowerIsBetter"
|
||||
>
|
||||
{gun.intraClip * intraClipCoefficient}
|
||||
</InfoWithDelta>
|
||||
))}
|
||||
<InfoWithDelta name="Caliber" decimals={0} unit="mm">
|
||||
{shell.caliber}
|
||||
</InfoWithDelta>
|
||||
@@ -457,10 +472,12 @@ export function Characteristics() {
|
||||
<Info name="Gun flexibility" unit="°" />
|
||||
<InfoWithDelta decimals={1} indent name="Depression">
|
||||
{gunModelDefinition.pitch.max +
|
||||
gunDefaultPitch +
|
||||
(hasImprovedVerticalStabilizer ? 3 : 0)}
|
||||
</InfoWithDelta>
|
||||
<InfoWithDelta decimals={1} indent name="Elevation">
|
||||
{-gunModelDefinition.pitch.min +
|
||||
{-gunModelDefinition.pitch.min -
|
||||
gunDefaultPitch +
|
||||
(hasImprovedVerticalStabilizer ? 3 : 0)}
|
||||
</InfoWithDelta>
|
||||
{gunModelDefinition.pitch.front && (
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<HTMLCanvasElement>(null);
|
||||
const hasImprovedVerticalStabilizer = useEquipment(122);
|
||||
const awaitedModelDefinitions = use(modelDefinitions);
|
||||
const canvasWrapper = useRef<HTMLDivElement>(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]);
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Flex, TextField } from '@radix-ui/themes';
|
||||
import { use, useEffect, useRef } from 'react';
|
||||
import { degToRad, radToDeg } from 'three/src/math/MathUtils';
|
||||
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||
import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions';
|
||||
import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform';
|
||||
@@ -20,22 +21,21 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
|
||||
const mode = useTankopediaPersistent((state) => state.mode);
|
||||
const hasCalibratedShells = useEquipment(103, true);
|
||||
const hasEnhancedArmor = useEquipment(110);
|
||||
|
||||
useEffect(() => {
|
||||
turretYawInput.current!.value = `${-Math.round(
|
||||
protagonist.yaw * (180 / Math.PI),
|
||||
)}`;
|
||||
}, [protagonist.yaw]);
|
||||
useEffect(() => {
|
||||
gunPitchInput.current!.value = `${-Math.round(
|
||||
protagonist.pitch * (180 / Math.PI),
|
||||
)}`;
|
||||
}, [protagonist.pitch]);
|
||||
|
||||
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
|
||||
const turretModelDefinition =
|
||||
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);
|
||||
}, [protagonist.yaw]);
|
||||
useEffect(() => {
|
||||
gunPitchInput.current!.value = (
|
||||
-radToDeg(protagonist.pitch) + initialGunPitch
|
||||
).toFixed(1);
|
||||
}, [protagonist.pitch]);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
@@ -68,22 +68,22 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
|
||||
Yaw
|
||||
</TextField.Slot>
|
||||
<TextField.Input
|
||||
defaultValue={Math.round(protagonist.yaw * (180 / Math.PI))}
|
||||
onBlur={() => {
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
protagonist.pitch,
|
||||
-Number(turretYawInput.current?.value) * (Math.PI / 180),
|
||||
degToRad(Number(turretYawInput.current!.value)),
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
);
|
||||
modelTransformEvent.emit({ pitch, yaw });
|
||||
mutateDuel((state) => {
|
||||
state.protagonist!.pitch = pitch;
|
||||
state.protagonist!.yaw = yaw;
|
||||
});
|
||||
turretYawInput.current!.value = `${Math.round(
|
||||
yaw * (180 / Math.PI),
|
||||
)}`;
|
||||
turretYawInput.current!.value = radToDeg(protagonist.yaw).toFixed(
|
||||
1,
|
||||
);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
@@ -116,22 +116,24 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
|
||||
Pitch
|
||||
</TextField.Slot>
|
||||
<TextField.Input
|
||||
defaultValue={-Math.round(protagonist.pitch * (180 / Math.PI))}
|
||||
onBlur={() => {
|
||||
const [pitch, yaw] = applyPitchYawLimits(
|
||||
-Number(gunPitchInput.current?.value) * (Math.PI / 180),
|
||||
degToRad(
|
||||
-Number(gunPitchInput.current!.value) + initialGunPitch,
|
||||
),
|
||||
protagonist.yaw,
|
||||
gunModelDefinition.pitch,
|
||||
turretModelDefinition.yaw,
|
||||
hasImprovedVerticalStabilizer,
|
||||
);
|
||||
modelTransformEvent.emit({ pitch, yaw });
|
||||
mutateDuel((state) => {
|
||||
state.protagonist!.pitch = pitch;
|
||||
state.protagonist!.yaw = yaw;
|
||||
});
|
||||
gunPitchInput.current!.value = `${Math.round(
|
||||
pitch * (180 / Math.PI),
|
||||
)}`;
|
||||
gunPitchInput.current!.value = (
|
||||
-radToDeg(protagonist.pitch) + initialGunPitch
|
||||
).toFixed(1);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { degToRad } from 'three/src/math/MathUtils';
|
||||
import {
|
||||
DuelMember,
|
||||
genericDefaultEquipmentMatrix,
|
||||
mutateDuel,
|
||||
} from '../../stores/duel';
|
||||
import { availableProvisions } from './availableProvisions';
|
||||
import { modelDefinitions } from './modelDefinitions';
|
||||
import { provisionDefinitions } from './provisionDefinitions';
|
||||
import { tankDefinitions } from './tankDefinitions';
|
||||
|
||||
@@ -13,6 +15,8 @@ export async function assignDuelMember(
|
||||
) {
|
||||
const awaitedTankDefinitions = await tankDefinitions;
|
||||
const awaitedProvisionDefinitions = await provisionDefinitions;
|
||||
const awaitedModelDefinitions = await modelDefinitions;
|
||||
const tankModelDefinition = awaitedModelDefinitions[id];
|
||||
const tank = awaitedTankDefinitions[id];
|
||||
const turret = tank.turrets.at(-1)!;
|
||||
const gun = turret.guns.at(-1)!;
|
||||
@@ -32,7 +36,7 @@ export async function assignDuelMember(
|
||||
shell,
|
||||
track,
|
||||
equipment: genericDefaultEquipmentMatrix,
|
||||
pitch: 0,
|
||||
pitch: degToRad(tankModelDefinition.turretRotation?.pitch ?? 0),
|
||||
yaw: 0,
|
||||
camouflage: true,
|
||||
consumables: [],
|
||||
|
||||
@@ -5,7 +5,7 @@ export function resolveDpm(
|
||||
shell: ShellDefinition,
|
||||
damageCoefficient = 1,
|
||||
reloadCoefficient = 1,
|
||||
interClipCoefficient = 1,
|
||||
intraClipCoefficient = 1,
|
||||
) {
|
||||
const alpha = shell.damage.armor * damageCoefficient;
|
||||
|
||||
@@ -14,14 +14,14 @@ export function resolveDpm(
|
||||
} else if (gun.type === 'autoLoader') {
|
||||
return (
|
||||
((alpha * gun.count) /
|
||||
(gun.reload + (gun.count - 1) * gun.interClip * interClipCoefficient)) *
|
||||
(gun.reload + (gun.count - 1) * gun.intraClip * intraClipCoefficient)) *
|
||||
60
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
((alpha * gun.count) /
|
||||
(gun.reload.reduce((a, b) => a + b, 0) +
|
||||
(gun.count - 1) * gun.interClip)) *
|
||||
(gun.count - 1) * gun.intraClip)) *
|
||||
60
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ export function resolveReload(gun: GunDefinition) {
|
||||
if (gun.type === 'regular') {
|
||||
return gun.reload;
|
||||
} else if (gun.type === 'autoLoader') {
|
||||
return gun.reload + (gun.count - 1) * gun.interClip;
|
||||
return gun.reload + (gun.count - 1) * gun.intraClip;
|
||||
} else {
|
||||
return (
|
||||
gun.reload.reduce((a, b) => a + b, 0) + (gun.count - 1) * gun.interClip
|
||||
gun.reload.reduce((a, b) => a + b, 0) + (gun.count - 1) * gun.intraClip
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -125,13 +125,13 @@ interface GunDefinitionRegular extends GunDefinitionBase {
|
||||
interface GunDefinitionAutoLoader extends GunDefinitionBase {
|
||||
type: 'autoLoader';
|
||||
reload: number;
|
||||
interClip: number;
|
||||
intraClip: number;
|
||||
count: number;
|
||||
}
|
||||
interface GunDefinitionAutoReloader extends GunDefinitionBase {
|
||||
type: 'autoReloader';
|
||||
reload: number[];
|
||||
interClip: number;
|
||||
intraClip: number;
|
||||
count: number;
|
||||
}
|
||||
export type ShellDefinition = {
|
||||
|
||||
Reference in new issue
Block a user