Object completion and mission objective counters
The native 79BB list walker processes expired lifecycle states before the player's mission interpreter runs. At 7A52–7A82, object +46 bit 0 determines whether completion increments C21B and decrements outstanding counter C16F. C16E clamps a negative signed result to zero.
The remaining bits of +46 control the disposition:
- Zero upper bits: unlink the expired object through 7AB4, without adding it to the free list.
- Upper bits 02h or higher below FEh: subtract two and recycle through 1CD4; the updated byte no longer retains the counted-object bit.
- Upper bits FEh: recycle without that decrement.
1CD4 prepends to header +4 and repairs active head/tail and neighbour links. Both removal paths return the next active object to the walker, allowing several expirations in the same pass. These are lifecycle effects, not a claim that every expiry corresponds to a player kill.
tools/verify_object_completion.py checks six two-object fixtures: counted/uncounted objects crossed with lifecycle upper bits 00h, 02h and FEh. It runs the original list walker, counter writes, list removal/recycling and then the player interpreter. With the objective cell list exhausted, both counted expirations reduce the outstanding count to zero, and the player's wait passes in the same update, scheduling its next delay.
Results retain free-list heads, completed counts and player continuation deadlines. Objects are supplied already expired; combat damage, collision and creation of the expired state are not simulated. This closes one scheduling link between object lifecycle and mission progression, not the entire mission lifecycle.