Files
firestorm/ADDING-A-MAP.md
CydandClaude Fable 5 e84d6e603c Document mech + map/mission workflows; README folder map + clone warning
- ADDING-A-MECH.md: full workflow for adding a 'Mech chassis (MSL ADD MECH
  touch points, positional Mech IDs, scriptaddmech.xls generator, hardpoints
  in .damage, rebuild/repack/deploy steps)
- ADDING-A-MAP.md: full workflow for maps (MapCreator terrain) vs missions
  (MW4Ed2-authored), .nfo MP registration, user vs stock routes, pitfalls
- CLAUDE.md: reference pointers to both new docs
- README.md: annotated folder map; warning to read RECOVERY.md before cloning

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-01 21:15:52 -05:00

187 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Adding a new map / mission — full workflow
How to add a new playable map (terrain) and mission (scenario) to BattleTech: FireStorm
(MW4/Gameleap 5.03 engine). Reconstructed 2026-07-01 from the repo. Companion doc:
[ADDING-A-MECH.md](ADDING-A-MECH.md).
## The big picture — maps are NOT like mechs
Adding a 'Mech touches compiled code and a dozen parallel index arrays. Adding a map/mission
touches **none of that**: there are no `MSL ADD MAP` markers, no Mech-ID-style positional
tables, and **no exe rebuild**. Maps and missions are discovered at runtime by **file
enumeration** and registered by **per-mission files**, so the whole job is content + packaging.
Two separate things, often confused:
| Thing | Lives in | Packs to | What it is |
|---|---|---|---|
| **Map** | `Content\Maps\<Map>\` | `resource\maps\<map>.mw4` | Terrain only: tile geometry, materials, HUD overview image |
| **Mission** | `Content\Missions\<Name>\` | `resource\missions\<name>.mw4` | A playable scenario **on** a map: placed objects, drop zones, AI nav, scripts, game types |
Several missions can share one map (e.g. `Maps\Minerl03` hosts both `Cantina` and
`CantinaSiege`; `Maps\Reduex` hosts `Reduex` + `ReduexSiege`).
**The original mod-toolkit documentation survives** in
[_UNUSED/Gameleap/EditorDocs/](_UNUSED/Gameleap/EditorDocs/): *Map Creation Tutorial.doc*,
*Simple Map Creation Tutorial.doc*, *Terrain Generation.doc*, *Map Creator.rtf*,
*Material_Map.rtf*, *NFO File Editor.rtf*, *Editor_Tutorial.rtf*, plus the ABL tutorials
(*ABL_Mission_Tutorial.rtf*, *ABL_Brain_Tutorial.rtf*, *ABL_Orders.rtf*) and sample
heightfield/colormap/detailmap TGAs. Read those for tool operation; this doc covers how the
pieces wire into *this* repo.
**The tools ship in the dev tree root** (`Gameleap\mw4\`): `MapCreator.exe`/`MapCreatora.exe`
(terrain generation), `Tctd.exe` (terrain color/texture data), `NFOEditor.exe` (MP `.nfo`
registration), `ERF Deluxe.exe` (erf inspection), and the mission editor `MW4Ed2.exe`
(launch via `Gameleap\mw4\run-editor.bat` — fully working per CLAUDE.md STEP 8/9).
---
## Part 1 — The MAP (terrain): `Content\Maps\<Map>\`
Source art is a set of TGAs (heightfield, colormap, detail map, material map — see the
*Terrain Generation* / *Material_Map* docs and their sample TGAs). **MapCreator** turns them
into the terrain tile set; **Tctd** generates `tctd.ini`.
Using [Maps/StormCanyon/](Gameleap/mw4/Content/Maps/StormCanyon/) as the template:
| File | Purpose |
|---|---|
| `<Map>.build` | Pack manifest: `[resource\maps\<map>.mw4]` + `instance=` + `TexturePool=textures\maps\<Map>\textures.hint` |
| `<Map>.instance` | One page: `model=<Map>.data`, `executionstate=AlwaysExecuteState` |
| `<Map>.data` | `[gamedata]` `class=mechwarrior4::mwmap`, `grid=<Map>.erf`, `hudmap=hud\<map>` |
| `AA..CC .erf/.bsp/.Material` | The terrain tile grid (3×3 for StormCanyon), geometry + BSP + per-tile material properties — **generated by MapCreator** |
| `<map>.erf` | The terrain grid referenced by `grid=` |
| `tctd.ini` | Terrain color/texture data — **generated by Tctd.exe** |
Plus two texture registrations:
1. **Map textures**: `Content\textures\Maps\<Map>\*.tga` with their **own**
`textures.hint` in that folder (referenced by the map `.build`'s `TexturePool=`).
2. **HUD overview image**: the `.data`'s `hudmap=hud\<map>` needs an `[hud\<map>]` entry in
the master [Content/textures/textures.hint](Gameleap/mw4/Content/textures/textures.hint)
with the TGA in `Content\textures\HUD\` (packs into `textures.mw4`).
---
## Part 2 — The MISSION: `Content\Missions\<Name>\`
**Work in the editor.** `MW4Ed2` creates a new mission by cloning
`Content\Missions\EditorTemplate\` (scripts, sounds, lights —
[GameInterface.cpp:1352](Gameleap/code/mw4/Code/MW4GameEd2/GameInterface.cpp#L1352)) onto a
map you pick, and on save writes all the files below back into `Content\Missions\<Name>\`.
File roles, using [Missions/StormCanyon/](Gameleap/mw4/Content/Missions/StormCanyon/) as the
template ("(editor)" = generated/maintained by MW4Ed2; hand-edit only the rest):
| File | Purpose |
|---|---|
| `<Name>.build` | Pack manifest: `[resource\missions\<name>.mw4]` + `texturepool=<name>.hint`, `Instance=`, `directory=...\scripts`, `Soundpool=<name>.sounds`. **The `[resource\...]` page name is the published .mw4 path** — stock MW4 missions abbreviate (`CentralPark``cpark.mw4`); FireStorm ones keep the full name |
| `<Name>.instance` | The hub: `model=<name>.data`, `map=maps\<map>\<map>.instance`, `props=<name>.contents`, `sky=`/`nightsky=` (an erf from `Content\Skies`), `missionbounds`/`warningbounds`, `nametable=`, `railgraph=`, `script=` |
| `<Name>.data` | Environment: fog banks, weather effects, clip planes, `allowrespawn`, `heatsinkefficiency`, `isnightmission`, `lights=`/`nightlights=` (editor) |
| `<Name>.contents` | Every placed object. Includes the **drop zones**: `[dropteam1..4]` + `[playerstart]` sections (`Model=Misc\DropZone\DropZone.data`, `DropPoints=DropZones\DropTeamN.contents`) — per-team spawn-point sets; this is the "≥N drop points per map" constraint from the MP-cap plan (editor) |
| `<Name>.ini` | Editor metadata per object (type=dropzone/helper, invulnerable, snaptoground…) (editor) |
| `<Name>.table` | Name↔ID replication table (editor) |
| `<Name>Graph.data`, `<Name>MoveGrid.data`, `<Name>RectGrid.data`, `<Name>AirMoveGrid.data` | AI rail graph + ground/air pathing grids (editor — [SaveRailGraph](Gameleap/code/mw4/Code/MW4GameEd2/GameInterface.cpp#L2130)) |
| `<Name>.lights`, `<Name>night.lights`, `<Name>_lightmap.raw` | Day/night lighting + baked lightmap (editor) |
| `Mission.bounds`, `Warning.bounds` | Playable-area polygons (editor) |
| `<Name>.hint`, `<Name>.sounds` | Mission-local texture pool + sound pool |
| `Scripts\*.abl` | Mission logic in ABL: a base `<Name>.abl`, `player.abl`, and **one script per supported game type** (`<Name>_Destruction.ABL`, `_TeamDestruction`, `_Attrition`, `_CTF`, …) referenced from the `.nfo` (see Part 3). ABL docs in EditorDocs |
---
## Part 3 — Registration (how the game finds it)
There are **two routes**, and FireStorm's own maps (Freezer, StormCanyon, Nazca…) use Route B:
### Route A — user mission (zero manifest edits)
The editor can save/publish straight to `Resource\UserMissions\`: the compiled
`<name>.mw4` + `.nfo` + a 112×112 overview `.tga`
([GameInterface.cpp:1443](Gameleap/code/mw4/Code/MW4GameEd2/GameInterface.cpp#L1443)).
User missions are **auto-discovered**: the MP host list enumerates
`Resource\UserMissions\*.nfo` and Instant Action enumerates `Resource\UserMissions\*.mw4`
([MW4Shell.cpp:4331](Gameleap/code/mw4/Code/MW4/MW4Shell.cpp#L4331)). Nothing else to edit.
Good for prototyping; the deployed game (`C:\VWE\firestorm\MW4`) currently ships 0 of these.
### Route B — stock mission (first-class FireStorm content)
1. **[Content/MechWarrior4.build](Gameleap/mw4/Content/MechWarrior4.build)** — add the
nested pair (mission inside its map, expressing the dependency):
```
maps\<map>\<map>.build={
missions\<name>\<name>.build={
}
}
```
(If the map already exists, add only the mission line inside its block.) The editor has an
`AddToBuildFile()` for this but its call is **commented out**
([GameInterface.cpp:1453](Gameleap/code/mw4/Code/MW4GameEd2/GameInterface.cpp#L1453)) —
edit by hand.
2. **`Resource\Missions\<Name>.nfo`** — the **multiplayer registration**, a loose text file
(never packed; the deploy copies `Resource\` wholesale). The shell enumerates
`Resource\Missions\*.nfo` ([MW4Shell.cpp:12546](Gameleap/code/mw4/Code/MW4/MW4Shell.cpp#L12546))
and reads: `[info]` (`longname` = lobby display name, `author`), and `[scenarios]` — one
nested `[server]` page per offered game type with `name`, `ruleset=$(CustomDestruction)`
etc. (constants from [Content/GameTypes.h](Gameleap/mw4/Content/GameTypes.h)),
`teamAllowed`/`teamcount`, `scenariotext`, and the matching `scriptname=...\Scripts\<Name>_<type>.abl`.
Copy [StormCanyon.nfo](Gameleap/mw4/Resource/Missions/StormCanyon.nfo) as the template
(or use `NFOEditor.exe`; *NFO File Editor.rtf* documents it).
3. **[Tables/missionnames.tbl](Gameleap/mw4/Content/Tables/missionnames.tbl)** — the
resource-name redirect table (packed into `core.mw4`). Stock MW4 rows map long names to
abbreviated .mw4 names; FireStorm rows are self-mappings. Add
`resource\missions\<Name>.mw4=resource\missions\<Name>.mw4` under `// BTFRSTRM Missions`.
4. **Instant Action (optional)** — the IA mission list = campaign-defined missions + user
missions ([GetMissionNames, MW4Shell.cpp:4297](Gameleap/code/mw4/Code/MW4/MW4Shell.cpp#L4297)).
To surface a stock mission in IA, add a page to
[Campaigns/InstantAction.Campaign](Gameleap/mw4/Content/Campaigns/InstantAction.Campaign)
(`[content\missions\<name>\<name>.instance]` with `Status=Displayed`, display-name string,
rollover text, map thumbnail). Campaign files pack via `props.build` `Campaign=` lines.
5. **Sky** — reuse an existing sky from `Content\Skies` (already packed in `skies.mw4`);
a new sky means a new entry in `Content\skies.build`. Beware the STEP 8 lesson: the
`.instance` `sky=` path must match the erf filename exactly (case/name).
---
## Part 4 — Build, deploy, verify
1. **No exe rebuild.** Repack resources with `build-env\build-resources.ps1` (wraps
`MW4pro.exe -build`; LAB_ONLY builds only — see
[build-env/RESOURCE-BUILD.md](build-env/RESOURCE-BUILD.md)). Output:
`resource\maps\<map>.mw4` + `resource\missions\<name>.mw4`, plus `textures.mw4`/`core.mw4`
if you touched `textures.hint`/`missionnames.tbl`.
2. **Redeploy** with `build-env\deploy-mw4.ps1` (copies `Resource\` — including the `.nfo`
and the repacked packages into `C:\VWE\firestorm\MW4`).
3. **Verify**:
- `MW4Ed2.exe <MissionName> -report` — headless load of the mission (same path the editor
uses; catches broken refs without clicking through the UI).
- Open it in the editor: drop zones present for every team, AI grids regenerate cleanly.
- Host a LAN game: mission appears in the host list under each declared game type with the
`.nfo` `longname`; all teams spawn at their `dropteam*` zones; HUD overview map shows.
- If IA-registered: appears in the Instant Action mission dropdown.
### Known pitfalls (all hit during STEP 7/8 content curation — the editor STOPs hard)
- **The editor loads every mission/map at startup** (`ObjMan->BuildResources()`) and LAB
builds STOP fatally on the first defect — one broken mission breaks editor startup for
everything.
- **Name consistency is everything**: the folder name, the `[page]` name in
`.build`/`.instance`, and the file basenames must agree (the `_backup`-dir and
`PhoenixPalaceSTB` incidents). `Map=` in the mission `.instance` must point at a map that
actually exists (the `arctic01`/`lunar02` dangling refs).
- The mission `.instance` `Model=` must reference the `[gamedata]`-class page (`<name>.data`),
not some other page (`hill.contents` incident).
- `.mw4` package names in `.build` page headers are the *published* identity — changing one
orphans the old `.dep`/`.mw4` in `Resource\`.
## Quick-reference: every touch point (Route B stock mission on a new map)
```
TERRAIN Content\Maps\<Map>\ (.build/.instance/.data + MapCreator tiles + tctd.ini)
Content\textures\Maps\<Map>\ (map textures + own textures.hint)
Content\textures\textures.hint ([hud\<map>] entry) + Content\textures\HUD\<map>.tga
MISSION Content\Missions\<Name>\ (editor-authored: ~18 files, see Part 2)
Content\Missions\<Name>\Scripts\*.abl (one per game type + player.abl)
REGISTER Content\MechWarrior4.build (nest mission .build under map .build — manual)
Resource\Missions\<Name>.nfo (MP game types; loose file, not packed)
Content\Tables\missionnames.tbl (self-mapping row; packs into core.mw4)
Content\Campaigns\InstantAction.Campaign (optional, for IA list)
BUILD build-env\build-resources.ps1 → deploy-mw4.ps1
TOOLS MapCreator.exe / Tctd.exe / NFOEditor.exe / MW4Ed2.exe (run-editor.bat)
DOCS _UNUSED\Gameleap\EditorDocs\ (original tutorials: map creation, terrain, NFO, ABL)
```