mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
13 files changed
+179
-109
No files matched your search
@@ -0,0 +1,18 @@
|
||||
# BlitzKit 1.29.16
|
||||
|
||||
Thank you to [GonnaHetzMe](https://github.com/karelpak1) for your contributions this update.
|
||||
|
||||
## Fixes
|
||||
|
||||
- [GonnaHetzMe] The turret for Centurion I is no longer offset from the body
|
||||
- Please allow up to 24 hours for the model to update
|
||||
- Vertical Stabilizers now give the correct 12% buff instead of 15%
|
||||
- Re-ordering tanks in Compare now works once again
|
||||
- Fixed review videos from being about the Object 452K across all tanks
|
||||
- Please allow up to 2 weeks for all tanks to refresh their videos
|
||||
- Tanks in Mixer with oscillating turrets are not handled properly
|
||||
|
||||
## Features
|
||||
|
||||
- Headings in the Compare tool are now even more compact for mobile devices
|
||||
- Enabled all tiers for the randomizer in Mixer
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "blitzkit",
|
||||
"version": "1.29.15",
|
||||
"version": "1.29.16",
|
||||
"license": "BlitzKit License",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -170,6 +170,7 @@ export async function extractModel(vfs: AbstractVFS, path: string) {
|
||||
break;
|
||||
|
||||
case "TransformComponent": {
|
||||
component["tc.localTranslation"] = [0, 0, 0]; // Game when is loading model resets position to [0, 0, 0], so any set value is ignored.
|
||||
node.setTranslation(component["tc.localTranslation"]);
|
||||
node.setRotation(component["tc.localRotation"]);
|
||||
node.setScale(component["tc.localScale"]);
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
Video,
|
||||
youtubers,
|
||||
} from "@blitzkit/core";
|
||||
import locales from "@blitzkit/i18n/locales.json";
|
||||
import { google } from "googleapis";
|
||||
import { cloneDeep, uniqBy } from "lodash-es";
|
||||
import { AssetUploader } from "./core/github/assetUploader";
|
||||
@@ -42,9 +43,11 @@ for (const tank of tanksSanitized) {
|
||||
}
|
||||
|
||||
try {
|
||||
const q = `World of Tanks Blitz ${tank.name.locales[locales.default]}`;
|
||||
|
||||
const results = await youtube.search.list({
|
||||
part: ["snippet"],
|
||||
q: `World of Tanks Blitz ${tank.name}`,
|
||||
q,
|
||||
});
|
||||
|
||||
if (!results.data.items || results.data.items.length === 0) continue;
|
||||
@@ -54,9 +57,9 @@ for (const tank of tanksSanitized) {
|
||||
(item) =>
|
||||
item.snippet?.channelId &&
|
||||
item.id?.videoId &&
|
||||
youtubers.some(({ id }) => id === item.snippet?.channelId)
|
||||
youtubers.some(({ id }) => id === item.snippet?.channelId),
|
||||
),
|
||||
(item) => item.snippet!.channelId
|
||||
(item) => item.snippet!.channelId,
|
||||
);
|
||||
|
||||
reviews.reviews[tank.id] = {
|
||||
@@ -66,11 +69,13 @@ for (const tank of tanksSanitized) {
|
||||
({
|
||||
id: item.id!.videoId!,
|
||||
author: item.snippet!.channelId!,
|
||||
} satisfies Video)
|
||||
}) satisfies Video,
|
||||
),
|
||||
};
|
||||
|
||||
console.log(`${++done} done; found ${items.length} for ${tank.name.locales.en}`);
|
||||
console.log(
|
||||
`${++done} done; found ${items.length} for ${tank.name.locales.en}`,
|
||||
);
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000 / 5));
|
||||
} catch (error) {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { StickyRowHeaderCell } from "../StickyRowHeaderCell";
|
||||
|
||||
type CompareRowProps = {
|
||||
display?: (
|
||||
member: Awaited<TankCharacteristics>
|
||||
member: Awaited<TankCharacteristics>,
|
||||
) => number | string | undefined;
|
||||
deltaType?: CompareCellDirection;
|
||||
decimals?: number;
|
||||
@@ -46,7 +46,7 @@ export function CompareRow({
|
||||
const values = stats.map((stat) =>
|
||||
typeof props.value === "function"
|
||||
? props.value(stat)!
|
||||
: (stat[props.value] as number)
|
||||
: (stat[props.value] as number),
|
||||
);
|
||||
const id = useRef(Math.random());
|
||||
const name =
|
||||
@@ -56,10 +56,10 @@ export function CompareRow({
|
||||
|
||||
return (
|
||||
<Table.Row>
|
||||
<StickyRowHeaderCell>
|
||||
<StickyRowHeaderCell left="-1.25rem">
|
||||
<Flex
|
||||
align="center"
|
||||
style={{ whiteSpace: "nowrap" }}
|
||||
maxWidth={{ initial: "6rem", sm: "unset" }}
|
||||
gap={indent ? { initial: "4", sm: "6" } : { initial: "1", sm: "2" }}
|
||||
>
|
||||
<IconButton
|
||||
@@ -111,8 +111,8 @@ export function CompareRow({
|
||||
const resolvedDisplayValue = display
|
||||
? display(stats[index])
|
||||
: decimals === undefined
|
||||
? value
|
||||
: value?.toFixed(decimals);
|
||||
? value
|
||||
: value?.toFixed(decimals);
|
||||
|
||||
return (
|
||||
<CompareCell
|
||||
@@ -145,8 +145,8 @@ export function CompareRow({
|
||||
deltaNominalDisplay
|
||||
? deltaNominalDisplay(delta)
|
||||
: decimals === undefined
|
||||
? delta
|
||||
: delta.toFixed(decimals)
|
||||
? delta
|
||||
: delta.toFixed(decimals)
|
||||
}`}
|
||||
)
|
||||
</Text>
|
||||
@@ -156,7 +156,7 @@ export function CompareRow({
|
||||
<Text color="gray">
|
||||
(
|
||||
{`${deltaPercentage > 0 ? "+" : ""}${Math.round(
|
||||
deltaPercentage * 100
|
||||
deltaPercentage * 100,
|
||||
)}%`}
|
||||
)
|
||||
</Text>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Heading, Table } from '@radix-ui/themes';
|
||||
import { times } from 'lodash-es';
|
||||
import { CompareEphemeral } from '../../stores/compareEphemeral';
|
||||
import { StickyColumnHeaderCell } from '../StickyColumnHeaderCell';
|
||||
import { Heading, Table } from "@radix-ui/themes";
|
||||
import { times } from "lodash-es";
|
||||
import { CompareEphemeral } from "../../stores/compareEphemeral";
|
||||
import { StickyColumnHeaderCell } from "../StickyColumnHeaderCell";
|
||||
|
||||
export function CompareSectionTitle({ children }: { children: string }) {
|
||||
const memberCount = CompareEphemeral.use((state) => state.members.length);
|
||||
|
||||
@@ -105,13 +105,13 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
crewSkills[skill] === 0
|
||||
? Var("gray-11")
|
||||
: permanentSkills.includes(skill)
|
||||
? Var("crimson-11")
|
||||
: Var("amber-11"),
|
||||
? Var("crimson-11")
|
||||
: Var("amber-11"),
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Flex>
|
||||
)
|
||||
),
|
||||
)}
|
||||
</Flex>
|
||||
</Button>
|
||||
@@ -173,19 +173,19 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
consumables,
|
||||
camouflage,
|
||||
},
|
||||
index
|
||||
index,
|
||||
) => {
|
||||
const equipmentPreset =
|
||||
equipmentDefinitions.presets[tank.equipment_preset];
|
||||
const provisionsList = availableProvisions(
|
||||
tank,
|
||||
gun,
|
||||
provisionDefinitions
|
||||
provisionDefinitions,
|
||||
);
|
||||
const consumablesList = Object.values(
|
||||
consumableDefinitions.consumables
|
||||
consumableDefinitions.consumables,
|
||||
).filter((consumable) =>
|
||||
checkConsumableProvisionInclusivity(consumable, tank, gun)
|
||||
checkConsumableProvisionInclusivity(consumable, tank, gun),
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -294,11 +294,11 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
<img
|
||||
alt={unwrap(
|
||||
provisionDefinitions.provisions[provision]
|
||||
.name
|
||||
.name,
|
||||
)}
|
||||
key={provision}
|
||||
src={asset(
|
||||
`/icons/provisions/${provision}.webp`
|
||||
`/icons/provisions/${provision}.webp`,
|
||||
)}
|
||||
style={{
|
||||
left: "50%",
|
||||
@@ -335,7 +335,7 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
<Popover.Content>
|
||||
<ProvisionsManager
|
||||
provisions={provisionsList.map(
|
||||
(provision) => provision.id
|
||||
(provision) => provision.id,
|
||||
)}
|
||||
selected={provisions}
|
||||
disabled={tank.max_provisions === provisions.length}
|
||||
@@ -452,7 +452,7 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
CompareEphemeral.mutate((draft) => {
|
||||
draft.members[index].equipmentMatrix = times(
|
||||
3,
|
||||
() => times(3, () => 0)
|
||||
() => times(3, () => 0),
|
||||
) as EquipmentMatrix;
|
||||
draft.sorting = undefined;
|
||||
});
|
||||
@@ -501,11 +501,11 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
alt={unwrap(
|
||||
consumableDefinitions.consumables[
|
||||
consumable
|
||||
].name
|
||||
].name,
|
||||
)}
|
||||
key={consumable}
|
||||
src={asset(
|
||||
`/icons/consumables/${consumable}.webp`
|
||||
`/icons/consumables/${consumable}.webp`,
|
||||
)}
|
||||
style={{
|
||||
left: "50%",
|
||||
@@ -610,7 +610,7 @@ export function CompareTable({ stats }: CompareTableProps) {
|
||||
</Flex>
|
||||
</Table.Cell>
|
||||
);
|
||||
}
|
||||
},
|
||||
)}
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
|
||||
@@ -55,7 +55,7 @@ export function TankCard({ index, tank }: TankCardProps) {
|
||||
};
|
||||
});
|
||||
const closest = distances.reduce((a, b) =>
|
||||
a.distance < b.distance ? a : b
|
||||
a.distance < b.distance ? a : b,
|
||||
);
|
||||
|
||||
dropIndex = closest.index;
|
||||
@@ -85,8 +85,8 @@ export function TankCard({ index, tank }: TankCardProps) {
|
||||
CompareEphemeral.mutate((draft) => {
|
||||
const fromIndex = index;
|
||||
const toIndex = dropIndex > index ? dropIndex - 1 : dropIndex;
|
||||
|
||||
const member = draft.members[fromIndex];
|
||||
|
||||
draft.members.splice(fromIndex, 1);
|
||||
draft.members.splice(toIndex, 0, member);
|
||||
});
|
||||
@@ -99,7 +99,7 @@ export function TankCard({ index, tank }: TankCardProps) {
|
||||
return () => {
|
||||
draggable.current?.removeEventListener("pointerdown", handlePointerDown);
|
||||
};
|
||||
}, []);
|
||||
}, [index]);
|
||||
|
||||
return (
|
||||
<StickyColumnHeaderCell width="0">
|
||||
@@ -141,7 +141,6 @@ export function TankCard({ index, tank }: TankCardProps) {
|
||||
</Text>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
<InsertionMarker index={index + 1} />
|
||||
</StickyColumnHeaderCell>
|
||||
);
|
||||
|
||||
@@ -84,7 +84,7 @@ export function Model() {
|
||||
|
||||
useEffect(() => {
|
||||
function handleModelTransform(
|
||||
event: QuicklimeEvent<ModelTransformEventData>
|
||||
event: QuicklimeEvent<ModelTransformEventData>,
|
||||
) {
|
||||
turretGroup.current.rotation.z = event.data.yaw;
|
||||
gunGroup.current.rotation.x = event.data.pitch;
|
||||
@@ -171,6 +171,49 @@ export function Model() {
|
||||
turretModel.gun_origin.y,
|
||||
]}
|
||||
>
|
||||
<group
|
||||
position={[
|
||||
-turretTankModel.turret_origin.x -
|
||||
turretTrackModel.origin.x -
|
||||
turretModel.gun_origin.x,
|
||||
-turretTankModel.turret_origin.z -
|
||||
turretTrackModel.origin.z -
|
||||
turretModel.gun_origin.z,
|
||||
-turretTankModel.turret_origin.y -
|
||||
turretTrackModel.origin.y -
|
||||
turretModel.gun_origin.y,
|
||||
]}
|
||||
>
|
||||
{turretNodes.map((node) => {
|
||||
const isCurrentMantlet =
|
||||
node.name ===
|
||||
`gun_${turretModel.guns[turret.turret.guns.at(-1)!.id].model_id.toString().padStart(2, "0")}_mask`;
|
||||
// const isCurrentGun =
|
||||
// node.name ===
|
||||
// `gun_${gunModel.model_id.toString().padStart(2, "0")}`;
|
||||
const isVisible = isCurrentMantlet;
|
||||
|
||||
if (!isVisible) return null;
|
||||
|
||||
return jsxTree(node, {
|
||||
mesh(_, props, key) {
|
||||
return (
|
||||
<mesh
|
||||
{...props}
|
||||
key={key}
|
||||
castShadow
|
||||
receiveShadow
|
||||
onPointerDown={(event) => {
|
||||
enablePitchRotation.current = true;
|
||||
handlePointerDown(event);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
||||
})}
|
||||
</group>
|
||||
|
||||
<group
|
||||
position={[
|
||||
-gunTankModel.turret_origin.x -
|
||||
@@ -185,13 +228,13 @@ export function Model() {
|
||||
]}
|
||||
>
|
||||
{gunNodes.map((node) => {
|
||||
const isCurrentMantlet =
|
||||
node.name ===
|
||||
`gun_${gunModel.model_id.toString().padStart(2, "0")}_mask`;
|
||||
// const isCurrentMantlet =
|
||||
// node.name ===
|
||||
// `gun_${gunModel.model_id.toString().padStart(2, "0")}_mask`;
|
||||
const isCurrentGun =
|
||||
node.name ===
|
||||
`gun_${gunModel.model_id.toString().padStart(2, "0")}`;
|
||||
const isVisible = isCurrentGun || isCurrentMantlet;
|
||||
const isVisible = isCurrentGun;
|
||||
|
||||
if (!isVisible) return null;
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { Table } from "@radix-ui/themes";
|
||||
import type { RowHeaderCellProps } from "@radix-ui/themes/src/components/table.js";
|
||||
|
||||
export function StickyRowHeaderCell({ style, ...props }: RowHeaderCellProps) {
|
||||
interface Props extends RowHeaderCellProps {
|
||||
left?: string | number;
|
||||
}
|
||||
|
||||
export function StickyRowHeaderCell({ style, left = 0, ...props }: Props) {
|
||||
return (
|
||||
<Table.RowHeaderCell
|
||||
style={{
|
||||
position: "sticky",
|
||||
left: 0,
|
||||
left,
|
||||
backgroundColor: "var(--color-panel)",
|
||||
...style,
|
||||
}}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { youtubers } from '@blitzkit/core';
|
||||
import { Box, Flex, Heading, Link, Skeleton, Text } from '@radix-ui/themes';
|
||||
import { awaitableReviews } from '../../core/awaitables/reviews';
|
||||
import { Var } from '../../core/radix/var';
|
||||
import { useLocale } from '../../hooks/useLocale';
|
||||
import { Duel } from '../../stores/duel';
|
||||
import type { MaybeSkeletonComponentProps } from '../../types/maybeSkeletonComponentProps';
|
||||
import { PageWrapper } from '../PageWrapper';
|
||||
import { VerifiedIcon } from '../VerifiedIcon';
|
||||
import { youtubers } from "@blitzkit/core";
|
||||
import { Box, Flex, Heading, Link, Skeleton, Text } from "@radix-ui/themes";
|
||||
import { awaitableReviews } from "../../core/awaitables/reviews";
|
||||
import { Var } from "../../core/radix/var";
|
||||
import { useLocale } from "../../hooks/useLocale";
|
||||
import { Duel } from "../../stores/duel";
|
||||
import type { MaybeSkeletonComponentProps } from "../../types/maybeSkeletonComponentProps";
|
||||
import { PageWrapper } from "../PageWrapper";
|
||||
import { VerifiedIcon } from "../VerifiedIcon";
|
||||
|
||||
const reviews = await awaitableReviews;
|
||||
|
||||
@@ -47,22 +47,22 @@ export function VideoSection({ skeleton }: MaybeSkeletonComponentProps) {
|
||||
<Flex
|
||||
direction="column"
|
||||
style={{
|
||||
borderRadius: 'var(--radius-3)',
|
||||
overflow: 'hidden',
|
||||
borderRadius: "var(--radius-3)",
|
||||
overflow: "hidden",
|
||||
background: skeleton
|
||||
? Var('color-panel-solid')
|
||||
? Var("color-panel-solid")
|
||||
: `url(${image})`,
|
||||
backgroundPosition: '0 18px',
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: "0 18px",
|
||||
backgroundSize: "cover",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
background: skeleton ? 'transparent' : `url(${image})`,
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center',
|
||||
background: skeleton ? "transparent" : `url(${image})`,
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
height: 128,
|
||||
aspectRatio: '16 / 9',
|
||||
aspectRatio: "16 / 9",
|
||||
}}
|
||||
/>
|
||||
<Flex
|
||||
@@ -70,8 +70,8 @@ export function VideoSection({ skeleton }: MaybeSkeletonComponentProps) {
|
||||
width="100%"
|
||||
justify="center"
|
||||
style={{
|
||||
backdropFilter: 'blur(4rem)',
|
||||
WebkitBackdropFilter: 'blur(4rem)',
|
||||
backdropFilter: "blur(4rem)",
|
||||
WebkitBackdropFilter: "blur(4rem)",
|
||||
}}
|
||||
align="center"
|
||||
gap="1"
|
||||
|
||||
@@ -8,7 +8,7 @@ const tanks = Object.values(tankDefinitions.tanks).filter((tank) => {
|
||||
const turret = tank.turrets.at(-1)!;
|
||||
const turretModel = tankModel.turrets[turret.id];
|
||||
|
||||
return tank.tier >= 10 && !turretModel.yaw;
|
||||
return !turretModel.yaw;
|
||||
});
|
||||
|
||||
export function curateMixer() {
|
||||
|
||||
@@ -76,7 +76,7 @@ export function tankCharacteristics(
|
||||
tankModelDefinition: ModelDefinition;
|
||||
equipmentDefinitions: EquipmentDefinitions;
|
||||
provisionDefinitions: ProvisionDefinitions;
|
||||
}
|
||||
},
|
||||
) {
|
||||
const preset = equipmentDefinitions.presets[tank.equipment_preset];
|
||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||
@@ -138,7 +138,7 @@ export function tankCharacteristics(
|
||||
provisionDefinitions.provisions[provision].crew
|
||||
? total + provisionDefinitions.provisions[provision].crew! / 100
|
||||
: total,
|
||||
0
|
||||
0,
|
||||
) + (hasImprovedVentilation ? 0.08 : 0);
|
||||
const commanderMastery = 1 + provisionCrewBonus;
|
||||
const loaderMastery =
|
||||
@@ -158,13 +158,13 @@ export function tankCharacteristics(
|
||||
coefficient(
|
||||
[applyReactiveArmor && shell.type !== ShellType.HE, -0.27],
|
||||
[applyDynamicArmor, -0.1],
|
||||
[applySpallLiner && shell.type === ShellType.HE, -0.2]
|
||||
[applySpallLiner && shell.type === ShellType.HE, -0.2],
|
||||
);
|
||||
const assaultDamageCoefficient =
|
||||
gun.assault_ranges && gun.assault_ranges.types.includes(shell.type)
|
||||
? gun.assault_ranges.ranges.find(
|
||||
({ distance }) => distance >= assaultDistance
|
||||
)?.factor ?? 0
|
||||
? (gun.assault_ranges.ranges.find(
|
||||
({ distance }) => distance >= assaultDistance,
|
||||
)?.factor ?? 0)
|
||||
: 1;
|
||||
const moduleDamageCoefficient = coefficient([hasTungsten, 0.15]);
|
||||
const reloadCoefficient =
|
||||
@@ -178,16 +178,16 @@ export function tankCharacteristics(
|
||||
const healthCoefficient = coefficient(
|
||||
[hasSandbagArmor, 0.03],
|
||||
[hasEnhancedSandbagArmor, 0.06],
|
||||
[hasImprovedAssembly, 0.04]
|
||||
[hasImprovedAssembly, 0.04],
|
||||
);
|
||||
const shellVelocityCoefficient = coefficient(
|
||||
[hasSupercharger, 0.35],
|
||||
[hasImprovedGunPowder, 0.3]
|
||||
[hasImprovedGunPowder, 0.3],
|
||||
);
|
||||
const aimTimeCoefficient =
|
||||
coefficient(
|
||||
[hasEnhancedGunLayingDrive, -0.15],
|
||||
[hasReticleCalibration, -0.3]
|
||||
[hasReticleCalibration, -0.3],
|
||||
) * coefficient([true, degressiveStat(gunnerMastery)]);
|
||||
const dispersionStillCoefficient =
|
||||
coefficient([hasRefinedGun, -0.15], [hasReticleCalibration, -0.3]) *
|
||||
@@ -197,20 +197,20 @@ export function tankCharacteristics(
|
||||
-0.12,
|
||||
]);
|
||||
const dispersionHullTraverseCoefficient = coefficient(
|
||||
[hasVerticalStabilizer, -0.15],
|
||||
[true, -crewSkills.smooth_turn / 100]
|
||||
[hasVerticalStabilizer, -0.12],
|
||||
[true, -crewSkills.smooth_turn / 100],
|
||||
);
|
||||
const dispersionAfterShotCoefficient = coefficient(
|
||||
[hasVerticalStabilizer, -0.15],
|
||||
[true, -crewSkills.soft_recoil / 100]
|
||||
[hasVerticalStabilizer, -0.12],
|
||||
[true, -crewSkills.soft_recoil / 100],
|
||||
);
|
||||
const dispersionMovingCoefficient = coefficient(
|
||||
[hasVerticalStabilizer, -0.15],
|
||||
[true, -crewSkills.smooth_driving / 100]
|
||||
[hasVerticalStabilizer, -0.12],
|
||||
[true, -crewSkills.smooth_driving / 100],
|
||||
);
|
||||
const dispersionTurretTraverseCoefficient = coefficient(
|
||||
[hasVerticalStabilizer, -0.15],
|
||||
[true, -crewSkills.smooth_turret * (2 / 100)]
|
||||
[hasVerticalStabilizer, -0.12],
|
||||
[true, -crewSkills.smooth_turret * (2 / 100)],
|
||||
);
|
||||
const enginePowerCoefficient = coefficient(
|
||||
[
|
||||
@@ -225,7 +225,7 @@ export function tankCharacteristics(
|
||||
[hasStandardFuel, 0.03],
|
||||
[hasImprovedFuel, 0.1],
|
||||
[hasGearOil, 0.03],
|
||||
[hasImprovedGearOil, 0.06]
|
||||
[hasImprovedGearOil, 0.06],
|
||||
);
|
||||
const turretTraverseCoefficient =
|
||||
coefficient([hasStandardFuel, 0.03], [hasImprovedFuel, 0.1]) *
|
||||
@@ -234,7 +234,7 @@ export function tankCharacteristics(
|
||||
coefficient(
|
||||
[hasImprovedControl, 0.11],
|
||||
[hasImprovedEnginePowerBoost, 0.01],
|
||||
[true, crewSkills.virtuoso / 100]
|
||||
[true, crewSkills.virtuoso / 100],
|
||||
) * coefficient([true, progressiveStat(driverMastery)]);
|
||||
|
||||
const resistanceHardCoefficient =
|
||||
@@ -253,22 +253,22 @@ export function tankCharacteristics(
|
||||
tank.class === TankClass.HEAVY
|
||||
? 0.06
|
||||
: tank.class === TankClass.MEDIUM
|
||||
? 0.08
|
||||
: tank.class === TankClass.LIGHT
|
||||
? 0.11
|
||||
: 0.04,
|
||||
? 0.08
|
||||
: tank.class === TankClass.LIGHT
|
||||
? 0.11
|
||||
: 0.04,
|
||||
]) * coefficient([true, progressiveStat(commanderMastery)]);
|
||||
const fireChanceCoefficient = coefficient([hasProtectiveKit, -0.2]);
|
||||
|
||||
const speedForwardsSum = sum(
|
||||
[hasImprovedEnginePowerBoost, 4],
|
||||
[hasGearOil, 2],
|
||||
[hasImprovedGearOil, 4]
|
||||
[hasImprovedGearOil, 4],
|
||||
);
|
||||
const speedBackwardsSum = sum(
|
||||
[hasImprovedEnginePowerBoost, 8],
|
||||
[hasGearOil, 2],
|
||||
[hasImprovedGearOil, 4]
|
||||
[hasImprovedGearOil, 4],
|
||||
);
|
||||
const camouflageCoefficientMoving = sum(
|
||||
[
|
||||
@@ -278,8 +278,8 @@ export function tankCharacteristics(
|
||||
tank.class === TankClass.TANK_DESTROYER
|
||||
? 0.04
|
||||
: tank.class === TankClass.HEAVY
|
||||
? 0.03
|
||||
: 0.02,
|
||||
? 0.03
|
||||
: 0.02,
|
||||
]),
|
||||
],
|
||||
[
|
||||
@@ -287,11 +287,11 @@ export function tankCharacteristics(
|
||||
tank.class === TankClass.HEAVY
|
||||
? 0.02
|
||||
: tank.class === TankClass.MEDIUM
|
||||
? 0.04
|
||||
: tank.class === TankClass.LIGHT
|
||||
? 0.07
|
||||
: 0.1,
|
||||
]
|
||||
? 0.04
|
||||
: tank.class === TankClass.LIGHT
|
||||
? 0.07
|
||||
: 0.1,
|
||||
],
|
||||
);
|
||||
const camouflageCoefficientStill = sum(
|
||||
[
|
||||
@@ -302,10 +302,10 @@ export function tankCharacteristics(
|
||||
tank.class === TankClass.TANK_DESTROYER
|
||||
? 0.04
|
||||
: tank.class === TankClass.HEAVY
|
||||
? 0.03
|
||||
: 0.02,
|
||||
? 0.03
|
||||
: 0.02,
|
||||
],
|
||||
[true, crewSkills.camouflage * (3 / 100)]
|
||||
[true, crewSkills.camouflage * (3 / 100)],
|
||||
),
|
||||
],
|
||||
[
|
||||
@@ -313,18 +313,18 @@ export function tankCharacteristics(
|
||||
tank.class === TankClass.HEAVY
|
||||
? 0.04
|
||||
: tank.class === TankClass.MEDIUM
|
||||
? 0.08
|
||||
: tank.class === TankClass.LIGHT
|
||||
? 0.14
|
||||
: 0.2,
|
||||
]
|
||||
? 0.08
|
||||
: tank.class === TankClass.LIGHT
|
||||
? 0.14
|
||||
: 0.2,
|
||||
],
|
||||
);
|
||||
|
||||
const size = normalizeBoundingBox(
|
||||
unionBoundingBox(
|
||||
tankModelDefinition.bounding_box,
|
||||
turretModelDefinition.bounding_box
|
||||
)
|
||||
turretModelDefinition.bounding_box,
|
||||
),
|
||||
);
|
||||
const weightKg =
|
||||
tank.weight + engine.weight + track.weight + turret.weight + gun.weight;
|
||||
@@ -344,7 +344,7 @@ export function tankCharacteristics(
|
||||
shell,
|
||||
damageCoefficient,
|
||||
reloadCoefficient,
|
||||
intraClipCoefficient
|
||||
intraClipCoefficient,
|
||||
);
|
||||
const intraClip =
|
||||
gun.gun_type?.$case === "regular"
|
||||
@@ -398,7 +398,7 @@ export function tankCharacteristics(
|
||||
const shellReloads =
|
||||
gun.gun_type!.$case === "auto_reloader"
|
||||
? gun.gun_type!.value.shell_reloads.map(
|
||||
(reload) => reload * reloadCoefficient
|
||||
(reload) => reload * reloadCoefficient,
|
||||
)
|
||||
: undefined;
|
||||
const shellReload =
|
||||
|
||||
Reference in new issue
Block a user