guards need their position inside a pair of waypoint boxes (else the game removes them): placing a guard gives it a box and event bit 0, check and inspector state with box around it button; exit and object checks use the engine's cell rule (tiles listed in the cell, swap models), tile cell from the map loader formula
This commit is contained in:
1 parent
a6708e5fff
commit
d9f1b8c2fe
15 files changed
+424
-40
No files matched your search
@@ -76,10 +76,31 @@ values only.
|
||||
| ObjectDontDropInBox, FallOffNoHurt | box mode (+ game state) | box |
|
||||
| WaterReboundPoints | active | rebound points |
|
||||
| RubyIdolDoor | p1 idols needed, p4 sign offset | – |
|
||||
| CityGuard | p0 view range², p1 chase range², p2 event bit, p3 wall collision | patrol (wraps) |
|
||||
| CityGuard family (high) | p0 view range², p1 chase range² (view capped to it), p2 event bit (0 = active at once), p3 wall collision (CityGuard only) | **boxes** (node pairs), must start inside one – see below |
|
||||
| JumpingBeetleBlue, Spider, Bunny | times in seconds (×30), ranges² | patrol path |
|
||||
|
||||
### Guards (CityGuard, CityGuardWithRubyIdol, CowGuard(NoCoin), GorillaGuard, LizardGuard(NoCoin), WarthogGuard)
|
||||
|
||||
One compiled template (same code in t1l1m002 unit 20 and the others). Start of the script:
|
||||
1. `if (p2 > 0) { hide; wait until g95 & (1 << (p2−1)); unhide } else wait until playerPtr ≠ 0` –
|
||||
p2 is an **event bit**: bits of global 95 are set by talking characters (TipoVillage,
|
||||
ChacaVillage), smash statues, LabBigCutscene, LabSlidingDoorPad … with the same number. All
|
||||
village guards have p2 = 0; 4 lab guards wait for an event.
|
||||
2. Waypoint scan: `wpFirst`, then pairs (`wpNext` twice): odd count → debug "Uneven number of
|
||||
WPs" + **remove**; the start box = first pair whose x/z box (`inWaypointBoxXZ`, op 0x178,
|
||||
inclusive, fixed point) contains the guard and whose first node has field +0x28 (`wpParam`,
|
||||
editor `unk2`) = 0; none → "Guard not in WP box" + **remove**. So the waypoints are **walking
|
||||
areas**, not a patrol path: the guard wanders (random turns) inside the current box; when it
|
||||
leaves it, `waypointStep(2)` looks for another box containing it (boxes with `wpParam ≠ 0` only
|
||||
from another such box), else it turns back (`clampToWaypointBox`). Chasing stays clamped to
|
||||
the boxes; it gives up beyond p1 or when the player leaves.
|
||||
All 41 original guards satisfy this (unit test `GuardsTest`). The editor: placing a guard gives
|
||||
it one 4×4 box and p2 = 0; `ObjectChecks` reports an error when the game would remove it and an
|
||||
info for p2 > 0; the Inspector shows the state plus a **Box around it** button (`Guards`,
|
||||
`Setups.guardBox`). Verified in game: CityGuard with its box on a new level (base village 2)
|
||||
appears and attacks the llama; a second one with a 4-node "square path" next to it never appears.
|
||||
|
||||
The rest (~150 placed types) shows raw values with the original statistics. Next candidates:
|
||||
PressurePadDoor (bit field), TargetRopePlatform, CataSwingingBlade (speeds/angles), RiverLog.
|
||||
Alligator (also box pairs: "Forcing alligator inside first WP box"), PressurePadDoor (bit field), TargetRopePlatform, CataSwingingBlade (speeds/angles), RiverLog.
|
||||
Tooling used (not in the repo): Ghidra script decompiling the handler table, a Python sweep
|
||||
disassembler with an op-name table, "parameter use" context dumps per type.
|
||||
Reference in new issue
Block a user