mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
hull traverse speeds
This commit is contained in:
1 parent
e7708ce01b
commit
e1bc11644d
8 files changed
+208
-78
No files matched your search
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
};
|
||||
Reference in new issue
Block a user