feat: mangle crew healths

This commit is contained in:
tresabhi committed 2025-01-30 12:49:15 -06:00
1 parent c6f4a13abc
commit 6829ff921d
5 files changed
+158 -74

No files matched your search

+1
View File
@@ -121,6 +121,7 @@
"NEGATIVEX", "NEGATIVEX",
"NEGATIVEY", "NEGATIVEY",
"NEGATIVEZ", "NEGATIVEZ",
"Newtonsoft",
"NITROPAY", "NITROPAY",
"nivo", "nivo",
"nmatname", "nmatname",
+4
View File
@@ -7,3 +7,7 @@
`Blitz/Content/TanksStuff/Common/DT_TankClasses.uasset` seems to have all tank classes `Blitz/Content/TanksStuff/Common/DT_TankClasses.uasset` seems to have all tank classes
`C:\Users\coola\AppData\Local\Blitz\Saved\PersistentDownloadDir\http\dl-wotblitz-gc.wargaming.net\dlc\p14y73c7_p5e_b10gg3RS_big_play\ue_localizations\development\general` has all localization files `C:\Users\coola\AppData\Local\Blitz\Saved\PersistentDownloadDir\http\dl-wotblitz-gc.wargaming.net\dlc\p14y73c7_p5e_b10gg3RS_big_play\ue_localizations\development\general` has all localization files
`Blitz/Config/DefaultBzBattleSettings.ini` contains all modules that can take damage when a tank takes fall damage
`Blitz/Config/DefaultLocalizationFetcher.ini` has a list of all locales
+15 -1
View File
@@ -19,7 +19,7 @@ message Tank {
required ModuleHealth ammo_bay_health = 10; required ModuleHealth ammo_bay_health = 10;
required ModuleHealth engine_health = 11; required ModuleHealth engine_health = 11;
required ModuleHealth fuel_tank_health = 12; required ModuleHealth fuel_tank_health = 12;
map<string, float> crew_health = 13; repeated CrewHealth crew_health = 13;
required float max_health = 14; required float max_health = 14;
required float health_burn_per_second = 15; required float health_burn_per_second = 15;
required float fire_starting_chance = 16; required float fire_starting_chance = 16;
@@ -49,6 +49,20 @@ message Tank {
required bool b_rotation_is_around_center = 36; required bool b_rotation_is_around_center = 36;
} }
enum CrewType {
COMMANDER = 0;
DRIVER = 1;
GUNNER_1 = 2;
GUNNER_2 = 3;
LOADER_1 = 4;
LOADER_2 = 5;
}
message CrewHealth {
required CrewType type = 1;
required float max_health = 2;
}
message Shell { message Shell {
required float speed = 1; required float speed = 1;
required float gravity = 2; required float gravity = 2;
+104 -72
View File
@@ -10,6 +10,59 @@ import { I18n } from "./i18n";
export const protobufPackage = "blitzkit"; export const protobufPackage = "blitzkit";
export enum CrewType {
COMMANDER = 0,
DRIVER = 1,
GUNNER_1 = 2,
GUNNER_2 = 3,
LOADER_1 = 4,
LOADER_2 = 5,
}
export function crewTypeFromJSON(object: any): CrewType {
switch (object) {
case 0:
case "COMMANDER":
return CrewType.COMMANDER;
case 1:
case "DRIVER":
return CrewType.DRIVER;
case 2:
case "GUNNER_1":
return CrewType.GUNNER_1;
case 3:
case "GUNNER_2":
return CrewType.GUNNER_2;
case 4:
case "LOADER_1":
return CrewType.LOADER_1;
case 5:
case "LOADER_2":
return CrewType.LOADER_2;
default:
throw new globalThis.Error("Unrecognized enum value " + object + " for enum CrewType");
}
}
export function crewTypeToJSON(object: CrewType): string {
switch (object) {
case CrewType.COMMANDER:
return "COMMANDER";
case CrewType.DRIVER:
return "DRIVER";
case CrewType.GUNNER_1:
return "GUNNER_1";
case CrewType.GUNNER_2:
return "GUNNER_2";
case CrewType.LOADER_1:
return "LOADER_1";
case CrewType.LOADER_2:
return "LOADER_2";
default:
throw new globalThis.Error("Unrecognized enum value " + object + " for enum CrewType");
}
}
export interface Tank { export interface Tank {
id: string; id: string;
name: I18n; name: I18n;
@@ -24,7 +77,7 @@ export interface Tank {
ammo_bay_health: ModuleHealth; ammo_bay_health: ModuleHealth;
engine_health: ModuleHealth; engine_health: ModuleHealth;
fuel_tank_health: ModuleHealth; fuel_tank_health: ModuleHealth;
crew_health: { [key: string]: number }; crew_health: CrewHealth[];
max_health: number; max_health: number;
health_burn_per_second: number; health_burn_per_second: number;
fire_starting_chance: number; fire_starting_chance: number;
@@ -50,9 +103,9 @@ export interface Tank {
b_rotation_is_around_center: boolean; b_rotation_is_around_center: boolean;
} }
export interface Tank_CrewHealthEntry { export interface CrewHealth {
key: string; type: CrewType;
value: number; max_health: number;
} }
export interface Shell { export interface Shell {
@@ -79,8 +132,11 @@ export interface ModuleHealth {
/** /**
* the range from 0 to this where the module is "red" and doesn't function * the range from 0 to this where the module is "red" and doesn't function
* all the while healing; after surpassing this, the "yellow" phase is reached * all the while healing; after surpassing this, the "yellow" phase is reached
* undefined for modules like ammo bays
*/ */
hysteresis_health: number; hysteresis_health?:
| number
| undefined;
/** /**
* the heal rate (per second); this won't apply if the health is at or above * the heal rate (per second); this won't apply if the health is at or above
* max_regen hence always leaving it in the "yellow" phase until repaired * max_regen hence always leaving it in the "yellow" phase until repaired
@@ -107,7 +163,7 @@ function createBaseTank(): Tank {
ammo_bay_health: createBaseModuleHealth(), ammo_bay_health: createBaseModuleHealth(),
engine_health: createBaseModuleHealth(), engine_health: createBaseModuleHealth(),
fuel_tank_health: createBaseModuleHealth(), fuel_tank_health: createBaseModuleHealth(),
crew_health: {}, crew_health: [],
max_health: 0, max_health: 0,
health_burn_per_second: 0, health_burn_per_second: 0,
fire_starting_chance: 0, fire_starting_chance: 0,
@@ -172,9 +228,9 @@ export const Tank: MessageFns<Tank> = {
if (message.fuel_tank_health !== undefined) { if (message.fuel_tank_health !== undefined) {
ModuleHealth.encode(message.fuel_tank_health, writer.uint32(98).fork()).join(); ModuleHealth.encode(message.fuel_tank_health, writer.uint32(98).fork()).join();
} }
Object.entries(message.crew_health).forEach(([key, value]) => { for (const v of message.crew_health) {
Tank_CrewHealthEntry.encode({ key: key as any, value }, writer.uint32(106).fork()).join(); CrewHealth.encode(v!, writer.uint32(106).fork()).join();
}); }
if (message.max_health !== 0) { if (message.max_health !== 0) {
writer.uint32(117).float(message.max_health); writer.uint32(117).float(message.max_health);
} }
@@ -355,10 +411,7 @@ export const Tank: MessageFns<Tank> = {
break; break;
} }
const entry13 = Tank_CrewHealthEntry.decode(reader, reader.uint32()); message.crew_health.push(CrewHealth.decode(reader, reader.uint32()));
if (entry13.value !== undefined) {
message.crew_health[entry13.key] = entry13.value;
}
continue; continue;
} }
case 14: { case 14: {
@@ -572,12 +625,9 @@ export const Tank: MessageFns<Tank> = {
ammo_bay_health: ModuleHealth.fromJSON(assertSet("Tank.ammo_bay_health", object.ammo_bay_health)), ammo_bay_health: ModuleHealth.fromJSON(assertSet("Tank.ammo_bay_health", object.ammo_bay_health)),
engine_health: ModuleHealth.fromJSON(assertSet("Tank.engine_health", object.engine_health)), engine_health: ModuleHealth.fromJSON(assertSet("Tank.engine_health", object.engine_health)),
fuel_tank_health: ModuleHealth.fromJSON(assertSet("Tank.fuel_tank_health", object.fuel_tank_health)), fuel_tank_health: ModuleHealth.fromJSON(assertSet("Tank.fuel_tank_health", object.fuel_tank_health)),
crew_health: isObject(object.crew_health) crew_health: globalThis.Array.isArray(object?.crew_health)
? Object.entries(object.crew_health).reduce<{ [key: string]: number }>((acc, [key, value]) => { ? object.crew_health.map((e: any) => CrewHealth.fromJSON(e))
acc[key] = Number(value); : [],
return acc;
}, {})
: {},
max_health: globalThis.Number(assertSet("Tank.max_health", object.max_health)), max_health: globalThis.Number(assertSet("Tank.max_health", object.max_health)),
health_burn_per_second: globalThis.Number( health_burn_per_second: globalThis.Number(
assertSet("Tank.health_burn_per_second", object.health_burn_per_second), assertSet("Tank.health_burn_per_second", object.health_burn_per_second),
@@ -658,14 +708,8 @@ export const Tank: MessageFns<Tank> = {
if (message.fuel_tank_health !== undefined) { if (message.fuel_tank_health !== undefined) {
obj.fuel_tank_health = ModuleHealth.toJSON(message.fuel_tank_health); obj.fuel_tank_health = ModuleHealth.toJSON(message.fuel_tank_health);
} }
if (message.crew_health) { if (message.crew_health?.length) {
const entries = Object.entries(message.crew_health); obj.crew_health = message.crew_health.map((e) => CrewHealth.toJSON(e));
if (entries.length > 0) {
obj.crew_health = {};
entries.forEach(([k, v]) => {
obj.crew_health[k] = v;
});
}
} }
if (message.max_health !== 0) { if (message.max_health !== 0) {
obj.max_health = message.max_health; obj.max_health = message.max_health;
@@ -774,15 +818,7 @@ export const Tank: MessageFns<Tank> = {
message.fuel_tank_health = (object.fuel_tank_health !== undefined && object.fuel_tank_health !== null) message.fuel_tank_health = (object.fuel_tank_health !== undefined && object.fuel_tank_health !== null)
? ModuleHealth.fromPartial(object.fuel_tank_health) ? ModuleHealth.fromPartial(object.fuel_tank_health)
: createBaseModuleHealth(); : createBaseModuleHealth();
message.crew_health = Object.entries(object.crew_health ?? {}).reduce<{ [key: string]: number }>( message.crew_health = object.crew_health?.map((e) => CrewHealth.fromPartial(e)) || [];
(acc, [key, value]) => {
if (value !== undefined) {
acc[key] = globalThis.Number(value);
}
return acc;
},
{},
);
message.max_health = object.max_health ?? 0; message.max_health = object.max_health ?? 0;
message.health_burn_per_second = object.health_burn_per_second ?? 0; message.health_burn_per_second = object.health_burn_per_second ?? 0;
message.fire_starting_chance = object.fire_starting_chance ?? 0; message.fire_starting_chance = object.fire_starting_chance ?? 0;
@@ -810,34 +846,34 @@ export const Tank: MessageFns<Tank> = {
}, },
}; };
function createBaseTank_CrewHealthEntry(): Tank_CrewHealthEntry { function createBaseCrewHealth(): CrewHealth {
return { key: "", value: 0 }; return { type: 0, max_health: 0 };
} }
export const Tank_CrewHealthEntry: MessageFns<Tank_CrewHealthEntry> = { export const CrewHealth: MessageFns<CrewHealth> = {
encode(message: Tank_CrewHealthEntry, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { encode(message: CrewHealth, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.key !== undefined) { if (message.type !== 0) {
writer.uint32(10).string(message.key); writer.uint32(8).int32(message.type);
} }
if (message.value !== undefined) { if (message.max_health !== 0) {
writer.uint32(21).float(message.value); writer.uint32(21).float(message.max_health);
} }
return writer; return writer;
}, },
decode(input: BinaryReader | Uint8Array, length?: number): Tank_CrewHealthEntry { decode(input: BinaryReader | Uint8Array, length?: number): CrewHealth {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input); const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length; let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseTank_CrewHealthEntry(); const message = createBaseCrewHealth();
while (reader.pos < end) { while (reader.pos < end) {
const tag = reader.uint32(); const tag = reader.uint32();
switch (tag >>> 3) { switch (tag >>> 3) {
case 1: { case 1: {
if (tag !== 10) { if (tag !== 8) {
break; break;
} }
message.key = reader.string(); message.type = reader.int32() as any;
continue; continue;
} }
case 2: { case 2: {
@@ -845,7 +881,7 @@ export const Tank_CrewHealthEntry: MessageFns<Tank_CrewHealthEntry> = {
break; break;
} }
message.value = reader.float(); message.max_health = reader.float();
continue; continue;
} }
} }
@@ -857,31 +893,31 @@ export const Tank_CrewHealthEntry: MessageFns<Tank_CrewHealthEntry> = {
return message; return message;
}, },
fromJSON(object: any): Tank_CrewHealthEntry { fromJSON(object: any): CrewHealth {
return { return {
key: globalThis.String(assertSet("Tank_CrewHealthEntry.key", object.key)), type: crewTypeFromJSON(assertSet("CrewHealth.type", object.type)),
value: globalThis.Number(assertSet("Tank_CrewHealthEntry.value", object.value)), max_health: globalThis.Number(assertSet("CrewHealth.max_health", object.max_health)),
}; };
}, },
toJSON(message: Tank_CrewHealthEntry): unknown { toJSON(message: CrewHealth): unknown {
const obj: any = {}; const obj: any = {};
if (message.key !== undefined) { if (message.type !== 0) {
obj.key = message.key; obj.type = crewTypeToJSON(message.type);
} }
if (message.value !== undefined) { if (message.max_health !== 0) {
obj.value = message.value; obj.max_health = message.max_health;
} }
return obj; return obj;
}, },
create<I extends Exact<DeepPartial<Tank_CrewHealthEntry>, I>>(base?: I): Tank_CrewHealthEntry { create<I extends Exact<DeepPartial<CrewHealth>, I>>(base?: I): CrewHealth {
return Tank_CrewHealthEntry.fromPartial(base ?? ({} as any)); return CrewHealth.fromPartial(base ?? ({} as any));
}, },
fromPartial<I extends Exact<DeepPartial<Tank_CrewHealthEntry>, I>>(object: I): Tank_CrewHealthEntry { fromPartial<I extends Exact<DeepPartial<CrewHealth>, I>>(object: I): CrewHealth {
const message = createBaseTank_CrewHealthEntry(); const message = createBaseCrewHealth();
message.key = object.key ?? ""; message.type = object.type ?? 0;
message.value = object.value ?? 0; message.max_health = object.max_health ?? 0;
return message; return message;
}, },
}; };
@@ -1158,7 +1194,7 @@ function createBaseModuleHealth(): ModuleHealth {
return { return {
max_health: 0, max_health: 0,
max_regen_health: 0, max_regen_health: 0,
hysteresis_health: 0, hysteresis_health: undefined,
health_regen_per_sec: 0, health_regen_per_sec: 0,
health_burn_per_sec: undefined, health_burn_per_sec: undefined,
}; };
@@ -1172,7 +1208,7 @@ export const ModuleHealth: MessageFns<ModuleHealth> = {
if (message.max_regen_health !== 0) { if (message.max_regen_health !== 0) {
writer.uint32(21).float(message.max_regen_health); writer.uint32(21).float(message.max_regen_health);
} }
if (message.hysteresis_health !== 0) { if (message.hysteresis_health !== undefined && message.hysteresis_health !== undefined) {
writer.uint32(29).float(message.hysteresis_health); writer.uint32(29).float(message.hysteresis_health);
} }
if (message.health_regen_per_sec !== 0) { if (message.health_regen_per_sec !== 0) {
@@ -1244,7 +1280,7 @@ export const ModuleHealth: MessageFns<ModuleHealth> = {
return { return {
max_health: globalThis.Number(assertSet("ModuleHealth.max_health", object.max_health)), max_health: globalThis.Number(assertSet("ModuleHealth.max_health", object.max_health)),
max_regen_health: globalThis.Number(assertSet("ModuleHealth.max_regen_health", object.max_regen_health)), max_regen_health: globalThis.Number(assertSet("ModuleHealth.max_regen_health", object.max_regen_health)),
hysteresis_health: globalThis.Number(assertSet("ModuleHealth.hysteresis_health", object.hysteresis_health)), hysteresis_health: isSet(object.hysteresis_health) ? globalThis.Number(object.hysteresis_health) : undefined,
health_regen_per_sec: globalThis.Number( health_regen_per_sec: globalThis.Number(
assertSet("ModuleHealth.health_regen_per_sec", object.health_regen_per_sec), assertSet("ModuleHealth.health_regen_per_sec", object.health_regen_per_sec),
), ),
@@ -1262,7 +1298,7 @@ export const ModuleHealth: MessageFns<ModuleHealth> = {
if (message.max_regen_health !== 0) { if (message.max_regen_health !== 0) {
obj.max_regen_health = message.max_regen_health; obj.max_regen_health = message.max_regen_health;
} }
if (message.hysteresis_health !== 0) { if (message.hysteresis_health !== undefined && message.hysteresis_health !== undefined) {
obj.hysteresis_health = message.hysteresis_health; obj.hysteresis_health = message.hysteresis_health;
} }
if (message.health_regen_per_sec !== 0) { if (message.health_regen_per_sec !== 0) {
@@ -1281,7 +1317,7 @@ export const ModuleHealth: MessageFns<ModuleHealth> = {
const message = createBaseModuleHealth(); const message = createBaseModuleHealth();
message.max_health = object.max_health ?? 0; message.max_health = object.max_health ?? 0;
message.max_regen_health = object.max_regen_health ?? 0; message.max_regen_health = object.max_regen_health ?? 0;
message.hysteresis_health = object.hysteresis_health ?? 0; message.hysteresis_health = object.hysteresis_health ?? undefined;
message.health_regen_per_sec = object.health_regen_per_sec ?? 0; message.health_regen_per_sec = object.health_regen_per_sec ?? 0;
message.health_burn_per_sec = object.health_burn_per_sec ?? undefined; message.health_burn_per_sec = object.health_burn_per_sec ?? undefined;
return message; return message;
@@ -1301,10 +1337,6 @@ type KeysOfUnion<T> = T extends T ? keyof T : never;
export type Exact<P, I extends P> = P extends Builtin ? P export type Exact<P, I extends P> = P extends Builtin ? P
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never }; : P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
function isObject(value: any): boolean {
return typeof value === "object" && value !== null;
}
function isSet(value: any): boolean { function isSet(value: any): boolean {
return value !== null && value !== undefined; return value !== null && value !== undefined;
} }
+34 -1
View File
@@ -3,6 +3,7 @@ using BlitzKit.CLI.Models;
using BlitzKit.CLI.Utils; using BlitzKit.CLI.Utils;
using CUE4Parse.FileProvider.Objects; using CUE4Parse.FileProvider.Objects;
using Google.Protobuf; using Google.Protobuf;
using Google.Protobuf.Collections;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace BlitzKit.CLI.Functions namespace BlitzKit.CLI.Functions
@@ -93,7 +94,7 @@ namespace BlitzKit.CLI.Functions
FuelTankHealth = MangleModuleHealth((props["FuelTankHealth"] as JObject)!), FuelTankHealth = MangleModuleHealth((props["FuelTankHealth"] as JObject)!),
}; };
tank.CrewHealth.Add("", 1); MangleCrewHealth(tank.CrewHealth, (props["CrewHealth"] as JArray)!);
tanks.Tanks_.Add(tank.Id); tanks.Tanks_.Add(tank.Id);
@@ -106,6 +107,38 @@ namespace BlitzKit.CLI.Functions
var tanksBytes = tanks.ToByteArray(); var tanksBytes = tanks.ToByteArray();
} }
public static Dictionary<string, CrewType> CrewTypes = new()
{
{ "EModuleOrTankmen::Commander", CrewType.Commander },
{ "EModuleOrTankmen::Driver", CrewType.Driver },
{ "EModuleOrTankmen::Gunner1", CrewType.Gunner1 },
{ "EModuleOrTankmen::Gunner2", CrewType.Gunner2 },
{ "EModuleOrTankmen::Loader1", CrewType.Loader1 },
{ "EModuleOrTankmen::Loader2", CrewType.Loader2 },
};
public static void MangleCrewHealth(RepeatedField<CrewHealth> map, JArray array)
{
foreach (var member in array.Cast<JObject>())
{
var key = member["Key"]!.Value<string>()!;
if (CrewTypes.TryGetValue(key, out var crewType))
{
CrewHealth crewHealth = new()
{
Type = crewType,
MaxHealth = member["Value"]!["MaxHealth"]!.Value<float>(),
};
map.Add(crewHealth);
}
else
{
throw new Exception($"Unrecognized CrewType: {key}");
}
}
}
public static ModuleHealth MangleModuleHealth(JObject obj) public static ModuleHealth MangleModuleHealth(JObject obj)
{ {
ModuleHealth moduleHealth = new() ModuleHealth moduleHealth = new()