feedback4: 阿戈尔's devoured base ATK is a 最终加算, and a marker knocked out during the devour still resolves its own marks (GitHub #165 points 2 and 3, PR #176 by @SpiritedAwayCN; the owner's decision of 2026-10-06)
- PRTS 卫戍协议:盟约 下半/PRTS盟约记录, 阿戈尔 ※: 「该付与来源获得所有标记单位的基础攻击力(最终加算)和阻挡数」. New additive mod key atkFinal (PRTS 游戏数据基础 A_f = F_t[(A + D_p)(1 + D_t) + F_p]): ATK = ((base + ΣatkFlat) × (1 + ΣatkPct) + ΣatkFinal) × ΠatkMul. The devour buff carries atkFinal instead of atkFlat: 1000 base ATK, +100 % skill, +2000 devoured → 4000 (was 6000). Every other mod key keeps its meaning. - 「标记按付与顺序触发【吞噬】效果,目标首次被击倒后解除自身被付与但还未触发的【吞噬】效果」 cancels only the knocked-out target's marks: a marker knocked out earlier in the pass now resolves its own marks, the kill credited to it (「击杀来源始终为对应标记的付与来源」). A → B → C with B devoured first: C takes B's 5000 and the kill is B's. The 3 revive slots, the 联防 front-tile devour and the down-at-start rules (DESIGN §24.3 / §24.4) are unchanged. - Point 5 (the 流失's own source is the target itself) stays open: the hooks still see the marker (DESIGN §24.7). - Tests: bonds_core — new 最终加算 test (4000; a 直接加算 still scaled; ×0.5 scales the whole), new A → B → C test, the dead-marker test rewritten (its mark now lands); feedback3-egir-down, feedback4-egir-unite, feedback3-ulpia-move read atkFinal; match/bosshp recomputes ATK with the 最终加算. - Docs: DESIGN §24.7 (and the §24 intro, §5.2 / §5.3, the §24.4 atkFlat lines marked), SIM.md §3, research 02 §3.6 and its JSON spec; data/bonds.json regenerated with build-data --offline — only egirShip.spec.algorithm[2] / [3] changed. - Golden: bond-egirShip-high (the devourers 深巡 / 幽灵鲨 / 斯卡蒂 no longer scale the devoured ATK by their ATK +%; the fight ends at 89.03 s instead of 74.03 s), coop2-ABYSS-10-boosted (from round 8 ai_0 has 3 more 阿戈尔 and 奥术 layers — 海霓's first-kill trait — and both bots' boss damage moves). The marker rule moves no scenario.
This commit is contained in:
1 parent
4f870013c7
commit
5bc2669407
15 files changed
+162
-58
No files matched your search
+2
-2
@@ -16,9 +16,9 @@ function resistPalsyDecay({ battle, unit }) {
|
||||
if (--p.stacks <= 0) battle.removeBuff(unit, p); else unit.markDirty();
|
||||
}
|
||||
|
||||
/** Additive mod keys (summed; × stacks). */
|
||||
/** Additive mod keys (summed; × stacks). `atkFinal` = 最终加算: added after the percentages (units.js _recalc). */
|
||||
export const ADD_KEYS = Object.freeze([
|
||||
'atkFlat', 'atkPct', 'defFlat', 'defPct', 'hpFlat', 'hpPct', 'resFlat', 'aspd', 'batPct', 'blockCnt',
|
||||
'atkFlat', 'atkPct', 'atkFinal', 'defFlat', 'defPct', 'hpFlat', 'hpPct', 'resFlat', 'aspd', 'batPct', 'blockCnt',
|
||||
'rangeExtend', 'defIgnoreFlat', 'defIgnorePct', 'resIgnoreFlat', 'resIgnorePct', 'dodgePhys', 'dodgeArts',
|
||||
'spRecoveryFlat', 'maxTargets', 'taunt', 'hpRegen', 'hpRegenRatio', 'spCostFlat', 'moveFlat', 'massFlat',
|
||||
]);
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
// ex_damage_scale_per_stack·L) instead; 6: cold wind (devices.js kjeragColdWind)
|
||||
// 拉特兰 lateranoShip member ammo skills start with floor(ammo × (1 + base_ammo_percent + ammo_percent_per_stack·L));
|
||||
// 6: every ammo used by a member → all members ATK +atk_per_consume (≤ max_atk_for_consume)
|
||||
// 阿戈尔 egirShip members max HP +(base_max_hp + max_hp_per_stack·L) (直接乘算); battle start devour (see devour());
|
||||
// 阿戈尔 egirShip members max HP +(base_max_hp + max_hp_per_stack·L) (直接乘算); battle start devour (see devour():
|
||||
// the marker's gained base ATK is a 最终加算, `atkFinal`, not scaled by its ATK +%);
|
||||
// 5: the first max_free_respawn_cnt members knocked out (in knock-out order, the devour's food
|
||||
// included) each redeploy at once (free) on that first knock-out
|
||||
// 叙拉古 siracusaShip every member deployment: ASPD +(base + per·L) for (base_duration + per·L) s; 6: 隐匿 for the same
|
||||
@@ -353,14 +354,20 @@ function egirDownAtStart(battle, u) {
|
||||
* the operator on the tile in front of them (one step along each member's own direction `dir`), and through marked
|
||||
* members the tiles in front of
|
||||
* those (chain); never themselves, a unit already marked by them or a unit that marked them. The marker gains the base
|
||||
* ATK (atkFlat) and block count of everything it marked; then each mark makes its target lose damage_value HP as a
|
||||
* ATK and block count of everything it marked — the ATK as a 最终加算 (`atkFinal`, PRTS 盟约记录 "该付与来源获得所有标记单位
|
||||
* 的基础攻击力(最终加算)和阻挡数"): added after its percentages, so its skill's ATK +% does not scale it (it was `atkFlat`
|
||||
* until 0.1.3: 1000 base ATK, +100 %, +2000 devoured gave 6000 instead of 4000; GitHub #165 point 2, PR #176, the owner's
|
||||
* decision of 2026-10-06, DESIGN §24.7). Then each mark makes its target lose damage_value HP as a
|
||||
* 物理流失 (PRTS 盟约记录: "造成5000点物理流失", 修正 "【吞噬】的物理流失来源为被付与目标自身;单位被【吞噬】击杀时,击杀来源始终为
|
||||
* 对应标记的付与来源"; PRTS 作战机制: a 物理流失 "会受到目标当前防御力…影响而相应衰减") — less the target's DEF as a physical hit
|
||||
* (its own source: no DEF ignore), then battle.loseHp: no shields, dodge or damage multipliers (DEF-free until 0.1.1); the
|
||||
* kill is credited to the marker — in marking order. A target knocked out during the pass has its remaining marks
|
||||
* cancelled, also when it is back at once (the 5-tier 立刻复活, 不屈's 立刻重新部署, 埃芒加德 / M3茧甲): PRTS 盟约记录 "目标首次被
|
||||
* 击倒后解除自身被付与但还未触发的【吞噬】效果". A marker off the field gives no further mark (the rule since 0.1.0; one knocked
|
||||
* out and back in the same pass still gives its marks).
|
||||
* 击倒后解除自身被付与但还未触发的【吞噬】效果". Only the target's state cancels a mark: a marker knocked out by an earlier
|
||||
* mark still resolves its own, credited to it (PRTS names only the target; "击杀来源始终为对应标记的付与来源") — GitHub #165
|
||||
* point 3, PR #176, the owner's decision of 2026-10-06; until 0.1.3 a marker off the field gave no further mark.
|
||||
* Not modelled: the 流失's own source (PRTS: the target itself) — the hooks see the marker as the source, as for the
|
||||
* credit (an open question, DESIGN §24.7).
|
||||
* 联防: the operators down since the end of their own combat (forced out by Battle.start) mark, are marked and resolve
|
||||
* their marks like standing ones, but nothing resolves on them (below; per players' reports, owner's decision 2026-10-04).
|
||||
* Whose operator stands in front does not matter (PRTS "依次吞噬身前一格干员", no own-side limit; the owner's decision of
|
||||
@@ -409,7 +416,7 @@ function devour(battle, pid, bb, members) {
|
||||
let atk = 0, block = 0;
|
||||
for (const t of mine) { atk += num(t.base.atk, 0); block += num(t.base.blockCnt, 0); marks.push([m, t]); }
|
||||
const mods = {};
|
||||
if (atk > 0) mods.atkFlat = atk;
|
||||
if (atk > 0) mods.atkFinal = atk; // 最终加算 (units.js _recalc)
|
||||
if (block > 0) mods.blockCnt = block;
|
||||
if (Object.keys(mods).length) S.passiveBuff(battle, m, 'bond:egir:devour', mods);
|
||||
}
|
||||
@@ -422,9 +429,10 @@ function devour(battle, pid, bb, members) {
|
||||
for (const [, t] of marks) if (!dep.has(t)) dep.set(t, items.deploymentOf(t));
|
||||
const knocked = (t) => !t.alive || items.deploymentOf(t) !== dep.get(t);
|
||||
for (const [m, t] of marks) {
|
||||
// (a member down since its own combat — downAtStart — resolves its marks as if it stood; a mark on it resolves nothing:
|
||||
// `knocked` — it is off the field)
|
||||
if (knocked(t) || !(m.alive || downAtStart(m))) continue;
|
||||
// every mark resolves whatever became of its marker — knocked out by an earlier mark (and revived or not), or down
|
||||
// since its own combat (downAtStart); a mark on a unit knocked out during the pass, or lying down since the 联防
|
||||
// start, resolves nothing (`knocked`: it is off the field)
|
||||
if (knocked(t)) continue;
|
||||
S.fxOn(battle, 'devour', t, 'bond:egirShip', 'devour', { from: m.id });
|
||||
if (amount > 0) battle.loseHp(t, mitigate(amount, 'phys', t.s), { source: m, tags: ['bond:egir:devour'] });
|
||||
if (!layered.has(t)) {
|
||||
|
||||
+3
-1
@@ -118,7 +118,9 @@ export class Unit {
|
||||
const b = this.base;
|
||||
const bHp = fin(b.maxHp, 1) > 0 ? fin(b.maxHp, 1) : 1;
|
||||
const maxHp = Math.max(1, fin((bHp + a('hpFlat')) * Math.max(0, 1 + a('hpPct')) * m('hpMul'), bHp));
|
||||
const atk = Math.max(0, fin((b.atk + a('atkFlat')) * Math.max(0, 1 + a('atkPct')) * m('atkMul'), fin(b.atk, 0)));
|
||||
// PRTS 游戏数据基础 属性基本公式 A_f = F_t[(A + D_p)(1 + D_t) + F_p]: `atkFinal` is the 最终加算 (FINAL_ADDITION) —
|
||||
// added after the percentages, inside the Πmul (阿戈尔's devoured base ATK, DESIGN §24.7)
|
||||
const atk = Math.max(0, fin(((b.atk + a('atkFlat')) * Math.max(0, 1 + a('atkPct')) + a('atkFinal')) * m('atkMul'), fin(b.atk, 0)));
|
||||
const def = Math.max(0, fin((b.def + a('defFlat')) * Math.max(0, 1 + a('defPct')) * m('defMul'), fin(b.def, 0)));
|
||||
const res = clamp(fin((b.res + a('resFlat')) * m('resMul'), fin(b.res, 0)), 0, 100);
|
||||
const aspd = clamp(fin(b.aspd + a('aspd'), 100), ASPD_MIN, ASPD_MAX);
|
||||
|
||||
Reference in new issue
Block a user