add script to inspect properties, add turret barrels

This commit is contained in:
Brian Beck 2025-11-16 11:36:10 -08:00
parent 1e7329b799
commit a05153303e
3 changed files with 94 additions and 1 deletions

View file

@ -51,7 +51,7 @@ async function run() {
const missionScript = fs.readFileSync(missionFile, "utf8");
console.log(
inspect(parseMissionScript(missionScript), {
colors: false,
colors: true,
depth: Infinity,
})
);

View file

@ -0,0 +1,75 @@
import fs from "node:fs/promises";
import { iterObjects, parseMissionScript } from "@/src/mission";
import { parseArgs } from "node:util";
import { basename } from "node:path";
/**
* For all missions, log all the property values matching the given filters.
*
* --types, -t: Comma-separatated list of object class names.
* --properties, -p: Comma-separated list of property names.
* --values: Whether to log ONLY the values (and not mission and class name).
*
* Example:
*
* tsx scripts/mission-properties.ts -t TerrainBlock -p position
*/
const { values, positionals } = parseArgs({
allowPositionals: true,
options: {
types: {
type: "string",
short: "t",
},
properties: {
type: "string",
short: "p",
},
values: {
type: "boolean",
},
},
});
const typeList =
!values.types || values.types === "*"
? null
: new Set(values.types.split(","));
const propertyList =
!values.properties || values.properties === "*"
? null
: new Set(values.properties.split(","));
async function run({
typeList,
propertyList,
valuesOnly,
}: {
typeList: Set<string> | null;
propertyList: Set<string> | null;
valuesOnly: boolean;
}) {
for await (const inFile of fs.glob("docs/base/**/*.mis")) {
const baseName = basename(inFile);
const missionScript = await fs.readFile(inFile, "utf8");
const mission = parseMissionScript(missionScript);
for (const consoleObject of iterObjects(mission.objects)) {
if (!typeList || typeList.has(consoleObject.className)) {
for (const property of consoleObject.properties) {
if (!propertyList || propertyList.has(property.target.name)) {
if (valuesOnly) {
console.log(property.value);
} else {
console.log(
`${baseName} > ${consoleObject.className} > ${property.target.name} = ${property.value}`
);
}
}
}
}
}
}
}
run({ typeList, propertyList, valuesOnly: values.values });

View file

@ -10,6 +10,11 @@ import {
import { ShapeModel, ShapePlaceholder } from "./GenericShape";
const dataBlockToShapeName = {
AABarrelLarge: "turret_aa_large.dts",
ELFBarrelLarge: "turret_elf_large.dts",
MissileBarrelLarge: "turret_missile_large.dts",
MortarBarrelLarge: "turret_mortar_large.dts",
PlasmaBarrelLarge: "turret_fusion_large.dts",
SentryTurret: "turret_sentry.dts",
TurretBaseLarge: "turret_base_large.dts",
};
@ -29,12 +34,14 @@ function getDataBlockShape(dataBlock: string) {
export function Turret({ object }: { object: ConsoleObject }) {
const dataBlock = getProperty(object, "dataBlock").value;
const initialBarrel = getProperty(object, "initialBarrel").value;
const [z, y, x] = useMemo(() => getPosition(object), [object]);
const [scaleX, scaleY, scaleZ] = useMemo(() => getScale(object), [object]);
const q = useMemo(() => getRotation(object, true), [object]);
const shapeName = getDataBlockShape(dataBlock);
const barrelShapeName = getDataBlockShape(initialBarrel);
if (!shapeName) {
console.error(`<Turret> missing shape for dataBlock: ${dataBlock}`);
@ -55,6 +62,17 @@ export function Turret({ object }: { object: ConsoleObject }) {
) : (
<ShapePlaceholder color="orange" />
)}
<group position={[0, 1.5, 0]}>
{barrelShapeName ? (
<ErrorBoundary fallback={<ShapePlaceholder color="red" />}>
<Suspense fallback={<ShapePlaceholder color="yellow" />}>
<ShapeModel shapeName={barrelShapeName} />
</Suspense>
</ErrorBoundary>
) : (
<ShapePlaceholder color="orange" />
)}
</group>
</group>
);
}