re: the kind-0 trigger condition is a point-to-segment proximity test
sub_8226DAF8 past the route-name lookup: it resolves the name through sub_823012D8,
requires the unit record's rec+100 != 0, pulls TWO three-double vectors out of that
record -- rec+32/+40/+48 and rec+64/+72/+80 -- and then makes a virtual call:
8226DC1C lwz r11, 0(r30) ; the ScriptPhase vptr
8226DC28 lwz r11, 60(r11) ; vtable slot 60
8226DC30 bcctrl ; test(phase, A, B, P = the route, f1 = node+16)
Slot 60 resolves to sub_82268068, which no built-in uses, so it is engine-internal.
Its arithmetic leaves no room for interpretation: per-axis fsub, fmul plus two fmadd,
fsqrt, giving |B - A|; reject if that is under 0.1 (the constant is literally 0.1, a
degenerate-segment guard); reject if |P - A| > f1 or |P - B| > f1; then compute
t = (P-A).(B-A) / |B-A|^2 and reject if t < 0.
That is a point-to-segment distance test, and it makes the node's double -- built-in
19's local[24] -- a RADIUS. So a kind-0 trigger fires when a route point lies within
that radius of the segment between two vectors from the unit's record.
Recorded as unproven: WHAT A and B are. A previous/current position pair would make
this the standard frame-rate-robust waypoint test, and it would be easy to write that
down -- which is exactly why it is not written down. rec+64/72/80 and rec+32/40/48
are two positions and nothing here says which.
All artefacts regenerate byte-identical; documentation only.
Still unread: sub_8226DC80, the kind-1 condition, entirely; and slot 60 past the
t < 0 rejection, where a second constant at 0x820B0000+25192 is loaded.
This commit is contained in:
@@ -207,14 +207,57 @@ measured to rise **at a squadron's route arrival time**. Route triggers are the
|
||||
mechanism that would do that. 🟡 Stated as a connection, not a demonstration —
|
||||
nothing here traces a trigger to that counter.
|
||||
|
||||
## ✅ What the kind-0 condition TESTS — a point-to-segment proximity check
|
||||
|
||||
`sub_8226DAF8` past the route-name lookup:
|
||||
|
||||
```
|
||||
8226DB84 bl 0x823012D8 ; look the route name up -> a route object; bail if absent
|
||||
8226DBB8 lwz r11, 324(r30) ; the unit array
|
||||
8226DBBC rlwinm r10, r26, 2,0,29; r26 = payload+0, the unit index
|
||||
8226DBC8 lwz r10, 100(r11) ; require rec+100 != 0, else return 0
|
||||
8226DBD4 lfd f0, 32(r11) … ; THREE doubles: rec+32, +40, +48 -> out vector B
|
||||
8226DBF8 lfd f0, 64(r11) … ; THREE doubles: rec+64, +72, +80 -> out vector A
|
||||
8226DBFC fmr f1, f31 ; the node's double (payload+16)
|
||||
8226DC1C lwz r11, 0(r30) ; the ScriptPhase vptr
|
||||
8226DC28 lwz r11, 60(r11) ; VTABLE SLOT 60
|
||||
8226DC30 bcctrl ; test(phase, A, B, P=the route, f1)
|
||||
```
|
||||
|
||||
**Slot 60 → `sub_82268068`**, which no built-in uses — it is engine-internal — and
|
||||
its arithmetic is unambiguous:
|
||||
|
||||
```
|
||||
f29 = |B - A| ; fsub per axis, fmul + 2x fmadd, fsqrt
|
||||
if |B - A| < 0.1 -> 0 ; degenerate segment (the constant is 0.1)
|
||||
f28 = |P - A| ; if > f1 -> 0
|
||||
|P - B| ; if > f1 -> 0
|
||||
t = (P-A)·(B-A) / |B-A|² ; the projection parameter
|
||||
if t < 0.0 -> 0
|
||||
```
|
||||
|
||||
Per-axis `fsub`, a sum of three squares, `fsqrt`, and a dot product divided by
|
||||
the squared length: this is a **point-to-segment distance test**, and the node's
|
||||
double is therefore a **RADIUS**.
|
||||
|
||||
So a kind-0 trigger fires when a route point lies within `local[24]` of the
|
||||
segment between two vectors taken from the unit's record.
|
||||
|
||||
🟡 **What A and B are is not established.** `rec+64/72/80` and `rec+32/40/48` are
|
||||
two positions; a previous/current pair would make this the standard
|
||||
frame-rate-robust waypoint test, and that is exactly the kind of tidy reading
|
||||
this corpus makes itself prove. Not proven here.
|
||||
|
||||
## 🟡 Not settled
|
||||
|
||||
* ~~What the drain actually spawns.~~ ✅ Resolved above: built-in 19's nodes carry
|
||||
a real routine offset at `+28`.
|
||||
* ~~Whether `+24` selects between the two node kinds~~ ✅ It does — see above.
|
||||
* **What the conditions actually TEST.** Only `sub_8226DAF8`'s first ~34
|
||||
instructions are read — up to the route-name lookup. What it compares the route
|
||||
against, and the whole of `sub_8226DC80` (kind 1), are unread.
|
||||
* ~~What the kind-0 condition tests~~ ✅ Read above. **`sub_8226DC80` (kind 1) is
|
||||
still unread entirely.**
|
||||
* **Which unit-record fields A and B are** — `rec+64/72/80` vs `rec+32/40/48`.
|
||||
* **The rest of slot 60** past the `t < 0` rejection (a second constant at
|
||||
`0x820B0000+25192` is loaded next).
|
||||
* **`payload+8`** is a computed value in both appenders (`r29-1` in built-in 19)
|
||||
and is passed to both testers; a waypoint index would fit, which is exactly why
|
||||
it is not being called one.
|
||||
|
||||
Reference in New Issue
Block a user