0.2.5-dev: 驭械术师 normal attacks keep the operator's own hit plus one drone hit, the drone multiplier and per-target map reset on redeploy, 洛洛 S2 keeps its lock until a kill or the skill ends (PRs #537 / #536 / #535 by @Xinglan233, ported); hit tiles use the official round-half-to-even with an edge inset (PR #520 by @Cloudnyco, ported); bots softly avoid living teammates' opening factions until they are eliminated (PR #518 by @IceCodeNew, ported with changes); golden: 43 more scenarios move, each named in docs/history/0.2.5.md

This commit is contained in:
sganggs committed 2026-10-12 14:45:01 +08:00
1 parent 7fd0478dc0
commit e0f3771821
41 files changed
+1939 -779

No files matched your search

+126
View File
@@ -271,3 +271,129 @@ the preceding digest exactly; the changed partner/side also changes preparation
All five already differed from 0.2.4, so the final release-relative total remains 45 scenarios (§30.9 plus these
additional pairing effects). There are no new corpus cases or removals. The other follow-up fixes do not move this
corpus; their dedicated regressions cover the reported and newly found cases.
### 30.17 Funnel normal attacks keep a body hit
PR #537 by @Xinglan233. [PRTS 分支特性信息 驭械术师](https://prts.wiki/w/分支特性信息/data) says a drone that has not
been released by a skill deals additional damage on top of the operator's attack: 20 % ATK at first, +15 on the same
target, cap 110 %. A skill-released drone deals skill damage.
The profession used to return that ramp as the whole normal-attack multiplier, so the body hit was missing.
`resolveHit` now keeps a 100 % ATK body instance and separate drone instances. `funnelMul` holds only the drone ramp;
an attack's `dmgMul` (至简's talent) is applied once to both. Extra attached drones raise `hits`, not the body count.
至简's charged S2 sets `funnelBodyHits`, so two body hits and two additions share one ramp step. Both share one
`attackId` and one attack hook; only the body is `isAttack`. Additions carry `addition` and `funnel` and are not also
emitted as a normal attack.
[ASSUMED] Body instances precede additions at the existing projectile impact, and a multi-hit volley takes one ramp
step. This covers ordinary attacks and unreleased skill attacks that set `funnelBodyHits`. Released skill paths that
do not set it (耶拉 S2, 澄闪 S1 while its own drones are out) keep their existing skill-damage path and do not gain a
second body. Whether those released skills should also have a body attack is not settled here. 澄闪 S3 and the
skill-drone simulator on 淬羽 stay on their own `dealDamage` paths.
Kits that stored the ramp on `dmgMul` (至简, both 耶拉 forms, 澄闪 S2) now store it on `funnelMul`.
Tests: `test/sim/funnel-body.test.js`, and the funnel cases in `kits_t3`, `kits_t6`, `kits_alt_t6`, `kits_alt_t2`
and `op_gdglow`.
### 30.18 Redeploy resets the drone ramp
PR #536 by @Xinglan233. The same branch page says that changing target, or redeploying the operator, restores the
drone damage to its initial value at once.
`installFunnel` resets `funnelTarget`, `funnelScale` and the per-target `funnelMap` (耶拉 / 至简) on a normal
deployment, including automatic revival against the same living target. A free move (`moveRedeploy`, the same carry
as a 秘术师's stored energy and 乌尔比安 S3) keeps the ramp. An in-flight drone still applies the ramp it computes on
impact, so a shot launched before the reset can step the new ramp. That limit is documented and not changed.
Tests: `test/sim/funnel-redeploy.test.js`, `test/match/funnel-redeploy.test.js`.
### 30.19 洛洛 S2 keeps its lock outside her range
PR #535 by @Xinglan233. The official skill table `skchr_rockr_2`, as recorded in `docs/research/03-operators.md`,
says the released drone stays locked until the enemy is killed or the skill ends, then returns. Leaving her attack
range is not a return condition. The branch page says a skill-released drone deals skill damage, and that additional
damage belongs to drones that were not released.
S2 now runs one independent skill tick (`rockr:drone`, one drone at both ranks). While the skill is up the trait
multiplier is detached, so new body shots are ordinary attacks and the unreleased addition is off. The drone's hits
are arts skill damage (`isSkill`, not `isAttack`). It inherits the trait ramp on its own copy, so an older projectile
cannot change that ramp. A living selectable lock stays valid outside the body's range. Ending the skill writes the
ramp back and restores the multiplier and the overload cap. S1 and other operators' funnel attacks keep their
existing paths. 立于磐石 is unchanged.
[ASSUMED] There is no flight delay. A lock that becomes untargetable is dropped and the drone retargets. Body control
(stun and the like) does not pause the released drone.
Tests: `test/content/rockrock-s2-lock.test.js`, and the 洛洛 case in `kits_t1t2`.
### 30.20 Hit tiles use half-even rounding
PR #520 by @Cloudnyco. PRTS 作战机制 (oldid 433935, 「碰撞体积与位置识别」) says the struck unit's coordinates are
rounded half to even (四舍六入五成双) onto the tile they occupy. `Math.round` sends an exact .5 toward +∞, so an enemy
held on an outer half-tile was indexed off the board and dropped from the hit index.
`roundHalfEven` is used for hit tiles only: `body.js` `posKey`, the point cases of `bodyOnTile` and `bodyTileReach`,
the point-enemy index in `battle/queries.js`, and `targeting.js` `tileKeyOf`. Movement, knockback, `ai.js`, a unit's
standing tile for range keys, and `onFrontLine` still use `Math.round`. #519's signed-zero case in `powi` was already
on this candidate and is left as it is.
[ASSUMED] `FIELD_EDGE_INSET` = 1/1048576 pulls a clamped enemy just inside the outer half-tile, so half-even rounding
keeps it on the edge tile. An inset of 1/1024 was rejected because it moved unbalance steps. The inset has no
official source.
Tests: `test/sim/hit-tile-round.test.js`, `test/sim/detmath.test.js`, the edge landing in
`feedback5-raid-own-board`, the 连星 probe in `op_wang`, and the 麦哲伦 probe in `feedback5-wv-summon-triggers`.
### 30.21 Bots soft-reserve a living teammate's opening bonds
PR #518 by @IceCodeNew, for issue #514. This is not an official rule. It extends the accepted #407 card penalty.
Opening-band choice and focus planning used to ignore a living teammate's selected strategy until someone from it was
deployed, so a bot could take that faction's high cards. A living teammate's strategy now soft-reserves its bonds for
both choices, before any member is deployed. The reservation ends when that teammate is eliminated (`alivePlayers`).
It does not hard-exclude a strategy, reserve stock, or stop an immediate merge. A reserved band's draw weight is a
quarter of its unreserved weight (`SOFT_BAND_RESERVE` = 0.25) and stays above zero, so the strategy can still be
drawn. Focus planning applies the existing −6 teammate penalty to those bonds as well. Mode-inactive bonds stay
weight 0 (DESIGN §21.26). A solo match has no teammate to reserve against. The shared-pool −18 card penalty is
unchanged, and a stronger merge can still win it.
[ASSUMED] The quarter weight is a project choice. The PR text called the reservation soft; its diff hard-zeroed the
weight. This candidate follows the text. The reservation is equal for human and AI teammates.
Tests: the two `#514` cases in `test/match/bot-smarter.test.js`. One proves the focus leaves the reserved bond while
the teammate lives and returns after elimination. The other proves a reserved strategy is still drawn, and drawn more
often once that teammate is eliminated. The existing card test still shows a merge outscoring the −18 penalty.
### 30.22 Golden changes after the funnel, hit-tile and bot-reservation ports
All 287 scenarios were recomputed once after §30.17–§30.21 and compared with this candidate before those ports
(`HEAD` `7fd0478d`, `git show HEAD:test/golden/*.json`). No scenario was added or removed. 43 digests differ from
that candidate. They are additional to §30.9 and §30.16.
Against released 0.2.4 the total is now 64. Of the previous 45, 21 are byte-for-byte the digests already on this
candidate and are not repeated below: `roster-011`, `roster-012`, `roster-013`, `roster-032`, `roster-033`,
`roster-034`, `roster-039`, `roster-040`, `roster-043`, `bond-maniShip-high`, `bond-yanShip-low`,
`boss-boss_2-pair`, `boss-boss_5-solo`, `hidden-boss_8-pair`, `hidden-boss_9-solo`, `solo-NORMAL-2`,
`coop2-NORMAL-3`, `solo-HARD-9-boosted`, `coop2-ABYSS-10-boosted`, `standin-06`, `standin-07`. The other 24 of
those 45 moved again, and 19 scenarios that still matched 0.2.4 on this candidate now differ.
Opening strategy ids do not change in any of the 20 match digests. A solo match has no teammate, so §30.21 cannot
move one. Co-op seeds keep the same `bandId` and the same bot-draw counts except `coop4-ABYSS-7`. The recorded
match moves are battle totals from §30.17–§30.20, and the later gold and LP those totals change. No isolated
counterfactual was re-run; the groups below follow who is actually on the board.
| Cause | Changed scenarios |
|---|---|
| Funnel body hit plus redeploy reset, and 洛洛 S2's independent lock (§30.17–§30.19). These boards include 洛洛 | `roster-004`, `roster-005`, `roster-023`, `roster-024`, `bond-victoriaShip-low`, `bond-victoriaShip-high` |
| Funnel body hit plus redeploy reset (§30.17–§30.18). 至简 and/or 耶拉, not 洛洛 | `roster-007`, `roster-009`, `roster-026`, `roster-028`, `bond-deputShip-low`, `bond-emptyShip-low`, `bond-kjeragShip-high`, `bond-maniShip-low`, `bond-miraShip-low`, `bond-sargonShip-high`, `bond-soloShip-low`, `bond-visiShip-low` |
| Same body hit and redeploy reset on 荒芜拉普兰德 | `roster-017`, `roster-019`, `roster-036`, `roster-046`, `roster-047`, `boss-boss_3-pair`, `boss-boss_5-pair`, `boss-boss_7-pair`, `hidden-boss_9-pair` |
| 澄闪 DIY: the normal attack is a body hit plus one drone addition (§30.17) | `diy-098`, `diy-099` |
| Hit-tile half-even rounding and the edge inset (§30.20). No funnel operator is deployed; the damage total stays 1388100 and the hook counts and the snapshot sample at index 27 move | `standin-04` |
| Full matches. Opening bands are unchanged. Final lineups include a funnel operator, except `coop2-HARD-4` (both seats eliminated, lineup empty) and `coop3-ABYSS-5` (the surviving lineup has none), whose first divergence is round 7 and round 5; those two are the hit-tile change, or a funnel operator who is not left in the stored lineup | `solo-FUNNY-1`, `solo-FUNNY-2`, `solo-NORMAL-1`, `solo-HARD-1`, `solo-ABYSS-1`, `coop2-HARD-4`, `coop2-NORMAL-1-coverage-standins`, `coop2-NORMAL-5-coverage-diy`, `coop2-NORMAL-8-serverrun`, `coop2-NORMAL-70-diy`, `coop3-ABYSS-5`, `coop4-FUNNY-6`, `coop4-ABYSS-7` |
Result flips inside that match list: `solo-NORMAL-1` defeat → victory (team LP 0 → 2); `solo-FUNNY-1` team LP 15 → 23
and `solo-FUNNY-2` team LP 8 → 23, both still victories, with every settled round row unchanged; `coop2-NORMAL-8-serverrun`
team LP 26 → 27; `coop4-ABYSS-7` eliminated at round 12 → defeat at round 13, and its shop and bot draw counts change.
The other matches keep the same end reason. `standin-04` is the only battle in this set with no funnel operator on
the board.