feedback3 WC: the 信标 gift sends the original operator (an elite stays an elite) and still arrives when the sender is eliminated; a failed grant waits for the next round start

This commit is contained in:
sganggs committed 2026-10-04 17:06:43 +08:00
1 parent bdb0765c55
commit ce33795d1b
6 files changed
+204 -19

No files matched your search

+39 -17
View File
@@ -15,7 +15,8 @@
// use_equip_reward_char_chess 拟态物质 3rd copy or a same-bond chess
// use_equip_reward_special_goods_char_chess {refresh_cnt} 寻呼模块 offer N same-bond chess (≤ shop level)
// use_equip_recruit_new_char_and_give_char_to_player_most_bond {refresh_cnt} 信标 destroy target, offer N same-tier
// chess, gift the original next prep
// chess, gift the original (an elite stays
// elite) next prep, sender eliminated or not
// sell_char_count_gain_equip_owner_bond {count} 商业包装方案 every `count` sells → same-bond chess
// char_chess_transformation_equip 突变细胞 after battle: holder destroyed, its equipment
// (the cell included — not consumed) back to
@@ -43,6 +44,19 @@ function rollSameBond(ctx, bonds, maxTier, exclude = null) {
return ctx.rollChess({ maxTier, filter: (id) => { const c = ctx.gd.chess(id); return !!(c && Array.isArray(c.bonds) && c.bonds.some((b) => set.has(b))) && !(exclude && exclude.includes(id)); } });
}
/** 信标: the living teammate (not the caller) with the most members of `bonds` ("相应盟约人数最多"), ties at random; null without one. */
function mostBondMate(ctx, bonds) {
const mates = ctx.teammates();
if (!mates.length) return null;
let best = -1;
let pick = [];
for (const t of mates) {
const score = bonds.reduce((s, b) => s + t.bondCount(b), 0);
if (score > best) { best = score; pick = [t]; } else if (score === best) pick.push(t);
}
return ctx.rng.pick(pick) || null;
}
const ITEM_HANDLERS = {
equip_destory_gain_random_coin: {
onEquip(ctx, ev) {
@@ -135,6 +149,12 @@ const ITEM_HANDLERS = {
if (ids.length) ctx.offerChess(ids, { source: 'item' });
},
},
// 信标 (act2autochess eff_acarm109 / eff_acgarm109 "装备时,目标干员和本装备销毁并进行一次特殊刷新,出现两名与携带者同等阶的
// 干员,免费获取其中一名 / 若在同盟模拟中且存在其他队友,下个休整期向相应盟约人数最多的队友发送1个原干员 / 相应盟约人数相同则
// 随机发送"; 芬 band_fang "原干员在下回合传递给对应盟约人数最多的队友"). The gift is the ORIGINAL operator: an elite carrier
// is sent as that elite (community report #6 after 0.1.2: it arrived as the normal card — the gift carried baseIdOf).
// Destroying the carrier returns its pool copies (an elite's 3) at once; the gift takes them again when it is granted
// (effect:builtin_gift: grantChess → acquireChess, an elite takes up to goldenCopies, as every effect grant).
use_equip_recruit_new_char_and_give_char_to_player_most_bond: {
onEquip(ctx, ev) {
const target = ctx.piece(ev.target.uid);
@@ -142,7 +162,7 @@ const ITEM_HANDLERS = {
const tier = ctx.gd.tierOf(target.id);
const n = Math.max(1, int(paramsOf(ctx, ev.item).refresh_cnt, 2));
const bonds = ctx.pieceBonds(target.uid);
const original = ctx.gd.baseIdOf(target.id);
const original = target.id; // the elite id for an elite (report #6)
ctx.destroyPiece(target.uid);
const ids = [];
// different operators of the target's tier, topped up from the tier below like the promotion reward (item 19)
@@ -153,16 +173,8 @@ const ITEM_HANDLERS = {
}
if (ids.length) ctx.offerChess(ids, { source: 'item', tier });
// co-op: next prep, send the original chess to the teammate with the most members of its bonds
const mates = ctx.teammates();
if (!mates.length) return;
let best = -1;
let pick = [];
for (const t of mates) {
const score = bonds.reduce((s, b) => s + t.bondCount(b), 0);
if (score > best) { best = score; pick = [t]; } else if (score === best) pick.push(t);
}
const to = ctx.rng.pick(pick);
if (to) ctx.addEffect({ id: `gift:${ev.item.uid}`, key: 'effect:builtin_gift', hidden: true, battle: false, params: { toPlayerId: to.playerId, chessId: original } });
const to = mostBondMate(ctx, bonds);
if (to) ctx.addEffect({ id: `gift:${ev.item.uid}`, key: 'effect:builtin_gift', hidden: true, battle: false, params: { toPlayerId: to.playerId, chessId: original, bonds } });
},
},
sell_char_count_gain_equip_owner_bond: {
@@ -230,15 +242,25 @@ const EFFECT_HANDLERS = {
if (n > 0) ctx.addFunds(n, 'doll');
},
},
// 信标's gift: at the next round start (下个休整期) the original operator goes to the teammate picked at equip time. It
// hangs on the SENDER and runs even when the sender was eliminated in between (`afterElimination`: Match.startRound →
// EffectDispatcher.dispatchEliminated) — an eliminated player gets no onRoundStart, so the gift was lost (GitHub #86).
// A receiver eliminated meanwhile is replaced by the living teammate with the most members of the operator's bonds
// (ties at random) [ASSUMED]; with no teammate left alive the gift is dropped. The effect is removed only after the
// operator was granted: a grant that fails (no copy of it left in the shared pool, the receiver's 整备区 and temp
// full) keeps it for the next round start — the official text names no refund [ASSUMED].
builtin_gift: {
afterElimination: true,
onRoundStart(ctx) {
const ref = ctx.source.ref;
ctx.removeEffect(ref.id);
const p = ref.params || {};
const to = ctx.player(p.toPlayerId);
if (!to || !p.chessId) return;
const got = to.grantChess(p.chessId);
if (got) to.giftTicker(ctx.name, p.chessId);
const rec = p.chessId ? ctx.gd.chess(p.chessId) : null;
if (!rec) { ctx.removeEffect(ref.id); return; }
const to = ctx.player(p.toPlayerId) || mostBondMate(ctx, Array.isArray(p.bonds) ? p.bonds : rec.bonds || []);
if (!to) { ctx.removeEffect(ref.id); return; }
if (!to.grantChess(p.chessId)) return;
ctx.removeEffect(ref.id);
to.giftTicker(ctx.name, p.chessId);
},
},
// 整备: the next purchased item becomes advanced (golden)