feat: more shit

This commit is contained in:
tresabhi committed 2025-02-01 21:21:12 -06:00
1 parent 920ef6e5c4
commit 8b0f95c53d
7 files changed
+129 -174

No files matched your search

+2 -3
View File
@@ -21,12 +21,12 @@ message Tank {
required ModuleHealth fuel_tank_health = 12; required ModuleHealth fuel_tank_health = 12;
repeated CrewHealth 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_sec = 15;
required float fire_starting_chance = 16; required float fire_starting_chance = 16;
required float concealment_stationary = 17; required float concealment_stationary = 17;
required float concealment_moving = 18; required float concealment_moving = 18;
required float concealment_factor_on_shot = 19; required float concealment_factor_at_shot = 19;
required float turret_turn_rate = 20; required float turret_turn_rate = 20;
required float circular_vision_radius = 21; required float circular_vision_radius = 21;
@@ -46,7 +46,6 @@ message Tank {
required float rotation_speed = 33; required float rotation_speed = 33;
required float terrain_resistance_hard = 34; required float terrain_resistance_hard = 34;
required float brake_force = 35; required float brake_force = 35;
required bool b_rotation_is_around_center = 36;
} }
enum CrewType { enum CrewType {
+19 -41
View File
@@ -79,11 +79,11 @@ export interface Tank {
fuel_tank_health: ModuleHealth; fuel_tank_health: ModuleHealth;
crew_health: CrewHealth[]; crew_health: CrewHealth[];
max_health: number; max_health: number;
health_burn_per_second: number; health_burn_per_sec: number;
fire_starting_chance: number; fire_starting_chance: number;
concealment_stationary: number; concealment_stationary: number;
concealment_moving: number; concealment_moving: number;
concealment_factor_on_shot: number; concealment_factor_at_shot: number;
turret_turn_rate: number; turret_turn_rate: number;
circular_vision_radius: number; circular_vision_radius: number;
shells: Shell[]; shells: Shell[];
@@ -100,7 +100,6 @@ export interface Tank {
rotation_speed: number; rotation_speed: number;
terrain_resistance_hard: number; terrain_resistance_hard: number;
brake_force: number; brake_force: number;
b_rotation_is_around_center: boolean;
} }
export interface CrewHealth { export interface CrewHealth {
@@ -165,11 +164,11 @@ function createBaseTank(): Tank {
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_sec: 0,
fire_starting_chance: 0, fire_starting_chance: 0,
concealment_stationary: 0, concealment_stationary: 0,
concealment_moving: 0, concealment_moving: 0,
concealment_factor_on_shot: 0, concealment_factor_at_shot: 0,
turret_turn_rate: 0, turret_turn_rate: 0,
circular_vision_radius: 0, circular_vision_radius: 0,
shells: [], shells: [],
@@ -186,7 +185,6 @@ function createBaseTank(): Tank {
rotation_speed: 0, rotation_speed: 0,
terrain_resistance_hard: 0, terrain_resistance_hard: 0,
brake_force: 0, brake_force: 0,
b_rotation_is_around_center: false,
}; };
} }
@@ -234,8 +232,8 @@ export const Tank: MessageFns<Tank> = {
if (message.max_health !== 0) { if (message.max_health !== 0) {
writer.uint32(117).float(message.max_health); writer.uint32(117).float(message.max_health);
} }
if (message.health_burn_per_second !== 0) { if (message.health_burn_per_sec !== 0) {
writer.uint32(125).float(message.health_burn_per_second); writer.uint32(125).float(message.health_burn_per_sec);
} }
if (message.fire_starting_chance !== 0) { if (message.fire_starting_chance !== 0) {
writer.uint32(133).float(message.fire_starting_chance); writer.uint32(133).float(message.fire_starting_chance);
@@ -246,8 +244,8 @@ export const Tank: MessageFns<Tank> = {
if (message.concealment_moving !== 0) { if (message.concealment_moving !== 0) {
writer.uint32(149).float(message.concealment_moving); writer.uint32(149).float(message.concealment_moving);
} }
if (message.concealment_factor_on_shot !== 0) { if (message.concealment_factor_at_shot !== 0) {
writer.uint32(157).float(message.concealment_factor_on_shot); writer.uint32(157).float(message.concealment_factor_at_shot);
} }
if (message.turret_turn_rate !== 0) { if (message.turret_turn_rate !== 0) {
writer.uint32(165).float(message.turret_turn_rate); writer.uint32(165).float(message.turret_turn_rate);
@@ -297,9 +295,6 @@ export const Tank: MessageFns<Tank> = {
if (message.brake_force !== 0) { if (message.brake_force !== 0) {
writer.uint32(285).float(message.brake_force); writer.uint32(285).float(message.brake_force);
} }
if (message.b_rotation_is_around_center !== false) {
writer.uint32(288).bool(message.b_rotation_is_around_center);
}
return writer; return writer;
}, },
@@ -427,7 +422,7 @@ export const Tank: MessageFns<Tank> = {
break; break;
} }
message.health_burn_per_second = reader.float(); message.health_burn_per_sec = reader.float();
continue; continue;
} }
case 16: { case 16: {
@@ -459,7 +454,7 @@ export const Tank: MessageFns<Tank> = {
break; break;
} }
message.concealment_factor_on_shot = reader.float(); message.concealment_factor_at_shot = reader.float();
continue; continue;
} }
case 20: { case 20: {
@@ -590,14 +585,6 @@ export const Tank: MessageFns<Tank> = {
message.brake_force = reader.float(); message.brake_force = reader.float();
continue; continue;
} }
case 36: {
if (tag !== 288) {
break;
}
message.b_rotation_is_around_center = reader.bool();
continue;
}
} }
if ((tag & 7) === 4 || tag === 0) { if ((tag & 7) === 4 || tag === 0) {
break; break;
@@ -629,16 +616,14 @@ export const Tank: MessageFns<Tank> = {
? object.crew_health.map((e: any) => CrewHealth.fromJSON(e)) ? object.crew_health.map((e: any) => CrewHealth.fromJSON(e))
: [], : [],
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_sec: globalThis.Number(assertSet("Tank.health_burn_per_sec", object.health_burn_per_sec)),
assertSet("Tank.health_burn_per_second", object.health_burn_per_second),
),
fire_starting_chance: globalThis.Number(assertSet("Tank.fire_starting_chance", object.fire_starting_chance)), fire_starting_chance: globalThis.Number(assertSet("Tank.fire_starting_chance", object.fire_starting_chance)),
concealment_stationary: globalThis.Number( concealment_stationary: globalThis.Number(
assertSet("Tank.concealment_stationary", object.concealment_stationary), assertSet("Tank.concealment_stationary", object.concealment_stationary),
), ),
concealment_moving: globalThis.Number(assertSet("Tank.concealment_moving", object.concealment_moving)), concealment_moving: globalThis.Number(assertSet("Tank.concealment_moving", object.concealment_moving)),
concealment_factor_on_shot: globalThis.Number( concealment_factor_at_shot: globalThis.Number(
assertSet("Tank.concealment_factor_on_shot", object.concealment_factor_on_shot), assertSet("Tank.concealment_factor_at_shot", object.concealment_factor_at_shot),
), ),
turret_turn_rate: globalThis.Number(assertSet("Tank.turret_turn_rate", object.turret_turn_rate)), turret_turn_rate: globalThis.Number(assertSet("Tank.turret_turn_rate", object.turret_turn_rate)),
circular_vision_radius: globalThis.Number( circular_vision_radius: globalThis.Number(
@@ -664,9 +649,6 @@ export const Tank: MessageFns<Tank> = {
assertSet("Tank.terrain_resistance_hard", object.terrain_resistance_hard), assertSet("Tank.terrain_resistance_hard", object.terrain_resistance_hard),
), ),
brake_force: globalThis.Number(assertSet("Tank.brake_force", object.brake_force)), brake_force: globalThis.Number(assertSet("Tank.brake_force", object.brake_force)),
b_rotation_is_around_center: globalThis.Boolean(
assertSet("Tank.b_rotation_is_around_center", object.b_rotation_is_around_center),
),
}; };
}, },
@@ -714,8 +696,8 @@ export const Tank: MessageFns<Tank> = {
if (message.max_health !== 0) { if (message.max_health !== 0) {
obj.max_health = message.max_health; obj.max_health = message.max_health;
} }
if (message.health_burn_per_second !== 0) { if (message.health_burn_per_sec !== 0) {
obj.health_burn_per_second = message.health_burn_per_second; obj.health_burn_per_sec = message.health_burn_per_sec;
} }
if (message.fire_starting_chance !== 0) { if (message.fire_starting_chance !== 0) {
obj.fire_starting_chance = message.fire_starting_chance; obj.fire_starting_chance = message.fire_starting_chance;
@@ -726,8 +708,8 @@ export const Tank: MessageFns<Tank> = {
if (message.concealment_moving !== 0) { if (message.concealment_moving !== 0) {
obj.concealment_moving = message.concealment_moving; obj.concealment_moving = message.concealment_moving;
} }
if (message.concealment_factor_on_shot !== 0) { if (message.concealment_factor_at_shot !== 0) {
obj.concealment_factor_on_shot = message.concealment_factor_on_shot; obj.concealment_factor_at_shot = message.concealment_factor_at_shot;
} }
if (message.turret_turn_rate !== 0) { if (message.turret_turn_rate !== 0) {
obj.turret_turn_rate = message.turret_turn_rate; obj.turret_turn_rate = message.turret_turn_rate;
@@ -777,9 +759,6 @@ export const Tank: MessageFns<Tank> = {
if (message.brake_force !== 0) { if (message.brake_force !== 0) {
obj.brake_force = message.brake_force; obj.brake_force = message.brake_force;
} }
if (message.b_rotation_is_around_center !== false) {
obj.b_rotation_is_around_center = message.b_rotation_is_around_center;
}
return obj; return obj;
}, },
@@ -820,11 +799,11 @@ export const Tank: MessageFns<Tank> = {
: createBaseModuleHealth(); : createBaseModuleHealth();
message.crew_health = object.crew_health?.map((e) => CrewHealth.fromPartial(e)) || []; message.crew_health = object.crew_health?.map((e) => CrewHealth.fromPartial(e)) || [];
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_sec = object.health_burn_per_sec ?? 0;
message.fire_starting_chance = object.fire_starting_chance ?? 0; message.fire_starting_chance = object.fire_starting_chance ?? 0;
message.concealment_stationary = object.concealment_stationary ?? 0; message.concealment_stationary = object.concealment_stationary ?? 0;
message.concealment_moving = object.concealment_moving ?? 0; message.concealment_moving = object.concealment_moving ?? 0;
message.concealment_factor_on_shot = object.concealment_factor_on_shot ?? 0; message.concealment_factor_at_shot = object.concealment_factor_at_shot ?? 0;
message.turret_turn_rate = object.turret_turn_rate ?? 0; message.turret_turn_rate = object.turret_turn_rate ?? 0;
message.circular_vision_radius = object.circular_vision_radius ?? 0; message.circular_vision_radius = object.circular_vision_radius ?? 0;
message.shells = object.shells?.map((e) => Shell.fromPartial(e)) || []; message.shells = object.shells?.map((e) => Shell.fromPartial(e)) || [];
@@ -841,7 +820,6 @@ export const Tank: MessageFns<Tank> = {
message.rotation_speed = object.rotation_speed ?? 0; message.rotation_speed = object.rotation_speed ?? 0;
message.terrain_resistance_hard = object.terrain_resistance_hard ?? 0; message.terrain_resistance_hard = object.terrain_resistance_hard ?? 0;
message.brake_force = object.brake_force ?? 0; message.brake_force = object.brake_force ?? 0;
message.b_rotation_is_around_center = object.b_rotation_is_around_center ?? false;
return message; return message;
}, },
}; };
+29 -89
View File
@@ -1,112 +1,52 @@
using Blitzkit; using Blitzkit;
using BlitzKit.CLI.Models; using BlitzKit.CLI.Models;
using BlitzKit.CLI.Utils;
using CUE4Parse.FileProvider.Objects;
using Google.Protobuf.Collections; using Google.Protobuf.Collections;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace BlitzKit.CLI.Functions namespace BlitzKit.CLI.Functions
{ {
public static class Mangler public class Mangler
{ {
public static void Mangle() readonly Tanks tanks = new();
{ readonly BlitzProvider provider = new();
Tanks tanks = new();
BlitzProvider provider = new();
foreach ( public void Mangle()
var nationDir in provider.RootDirectory.GetDirectory("Blitz/Content/Tanks").Directories {
) var nationDirs = provider.RootDirectory.GetDirectory("Blitz/Content/Tanks").Directories;
foreach (var nationDir in nationDirs)
{ {
if (nationDir.Key == "TankStub") if (nationDir.Key == "TankStub")
continue; continue;
foreach (var tankDir in nationDir.Value.Directories) MangleNation(nationDir.Value);
{
var id = tankDir.Key;
if (id != "R90_IS_4")
continue;
var attributeFileName = $"DA_{id}_Attributes.uasset";
var hasAttributesFile = tankDir.Value.HasFile(attributeFileName);
GameFile? attributesFile = null;
if (hasAttributesFile)
{
attributesFile = tankDir.Value.GetFile(attributeFileName);
}
else
{
PrettyLog.Warn(
$"No attributes file found for {nationDir.Key}/{id}, it may be misspelled; finding any attributes file..."
);
foreach (var file in tankDir.Value.Files)
{
if (file.Key.EndsWith("_Attributes.uasset"))
{
attributesFile = file.Value;
break;
}
}
if (attributesFile == null)
{
PrettyLog.Error(
$"No suffixed attributes file found for {nationDir.Key}/{id}; skipping..."
);
continue;
}
}
var exports = provider.LoadAllObjects(attributesFile.Path);
var tankAttributesDataAsset =
exports.First((export) => export.ExportType == "TankAttributesDataAsset")
?? throw new Exception("TankAttributesDataAsset not found");
var attr = JObject.FromObject(tankAttributesDataAsset);
if (attr["Properties"] is not JObject props || props["MaxHealth"] == null)
{
PrettyLog.Warn($"{nationDir.Key}/{id} has not migrated to Reforged; skipping...");
continue;
}
var tank = MangleTank(id, props);
tanks.Tanks_.Add(tank.Id);
Console.WriteLine($"Mangled {nationDir.Key}/{id}");
}
} }
} }
public static Tank MangleTank(string id, JObject props) void MangleNation(VfsDirectory nation)
{ {
Tank tank = new() foreach (var tankDir in nation.Directories)
{ {
Id = id, if (tankDir.Value.Name != "R90_IS_4")
// TODO: Name continue;
// TODO: Set
// TODO: Class
// TODO: Faction
TurretRotatorHealth = MangleModuleHealth((props["TurretRotatorHealth"] as JObject)!), var tank = MangleTank(tankDir.Value);
SurveyingDeviceHealth = MangleModuleHealth((props["SurveyingDeviceHealth"] as JObject)!),
GunHealth = MangleModuleHealth((props["GunHealth"] as JObject)!),
ChassisHealth = MangleModuleHealth((props["ChassisHealth"] as JObject)!),
AmmoBayHealth = MangleModuleHealth((props["AmmoBayHealth"] as JObject)!),
EngineHealth = MangleModuleHealth((props["EngineHealth"] as JObject)!),
FuelTankHealth = MangleModuleHealth((props["FuelTankHealth"] as JObject)!),
};
MangleCrewHealth(tank.CrewHealth, (props["CrewHealth"] as JArray)!); tanks.Tanks_.Add(tank.Id);
}
return tank;
} }
public static Dictionary<string, CrewType> CrewTypes = new() Tank MangleTank(VfsDirectory tankDir)
{
var pdaName = $"PDA_{tankDir.Name}";
var pda = tankDir.GetUasset($"{pdaName}.uasset").Get(pdaName);
Console.WriteLine(pda);
return new();
}
Dictionary<string, CrewType> CrewTypes = new()
{ {
{ "EModuleOrTankmen::Commander", CrewType.Commander }, { "EModuleOrTankmen::Commander", CrewType.Commander },
{ "EModuleOrTankmen::Driver", CrewType.Driver }, { "EModuleOrTankmen::Driver", CrewType.Driver },
@@ -116,7 +56,7 @@ namespace BlitzKit.CLI.Functions
{ "EModuleOrTankmen::Loader2", CrewType.Loader2 }, { "EModuleOrTankmen::Loader2", CrewType.Loader2 },
}; };
public static void MangleCrewHealth(RepeatedField<CrewHealth> map, JArray array) void MangleCrewHealth(RepeatedField<CrewHealth> map, JArray array)
{ {
foreach (var member in array.Cast<JObject>()) foreach (var member in array.Cast<JObject>())
{ {
@@ -138,7 +78,7 @@ namespace BlitzKit.CLI.Functions
} }
} }
public static ModuleHealth MangleModuleHealth(JObject obj) ModuleHealth MangleModuleHealth(JObject obj)
{ {
ModuleHealth moduleHealth = new() ModuleHealth moduleHealth = new()
{ {
+3 -40
View File
@@ -15,7 +15,7 @@ namespace BlitzKit.CLI.Models
private static readonly string LOCAL_MAPPINGS_PATH = private static readonly string LOCAL_MAPPINGS_PATH =
"../../submodules/blitzkit-closed/blitz.usmap"; "../../submodules/blitzkit-closed/blitz.usmap";
public readonly VfsDirectory RootDirectory = new(); public readonly VfsDirectory RootDirectory;
public BlitzProvider() public BlitzProvider()
: base( : base(
@@ -25,6 +25,7 @@ namespace BlitzKit.CLI.Models
versions: new(EGame.GAME_UE5_3) versions: new(EGame.GAME_UE5_3)
) )
{ {
RootDirectory = new() { Name = "", provider = this };
MappingsContainer = new FileUsmapTypeMappingsProvider(LOCAL_MAPPINGS_PATH); MappingsContainer = new FileUsmapTypeMappingsProvider(LOCAL_MAPPINGS_PATH);
Initialize(); Initialize();
@@ -51,7 +52,7 @@ namespace BlitzKit.CLI.Models
} }
else else
{ {
VfsDirectory newDirectory = new(); VfsDirectory newDirectory = new() { Name = segment, provider = this };
directory.AddDirectory(segment, newDirectory); directory.AddDirectory(segment, newDirectory);
directory = newDirectory; directory = newDirectory;
} }
@@ -59,42 +60,4 @@ namespace BlitzKit.CLI.Models
} }
} }
} }
public class VfsDirectory
{
public Dictionary<string, VfsDirectory> Directories = [];
public Dictionary<string, GameFile> Files = [];
public void AddFile(string name, GameFile file) => Files.TryAdd(name, file);
public bool HasFile(string name) => Files.ContainsKey(name);
public GameFile GetFile(string name)
{
var directoryPath = Path.GetDirectoryName(name);
var fileName = Path.GetFileName(name);
var directory =
directoryPath == null || directoryPath.Length == 0 ? this : GetDirectory(directoryPath);
return directory.Files[fileName];
}
public bool HasDirectory(string name) => Directories.ContainsKey(name);
public VfsDirectory GetDirectory(string name)
{
var segments = name.Split('/');
var directory = this;
foreach (var segment in segments)
{
directory = directory.Directories[segment];
}
return directory;
}
public void AddDirectory(string name, VfsDirectory directory) =>
Directories.Add(name, directory);
}
} }
+25
View File
@@ -0,0 +1,25 @@
using CUE4Parse.FileProvider;
using CUE4Parse.FileProvider.Objects;
using CUE4Parse.UE4.Assets.Exports;
namespace BlitzKit.CLI.Models
{
public class Uasset
{
readonly GameFile file;
readonly Dictionary<string, UObject> objects = [];
public Uasset(GameFile file, AbstractFileProvider provider)
{
this.file = file;
var objects = provider.LoadAllObjects(file.Path);
foreach (var obj in objects)
{
this.objects.Add(obj.Name, obj);
}
}
public UObject Get(string name) => objects[name];
}
}
+47
View File
@@ -0,0 +1,47 @@
using CUE4Parse.FileProvider;
using CUE4Parse.FileProvider.Objects;
namespace BlitzKit.CLI.Models
{
public class VfsDirectory
{
public Dictionary<string, VfsDirectory> Directories = [];
public Dictionary<string, GameFile> Files = [];
public required string Name;
public required AbstractFileProvider provider;
public void AddFile(string name, GameFile file) => Files.TryAdd(name, file);
public bool HasFile(string name) => Files.ContainsKey(name);
public Uasset GetUasset(string name) => new(GetFile(name), provider);
public GameFile GetFile(string name)
{
var directoryPath = Path.GetDirectoryName(name);
var fileName = Path.GetFileName(name);
var directory =
directoryPath == null || directoryPath.Length == 0 ? this : GetDirectory(directoryPath);
return directory.Files[fileName];
}
public bool HasDirectory(string name) => Directories.ContainsKey(name);
public VfsDirectory GetDirectory(string name)
{
var segments = name.Split('/');
var directory = this;
foreach (var segment in segments)
{
directory = directory.Directories[segment];
}
return directory;
}
public void AddDirectory(string name, VfsDirectory directory) =>
Directories.Add(name, directory);
}
}
+4 -1
View File
@@ -19,7 +19,10 @@ namespace BlitzKit.CLI
case "mangle": case "mangle":
{ {
Mangler.Mangle(); Mangler mangler = new();
mangler.Mangle();
break; break;
} }