aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmil A. Overbeck <emil.a.overbeck@gmail.com>2026-07-19 02:57:01 +0200
committerEmil A. Overbeck <emil.a.overbeck@gmail.com>2026-07-19 02:57:01 +0200
commitd42411ef884484c9c49482dd944a8394e78d8e15 (patch)
treeea1100f54056ee5549cf6bf7c594a944c72f4e5c
parent0807c89343480b15c7b63a0e864782179eb28ef5 (diff)
downloadforts_clone-d42411ef884484c9c49482dd944a8394e78d8e15.tar.gz
forts_clone-d42411ef884484c9c49482dd944a8394e78d8e15.zip
Update docs
-rw-r--r--CLAUDE.md36
-rw-r--r--requirements/milestones.org79
-rw-r--r--research/gameplay-gaps.org88
3 files changed, 145 insertions, 58 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index e94eeb5..a2453f7 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -153,12 +153,17 @@ See `requirements/milestones.org` for the live checklist. Roughly:
- **M0–M3 done:** scaffolding, rendering/physics, building system, structural
destruction (stress/collapse/fire).
-- **M4 in progress:** cannon (ballistic) + laser (beam/fire) with the Forts
- select-a-weapon-and-aim-in-its-arc UX. Missing: mortar, flak/point-defence,
- machinegun/sniper (hitscan), guided missiles, EMP, per-shot recoil.
-- **M5 in progress:** reactors + win/loss + restart (R), real resource economy
+- **M4 mostly done:** per-strut HP, cannon (ballistic) + laser (beam/fire) with
+ the Forts select-a-weapon-and-aim-in-its-arc UX, direct-vs-splash delivery,
+ fire + spread. Missing: mortar, flak/point-defence, machinegun/sniper
+ (hitscan), guided missiles, EMP, per-shot recoil, metal-per-shot.
+- **M5 mostly done:** reactors + win/loss + restart (R), real resource economy
(mines on deposits, turbines by height, storage caps, firing costs energy),
- device framework + placement.
+ device framework + placement. Two gaps: fire does **not** damage devices, and
+ devices are not mounted on the strut graph, so the "cut its supports and the
+ reactor falls" victory path does not exist.
+- **M6 partial:** enemy fort (`data/mods/enemy-fort/`) + deposits both sides;
+ terrain is still a flat half-plane and there is no sky backdrop.
- **Not started / later:** repair & recycle (M7), armour/door/shield materials,
tech tree + upgrades, commanders, real map/terrain, AI, netcode.
@@ -177,6 +182,27 @@ consult it before deciding what to build; don't guess from vibes.
- **Build before you claim done** (compile in the container) and validate any Lua
you touched with a standalone `lua` run. Be honest about what you couldn't
verify (the GUI can't run headless here).
+- **Keep the status docs in sync — same commit as the change.** When you land,
+ extend or remove a feature, update all three in the commit that changes the
+ behaviour, not later:
+ 1. `requirements/milestones.org` — tick the boxes you actually delivered, and
+ fix any item whose *description* no longer matches what was built.
+ 2. `research/gameplay-gaps.org` — the "What we HAVE" baseline, the affected
+ `**` section, the roadmap table, and the "smallest next steps" queue.
+ 3. `CLAUDE.md` §6 — the milestone summary, plus §2/§3/§4 if the architecture,
+ the physics model or the data schema moved.
+
+ Rules that make this worth doing:
+ - **Verify against the code, not memory.** Grep for the thing before ticking
+ it. These docs drove a real prioritisation error once: every M4/M5 box sat
+ unchecked and the gaps doc still claimed "we have ZERO devices" long after
+ reactors, mines, turbines, the economy and win/loss had shipped.
+ - **Record the gap, not just the win.** Half-done is `[~]` plus a one-line
+ note on exactly what is missing (e.g. M5's reactor exists, but nothing
+ mounts it on the strut graph, so there is no collapse-victory path). A
+ `[X]` that hides a caveat is worse than an unticked box.
+ - §6 tells everyone to consult `gameplay-gaps.org` before choosing work,
+ not to guess from vibes. That holds only while the doc is true.
- **Don't commit game assets** (§5), `builddir/`, or `imgui.ini`.
- Match surrounding code style; keep the engine/game split; prefer data (Lua)
over hard-coded constants.
diff --git a/requirements/milestones.org b/requirements/milestones.org
index 9aa5a5a..3aeb4a9 100644
--- a/requirements/milestones.org
+++ b/requirements/milestones.org
@@ -25,6 +25,11 @@ Notes:
- Pivoted from bgfx to SDL3 renderer for M0. bgfx init fails silently on this
system (EGL-only Linux backend, GLX removed upstream). SDL3 OpenGL renderer
works perfectly. Revisit bgfx later in the project.
+- Follow-up: no source file =#include=s bgfx, SoLoud, ENet or EnTT, so
+ =meson.build= now treats them as OPTIONAL (linked only if a source build has
+ put them in /usr/local) and falls back to system packages otherwise. That is
+ what makes a native (non-container) build possible -- see README. Promote each
+ back to a required dependency when it is actually wired up.
- Header collision: -I/usr/local/include/bx caused sys/types.h to find
bx/endian.h instead of glibc endian.h. Fixed by using single
-I/usr/local/include with qualified <bx/...> includes.
@@ -104,9 +109,9 @@ graph, and form structures.
- [X] Build-grace radial timer on un-triangulated struts (temporary rigid hold)
- [X] Building costs: placing a piece deducts metal + energy
- [X] Simple HUD: resource bars + current-material indicator
-- [ ] Resource system: Metal (mines on deposits) + Energy (wind turbines)
- -- DEFERRED to M5 (needs the reactor / game-loop context). For now metal
- and energy are fixed starting pools that only deplete.
+- [X] Resource system: Metal (mines on deposits) + Energy (wind turbines)
+ -- was deferred to M5 and DELIVERED there (generation, storage caps,
+ build + firing costs).
* M3: Structural Destruction [MOSTLY DONE]
(swapped with weapons -- destruction goes hand-in-hand with M2 building)
@@ -126,47 +131,64 @@ This is the purely-structural half of Forts destruction (no weapons yet).
- [X] Disconnection -> fall -> destroy: a chunk that loses its path to a
foundation simply falls under gravity and dies on the ground
- [X] Materials: wood, background bracing, ropes (tension-only)
-- [ ] Per-strut HP pool (separate from stress) -- belongs with M4 weapon damage
-- [ ] Fire (damage-over-time, strut-to-strut spread) -- M4
+- [X] Per-strut HP pool (separate from stress) -- delivered in M4
+- [X] Fire (damage-over-time, strut-to-strut spread) -- delivered in M4
-* M4: Weapons & Damage
+* M4: Weapons & Damage [MOSTLY DONE]
(swapped with destruction)
Goal: Place and fire all three weapons. They feed the M3 graph via two damage
models (per-strut HP and radius splash) plus fire.
-- [ ] Per-strut HP pool, depleted by weapon hits (independent of stress)
-- [ ] Cannon: click-drag angle/power, Box2D ballistic projectile, splash
- damage with linear radius falloff, knockback impulse, ~25% fire chance
-- [ ] Laser: click-drag beam; stops at wood, passes bg-brace/ropes; 100% ignite
+- [X] Per-strut HP pool, depleted by weapon hits (independent of stress)
+- [X] Cannon: ballistic projectile, splash damage with linear radius falloff,
+ knockback impulse, ~25% fire chance, per-shot energy cost.
+ NOTE: the UX is Forts' select-a-weapon-and-aim-within-its-arc, not the
+ click-drag angle/power originally sketched here. The projectile uses our
+ own integrator; Box2D is still idle.
+- [X] Laser: beam; stops at wood, passes bg-brace/ropes; 100% ignite
- [ ] Flak: auto-target incoming shells within an arc; hitscan/fast projectile
-- [ ] Direct vs splash delivery: foreground struts block direct fire;
+- [X] Direct vs splash delivery: foreground struts block direct fire;
background bracing is passed through by direct hits but takes splash + fire
-- [ ] Fire system: ignition flag, damage-over-time, spread along the graph,
+- [X] Fire system: ignition flag, damage-over-time, spread along the graph,
burns background bracing faster (the counter to the bg-brace trick)
-* M5: Reactor, Resources & Game Loop
+Still missing from the vanilla roster / mechanics (see gameplay-gaps.org #5, #8):
+mortar, flak + point-defence, machinegun/sniper (hitscan), guided swarm
+missiles, EMP, and per-shot RECOIL on the firing structure (we apply knockback
+to targets only).
+
+* M5: Reactor, Resources & Game Loop [MOSTLY DONE]
Goal: There's a reactor to destroy, and a real economy to build it with.
-- [ ] Reactor entity -- large block, HP bar
-- [ ] Player reactor on left, dummy reactor on right
-- [ ] Reactor takes damage from direct hits, fire, falling/collision
-- [ ] Win condition: destroy reactor HP OR disconnect it from its foundation
- (collapse) -- two distinct victory paths
-- [ ] Resource system (deferred from M2): mines on metal deposits, wind
- turbines for energy, generation rates, "can't build when broke"
-- [ ] Win/lose condition + restart (R key)
+- [X] Reactor entity -- large block, HP bar (a device with =is_core=)
+- [X] Player reactor on left, enemy reactor on right (via the enemy-fort mod)
+- [~] Reactor takes damage from direct hits, fire, falling/collision
+ -- splash and beam damage hit devices; FIRE does not damage devices, and
+ devices are not attached to the strut graph, so they never fall.
+- [~] Win condition: destroy reactor HP OR disconnect it from its foundation
+ (collapse) -- only the HP path exists. The round ends when a team has no
+ surviving =is_core= device. The collapse path needs devices mounted on
+ the graph (see M6 / gameplay-gaps.org #3).
+- [X] Resource system (deferred from M2): mines on metal deposits, wind
+ turbines for energy, generation rates, storage caps, build/fire costs
+- [X] Win/lose condition + restart (R key)
-* M6: Dummy Fort & Map
+* M6: Dummy Fort & Map [PARTIAL]
Goal: The dummy fort on the right is a hand-crafted target. The map has metal
deposits and a complete layout.
-- [ ] Dummy fort pre-built structure (reactor, wood walls, bg-brace, ropes)
-- [ ] Map layout: terrain with metal deposits on both sides
-- [ ] Player starting area: reactor + small starter shell + nearby deposits
-- [ ] Visual polish: distinct colors for materials, simple sky backdrop
+- [X] Dummy fort pre-built structure -- =data/mods/enemy-fort/= builds a
+ triangulated fort at x=25..29 with the enemy reactor inside. Wood only;
+ no bg-brace or ropes in it yet.
+- [~] Map layout: metal deposits on both sides exist (=data/map.lua=), but the
+ terrain is still a flat half-plane, not a real heightmap.
+- [~] Player starting area: player reactor + nearby deposits on the left; there
+ is no pre-built starter shell.
+- [~] Visual polish: materials are visually distinct and can load real Forts art
+ (see CLAUDE.md section 5); no sky backdrop is drawn yet.
* M7: Polish & Controls
@@ -175,7 +197,10 @@ Goal: Everything feels good. Controls are responsive. Visuals are clear.
- [ ] Repair tool: right-click damaged piece, pay resources to restore HP
- [ ] Recycle: shift+click to remove piece, recover partial resources
- [X] Camera feel: pan (arrows / middle-drag), scroll zoom (basic; edge-scroll TBD)
-- [ ] Visual feedback: damage states, fire glow
+- [~] Visual feedback: fire glow done (burning struts flicker orange); no
+ per-damage-state art yet. Forts ships damage-state textures
+ (=materials/wood_panel_damaged_1..3.tga=, =bracing-d1/d2=, =armor-d1/d2=)
+ that a =texture_forts=-style field could pick up.
- [X] Build UX: ghost/extrusion previews, hover highlights, build-grace timers
- [ ] Edge cases: zero resources enforcement, etc.
diff --git a/research/gameplay-gaps.org b/research/gameplay-gaps.org
index 4974ef6..c6d1b17 100644
--- a/research/gameplay-gaps.org
+++ b/research/gameplay-gaps.org
@@ -17,20 +17,38 @@ constants.lua) cross-checked against community docs:
* What we HAVE (baseline)
+Re-verified against the code on <2026-07-18>. Keep this section honest: it is
+what the rest of the document is measured against.
+
Building (wood / bg-brace / rope), mass-spring structural sim with stress +
axial/angle breaking + cascading collapse, ground destroys debris, fire
-(DoT + spread), HP, two weapons (cannon = ballistic, laser = beam/ignite),
-a static enemy fort, Lua-data + mods, a dev UI. Resources are a placeholder
-(depleting pools, no generation).
+(DoT + spread), per-strut HP, two weapons (cannon = ballistic, laser =
+beam/ignite) with per-shot energy cost and firing arcs, a pre-built enemy fort
+(=data/mods/enemy-fort/=), Lua-data + mods, a dev UI.
+
+Since the first draft of this document we also have:
+- *Devices*: reactor (=is_core=), mine, wind turbine, battery -- placeable, with
+ HP, damaged by splash and beams.
+- *A real economy*: mines on metal deposits, turbines scaling with height,
+ storage caps, and metal/energy actually spent on building and firing.
+- *A game loop*: win/lose when a team loses its last =is_core= device, plus
+ restart on R.
+- *Bring-your-own Forts art*: =texture_forts= paths load real sprites from the
+ player's own install, falling back to the CC0 placeholders.
* MISSING — grouped by system, each with the in-game reference
-** 1. The Reactor + win/loss [CRITICAL — this is the actual game]
+** 1. The Reactor + win/loss [MOSTLY DONE — M5]
The core the whole game is about. =devices/reactor.lua=: HitPoints 100 (fragile),
and it is ALSO a generator (EnergyProductionRate 100, MetalProductionRate 5).
Win = destroy the enemy reactor by (a) direct damage, (b) fire/splash, or
-(c) cutting its supports so it falls. We have no reactor, no win/loss, no restart.
--> our M5.
+(c) cutting its supports so it falls.
+
+DONE: the reactor exists as an =is_core= device that also generates, takes
+splash and beam damage, and ends the round when a team has none left; R
+restarts. STILL MISSING: fire does not damage devices, and path (c) does not
+exist -- devices sit at fixed coordinates rather than being mounted on the strut
+graph, so cutting the supports under a reactor never drops it.
** 2. Real resource economy [CRITICAL for the core loop]
Two resources, generated by devices (all values from =devices/*.lua=):
@@ -43,9 +61,17 @@ Two resources, generated by devices (all values from =devices/*.lua=):
Resources are capped, not infinite pools.
- *Costs*: building pieces, weapons, devices, AND FIRING all cost metal/energy
(cannon EnergyFireCost 2000, MetalFireCost 50). Repair costs too.
-We have placeholder pools only. -> deferred to our M5.
+DONE in M5: mines on deposits, turbines scaling with height, battery storage
+caps, and metal/energy spent on both building and firing. STILL MISSING: the
+upgraded variants (mine2, turbine2), the derrick and the metal store, and
+repair costs (see #7).
+
+** 3. Devices [PARTIAL — we now have 4 of them]
+We have reactor, mine, turbine and battery, placeable with HP. Two structural
+gaps remain: devices are NOT mounted on the strut graph (they sit at fixed
+coordinates, so they cannot fall when their supports are cut -- see #1), and
+most of the catalogue below is still absent.
-** 3. Devices (whole category — we have ZERO)
From =devices/device_list.lua=:
- Resource: mine, mine2, turbine, turbine2, derrick, battery (energy store),
store (metal store), reactor, minireactor.
@@ -89,7 +115,8 @@ Doors and shields are real tactical mechanics (open to shoot, shield vs lasers).
** 8. Weapon aiming/firing details we simplified
- Cannon/weapons cost energy+metal PER SHOT (EnergyFireCost) — firing is
- resource-limited, not just reload-limited.
+ resource-limited, not just reload-limited. DONE for energy (=energy_cost= per
+ weapon); the per-shot METAL cost is still missing.
- Recoil/kickback pushes the fort (we apply knockback to targets only, not
recoil to the firing structure — Forts Recoil 600000, KickbackMean 40).
- Spotters: sniper reveals targets and guides swarm missiles.
@@ -115,29 +142,38 @@ replays (trivial with deterministic lockstep), sandbox. All post-v0.1.
Mapping the above onto the (already-reordered) milestones:
-| Gap | Milestone | Notes |
+| Gap | Milestone | Status / notes |
|---------------------------------------+-----------+--------------------------------|
-| Reactor + win/loss + restart | M5 | the actual objective |
-| Resource economy (mine/turbine/store) | M5 | deposits, generation, caps |
-| Repair + Recycle | M7 | resource-cost actions |
-| Devices framework (mount on struts) | M5/M6 | reactor is the first device |
+| Reactor + win/loss + restart | M5 | DONE; no collapse-win path |
+| Resource economy (mine/turbine/store) | M5 | DONE (no mine2/turbine2/store) |
+| Per-shot energy cost | M4 | DONE (metal-per-shot missing) |
+| Devices framework (mount on struts) | M5/M6 | not mounted on strut graph |
| Armour + Door + Shield materials | M4/M7 | data-driven, small each |
+| Firing recoil on the shooter | M4 | small, faithful, not started |
| More weapons (mortar/flak/mg/missile) | M4 | point-defence + guided are new |
-| Per-shot energy cost + recoil | M4 | small, faithful |
+| Repair + Recycle | M7 | resource-cost actions |
| Tech tree + Upgrades | post-v0.1 | big; build-order strategy |
| Commanders/Factions | post-v0.1 | defines identity, large |
-| Map deposits / terrain / foundations | M6 | needs a real map format |
+| Map deposits / terrain / foundations | M6 | deposits done; terrain flat |
| AI / campaign / multiplayer | post-v1 | out of scope |
* Smallest high-value next steps (concrete)
-1. *Reactor as a device + win/loss* (M5 kickoff): a mountable block with HP that,
- at 0 HP or when disconnected from a foundation, ends the round. Gives the game
- an actual goal to shoot for. (We already destroy struts and detect
- foundation-connectivity, so both victory paths are within reach.)
-2. *Real resources*: mines on deposits (+metal, -energy), turbines (+energy by
- height), storage caps, and make building/firing actually spend them.
-3. *Armour + Door materials*: data-only additions to the Lua material table
- (armour = high HP/stiff/heavy; door = toggles blocking) — cheap, high value.
-4. *Per-shot energy cost + firing recoil* on the cannon/laser — a few lines,
- makes combat feel like Forts.
+Items 1 and 2 of the original list (reactor + win/loss, real resources) are DONE;
+what follows is the refreshed queue.
+
+1. *Armour material*: data-only addition to =data/materials.lua= (Forts armour is
+ HP 400, +25% stiffness, 2x mass). The material system already has every field
+ it needs, and =materials/armor.tga= is a TGA, so =texture_forts= picks up the
+ real sprite for free. Cheapest real gameplay depth available.
+2. *Firing recoil*: apply an impulse to the FIRING structure, not just the target
+ (Forts Recoil 600000, KickbackMean 40). The knockback machinery already
+ exists; this is a few lines and makes combat feel like Forts.
+3. *Mount devices on the strut graph*: attach devices to nodes so cutting the
+ supports drops them. Unlocks the second victory path in #1 and makes reactors
+ killable by collapse, which is a signature Forts moment.
+4. *Door material*: toggles =blocks_projectiles= so you can open to shoot and
+ close to tank. Needs a small mechanic, not just data.
+5. *Mortar or flak*: the next weapons. Flak brings a genuinely new mechanic
+ (point-defence intercepting incoming shells); mortar is a high-arc,
+ high-building-damage counterpart to the cannon.