hull traverse speeds

This commit is contained in:
tresabhi committed 2026-10-11 01:36:34 -05:00
1 parent e7708ce01b
commit e1bc11644d
8 files changed
+208 -78

No files matched your search

+5
View File
@@ -66,6 +66,7 @@
"azimuth_right": "Azimuth right",
"speed_forward": "Speed forward",
"speed_backward": "Speed backward",
"speeds": "Speeds",
"engine_power": "Engine power",
"brake_force": "Brake force",
"weight": "Weight",
@@ -79,6 +80,10 @@
"medium_terrain_coefficient_raw": "Medium",
"soft_terrain_coefficient_raw": "Soft",
"hull_traverse_speed": "Hull traverse speed",
"hull_traverse_speeds": "Hull traverse speeds",
"hull_traverse_speed_hard": "Hard",
"hull_traverse_speed_medium": "Medium",
"hull_traverse_speed_soft": "Soft",
"turret_traverse_speed": "Turret traverse speed",
"gun_traverse_speed": "Gun traverse speed",
"health": "Health",
+55 -53
View File
@@ -5,54 +5,12 @@ import {
unionBoundingBox,
} from "@blitzkit/core";
import { ShellType, TankClass } from "@blitzkit/protos";
import { hullTraverseSpeed } from "../tankopedia/hullTraverseSpeed";
import { rawTerrainCoefficient } from "../tankopedia/rawTerrainCoefficient";
import {
CharacteristicType,
type Characteristic,
type CharacteristicContext,
} from "../types/characteristics";
import { rawTerrainCoefficient } from "../tankopedia/rawTerrainCoefficient";
function intraClipCoefficient({
script,
}: Pick<CharacteristicContext, "script">) {
let coefficient = 1;
script("protagonist", "NewAutoloader", (effect) => {
coefficient *= effect.clipReloadTimeFactor;
});
return coefficient;
}
function aimTimeCoefficient({ script }: Pick<CharacteristicContext, "script">) {
let coefficient = 1;
script("protagonist", "miscAttrs/gunAimingTimeFactor", (effect) => {
coefficient += effect.bonusValues!.percent / 100;
});
script("protagonist", "FireControlSystem", (effect) => {
coefficient *= effect.aimingTimeFactor;
});
return coefficient;
}
function dispersionCoefficient({
script,
}: Pick<CharacteristicContext, "script">) {
let coefficient = 1;
script("protagonist", "miscAttrs/shotDispersionAngleFactor", (effect) => {
coefficient += effect.bonusValues!.percent / 100;
});
script("protagonist", "FireControlSystem", (effect) => {
coefficient *= effect.shotDispersionAngleFactor;
});
return coefficient;
}
export const characteristics = {
gun_type: {
@@ -490,10 +448,20 @@ export const characteristics = {
dispersion: {
type: CharacteristicType.Number,
compute({ gun, degressive, script }) {
let coefficient = 1;
script("protagonist", "miscAttrs/shotDispersionAngleFactor", (effect) => {
coefficient += effect.bonusValues!.percent / 100;
});
script("protagonist", "FireControlSystem", (effect) => {
coefficient *= effect.shotDispersionAngleFactor;
});
return (
gun.dispersion_base *
degressive("gunner") *
dispersionCoefficient({ script })
coefficient
);
},
},
@@ -527,8 +495,9 @@ export const characteristics = {
gun_frontal_depression: {
type: CharacteristicType.Number,
should_render({ state, turret, gun }) {
return state.model.turrets[turret.id].guns[gun.id].pitch!.front !==
undefined;
return (
state.model.turrets[turret.id].guns[gun.id].pitch!.front !== undefined
);
},
compute({ state, turret, gun }) {
return state.model.turrets[turret.id].guns[gun.id].pitch!.front!.max;
@@ -538,8 +507,9 @@ export const characteristics = {
gun_frontal_elevation: {
type: CharacteristicType.Number,
should_render({ state, turret, gun }) {
return state.model.turrets[turret.id].guns[gun.id].pitch!.front !==
undefined;
return (
state.model.turrets[turret.id].guns[gun.id].pitch!.front !== undefined
);
},
compute({ state, turret, gun }) {
return -state.model.turrets[turret.id].guns[gun.id].pitch!.front!.min;
@@ -549,8 +519,9 @@ export const characteristics = {
gun_rear_depression: {
type: CharacteristicType.Number,
should_render({ state, turret, gun }) {
return state.model.turrets[turret.id].guns[gun.id].pitch!.back !==
undefined;
return (
state.model.turrets[turret.id].guns[gun.id].pitch!.back !== undefined
);
},
compute({ state, turret, gun }) {
return state.model.turrets[turret.id].guns[gun.id].pitch!.back!.max;
@@ -560,8 +531,9 @@ export const characteristics = {
gun_rear_elevation: {
type: CharacteristicType.Number,
should_render({ state, turret, gun }) {
return state.model.turrets[turret.id].guns[gun.id].pitch!.back !==
undefined;
return (
state.model.turrets[turret.id].guns[gun.id].pitch!.back !== undefined
);
},
compute({ state, turret, gun }) {
return -state.model.turrets[turret.id].guns[gun.id].pitch!.back!.min;
@@ -690,6 +662,36 @@ export const characteristics = {
},
},
hull_traverse_speed_hard: {
type: CharacteristicType.Number,
compute(context): number {
return hullTraverseSpeed(
context.characteristic("hard_terrain_coefficient_raw") as number,
context,
);
},
},
hull_traverse_speed_medium: {
type: CharacteristicType.Number,
compute(context): number {
return hullTraverseSpeed(
context.characteristic("medium_terrain_coefficient_raw") as number,
context,
);
},
},
hull_traverse_speed_soft: {
type: CharacteristicType.Number,
compute(context): number {
return hullTraverseSpeed(
context.characteristic("soft_terrain_coefficient_raw") as number,
context,
);
},
},
turret_traverse_speed: {
type: CharacteristicType.Number,
compute({ turret, progressive }) {
@@ -155,8 +155,9 @@ export const characteristicsGroups: CharacteristicsGroup[] = [
name: "maneuverability",
// render: CharacteristicsGroupRender.Statistical,
order: [
{ name: "speed_forward", units: "km_h" },
{ name: "speed_backward", units: "km_h" },
{ label: "speeds" },
{ name: "speed_forward", units: "km_h", indent: true },
{ name: "speed_backward", units: "km_h", indent: true },
{ name: "weight", decimals: 1, units: "t" },
{ name: "engine_power", units: "bhp" },
@@ -173,7 +174,10 @@ export const characteristicsGroups: CharacteristicsGroup[] = [
{ name: "medium_terrain_coefficient_raw", decimals: 2, indent: true },
{ name: "soft_terrain_coefficient_raw", decimals: 2, indent: true },
{ name: "hull_traverse_speed", units: "deg_s" },
{ label: "hull_traverse_speeds" },
{ name: "hull_traverse_speed_hard", units: "deg_s", indent: true },
{ name: "hull_traverse_speed_medium", units: "deg_s", indent: true },
{ name: "hull_traverse_speed_soft", units: "deg_s", indent: true },
{ name: "turret_traverse_speed", units: "deg_s" },
{ name: "gun_traverse_speed", units: "deg_s" },
@@ -91,19 +91,17 @@ export function computeCharacteristics(
}
}
const protagonist = states.protagonist;
const protagonistEquipmentPreset = equipment.presets[tank.equipment_preset];
const hasImprovedVentilation = Object.entries(protagonist.equipment).some(
([index, choice]) =>
protagonistEquipmentPreset.slots[Number(index)]?.options[choice] === 102,
);
const provisionCrewBonus =
protagonist.provisions.reduce(
(total, id) =>
total +
(scripts.provisions[id]?.bonusValues?.crewLevelIncrease ?? 0) / 100,
0,
) + (hasImprovedVentilation ? 0.08 : 0);
let provisionCrewBonus = 0;
script("protagonist", "Stimulator", (effect) => {
provisionCrewBonus += (effect.bonusValues?.crewLevelIncrease ?? 0) / 100;
});
script("protagonist", "StaticAdditiveDevice", (effect) => {
if (effect.attribute !== "miscAttrs/crewLevelIncrease") return;
provisionCrewBonus += (effect.bonusValues?.value ?? 0) / 100;
});
const commanderMastery = 1 + provisionCrewBonus;
const crewMastery = {
commander: commanderMastery,
+6 -3
View File
@@ -79,6 +79,7 @@ export enum TankopediaRelativeAgainst {
export interface TankEnvironment {
equalize: boolean;
distance: number;
skills: Record<string, number>;
}
interface Tankopedia {
@@ -91,7 +92,6 @@ interface Tankopedia {
modelRequested: boolean;
shot?: Shot;
skills: Record<string, number>;
relativeAgainst: TankopediaRelativeAgainst;
editStatic: boolean;
highlightArmor?: {
@@ -127,13 +127,16 @@ export const Tankopedia = new Soapstone<Tankopedia, [TankDefinition]>(
antagonist: createTankState(tank),
model: models.models[tank.id],
environment: { equalize: false, distance: 0 },
environment: {
equalize: false,
distance: 0,
skills: createDefaultSkills(skills),
},
modelRequested: false,
relativeAgainst: TankopediaRelativeAgainst.Class,
editStatic: false,
skills: createDefaultSkills(skills),
xpMultiplier: 1,
requestedDisplay: TankopediaDisplay.Model,
display: TankopediaDisplay.Model,
@@ -0,0 +1,109 @@
import type {
CharacteristicContext,
CharacteristicScript,
} from "../types/characteristics";
import { tankClassToBlitzTankClass } from "./tankClass";
function hullTraverseEnginePowerCoefficient(
tank: TankDefinition,
script: CharacteristicScript,
) {
let coefficient = 1;
const enginePowerPercentage = tankClassToBlitzTankClass[tank.class];
script("protagonist", "RecycledEngine", (effect) => {
coefficient +=
(effect.enginePowerPercentageBonus?.[enginePowerPercentage] ?? 0) / 100;
});
script("protagonist", "Afterburning", (effect) => {
coefficient += (effect.bonusValues?.enginePowerIncrease ?? 0) / 100;
});
script("protagonist", "ImprovedAfterburning", (effect) => {
coefficient += (effect.enginePowerIncrease ?? 1) - 1;
});
script("protagonist", "Fuel", (effect) => {
coefficient += (effect.bonusValues?.enginePowerIncrease ?? 0) / 100;
});
script("protagonist", "GearOil", (effect) => {
coefficient += (effect.bonusValues?.enginePowerIncrease ?? 0) / 100;
});
script("protagonist", "AttributesModifier", (effect) => {
coefficient *= effect.attributes?.enginePowerFactor ?? 1;
});
return coefficient;
}
function hullTraverseRotationCoefficient(
driverCoefficient: number,
virtuosoSkill: number,
script: CharacteristicScript,
) {
let coefficient = 1 + virtuosoSkill / 100;
let rotationSpeedFactor = 1;
script("protagonist", "StaticPhysicsAttrsModifier", (effect) => {
coefficient += (effect.bonusPercentage?.rotationSpeedFactor ?? 0) / 100;
});
script("protagonist", "ImprovedAfterburning", (effect) => {
rotationSpeedFactor *= effect.rotationSpeedFactor ?? 1;
});
script("protagonist", "AfterburnerAbility", (effect) => {
rotationSpeedFactor *= effect.bonusValues?.rotationSpeedFactor ?? 1;
});
return driverCoefficient * coefficient * rotationSpeedFactor;
}
export function hullTraverseSpeed(
rawTerrainResistance: number,
context: CharacteristicContext,
) {
const {
tank,
engine,
track,
turret,
gun,
progressive,
script,
environment,
} = context;
const terrainResistance = track.resistance_hard;
const stockEngine = tank.engines[0];
const stockTrack = tank.tracks[0];
const stockTurret = tank.turrets[0];
const stockGun = stockTurret.guns[0];
const stockWeight =
tank.weight +
stockEngine.weight +
stockTrack.weight +
stockTurret.weight +
stockGun.weight;
const weight =
tank.weight + engine.weight + track.weight + turret.weight + gun.weight;
const enginePower =
(engine.power * hullTraverseEnginePowerCoefficient(tank, script)) /
stockEngine.power;
const rotationSpeed = hullTraverseRotationCoefficient(
progressive("driver"),
environment.skills.virtuoso ?? 0,
script,
);
return (
enginePower *
track.traverse_speed *
rotationSpeed *
(terrainResistance / rawTerrainResistance) *
(stockWeight / weight)
);
}
@@ -6,17 +6,17 @@ export function rawTerrainCoefficient(
driverCoefficient: number,
script: CharacteristicScript,
) {
let passabilityIncrease = 0;
let passabilityFactor = 1;
let terrainResistanceFactor = 1;
script("protagonist", "Grousers", (effect) => {
passabilityIncrease +=
(effect.bonusPercentage?.[passabilityAttribute] ?? 0) / 100;
passabilityFactor *=
1 - (effect.bonusPercentage?.[passabilityAttribute] ?? 0) / 100;
});
script("protagonist", "AttributesModifier", (effect) => {
passabilityIncrease +=
(effect.attributes?.[passabilityAttribute] ?? 0) / 100;
passabilityFactor *=
1 - (effect.attributes?.[passabilityAttribute] ?? 0) / 100;
});
script("protagonist", "AfterburnerAbility", (effect) => {
@@ -25,7 +25,7 @@ export function rawTerrainCoefficient(
return (
resistance *
(1 - passabilityIncrease) *
passabilityFactor *
terrainResistanceFactor *
driverCoefficient
);
@@ -0,0 +1,9 @@
import type { BlitzTankClass } from "@blitzkit/core";
import { TankClass } from "@blitzkit/protos";
export const tankClassToBlitzTankClass: Record<TankClass, BlitzTankClass> = {
[TankClass.TANK_CLASS_LIGHT]: "lightTank",
[TankClass.TANK_CLASS_MEDIUM]: "mediumTank",
[TankClass.TANK_CLASS_HEAVY]: "heavyTank",
[TankClass.TANK_CLASS_TANK_DESTROYER]: "AT-SPG",
};