Merge pull request #94 from tresabhi/1.16.3

This commit is contained in:
TrèsAbhi authored and GitHub committed 2024-03-12 22:43:51 -05:00
commit c54ceb944e
14 files changed
+173 -78

No files matched your search

+1
View File
@@ -73,6 +73,7 @@
"lods",
"metallicness",
"minitelrose",
"Minotauro",
"MIPMAPCOUNT",
"modeltransform",
"MURICA",
+36
View File
@@ -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
+21
View File
@@ -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
+2 -2
View File
@@ -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') {
+17 -18
View File
@@ -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);
}
}
}
+5 -1
View File
@@ -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: [],
+3 -3
View File
@@ -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
);
}
+2 -2
View File
@@ -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
);
}
}
+2 -2
View File
@@ -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 = {