diff --git a/scripts/inspect-mission.ts b/scripts/inspect-mission.ts index 5b743cf9..7d4b7ab1 100644 --- a/scripts/inspect-mission.ts +++ b/scripts/inspect-mission.ts @@ -51,7 +51,7 @@ async function run() { const missionScript = fs.readFileSync(missionFile, "utf8"); console.log( inspect(parseMissionScript(missionScript), { - colors: false, + colors: true, depth: Infinity, }) ); diff --git a/scripts/mission-properties.ts b/scripts/mission-properties.ts new file mode 100644 index 00000000..69a4eaa5 --- /dev/null +++ b/scripts/mission-properties.ts @@ -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 | null; + propertyList: Set | 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 }); diff --git a/src/components/Turret.tsx b/src/components/Turret.tsx index feb8b2b9..09efb7fb 100644 --- a/src/components/Turret.tsx +++ b/src/components/Turret.tsx @@ -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(` missing shape for dataBlock: ${dataBlock}`); @@ -55,6 +62,17 @@ export function Turret({ object }: { object: ConsoleObject }) { ) : ( )} + + {barrelShapeName ? ( + }> + }> + + + + ) : ( + + )} + ); }