feedback6: merge R21H — 器物 (频次) enemies take the 攻坚 HP share and not 补给线's (the data's exclusion list names exactly the 14 器物), leader summons take the round's enemy scaling (PR #272 by @CXUtk, re-implemented from the data); tools/golden.mjs keeps R21H's roundMods import and drops uniteStageId (removed by R21B); golden regenerated on the merge — vs the parent exactly R21H's 74 scenarios, vs the branch only the other streams' moves

This commit is contained in:
sganggs committed 2026-10-07 18:21:01 +08:00
commit a9fe794c3f
20 files changed
+1493 -1326

No files matched your search

+7 -1
View File
@@ -397,14 +397,20 @@ export class GameData {
return typeof v === 'number' && Number.isFinite(v) && v > 0 ? v : null;
}
/** Official enemy multipliers of round r (config enemyScale: the PRTS table + 终极 speed ×1.15 from R3). */
/**
* Official enemy multipliers of round r (config enemyScale: the PRTS table + 终极 speed ×1.15 from R3). `supplyHpMul`
* (only when ≠ 1: co-op 终极 R5–R15) = the share of hpMul from 补给线 / 补给线II (config `supplyHp`), effects whose
* `enemy_exclude` leaves out the 14 器物 hit-count keys — they take hpMul / supplyHpMul (archetypes.js `times`).
*/
baseEnemyScale(r) {
const e = this.mode.enemyScale && this.mode.enemyScale[String(r)];
if (!e || typeof e !== 'object') return { hpMul: 1, atkMul: 1, speedMul: 1 };
const supply = numOr(e.supplyHp, 1);
return {
hpMul: Math.max(0.01, numOr(e.hp, 1)),
atkMul: Math.max(0, numOr(e.atk, 1)),
speedMul: Math.max(0.01, numOr(e.speed, 1)),
...(supply > 0 && supply !== 1 ? { supplyHpMul: supply } : {}),
};
}
+2 -1
View File
@@ -99,7 +99,8 @@ export class MatchBoss {
spawns: this._sanitizeSpawns(spawns),
routes: wave.routes,
sharedBoss: this.bossPool,
flags: { layerGainsEnabled: false, ...this.gd.dp },
// the round's enemy effects for the leaders' mid-fight summons (server/sim/content/bosses.js summonMods)
flags: { layerGainsEnabled: false, ...this.gd.dp, enemyScale: this.gd.enemyScale(this.round) },
fieldId,
enemyOverrides: wave.overrides,
waveId: wave.templateId,
+11 -3
View File
@@ -234,6 +234,13 @@ export function scaleFor(gd, r) {
return gd.enemyScale(r);
}
/** The spawn mods of a round's scale for a non-leader enemy: HP / ATK / speed, plus `supplyHpMul` when the round has one. */
export function roundMods(scale) {
const m = { hpMul: scale.hpMul, atkMul: scale.atkMul, speedMul: scale.speedMul };
if (scale.supplyHpMul != null) m.supplyHpMul = scale.supplyHpMul;
return m;
}
/** Slot class of an enemy that has no placeholder slot (literal template keys, bounty adds). */
export function classOf(gd, enemyKey) {
const e = gd.enemy(enemyKey);
@@ -327,8 +334,9 @@ function templateSpawns(gd, tpl, round, pick) {
interval: count > 1 ? step : 0,
// the round multipliers are ENEMY effects on every enemy but 炎佑 (aceffect_enemy_1–5 `enemy_attribute_mul`,
// enemy_exclude = enemy_9012_acloon): leader parts take them all; the leader takes ATK / speed but not HP — its HP
// is the server pool, "领袖单位于服务器的生命值加成不受上述加成影响" (PRTS 下半)
mods: isBoss ? { atkMul: scale.atkMul, speedMul: scale.speedMul, slot } : { hpMul: scale.hpMul, atkMul: scale.atkMul, speedMul: scale.speedMul, slot },
// is the server pool, "领袖单位于服务器的生命值加成不受上述加成影响" (PRTS 下半). `supplyHpMul` (roundMods) rides along for
// the 器物 hit-count units, which 补给线 / 补给线II leave out (archetypes.js `times`; also a 频次 enemy's death spawn)
mods: isBoss ? { atkMul: scale.atkMul, speedMul: scale.speedMul, slot } : { ...roundMods(scale), slot },
actionIndex: i,
preview: previewInfo(gd, key, routes[routeIndex], isBoss, leader),
};
@@ -528,7 +536,7 @@ function bountyPlan(gd, round, wave, bounties, playerId, side) {
routeIndex,
count: run.len,
interval: run.len > 1 ? step : 0,
mods: { hpMul: scale.hpMul, atkMul: scale.atkMul, speedMul: scale.speedMul, slot: classOf(gd, c.enemyKey), bountyId: b.id },
mods: { ...roundMods(scale), slot: classOf(gd, c.enemyKey), bountyId: b.id },
tag: 'bounty',
ownerPlayerId: playerId,
preview: previewInfo(gd, c.enemyKey, routes[routeIndex], false, leader),