Skip to content

modules: placement — where a thing can legally stand, answered once - #8632

Draft
keithharvey wants to merge 1 commit into
combatfrom
placement
Draft

modules: placement — where a thing can legally stand, answered once#8632
keithharvey wants to merge 1 commit into
combatfrom
placement

Conversation

@keithharvey

@keithharvey keithharvey commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Three systems put units on the map and each decided "is this ground usable" separately. The wave director had a careful cascade, the mission roster had no check at all, and the mission move action teleported blind.

One place to ask now:

local x, y, z, why = Placement.NearestValid(wantX, wantZ, {
    radius = 400, footprint = 64, surface = "land",
})

The search walks an integer lattice outward in rings, no RNG and no trig, so the same request gives the same answer on every client and in a replay. It returns the nearest valid spot rather than an arbitrary legal one.

It wraps damgam_lib/position_checks.lua instead of reimplementing it, reports which check refused, and returns the ground height so callers don't have to look it up. One surface mode is new: solid means land or sea but not the shoreline between, which a burrow can't straddle.

position_checks reads the world when it loads, so it's pulled in on first use — loading it eagerly took every consumer's specs down.

No consumers in this commit. waves (#8576) and missions wire it in theirs, where the call is visible in context.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Integration Test Results

20 tests  ±0   8 ✅ ±0   16s ⏱️ ±0s
 1 suites ±0   8 💤 ±0 
 1 files   ±0   4 ❌ ±0 

For more details on these failures, see this check.

Results for commit dd027ca. ± Comparison against base commit 82eaef6.

♻️ This comment has been updated with latest results.

Three systems put units on the map and each answered "is this ground I can
use" differently. The wave director had a careful cascade. The mission
roster had nothing at all — it took a map fraction, converted it, and called
CreateUnit, so a roster written for any map could put a lab in the sea on
this one. And the mission API's move action teleports blind: no ground test,
a square offset called a radius, and the unit's OLD height carried to the
new x and z, which leaves it floating or buried on any slope.

So the question gets a module. Ask it where something can stand and it
answers, or says what refused.

    local x, y, z, why = Placement.NearestValid(wantX, wantZ, {
        radius = 400, footprint = 64, surface = "land",
    })

DETERMINISTIC, which is the point. The walk is an integer lattice — rings of
increasing distance, sorted by true distance inside each ring — so there is
no floating point for two clients to disagree about and no die to roll. The
same request on the same map gives the same answer on every client, in a
replay, and in a spec that asserts exact coordinates. It is also why the
answer is the CLOSEST match: a caller gets the point they asked for, or the
nearest place the terrain allows, rather than somewhere random that happened
to be legal.

The tests are not reimplemented. damgam_lib/position_checks.lua already
knows how to ask about flatness, occupancy, surface and bounds; this wraps
them into one question, records which one refused, and hands back the ground
height so no caller has to remember to ask for it.

"solid" is a surface mode the wrapped checks did not have a name for: land
or sea, but never the shoreline between them. A burrow may sit on either and
not across the line, or half its spawns drown.

position_checks reads the world when it loads, so it is pulled in on first
USE. A module that explodes at require time takes every consumer's spec down
with it, and nothing here needs the map until asked a question about it.

No consumers in this commit — the modules that use it declare and wire it in
their own, which is where a reviewer can see the call in context.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant