mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-11-02 15:30:37 +01:00
feat: burst data
This commit is contained in:
1 parent
79c450798c
commit
c20f8c5040
37 files changed
+973
-1378
No files matched your search
@@ -197,15 +197,10 @@ export const researchCommand = new Promise<CommandRegistry>((resolve) => {
|
|||||||
|
|
||||||
turret.guns.forEach((gun) => {
|
turret.guns.forEach((gun) => {
|
||||||
if (
|
if (
|
||||||
gun.gun_type!.value.base.research_cost !== undefined &&
|
gun.research_cost !== undefined &&
|
||||||
typeof gun.gun_type!.value.base.research_cost
|
typeof gun.research_cost.research_cost_type!.value === 'number'
|
||||||
.research_cost_type!.value === 'number'
|
|
||||||
) {
|
) {
|
||||||
gunXps.set(
|
gunXps.set(gun.id, gun.research_cost.research_cost_type!.value);
|
||||||
gun.gun_type!.value.base.id,
|
|
||||||
gun.gun_type!.value.base.research_cost.research_cost_type!
|
|
||||||
.value,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
GunDefinition,
|
GunDefinition,
|
||||||
GunDefinitionAutoReloaderProperties,
|
GunDefinitionAutoReloader,
|
||||||
ShellDefinition,
|
ShellDefinition,
|
||||||
} from '../protos';
|
} from '../protos';
|
||||||
|
|
||||||
@@ -15,34 +15,31 @@ export function resolveDpm(
|
|||||||
let dps: number;
|
let dps: number;
|
||||||
|
|
||||||
if (gun.gun_type!.$case === 'regular') {
|
if (gun.gun_type!.$case === 'regular') {
|
||||||
dps = alpha / (reloadCoefficient * gun.gun_type!.value.extension.reload);
|
dps = alpha / (reloadCoefficient * gun.gun_type!.value.reload);
|
||||||
} else if (gun.gun_type!.$case === 'auto_loader') {
|
} else if (gun.gun_type!.$case === 'auto_loader') {
|
||||||
dps =
|
dps =
|
||||||
(alpha * gun.gun_type!.value.extension.shell_count) /
|
(alpha * gun.gun_type!.value.shell_count) /
|
||||||
(gun.gun_type!.value.extension.clip_reload * reloadCoefficient +
|
(gun.gun_type!.value.clip_reload * reloadCoefficient +
|
||||||
(gun.gun_type!.value.extension.shell_count - 1) *
|
(gun.gun_type!.value.shell_count - 1) *
|
||||||
gun.gun_type!.value.extension.intra_clip *
|
gun.gun_type!.value.intra_clip *
|
||||||
intraClipCoefficient);
|
intraClipCoefficient);
|
||||||
} else {
|
} else {
|
||||||
const mostOptimalShell =
|
const mostOptimalShell = gun.gun_type!.value.shell_reloads.reduce<null | {
|
||||||
gun.gun_type!.value.extension.shell_reloads.reduce<null | {
|
index: number;
|
||||||
index: number;
|
reload: number;
|
||||||
reload: number;
|
}>((current, reloadRaw, index) => {
|
||||||
}>((current, reloadRaw, index) => {
|
const reload =
|
||||||
const reload =
|
reloadRaw * reloadCoefficient +
|
||||||
reloadRaw * reloadCoefficient +
|
(index > 0
|
||||||
(index > 0
|
? (gun.gun_type!.value as GunDefinitionAutoReloader).intra_clip *
|
||||||
? (
|
intraClipCoefficient
|
||||||
gun.gun_type!.value
|
: 0);
|
||||||
.extension as GunDefinitionAutoReloaderProperties
|
|
||||||
).intra_clip * intraClipCoefficient
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
if (current === null || reload < current.reload) {
|
if (current === null || reload < current.reload) {
|
||||||
return { index, reload };
|
return { index, reload };
|
||||||
}
|
}
|
||||||
return current;
|
return current;
|
||||||
}, null)!;
|
}, null)!;
|
||||||
|
|
||||||
dps = alpha / mostOptimalShell?.reload;
|
dps = alpha / mostOptimalShell?.reload;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ export function uniqueGuns(turrets: TurretDefinition[]) {
|
|||||||
|
|
||||||
forEachRight(turrets, (turret) => {
|
forEachRight(turrets, (turret) => {
|
||||||
forEachRight(turret.guns, (gun) => {
|
forEachRight(turret.guns, (gun) => {
|
||||||
if (!gunIds.has(gun.gun_type!.value.base.id)) {
|
if (!gunIds.has(gun.id)) {
|
||||||
gunIds.add(gun.gun_type!.value.base.id);
|
gunIds.add(gun.id);
|
||||||
guns.push({ turret, gun });
|
guns.push({ turret, gun });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -108,58 +108,48 @@ message GunDefinition {
|
|||||||
GunDefinitionAutoLoader auto_loader = 2;
|
GunDefinitionAutoLoader auto_loader = 2;
|
||||||
GunDefinitionAutoReloader auto_reloader = 3;
|
GunDefinitionAutoReloader auto_reloader = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
required uint32 id = 4;
|
||||||
|
required float rotation_speed = 5;
|
||||||
|
optional ResearchCost research_cost = 6;
|
||||||
|
required uint32 weight = 7;
|
||||||
|
required I18nString name = 8;
|
||||||
|
required uint32 tier = 9;
|
||||||
|
repeated ShellDefinition shells = 10;
|
||||||
|
required float camouflage_loss = 11;
|
||||||
|
required float aim_time = 12;
|
||||||
|
required float dispersion_base = 13;
|
||||||
|
required float dispersion_traverse = 14;
|
||||||
|
required float dispersion_shot = 15;
|
||||||
|
required float dispersion_damaged = 16;
|
||||||
|
repeated Unlock unlocks = 17;
|
||||||
|
required uint32 shell_capacity = 18;
|
||||||
|
optional AssaultRanges assault_ranges = 19;
|
||||||
|
optional Burst burst = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GunDefinitionRegular {
|
message GunDefinitionRegular {
|
||||||
required GunDefinitionBase base = 1;
|
|
||||||
required GunDefinitionRegularProperties extension = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GunDefinitionRegularProperties {
|
|
||||||
required float reload = 1;
|
required float reload = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GunDefinitionAutoLoader {
|
message GunDefinitionAutoLoader {
|
||||||
required GunDefinitionBase base = 1;
|
|
||||||
required GunDefinitionAutoLoaderProperties extension = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GunDefinitionAutoLoaderProperties {
|
|
||||||
required float clip_reload = 1;
|
required float clip_reload = 1;
|
||||||
required float intra_clip = 2;
|
required float intra_clip = 2;
|
||||||
required float shell_count = 3;
|
required float shell_count = 3;
|
||||||
|
optional Burst burst = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Burst {
|
||||||
|
required uint32 count = 1;
|
||||||
|
required float interval = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GunDefinitionAutoReloader {
|
message GunDefinitionAutoReloader {
|
||||||
required GunDefinitionBase base = 1;
|
|
||||||
required GunDefinitionAutoReloaderProperties extension = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GunDefinitionAutoReloaderProperties {
|
|
||||||
repeated float shell_reloads = 1;
|
repeated float shell_reloads = 1;
|
||||||
required float intra_clip = 2;
|
required float intra_clip = 2;
|
||||||
required float shell_count = 3;
|
required float shell_count = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GunDefinitionBase {
|
|
||||||
required uint32 id = 1;
|
|
||||||
required float rotation_speed = 2;
|
|
||||||
optional ResearchCost research_cost = 3;
|
|
||||||
required uint32 weight = 4;
|
|
||||||
required I18nString name = 5;
|
|
||||||
required uint32 tier = 6;
|
|
||||||
repeated ShellDefinition shells = 7;
|
|
||||||
required float camouflage_loss = 8;
|
|
||||||
required float aim_time = 9;
|
|
||||||
required float dispersion_base = 10;
|
|
||||||
required float dispersion_traverse = 11;
|
|
||||||
required float dispersion_shot = 12;
|
|
||||||
required float dispersion_damaged = 13;
|
|
||||||
repeated Unlock unlocks = 14;
|
|
||||||
required uint32 shell_capacity = 15;
|
|
||||||
optional AssaultRanges assault_ranges = 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
message AssaultRanges {
|
message AssaultRanges {
|
||||||
repeated AssaultRange ranges = 1;
|
repeated AssaultRange ranges = 1;
|
||||||
repeated ShellType types = 2;
|
repeated ShellType types = 2;
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -12,7 +12,6 @@ import {
|
|||||||
EquipmentSlot,
|
EquipmentSlot,
|
||||||
GameDefinitions,
|
GameDefinitions,
|
||||||
GunDefinition,
|
GunDefinition,
|
||||||
GunDefinitionBase,
|
|
||||||
I18nString,
|
I18nString,
|
||||||
MapDefinitions,
|
MapDefinitions,
|
||||||
ModelDefinitions,
|
ModelDefinitions,
|
||||||
@@ -274,6 +273,7 @@ interface VehicleDefinitions {
|
|||||||
pumpGunMode?: boolean;
|
pumpGunMode?: boolean;
|
||||||
pumpGunReloadTimes?: string;
|
pumpGunReloadTimes?: string;
|
||||||
clip?: { count: number; rate: number };
|
clip?: { count: number; rate: number };
|
||||||
|
burst?: { count: number; rate: number };
|
||||||
models: { undamaged: string };
|
models: { undamaged: string };
|
||||||
extras?: {
|
extras?: {
|
||||||
trayShell?: {
|
trayShell?: {
|
||||||
@@ -1304,7 +1304,12 @@ export async function definitions() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const base = {
|
if (gun.burst) {
|
||||||
|
console.log(tankId);
|
||||||
|
console.log(gun.burst);
|
||||||
|
}
|
||||||
|
|
||||||
|
tankDefinitions.tanks[tankId].turrets[turretIndex].guns.push({
|
||||||
id: gunId,
|
id: gunId,
|
||||||
weight: gunListEntry.weight,
|
weight: gunListEntry.weight,
|
||||||
rotation_speed: gunListEntry.rotationSpeed,
|
rotation_speed: gunListEntry.rotationSpeed,
|
||||||
@@ -1324,41 +1329,39 @@ export async function definitions() {
|
|||||||
unlocks: resolveUnlocks(gun.unlocks),
|
unlocks: resolveUnlocks(gun.unlocks),
|
||||||
shell_capacity: gun.maxAmmo ?? gunListEntry.maxAmmo,
|
shell_capacity: gun.maxAmmo ?? gunListEntry.maxAmmo,
|
||||||
assault_ranges,
|
assault_ranges,
|
||||||
} satisfies GunDefinitionBase;
|
|
||||||
|
|
||||||
tankDefinitions.tanks[tankId].turrets[turretIndex].guns.push({
|
|
||||||
gun_type:
|
gun_type:
|
||||||
gunType === 'regular'
|
gunType === 'regular'
|
||||||
? {
|
? {
|
||||||
$case: 'regular',
|
$case: 'regular',
|
||||||
value: {
|
value: {
|
||||||
base,
|
reload: gun.reloadTime,
|
||||||
extension: { reload: gun.reloadTime },
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: gunType === 'autoReloader'
|
: gunType === 'autoReloader'
|
||||||
? {
|
? {
|
||||||
$case: 'auto_reloader',
|
$case: 'auto_reloader',
|
||||||
value: {
|
value: {
|
||||||
base,
|
intra_clip: 60 / gun.clip!.rate,
|
||||||
extension: {
|
shell_count: gunClipCount,
|
||||||
intra_clip: 60 / gun.clip!.rate,
|
shell_reloads: gun
|
||||||
shell_count: gunClipCount,
|
.pumpGunReloadTimes!.split(' ')
|
||||||
shell_reloads: gun
|
.map(Number),
|
||||||
.pumpGunReloadTimes!.split(' ')
|
|
||||||
.map(Number),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
$case: 'auto_loader',
|
$case: 'auto_loader',
|
||||||
value: {
|
value: {
|
||||||
base,
|
intra_clip: 60 / gun.clip!.rate,
|
||||||
extension: {
|
clip_reload: gun.reloadTime,
|
||||||
intra_clip: 60 / gun.clip!.rate,
|
shell_count: gunClipCount,
|
||||||
clip_reload: gun.reloadTime,
|
burst:
|
||||||
shell_count: gunClipCount,
|
gun.burst && gun.burst.count > 1
|
||||||
},
|
? {
|
||||||
|
count: gun.burst.count,
|
||||||
|
interval: 60 / gun.burst.rate,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} satisfies GunDefinition);
|
} satisfies GunDefinition);
|
||||||
@@ -1407,7 +1410,7 @@ export async function definitions() {
|
|||||||
|
|
||||||
tankDefinitions.tanks[tankId].turrets[turretIndex].guns[
|
tankDefinitions.tanks[tankId].turrets[turretIndex].guns[
|
||||||
gunIndex
|
gunIndex
|
||||||
].gun_type!.value.base!.shells.push({
|
].shells.push({
|
||||||
id: shellId,
|
id: shellId,
|
||||||
name: shellName,
|
name: shellName,
|
||||||
velocity: gunShellEntry.speed,
|
velocity: gunShellEntry.speed,
|
||||||
@@ -1495,9 +1498,7 @@ export async function definitions() {
|
|||||||
turret.research_cost = turretXps.get(turret.id);
|
turret.research_cost = turretXps.get(turret.id);
|
||||||
|
|
||||||
Object.values(turret.guns).forEach((gunRaw) => {
|
Object.values(turret.guns).forEach((gunRaw) => {
|
||||||
gunRaw.gun_type!.value.base!.research_cost = gunXps.get(
|
gunRaw.research_cost = gunXps.get(gunRaw.id);
|
||||||
gunRaw.gun_type!.value.base!.id,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -100,8 +100,7 @@ export function ArmorPlateDisplay() {
|
|||||||
const { protagonist } = duelStore.getState();
|
const { protagonist } = duelStore.getState();
|
||||||
const tank = draft.model;
|
const tank = draft.model;
|
||||||
const turret = tank.turrets[protagonist.turret.id];
|
const turret = tank.turrets[protagonist.turret.id];
|
||||||
const gun =
|
const gun = turret.guns[protagonist.gun.id];
|
||||||
turret.guns[protagonist.gun.gun_type!.value.base.id];
|
|
||||||
const track = tank.tracks[protagonist.track.id];
|
const track = tank.tracks[protagonist.track.id];
|
||||||
|
|
||||||
if (highlightArmor.name.startsWith('hull_')) {
|
if (highlightArmor.name.startsWith('hull_')) {
|
||||||
@@ -154,12 +153,8 @@ export function ArmorPlateDisplay() {
|
|||||||
const turret = tank.turrets[protagonist.turret.id];
|
const turret = tank.turrets[protagonist.turret.id];
|
||||||
const initialTurret =
|
const initialTurret =
|
||||||
initialTank.turrets[protagonist.turret.id];
|
initialTank.turrets[protagonist.turret.id];
|
||||||
const gun =
|
const gun = turret.guns[protagonist.gun.id];
|
||||||
turret.guns[protagonist.gun.gun_type!.value.base.id];
|
const initialGun = initialTurret.guns[protagonist.gun.id];
|
||||||
const initialGun =
|
|
||||||
initialTurret.guns[
|
|
||||||
protagonist.gun.gun_type!.value.base.id
|
|
||||||
];
|
|
||||||
const track = tank.tracks[protagonist.track.id];
|
const track = tank.tracks[protagonist.track.id];
|
||||||
const initialTrack =
|
const initialTrack =
|
||||||
initialTank.tracks[protagonist.track.id];
|
initialTank.tracks[protagonist.track.id];
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ export const PrimaryArmorScene = memo(() => {
|
|||||||
const tankModelDefinition = useTankModelDefinition();
|
const tankModelDefinition = useTankModelDefinition();
|
||||||
const trackModelDefinition = tankModelDefinition.tracks[track.id];
|
const trackModelDefinition = tankModelDefinition.tracks[track.id];
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||||
turretModelDefinition.guns[gun.gun_type!.value.base.id];
|
|
||||||
const hullOrigin = correctZYTuple(trackModelDefinition.origin);
|
const hullOrigin = correctZYTuple(trackModelDefinition.origin);
|
||||||
const turretOrigin = correctZYTuple(tankModelDefinition.turret_origin);
|
const turretOrigin = correctZYTuple(tankModelDefinition.turret_origin);
|
||||||
const gunOrigin = correctZYTuple(turretModelDefinition.gun_origin);
|
const gunOrigin = correctZYTuple(turretModelDefinition.gun_origin);
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
|
|||||||
const tankModelDefinition = useTankModelDefinition();
|
const tankModelDefinition = useTankModelDefinition();
|
||||||
const trackModelDefinition = tankModelDefinition.tracks[track.id];
|
const trackModelDefinition = tankModelDefinition.tracks[track.id];
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||||
turretModelDefinition.guns[gun.gun_type!.value.base.id];
|
|
||||||
const hullOrigin = correctZYTuple(trackModelDefinition.origin);
|
const hullOrigin = correctZYTuple(trackModelDefinition.origin);
|
||||||
const turretOrigin = correctZYTuple(tankModelDefinition.turret_origin);
|
const turretOrigin = correctZYTuple(tankModelDefinition.turret_origin);
|
||||||
const gunOrigin = correctZYTuple(turretModelDefinition.gun_origin);
|
const gunOrigin = correctZYTuple(turretModelDefinition.gun_origin);
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ export const StaticArmor = memo<ArmorSceneProps>(({ thicknessRange }) => {
|
|||||||
const tankModelDefinition = useTankModelDefinition();
|
const tankModelDefinition = useTankModelDefinition();
|
||||||
const trackModelDefinition = tankModelDefinition.tracks[track.id];
|
const trackModelDefinition = tankModelDefinition.tracks[track.id];
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||||
turretModelDefinition.guns[gun.gun_type!.value.base.id];
|
|
||||||
const hullOrigin = correctZYTuple(trackModelDefinition.origin);
|
const hullOrigin = correctZYTuple(trackModelDefinition.origin);
|
||||||
const turretOrigin = correctZYTuple(tankModelDefinition.turret_origin);
|
const turretOrigin = correctZYTuple(tankModelDefinition.turret_origin);
|
||||||
const gunOrigin = correctZYTuple(turretModelDefinition.gun_origin);
|
const gunOrigin = correctZYTuple(turretModelDefinition.gun_origin);
|
||||||
|
|||||||
@@ -33,43 +33,35 @@ export function Body({ stats }: BodyProps) {
|
|||||||
<StickyColumnHeaderCell key={key} top={137}>
|
<StickyColumnHeaderCell key={key} top={137}>
|
||||||
<Flex justify="center">
|
<Flex justify="center">
|
||||||
<Flex>
|
<Flex>
|
||||||
{gun.gun_type!.value.base.shells.map(
|
{gun.shells.map((thisShell, shellIndex) => (
|
||||||
(thisShell, shellIndex) => (
|
<IconButton
|
||||||
<IconButton
|
color={thisShell.id === shell.id ? undefined : 'gray'}
|
||||||
color={thisShell.id === shell.id ? undefined : 'gray'}
|
variant="soft"
|
||||||
variant="soft"
|
key={thisShell.id}
|
||||||
key={thisShell.id}
|
style={{
|
||||||
style={{
|
borderTopLeftRadius: shellIndex === 0 ? undefined : 0,
|
||||||
borderTopLeftRadius: shellIndex === 0 ? undefined : 0,
|
borderBottomLeftRadius:
|
||||||
borderBottomLeftRadius:
|
shellIndex === 0 ? undefined : 0,
|
||||||
shellIndex === 0 ? undefined : 0,
|
borderTopRightRadius:
|
||||||
borderTopRightRadius:
|
shellIndex === gun.shells.length - 1 ? undefined : 0,
|
||||||
shellIndex ===
|
borderBottomRightRadius:
|
||||||
gun.gun_type!.value.base.shells.length - 1
|
shellIndex === gun.shells.length - 1 ? undefined : 0,
|
||||||
? undefined
|
marginLeft: shellIndex === 0 ? 0 : -1,
|
||||||
: 0,
|
}}
|
||||||
borderBottomRightRadius:
|
onClick={() => {
|
||||||
shellIndex ===
|
mutateCompareEphemeral((draft) => {
|
||||||
gun.gun_type!.value.base.shells.length - 1
|
draft.members[index].shell = thisShell;
|
||||||
? undefined
|
});
|
||||||
: 0,
|
}}
|
||||||
marginLeft: shellIndex === 0 ? 0 : -1,
|
>
|
||||||
}}
|
<img
|
||||||
onClick={() => {
|
alt={unwrap(thisShell.name)}
|
||||||
mutateCompareEphemeral((draft) => {
|
width={16}
|
||||||
draft.members[index].shell = thisShell;
|
height={16}
|
||||||
});
|
src={asset(`icons/shells/${thisShell.icon}.webp`)}
|
||||||
}}
|
/>
|
||||||
>
|
</IconButton>
|
||||||
<img
|
))}
|
||||||
alt={unwrap(thisShell.name)}
|
|
||||||
width={16}
|
|
||||||
height={16}
|
|
||||||
src={asset(`icons/shells/${thisShell.icon}.webp`)}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</StickyColumnHeaderCell>
|
</StickyColumnHeaderCell>
|
||||||
|
|||||||
@@ -250,8 +250,7 @@ export function CompareTable({ stats }: CompareTableProps) {
|
|||||||
|
|
||||||
member.turret = member.tank.turrets[0];
|
member.turret = member.tank.turrets[0];
|
||||||
member.gun = member.turret.guns[0];
|
member.gun = member.turret.guns[0];
|
||||||
member.shell =
|
member.shell = member.gun.shells[0];
|
||||||
member.gun.gun_type!.value.base.shells[0];
|
|
||||||
member.engine = member.tank.engines[0];
|
member.engine = member.tank.engines[0];
|
||||||
member.track = member.tank.tracks[0];
|
member.track = member.tank.tracks[0];
|
||||||
});
|
});
|
||||||
@@ -267,8 +266,7 @@ export function CompareTable({ stats }: CompareTableProps) {
|
|||||||
|
|
||||||
member.turret = member.tank.turrets.at(-1)!;
|
member.turret = member.tank.turrets.at(-1)!;
|
||||||
member.gun = member.turret.guns.at(-1)!;
|
member.gun = member.turret.guns.at(-1)!;
|
||||||
member.shell =
|
member.shell = member.gun.shells[0];
|
||||||
member.gun.gun_type!.value.base.shells[0];
|
|
||||||
member.engine = member.tank.engines.at(-1)!;
|
member.engine = member.tank.engines.at(-1)!;
|
||||||
member.track = member.tank.tracks.at(-1)!;
|
member.track = member.tank.tracks.at(-1)!;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export function ModuleManager({
|
|||||||
const draft = { ...modules };
|
const draft = { ...modules };
|
||||||
draft.turret = turret;
|
draft.turret = turret;
|
||||||
draft.gun = draft.turret.guns.at(-1)!;
|
draft.gun = draft.turret.guns.at(-1)!;
|
||||||
draft.shell = draft.gun.gun_type!.value.base.shells[0];
|
draft.shell = draft.gun.shells[0];
|
||||||
|
|
||||||
onChange?.(draft);
|
onChange?.(draft);
|
||||||
setTurretMenuOpen(false);
|
setTurretMenuOpen(false);
|
||||||
@@ -83,9 +83,7 @@ export function ModuleManager({
|
|||||||
|
|
||||||
<ModuleButton
|
<ModuleButton
|
||||||
module="gun"
|
module="gun"
|
||||||
discriminator={
|
discriminator={TIER_ROMAN_NUMERALS[modules.gun.tier]}
|
||||||
TIER_ROMAN_NUMERALS[modules.gun.gun_type!.value.base.tier]
|
|
||||||
}
|
|
||||||
onClick={() => setGunMenuOpen(true)}
|
onClick={() => setGunMenuOpen(true)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -95,18 +93,16 @@ export function ModuleManager({
|
|||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
|
|
||||||
<DropdownMenu.Content>
|
<DropdownMenu.Content>
|
||||||
<DropdownMenu.RadioGroup
|
<DropdownMenu.RadioGroup value={`${modules.gun.id}`}>
|
||||||
value={`${modules.gun.gun_type!.value.base.id}`}
|
|
||||||
>
|
|
||||||
{[...modules.turret.guns].reverse().map((gun) => {
|
{[...modules.turret.guns].reverse().map((gun) => {
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.RadioItem
|
<DropdownMenu.RadioItem
|
||||||
key={gun.gun_type!.value.base.id}
|
key={gun.id}
|
||||||
value={`${gun.gun_type!.value.base.id}`}
|
value={`${gun.id}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const draft = { ...modules };
|
const draft = { ...modules };
|
||||||
draft.gun = gun;
|
draft.gun = gun;
|
||||||
draft.shell = draft.gun.gun_type!.value.base.shells[0];
|
draft.shell = draft.gun.shells[0];
|
||||||
|
|
||||||
onChange?.(draft);
|
onChange?.(draft);
|
||||||
setGunMenuOpen(false);
|
setGunMenuOpen(false);
|
||||||
@@ -115,11 +111,9 @@ export function ModuleManager({
|
|||||||
<ModuleButton
|
<ModuleButton
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
module="gun"
|
module="gun"
|
||||||
discriminator={
|
discriminator={TIER_ROMAN_NUMERALS[gun.tier]}
|
||||||
TIER_ROMAN_NUMERALS[gun.gun_type!.value.base.tier]
|
|
||||||
}
|
|
||||||
/>{' '}
|
/>{' '}
|
||||||
{unwrap(gun.gun_type!.value.base.name)}
|
{unwrap(gun.name)}
|
||||||
</DropdownMenu.RadioItem>
|
</DropdownMenu.RadioItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -25,19 +25,18 @@ export function TankSearchCard({ tank, onSelect }: TankSearchCardProps) {
|
|||||||
|
|
||||||
const turret = tank.turrets.at(-1)!;
|
const turret = tank.turrets.at(-1)!;
|
||||||
const gun = turret.guns.at(-1)!;
|
const gun = turret.guns.at(-1)!;
|
||||||
const shell0 = gun.gun_type!.value.base.shells[0];
|
const shell0 = gun.shells[0];
|
||||||
const shell1 = gun.gun_type!.value.base.shells[1];
|
const shell1 = gun.shells[1];
|
||||||
const shell2 = gun.gun_type!.value.base.shells[2];
|
const shell2 = gun.shells[2];
|
||||||
const tracks = tank.tracks.at(-1)!;
|
const tracks = tank.tracks.at(-1)!;
|
||||||
const engine = tank.engines.at(-1)!;
|
const engine = tank.engines.at(-1)!;
|
||||||
const tankModelDefinition = modelDefinitions.models[tank.id];
|
const tankModelDefinition = modelDefinitions.models[tank.id];
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||||
turretModelDefinition.guns[gun.gun_type!.value.base.id];
|
|
||||||
|
|
||||||
switch (tankopediaSort.by) {
|
switch (tankopediaSort.by) {
|
||||||
case 'fire.aimTime':
|
case 'fire.aimTime':
|
||||||
return gun.gun_type!.value.base.aim_time.toFixed(2);
|
return gun.aim_time.toFixed(2);
|
||||||
case 'fire.caliber':
|
case 'fire.caliber':
|
||||||
return shell0.caliber.toFixed(0);
|
return shell0.caliber.toFixed(0);
|
||||||
case 'fire.damage':
|
case 'fire.damage':
|
||||||
@@ -47,7 +46,7 @@ export function TankSearchCard({ tank, onSelect }: TankSearchCardProps) {
|
|||||||
case 'fire.dispersionMoving':
|
case 'fire.dispersionMoving':
|
||||||
return tracks.dispersion_move.toFixed(3);
|
return tracks.dispersion_move.toFixed(3);
|
||||||
case 'fire.dispersionStill':
|
case 'fire.dispersionStill':
|
||||||
return gun.gun_type!.value.base.dispersion_base.toFixed(3);
|
return gun.dispersion_base.toFixed(3);
|
||||||
case 'fire.dpm':
|
case 'fire.dpm':
|
||||||
return resolveDpm(gun, shell0).toFixed(0);
|
return resolveDpm(gun, shell0).toFixed(0);
|
||||||
case 'fire.dpmPremium':
|
case 'fire.dpmPremium':
|
||||||
@@ -63,7 +62,7 @@ export function TankSearchCard({ tank, onSelect }: TankSearchCardProps) {
|
|||||||
case 'fire.shellVelocity':
|
case 'fire.shellVelocity':
|
||||||
return shell0.velocity.toFixed(0);
|
return shell0.velocity.toFixed(0);
|
||||||
case 'fire.shellCapacity':
|
case 'fire.shellCapacity':
|
||||||
return gun.gun_type!.value.base.shell_capacity.toFixed(0);
|
return gun.shell_capacity.toFixed(0);
|
||||||
case 'fire.shellRange':
|
case 'fire.shellRange':
|
||||||
return shell0.range.toFixed(0);
|
return shell0.range.toFixed(0);
|
||||||
case 'fire.gunDepression':
|
case 'fire.gunDepression':
|
||||||
@@ -89,7 +88,7 @@ export function TankSearchCard({ tank, onSelect }: TankSearchCardProps) {
|
|||||||
engine.weight +
|
engine.weight +
|
||||||
tracks.weight +
|
tracks.weight +
|
||||||
turret.weight +
|
turret.weight +
|
||||||
gun.gun_type!.value.base.weight)
|
gun.weight)
|
||||||
).toFixed(1);
|
).toFixed(1);
|
||||||
case 'maneuverability.weight':
|
case 'maneuverability.weight':
|
||||||
return (
|
return (
|
||||||
@@ -97,7 +96,7 @@ export function TankSearchCard({ tank, onSelect }: TankSearchCardProps) {
|
|||||||
engine.weight +
|
engine.weight +
|
||||||
tracks.weight +
|
tracks.weight +
|
||||||
turret.weight +
|
turret.weight +
|
||||||
gun.gun_type!.value.base.weight) /
|
gun.weight) /
|
||||||
1000
|
1000
|
||||||
).toFixed(1);
|
).toFixed(1);
|
||||||
case 'maneuverability.traverseSpeed':
|
case 'maneuverability.traverseSpeed':
|
||||||
@@ -111,11 +110,7 @@ export function TankSearchCard({ tank, onSelect }: TankSearchCardProps) {
|
|||||||
case 'survivability.camouflageMoving':
|
case 'survivability.camouflageMoving':
|
||||||
return (tank.camouflage_moving * 100).toFixed(0);
|
return (tank.camouflage_moving * 100).toFixed(0);
|
||||||
case 'survivability.camouflageShooting':
|
case 'survivability.camouflageShooting':
|
||||||
return (
|
return (tank.camouflage_still * gun.camouflage_loss * 100).toFixed(0);
|
||||||
tank.camouflage_still *
|
|
||||||
gun.gun_type!.value.base.camouflage_loss *
|
|
||||||
100
|
|
||||||
).toFixed(0);
|
|
||||||
case 'survivability.volume': {
|
case 'survivability.volume': {
|
||||||
const dimensions = normalizeBoundingBox(
|
const dimensions = normalizeBoundingBox(
|
||||||
unionBoundingBox(
|
unionBoundingBox(
|
||||||
|
|||||||
@@ -104,11 +104,9 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.camouflage_still *
|
a.camouflage_still *
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base
|
a.turrets.at(-1)!.guns.at(-1)!.camouflage_loss -
|
||||||
.camouflage_loss -
|
|
||||||
b.camouflage_still *
|
b.camouflage_still *
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base
|
b.turrets.at(-1)!.guns.at(-1)!.camouflage_loss,
|
||||||
.camouflage_loss,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -171,11 +169,11 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
(a, b) =>
|
(a, b) =>
|
||||||
resolveDpm(
|
resolveDpm(
|
||||||
a.turrets.at(-1)!.guns.at(-1)!,
|
a.turrets.at(-1)!.guns.at(-1)!,
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0],
|
a.turrets.at(-1)!.guns.at(-1)!.shells[0],
|
||||||
) -
|
) -
|
||||||
resolveDpm(
|
resolveDpm(
|
||||||
b.turrets.at(-1)!.guns.at(-1)!,
|
b.turrets.at(-1)!.guns.at(-1)!,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0],
|
b.turrets.at(-1)!.guns.at(-1)!.shells[0],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -183,18 +181,16 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
case 'fire.dpmPremium':
|
case 'fire.dpmPremium':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
(a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[1]
|
(a.turrets.at(-1)!.guns.at(-1)!.shells[1]
|
||||||
? resolveDpm(
|
? resolveDpm(
|
||||||
a.turrets.at(-1)!.guns.at(-1)!,
|
a.turrets.at(-1)!.guns.at(-1)!,
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base
|
a.turrets.at(-1)!.guns.at(-1)!.shells[1],
|
||||||
.shells[1],
|
|
||||||
)
|
)
|
||||||
: 0) -
|
: 0) -
|
||||||
(b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[1]
|
(b.turrets.at(-1)!.guns.at(-1)!.shells[1]
|
||||||
? resolveDpm(
|
? resolveDpm(
|
||||||
b.turrets.at(-1)!.guns.at(-1)!,
|
b.turrets.at(-1)!.guns.at(-1)!,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base
|
b.turrets.at(-1)!.guns.at(-1)!.shells[1],
|
||||||
.shells[1],
|
|
||||||
)
|
)
|
||||||
: 0),
|
: 0),
|
||||||
);
|
);
|
||||||
@@ -211,108 +207,92 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
case 'fire.caliber':
|
case 'fire.caliber':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
a.turrets.at(-1)!.guns.at(-1)!.shells[0].caliber -
|
||||||
.caliber -
|
b.turrets.at(-1)!.guns.at(-1)!.shells[0].caliber,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
|
||||||
.caliber,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.standardPenetration':
|
case 'fire.standardPenetration':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
a.turrets.at(-1)!.guns.at(-1)!.shells[0].penetration.near -
|
||||||
.penetration.near -
|
b.turrets.at(-1)!.guns.at(-1)!.shells[0].penetration.near,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
|
||||||
.penetration.near,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.premiumPenetration':
|
case 'fire.premiumPenetration':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
(a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[1]
|
(a.turrets.at(-1)!.guns.at(-1)!.shells[1]?.penetration.near ??
|
||||||
?.penetration.near ?? 0) -
|
0) -
|
||||||
(b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[1]
|
(b.turrets.at(-1)!.guns.at(-1)!.shells[1]?.penetration.near ??
|
||||||
?.penetration.near ?? 0),
|
0),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.tertiaryPenetration':
|
case 'fire.tertiaryPenetration':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
(a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[2]
|
(a.turrets.at(-1)!.guns.at(-1)!.shells[2]?.penetration.near ??
|
||||||
?.penetration.near ?? 0) -
|
0) -
|
||||||
(b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[2]
|
(b.turrets.at(-1)!.guns.at(-1)!.shells[2]?.penetration.near ??
|
||||||
?.penetration.near ?? 0),
|
0),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.damage':
|
case 'fire.damage':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
a.turrets.at(-1)!.guns.at(-1)!.shells[0].armor_damage -
|
||||||
.armor_damage -
|
b.turrets.at(-1)!.guns.at(-1)!.shells[0].armor_damage,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
|
||||||
.armor_damage,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.moduleDamage':
|
case 'fire.moduleDamage':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
a.turrets.at(-1)!.guns.at(-1)!.shells[0].module_damage -
|
||||||
.module_damage -
|
b.turrets.at(-1)!.guns.at(-1)!.shells[0].module_damage,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
|
||||||
.module_damage,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.shellVelocity':
|
case 'fire.shellVelocity':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
a.turrets.at(-1)!.guns.at(-1)!.shells[0].velocity -
|
||||||
.velocity -
|
b.turrets.at(-1)!.guns.at(-1)!.shells[0].velocity,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
|
||||||
.velocity,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.shellRange':
|
case 'fire.shellRange':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
a.turrets.at(-1)!.guns.at(-1)!.shells[0].range -
|
||||||
.range -
|
b.turrets.at(-1)!.guns.at(-1)!.shells[0].range,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
|
||||||
.range,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.shellCapacity':
|
case 'fire.shellCapacity':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base
|
a.turrets.at(-1)!.guns.at(-1)!.shell_capacity -
|
||||||
.shell_capacity -
|
b.turrets.at(-1)!.guns.at(-1)!.shell_capacity,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base
|
|
||||||
.shell_capacity,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.aimTime':
|
case 'fire.aimTime':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.aim_time -
|
a.turrets.at(-1)!.guns.at(-1)!.aim_time -
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.aim_time,
|
b.turrets.at(-1)!.guns.at(-1)!.aim_time,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'fire.dispersionStill':
|
case 'fire.dispersionStill':
|
||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base
|
a.turrets.at(-1)!.guns.at(-1)!.dispersion_base -
|
||||||
.dispersion_base -
|
b.turrets.at(-1)!.guns.at(-1)!.dispersion_base,
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base
|
|
||||||
.dispersion_base,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -328,13 +308,11 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
modelDefinitions.models[a.id].turrets[a.turrets.at(-1)!.id]
|
modelDefinitions.models[a.id].turrets[a.turrets.at(-1)!.id]
|
||||||
.guns[a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.id]
|
.guns[a.turrets.at(-1)!.guns.at(-1)!.id].pitch.max +
|
||||||
.pitch.max +
|
|
||||||
(modelDefinitions.models[a.id].initial_turret_rotation?.pitch ??
|
(modelDefinitions.models[a.id].initial_turret_rotation?.pitch ??
|
||||||
0) -
|
0) -
|
||||||
modelDefinitions.models[b.id].turrets[b.turrets.at(-1)!.id]
|
modelDefinitions.models[b.id].turrets[b.turrets.at(-1)!.id]
|
||||||
.guns[b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.id]
|
.guns[b.turrets.at(-1)!.guns.at(-1)!.id].pitch.max -
|
||||||
.pitch.max -
|
|
||||||
(modelDefinitions.models[b.id].initial_turret_rotation?.pitch ??
|
(modelDefinitions.models[b.id].initial_turret_rotation?.pitch ??
|
||||||
0),
|
0),
|
||||||
);
|
);
|
||||||
@@ -344,13 +322,11 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
sorted = filtered.sort(
|
sorted = filtered.sort(
|
||||||
(a, b) =>
|
(a, b) =>
|
||||||
modelDefinitions.models[b.id].turrets[b.turrets.at(-1)!.id]
|
modelDefinitions.models[b.id].turrets[b.turrets.at(-1)!.id]
|
||||||
.guns[b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.id]
|
.guns[b.turrets.at(-1)!.guns.at(-1)!.id].pitch.min +
|
||||||
.pitch.min +
|
|
||||||
(modelDefinitions.models[b.id].initial_turret_rotation?.pitch ??
|
(modelDefinitions.models[b.id].initial_turret_rotation?.pitch ??
|
||||||
0) -
|
0) -
|
||||||
modelDefinitions.models[a.id].turrets[a.turrets.at(-1)!.id]
|
modelDefinitions.models[a.id].turrets[a.turrets.at(-1)!.id]
|
||||||
.guns[a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.id]
|
.guns[a.turrets.at(-1)!.guns.at(-1)!.id].pitch.min -
|
||||||
.pitch.min -
|
|
||||||
(modelDefinitions.models[a.id].initial_turret_rotation?.pitch ??
|
(modelDefinitions.models[a.id].initial_turret_rotation?.pitch ??
|
||||||
0),
|
0),
|
||||||
);
|
);
|
||||||
@@ -382,14 +358,13 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
a.engines.at(-1)!.weight +
|
a.engines.at(-1)!.weight +
|
||||||
a.tracks.at(-1)!.weight +
|
a.tracks.at(-1)!.weight +
|
||||||
a.turrets.at(-1)!.weight +
|
a.turrets.at(-1)!.weight +
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base
|
a.turrets.at(-1)!.guns.at(-1)!.weight) -
|
||||||
.weight) -
|
|
||||||
b.engines.at(-1)!.power /
|
b.engines.at(-1)!.power /
|
||||||
(b.weight +
|
(b.weight +
|
||||||
b.engines.at(-1)!.weight +
|
b.engines.at(-1)!.weight +
|
||||||
b.tracks.at(-1)!.weight +
|
b.tracks.at(-1)!.weight +
|
||||||
b.turrets.at(-1)!.weight +
|
b.turrets.at(-1)!.weight +
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.weight),
|
b.turrets.at(-1)!.guns.at(-1)!.weight),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -400,12 +375,12 @@ export const TankSearch = memo<TankSearchProps>(
|
|||||||
a.engines.at(-1)!.weight +
|
a.engines.at(-1)!.weight +
|
||||||
a.tracks.at(-1)!.weight +
|
a.tracks.at(-1)!.weight +
|
||||||
a.turrets.at(-1)!.weight +
|
a.turrets.at(-1)!.weight +
|
||||||
a.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.weight -
|
a.turrets.at(-1)!.guns.at(-1)!.weight -
|
||||||
(b.weight +
|
(b.weight +
|
||||||
b.engines.at(-1)!.weight +
|
b.engines.at(-1)!.weight +
|
||||||
b.tracks.at(-1)!.weight +
|
b.tracks.at(-1)!.weight +
|
||||||
b.turrets.at(-1)!.weight +
|
b.turrets.at(-1)!.weight +
|
||||||
b.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.weight),
|
b.turrets.at(-1)!.guns.at(-1)!.weight),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
+8
-15
@@ -26,6 +26,7 @@ import { AssaultRangesVisualizer } from './AssaultRangesVisualizer';
|
|||||||
import { GunFlexibilityVisualizer } from './GunFlexibilityVisualizer';
|
import { GunFlexibilityVisualizer } from './GunFlexibilityVisualizer';
|
||||||
import { Info } from './Info';
|
import { Info } from './Info';
|
||||||
import { InfoWithDelta } from './InfoWithDelta';
|
import { InfoWithDelta } from './InfoWithDelta';
|
||||||
|
import { ReloadVisualizer } from './ReloadVisualizer';
|
||||||
import { RicochetVisualizer } from './RicochetVisualizer';
|
import { RicochetVisualizer } from './RicochetVisualizer';
|
||||||
import { StatsTableWrapper } from './StatsTableWrapper';
|
import { StatsTableWrapper } from './StatsTableWrapper';
|
||||||
import type { StatsAcceptorProps } from './TraverseVisualizer';
|
import type { StatsAcceptorProps } from './TraverseVisualizer';
|
||||||
@@ -54,8 +55,7 @@ export function Firepower({
|
|||||||
]);
|
]);
|
||||||
const tankModelDefinition = useTankModelDefinition();
|
const tankModelDefinition = useTankModelDefinition();
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||||
turretModelDefinition.guns[gun.gun_type!.value.base.id];
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (penetrationDistanceInput.current) {
|
if (penetrationDistanceInput.current) {
|
||||||
@@ -71,7 +71,7 @@ export function Firepower({
|
|||||||
</Heading>
|
</Heading>
|
||||||
|
|
||||||
<Flex>
|
<Flex>
|
||||||
{gun.gun_type!.value.base.shells.map((thisShell, shellIndex) => {
|
{gun.shells.map((thisShell, shellIndex) => {
|
||||||
const selected = thisShell.id === shell.id;
|
const selected = thisShell.id === shell.id;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -84,13 +84,9 @@ export function Firepower({
|
|||||||
borderTopLeftRadius: shellIndex === 0 ? undefined : 0,
|
borderTopLeftRadius: shellIndex === 0 ? undefined : 0,
|
||||||
borderBottomLeftRadius: shellIndex === 0 ? undefined : 0,
|
borderBottomLeftRadius: shellIndex === 0 ? undefined : 0,
|
||||||
borderTopRightRadius:
|
borderTopRightRadius:
|
||||||
shellIndex === gun.gun_type!.value.base.shells.length - 1
|
shellIndex === gun.shells.length - 1 ? undefined : 0,
|
||||||
? undefined
|
|
||||||
: 0,
|
|
||||||
borderBottomRightRadius:
|
borderBottomRightRadius:
|
||||||
shellIndex === gun.gun_type!.value.base.shells.length - 1
|
shellIndex === gun.shells.length - 1 ? undefined : 0,
|
||||||
? undefined
|
|
||||||
: 0,
|
|
||||||
marginLeft: shellIndex === 0 ? 0 : -1,
|
marginLeft: shellIndex === 0 ? 0 : -1,
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -125,11 +121,8 @@ export function Firepower({
|
|||||||
<InfoWithDelta stats={stats} decimals={0} value="moduleDamage" />
|
<InfoWithDelta stats={stats} decimals={0} value="moduleDamage" />
|
||||||
<InfoWithDelta stats={stats} decimals={0} value="penetration" />
|
<InfoWithDelta stats={stats} decimals={0} value="penetration" />
|
||||||
|
|
||||||
{gun.gun_type!.value.base.assault_ranges?.types.includes(shell.type) && (
|
{gun.assault_ranges?.types.includes(shell.type) && (
|
||||||
<AssaultRangesVisualizer
|
<AssaultRangesVisualizer stats={stats} ranges={gun.assault_ranges} />
|
||||||
stats={stats}
|
|
||||||
ranges={gun.gun_type!.value.base.assault_ranges}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{gun.gun_type!.$case === 'auto_reloader' && (
|
{gun.gun_type!.$case === 'auto_reloader' && (
|
||||||
@@ -190,7 +183,7 @@ export function Firepower({
|
|||||||
value="intraClip"
|
value="intraClip"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{/* <ReloadVisualizer stats={stats} /> */}
|
<ReloadVisualizer stats={stats} />
|
||||||
|
|
||||||
{typeof shell.penetration !== 'number' && (
|
{typeof shell.penetration !== 'number' && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ export function ModelChunk({ only }: Props) {
|
|||||||
|
|
||||||
const tankModel = modelDefinitions.models[tank.id];
|
const tankModel = modelDefinitions.models[tank.id];
|
||||||
const turretModel = tankModel.turrets[turret.id];
|
const turretModel = tankModel.turrets[turret.id];
|
||||||
const gunModel = turretModel.guns[gun.gun_type!.value.base.id];
|
const gunModel = turretModel.guns[gun.id];
|
||||||
|
|
||||||
const originZ = tankModel.turret_origin.z + turretModel.gun_origin.z;
|
const originZ = tankModel.turret_origin.z + turretModel.gun_origin.z;
|
||||||
const originY = tankModel.turret_origin.y + turretModel.gun_origin.y;
|
const originY = tankModel.turret_origin.y + turretModel.gun_origin.y;
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ export function GunFlexibilityVisualizer({
|
|||||||
|
|
||||||
const tankModel = modelDefinition.models[tank.id];
|
const tankModel = modelDefinition.models[tank.id];
|
||||||
const turretModel = tankModel.turrets[turret.id];
|
const turretModel = tankModel.turrets[turret.id];
|
||||||
const gunModel = turretModel.guns[gun.gun_type!.value.base.id];
|
const gunModel = turretModel.guns[gun.id];
|
||||||
|
|
||||||
const [yaw, setYaw] = useState(0);
|
const [yaw, setYaw] = useState(0);
|
||||||
const [pitch, setPitch] = useState(0);
|
const [pitch, setPitch] = useState(0);
|
||||||
|
|||||||
+3
-7
@@ -61,9 +61,7 @@ export const InfoWithDelta = memo<InfoWithDeltaProps>(
|
|||||||
const delta = useDelta(uhWhatDoICallThisVariable);
|
const delta = useDelta(uhWhatDoICallThisVariable);
|
||||||
const protagonistTank = Duel.use((state) => state.protagonist.tank);
|
const protagonistTank = Duel.use((state) => state.protagonist.tank);
|
||||||
const shellIndex = Duel.use((state) =>
|
const shellIndex = Duel.use((state) =>
|
||||||
state.protagonist.gun.gun_type!.value.base.shells.indexOf(
|
state.protagonist.gun.shells.indexOf(state.protagonist.shell),
|
||||||
state.protagonist.shell,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
const equipmentMatrix = Duel.use(
|
const equipmentMatrix = Duel.use(
|
||||||
(state) => state.protagonist.equipmentMatrix,
|
(state) => state.protagonist.equipmentMatrix,
|
||||||
@@ -89,9 +87,7 @@ export const InfoWithDelta = memo<InfoWithDeltaProps>(
|
|||||||
provisionDefinitions,
|
provisionDefinitions,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (member.gun.shells[shellIndex] === undefined) {
|
||||||
member.gun.gun_type!.value.base.shells[shellIndex] === undefined
|
|
||||||
) {
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +103,7 @@ export const InfoWithDelta = memo<InfoWithDeltaProps>(
|
|||||||
engine: member.engine,
|
engine: member.engine,
|
||||||
gun: member.gun,
|
gun: member.gun,
|
||||||
equipmentMatrix: equipmentMatrix,
|
equipmentMatrix: equipmentMatrix,
|
||||||
shell: member.gun.gun_type!.value.base.shells[shellIndex],
|
shell: member.gun.shells[shellIndex],
|
||||||
stockEngine: tank.engines[0],
|
stockEngine: tank.engines[0],
|
||||||
stockGun: tank.turrets[0].guns[0],
|
stockGun: tank.turrets[0].guns[0],
|
||||||
stockTrack: tank.tracks[0],
|
stockTrack: tank.tracks[0],
|
||||||
|
|||||||
+2
-4
@@ -11,7 +11,7 @@ export function ShellSwitcher() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex>
|
<Flex>
|
||||||
{gun.gun_type!.value.base.shells.map((thisShell, shellIndex) => {
|
{gun.shells.map((thisShell, shellIndex) => {
|
||||||
const selected = thisShell.id === shell.id;
|
const selected = thisShell.id === shell.id;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -26,9 +26,7 @@ export function ShellSwitcher() {
|
|||||||
borderBottomLeftRadius: shellIndex === 0 ? '50%' : 0,
|
borderBottomLeftRadius: shellIndex === 0 ? '50%' : 0,
|
||||||
borderTopRightRadius: 0,
|
borderTopRightRadius: 0,
|
||||||
borderBottomRightRadius:
|
borderBottomRightRadius:
|
||||||
shellIndex === gun.gun_type!.value.base.shells.length - 1
|
shellIndex === gun.shells.length - 1 ? '50%' : 0,
|
||||||
? '50%'
|
|
||||||
: 0,
|
|
||||||
marginLeft: shellIndex === 0 ? 0 : -1,
|
marginLeft: shellIndex === 0 ? 0 : -1,
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
+1
-2
@@ -41,8 +41,7 @@ export function Characteristics({ skeleton }: MaybeSkeletonComponentProps) {
|
|||||||
const stockGun = stockTurret.guns[0];
|
const stockGun = stockTurret.guns[0];
|
||||||
const tankModelDefinition = useTankModelDefinition();
|
const tankModelDefinition = useTankModelDefinition();
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||||
turretModelDefinition.guns[gun.gun_type!.value.base.id];
|
|
||||||
const stats = tankCharacteristics(
|
const stats = tankCharacteristics(
|
||||||
{
|
{
|
||||||
tank,
|
tank,
|
||||||
|
|||||||
+15
-26
@@ -33,7 +33,7 @@ type ModuleDefinition =
|
|||||||
|
|
||||||
function extractModule(raw: ModuleDefinition | TankDefinition) {
|
function extractModule(raw: ModuleDefinition | TankDefinition) {
|
||||||
if ('gun_type' in raw) {
|
if ('gun_type' in raw) {
|
||||||
return raw.gun_type!.value.base;
|
return raw;
|
||||||
} else
|
} else
|
||||||
return raw as Exclude<ModuleDefinition | TankDefinition, GunDefinition>;
|
return raw as Exclude<ModuleDefinition | TankDefinition, GunDefinition>;
|
||||||
}
|
}
|
||||||
@@ -179,37 +179,31 @@ export function Modules() {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
!draft.protagonist.turret.guns.some(
|
!draft.protagonist.turret.guns.some(
|
||||||
(gun) =>
|
(gun) => gun.id === draft.protagonist.gun.id,
|
||||||
gun.gun_type!.value.base.id ===
|
|
||||||
draft.protagonist.gun.gun_type!.value.base.id,
|
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
draft.protagonist.gun = draft.protagonist.turret.guns.at(-1)!;
|
draft.protagonist.gun = draft.protagonist.turret.guns.at(-1)!;
|
||||||
draft.protagonist.shell =
|
draft.protagonist.shell = draft.protagonist.gun.shells[0];
|
||||||
draft.protagonist.gun.gun_type!.value.base.shells[0];
|
|
||||||
}
|
}
|
||||||
} else if (unlock.type === ModuleType.GUN) {
|
} else if (unlock.type === ModuleType.GUN) {
|
||||||
const gunInTurret = draft.protagonist.turret.guns.find(
|
const gunInTurret = draft.protagonist.turret.guns.find(
|
||||||
(gun) => gun.gun_type!.value.base.id === unlock.id,
|
(gun) => gun.id === unlock.id,
|
||||||
);
|
);
|
||||||
if (gunInTurret) {
|
if (gunInTurret) {
|
||||||
draft.protagonist.gun = gunInTurret;
|
draft.protagonist.gun = gunInTurret;
|
||||||
draft.protagonist.shell = gunInTurret.gun_type!.value.base.shells[0];
|
draft.protagonist.shell = gunInTurret.shells[0];
|
||||||
} else {
|
} else {
|
||||||
// TODO: warn somehow?
|
// TODO: warn somehow?
|
||||||
const suitableTurret = draft.protagonist.tank.turrets.find((turret) =>
|
const suitableTurret = draft.protagonist.tank.turrets.find((turret) =>
|
||||||
turret.guns.some(
|
turret.guns.some((gun) => gun.id === unlock.id),
|
||||||
(gun) => gun.gun_type!.value.base.id === unlock.id,
|
|
||||||
),
|
|
||||||
)!;
|
)!;
|
||||||
const gunInSuitableTurret = suitableTurret.guns.find(
|
const gunInSuitableTurret = suitableTurret.guns.find(
|
||||||
(gun) => gun.gun_type!.value.base.id === unlock.id,
|
(gun) => gun.id === unlock.id,
|
||||||
)!;
|
)!;
|
||||||
|
|
||||||
draft.protagonist.turret = suitableTurret;
|
draft.protagonist.turret = suitableTurret;
|
||||||
draft.protagonist.gun = gunInSuitableTurret;
|
draft.protagonist.gun = gunInSuitableTurret;
|
||||||
draft.protagonist.shell =
|
draft.protagonist.shell = gunInSuitableTurret.shells[0];
|
||||||
gunInSuitableTurret.gun_type!.value.base.shells[0];
|
|
||||||
}
|
}
|
||||||
} else if (unlock.type === ModuleType.ENGINE) {
|
} else if (unlock.type === ModuleType.ENGINE) {
|
||||||
draft.protagonist.engine = draft.protagonist.tank.engines.find(
|
draft.protagonist.engine = draft.protagonist.tank.engines.find(
|
||||||
@@ -241,11 +235,9 @@ export function Modules() {
|
|||||||
} else if (unlock.type === ModuleType.GUN) {
|
} else if (unlock.type === ModuleType.GUN) {
|
||||||
module = tank.turrets
|
module = tank.turrets
|
||||||
.find((turret) =>
|
.find((turret) =>
|
||||||
turret.guns.some(
|
turret.guns.some((gun) => gun.id === unlock.id),
|
||||||
(gun) => gun.gun_type!.value.base.id === unlock.id,
|
|
||||||
),
|
|
||||||
)!
|
)!
|
||||||
.guns.find((gun) => gun.gun_type!.value.base.id === unlock.id)!;
|
.guns.find((gun) => gun.id === unlock.id)!;
|
||||||
} else if (unlock.type === ModuleType.VEHICLE) {
|
} else if (unlock.type === ModuleType.VEHICLE) {
|
||||||
module = tankDefinitions.tanks[unlock.id];
|
module = tankDefinitions.tanks[unlock.id];
|
||||||
}
|
}
|
||||||
@@ -308,7 +300,7 @@ export function Modules() {
|
|||||||
(unlock.type === ModuleType.TURRET
|
(unlock.type === ModuleType.TURRET
|
||||||
? turret.id
|
? turret.id
|
||||||
: unlock.type === ModuleType.GUN
|
: unlock.type === ModuleType.GUN
|
||||||
? gun.gun_type!.value.base.id
|
? gun.id
|
||||||
: unlock.type === ModuleType.ENGINE
|
: unlock.type === ModuleType.ENGINE
|
||||||
? engine.id
|
? engine.id
|
||||||
: unlock.type === ModuleType.TRACKS
|
: unlock.type === ModuleType.TRACKS
|
||||||
@@ -319,8 +311,7 @@ export function Modules() {
|
|||||||
unlock.type === ModuleType.TURRET
|
unlock.type === ModuleType.TURRET
|
||||||
? extractModule(module).id == topTurret.id
|
? extractModule(module).id == topTurret.id
|
||||||
: unlock.type === ModuleType.GUN
|
: unlock.type === ModuleType.GUN
|
||||||
? extractModule(module).id ===
|
? extractModule(module).id === topGun.id
|
||||||
topGun.gun_type!.value.base.id
|
|
||||||
: unlock.type === ModuleType.ENGINE
|
: unlock.type === ModuleType.ENGINE
|
||||||
? extractModule(module).id === topEngine.id
|
? extractModule(module).id === topEngine.id
|
||||||
: unlock.type === ModuleType.TRACKS
|
: unlock.type === ModuleType.TRACKS
|
||||||
@@ -371,8 +362,7 @@ export function Modules() {
|
|||||||
mutateDuel((draft) => {
|
mutateDuel((draft) => {
|
||||||
draft.protagonist.turret = draft.protagonist.tank.turrets[0];
|
draft.protagonist.turret = draft.protagonist.tank.turrets[0];
|
||||||
draft.protagonist.gun = draft.protagonist.turret.guns[0];
|
draft.protagonist.gun = draft.protagonist.turret.guns[0];
|
||||||
draft.protagonist.shell =
|
draft.protagonist.shell = draft.protagonist.gun.shells[0];
|
||||||
draft.protagonist.gun.gun_type!.value.base.shells[0];
|
|
||||||
draft.protagonist.engine = draft.protagonist.tank.engines[0];
|
draft.protagonist.engine = draft.protagonist.tank.engines[0];
|
||||||
draft.protagonist.track = draft.protagonist.tank.tracks[0];
|
draft.protagonist.track = draft.protagonist.tank.tracks[0];
|
||||||
});
|
});
|
||||||
@@ -387,8 +377,7 @@ export function Modules() {
|
|||||||
draft.protagonist.turret =
|
draft.protagonist.turret =
|
||||||
draft.protagonist.tank.turrets.at(-1)!;
|
draft.protagonist.tank.turrets.at(-1)!;
|
||||||
draft.protagonist.gun = draft.protagonist.turret.guns.at(-1)!;
|
draft.protagonist.gun = draft.protagonist.turret.guns.at(-1)!;
|
||||||
draft.protagonist.shell =
|
draft.protagonist.shell = draft.protagonist.gun.shells[0];
|
||||||
draft.protagonist.gun.gun_type!.value.base.shells[0];
|
|
||||||
draft.protagonist.engine =
|
draft.protagonist.engine =
|
||||||
draft.protagonist.tank.engines.at(-1)!;
|
draft.protagonist.tank.engines.at(-1)!;
|
||||||
draft.protagonist.track =
|
draft.protagonist.track =
|
||||||
@@ -427,7 +416,7 @@ export function Modules() {
|
|||||||
{tree(ModuleType.GUN, [
|
{tree(ModuleType.GUN, [
|
||||||
{
|
{
|
||||||
cost: { type: 'xp', value: 0 },
|
cost: { type: 'xp', value: 0 },
|
||||||
id: gun0.gun_type!.value.base.id,
|
id: gun0.id,
|
||||||
type: ModuleType.GUN,
|
type: ModuleType.GUN,
|
||||||
},
|
},
|
||||||
])}
|
])}
|
||||||
|
|||||||
+1
-1
@@ -90,7 +90,7 @@ export function CustomShellButton() {
|
|||||||
modified.normalization = undefined;
|
modified.normalization = undefined;
|
||||||
modified.ricochet = undefined;
|
modified.ricochet = undefined;
|
||||||
modified.explosion_radius =
|
modified.explosion_radius =
|
||||||
gun.gun_type!.value.base.shells.find(
|
gun.shells.find(
|
||||||
(shell) => shell.type === ShellType.HE,
|
(shell) => shell.type === ShellType.HE,
|
||||||
)?.explosion_radius ?? 1;
|
)?.explosion_radius ?? 1;
|
||||||
break;
|
break;
|
||||||
|
|||||||
+1
-2
@@ -21,8 +21,7 @@ export function QuickInputs() {
|
|||||||
const tankModelDefinition = useTankModelDefinition();
|
const tankModelDefinition = useTankModelDefinition();
|
||||||
const turretModelDefinition =
|
const turretModelDefinition =
|
||||||
tankModelDefinition.turrets[protagonist.turret.id];
|
tankModelDefinition.turrets[protagonist.turret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
||||||
turretModelDefinition.guns[protagonist.gun.gun_type!.value.base.id];
|
|
||||||
const initialGunPitch =
|
const initialGunPitch =
|
||||||
tankModelDefinition.initial_turret_rotation?.pitch ?? 0;
|
tankModelDefinition.initial_turret_rotation?.pitch ?? 0;
|
||||||
const hasImprovedVerticalStabilizer = useEquipment(122);
|
const hasImprovedVerticalStabilizer = useEquipment(122);
|
||||||
|
|||||||
+8
-15
@@ -141,7 +141,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
|||||||
mr="2"
|
mr="2"
|
||||||
mb="1"
|
mb="1"
|
||||||
>
|
>
|
||||||
{TIER_ROMAN_NUMERALS[antagonistGun.gun_type!.value.base.tier]}
|
{TIER_ROMAN_NUMERALS[antagonistGun.tier]}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<img
|
<img
|
||||||
@@ -161,26 +161,20 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
|||||||
{[...antagonistUniqueGuns].reverse().map(({ gun, turret }) => (
|
{[...antagonistUniqueGuns].reverse().map(({ gun, turret }) => (
|
||||||
<ModuleButton
|
<ModuleButton
|
||||||
module="gun"
|
module="gun"
|
||||||
key={gun.gun_type!.value.base.id}
|
key={gun.id}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
mutateDuel((draft) => {
|
mutateDuel((draft) => {
|
||||||
draft.antagonist.turret = turret;
|
draft.antagonist.turret = turret;
|
||||||
draft.antagonist.gun = gun;
|
draft.antagonist.gun = gun;
|
||||||
draft.antagonist.shell =
|
draft.antagonist.shell = gun.shells[0];
|
||||||
gun.gun_type!.value.base.shells[0];
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
selected={
|
selected={gun.id === antagonistGun.id}
|
||||||
gun.gun_type!.value.base.id ===
|
discriminator={TIER_ROMAN_NUMERALS[gun.tier]}
|
||||||
antagonistGun.gun_type!.value.base.id
|
|
||||||
}
|
|
||||||
discriminator={
|
|
||||||
TIER_ROMAN_NUMERALS[gun.gun_type!.value.base.tier]
|
|
||||||
}
|
|
||||||
secondaryDiscriminator={
|
secondaryDiscriminator={
|
||||||
<Text style={{ fontSize: '0.75em' }}>
|
<Text style={{ fontSize: '0.75em' }}>
|
||||||
{literals(strings.common.units.mm, [
|
{literals(strings.common.units.mm, [
|
||||||
gun.gun_type!.value.base.shells[0].caliber.toFixed(0),
|
gun.shells[0].caliber.toFixed(0),
|
||||||
])}
|
])}
|
||||||
</Text>
|
</Text>
|
||||||
}
|
}
|
||||||
@@ -198,7 +192,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
|||||||
}}
|
}}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
>
|
>
|
||||||
{antagonistGun.gun_type!.value.base.shells.map((thisShell) => (
|
{antagonistGun.shells.map((thisShell) => (
|
||||||
<IconButton
|
<IconButton
|
||||||
color={
|
color={
|
||||||
thisShell.id === antagonistShell.id && !hasCustomShell
|
thisShell.id === antagonistShell.id && !hasCustomShell
|
||||||
@@ -367,8 +361,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
|||||||
draft.antagonist.turret = tank.turrets.at(-1)!;
|
draft.antagonist.turret = tank.turrets.at(-1)!;
|
||||||
draft.antagonist.gun =
|
draft.antagonist.gun =
|
||||||
draft.antagonist.turret.guns.at(-1)!;
|
draft.antagonist.turret.guns.at(-1)!;
|
||||||
draft.antagonist.shell =
|
draft.antagonist.shell = draft.antagonist.gun.shells[0];
|
||||||
draft.antagonist.gun.gun_type!.value.base.shells[0];
|
|
||||||
});
|
});
|
||||||
setAntagonistSelectorOpen(false);
|
setAntagonistSelectorOpen(false);
|
||||||
}}
|
}}
|
||||||
|
|||||||
+1
-3
@@ -56,9 +56,7 @@ export function Controls({
|
|||||||
const antagonistTurretModelDefinition =
|
const antagonistTurretModelDefinition =
|
||||||
antagonistModelDefinition.turrets[antagonistTurret.id];
|
antagonistModelDefinition.turrets[antagonistTurret.id];
|
||||||
const protagonistGunModelDefinition =
|
const protagonistGunModelDefinition =
|
||||||
protagonistTurretModelDefinition.guns[
|
protagonistTurretModelDefinition.guns[protagonistGun.id];
|
||||||
protagonistGun.gun_type!.value.base.id
|
|
||||||
];
|
|
||||||
const protagonistHullOrigin = new Vector3(
|
const protagonistHullOrigin = new Vector3(
|
||||||
protagonistTrackModelDefinition.origin.x,
|
protagonistTrackModelDefinition.origin.x,
|
||||||
protagonistTrackModelDefinition.origin.y,
|
protagonistTrackModelDefinition.origin.y,
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ export function InitialAligner() {
|
|||||||
|
|
||||||
const tankModel = modelDefinitions.models[tank.id];
|
const tankModel = modelDefinitions.models[tank.id];
|
||||||
const turretModel = tankModel.turrets[turret.id];
|
const turretModel = tankModel.turrets[turret.id];
|
||||||
const gunModel = turretModel.guns[gun.gun_type!.value.base.id];
|
const gunModel = turretModel.guns[gun.id];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const [pitch, yaw] = applyPitchYawLimits(
|
const [pitch, yaw] = applyPitchYawLimits(
|
||||||
|
|||||||
+1
-1
@@ -49,7 +49,7 @@ export function SceneProps() {
|
|||||||
const trackModelDefinition =
|
const trackModelDefinition =
|
||||||
modelDefinitions.models[tank.id].tracks[track.id];
|
modelDefinitions.models[tank.id].tracks[track.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition =
|
||||||
tankModelDefinition.turrets[turret.id].guns[gun.gun_type!.value.base.id];
|
tankModelDefinition.turrets[turret.id].guns[gun.id];
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
const hullOrigin = new Vector3(
|
const hullOrigin = new Vector3(
|
||||||
trackModelDefinition.origin.x,
|
trackModelDefinition.origin.x,
|
||||||
|
|||||||
+1
-2
@@ -28,8 +28,7 @@ export function TankModel() {
|
|||||||
const tankModelDefinition = useTankModelDefinition();
|
const tankModelDefinition = useTankModelDefinition();
|
||||||
const turretModelDefinition =
|
const turretModelDefinition =
|
||||||
tankModelDefinition.turrets[protagonist.turret.id];
|
tankModelDefinition.turrets[protagonist.turret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
||||||
turretModelDefinition.guns[protagonist.gun.gun_type!.value.base.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);
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -31,8 +31,7 @@ export function TransitionSkeleton() {
|
|||||||
const tankModelDefinition = useTankModelDefinition();
|
const tankModelDefinition = useTankModelDefinition();
|
||||||
const turretModelDefinition =
|
const turretModelDefinition =
|
||||||
tankModelDefinition.turrets[protagonist.turret.id];
|
tankModelDefinition.turrets[protagonist.turret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
|
||||||
turretModelDefinition.guns[protagonist.gun.gun_type!.value.base.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);
|
||||||
const revealed = tankopediaEphemeralStore((state) => state.revealed);
|
const revealed = tankopediaEphemeralStore((state) => state.revealed);
|
||||||
|
|||||||
+1
-2
@@ -59,8 +59,7 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
|
|||||||
const tankModelDefinition = useTankModelDefinition();
|
const tankModelDefinition = useTankModelDefinition();
|
||||||
const turretModelDefinition =
|
const turretModelDefinition =
|
||||||
tankModelDefinition.turrets[protagonistTurret.id];
|
tankModelDefinition.turrets[protagonistTurret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[protagonistGun.id];
|
||||||
turretModelDefinition.guns[protagonistGun.gun_type!.value.base.id];
|
|
||||||
const rawDisplay = TankopediaEphemeral.use((state) => state.display);
|
const rawDisplay = TankopediaEphemeral.use((state) => state.display);
|
||||||
const [display, setDisplay] = useState(rawDisplay);
|
const [display, setDisplay] = useState(rawDisplay);
|
||||||
const hideTankModelUnderArmor = TankopediaPersistent.use(
|
const hideTankModelUnderArmor = TankopediaPersistent.use(
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) {
|
|||||||
(filtered.reduce((accumulator, thisTank) => {
|
(filtered.reduce((accumulator, thisTank) => {
|
||||||
return (
|
return (
|
||||||
accumulator +
|
accumulator +
|
||||||
thisTank.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0]
|
thisTank.turrets.at(-1)!.guns.at(-1)!.shells[0].penetration.near
|
||||||
.penetration.near
|
|
||||||
);
|
);
|
||||||
}, 0) /
|
}, 0) /
|
||||||
filtered.length) *
|
filtered.length) *
|
||||||
@@ -51,8 +50,7 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function handleKeyDown(event: KeyboardEvent) {
|
function handleKeyDown(event: KeyboardEvent) {
|
||||||
const { shells } =
|
const { shells } = duelStore.getState().antagonist.gun;
|
||||||
duelStore.getState().antagonist.gun.gun_type!.value.base;
|
|
||||||
|
|
||||||
times(3, (index) => {
|
times(3, (index) => {
|
||||||
if (event.key === `${index + 1}` && shells.length > index) {
|
if (event.key === `${index + 1}` && shells.length > index) {
|
||||||
|
|||||||
@@ -31,9 +31,8 @@ export function filterTank(filters: TankFilters, tank: TankDefinition) {
|
|||||||
SHELLS.every(
|
SHELLS.every(
|
||||||
(index) =>
|
(index) =>
|
||||||
filters.shells[index] === null ||
|
filters.shells[index] === null ||
|
||||||
gun.gun_type!.value.base.shells[index] === undefined ||
|
gun.shells[index] === undefined ||
|
||||||
gun.gun_type!.value.base.shells[index].type ===
|
gun.shells[index].type === filters.shells[index],
|
||||||
filters.shells[index],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,18 +2,16 @@ import type { GunDefinition } from '@blitzkit/core';
|
|||||||
|
|
||||||
export function resolveReload(gun: GunDefinition) {
|
export function resolveReload(gun: GunDefinition) {
|
||||||
if (gun.gun_type!.$case === 'regular') {
|
if (gun.gun_type!.$case === 'regular') {
|
||||||
return gun.gun_type!.value.extension.reload;
|
return gun.gun_type!.value.reload;
|
||||||
} else if (gun.gun_type!.$case === 'auto_loader') {
|
} else if (gun.gun_type!.$case === 'auto_loader') {
|
||||||
return (
|
return (
|
||||||
gun.gun_type!.value.extension.clip_reload +
|
gun.gun_type!.value.clip_reload +
|
||||||
(gun.gun_type!.value.extension.shell_count - 1) *
|
(gun.gun_type!.value.shell_count - 1) * gun.gun_type!.value.intra_clip
|
||||||
gun.gun_type!.value.extension.intra_clip
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
gun.gun_type!.value.extension.shell_reloads.reduce((a, b) => a + b, 0) +
|
gun.gun_type!.value.shell_reloads.reduce((a, b) => a + b, 0) +
|
||||||
(gun.gun_type!.value.extension.shell_count - 1) *
|
(gun.gun_type!.value.shell_count - 1) * gun.gun_type!.value.intra_clip
|
||||||
gun.gun_type!.value.extension.intra_clip
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,8 +80,7 @@ export function tankCharacteristics(
|
|||||||
) {
|
) {
|
||||||
const preset = equipmentDefinitions.presets[tank.equipment_preset];
|
const preset = equipmentDefinitions.presets[tank.equipment_preset];
|
||||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||||
const gunModelDefinition =
|
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||||
turretModelDefinition.guns[gun.gun_type!.value.base.id];
|
|
||||||
|
|
||||||
function equipment(id: number) {
|
function equipment(id: number) {
|
||||||
return preset.slots.some((slot, index) => {
|
return preset.slots.some((slot, index) => {
|
||||||
@@ -160,9 +159,8 @@ export function tankCharacteristics(
|
|||||||
[applySpallLiner && shell.type === ShellType.HE, -0.2],
|
[applySpallLiner && shell.type === ShellType.HE, -0.2],
|
||||||
);
|
);
|
||||||
const assaultDamageCoefficient =
|
const assaultDamageCoefficient =
|
||||||
gun.gun_type!.value.base.assault_ranges &&
|
gun.assault_ranges && gun.assault_ranges.types.includes(shell.type)
|
||||||
gun.gun_type!.value.base.assault_ranges.types.includes(shell.type)
|
? (gun.assault_ranges.ranges.find(
|
||||||
? (gun.gun_type!.value.base.assault_ranges.ranges.find(
|
|
||||||
({ distance }) => distance >= assaultDistance,
|
({ distance }) => distance >= assaultDistance,
|
||||||
)?.factor ?? 0)
|
)?.factor ?? 0)
|
||||||
: 1;
|
: 1;
|
||||||
@@ -322,18 +320,14 @@ export function tankCharacteristics(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
const weightKg =
|
const weightKg =
|
||||||
tank.weight +
|
tank.weight + engine.weight + track.weight + turret.weight + gun.weight;
|
||||||
engine.weight +
|
|
||||||
track.weight +
|
|
||||||
turret.weight +
|
|
||||||
gun.gun_type!.value.base.weight;
|
|
||||||
const weightTons = weightKg / 1000;
|
const weightTons = weightKg / 1000;
|
||||||
const stockWeight =
|
const stockWeight =
|
||||||
tank.weight +
|
tank.weight +
|
||||||
stockEngine.weight +
|
stockEngine.weight +
|
||||||
stockTrack.weight +
|
stockTrack.weight +
|
||||||
stockTurret.weight +
|
stockTurret.weight +
|
||||||
stockGun.gun_type!.value.base.weight;
|
stockGun.weight;
|
||||||
const resolvedEnginePower = engine.power * enginePowerCoefficient;
|
const resolvedEnginePower = engine.power * enginePowerCoefficient;
|
||||||
const damageCoefficientWithoutAssault = armorDamageCoefficient;
|
const damageCoefficientWithoutAssault = armorDamageCoefficient;
|
||||||
const damageCoefficient =
|
const damageCoefficient =
|
||||||
@@ -348,10 +342,10 @@ export function tankCharacteristics(
|
|||||||
const intraClip =
|
const intraClip =
|
||||||
gun.gun_type?.$case === 'regular'
|
gun.gun_type?.$case === 'regular'
|
||||||
? undefined
|
? undefined
|
||||||
: gun.gun_type!.value.extension.intra_clip * intraClipCoefficient;
|
: gun.gun_type!.value.intra_clip * intraClipCoefficient;
|
||||||
const mostOptimalShellIndex =
|
const mostOptimalShellIndex =
|
||||||
gun.gun_type!.$case === 'auto_reloader'
|
gun.gun_type!.$case === 'auto_reloader'
|
||||||
? gun.gun_type!.value.extension.shell_reloads.reduce<null | {
|
? gun.gun_type!.value.shell_reloads.reduce<null | {
|
||||||
index: number;
|
index: number;
|
||||||
reload: number;
|
reload: number;
|
||||||
}>((current, reloadRaw, index) => {
|
}>((current, reloadRaw, index) => {
|
||||||
@@ -369,43 +363,34 @@ export function tankCharacteristics(
|
|||||||
const damage = shell.armor_damage * damageCoefficient;
|
const damage = shell.armor_damage * damageCoefficient;
|
||||||
const dpmEffective =
|
const dpmEffective =
|
||||||
gun.gun_type!.$case === 'auto_reloader'
|
gun.gun_type!.$case === 'auto_reloader'
|
||||||
? gun.gun_type!.value.extension.shell_reloads[0] >
|
? gun.gun_type!.value.shell_reloads[0] >
|
||||||
gun.gun_type!.value.extension.shell_reloads[1] +
|
gun.gun_type!.value.shell_reloads[1] + gun.gun_type!.value.intra_clip
|
||||||
gun.gun_type!.value.extension.intra_clip
|
|
||||||
? ((armorDamageCoefficient * shell.armor_damage) /
|
? ((armorDamageCoefficient * shell.armor_damage) /
|
||||||
(gun.gun_type!.value.extension.shell_reloads.at(-1)! *
|
(gun.gun_type!.value.shell_reloads.at(-1)! * reloadCoefficient +
|
||||||
reloadCoefficient +
|
gun.gun_type!.value.intra_clip * intraClipCoefficient)) *
|
||||||
gun.gun_type!.value.extension.intra_clip *
|
|
||||||
intraClipCoefficient)) *
|
|
||||||
(60 -
|
(60 -
|
||||||
(gun.gun_type!.value.extension.shell_reloads.slice(0, -1).length -
|
(gun.gun_type!.value.shell_reloads.slice(0, -1).length - 1) *
|
||||||
1) *
|
gun.gun_type!.value.intra_clip *
|
||||||
gun.gun_type!.value.extension.intra_clip *
|
|
||||||
intraClipCoefficient) +
|
intraClipCoefficient) +
|
||||||
armorDamageCoefficient *
|
armorDamageCoefficient *
|
||||||
shell.armor_damage *
|
shell.armor_damage *
|
||||||
gun.gun_type!.value.extension.shell_reloads.slice(0, -1).length
|
gun.gun_type!.value.shell_reloads.slice(0, -1).length
|
||||||
: ((armorDamageCoefficient * shell.armor_damage) /
|
: ((armorDamageCoefficient * shell.armor_damage) /
|
||||||
(gun.gun_type!.value.extension.shell_reloads[0] *
|
(gun.gun_type!.value.shell_reloads[0] * reloadCoefficient +
|
||||||
reloadCoefficient +
|
gun.gun_type!.value.intra_clip * intraClipCoefficient)) *
|
||||||
gun.gun_type!.value.extension.intra_clip *
|
|
||||||
intraClipCoefficient)) *
|
|
||||||
(60 -
|
(60 -
|
||||||
(gun.gun_type!.value.extension.shell_reloads.slice(1).length -
|
(gun.gun_type!.value.shell_reloads.slice(1).length - 1) *
|
||||||
1) *
|
gun.gun_type!.value.intra_clip *
|
||||||
gun.gun_type!.value.extension.intra_clip *
|
|
||||||
intraClipCoefficient) +
|
intraClipCoefficient) +
|
||||||
armorDamageCoefficient *
|
armorDamageCoefficient *
|
||||||
shell.armor_damage *
|
shell.armor_damage *
|
||||||
gun.gun_type!.value.extension.shell_reloads.slice(1).length
|
gun.gun_type!.value.shell_reloads.slice(1).length
|
||||||
: undefined;
|
: undefined;
|
||||||
const shells =
|
const shells =
|
||||||
gun.gun_type!.$case === 'regular'
|
gun.gun_type!.$case === 'regular' ? 1 : gun.gun_type!.value.shell_count;
|
||||||
? 1
|
|
||||||
: gun.gun_type!.value.extension.shell_count;
|
|
||||||
const shellReloads =
|
const shellReloads =
|
||||||
gun.gun_type!.$case === 'auto_reloader'
|
gun.gun_type!.$case === 'auto_reloader'
|
||||||
? gun.gun_type!.value.extension.shell_reloads.map(
|
? gun.gun_type!.value.shell_reloads.map(
|
||||||
(reload) => reload * reloadCoefficient,
|
(reload) => reload * reloadCoefficient,
|
||||||
)
|
)
|
||||||
: undefined;
|
: undefined;
|
||||||
@@ -413,30 +398,28 @@ export function tankCharacteristics(
|
|||||||
gun.gun_type!.$case === 'auto_reloader'
|
gun.gun_type!.$case === 'auto_reloader'
|
||||||
? undefined
|
? undefined
|
||||||
: (gun.gun_type!.$case === 'regular'
|
: (gun.gun_type!.$case === 'regular'
|
||||||
? gun.gun_type!.value.extension.reload
|
? gun.gun_type!.value.reload
|
||||||
: gun.gun_type!.value.extension.clip_reload) * reloadCoefficient;
|
: gun.gun_type!.value.clip_reload) * reloadCoefficient;
|
||||||
const caliber = shell.caliber;
|
const caliber = shell.caliber;
|
||||||
const penetration = shell.penetration.near * penetrationCoefficient;
|
const penetration = shell.penetration.near * penetrationCoefficient;
|
||||||
const clipDamage =
|
const clipDamage =
|
||||||
gun.gun_type!.$case === 'regular'
|
gun.gun_type!.$case === 'regular'
|
||||||
? undefined
|
? undefined
|
||||||
: gun.gun_type!.value.extension.shell_count * damage;
|
: gun.gun_type!.value.shell_count * damage;
|
||||||
const moduleDamage = shell.module_damage * moduleDamageCoefficient;
|
const moduleDamage = shell.module_damage * moduleDamageCoefficient;
|
||||||
const explosionRadius = shell.explosion_radius;
|
const explosionRadius = shell.explosion_radius;
|
||||||
const shellVelocity = shell.velocity * shellVelocityCoefficient;
|
const shellVelocity = shell.velocity * shellVelocityCoefficient;
|
||||||
const aimTime = gun.gun_type!.value.base.aim_time * aimTimeCoefficient;
|
const aimTime = gun.aim_time * aimTimeCoefficient;
|
||||||
const dispersion =
|
const dispersion = gun.dispersion_base * dispersionStillCoefficient;
|
||||||
gun.gun_type!.value.base.dispersion_base * dispersionStillCoefficient;
|
|
||||||
const dispersionMoving = track.dispersion_move * dispersionMovingCoefficient;
|
const dispersionMoving = track.dispersion_move * dispersionMovingCoefficient;
|
||||||
const dispersionHullTraversing =
|
const dispersionHullTraversing =
|
||||||
track.dispersion_traverse * dispersionHullTraverseCoefficient;
|
track.dispersion_traverse * dispersionHullTraverseCoefficient;
|
||||||
const dispersionTurretTraversing =
|
const dispersionTurretTraversing =
|
||||||
gun.gun_type!.value.base.dispersion_traverse *
|
gun.dispersion_traverse * dispersionTurretTraverseCoefficient;
|
||||||
dispersionTurretTraverseCoefficient;
|
|
||||||
const dispersionShooting =
|
const dispersionShooting =
|
||||||
gun.gun_type!.value.base.dispersion_shot * dispersionAfterShotCoefficient;
|
gun.dispersion_shot * dispersionAfterShotCoefficient;
|
||||||
const dispersionGunDamaged =
|
const dispersionGunDamaged =
|
||||||
gun.gun_type!.value.base.dispersion_damaged * dispersionDamagedCoefficient;
|
gun.dispersion_damaged * dispersionDamagedCoefficient;
|
||||||
const gunDepression =
|
const gunDepression =
|
||||||
gunModelDefinition.pitch.max +
|
gunModelDefinition.pitch.max +
|
||||||
gunDefaultPitch +
|
gunDefaultPitch +
|
||||||
@@ -478,8 +461,7 @@ export function tankCharacteristics(
|
|||||||
resolvedEnginePower / weightTons / softTerrainCoefficientRaw;
|
resolvedEnginePower / weightTons / softTerrainCoefficientRaw;
|
||||||
const weight = weightTons;
|
const weight = weightTons;
|
||||||
const turretTraverseSpeed = turret.traverse_speed * turretTraverseCoefficient;
|
const turretTraverseSpeed = turret.traverse_speed * turretTraverseCoefficient;
|
||||||
const gunTraverseSpeed =
|
const gunTraverseSpeed = gun.rotation_speed * turretTraverseCoefficient;
|
||||||
gun.gun_type!.value.base.rotation_speed * turretTraverseCoefficient;
|
|
||||||
/**
|
/**
|
||||||
* resistance_hard is used in all cases as this is the coefficient between
|
* resistance_hard is used in all cases as this is the coefficient between
|
||||||
* the absolute best coefficient and the current
|
* the absolute best coefficient and the current
|
||||||
@@ -511,14 +493,12 @@ export function tankCharacteristics(
|
|||||||
? tank.camouflage_still * camouflageCoefficientStill
|
? tank.camouflage_still * camouflageCoefficientStill
|
||||||
: tank.camouflage_moving * camouflageCoefficientMoving;
|
: tank.camouflage_moving * camouflageCoefficientMoving;
|
||||||
const camouflageShootingStill =
|
const camouflageShootingStill =
|
||||||
tank.camouflage_still *
|
tank.camouflage_still * gun.camouflage_loss * camouflageCoefficientStill;
|
||||||
gun.gun_type!.value.base.camouflage_loss *
|
|
||||||
camouflageCoefficientStill;
|
|
||||||
const camouflageShootingMoving =
|
const camouflageShootingMoving =
|
||||||
(tank.class === TankClass.LIGHT
|
(tank.class === TankClass.LIGHT
|
||||||
? tank.camouflage_still * camouflageCoefficientStill
|
? tank.camouflage_still * camouflageCoefficientStill
|
||||||
: tank.camouflage_moving * camouflageCoefficientMoving) *
|
: tank.camouflage_moving * camouflageCoefficientMoving) *
|
||||||
gun.gun_type!.value.base.camouflage_loss;
|
gun.camouflage_loss;
|
||||||
const camouflageCaughtOnFire =
|
const camouflageCaughtOnFire =
|
||||||
tank.camouflage_onFire * tank.camouflage_still * camouflageCoefficientStill;
|
tank.camouflage_onFire * tank.camouflage_still * camouflageCoefficientStill;
|
||||||
const width = size.z;
|
const width = size.z;
|
||||||
@@ -529,7 +509,7 @@ export function tankCharacteristics(
|
|||||||
const shellRicochet = isExplosive(shell.type) ? undefined : shell.ricochet;
|
const shellRicochet = isExplosive(shell.type) ? undefined : shell.ricochet;
|
||||||
const crewCount = tank.crew.length;
|
const crewCount = tank.crew.length;
|
||||||
const shellRange = shell.range;
|
const shellRange = shell.range;
|
||||||
const shellCapacity = gun.gun_type!.value.base.shell_capacity;
|
const shellCapacity = gun.shell_capacity;
|
||||||
const gunType = gun.gun_type!.$case;
|
const gunType = gun.gun_type!.$case;
|
||||||
const penetrationAt250m = shell.penetration.far;
|
const penetrationAt250m = shell.penetration.far;
|
||||||
|
|
||||||
|
|||||||
@@ -23,11 +23,10 @@ export function tankToDuelMember(
|
|||||||
provisions: createDefaultProvisions(tank, gun, provisionDefinitions),
|
provisions: createDefaultProvisions(tank, gun, provisionDefinitions),
|
||||||
engine: tank.engines.at(-1)!,
|
engine: tank.engines.at(-1)!,
|
||||||
gun,
|
gun,
|
||||||
shell: tank.turrets.at(-1)!.guns.at(-1)!.gun_type!.value.base.shells[0],
|
shell: tank.turrets.at(-1)!.guns.at(-1)!.shells[0],
|
||||||
tank,
|
tank,
|
||||||
track: tank.tracks.at(-1)!,
|
track: tank.tracks.at(-1)!,
|
||||||
turret,
|
turret,
|
||||||
assaultDistance:
|
assaultDistance: (gun.assault_ranges?.ranges[0].distance ?? 0) / 2,
|
||||||
(gun.gun_type!.value.base.assault_ranges?.ranges[0].distance ?? 0) / 2,
|
|
||||||
} satisfies DuelMember;
|
} satisfies DuelMember;
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ const url = import.meta.env.SITE + Astro.url.pathname;
|
|||||||
const icon = asset(`icons/tanks/big/${id}.webp`);
|
const icon = asset(`icons/tanks/big/${id}.webp`);
|
||||||
const turret = tank.turrets.at(-1)!;
|
const turret = tank.turrets.at(-1)!;
|
||||||
const gun = turret.guns.at(-1)!;
|
const gun = turret.guns.at(-1)!;
|
||||||
const shell = gun.gun_type!.value.base.shells[0];
|
const shell = gun.shells[0];
|
||||||
const characteristics = tankCharacteristics(
|
const characteristics = tankCharacteristics(
|
||||||
{
|
{
|
||||||
tank,
|
tank,
|
||||||
|
|||||||
Reference in new issue
Block a user