docs: rewrite ARCHITECTURE as a Module/Function/Feature master plan
Decompose the full Red Alert 3 feature set three levels deep (29 modules, 169 functions, ~500 features) with per-feature status and milestone tags. Fold the release roadmap into ARCHITECTURE section 5 and remove docs/ROADMAP.md.
This commit is contained in:
@@ -97,7 +97,7 @@ built-in test map so the project still builds and runs in CI.
|
|||||||
| `apps/openra3/main.cpp` | `menu` / `maps` / `skirmish` / `render` CLI |
|
| `apps/openra3/main.cpp` | `menu` / `maps` / `skirmish` / `render` CLI |
|
||||||
| `tests/ra3_tests.cpp` | smoke tests (run via `ctest`) |
|
| `tests/ra3_tests.cpp` | smoke tests (run via `ctest`) |
|
||||||
| `tools/` | reference fetch + Ghidra-driven reconstruction helpers |
|
| `tools/` | reference fetch + Ghidra-driven reconstruction helpers |
|
||||||
| `docs/` | architecture, reverse-engineering notes, roadmap |
|
| `docs/` | architecture & master plan, reverse-engineering notes |
|
||||||
| `Dockerfile` | Linux build image (`dev` toolchain + `deploy` runtime) |
|
| `Dockerfile` | Linux build image (`dev` toolchain + `deploy` runtime) |
|
||||||
| `Dockerfile.win` | isolated Windows cross-build image (llvm-mingw + SDL3 MinGW) |
|
| `Dockerfile.win` | isolated Windows cross-build image (llvm-mingw + SDL3 MinGW) |
|
||||||
| `cmake/toolchains/` | `llvm-mingw-x86_64.cmake` cross toolchain |
|
| `cmake/toolchains/` | `llvm-mingw-x86_64.cmake` cross toolchain |
|
||||||
|
|||||||
+740
-101
@@ -1,131 +1,770 @@
|
|||||||
# Architecture
|
# Architecture & Master Plan
|
||||||
|
|
||||||
OpenRA3 is organised as a stack of C++26 modules. Each layer may import the ones
|
OpenRA3 is a from-scratch, portable re-implementation of **Command & Conquer:
|
||||||
below it, never the ones above. Every module uses `import std;` for the standard
|
Red Alert 3** (SAGE 2.0) in **pure C++26** — C++ modules, `import std;`, no
|
||||||
library; the engine is built with Clang + libc++ on Linux and cross-compiled
|
scripting language, no managed runtime, no other programming language anywhere
|
||||||
with llvm-mingw for Windows.
|
in the tree. It is built with Clang + libc++ on Linux and cross-compiled to
|
||||||
|
Windows with llvm-mingw.
|
||||||
|
|
||||||
|
This document is two things at once:
|
||||||
|
|
||||||
|
1. the **layer architecture** (how the modules sit on top of one another), and
|
||||||
|
2. the **master plan** — the complete Red Alert 3 feature set decomposed three
|
||||||
|
levels deep into **Module → Function → Feature**, each tagged with its
|
||||||
|
implementation status and target milestone.
|
||||||
|
|
||||||
|
The decomposition is the contract: every feature RA3 has is either implemented,
|
||||||
|
being implemented, or explicitly planned here. Nothing is silently dropped.
|
||||||
|
|
||||||
|
> **Scope.** Offline only. Single-player campaign, skirmish, Commander's
|
||||||
|
> Challenge and LAN lockstep — never an online service, matchmaking, EA account
|
||||||
|
> or GameSpy/Steam integration. The simulation is deterministic and
|
||||||
|
> self-contained. No game assets or binaries are shipped; the engine reads the
|
||||||
|
> user's own install at runtime.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Principles
|
||||||
|
|
||||||
|
Same five rules as the rest of the tree, restated because the plan is written
|
||||||
|
against them:
|
||||||
|
|
||||||
|
1. **Pure C++.** One language. No Lua, no JS, no C#, no Python at runtime.
|
||||||
|
Python is allowed *only* in offline build tooling (`tools/`, cmake helper
|
||||||
|
scripts), never linked into `openra3`.
|
||||||
|
2. **No raw owning pointers.** Ownership is `std::unique_ptr`; cross-references
|
||||||
|
are non-owning views (`thing *`, handles, indices).
|
||||||
|
3. **Portable simulation.** No platform API in the foundation or simulation
|
||||||
|
layers. All platform concerns live behind `display` / `audio` / `video`.
|
||||||
|
4. **Determinism.** Anything that can diverge between runs (RNG, iteration
|
||||||
|
order, float accumulation, hash order) is explicit, seeded and testable.
|
||||||
|
5. **RE-traceable.** Every structure or constant taken from the retail
|
||||||
|
`ra3_1.12.game` (image base `0x400000`) or from the GPLv3 SAGE 1.0 reference
|
||||||
|
cites its origin. No asserted fact without a source.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Layer architecture
|
||||||
|
|
||||||
|
Each layer may import the ones below it, never the ones above. The `ra3`
|
||||||
|
umbrella module re-exports the SDK; applications import `ra3` only.
|
||||||
|
|
||||||
```
|
```
|
||||||
┌───────────────────────────────────────┐
|
L6 tooling / apps openra3 (CLI) tools/ (offline, Python allowed)
|
||||||
applications │ openra3 (apps/openra3) │
|
| import ra3
|
||||||
└───────────────────┬───────────────────┘
|
---------------------------------------------------------------------------
|
||||||
│ import ra3
|
v
|
||||||
┌───────────────────▼───────────────────┐
|
L5 meta ra3.i18n ra3.mod ra3.net (deferred)
|
||||||
umbrella │ ra3 (re-exports everything) │
|
|
|
||||||
└───────────────────┬───────────────────┘
|
L4 match services ra3.match ra3.replay ra3.save
|
||||||
┌──────────────┬───────────────┼───────────────┬──────────────┐
|
|
|
||||||
▼ ▼ ▼ ▼ ▼
|
L3 presentation ra3.client ── ra3.render ── ra3.audio ── ra3.video
|
||||||
ra3.display ra3.render ra3.skirmish ra3.client ra3.game
|
| \ |
|
||||||
backend pick framebuffer match rules display+loops RA3 sides
|
| \ v
|
||||||
│ │ │ │ │
|
| ra3.display (backend pick)
|
||||||
┌──┴───┐ │ └───────┬───────┘ │
|
| / \
|
||||||
▼ ▼ ▼ ▼ │
|
v ra3.ui ra3.vulkan
|
||||||
ra3.ui ra3.vulkan ra3.terrain ra3.logic │
|
| (SDL3) (Vulkan)
|
||||||
SDL Vulkan heightmap/blends simulation │
|
---------------------------------------------------------------------------
|
||||||
┌──────────────────────┘
|
v
|
||||||
▼
|
L2 simulation ra3.logic ra3.modules ra3.combat ra3.movement
|
||||||
ra3.map / ra3.fs
|
ra3.economy ra3.ai ra3.script ra3.powers ra3.shroud
|
||||||
catalog / BIG4 + RefPack
|
|
|
||||||
|
L1 data & assets ra3.data ── ra3.assets ── ra3.map ── ra3.terrain
|
||||||
|
| |
|
||||||
|
v v
|
||||||
|
ra3.fs (BIG4 / RefPack / install)
|
||||||
|
|
|
||||||
|
L0 foundation ra3.core (types, math, containers, RNG, message bus)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Presentation layer
|
The current concrete modules (`ra3.core`, `ra3.logic`, `ra3.data`,
|
||||||
|
`ra3.skirmish`, `ra3.fs`, `ra3.map`, `ra3.terrain`, `ra3.render`, `ra3.ui.*`,
|
||||||
|
`ra3.vulkan.*`, `ra3.display`, `ra3.game`, `ra3.client`) are the **seeds** of the
|
||||||
|
target modules below. `ra3.skirmish` and `ra3.game` will be absorbed into
|
||||||
|
`ra3.ai` / `ra3.match`; new modules are added as their subsystems are recovered.
|
||||||
|
|
||||||
`ra3.client::display` is the single seam between the engine and the windowing
|
### Status legend
|
||||||
stack. A backend implements only the low-level primitives (`init`, `present`,
|
|
||||||
`poll_event`, `window_size`, `key_down`, `shutdown`) and, optionally,
|
|
||||||
`present_terrain`; the interactive loops (menu, image viewer, camera viewer,
|
|
||||||
GPU terrain) and the native-to-`ui_event` mapping live once in the base class,
|
|
||||||
so the SDL and Vulkan paths cannot drift. SDL3 remains the platform layer (it
|
|
||||||
owns the window, input and the low-cost blit backend); Vulkan is the accelerated
|
|
||||||
backend. `ra3.display` selects the first backend that starts, and the app never
|
|
||||||
references a backend by name.
|
|
||||||
|
|
||||||
The Vulkan backend currently hand-rolls its pipelines. As materials, skybox and
|
| Tag | Meaning |
|
||||||
HUD arrive, a thin RHI + render-graph belongs between `ra3.client` and the
|
| --- | --- |
|
||||||
Vulkan/SDL backends; `present_terrain` is the placeholder for that step.
|
| `[x]` | implemented and tested on `main` |
|
||||||
|
| `[~]` | partially implemented / works for the happy path |
|
||||||
|
| `[ ]` | planned, not started |
|
||||||
|
| `(vX.Y)` | target milestone (see the roll-up in §5) |
|
||||||
|
| `!!` | needs reverse engineering before it can be built |
|
||||||
|
|
||||||
|
| Function tag | Meaning |
|
||||||
|
| --- | --- |
|
||||||
|
| `D` | **done** — the function's features are largely present |
|
||||||
|
| `P` | **partial** — some features present |
|
||||||
|
|
||||||
## Module responsibilities
|
---
|
||||||
|
|
||||||
### `ra3.core`
|
## 3. Master plan — Module → Function → Feature
|
||||||
The vocabulary every other module shares, mirroring SAGE's `GameEngine/Common`:
|
|
||||||
`real`/`int32`/`uint32`, `coord3d`/`coord2d`/`rgb_color`, `ascii_string` +
|
|
||||||
`make_name_key`, the deterministic `random` stream, and the `message_stream`
|
|
||||||
command bus (node layout derived from retail `MessageStream::appendMessage`,
|
|
||||||
`0x0060c4a0`).
|
|
||||||
|
|
||||||
### `ra3.logic`
|
### M00 `ra3.core` — foundation vocabulary `[D]`
|
||||||
The deterministic simulation, mirroring SAGE's `GameLogic`: `thing` → `object`
|
|
||||||
with pluggable `update_module`s, `player`/`player_list`, the `partition_manager`
|
|
||||||
spatial grid, and the 30 Hz `game_logic` driver (`prepare_new_game` /
|
|
||||||
`start_new_game` / `update`).
|
|
||||||
|
|
||||||
### `ra3.client`
|
Mirrors SAGE `GameEngine/Common`. Everything else speaks this.
|
||||||
The presentation boundary: the abstract `display` (low-level primitives plus the
|
|
||||||
shared interactive loops and `ui_event` mapping), a `headless_display` for
|
|
||||||
CPU-only runs, and `game_client`, the facade that owns the simulation and drives
|
|
||||||
the frame loop.
|
|
||||||
|
|
||||||
### `ra3.display`
|
- **F1 Types & math** `[D]`
|
||||||
Backend selection: tries Vulkan, then SDL, then reports failure so the caller can
|
- `[x]` `real` (float), `int32`/`uint32`/`uint16`/`uint8`, `bool` aliases
|
||||||
fall back to an offscreen image. The only module that names a concrete backend.
|
- `[x]` `coord2d` / `coord3d` vectors, dot/cross/length/normalize
|
||||||
|
- `[x]` `rgb_color` / `argb_color`, packing and lerp
|
||||||
|
- `[x]` geometry: `segment`, `triangle`, `plane`, ray/segment intersection
|
||||||
|
- `[ ]` fixed-point helpers for replay-stable accumulation `(v0.4)`
|
||||||
|
- `[ ]` matrix / quaternion (needed by W3D models) `(v0.6)`
|
||||||
|
- `[ ]` `KindOf` flag bitset (SAGE object taxonomy) `(v0.4)`
|
||||||
|
- **F2 Containers** `[D]`
|
||||||
|
- `[x]` `ascii_string` + `make_name_key` (case-folded hash for data lookup)
|
||||||
|
- `[x]` intrusive doubly linked list (message stream node layout)
|
||||||
|
- `[x]` deterministic iteration-order map (insertion-ordered)
|
||||||
|
- `[ ]` object pool / arena for per-frame allocations `(v0.4)`
|
||||||
|
- `[ ]` interned string table `(v0.5)`
|
||||||
|
- **F3 Deterministic RNG** `[D]`
|
||||||
|
- `[x]` seedable `random` stream (`game_logic` random)
|
||||||
|
- `[ ]` independent per-player / per-subsystem streams `(v0.4)`
|
||||||
|
- `[ ]` shuffle / weighted-pick primitives `(v0.4)`
|
||||||
|
- **F4 Message stream** `[D]`
|
||||||
|
- `[x]` command bus with retail node layout (`appendMessage` `0x0060c4a0`)
|
||||||
|
- `[x]` ordered per-frame command drain
|
||||||
|
- `[ ]` command argument blocks (build/target/waypoint payloads) `(v0.4)`
|
||||||
|
- `[ ]` network/replay source tagging `(v0.4)`
|
||||||
|
- **F5 Diagnostics** `[~]`
|
||||||
|
- `[x]` logging sink + assert macro
|
||||||
|
- `[ ]` scoped profiling timers, per-subsystem counters `(v0.4)`
|
||||||
|
- `[ ]` structured crash/report capture `(v0.8)`
|
||||||
|
- **F6 Serialization primitives** `[~]`
|
||||||
|
- `[x]` little-endian byte reader/writer
|
||||||
|
- `[ ]` chunked binary reader/writer with versioning `(v0.5)`
|
||||||
|
- `[ ]` stable content hashing (replay/desync checks) `(v0.4)`
|
||||||
|
- **F7 Localization primitives** `[~]` (see M26)
|
||||||
|
- `[x]` UTF-16 unit access, CSF low-byte `^0xFF` decode
|
||||||
|
- `[ ]` placeholder substitution, plural/gender rules `(v0.5)`
|
||||||
|
|
||||||
### `ra3.terrain`
|
### M01 `ra3.fs` — containers & install `[D]`
|
||||||
The real map terrain: parses `CkMp`'s `HeightMapData` and `BlendTileData`
|
|
||||||
(tiles, `Blends`/`ThreeWayBlends` and their `BlendDescription`s), loads the
|
|
||||||
`Terrain.big` tile textures, and rasterises the map (software `render`/`render3d`
|
|
||||||
and the GPU `gpu_terrain` for `present_terrain`).
|
|
||||||
|
|
||||||
### `ra3.game`
|
- **F1 BIG archive** `[D]`
|
||||||
Red Alert 3 data that SAGE keeps in `PlayerTemplate`: the three sides
|
- `[x]` `BIG4` header parse (`fileSize` LE, `fileCount`/offsets BE) + name index
|
||||||
(`faction` flags `Empire=2`, `Allied=4`, `Soviet=8`, `Random=7`, recovered from
|
- `[x]` payload read on demand (index-only resident memory)
|
||||||
the retail skirmish setup) and skirmish defaults.
|
- `[ ]` `BIGF` (RefPack whole-archive) variant `!!` `(v0.5)`
|
||||||
|
- `[ ]` write support (pack/repack, used by tooling) `(v0.8)`
|
||||||
|
- **F2 RefPack codec** `[D]`
|
||||||
|
- `[x]` decode: 2/3/4-byte commands, long-literal, stop opcode
|
||||||
|
- `[x]` `refpack_output_size` without full decompress
|
||||||
|
- `[ ]` encode (for tooling round-trips) `(v0.8)`
|
||||||
|
- **F3 Install locator** `[D]`
|
||||||
|
- `[x]` `--game-dir` / `$RA3_GAME_DIR` / `C:\Red Alert 3` defaults
|
||||||
|
- `[ ]` registry / Steam / EA-app discovery `(v0.5)`
|
||||||
|
- `[ ]` Uprising as an optional content source `(v0.5)`
|
||||||
|
- **F4 Virtual file system** `[~]`
|
||||||
|
- `[x]` layered archive mounts (loose files → `*.big`)
|
||||||
|
- `[ ]` patch/language precedence rules (newest `Lang-*.big` wins) `(v0.5)`
|
||||||
|
- `[ ]` case-insensitive lookup + path normalisation `(v0.5)`
|
||||||
|
- **F5 Extraction targets** `[D]`
|
||||||
|
- `[x]` `openra3 extract` dumps maps/terrain to `assets/`
|
||||||
|
- `[ ]` full asset dump via `ra3tools` integration as a build target `(v0.5)`
|
||||||
|
|
||||||
### `ra3.fs`
|
### M02 `ra3.data` — data schema & balance `[P]`
|
||||||
Reading the user's installation. Implements the `BIG4` archive container and
|
|
||||||
EA's RefPack codec, plus `find_game_dir` (`--game-dir` / `$RA3_GAME_DIR` /
|
|
||||||
`C:\Red Alert 3`). Only the archive index is held in memory; payloads are read
|
|
||||||
on demand.
|
|
||||||
|
|
||||||
### `ra3.map`
|
- **F1 Data schema** `[ ]` `!!`
|
||||||
Map discovery and loading: scans `MapsMultiplayer.big` for main map entries,
|
- `[ ]` SAGE INI parser (`#include`, `#define`, inheritance) `(v0.5)`
|
||||||
unwraps the two compression layers (`BIG4` RefPack → `EAR\0` wrapper → RefPack →
|
- `[ ]` XML rule schema
|
||||||
`CkMp`), recovers `Player_N_Start` waypoint coordinates, and decodes the
|
- `[ ]` `.manifest` compiled-blob schema `!!` `(v0.5)`
|
||||||
localized display names from the install's `gamestrings.csf`. Degenerate
|
- **F2 Compiled asset blobs** `[ ]` `!!`
|
||||||
extractions are rejected so the caller can fall back.
|
- `[ ]` `global.bin` deserialisation `(v0.5)`
|
||||||
|
- `[ ]` `static.*.bin` deserialisation `(v0.5)`
|
||||||
|
- `[ ]` version/dependency validation `(v0.5)`
|
||||||
|
- **F3 Balance tables** `[~]`
|
||||||
|
- `[x]` damage types, `ArmorTemplate` percentages
|
||||||
|
- `[x]` weapon target masks, weapon definitions
|
||||||
|
- `[x]` unit/structure build costs, times, prerequisites
|
||||||
|
- `[x]` ore economy constants
|
||||||
|
- `[ ]` read these from the install instead of pinned constants `(v0.5)`
|
||||||
|
- **F4 Object definitions** `[ ]`
|
||||||
|
- `[ ]` `ThingTemplate`/`ObjectTemplate` inheritance graph `(v0.5)`
|
||||||
|
- `[ ]` module descriptor lists (per-object update/draw module sets)
|
||||||
|
- `[ ]` `WeaponTemplate`/`ArmorTemplate`/`LocomotorTemplate` stores
|
||||||
|
- **F5 Faction & player templates** `[~]`
|
||||||
|
- `[x]` Allied / Soviet / Empire side flags (`2/4/8`), match templates
|
||||||
|
- `[ ]` commander/sub-commander definitions `(v0.7)`
|
||||||
|
- `[ ]` build/upgrade unlock trees per faction `(v0.5)`
|
||||||
|
- **F6 Rules & settings** `[ ]`
|
||||||
|
- `[ ]` skirmish options (cash, crates, superweapons, speed, limits)
|
||||||
|
- `[ ]` bonus crate effect table
|
||||||
|
- `[ ]` AI personality tables
|
||||||
|
- `[ ]` map-specific rule overrides (`map.ini`)
|
||||||
|
- **F7 Validation** `[ ]`
|
||||||
|
- `[ ]` schema diagnostics with source location
|
||||||
|
- `[ ]` cross-reference integrity (missing templates/refs)
|
||||||
|
|
||||||
### `ra3.skirmish`
|
### M03 `ra3.assets` — runtime asset manager `[ ]`
|
||||||
The minimal match: two players, unit classes (harvester/infantry/tank/base),
|
|
||||||
passive + harvester income, a simple build AI, movement and combat on a fixed
|
|
||||||
30 Hz step, and a base-destruction win condition. Fully deterministic.
|
|
||||||
|
|
||||||
### `ra3.render`
|
- **F1 Textures** `[~]`
|
||||||
A dependency-free software renderer: an ARGB8888 `image` framebuffer with
|
- `[x]` TGA decode (`ra3.render`); 256×256 terrain cells
|
||||||
blit/line/circle/text primitives (an embedded 8x8 bitmap font), a TGA decoder for
|
- `[ ]` DDS / DXT compressed textures `(v0.5)`
|
||||||
the game's map art, a 24-bit BMP encoder for headless output, and `compose` which
|
- `[ ]` atlas + mip generation, gutter padding (GPU) `[~]`
|
||||||
overlays a world grid and markers (start positions, live units) onto the map art.
|
- `[ ]` async upload / streaming `(v0.6)`
|
||||||
|
- **F2 Models** `[ ]` `!!`
|
||||||
|
- `[ ]` W3D container parse (chunks, hierarchy, meshes) `(v0.6)`
|
||||||
|
- `[ ]` materials, shaders, texture references
|
||||||
|
- `[ ]` LOD sets, collision meshes
|
||||||
|
- **F3 Animation** `[ ]` `!!`
|
||||||
|
- `[ ]` W3D animation chunks, bone poses `(v0.6)`
|
||||||
|
- `[ ]` blend trees / transition animations
|
||||||
|
- **F4 Audio** `[ ]` `!!`
|
||||||
|
- `[ ]` audio container + codec decode `(v0.7)`
|
||||||
|
- `[ ]` cue/event tables (unit responses, weapon foley)
|
||||||
|
- **F5 Fonts & glyphs** `[ ]`
|
||||||
|
- `[ ]` bitmap/vector font load; CJK coverage `(v0.5)`
|
||||||
|
- **F6 Asset registry** `[ ]`
|
||||||
|
- `[ ]` cache with ref counting, eviction `(v0.6)`
|
||||||
|
- `[ ]` name-key lookup into the data schema
|
||||||
|
- **F7 UI art (`.apt`)** `[ ]` `!!`
|
||||||
|
- `[ ]` RA3 interface art decode (HUD/command bar) `(v0.7)`
|
||||||
|
|
||||||
### `ra3.ui`
|
### M04 `ra3.map` — map catalog & loader `[D]`
|
||||||
The SDL3 backend: `sdl_display` implements the `ra3.client::display` primitives
|
|
||||||
using an `SDL_Renderer` streaming texture. Cheap and dependency-light, it is the
|
|
||||||
fallback when Vulkan is unavailable. A null backend returns `false` so the build
|
|
||||||
still runs without SDL3.
|
|
||||||
|
|
||||||
### `ra3.vulkan`
|
- **F1 Catalog** `[D]`
|
||||||
The accelerated backend: `vulkan_display` implements the same primitives and
|
- `[x]` scan `MapsMultiplayer.big` for main map entries
|
||||||
adds `present_terrain`, a GPU heightfield raymarcher (mipmapped tile atlas with a
|
- `[ ]` campaign + challenge map catalog `(v0.7)`
|
||||||
replicated gutter and the retail SAGE blend ramp). A null backend reports failure
|
- **F2 Compiled map (`CkMp`)** `[D]`
|
||||||
when no Vulkan loader is present.
|
- `[x]` double unwrap (`BIG4` RefPack → `EAR\0` → RefPack → `CkMp`)
|
||||||
|
- `[x]` name table + chunk list (`{index,version,size,data}`)
|
||||||
|
- `[ ]` full typed chunk dispatch for all chunk kinds `(v0.5)`
|
||||||
|
- **F3 Start positions** `[~]`
|
||||||
|
- `[x]` `Player_N_Start` waypoint scan → `coord3d`
|
||||||
|
- `[ ]` `MPPositionList` layout for maps without waypoints `!!` `(v0.5)`
|
||||||
|
- **F4 Metadata** `[~]`
|
||||||
|
- `[x]` display names from `gamestrings.csf` (`MAP:<ID>`)
|
||||||
|
- `[ ]` player count, size, supported game modes `(v0.5)`
|
||||||
|
- **F5 Map rules** `[ ]`
|
||||||
|
- `[ ]` `map.ini` override application `(v0.5)`
|
||||||
|
- **F6 Preview art** `[~]`
|
||||||
|
- `[x]` `<map>_art.tga` overview decode (`--thumbnail`)
|
||||||
|
- **F7 Validation & fallback** `[D]`
|
||||||
|
- `[x]` reject degenerate extractions, fall back to built-in test map
|
||||||
|
- `[ ]` integrity/version checks with actionable errors `(v0.5)`
|
||||||
|
|
||||||
## Design rules
|
### M05 `ra3.terrain` — terrain `[P]`
|
||||||
|
|
||||||
|
- **F1 Heightmap** `[D]`
|
||||||
|
- `[x]` `HeightMapData` v6 (grid, border, `u16` elevations, scale)
|
||||||
|
- `[ ]` multi-resolution / LOD height sampling `(v0.6)`
|
||||||
|
- **F2 Blend tiles** `[D]`
|
||||||
|
- `[x]` `BlendTileData` v27: tile grid, blends/three-way/cliff tables
|
||||||
|
- `[x]` `BlendDescription` parse; `secondaryTile` decode
|
||||||
|
- `[x]` retail `Terrain.fx` blend ramp (`blend_factor`, axis flags)
|
||||||
|
- **F3 Terrain textures** `[D]`
|
||||||
|
- `[x]` `art\terrain\*.tga` from `Terrain.big` / `Core11.big`
|
||||||
|
- `[x]` cell atlas with replicated gutter (GPU bleeding fix)
|
||||||
|
- `[ ]` continuous 32 px / Morton layout (kill residual grid lines) `(v0.4)`
|
||||||
|
- **F4 Water** `[ ]` `!!`
|
||||||
|
- `[ ]` water height/type, sea level `(v0.6)`
|
||||||
|
- `[ ]` animated waves + shoreline blending `(v0.6)`
|
||||||
|
- `[ ]` shroud-aware water rendering `(v0.6)`
|
||||||
|
- **F5 Cliffs & roads** `[ ]` `!!`
|
||||||
|
- `[x]` `CliffTextures` table parsed
|
||||||
|
- `[ ]` cliff mesh + `CliffTextureMapping` UV remap `(v0.6)`
|
||||||
|
- `[ ]` roads and bridges (passability + render) `(v0.6)`
|
||||||
|
- **F6 Terrain lighting** `[ ]`
|
||||||
|
- `[ ]` per-vertex normals, cell lighting, global light `(v0.6)`
|
||||||
|
- **F7 Terrain queries** `[~]`
|
||||||
|
- `[x]` height lookup (render)
|
||||||
|
- `[ ]` passability grid (ground/naval/amphibious/air) `(v0.4)`
|
||||||
|
- `[ ]` buildability grid (flatness, slope, water) `(v0.4)`
|
||||||
|
|
||||||
|
### M06 `ra3.logic` — simulation core `[P]`
|
||||||
|
|
||||||
|
- **F1 Objects & things** `[~]`
|
||||||
|
- `[x]` `thing` → `object` with pluggable `update_module`s
|
||||||
|
- `[x]` global object registry with stable ids
|
||||||
|
- `[ ]` handle/reference system (survives deletion) `(v0.4)`
|
||||||
|
- `[ ]` object destruction lifecycle + death dispatch `(v0.4)`
|
||||||
|
- **F2 Players & teams** `[~]`
|
||||||
|
- `[x]` `player` / `player_list`
|
||||||
|
- `[x]` money (`std::vector<Money*>`) and power fields
|
||||||
|
- `[x]` team assignment and relations
|
||||||
|
- `[ ]` diplomacy matrix, ally vision sharing `(v0.5)`
|
||||||
|
- **F3 Partition manager** `[~]`
|
||||||
|
- `[x]` spatial grid, neighborhood queries
|
||||||
|
- `[ ]` cell-resolution + large-object multi-cell registration `(v0.4)`
|
||||||
|
- **F4 Game loop** `[~]`
|
||||||
|
- `[x]` 30 Hz deterministic step with frame counter
|
||||||
|
- `[x]` `prepare_new_game` / `start_new_game` two-phase start
|
||||||
|
- `[ ]` per-tick module scheduling with stable ordering `(v0.4)`
|
||||||
|
- **F5 Commands** `[~]`
|
||||||
|
- `[x]` `message_stream` bus
|
||||||
|
- `[ ]` typed commands (build, attack, move, ability, sell, repair) `(v0.4)`
|
||||||
|
- `[ ]` command validation + feedback (insufficient funds, etc.) `(v0.4)`
|
||||||
|
- **F6 Determinism** `[~]`
|
||||||
|
- `[x]` seeded logic random
|
||||||
|
- `[ ]` replay-hash of state per tick `(v0.4)`
|
||||||
|
- `[ ]` float determinism policy / fixed-point where required `(v0.4)`
|
||||||
|
- **F7 Victory / defeat** `[~]`
|
||||||
|
- `[x]` team-wipe / base-destruction win condition
|
||||||
|
- `[ ]` surrender, disconnection, timed, objective victories `(v0.5)`
|
||||||
|
- `[ ]` score / stats accumulation `(v0.8)`
|
||||||
|
|
||||||
|
### M07 `ra3.modules` — object update & draw modules `[P]`
|
||||||
|
|
||||||
|
- **F1 Module system** `[~]`
|
||||||
|
- `[x]` update modules attached to objects with a simple order
|
||||||
|
- `[ ]` module descriptor data-binding (from `ThingTemplate`) `(v0.5)`
|
||||||
|
- `[ ]` interface queries (get WeaponModule / ContainModule on demand) `(v0.4)`
|
||||||
|
- **F2 Locomotor** `[ ]`
|
||||||
|
- `[ ]` movement state machine (idle/moving/attacking) `(v0.4)`
|
||||||
|
- **F3 Weapon module** `[~]`
|
||||||
|
- `[x]` simple weapons on units, auto-target + fire
|
||||||
|
- `[ ]` multi-weapon slots, turret aiming/rotation `(v0.4)`
|
||||||
|
- `[ ]` reload/clip, deploy/undeploy states `(v0.6)`
|
||||||
|
- **F4 Contain** `[ ]`
|
||||||
|
- `[ ]` transport passenger slots, load/unload `(v0.4)`
|
||||||
|
- `[ ]` garrison of civilian structures `(v0.6)`
|
||||||
|
- `[ ]` paradrop / airdrop `(v0.6)`
|
||||||
|
- **F5 Production** `[~]`
|
||||||
|
- `[x]` pay-as-you-go build queue on a factory
|
||||||
|
- `[ ]` per-factory queues, rally points, queue reordering `(v0.4)`
|
||||||
|
- `[ ]` building placement → production handoff `(v0.4)`
|
||||||
|
- **F6 Power** `[~]`
|
||||||
|
- `[x]` power production/consumption fields
|
||||||
|
- `[ ]` brownout/blackout effects on radar + build speed `(v0.4)`
|
||||||
|
- **F7 Upgrades** `[ ]`
|
||||||
|
- `[ ]` upgrade research, unlock dependent modules/weapons `(v0.5)`
|
||||||
|
- **F8 Experience / veterancy** `[ ]`
|
||||||
|
- `[ ]` XP from kills, ranks (veteran/elite/heroic), bonuses `(v0.6)`
|
||||||
|
- `[ ]` chevron rendering `(v0.6)`
|
||||||
|
- **F9 Special abilities** `[~]`
|
||||||
|
- `[ ]` secondary ability slots with cooldown, target/area types `(v0.6)`
|
||||||
|
- `[ ]` toggle/instant/targeted ability kinds `(v0.6)`
|
||||||
|
- **F10 Stealth / disguise / detection** `[ ]`
|
||||||
|
- `[ ]` stealth states, detection radius, decloak on fire `(v0.6)`
|
||||||
|
- `[ ]` disguise (spy-like) and detection interaction `(v0.6)`
|
||||||
|
- **F11 Structure modules** `[~]`
|
||||||
|
- `[x]` base structures, destruction
|
||||||
|
- `[ ]` construction/assembly animation, sell, repair `(v0.4)`
|
||||||
|
- `[ ]` walls/gates if present, defensive structures `(v0.6)`
|
||||||
|
- **F12 Resource modules** `[~]`
|
||||||
|
- `[x]` harvester ↔ refinery ore cycle
|
||||||
|
- `[ ]` ore field spread/depletion, multiple miners, dock queue `(v0.4)`
|
||||||
|
- **F13 Shroud modules** `[ ]`
|
||||||
|
- `[ ]` per-object shroud reveal / clearance `(v0.4)`
|
||||||
|
- **F14 Draw modules** `[ ]`
|
||||||
|
- `[ ]` model draw, animation, particles, construction ghost, temp effects `(v0.6)`
|
||||||
|
|
||||||
|
### M08 `ra3.combat` — weapons, warheads, damage `[P]`
|
||||||
|
|
||||||
|
- **F1 Weapons** `[~]`
|
||||||
|
- `[x]` damage, range, rate of fire, target masks
|
||||||
|
- `[ ]` clip/burst, scatter, arc, continuous beam `(v0.4)`
|
||||||
|
- `[ ]` primary vs secondary weapon selection `(v0.4)`
|
||||||
|
- **F2 Warheads** `[~]`
|
||||||
|
- `[x]` damage type + armor multiplier resolution
|
||||||
|
- `[ ]` radius/falloff, affects mask, death type on kill `(v0.4)`
|
||||||
|
- **F3 Armor** `[~]`
|
||||||
|
- `[x]` `ArmorTemplate` percentage table
|
||||||
|
- `[ ]` armor upgrades and per-state armor `(v0.6)`
|
||||||
|
- **F4 Damage application** `[~]`
|
||||||
|
- `[x]` damage resolution against armor
|
||||||
|
- `[ ]` conditional modifiers (from above, in air, moving) `(v0.4)`
|
||||||
|
- `[ ]` friendly-fire policy, self-damage `(v0.4)`
|
||||||
|
- **F5 Projectiles** `[ ]`
|
||||||
|
- `[ ]` ballistic / laser / missile / beam / homing / arcing `(v0.4)`
|
||||||
|
- `[ ]` projectile draw + impact VFX hook `(v0.6)`
|
||||||
|
- **F6 Targeting** `[~]`
|
||||||
|
- `[x]` simple nearest/in-range acquisition
|
||||||
|
- `[ ]` priority scans (attack-move, guard, force-attack) `(v0.4)`
|
||||||
|
- `[ ]` re-targeting, leash, target ground `(v0.4)`
|
||||||
|
- **F7 Special effects** `[ ]`
|
||||||
|
- `[ ]` EMP/stun, flame/radiation DoT, mind-control, shrink/grow `(v0.7)`
|
||||||
|
- **F8 Death & corpses** `[ ]`
|
||||||
|
- `[ ]` death types, wrecks, gibs, salvage, rebuild `(v0.6)`
|
||||||
|
|
||||||
|
### M09 `ra3.movement` — locomotion & pathfinding `[ ]`
|
||||||
|
|
||||||
|
- **F1 Locomotors** `[ ]`
|
||||||
|
- `[ ]` ground / air / naval / amphibious / hover / teleport `!!` `(v0.4)`
|
||||||
|
- `[ ]` turn rates, acceleration, braking, banking `(v0.6)`
|
||||||
|
- **F2 Pathfinding** `[ ]`
|
||||||
|
- `[ ]` grid A* over the passability grid `(v0.4)`
|
||||||
|
- `[ ]` hierarchical / jump-point refinement `(v0.6)`
|
||||||
|
- `[ ]` dynamic obstacle integration (buildings, units) `(v0.6)`
|
||||||
|
- **F3 Steering & flocking** `[ ]`
|
||||||
|
- `[ ]` separation, avoidance, group cohesion `(v0.6)`
|
||||||
|
- `[ ]` formation slots (line/wedge/box) `(v0.6)`
|
||||||
|
- **F4 Orders & waypoints** `[~]`
|
||||||
|
- `[x]` straight-line move toward a target (skirmish)
|
||||||
|
- `[ ]` waypoint queues, queued orders with shift `(v0.4)`
|
||||||
|
- `[ ]` guard / patrol / attack-move / stop / scatter `(v0.4)`
|
||||||
|
- **F5 Collision & crush** `[ ]`
|
||||||
|
- `[ ]` unit-unit collision, pushing, crush damage `(v0.6)`
|
||||||
|
- **F6 Naval & amphibious** `[ ]`
|
||||||
|
- `[ ]` water-only movement, amphibious land↔water transition `!!` `(v0.6)`
|
||||||
|
- **F7 Transport & airdrop** `[ ]`
|
||||||
|
- `[ ]` boarding/unloading, airdrop descent `(v0.6)`
|
||||||
|
|
||||||
|
### M10 `ra3.economy` — resources, power, construction `[P]`
|
||||||
|
|
||||||
|
- **F1 Ore / resource** `[~]`
|
||||||
|
- `[x]` ore fields and harvester↔refinery cycle
|
||||||
|
- `[ ]` ore spread/regrowth, depletion, ore density `(v0.4)`
|
||||||
|
- **F2 Power** `[~]`
|
||||||
|
- `[x]` power balance fields
|
||||||
|
- `[ ]` brownout/blackout consequences `(v0.4)`
|
||||||
|
- **F3 Construction** `[~]`
|
||||||
|
- `[x]` pay-as-you-go queue, tech prerequisites, build times
|
||||||
|
- `[ ]` build-radius rules (structures must be in base vicinity) `(v0.4)`
|
||||||
|
- `[ ]` low-power build-speed penalty `(v0.4)`
|
||||||
|
- **F4 Placement** `[ ]`
|
||||||
|
- `[ ]` placement grid, footprint validation, green/red ghost `(v0.4)`
|
||||||
|
- `[ ]` adjacency bonuses / prerequisite-adjacent structures `(v0.6)`
|
||||||
|
- **F5 Repair & sell** `[ ]`
|
||||||
|
- `[ ]` structure repair over time, cost, sell refund `(v0.4)`
|
||||||
|
- `[ ]` unit repair pads if present `(v0.6)`
|
||||||
|
- **F6 Rally points** `[ ]`
|
||||||
|
- `[ ]` factory rally, rally preview, waypoint rally `(v0.6)`
|
||||||
|
- **F7 Income modifiers** `[ ]`
|
||||||
|
- `[ ]` bonus crates (cash/units/repair/heal, `random_bonus_crates`) `(v0.5)`
|
||||||
|
|
||||||
|
### M11 `ra3.ai` — computer opponents `[P]`
|
||||||
|
|
||||||
|
- **F1 Skirmish AI** `[~]`
|
||||||
|
- `[x]` simple build AI (base, ore, a couple of unit types)
|
||||||
|
- `[ ]` data-driven build orders per faction `(v0.5)`
|
||||||
|
- `[ ]` economy management (expand, defend harvesters) `(v0.5)`
|
||||||
|
- **F2 Attack management** `[~]`
|
||||||
|
- `[x]` send units at the enemy base
|
||||||
|
- `[ ]` attack force assembly, waves, retreat/regroup `(v0.5)`
|
||||||
|
- `[ ]` targeting priorities (harvesters, key structures) `(v0.6)`
|
||||||
|
- **F3 Team AI / diplomacy** `[ ]`
|
||||||
|
- `[ ]` allied coordination, shared attacks, base defense `(v0.6)`
|
||||||
|
- **F4 Difficulty & personalities** `[ ]`
|
||||||
|
- `[ ]` easy/normal/hard modifiers, AI cheating options `(v0.5)`
|
||||||
|
- `[ ]` commander personalities (aggressive/turtle/air/naval) `(v0.7)`
|
||||||
|
- **F5 Scouting** `[ ]`
|
||||||
|
- `[ ]` exploration, map awareness, threat response `(v0.6)`
|
||||||
|
- **F6 Superweapon usage** `[ ]`
|
||||||
|
- `[ ]` AI powers/power targeting `(v0.7)`
|
||||||
|
- **F7 Script hooks** `[ ]`
|
||||||
|
- `[ ]` AI cooperation with script triggers (campaign) `(v0.7)`
|
||||||
|
|
||||||
|
### M12 `ra3.script` — triggers & missions `[ ]`
|
||||||
|
|
||||||
|
- **F1 Trigger system** `[ ]` `!!`
|
||||||
|
- `[ ]` conditions (elapsed, object in region, destroyed, flag) `(v0.7)`
|
||||||
|
- `[ ]` actions (spawn, order, reveal, camera, dialog, win/lose) `(v0.7)`
|
||||||
|
- **F2 Script engine** `[ ]` `!!`
|
||||||
|
- `[ ]` SAGE script language / mission script parse `(v0.7)`
|
||||||
|
- `[ ]` timers, counters, flags, per-player state `(v0.7)`
|
||||||
|
- **F3 Campaign missions** `[ ]`
|
||||||
|
- `[ ]` mission objectives, sequential phases, briefing `(v0.8)`
|
||||||
|
- `[ ]` three faction campaigns (Allied/Soviet/Empire) `(v0.8)`
|
||||||
|
- **F4 Reinforcements & spawns** `[ ]`
|
||||||
|
- `[ ]` scripted spawns, cinematic units, capture `(v0.8)`
|
||||||
|
- **F5 Tutorials** `[ ]`
|
||||||
|
- `[ ]` tutorial message gates, camera lock/unlock actions `(v0.8)`
|
||||||
|
- **F6 Co-op** `[ ]`
|
||||||
|
- `[ ]` co-op commander missions `(v0.9)`
|
||||||
|
|
||||||
|
### M13 `ra3.powers` — superweapons & support powers `[ ]`
|
||||||
|
|
||||||
|
- **F1 Superweapons** `[ ]` `!!`
|
||||||
|
- `[ ]` Allied Chronosphere `(v0.7)`
|
||||||
|
- `[ ]` Soviet Vacuum Imploder `(v0.7)`
|
||||||
|
- `[ ]` Empire Psionic Decimator `(v0.7)`
|
||||||
|
- `[ ]` charge timer, targeting, ready state, HUD `(v0.7)`
|
||||||
|
- **F2 Support powers** `[ ]`
|
||||||
|
- `[ ]` per-faction powers (spy satellite, air support, etc.) `(v0.7)`
|
||||||
|
- `[ ]` cooldowns, targeting types, cost `(v0.7)`
|
||||||
|
- **F3 Commander's Challenge powers** `[ ]`
|
||||||
|
- `[ ]` challenge-mode power loadouts `(v0.8)`
|
||||||
|
|
||||||
|
### M14 `ra3.shroud` — fog of war & radar `[ ]`
|
||||||
|
|
||||||
|
- **F1 Shroud** `[ ]`
|
||||||
|
- `[ ]` per-player unexplored grid `(v0.4)`
|
||||||
|
- **F2 Fog of war** `[ ]`
|
||||||
|
- `[ ]` explored-but-unseen dimming `(v0.4)`
|
||||||
|
- **F3 Reveal sources** `[ ]`
|
||||||
|
- `[ ]` units/structures reveal radius, abilities, spy satellite `(v0.6)`
|
||||||
|
- **F4 Radar / minimap** `[ ]`
|
||||||
|
- `[ ]` radar texture, unit blips, radar-offline on low power `(v0.6)`
|
||||||
|
- **F5 Shroud ↔ logic** `[ ]`
|
||||||
|
- `[ ]` targetability gating, option for AI to ignore shroud `(v0.4)`
|
||||||
|
|
||||||
|
### M15 `ra3.client` — game client & shell `[P]`
|
||||||
|
|
||||||
|
- **F1 Game client** `[~]`
|
||||||
|
- `[x]` `game_client` facade owning the sim, driving the frame loop
|
||||||
|
- `[ ]` sim/present decoupling, interpolation, catch-up `(v0.6)`
|
||||||
|
- **F2 Tactical view / camera** `[~]`
|
||||||
|
- `[x]` controls: wheel zoom, edge scroll, clamped pan, open on player start
|
||||||
|
- `[x]` camera tuning table (`cameraMinHeight` …) + lock actions
|
||||||
|
- `[ ]` retail perspective camera, pitch/yaw, FOV (needs 3D terrain) `(v0.6)`
|
||||||
|
- **F3 Selection** `[ ]`
|
||||||
|
- `[ ]` click select, drag-box, double-click type select `(v0.6)`
|
||||||
|
- `[ ]` control groups (Ctrl+N), type filters, select-all-of-type `(v0.6)`
|
||||||
|
- **F4 Orders** `[ ]`
|
||||||
|
- `[ ]` contextual right-click orders, force-attack, force-move `(v0.6)`
|
||||||
|
- `[ ]` order queue with shift, formation move `(v0.6)`
|
||||||
|
- **F5 Command bar** `[ ]` `!!`
|
||||||
|
- `[ ]` build/production palettes, ability buttons, portraits `(v0.7)`
|
||||||
|
- `[ ]` tooltips, cost/time, cooldown sweep, disabled states `(v0.7)`
|
||||||
|
- **F6 HUD** `[ ]`
|
||||||
|
- `[x]` minimal match-state overlay (units, start markers)
|
||||||
|
- `[ ]` resource/power readouts, objectives, notifications `(v0.7)`
|
||||||
|
- `[ ]` EVA voice announcements hook `(v0.7)`
|
||||||
|
- **F7 Shell menus** `[~]`
|
||||||
|
- `[x]` map list by localized name + full render/skirmish options; console fallback
|
||||||
|
- `[ ]` main menu, skirmish setup, faction/team/color pickers `(v0.7)`
|
||||||
|
- `[ ]` options (video/audio/keybinds), pause, load/save, credits `(v0.8)`
|
||||||
|
- **F8 Feedback & cursors** `[ ]`
|
||||||
|
- `[ ]` action cursor, placement ghost, move/attack markers `(v0.6)`
|
||||||
|
|
||||||
|
### M16 `ra3.render` — renderer & RHI `[P]`
|
||||||
|
|
||||||
|
- **F1 RHI** `[ ]`
|
||||||
|
- `[ ]` device/queue/swapchain abstraction over Vulkan `(v0.6)`
|
||||||
|
- `[ ]` buffers, textures, samplers, descriptor sets, pipelines `(v0.6)`
|
||||||
|
- `[ ]` `present_terrain` is the seam where this lands today `[~]`
|
||||||
|
- **F2 Render graph** `[ ]`
|
||||||
|
- `[ ]` pass scheduling, barriers, transient/aliased resources `(v0.6)`
|
||||||
|
- **F3 Terrain render** `[~]`
|
||||||
|
- `[x]` top-down software + GPU heightfield with blend ramp + gutter atlas
|
||||||
|
- `[ ]` perspective terrain mesh, LOD, cliff, water `(v0.6)`
|
||||||
|
- **F4 Model render** `[ ]` `!!`
|
||||||
|
- `[ ]` W3D draw, skinning, materials, team colors `(v0.6)`
|
||||||
|
- `[ ]` shadows, decals, ground marks `(v0.6)`
|
||||||
|
- **F5 VFX** `[ ]`
|
||||||
|
- `[ ]` particle systems, beams, muzzle flashes, explosions `(v0.6)`
|
||||||
|
- `[ ]` shader effect graph (retail `.fxo` parity where feasible) `!!` `(v0.7)`
|
||||||
|
- **F6 Sky & atmosphere** `[ ]`
|
||||||
|
- `[ ]` skybox, fog, weather, time-of-day `(v0.7)`
|
||||||
|
- **F7 HUD render** `[ ]`
|
||||||
|
- `[ ]` 2D art layer, fonts, minimap/radar texture `(v0.7)`
|
||||||
|
- **F8 Software renderer** `[D]`
|
||||||
|
- `[x]` ARGB framebuffer, blit/line/circle/text, TGA decode, BMP encode
|
||||||
|
- `[x]` map compositing, grid, markers; headless output
|
||||||
|
- **F9 Post-processing** `[ ]`
|
||||||
|
- `[ ]` bloom, color grading, AA, resolution scaling `(v0.7)`
|
||||||
|
|
||||||
|
### M17 `ra3.ui` — platform layer & backends `[D]`
|
||||||
|
|
||||||
|
- **F1 Display abstraction** `[D]`
|
||||||
|
- `[x]` shared primitives + interactive loops + `ui_event` mapping in the base
|
||||||
|
- `[x]` backends implement primitives only (SDL/Vulkan cannot drift)
|
||||||
|
- **F2 SDL3 backend** `[D]`
|
||||||
|
- `[x]` window, streaming-texture blit, input polling
|
||||||
|
- `[ ]` gamepad support `(v0.8)`
|
||||||
|
- **F3 Backend selection (`ra3.display`)** `[D]`
|
||||||
|
- `[x]` try Vulkan → SDL → report failure for offscreen fallback
|
||||||
|
- **F4 Input mapping** `[~]`
|
||||||
|
- `[x]` keyboard/mouse state, modifier masks
|
||||||
|
- `[ ]` rebindable keybinds, mouse capture, scroll wheel events `(v0.6)`
|
||||||
|
- **F5 Window modes** `[ ]`
|
||||||
|
- `[ ]` windowed/fullscreen/borderless, resize, multi-monitor `(v0.6)`
|
||||||
|
- **F6 Null/headless backend** `[D]`
|
||||||
|
- `[x]` returns false so the tree builds and runs without SDL3/Vulkan
|
||||||
|
|
||||||
|
### M18 `ra3.vulkan` — Vulkan backend `[P]`
|
||||||
|
|
||||||
|
- **F1 Device & swapchain** `[~]`
|
||||||
|
- `[x]` embedded SPIR-V, SDL3 surface, present path
|
||||||
|
- `[ ]` formal RHI integration (see M16 F1) `(v0.6)`
|
||||||
|
- **F2 Terrain presentation** `[D]`
|
||||||
|
- `[x]` GPU heightfield raymarch, mipmapped atlas, gutter, retail blend ramp
|
||||||
|
- **F3 Materials & pipelines** `[ ]`
|
||||||
|
- `[ ]` model/particle/HUD pipelines `(v0.6)`
|
||||||
|
- **F4 Null fallback** `[D]`
|
||||||
|
- `[x]` report failure when no Vulkan loader is present
|
||||||
|
|
||||||
|
### M19 `ra3.audio` — audio `[ ]`
|
||||||
|
|
||||||
|
- **F1 SFX** `[ ]`
|
||||||
|
- `[ ]` 3D positional sound from cues/events `(v0.7)`
|
||||||
|
- **F2 Music** `[ ]`
|
||||||
|
- `[ ]` streaming music, playlists, combat stingers `(v0.7)`
|
||||||
|
- **F3 Voice & EVA** `[ ]`
|
||||||
|
- `[ ]` unit response lines, announcer (EVA) events `(v0.7)`
|
||||||
|
- **F4 Mixer** `[ ]`
|
||||||
|
- `[ ]` buses (master/sfx/music/voice), volume, ducking, reverb `(v0.7)`
|
||||||
|
- **F5 Codecs** `[ ]` `!!`
|
||||||
|
- `[ ]` decode RA3 audio formats `(v0.7)`
|
||||||
|
|
||||||
|
### M20 `ra3.video` — movies & cutscenes `[ ]`
|
||||||
|
|
||||||
|
- **F1 Movie playback** `[ ]` `!!`
|
||||||
|
- `[ ]` intro/briefing/ending video decode + playback `(v0.8)`
|
||||||
|
- `[ ]` skip, subtitles, aspect handling `(v0.8)`
|
||||||
|
- **F2 In-engine cutscenes** `[ ]`
|
||||||
|
- `[ ]` scripted camera + unit animation sequences `(v0.8)`
|
||||||
|
|
||||||
|
### M21 `ra3.match` — game setup & match rules `[P]`
|
||||||
|
|
||||||
|
- **F1 Game setup** `[~]`
|
||||||
|
- `[x]` map + two players + seed defaults
|
||||||
|
- `[ ]` faction/color/team/start-slot selection, AI personalities `(v0.7)`
|
||||||
|
- **F2 Rules & options** `[ ]`
|
||||||
|
- `[ ]` starting cash, crates on/off, superweapons on/off, speed, limits `(v0.7)`
|
||||||
|
- **F3 Match flow** `[~]`
|
||||||
|
- `[x]` `prepare_new_game` / `start_new_game` split mirroring retail
|
||||||
|
- `[ ]` loading progress, in-game start countdown `(v0.7)`
|
||||||
|
- **F4 Factions** `[~]`
|
||||||
|
- `[x]` Allied / Soviet / Empire player templates
|
||||||
|
- `[ ]` full faction tech trees and rosters `(v0.5)`
|
||||||
|
- **F5 Victory & scoring** `[~]`
|
||||||
|
- `[x]` team-wipe victory
|
||||||
|
- `[ ]` full victory conditions, post-match score screen `(v0.8)`
|
||||||
|
|
||||||
|
### M22 `ra3.replay` — recording & playback `[ ]`
|
||||||
|
|
||||||
|
- **F1 Recorder** `[ ]`
|
||||||
|
- `[ ]` capture command stream + seed + map id per match `(v0.4)`
|
||||||
|
- **F2 Replay format** `[ ]`
|
||||||
|
- `[ ]` self-describing header, command log, checksums `(v0.4)`
|
||||||
|
- `[ ]` compatibility with retail `.RA3Replay` playback `!!` `(v0.9)`
|
||||||
|
- **F3 Playback** `[ ]`
|
||||||
|
- `[ ]` deterministic re-simulation, speed control, seek `(v0.4)`
|
||||||
|
- **F4 Golden replays** `[ ]`
|
||||||
|
- `[ ]` curated replay corpus as a regression test `(v0.4)`
|
||||||
|
- **F5 Observer / spectator** `[ ]`
|
||||||
|
- `[ ]` watch live or recorded matches, fog option `(v0.9)`
|
||||||
|
|
||||||
|
### M23 `ra3.save` — save/load & profiles `[ ]`
|
||||||
|
|
||||||
|
- **F1 Save / load** `[ ]`
|
||||||
|
- `[ ]` full simulation state serialization (objects, modules, queues) `(v0.8)`
|
||||||
|
- `[ ]` versioned saves with migration `(v0.8)`
|
||||||
|
- **F2 Profiles** `[ ]`
|
||||||
|
- `[ ]` player profile, stats, progress/unlocks `(v0.8)`
|
||||||
|
- **F3 Options persistence** `[ ]`
|
||||||
|
- `[ ]` settings, keybinds, last-used skirmish config `(v0.7)`
|
||||||
|
- **F4 Checkpoints** `[ ]`
|
||||||
|
- `[ ]` campaign checkpoint save/restore `(v0.9)`
|
||||||
|
|
||||||
|
### M24 `ra3.mod` — data packages `[ ]`
|
||||||
|
|
||||||
|
- **F1 Data packages** `[ ]`
|
||||||
|
- `[ ]` load order, override precedence, loose-file mounting `(v0.8)`
|
||||||
|
- **F2 Content discovery** `[ ]`
|
||||||
|
- `[ ]` scan user mod dirs and additional `.big` archives `(v0.8)`
|
||||||
|
- **F3 Mod validation** `[ ]`
|
||||||
|
- `[ ]` schema + reference checks, actionable errors `(v0.8)`
|
||||||
|
|
||||||
|
### M25 `ra3.net` — LAN lockstep `[ ]` *(deferred, offline-only)*
|
||||||
|
|
||||||
|
- **F1 Lockstep** `[ ]`
|
||||||
|
- `[ ]` deterministic lockstep over LAN, command-exchange only `(v1.0)`
|
||||||
|
- **F2 Lobby & sync** `[ ]`
|
||||||
|
- `[ ]` lobby, slot/team assignment, start sync `(v1.0)`
|
||||||
|
- **F3 Desync detection** `[ ]`
|
||||||
|
- `[ ]` state-hash comparison, desync report `(v1.0)`
|
||||||
|
|
||||||
|
> No online service, matchmaking, EA account or third-party network
|
||||||
|
> integration — ever. LAN only.
|
||||||
|
|
||||||
|
### M26 `ra3.i18n` — localization `[P]`
|
||||||
|
|
||||||
|
- **F1 CSF strings** `[~]`
|
||||||
|
- `[x]` parse `gamestrings.csf` (UTF-16 units, low byte `^0xFF`)
|
||||||
|
- `[x]` map display-name lookup (`MAP:<ID>`)
|
||||||
|
- `[ ]` full string-table load for all UI text `(v0.5)`
|
||||||
|
- **F2 Language selection** `[~]`
|
||||||
|
- `[x]` newest `Lang-English*.big` wins
|
||||||
|
- `[ ]` all supported languages, fallback chain `(v0.5)`
|
||||||
|
- **F3 Fonts & shaping** `[ ]`
|
||||||
|
- `[ ]` glyph coverage, CJK/RTL shaping where applicable `(v0.6)`
|
||||||
|
- **F4 Substitution** `[ ]`
|
||||||
|
- `[ ]` placeholders, numbers, plurals `(v0.5)`
|
||||||
|
|
||||||
|
### M27 `apps` — applications `[D]`
|
||||||
|
|
||||||
|
- **F1 CLI** `[D]`
|
||||||
|
- `[x]` `menu` / `menu-preview` / `maps` / `skirmish` / `render` / `extract`
|
||||||
|
- `[ ]` `replay`, `benchmark`, `validate-data` subcommands `(v0.5)`
|
||||||
|
- **F2 Extraction pipeline** `[~]`
|
||||||
|
- `[x]` `extract` → `assets/` (maps, terrain)
|
||||||
|
- `[ ]` full asset dump (models/textures/audio/movies) as a build target `(v0.5)`
|
||||||
|
- **F3 Diagnostics** `[ ]`
|
||||||
|
- `[ ]` headless render/benchmark modes for CI `(v0.4)`
|
||||||
|
|
||||||
|
### M28 `tools` — offline tooling `[~]`
|
||||||
|
|
||||||
|
*(Python is permitted here; it is never linked into `openra3`.)*
|
||||||
|
|
||||||
|
- **F1 Reference fetch** `[D]`
|
||||||
|
- `[x]` sparse-clone SAGE 1.0 reference into git-ignored `reference/`
|
||||||
|
- **F2 Ghidra workflow** `[D]`
|
||||||
|
- `[x]` MCP-driven recovery loop + recovered symbol map (see RE doc)
|
||||||
|
- `[ ]` automated structure/table extractors `(v0.5)`
|
||||||
|
- **F3 Format inspectors** `[ ]`
|
||||||
|
- `[ ]` BIG/RefPack/CkMp/W3D/APT dumpers `(v0.5)`
|
||||||
|
- **F4 CI & packaging** `[D]`
|
||||||
|
- `[x]` GitLab CI builds both targets → test → package
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Cross-cutting invariants
|
||||||
|
|
||||||
|
These hold across **every** module above and are enforced in review:
|
||||||
|
|
||||||
|
1. **Language** — runtime code is C++ only. Build tooling may use Python.
|
||||||
|
2. **Ownership** — no raw owning pointers; `unique_ptr` for ownership, handles or
|
||||||
|
`thing *` views for references.
|
||||||
|
3. **Layering** — a module imports only lower layers. `ra3.core` imports no
|
||||||
|
engine module and no platform API.
|
||||||
|
4. **Determinism** — RNG, iteration, hashing and float use are explicit and
|
||||||
|
seedable; the logic step must be bit-reproducible for a given input stream.
|
||||||
|
5. **RE-traceable** — retail structure/constant changes cite an address in
|
||||||
|
[`REVERSE_ENGINEERING.md`](REVERSE_ENGINEERING.md).
|
||||||
|
6. **Offline** — no online service; LAN lockstep (M25) is the only networking,
|
||||||
|
and only command exchange.
|
||||||
|
7. **No bundled assets** — game data is read from the user's install; nothing
|
||||||
|
from it is committed. The tree builds and runs in CI on a built-in test map.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Milestone mapping
|
||||||
|
|
||||||
|
The plan rolls up to these releases:
|
||||||
|
|
||||||
|
| Milestone | Modules advanced | Delivers |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `v0.3.x` (done) | M00, M01, M04, M05(F1–F3), M06, M07(partial), M08(partial), M10(partial), M16(F3,F8), M17, M18 | minimal deterministic skirmish, real terrain, Vulkan present, menu |
|
||||||
|
| `v0.4.0` | M05(F4–F7), M06, M07, M08, M09(F1,F2,F4), M14, M22(F1–F4) | real update modules: locomotor, projectiles/warheads, placement, shroud, pathfinding, replay |
|
||||||
|
| `v0.5.0` | M02, M03, M04(F3,F4), M08, M10(F3,F4), M11(F1,F2), M26 | data-driven content: deserialise `.bin`/`.manifest`, real rosters, maps, strings |
|
||||||
|
| `v0.6.0` | M03(F1–F3), M07(F4,F6,F8,F14), M09(F2–F7), M16(F1,F2,F4,F5), M18(F3), M15(F1–F4,F8) | full renderer: perspective terrain, W3D models, in-game client + input |
|
||||||
|
| `v0.7.0` | M13, M15(F5–F7), M19, M11(F4–F6), M20, M21 | HUD/command bar, audio, superweapons, Commander's Challenge |
|
||||||
|
| `v0.8.0` | M12, M20(F1), M23, M24, M21(F5) | campaigns, cutscenes, save/load, mods |
|
||||||
|
| `v0.9.0` | M22(F2,F5), M12(F6), M25 | retail replay playback, co-op, LAN lockstep |
|
||||||
|
| `v1.0.0` | all | feature-complete offline RA3 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Design rules
|
||||||
|
|
||||||
|
The five rules the codebase is held to (restated from §1, with the concrete
|
||||||
|
consequences that trip people up):
|
||||||
|
|
||||||
1. **No raw owning pointers.** Ownership is `std::unique_ptr`; the partition
|
1. **No raw owning pointers.** Ownership is `std::unique_ptr`; the partition
|
||||||
manager holds non-owning `thing *` views only.
|
manager and object registry hold non-owning `thing *` views only.
|
||||||
2. **Portable simulation.** No platform APIs in `ra3.core` / `ra3.logic`. All
|
2. **Portable simulation.** No platform APIs in `ra3.core` / simulation
|
||||||
platform concerns live behind `display`.
|
modules. All platform concerns live behind `display`.
|
||||||
3. **Determinism.** Anything that can diverge between runs (random, iteration
|
3. **Determinism.** Anything that can diverge between runs (random, iteration
|
||||||
order) is explicit and seedable.
|
order) is explicit and seedable.
|
||||||
4. **RE-traceable.** Where a structure or constant comes from the retail
|
4. **RE-traceable.** Where a structure or constant comes from the retail
|
||||||
binary, the address is cited in the comment.
|
binary, the address is cited in the comment.
|
||||||
5. **No bundled assets, no online.** Game data is read from the user's install
|
5. **No bundled assets, no online.** Game data is read from the user's install
|
||||||
and never committed; there is no networking or online service.
|
and never committed; there is no networking or online service.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Where to start
|
||||||
|
|
||||||
|
- New to the codebase: read this plan top-to-bottom (§3 is the feature set,
|
||||||
|
§5 the near-term order of work).
|
||||||
|
- Picking up a feature: find its **Function** above, take the lowest-numbered
|
||||||
|
unmet `[ ]` **Feature**, and cite its supporting retail address.
|
||||||
|
- Reverse engineering a subsystem: follow the loop in
|
||||||
|
[`REVERSE_ENGINEERING.md`](REVERSE_ENGINEERING.md); the `!!` tags above mark
|
||||||
|
the functions that still need a recovery pass before they can be built.
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
# Roadmap
|
|
||||||
|
|
||||||
OpenRA3 is a very large undertaking. This roadmap is deliberately honest about
|
|
||||||
scope: reconstructing a 2008 RTS engine from a decompiler plus a related open
|
|
||||||
engine is a multi-year, multi-person effort. The milestones below are ordered so
|
|
||||||
that each one produces something that builds and runs.
|
|
||||||
|
|
||||||
## Done
|
|
||||||
|
|
||||||
- [x] **v0.0.1 — skeleton + minimal skirmish.** C++26 modules, GCC 16,
|
|
||||||
CMake/Ninja, Docker `dev`/`deploy`, GitLab CI. Reads `BIG4`/RefPack data
|
|
||||||
from a local install, recovers map start waypoints, and runs a
|
|
||||||
deterministic headless two-player skirmish to a decision.
|
|
||||||
- [x] **v0.1.0 — map renderer + window.** Software ARGB framebuffer, TGA
|
|
||||||
decoder for the map art, BMP output, map/grid/unit compositing, and an
|
|
||||||
SDL3 window viewer (pan/zoom).
|
|
||||||
- [x] **v0.2.0 — dual toolchain.** Switched to Clang + libc++ with
|
|
||||||
`import std;` in every module; added an isolated Windows cross-build
|
|
||||||
(llvm-mingw + SDL3 MinGW) producing `openra3.exe` + `SDL3.dll`, alongside
|
|
||||||
the Linux build. Both images are separate to keep the toolchains apart.
|
|
||||||
- [x] **v0.3.2 — real terrain.** `ra3.terrain` parses the map's `HeightMapData`
|
|
||||||
and `BlendTileData` and rasterises the actual terrain from the install's
|
|
||||||
`Terrain.big` tile textures (top-down, elevation-shaded), replacing the
|
|
||||||
`<map>_art.tga` overview as what `render` draws.
|
|
||||||
- [x] **v0.3.0 — real balance + skirmish + Vulkan.** `ra3.data` pins the retail
|
|
||||||
numbers (damage types, `ArmorTemplate` percentages, weapons, units,
|
|
||||||
structures, ore economy) audited from EA's open RA3 XML; `ra3.skirmish` is
|
|
||||||
rebuilt on them (armour resolution, weapon target masks, pay-as-you-go
|
|
||||||
build queue, power, tech prerequisites, refinery ore cycle, team-wipe
|
|
||||||
victory); and `ra3.vulkan` replaces the presentation stack with Vulkan
|
|
||||||
(SDL3 surface, embedded SPIR-V), with a null fallback where no loader
|
|
||||||
exists.
|
|
||||||
|
|
||||||
## Next
|
|
||||||
|
|
||||||
- [ ] **v0.3.1 — tactical map view.** The Vulkan/SDL viewer reproduces the
|
|
||||||
retail tactical view (`TheTacticalView`, `ra3_1.12.game` `0x00cdb7b4`):
|
|
||||||
opens centred on the player's start, wheel zoom, edge scroll and clamped
|
|
||||||
pan. A hand-rolled HUD was tried and removed — the real in-game interface
|
|
||||||
is `.apt` art that must be recovered first, so it is not on the near
|
|
||||||
roadmap.
|
|
||||||
- [ ] **v0.4.0 — real update modules.** Locomotor movement, projectiles and
|
|
||||||
warheads, build placement, shroud, and pathfinding, driven by the
|
|
||||||
`GameObject` module set recovered from the binary.
|
|
||||||
- [ ] **v0.5.0 — data-driven content.** Deserialise the compiled assets
|
|
||||||
(`global.bin`/`static.*.bin` + `.manifest`) so `ra3.data` reads the
|
|
||||||
install instead of pinned constants; real maps, models and strings.
|
|
||||||
- [ ] **v0.6.0 — full renderer.** Perspective terrain (the heightmap is decoded
|
|
||||||
but drawn top-down today), W3D models and the full in-game client on
|
|
||||||
Vulkan, plus input.
|
|
||||||
|
|
||||||
## Cross-cutting tracks
|
|
||||||
|
|
||||||
- **RE depth** — keep recovering retail layouts (see
|
|
||||||
[`REVERSE_ENGINEERING.md`](REVERSE_ENGINEERING.md)); every structure gets an
|
|
||||||
address citation and a test.
|
|
||||||
- **Determinism & replay** — the logic random stream and frame ordering must be
|
|
||||||
reproducible; replay format and a golden-replay test suite.
|
|
||||||
- **Offline only** — no online mode. Multiplayer, if pursued, is LAN lockstep on
|
|
||||||
the message stream, never an online service.
|
|
||||||
Reference in New Issue
Block a user