0.2.5-dev: community round 30 and follow-ups

- Stock: fixed trait gifts (缪尔赛思 / 变形者集群 变形同构体, 耶拉 不融冰, 蜜蜡 / 卡涅利安 迅捷作战粮, 诗怀雅 盟约之币) still occupy stock but are granted past the cap; an operator card already shown in the shop or a reward can be taken after the pool runs out and overdraws (GitHub #498, the owner's decision); item buys and item rewards keep the stock check. 洛洛 / 焰尾 sub-pools use the measured weights (PR #497 by @2321Robin; the occupancy idea of PR #496 by @2321Robin re-implemented differently).
- Boss pairs are drawn at random once per match and fixed to battle start; the Hidden Core reuses them; a leaver does not split a full pair (the owner's decision).
- 阿戈尔 in 联防 no longer re-applies the opening devour HP loss or a false revive; Touch's team medic stays for the match after its holder leaves (owner-approved, official lifetime unverified).
- Auto-skill ranges: 司霆惊蛰 S2, 斩业星熊 S3 against air, 予愿安洁莉娜 S3; 自在's post-rebirth invulnerability is also untargetable (#510); Horn / Clementia / catapult / 忍冬 first hit (PR #502 by @Xinglan233); 不融冰 / tear gas trigger on real damage.
- Bond layer-up sound in round start / draft / prep / battle (#482): one channel, a new cue replaces the old, no extra cooldown; a prep update that adds layers and activates a bond plays one cue.
- Client: multi-swing fix (#506), refresh single-flight (PR #507 by @robll-v1), LP tower keeps the settled value with a −N tick (PR #504 by @robll-v1), export with only 潜能 / 练度 changes (PR #503 by @Xinglan233), spectator rosters list DIY members (PR #505 by @Xinglan233), banned members beside bond tooltips (PR #494 by @YuriRestia), recovery action above the away overlay (PR #511 by @RainoutOvO), the /dev/sim-check.html consistency page (PR #492 by @Cloudnyco), Korean (PR #490 by @D-Roote) and English Victoria wording (PR #499 by @YuriRestia).
- golden: 45 of 287 scenarios move against 0.2.4 (roster 17, bonds 3, fields 6, matches 17, standins 2), each attributed in docs/history/0.2.5.md §30.9 / §30.16.
This commit is contained in:
sganggs committed 2026-10-12 14:07:08 +08:00
1 parent bc50cac01f
commit 221e6b8dd2
134 files changed
+4590 -1201

No files matched your search

+4 -2
View File
@@ -337,10 +337,11 @@ function rebirthCleanse(b, e) {
* (no move / attack / skill).
* `onKo(b, e, a)` runs at once (self-destruct, freeing prisoners …), `during(b, e, a, elapsed)` every tick of it; then the
* enemy stands up with `hpRatio` of its max HP, `onReborn(b, e, a)` switches the form and `invincible` s of 无敌 follow.
* `invincibleUntargetable` opts a verified enemy into hostile selection immunity for that same window (Xi, #510).
* `a.state`: undefined → 'reborn' → 'form2'. The 'telegraph' fx of the knock-out carries `form: 'reborn'` and the 'revive'
* fx `form: 'form2'`: models with those clip sets (render/units.js FORMS — 锏, 扎罗, “复仇者”, 杰斯顿) play them.
*/
function reborn({ dur = 0, hpRatio = 1, invincible = 0, onKo = null, during = null, onReborn = null, key = 'ab:reborn' } = {}) {
function reborn({ dur = 0, hpRatio = 1, invincible = 0, invincibleUntargetable = false, onKo = null, during = null, onReborn = null, key = 'ab:reborn' } = {}) {
const finish = (b, e, a) => {
if (!e.alive || a.state !== 'reborn') return;
a.state = 'form2';
@@ -348,7 +349,8 @@ function reborn({ dur = 0, hpRatio = 1, invincible = 0, onKo = null, during = nu
e.profile.noAttack = a.noAtk;
if (onReborn) safe(b, e, () => onReborn(b, e, a));
e.hp = Math.max(1, e.s.maxHp * Math.max(0, Math.min(1, hpRatio)));
if (invincible > 0) b.addBuff(e, { key: `${key}:inv`, duration: invincible, visible: true, flags: { invulnerable: true } });
if (invincible > 0) b.addBuff(e, { key: `${key}:inv`, duration: invincible, visible: true,
flags: { invulnerable: true, ...(invincibleUntargetable ? { untargetable: true } : {}) } });
if (e.route) e.route.pts = null;
e.atkCd = 0;
rebirthCooldowns(e);
+3
View File
@@ -473,6 +473,9 @@ function kitXi(ab) {
};
const re = reborn({
dur: T(ab, 'reborn.duration') ?? 0, invincible: T(ab, 'reborn.invincible') ?? 0,
// #510: Xi's post-rebirth 无敌 also prevents hostile selection (PRTS “自在” / 无敌).
// Explicit opt-in: the engine's general invulnerable flag remains damage protection only.
invincibleUntargetable: true,
onKo(b, e) { b.removeBuff(e, 'ab:xiShield'); },
onReborn(b, e) {
P.form2 = true;
+3 -1
View File
@@ -412,7 +412,9 @@ export const SPECIAL_KITS = Object.freeze({
// report of 2026-10-06, item 24); it picks by 仇恨值, not its blocker first
spawn(b, e) { e.profile.blockFree = true; },
dealt(c, b, e) {
const n = T(ab, 'Attack.attack@times') ?? 1, r = T(ab, 'Attack.attack@projectile_range') ?? 0;
// PRTS 自制投石机: normal stones splash in radius 1.5. The talent's projectile_range (0.5) belongs to
// the separate 入戏 random-offset attack, not its ordinary volley in this mode.
const n = T(ab, 'Attack.attack@times') ?? 1, r = 1.5;
const t = c.target;
for (let i = 1; i < n; i++) hurt(b, e, t, e.s.atk, 'phys');
// the stone's splash ("碰撞无视迷彩"): an area selection — no unblocking 隐匿 ally