feedback3: merge W3D — 折桠's skill idle (community report #23), the ammo bar's real total (#35), unit sounds at the official chance and volume (#30), shots from the hands to the chest (GitHub #61), stuck model loads restarted (GitHub #68), the boss leader shown in prep with its hit tiles (#12)
This commit is contained in:
commit
a57c2a85e2
26 files changed
+1105
-89
No files matched your search
@@ -562,9 +562,11 @@ export function withBounties(gd, round, wave, bounties, playerId, { side = null
|
||||
|
||||
/**
|
||||
* nextEnemies preview (m.private.nextEnemies): one entry per spawn action (research 08 §4.2 input), in spawn order:
|
||||
* `{ enemyKey, count, gate: 'upper'|'lower', t, fly, elite, boss, source: 'wave'|'bounty', tag }` — `tag` 'boss' /
|
||||
* `{ enemyKey, count, gate: 'upper'|'lower', t, fly, elite, boss, source: 'wave'|'bounty', tag, start? }` — `tag` 'boss' /
|
||||
* 'bounty' / null kept for the drawer's grouping; Σ count = the enemies of the round (HUD). Boss parts are omitted.
|
||||
* The client places the models in the gate's pen zone (≤ 50 shown, elites and bosses always).
|
||||
* The client places the models in the gate's pen zone (≤ 50 shown, elites and bosses always) — except a leader: its
|
||||
* entry carries its spawn tile `start` ([row, col] on the boss field) and the Final Assault / Hidden Core prep shows it
|
||||
* standing there (render/app.js, community report #12; display only).
|
||||
*/
|
||||
export function previewOf(spawns) {
|
||||
const out = [];
|
||||
@@ -583,6 +585,7 @@ export function previewOf(spawns) {
|
||||
boss: tag === 'boss',
|
||||
source: tag === 'bounty' ? 'bounty' : 'wave',
|
||||
tag,
|
||||
...(tag === 'boss' && Array.isArray(pv.start) && pv.start.length >= 2 && pv.start.every(Number.isFinite) ? { start: [pv.start[0], pv.start[1]] } : {}),
|
||||
_seq: seq++,
|
||||
});
|
||||
}
|
||||
|
||||
+13
-1
@@ -98,6 +98,7 @@ export class SkillRuntime {
|
||||
this.active = false;
|
||||
this.timeLeft = 0;
|
||||
this.ammoLeft = 0;
|
||||
this.ammoMax = 0; // ammo kind: the most bullets this activation held (snapshot's draining bar)
|
||||
this.pending = false; // instant/charges: next attack uses spec.attack
|
||||
this.activations = 0;
|
||||
this.lastStart = -Infinity;
|
||||
@@ -195,6 +196,7 @@ export class SkillRuntime {
|
||||
this.pending = false;
|
||||
this.timeLeft = 0;
|
||||
this.ammoLeft = 0;
|
||||
this.ammoMax = 0;
|
||||
this.charges = 0;
|
||||
this.sp = 0;
|
||||
this._trigKeys = null;
|
||||
@@ -429,6 +431,7 @@ export class SkillRuntime {
|
||||
this.active = true;
|
||||
this.timeLeft = this.kind === 'duration' ? Math.max(0.01, this.duration) : (this.kind === 'ammo' && this.duration > 0 ? this.duration : Infinity);
|
||||
this.ammoLeft = this.kind === 'ammo' ? Math.max(1, this.ammo) : 0;
|
||||
this.ammoMax = this.ammoLeft;
|
||||
this._applyMods();
|
||||
} else {
|
||||
// instant / charges
|
||||
@@ -441,6 +444,9 @@ export class SkillRuntime {
|
||||
u.skillAnimUntil = b.time + 0.5;
|
||||
this._call('onStart', { reason });
|
||||
if (b._hooks.skillStart) b.emit('skillStart', { unit: u, skill: this, reason });
|
||||
// bullets added in skillStart (拉特兰's ×(1.05 + 0.015 × layers), 逃犯引渡手续, talents): the bar's full mark
|
||||
// (community report #35: the extra bullets sat above a full bar until fewer than the base count were left)
|
||||
if (this.active && this.ammoLeft > this.ammoMax) this.ammoMax = this.ammoLeft;
|
||||
if (!this.isTimed && !this.pending) this.end('instant');
|
||||
return true;
|
||||
}
|
||||
@@ -487,6 +493,7 @@ export class SkillRuntime {
|
||||
this.pending = false;
|
||||
this.timeLeft = 0;
|
||||
this.ammoLeft = 0;
|
||||
this.ammoMax = 0;
|
||||
const n = this.activations;
|
||||
this._call('onEnd', { reason });
|
||||
if (!this.active && this.activations === n) this._removeMods();
|
||||
@@ -509,7 +516,12 @@ export class SkillRuntime {
|
||||
|
||||
// ---- helpers for content -------------------------------------------------------------------------------
|
||||
// (non-finite arguments are ignored: a NaN timer/ammo count would keep the skill active forever)
|
||||
addAmmo(n) { if (this.active && this.kind === 'ammo' && Number.isFinite(n)) this.ammoLeft += n; }
|
||||
// (bullets added above the activation's most so far raise the bar's full mark: the bar drains one bullet at a time)
|
||||
addAmmo(n) {
|
||||
if (!this.active || this.kind !== 'ammo' || !Number.isFinite(n)) return;
|
||||
this.ammoLeft += n;
|
||||
if (this.ammoLeft > this.ammoMax) this.ammoMax = this.ammoLeft;
|
||||
}
|
||||
extend(seconds) { if (this.active && Number.isFinite(this.timeLeft) && Number.isFinite(seconds)) this.timeLeft += seconds; }
|
||||
addCharge(n = 1) { if (!Number.isFinite(n)) return; this.charges = Math.max(0, Math.min(this.maxCharges, this.charges + n)); if (this.charges >= this.maxCharges) this.sp = this.spCost; }
|
||||
stop() { this.end('stopped'); }
|
||||
|
||||
@@ -92,8 +92,9 @@ export function unitTuple(u, t) {
|
||||
const spMax = sk && !sk.noSkill ? sk.spCost : 0;
|
||||
let sp = sk && !sk.noSkill ? sk.sp : 0;
|
||||
if (sk && sk.active && sk.isTimed) {
|
||||
// show remaining duration/ammo as a draining bar
|
||||
if (sk.kind === 'ammo') sp = spMax * (sk.ammoLeft / Math.max(1, sk.ammo));
|
||||
// show remaining duration/ammo as a draining bar — ammo out of the activation's real total (base + bullets added:
|
||||
// 拉特兰, 逃犯引渡手续, refills; community report #35), so every bullet shortens it
|
||||
if (sk.kind === 'ammo') sp = spMax * (sk.ammoLeft / Math.max(1, sk.ammoMax || sk.ammo || 0, sk.ammoLeft));
|
||||
else if (Number.isFinite(sk.timeLeft) && sk.duration > 0) sp = spMax * (sk.timeLeft / sk.duration);
|
||||
}
|
||||
// hp is rounded up (a living unit never shows 0) but never above the rounded max HP
|
||||
|
||||
Reference in new issue
Block a user