feedback3 WG: a split or summoned child does not carry the kill bounty, and 联防 pays a bounty card only when the leaked enemy is that card's enemy
This commit is contained in:
1 parent
bedeac6f52
commit
95b8a24d28
3 files changed
+168
-4
No files matched your search
@@ -52,11 +52,16 @@ export function planUnite(m, results) {
|
||||
for (const l of r.leaked || []) {
|
||||
if (!l || l.counted === false) continue;
|
||||
if (!m.gd.enemy(l.enemyKey)) { notReentered.set(ps.playerId, (notReentered.get(ps.playerId) || 0) + 1); continue; }
|
||||
// kill bounties keep paying in 联防: a 悬赏 card (mods.bountyId) or a bounty set on the SpawnSpec by content
|
||||
// (copied into mods.bountyCoins by the match)
|
||||
// kill bounties keep paying in 联防, and only on the card's own enemy. A split or summoned child
|
||||
// never carries bountyId / bountyCoins (spawnChildren). A leak that still has the card's id but is
|
||||
// some other enemy — a copy that did not go through spawnChildren — does not collect the card either
|
||||
// (GitHub #67, #89-2; owner 2026-10-04: the main body only). A bounty set on the SpawnSpec by content
|
||||
// is copied into mods.bountyCoins by the match and has no card to match.
|
||||
const bountyId = l.mods && l.mods.bountyId;
|
||||
const b = bountyId ? ps.bounties.find((x) => x.id === bountyId) : null;
|
||||
let bounty = b && b.card && b.card.payout !== 'perfect' && Number(b.card.coin) > 0 ? { coins: Math.trunc(b.card.coin), ownerPlayerId: ps.playerId } : null;
|
||||
const card = b && b.card;
|
||||
let bounty = card && card.payout !== 'perfect' && Number(card.coin) > 0 && l.enemyKey === card.enemyKey
|
||||
? { coins: Math.trunc(card.coin), ownerPlayerId: ps.playerId } : null;
|
||||
const extra = !bountyId && l.mods ? Math.trunc(Number(l.mods.bountyCoins) || 0) : 0;
|
||||
if (!bounty && extra > 0) bounty = { coins: extra, ownerPlayerId: ps.playerId };
|
||||
leaked.push({ enemyKey: l.enemyKey, mods: l.mods ? { ...l.mods } : null, lpr: l.lpr ?? 1, sourcePlayerId: ps.playerId, tag: l.tag ?? null, bounty });
|
||||
|
||||
@@ -554,16 +554,31 @@ export function stayRoute(e, secs = 99999) {
|
||||
return { motion: e.motion === 'FLY' ? 'FLY' : 'WALK', start: p, end: p, steps: [{ t: 'wait', s: secs }] };
|
||||
}
|
||||
|
||||
/**
|
||||
* Mods copied onto a split or summoned child. The parent's stat multipliers travel; a kill bounty does not
|
||||
* (owner 2026-10-04: the main body alone carries it — GitHub #67, #89-2). `bountyId` is the 悬赏 card and
|
||||
* `bountyCoins` is the coin copy the match writes for 联防. The parent object is left as it is.
|
||||
*/
|
||||
function modsWithoutBounty(mods) {
|
||||
if (!mods || typeof mods !== 'object') return mods ?? null;
|
||||
if (mods.bountyId == null && mods.bountyCoins == null) return mods;
|
||||
const copy = { ...mods };
|
||||
delete copy.bountyId;
|
||||
delete copy.bountyCoins;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/** Spawn `n` enemies at the parent's position that continue its route. Returns the spawned units. */
|
||||
export function spawnChildren(b, parent, key, n, opts = {}) {
|
||||
const out = [];
|
||||
const route = opts.route ?? remainingRoute(parent);
|
||||
const cnt = Math.max(0, Math.min(20, Math.floor(n)));
|
||||
const mods = modsWithoutBounty(opts.mods ?? parent.mods ?? null);
|
||||
for (let i = 0; i < cnt; i++) {
|
||||
const off = cnt > 1 ? (i - (cnt - 1) / 2) * 0.2 : 0;
|
||||
const pos = opts.pos ?? [parent.y, parent.x + off];
|
||||
const c = b.spawnEnemy(key, {
|
||||
pos, route, mods: opts.mods ?? parent.mods ?? null, tag: opts.tag ?? null, countInTotal: opts.countInTotal,
|
||||
pos, route, mods, tag: opts.tag ?? null, countInTotal: opts.countInTotal,
|
||||
ownerPlayerId: parent.ownerId ?? null, sourcePlayerId: parent.sourcePlayerId ?? null,
|
||||
});
|
||||
if (c) out.push(c);
|
||||
|
||||
Reference in new issue
Block a user