Repository navigation
Conversation
Confetti3
marked this pull request as draft
September 18, 2026 18:27
Confetti3
force-pushed
the
strange-terrain-pr
branch
from
September 18, 2026 18:42
0c33a7c to
85ed609
Compare
…dies A union arm is read by the ordinary per-type reader (86657, union reader 0x1409F3D60, family-4 table 0x141F94F38): a scalar arm takes the union field's own zero width and reads no bits, a nested arm is a no-op, and a type-34 arm is the selected-schema reader. Type 12 shares RAW64's form. Types 20, 30 and 31 share type 18's mode-one reader and type 21 the nullable-u32 reader; one helper now applies those aliases to fields and union arms alike. Type 37 is a nested walk of the schema its reader's global names, 808092FF (24 bits). Without these, component 80803D3B on the Knight's child dropped its frame, the creates in that frame were lost, and every later frame failed on group size.
…does The native anchor pass (0x141713250) runs before its remove pass: an entity that receives a record detaches to root every direct child that received none in the same batch. Without it the registry kept children the client had already dropped from the group, and the next implicit group misparsed.
The client sends a child that is being removed as its own direct element, not inside its parent's implicit group.
… damageState The damage component 80804BEE replicates on lane 2 with one ten-bit level per pool; pool 0 is health, pool 1 shield. The codec keeps the two levels on the update payload, the policy lane keys them by the actor's authored source (its squad when the world view maps one) and finds the mission from the session's policy binding or, without one, from the packet source. The mission runtime raises damageState through the same row lookup and event path as Sense levels. On 86657 a bound combatant never republishes Sense, so this is the only source of boss health: Nokris's clamp holds at 880, 614 and 338 of 1023 arrive here.
Confetti3
marked this pull request as ready for review
September 19, 2026 16:15
Owner
|
- Append every type-34 filter predicate through a capacity check; `inside` could write predicates[8] once `targets` or `squad` filled the body. - Keep squad_state alive_count and previous_alive_count integers (zero when population_available is false) and removal_flag a boolean, so existing scripts that compare them do not fault. - Let rule-less squads take actor commands: one squad_runnable() check now serves placement and both actor-command gates. - Drop the attachment previousRevision compare, which read the revision from the snapshot it was checked against and so could never fail. A request is stale when its spawn_generation no longer names the retained placement. - Squad reports: a forward counter gap that confirms the spawn generation keeps the population comparison, a report naming a newer placement is never a replay, a consecutive root-absent delta continues the retained levels, created counts carry across a proven lifetime, and a cost reset publishes. - Keep entity damage levels in their own table, stop a recycled object row from raising an interaction twice, fill entitySpawned.spawn_generation, and treat type 12 as raw 64-bit in the encoder as the decoder does. - Remove dead and write-only additions (a no-op payload gate, unused fields, statuses and aliases), revert unrelated churn, and rewrite comments that cited addresses, run notes or content names.
Both sides raised the SDK pack version to 41 for different layouts, so the merged reader takes 42 and rejects packs generated by either.
Contributor
Author
|
Thanks for the review. Addressed in 8b3a88c:
Also merged current master; upstream took SDK pack versions 41 and 42, so this is now 43. |
Upstream's scene event keys took SDK pack version 42, so squad-member spawn profiles move to 43. Relation validation keeps both new checks.
Master now carries squad-member spawn profiles (squad_profiles.h), so this branch drops its duplicate helper, flag name and relation check and uses master's. The pack reader moves to 43 because rule-less squads still change pack content.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is the engine side of getting Strange Terrain (the Nokris strike) playable start to finish. I wrote the mission against 0.5 and kept hitting things the SDK couldn't express yet, so this PR is everything the script needed that wasn't there. The mission itself is a separate draft PR on SunriseMissions and should wait for this one.
I know the rules say one feature per PR. These pieces all exist for the same strike and I've only tested them together, so I've kept them in one PR but split it into commits that each build on their own: two for the SDK and runtime work, then four for lane-2 decoding and boss health (added 19 Sep, described below). If you'd rather review them separately, say so and I'll break it up along those lines.
This PR is server side only. An earlier version also carried client hooks for Nokris's health gates and death. I've taken those out and will send them as a separate PR stacked on this one (see the end).
What it adds
SDK generation (commit 1)
kSquadRequiresSelectedRuleand can only be placed with an explicit type-66 rule (squad:place{spawn_rule=}), so nothing that worked before changes. The strike's tunnel knights are authored this way.Host and mission runtime (commit 2)
slot:set_squad_attachment{source=, spawn_generation=, active=}– points a type-26 hop-on at a squad. The Host tracks ownership so the attachment follows its squad through objective assignments and can't be re-pointed by a stale request. It accepts any type-26 slot and squad that share an object and roster group; nothing is keyed to this strike.slot:set_mission_effect{filter=, enabled=, revision=}and two newset_object_filterarguments (targets,squad). Together these are what actually make shield bubbles and crystal beams render; a bare attachment is accepted by the client but draws nothing.slot:set_volume_active{volume=, active=}– the native type-32 toggle for a type-60 volume.on_event_trigger_state– level-style occupancy for type-30 triggers, with a continuity value so a script can tell a fresh baseline from a real change.schemaUnavailable, and the attachment (8080954A) and engagement (808094F0) Sense bodies are decoded (engagement only in its empty-list form, which is all I have seen).tracelog level for the per-row roster dumps, which were drowning the log atdebug.Lane-2 decoding (commits 3–5)
Lane 2 went dark the moment the relic Knight died and stayed dark, which is why I originally thought boss health never reached the server. It was three decoder gaps, found from rejected-packet captures and checked against the 86657 readers:
0x1409F3D60) reads a six-bit selector and calls the ordinary per-type reader from the family table (0x141F94F38). So a scalar arm takes the union field's own zero width and reads no bits, a nested arm (type 1) is a no-op, and a type-34 arm is the normal selected-schema reader. Sunrise refused all three.808092FF(19-bit real + 5-bit int8). I checked this one offline: two captured updates of known length (304 bits) land exactly.0x141713250) detaches every direct child that gets no record in a batch where its parent does. Without that rule the registry kept children the client had already dropped, and the next implicit group misparsed.One frame that fails to decode is expensive: the transport has already acked it, so any creates inside are lost and every later frame fails on group size with no schema error. That is what the 70–120 drop bursts were.
An earlier version of this work had a retry that re-parsed a failed packet with children excluded or a group trimmed. I removed it. It accepted a wrong parse once (a mis-sized payload also re-parses after a trim), and with the rules above it never fires.
Boss health from lane 2 (commit 6)
80804BEEreplicates one ten-bit level per pool (pool 0 health, pool 1 shield). The codec keeps both on the update payload, the policy lane keys them by the actor's authored source (its squad when the world view maps one), and the mission runtime raisesdamageStatethrough the same row lookup and event path the Sense levels already use.<=, not equality.combatant_damage changedlog line now always carriestype=andsource=sense|entity.Notes for review
activity_wire_codec_decode_runtime.hwas already at 1007 and gains 10). The type-26 and type-32 bodies got their own headers next tomission_effect_auth.h, and the root Sense framing got its own translation unit for that reason..clang-format. I haven't run clang-tidy locally.Not in this PR
Nokris has three health gates (86% / 60% / 33%) where he has to stop taking damage until the crystal phase is cleared. With commit 6 the script now sees him cross each gate, and sees his death, from the server side, so I no longer need a client hook to observe health. What still needs the client is holding him at the floor: I haven't found a server-side way to stop a boss taking damage. That work lives on its own branch (
strange-terrain-native), stacked on this one. If there's a server-side way to hold a boss at a health floor, I'd much rather use that and drop the hooks.Without that follow-up, the Nokris shield hop-on also selects no actor.
set_squad_attachmentitself isn't tied to the strike, but the Kvada first-selection repair it needs there is a client patch too. The strike's boss fight needs the follow-up, so the SunriseMissions draft should wait for it.Testing
Solo, build 86657, not tested with more than one player.