feedback3 WI: 琳琅诗怀雅 S3 shoots her coins when the purse reaches 10
This commit is contained in:
1 parent
473b8eb5b0
commit
ab56ea01b1
2 files changed
+40
-21
No files matched your search
@@ -406,7 +406,8 @@ const KITS = {
|
||||
// a small push, radial despite the text's 向前 — PRTS 备注 "推开效果为径向推动"; client charpack char_1033_swire2:
|
||||
// the RandomGold ability (Skill_3_End) carries swire2_s_3[knockback] of template knockback[relative]; 地面敌方单位,
|
||||
// 弹道不可对空). It does not close itself when the purse is full (PRTS 卫戍协议/帮助 「通常不会自动关闭技能」; the skill
|
||||
// text is 「可随时主动关闭」; GitHub #89-1). The player closes it: skill.end('manual'), which spends the coins.
|
||||
// text is 「可随时主动关闭」). Owner's decision 2026-10-04: the written cap (金币上限为10) is the close — at the cap the
|
||||
// coins are shot at once (skill.end('manual')), with or without a mark. Below the cap it stays open.
|
||||
// 精锐 module MER-Y: ATK +4 % per trait payment (≤ 5 stacks).
|
||||
chess_char_3_04_a: (bb, chess, def) => {
|
||||
const d = defOf(chess, def);
|
||||
@@ -501,11 +502,16 @@ const KITS = {
|
||||
for (const e of unit.blocking || []) if (e.alive && !e.isFlying && !list.includes(e)) list.push(e);
|
||||
return list;
|
||||
};
|
||||
const purseCap = Math.max(1, Math.floor(num(s.bb.sp, 10)));
|
||||
return {
|
||||
kind: 'toggle',
|
||||
attack: { hits: 2 },
|
||||
// PRTS 卫戍协议/帮助 「通常不会自动关闭技能」; 千金一掷 「可随时主动关闭」 (GitHub #89-1). A full purse
|
||||
// with a markable enemy does not end it. skill.end('manual') is the close that spends the coins.
|
||||
// Owner 2026-10-04: 「金币上限为10」 is the close. Reaching the cap shoots the coins (the onEnd below).
|
||||
// It does not wait for a mark — a cap with nobody in range still spends them and hits nothing. Below the
|
||||
// cap the skill stays open (the old close also required a markable enemy; that wait is withdrawn).
|
||||
onTick({ unit, skill }) {
|
||||
if (skill.active && (unit.mem.coins ?? 0) + 1e-9 >= purseCap) skill.end('manual');
|
||||
},
|
||||
onEnd({ battle, unit, reason }) {
|
||||
if (reason !== 'manual' || !unit.alive) return;
|
||||
const n = unit.mem.coins ?? 0;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// test/sim/feedback3-swire-s3.test.js — GitHub #89-1: 琳琅诗怀雅 S3 千金一掷 used to call skill.end('manual')
|
||||
// from onTick once her coins were full and a ground enemy stood in the coin range. PRTS 卫戍协议/帮助 技能操作
|
||||
// 「通常不会自动关闭技能」 and the skill text 「可随时主动关闭技能;携带此技能时金币上限为10」: she keeps it
|
||||
// open. The close is still skill.end('manual') — the same call the old onTick used, and feedback1d-push.test.js —
|
||||
// which spends the coins and pushes. No markable target still ends and does not throw.
|
||||
// test/sim/feedback3-swire-s3.test.js — 琳琅诗怀雅 S3 千金一掷. Owner 2026-10-04: the written purse cap
|
||||
// (「金币上限为10」) is the close. At the cap the coins are shot (skill.end('manual'): damage + radial push).
|
||||
// Below the cap the skill stays open. No mark still spends and hits nothing.
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
@@ -29,32 +27,47 @@ const arm = (h) => {
|
||||
return u;
|
||||
};
|
||||
|
||||
test('琳琅诗怀雅 S3 stays open with a full purse and a coin target; skill.end(\'manual\') still spends', REAL, () => {
|
||||
test('琳琅诗怀雅 S3 shoots the purse when it reaches the cap of 10, and stays open below it', REAL, () => {
|
||||
const under = battle(true);
|
||||
const u9 = arm(under);
|
||||
u9.mem.coins = 9;
|
||||
// shorter than the merchant trait's 3 s payment, which would add a coin and reach the cap
|
||||
under.run(2);
|
||||
assert.equal(u9.skill.active, true, '9 coins do not close it');
|
||||
assert.equal(u9.mem.coins, 9);
|
||||
|
||||
const h = battle(true);
|
||||
const u = arm(h);
|
||||
const full = 10; // S3 blackboard sp: the purse cap 「金币上限为10」
|
||||
u.mem.coins = full;
|
||||
h.run(6);
|
||||
assert.equal(u.skill.active, true, 'several seconds do not close it');
|
||||
assert.equal(u.mem.coins, full, 'the coins are still hers');
|
||||
const e = h.enemies()[0];
|
||||
const hp0 = e.hp;
|
||||
u.skill.end('manual');
|
||||
assert.equal(u.skill.active, false);
|
||||
assert.equal(u.mem.coins, 0, 'the close spends every coin');
|
||||
assert.ok(e.hp < hp0, 'and the coins hit the enemy in range');
|
||||
u.mem.coins = 10;
|
||||
h.run(0.2);
|
||||
assert.equal(u.skill.active, false, 'the cap shoots');
|
||||
assert.equal(u.mem.coins, 0, 'every coin is spent');
|
||||
assert.ok(e.hp < hp0, 'the coins hit the enemy in range');
|
||||
assert.equal(h.b.errors.length, 0);
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('琳琅诗怀雅 S3: closing with no markable target still ends and spends, and does not throw', REAL, () => {
|
||||
test('琳琅诗怀雅 S3: the cap with no markable target still ends and spends, and does not throw', REAL, () => {
|
||||
const h = battle(false);
|
||||
const u = arm(h);
|
||||
u.mem.coins = 4;
|
||||
assert.doesNotThrow(() => u.skill.end('manual'));
|
||||
u.mem.coins = 10;
|
||||
assert.doesNotThrow(() => h.run(0.2));
|
||||
assert.equal(u.skill.active, false);
|
||||
assert.equal(u.mem.coins, 0);
|
||||
assert.equal(h.hooksOf('damaged').length, 0, 'nothing to pay');
|
||||
assert.equal(h.b.errors.length, 0);
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('琳琅诗怀雅 S3: a manual close below the cap still spends', REAL, () => {
|
||||
const h = battle(false);
|
||||
const u = arm(h);
|
||||
u.mem.coins = 4;
|
||||
assert.doesNotThrow(() => u.skill.end('manual'));
|
||||
assert.equal(u.skill.active, false);
|
||||
assert.equal(u.mem.coins, 0);
|
||||
assert.equal(h.hooksOf('damaged').length, 0);
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
Reference in new issue
Block a user