Skip to content

HD2Runtime v0.31.3 — Custom Stratagems with Warbond Carriers, LAS-22 Shear, Exosuit and Bastion Ammunition, FX-12 Relay Recharge

Choose a tag to compare

@SkyeShade SkyeShade released this 12 Oct 03:55
· 20 commits to master since this release

HD2Runtime 0.31.3 — custom stratagems with warbond carriers, LAS-22 Shear, Exosuit and Bastion ammunition, FX-12 relay recharge

0.31.3 is a hotfix release built from player reports: picking a custom stratagem no longer fails on every click when
the lobby's carrier is a stratagem this account does not own (the warbond expendables), the LAS-22 Shear is in the
weapon stats, the EXO-55 Breakthrough's cannon has its ammunition fields, the Exosuit and TD-220 Bastion cannon
ammunition is documented (31 spare magazines is the network maximum; more shells through the magazine capacity), and the
FX-12 Shield Generator Relay's recharge rate and delays are editable. The docs now say that weapon.suppressed has no
audible effect in this game build.

Each item says whether it was seen working in game ("live") or is covered by the offline tests and the snapshot
validators only. Nothing in this release is live-tested, and nothing in it was tested in multiplayer. The new fields
need allow_unverified_effect.

Custom stratagems: never refused for a carrier the account does not own (offline only)

  • A player report (two logs, custom multiplayer): picking the EAT-23 Expendable EMS or the EAT-40 Expendable Gas in the
    custom panel was refused on every click: custom stratagem panel click: selecting eat23_ems (its carrier EAT-411 Leveller) into slot 0 -> stratagem selector REFUSED (nothing written): TOKEN_NOT_OWNED: EAT-411 Leveller is not owned, and the same with the EAT-700 Expendable Napalm, although the availability line had said
    EAT-700 Expendable Napalm cannot carry it: not owned earlier (solo) and then AVAILABLE ... (condensed: EAT-700 Expendable Napalm is also its beacon carrier and its pod) in the lobby.
  • Cause: with several players the lobby's carrier for a custom stratagem is ranked without ownership, so every machine
    computes the same one; a carrier this account does not own is refused locally (local_refused). That refusal was
    applied only to custom stratagems already in the loadout. The pick (custom_stratagems.probe_carrier) took the
    lobby's carrier from the ship preview or the availability view (the expendable's condensed carrier,
    avail.carrier, or the group view) without looking at ownership, and the availability step ignored the condensed
    verdict's "not owned here" flag. The selector's guard then refused the write, every click. In the first log the
    host owned the EAT-700 (its own EAT-40 held it), so the lobby gave the EAT-23 the EAT-411, which it does not own; in
    the second the player owned neither.
  • The guard stays: the saved loadout, the game's server and the other players read the slot, so a carrier or token the
    account does not own is never written (TOKEN_NOT_OWNED still refuses a direct write).
  • Now the pick writes only a carrier this account owns (custom_stratagems.pick_plan):
    • solo: the allocation ranks only owned carriers. An expendable whose carrier weapon's own stratagem is not owned
      takes a separate blue support carrier the account owns (the same custom stratagem: its carrier weapon is still the
      clone). A carrier from an older view that the account does not own is never written. With no owned carrier at
      all, the pick is refused with the reason and nothing is written;
    • custom multiplayer: when this account does not own the lobby's carrier, the pick takes the first carrier of the
      definition's own pool (its group or policy, in the allocator's rank) that this account owns and no other custom
      stratagem holds. This is checked by allocating the lobby again with this player's slot holding it. Every machine
      reads that slot as the id's pin (the r41 pins), so the lobby's carrier for it becomes that carrier everywhere and
      the carrier hashes agree. For an expendable, a slot holding a separate support carrier makes it a fallback one on
      every machine (expendable_pass; solo nothing changes). With no owned carrier, or when another player's slot
      already holds the id with a carrier this account does not own, it is UNAVAILABLE with the reason (the token
      would be refused at mission start the same way: never remapped);
    • the availability line says what the pick will write;
    • the panel says a refused pick once while it stays open, and the tile keeps its warning and reason. It never tries
      the write again on every click.
  • Not changed: the lobby's ranking (still without ownership), the carrier groups' members, the registry hash and the
    peer protocol.
  • Tests: tests/test_custom_stratagem_unowned_carrier.py covers both reports (the condensed EAT-700 not owned solo and
    in a lobby; the EAT-411 the lobby gives after another player's EAT-40; a group carrier not owned in a lobby; the
    refusal said once; the selector's guard on a direct write).
  • Needs a live test: two players with custom multiplayer, one account without the EAT-700 and EAT-411 (and with a
    blue support weapon such as the M-105 Stalwart unlocked). Pick the EAT-40 on that account: its slot should hold the
    support weapon (CARRIER-IN-SLOT PROBE ... its pick writes M-105 Stalwart), the other machine's CUSTOM MP CARRIERS should show the same carrier for it, and in the mission the beacon should deliver the EAT-40 clones from
    the EAT-700's pod. The fallback beacon carrier for an expendable has not been live-tested with several players.

LAS-22 Shear in the weapon stats (offline only)

  • Players asked for the LAS-22 Shear's stats: hd2.weapon('LAS-22 Shear') did not exist, and the editor did not list it.
  • Cause: the player weapon catalogue's 80 weapons come from a published-stat list that has no Shear. Runtime had
    captured its entity (laser_rifle_charge) only as the LAS-5 Scythe's second candidate, and 0.30.2 dropped it there
    as "another weapon" when it proved the Scythe's own entity.
  • Now the game's own armory names it. Armory item 7DE53646 (primary) holds that entity, and its name record composes
    "LAS-22 Shear". The same path gives each of the 80 catalogued weapons its catalogued entity. It is catalogued as a
    primary (Energy-Based) on its own records, with the Scythe's 64 fields (38 writable):
    • handling, spread, recoil and reticle;
    • heat capacity and heat per shot, behind allow_unverified_effect: no published values cross-check them;
    • its beam fire mode, rate and pulse;
    • the beam and damage row (shared with the Scythe);
    • armory traits and penetration label;
    • a beam swap through its own default muzzle (weapon:beam_source(), Laser. Charge Standard).
  • Its default heatsink overwrites heat per second, cooling, the heatsink counts and the firing-charge members when the
    weapon is built. Those stay read-only, and the reason gives the value the game uses: 25 heat/s, not the base 30, and a
    charge loss of 100/s, not the base 500. For the same reason the Scythe's overwritten heatsink count now says "to 4;
    the base value here is 6".
  • hd2.attack_output('LAS-22 Shear') is a beam donor (the Scythe's beam row, through the Shear's own package). Kill
    events name the Shear.
  • Not covered: the burst the game describes when the Shear fully overheats (no proven member). Nothing about the Shear
    is live-tested. Every writable field resolves on the reference snapshot with the catalogued value
    (tests/test_shear.py).
  • Editor: no change needed. It lists the Runtime's player weapons by slot, so the Shear appears under Primary with this
    Runtime.

Compatibility (the Scythe's beam and damage row)

  • The Scythe and the Shear fire the same beam and damage rows, so the Scythe's beam.length, beam.radius and
    damage.* fields (19) are now shared and need allow_shared. The game always shared them; Runtime did not know.
  • Mods that declare SDK 0.31.2 or older keep writing them without it. Each such write is a logged legacy operation
    (docs/legacy-sdk-compatibility.md, the allow_shared entries of schemas/legacy_acknowledgements.json). Mods built
    with the 0.31.3 SDK need allow_shared=true, as the SDK metadata says.

TD-220 Bastion cannon ammunition: the 31-magazine maximum confirmed (research, docs only)

  • A user asked whether the Bastion's main cannon can carry more than the 31 spare magazines Runtime allows since 0.31.2,
    suspecting a 10-bit network field.
  • Re-derived from the game code (research/docs/ammo-network-fields-F5FEE03DCFDB.md): every weapon's live ammunition
    uses the same fields, by its ammunition component, whatever carries it (player, support, vehicle mount, Exosuit arm,
    sentry). Spare magazines are 5 bits (0 to 31), rounds in the magazine 11 bits (0 to 2047), and a rounds feed's spare
    rounds 9 bits (0 to 511). The cannon's spare shells are spare magazines of one shell each, so 31 spare (32 shells) is
    the most it can carry; vanilla is 30 (31 shells). The 10-bit field (0 to 1023) is a deposit's: backpacks and a
    vehicle's own deposit, which the Bastion cannon does not reload from.
  • No maximum changed. docs/vehicle-weapons.md ("Ammunition limits") now explains this and how to get more shells:
    raise weapon.capacity (shells = capacity x (spare magazines + 1); capacity 2 gives up to 64).
  • Not live-tested.

Exosuit ammunition: the EXO-55 Breakthrough cannon's rounds (offline only)

  • A user reported that the EXO-55 Breakthrough's right gun has no magazine or ammo counts, nor do the EXO-49
    Emancipator and EXO-45 Patriot ("I bet all of them have their ammo counts missing").
  • Checked every Exosuit weapon arm. The magazine arms already had theirs since 0.30, on each arm's own record:
    weapon.capacity and the three magazine.* counts on both EXO-45 Patriot arms (rocket pod 14, minigun 1350),
    both EXO-49 Emancipator autocannons (100 each) and both EXO-51 Lumberer arms (flamethrower 500, cannon 25). Their
    magazine counts are 0 / 6 / 0 and no reload is known to use them, so weapon.capacity is the arm's whole supply (in
    the editor it sits in the Weapon section as "Magazine capacity", the counts under Ammo & Magazine).
  • The real gap was the Breakthrough cannon. It is rounds-fed (WeaponRoundsComponentData, like a shotgun), not
    magazine-fed, and the mounted-weapon catalogue only read magazine records. Now it has, on its own record:
    rounds.feed_capacity_1 (rounds per magazine, 6), rounds.spare_rounds (64), rounds.starting_rounds (64) and
    rounds.rounds_from_supply (0). The spare-round fields take at most 511 (the 9-bit spare_rounds network field,
    research/docs/ammo-network-fields-F5FEE03DCFDB.md); the feed has no network field and no maximum, as for player and
    support weapons. Unlike the other arms it owns a reload (1.1 s, reload.duration already published) that draws on
    the spare rounds. It has no second feed (rounds.feed_capacity_2 listed as blocked).
  • Every new field needs allow_unverified_effect. Each was resolved, changed, read back, rolled back and
    conflict-checked on the reference snapshot (validation/vehicle-weapon-authoring-snapshot.json: 878 fields).
  • docs/vehicle-weapons.md has a new "Exosuit ammunition" section with every arm's fields and vanilla values.
    Tests: tests/test_vehicle_weapons.py (every Exosuit arm's ammunition fields against the snapshot values; the
    Breakthrough maxima and acknowledgement in Lua).
  • TD-220 Bastion cannon rounds per magazine: already exposed as weapon.capacity (vanilla 1, at most 2047, behind
    allow_unverified_effect); shells = capacity x (spare magazines + 1). No change needed. All 21 vehicle
    magazine mounts publish weapon.capacity.
  • Editor: no change needed. It shows every editable mounted-weapon field, so the Breakthrough's four rounds fields
    appear under Ammo & Magazine with this Runtime.
  • Not live-tested.

FX-12 Shield Generator Relay: shield recharge speed and delays (offline only)

  • A user asked for the Shield Generator Relay's recharge speed and recharge delay. The relay exposed only its shield
    radius and capacity; the recharge members were blocked because their names came from an external export only.
  • The SH-32 and the SH-51 barrier already had them since 0.30.4, proven by the exact published values of three shields
    at the same ShieldComponent members. Now the game code reading them is traced too
    (research/docs/shield-recharge-F5FEE03DCFDB.md): the shield update resolves the shield's type record every frame
    and, while recharging, adds the recharge rate times the frame time, capped at the capacity; each hit copies the
    recharge delay into the shield's timer, and the hit that breaks the shield copies the broken delay instead. Every
    shield (SH-32, SH-51 barrier, relay, G-SH-39) runs through that same code.
  • New on hd2.stratagem('FX-12 Shield Generator Relay'):deployed_entity():shield(), each 0 to 100000 and behind
    allow_unverified_effect (the relay's own record, so no allow_shared):
    • shield.recharge_rate (hd2.fields.shield.recharge_rate), vanilla 400 health per second; applies at once;
    • shield.recharge_delay (hd2.fields.shield.recharge_delay), vanilla 0.01 s after a hit; applies from the next hit;
    • shield.broken_recharge_delay (hd2.fields.shield.broken_recharge_delay), vanilla 45 s after breaking; applies
      from the next break.
  • Not exposed: the "restart charge" member (no reader found in the shield update or hit path). The EXO-55
    Breakthrough's shield arm has no shield energy at all (no ShieldComponent; its plate health and armor are on
    hd2.vehicle('EXO-55 Breakthrough Exosuit'):shield() since 0.30.4).
  • Docs: docs/stratagem-authoring.md ("Shield Generator Relay shield and damage zones"), docs/backpack-authoring.md.
    Tests: tests/test_entity_authoring.py (vanilla values equal the published ones; acknowledgement and range in Lua).
  • Editor: no change needed. It lists every editable numeric stratagem field by its target, so the three appear in the
    relay's Shield section with this Runtime (with the unverified-effect acknowledgement).
  • Needs a live test: deploy a relay with shield.recharge_rate 40 (one tenth) and shield.broken_recharge_delay 5, break
    the shield, and time the restart (about 5 s instead of 45) and the refill after it (about ten times slower than
    vanilla). Then hit the full shield once with shield.recharge_delay 5: it should wait about 5 s before refilling.

weapon.suppressed has no audible effect (docs only)

  • Asked while trying to make the APW-1 Anti-Materiel Rifle suppressed: weapon.suppressed is set on the four
    suppressed weapons (AR-59 Suppressor, M6C/SOCOM Pistol, M7S SMG, R-72 Censor), but in this game build it has no audible
    or AI effect. The game only uses it to tag a shot's impact noise, and both tagged noise types have zero strength.
  • What makes the suppressed weapons quiet is each weapon's firing noise class (an unmapped member, not exposed) and its
    own firing sound. So no field makes another weapon suppressed; it is not exposed on support weapons.
  • docs/player-weapon-authoring.md ("weapon.suppressed has no audible effect") and the field's reason in the SDK
    metadata say so. Research: research/docs/weapon-suppressed-F5FEE03DCFDB.md. No behaviour changed.

Compatibility

  • Mods built for 0.31.2 work unchanged. A mod that declares SDK 0.31.2 or older and writes the LAS-5 Scythe's beam or
    damage row without allow_shared keeps working, as a logged legacy operation (see "LAS-22 Shear").
  • The startup line reads HD2Runtime 0.31.3 initialized (API 1).
  • The LAS-22 Shear, the EXO-55 Breakthrough cannon's rounds.* fields and the FX-12 relay's shield.recharge_rate,
    recharge_delay and broken_recharge_delay are unknown on 0.31.2: declare min_version 0.31.3 for them.
  • Custom multiplayer needs the same Runtime version on every machine (unchanged): a lobby mixing 0.31.3 with 0.31.2
    reports the other version as incompatible, so custom stratagems stay unavailable there (fail closed). This matters
    here because a 0.31.2 machine would still compute the condensed carrier for an expendable whose slot holds a separate
    support carrier.
  • HD2R Editor 0.9.4 is released alongside; the editor lists the new fields from the Runtime's SDK metadata.