A skill clip with no Begin and no Idle plays once at its own length: 德克萨斯 S2 剑雨 and the other instant skills of that shape (#160)

Deploy-time passives without a duration send the same 0.5 s skill window, so 琳琅诗怀雅's passives play their clip too. Contributed by @xcdoge.
This commit is contained in:
xcdoge authored and GitHub committed 2026-10-05 22:36:43 +08:00
1 parent ffdb1293c4
commit 64715116ba
5 files changed
+232 -3

No files matched your search

+17
View File
@@ -2123,3 +2123,20 @@ Decisions of the owner, 2026-10-04: a 联防 devour counts members who enter alr
- **Now**: one attempt at `local` or `assets` is abandoned after `ART_MANIFEST_TIMEOUT_MS`. A timeout or any other failure sets that file `missing` and notifies immediately, which is the existing glyph path. The status stays `missing` through the retry wait (going back to `loading` would blank the button again). A later attempt that succeeds notifies `ready` and the picture replaces the glyph. A 404 or bad JSON is still not retried. Chess and the other text files are not on this clock and still stay `loading` across retries.
- [ASSUMED]: 8 seconds. A response that arrives after that attempt's clock is ignored; the retry is a new request, and the in-flight fetch is not aborted. After the two existing retries the glyph stays until the next `invalidate` or page load.
- **Tests**: `test/ui/emotes.test.js` (stub timer, no network: hung `local` is `missing` before the retry wait, then `ready`; a thrown fetch is the same; a timeout with no retry and a 404 stay `missing`; `chess` arms no timer). `test/ui/playtest3.test.js` data-store retry and `test/client-static.test.js` data.js still pass. No browser render: `EmoteArt` already picks the glyph from `missing`.
---
## 24. Community reports after 0.1.3
Reports after the 0.1.3 release. Each was checked against the official data and PRTS; anything with no source is marked [ASSUMED]. Where each is handled: a skill clip with no Begin and no own Idle plays once (德克萨斯 S2 剑雨) → §24.1.
### 24.1 A skill clip with no Begin and no own Idle plays once — 德克萨斯 S2 剑雨 (player report) — `render/spine.js SpineActor.setSkill / update` (`SKILL_CLIP_MIN`, `skillClipOnce`, `skillEndPending`)
- **Seen** (player report after 0.1.3): 德克萨斯's S2 剑雨 casts with no skill animation — she stays in her idle through the whole cast.
- **Official** [DATA]: her Front model has a single skill clip, `Skill` (2.167 s) — no `Skill_Begin`, no `Skill_Idle`, no `Skill_End`, so the manifest roles are `anims.skill {begin: null, loop: 'Skill', end: null}` and `anims.skills["0"] / ["1"]` are the same clip. Both her skills are instant (`durationType NONE`, duration 0; S1 冲锋号令·γ型, S2 剑雨). The official plays that `Skill` clip on the cast.
- **Cause**: `setSkill(true)` played a clip only when the skill had a Begin clip; with `begin === null` it fell through to `else if (this.mode === 'base') this._play(this._baseName())` — the idle. The loop clip was reachable only through an attack (`_attackClip`), and an instant skill makes no attack inside its activation window: sim `skills.js` fires `['skill', id, 1]` and `['skill', id, 0]` in the same tick (`activate` → `end('instant')`) and only holds the anim code `SKILL` for 0.5 s (`snapshot.js animOf`), so the actor was back on its idle before a frame passed.
- **Now**: a skill clip with neither a Begin nor its own Idle (its loop is not its idle, and it is not borrowed from the attack clip: `via !== 'attack'`) plays that clip once for its own length — `max(SKILL_CLIP_MIN 0.2 s, dur(loop))` — as the skill's own window; a `setSkill(false)` inside that window only marks the transition, so when the window ends the actor plays the skill's End clip (if it has one) or the idle. An instant skill therefore shows its animation instead of a one-frame flash, and a longer skill of the same shape still rests in its idle between attacks while its attacks use the loop, exactly as before. Untouched: a Begin clip with its queued idle / loop, a skill with an idle clip of its own (§23.13), `via: 'attack'` clips, `loop === idle` stances and enemies.
- **Scale**: 90 such clips on 61 Front models (96 clips have no Begin at all — the 6 with an own Idle keep the §23.13 path); 57 of the 90 belong to instant skills.
- **A PASSIVE skill reaches none of this through `activate()`**: `Skill.activate()` returns early for `kind === 'passive'` (`sim/skills.js`); a passive goes through `_startPassive()` (active + mods + `onStart`). Three of the 57 instant clips are passives in the data — 琳琅诗怀雅 S1 仗义疏财 / S2 “见面礼” and 凯瑟琳 S1; 凯瑟琳 S1 turned out to be `kind: instant` in the sim (so it already casts), and the two 琳琅诗怀雅 ones now fire the same window from `_startPassive` — on at the deployment, off after `SKILL_ANIM_WINDOW` (0.5 s) while the passive itself stays active. So all 57 are live.
- **Deploy-time passives with a duration are left alone** (缄默德克萨斯 S1–S3 8–12 s, 野鬃 S1, 伊内丝 S3, 耀骑士临光 S2): the sim keeps a passive active until death, so how long its stance should show is a separate question. A clip that IS the normal attack clip (`anims.skill.loop === anims.attack.loop`: 缄默德克萨斯 S1, 砾, 普罗旺斯, 斯卡蒂 S2) is never played as a skill animation — the new branch requires a distinct clip, so a deploy-time passive on those shows no attack twitch.
- **Tests**: `test/render/feedback4-texas-skill-clip.test.js` (德克萨斯 S2: the clip plays, holds through the same-tick off, then the idle, with no base flash in between; two more real instant entries — `char_140_whitew` S1 日晷, `char_206_gnosis` S2 零度爆发; 银灰 S3 真银斩 — the same shape but long — rests without freezing on the clip's last frame and still attacks with the loop; the deploy-time passives 琳琅诗怀雅 S1/S2 hold their 1 s clip through the sim's 0.5 s window and then idle; a clip that is the attack clip falls through to the base clip; unchanged: 折桠 S2 begin → idle, 耀骑士临光 S3 own idle, 宴 begin → loop). `test/sim/skills.test.js` covers the sim side (the passive window opens at the deployment and closes 0.5 s later, the passive staying active; a timed passive fires nothing). `test/render/feedback3-skill-idle.test.js`, `feedback3-move-deploy.test.js`, `loadout-skill.test.js` and the full suite stay green.