Playtest #6 follow-up (v2.5.1): leader HP review — 直接乘算, one debuff instance, 999 layer cap, 限伤; elite to the board; 假想敌:胄 kit
- co-op leaders died within seconds: leader HP is the official data (40 values pinned); bond / strategy / item / 机变 / 特质 "+X%" bonuses now add up (PRTS 直接乘算) instead of compounding; a same-named enemy debuff keeps one (strongest) instance per target (奥术 across a pair field); leader parts pass damage 1:1; fixed co-op pool (the user's call) - official limits read from the client: each bond stops at 999 layers (MAX_GARRISON_STACK); a leader hit of 300000+ in boss / hidden battles is cancelled (MAX_BATTLE_DAMAGE, 限伤) — shared/constants.js switches, research 11 - a merge that consumes a deployed copy puts the elite on that tile and facing (user-confirmed); gold target highlight, promotion effect - 假想敌:胄 per PRTS: one shell, shells within range, any drone death costs 2 % max HP, 剑/锤 sorties and 瘫痪 - DESIGN §20.10–§20.14; 2842 unit tests, all 28 browser suites green; Chrome = Node on boss fields
This commit is contained in:
1 parent
6464e4b46a
commit
620f88c0d8
81 files changed
+4194
-447
No files matched your search
@@ -97,7 +97,7 @@ export class GameData {
|
||||
|
||||
/**
|
||||
* Leader HP pool multiplier — always 1 (no custom balance). Kept for callers written against the old tuning layer
|
||||
* (finalAssault.bossPoolHp); use `bossPoolHp` for the official pool.
|
||||
* (finalAssault.bossPoolHp); use `bossPoolHp` / `bossPoolShare` for the official pool.
|
||||
* @deprecated
|
||||
*/
|
||||
bossHpMul(bossId) { // eslint-disable-line no-unused-vars
|
||||
@@ -105,23 +105,42 @@ export class GameData {
|
||||
}
|
||||
|
||||
/**
|
||||
* Official shared leader HP pool (research 08 §6 #7): co-op = bloodPoint[difficulty] as is — split leaders share one
|
||||
* pool, "敌方领袖的总生命值不变", no alive-player scaling; solo = bloodPoint × config bossHpScale.solo (0.25,
|
||||
* [ASSUMED], flagged in data). Leaders are never scaled by enemyScale.
|
||||
* Official shared leader HP pool (DESIGN §20.10): ONE pool for every boss field of the match (official tip "最终攻势中,
|
||||
* 所有人将一起对敌方领袖造成伤害"; the mirrored copies of a pair field share it — notice 5114 "两侧的敌方领袖共享生命值
|
||||
* (敌方领袖的总生命值不变)", which is about those copies, not about the number of players). Co-op = bloodPoint
|
||||
* [difficulty]; with config bossHpScale.aliveScaling (default false) × alive / aliveFull (4) — 巴哈姆特 12294 "聯機隊友
|
||||
* (撤退/死掉)變少,最後boss血條也會變少" is one community note without a proportion, kept off until confirmed (it would
|
||||
* shorten fights after eliminations, the opposite of the playtest report); `aliveCount` omitted ⇒ a full team. Solo = bloodPoint ×
|
||||
* bossHpScale.solo (0.25 = one player of four, [ASSUMED]). Leaders are never scaled by enemyScale ("领袖单位于服务器的
|
||||
* 生命值加成不受上述加成影响").
|
||||
* @param {string} bossId
|
||||
* @param {number} [aliveCount] alive players at the Final Assault / Hidden Core start (co-op)
|
||||
* @returns {number}
|
||||
*/
|
||||
bossPoolHp(bossId) {
|
||||
bossPoolHp(bossId, aliveCount) {
|
||||
const boss = this.boss(bossId);
|
||||
const diff = this.difficulty;
|
||||
let base = boss && boss.bloodPoint && Number.isFinite(boss.bloodPoint[diff]) ? boss.bloodPoint[diff] : null;
|
||||
if (base == null && boss && boss.bloodPoint) base = Object.values(boss.bloodPoint).find((v) => Number.isFinite(v)) ?? null;
|
||||
if (base == null) base = 500000;
|
||||
return Math.max(1, Math.round(base * this.bossPoolShare(aliveCount)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplier of bloodPoint for the leader pool (see bossPoolHp): solo = bossHpScale.solo (0.25); co-op = coop (1) ×
|
||||
* min(alive, aliveFull) / aliveFull when bossHpScale.aliveScaling (mode entry first, then the global one).
|
||||
* @param {number} [aliveCount]
|
||||
*/
|
||||
bossPoolShare(aliveCount) {
|
||||
const ms = this.mode.bossHpScale && typeof this.mode.bossHpScale === 'object' ? this.mode.bossHpScale : {};
|
||||
const cs = this.config.bossHpScale && typeof this.config.bossHpScale === 'object' ? this.config.bossHpScale : {};
|
||||
const pick = (k, d) => (Number.isFinite(ms[k]) && ms[k] > 0 ? ms[k] : Number.isFinite(cs[k]) && cs[k] > 0 ? cs[k] : d);
|
||||
const mul = this.isSolo ? pick('solo', 0.25) : pick('coop', 1);
|
||||
return Math.max(1, Math.round(base * mul));
|
||||
if (this.isSolo) return pick('solo', 0.25);
|
||||
const scaling = typeof ms.aliveScaling === 'boolean' ? ms.aliveScaling : cs.aliveScaling === true;
|
||||
const full = Math.max(1, Math.floor(pick('aliveFull', 4)));
|
||||
const n = Number(aliveCount);
|
||||
const alive = scaling && Number.isFinite(n) && n >= 1 ? Math.min(full, Math.floor(n)) : full;
|
||||
return pick('coop', 1) * (alive / full);
|
||||
}
|
||||
|
||||
/** config.titles with the tuning overrides (stat / rule per title id) merged in. */
|
||||
|
||||
Reference in new issue
Block a user