feedback7 R22-RENDER: 赤刃明霄陈 S3's sword wave is drawn along its path — the sim sends its position as a chen3Wave fx every 0.12 s, the client draws a 'qi' blade (PR #382 by @Convey123, owner item 12); golden: diy-073 / diy-074 events.fx and fx.chen3Wave only
The 赤霄·天喟 wave is a kit-managed probe (it turns corners and lives as long as the skill), not a snapshot
projectile, and the sim emitted one `dash` at the cast and a `slash` per hit — nothing along the way, so the client
drew no wave. op-chen3.js now emits fx('chen3Wave', { x, y, fromX, fromY, dr, dc, id }) every WAVE_FX_EVERY (0.12 s;
4 ticks), the trail restarting at a corner; render/fx registers chen3Wave → 'qi' (pt: drawn at the event, never on
her) and draws a streak plus a crescent head turned the way it travels. The look is a procedural stand-in, not the
official particle prefab.
Substantially @Convey123's code (PR #382), authored as theirs. Changed on review: the head is projected after
streak() — streak() reuses the effect system's projection scratch, so the PR drew the crescent on the trail's start,
one event behind the wave — and the trail, head and heading share one height; an unused test variable dropped.
Golden: diy-073 (5_diy*=chen3 S3 in two slots) events.fx 508 → 1558, fx.chen3Wave → 1050; diy-074 (6_diy*=chen3 S3)
events.fx 272 → 872, fx.chen3Wave → 600. HP, kills, damage, hooks and snapshot hashes unchanged: battle.fx only
records an event.
Tests: test/content/op_chen3.test.js (+1: the events, their cadence, id, direction, trail start, silence after the
skill) 12/12; test/render/fxchen3wave.test.js (new, 6: the archetype, drawn at the wave not at her, the head on the
wave and turned with it, a sweep joining into one trail, junk input, nothing left after) 6/6; boardart 15/15.
This commit is contained in:
1 parent
ae22335cfe
commit
ffa538c39d
6 files changed
+219
-8
No files matched your search
@@ -15,6 +15,9 @@ export const FX_KINDS = Object.freeze({
|
||||
frostNova: { a: 'blast', c: 0x9fe6ff, smoke: 0x1c2630 }, sunBurst: { a: 'blast', c: 0xffe28a }, meltdown: { a: 'blast', c: 0xff5a2a, r: 1.5, heavy: true },
|
||||
iceSpike: { a: 'blast', c: 0xbfeeff, smoke: 0x1c2630 }, rockfall: { a: 'blast', c: 0xc8a878, smoke: 0x4a3f33 }, rockslide: { a: 'blast', c: 0xc8a878, smoke: 0x4a3f33 },
|
||||
finale: { a: 'blast', c: 0xffd45a, r: 1.5 }, swordStorm: { a: 'blast', c: 0xdfe8ff }, swordRain: { a: 'blast', c: 0xdfe8ff }, liberate: { a: 'blast', c: 0xffffff },
|
||||
// 赤刃明霄陈 S3 赤霄·天喟 的龙剑气: a travelling blade, drawn from the sim's per-interval `chen3Wave` events (its own
|
||||
// position + the previous point + direction); `pt` because it is not at the caster (it roams and passes by her tile)
|
||||
chen3Wave: { a: 'qi', c: 0xdfe8ff, pt: true },
|
||||
quadShot: { a: 'volley', c: 0xfff2d0 }, featherArrow: { a: 'counter', c: 0xfff2d0 },
|
||||
burst: { a: 'element', c: 0xd0a0ff },
|
||||
// areas
|
||||
|
||||
@@ -47,10 +47,11 @@ export class FxSim {
|
||||
/**
|
||||
* b.ev 'fx': every kind the sim / content emits has a visual (FX_KINDS archetypes: blast, shell, zone, telegraph,
|
||||
* heal, sp, shield, shatter, summon, vanish, blink, move, wave, mark, reticle, buff, lift, sleep, crit, dodge,
|
||||
* counter, dp, coin, crate, down, beam, bolt, strike, volley, pillar, lp, chill, element, flame), except kinds whose
|
||||
* counter, dp, coin, crate, down, beam, bolt, strike, volley, pillar, lp, chill, element, flame, qi), except kinds whose
|
||||
* archetype is 'none' (hitCap: a leader hit cancelled by 限伤 draws nothing); unknown kinds get a generic sparkle. `extra` keys used: id (anchor unit — or the shooter of a `pt` kind), r | radius, dur | duration,
|
||||
* t (shell flight, game s), src / from / to / target / targets (unit ids), fx, fy / fromX, fromY / tx, ty (positions),
|
||||
* element, n, scale, kind, tiles, hold ('lock': the reticle waits while the shooter's skill runs).
|
||||
* element, n, scale, kind, tiles, hold ('lock': the reticle waits while the shooter's skill runs), dr / dc (a
|
||||
* direction in tiles: 'qi' points its blade that way).
|
||||
*/
|
||||
simFx(kind, x, y, extra) {
|
||||
const ex = extra && typeof extra === 'object' ? extra : {};
|
||||
@@ -168,6 +169,27 @@ export class FxSim {
|
||||
}
|
||||
break;
|
||||
}
|
||||
// a travelling blade (赤刃明霄陈 S3's 龙剑气): a short trail from where it was to where it is, plus a crescent head
|
||||
// turned the way it moves — the sim sends one of these every 0.12 s, and the trail outlives that gap so the
|
||||
// events join into one sweeping wave. A procedural stand-in (the official effect is a particle prefab this client
|
||||
// does not extract). Trail, head and heading share one height; the head is projected after streak(), which
|
||||
// reuses this._p / this._q (projected before it, the head was drawn at the trail's start, one event behind)
|
||||
case 'qi': {
|
||||
const z = at.z + 0.35;
|
||||
const fx0 = num(ex.fromX, NaN), fy0 = num(ex.fromY, NaN);
|
||||
if (Number.isFinite(fx0) && Number.isFinite(fy0)) this.streak(fx0, fy0, at.x, at.y, z, col, 0.34);
|
||||
const h = cam.project(at.x, at.y, z, this._p), hx = h.x, hy = h.y, hs = h.s;
|
||||
const dr = num(ex.dr, NaN), dc = num(ex.dc, NaN);
|
||||
let rot = 0;
|
||||
if (Number.isFinite(dr) && Number.isFinite(dc) && (dr || dc)) {
|
||||
const q = cam.project(at.x + dc * 0.5, at.y + dr * 0.5, z, this._q);
|
||||
// the `slash` sprite's crescent bulges along its local −y, so this turns that edge onto the travel direction
|
||||
rot = Math.atan2(q.x - hx, -(q.y - hy));
|
||||
}
|
||||
this.particle('slash', hx, hy, { tint: col, life: 0.3, s0: hs / 128 * 1.3, s1: hs / 128 * 2.0, a0: 0.9, a1: 0, rot });
|
||||
this.particle('glow', hx, hy, { tint: col, life: 0.26, s0: hs / 128 * 0.8, s1: hs / 128 * 1.5, a0: 0.55, a1: 0 });
|
||||
break;
|
||||
}
|
||||
case 'wave': {
|
||||
const k = clamp(num(ex.scale, 1), 0.5, 4);
|
||||
const rr = Math.max(0.8, r * (ex.scale ? Math.min(2, k / 2) : 1));
|
||||
|
||||
Reference in new issue
Block a user