feedback6 R21F: enemy animation states, the client part of PR #275 by @xcdoge re-implemented — the resolver gives an enemy every numbered skill clip (anims.skills; the caller's first index stays the primary, operators unchanged, 宴's PREFAB_SPINE_ROLES fix kept), the stun spellings Stun_1 and Dizzy_Begin/Loop/End, a separate run role (Run_Begin/Loop/End); the renderer walks an enemy faster than moveSpeed 1 on its Run cycle (猎狗pro, 深池侦察犬 ×2; [ASSUMED] threshold), swaps an enemy's skill clip on a cast event (UnitView.setSkillSlot; a form in force is kept), and plays the 重生 of 巨大的丑东西 (Revive, then the fleeing 大祭司 Idle_2 / Move_2 / Stun_2) and 自在 (Revive_01); data/assets.json regenerated offline: 18 enemies gain anims.skills, 6 anims.run, 3 a stun clip (巨大的丑东西, 斩胄之剑, 破胄之锤), nothing else; the sim's cast slot (a new event) is not part of it; golden: unchanged
This commit is contained in:
1 parent
14df10a5a3
commit
76a2db7dd0
11 files changed
+315
-19
No files matched your search
@@ -77,6 +77,30 @@ describe('Spine actor + audio use the equipped skill', () => {
|
||||
assert.equal((await actorFor(1)).roles.skill.loop, 'Skill_3_Loop', 'no clip for S2 in the model: primary');
|
||||
});
|
||||
|
||||
// PR #275 (@xcdoge): the slot an enemy ability casts (render/app.js `case 'cast'` → UnitView.setSkillSlot) swaps its
|
||||
// skill clip mid-battle, so a multi-skill boss does not show one cast animation for every ability.
|
||||
test('an enemy cast slot swaps its skill clip mid-battle (a form in force is kept)', async () => {
|
||||
const ctx = fakeViewCtx(fake.P, { assets, cam });
|
||||
const v = new UnitView(ctx, { id: 9, side: 'enemy', kind: 'enemy', defId: 'enemy_1521_dslily', x: 5, y: 10, maxHp: 100 }, {});
|
||||
await tick(); await tick();
|
||||
assert.ok(v.actor, 'spine actor built');
|
||||
assert.equal(v.actor.roles.skill.loop, 'Skill_3_Loop', 'the manifest primary clip to start with');
|
||||
assert.equal(v.skillIndex, null, 'no slot reported yet');
|
||||
v.setSkillSlot(0);
|
||||
assert.equal(v.skillIndex, 0);
|
||||
assert.equal(v.actor.roles.skill.loop, 'Skill_1', 'that slot’s own clip');
|
||||
v.setSkillSlot(-1);
|
||||
v.setSkillSlot(1.5);
|
||||
assert.equal(v.skillIndex, 0, 'a non-slot is ignored');
|
||||
v.actor.setForm({ idle: 'Attack' });
|
||||
v.setSkillSlot(2);
|
||||
assert.equal(v.actor.roles.skill.loop, 'Skill_3_Loop', 'the next slot');
|
||||
assert.equal(v.actor.roles.idle, 'Attack', 'the form in force survives the slot change');
|
||||
v.actor.setForm(null);
|
||||
assert.equal(v.actor.roles.idle, 'Idle');
|
||||
assert.equal(v.actor.roles.skill.loop, 'Skill_3_Loop', 'and the slot survives the form ending');
|
||||
});
|
||||
|
||||
test('audio: the equipped skill’s own ON_SKILL_START sound', () => {
|
||||
const manifest = { audio: { sfx: { units: { char_350_surtr: { skill: '/sfx/s3.mp3', skills: { 0: '/sfx/s1.mp3', 2: '/sfx/s3.mp3' } } } } } };
|
||||
const a = new AudioManager({ win: null, getManifest: () => manifest });
|
||||
|
||||
Reference in new issue
Block a user