feedback6 R21H: the round's enemy effects reach the 频次 器物 and the leaders' mid-fight summons (PR #272, 感谢 @CXUtk); golden: 74 moved
器物 (the 14 hit-count keys): hits = data × the spawn's hpMul ÷ supplyHpMul, rounded as before (setHits) — 攻坚装备 / II / III leave out only 炎佑, 补给线 / 补给线II also exactly these 14 keys (activity_table aceffect_enemy_2 / 2_2 enemy_exclude, data/effects.json); until now setHits(def.maxHp) overwrote the round's HP (青铜镜 30 hits at every difficulty). build-data writes enemyScale[r].supplyHp = 1.2^(kHp − kAtk) · extra (the HP-only 补给线II steps and 补给线's 1.08; co-op 终极 R5–R15 only — the rebuild changed config.json alone), gamedata returns it as supplyHpMul and the wave / 悬赏 mods carry it (waves.js roundMods; a 频次 enemy's death spawn inherits it). Not taken from the PR: its 1.08 / 1.2 back-calculation (it counted the 补给线II steps as 攻坚装备) and its fractional-HP ceiling. Leader summons (死亡集群's 妖怪, 刺胄之弹, “裂管之音”/“断弦之音”, 不祥幻影): the boss / hidden field carries the round's scale as flags.enemyScale (bossRounds.js, golden fields, tools/balance.mjs) and bosses.js summonMods gives them HP / ATK / speed (死亡集群's summon.hp_ratio on top; 刺胄之弹 / 余音 hit counts follow their HP); the leader's pool stays exempt; 王权号令's invulnerable equipment unchanged; 炎佑 is an ally token, never scaled (no change). Unchanged and open: the 逐火 / 再生 husk counts (talent prop_max_hp). Golden — 器物 counts: roster 37 (002 003 004 005 007–020 022 023 025 026 029–034 036–041 043 045 049: each holds a 器物 extra spawn / 频次 wave / death spawn), bond-soloShip-high, diy 9 (036 040 056 062 068 073 091 114 115), boss-boss_6-solo (俗心's 小说卷轴 escorts); matches 16 (all but solo-ABYSS-2 and coop2-NORMAL-70-diy: 频次 rounds / 悬赏 and the Final Assault summons). Summons: boss-boss_1-pair/solo, hidden-boss_8-pair/solo (妖怪, 刺胄之弹), boss-boss_3-pair/solo, hidden-boss_10-pair/solo (余音), boss-boss_5-pair/solo (不祥幻影). standins unchanged.
This commit is contained in:
1 parent
783bd30afd
commit
e33ee3db8f
20 files changed
+1491
-1324
No files matched your search
+1
-1
@@ -397,7 +397,7 @@ export function runBoss({ data, mode, difficulty, round, seed, profile = 1, boss
|
||||
const b = m.newBattle({
|
||||
seed: deriveSeed(m.seed, `${fieldId}:${round}`), kind: hidden ? 'hidden' : 'boss', modeId: m.modeId, round, stageId: m.stageId,
|
||||
rect: { ...GEO.BOSS_RECT }, timeLimit: Infinity, players: inputs, spawns: m._sanitizeSpawns(spawns), routes: wave.routes,
|
||||
sharedBoss: pool, flags: { layerGainsEnabled: false, ...gd.dp }, fieldId, enemyOverrides: wave.overrides, waveId: wave.templateId, bossId: id,
|
||||
sharedBoss: pool, flags: { layerGainsEnabled: false, ...gd.dp, enemyScale: gd.enemyScale(round) }, fieldId, enemyOverrides: wave.overrides, waveId: wave.templateId, bossId: id,
|
||||
});
|
||||
b.on('enemyLeak', (ctx) => {
|
||||
const e = ctx && ctx.enemy;
|
||||
|
||||
@@ -3467,7 +3467,13 @@ const DEFAULT_ENEMY_MULTIPLIERS = {
|
||||
abyssMoveSpeedMulFromRound3: 1.15,
|
||||
};
|
||||
|
||||
/** Enemy stat multipliers {atk, hp, speed} of one round (research 01 A3; leader HP pools excluded). */
|
||||
/**
|
||||
* Enemy stat multipliers {atk, hp, speed} of one round (research 01 A3; leader HP pools excluded). `supplyHp` (only
|
||||
* when ≠ 1) = the share of `hp` that comes from 补给线 / 补给线II: the HP-only steps — 1.2^(kHp − kAtk), 补给线II "最大生命值
|
||||
* +20%" with no ATK (攻坚装备 always brings ATK ×1.1, so kAtk counts its stacks) — times `extra` 1.08 (补给线). Those two
|
||||
* effects leave out the 14 器物 hit-count keys (activity_table aceffect_enemy_2 / 2_2 `enemy_exclude`, data/effects.json),
|
||||
* which take hp / supplyHp (server/sim/content/enemies/archetypes.js `times`).
|
||||
*/
|
||||
function enemyScaleFor(table, type, difficulty, round, isHidden) {
|
||||
const t = table?.[type === 'SINGLE' ? 'single' : 'multi']?.[difficulty];
|
||||
if (!t) return { atk: 1, hp: 1, speed: 1, assumed: true };
|
||||
@@ -3477,8 +3483,10 @@ function enemyScaleFor(table, type, difficulty, round, isHidden) {
|
||||
const kHp = t.kHp ? pick(t.kHp, t.hiddenHp) : pick(t.k, t.hidden);
|
||||
const extra = t.hpExtra ? (isHidden ? t.hiddenHpExtra ?? 1 : t.hpExtra[Math.min(i, t.hpExtra.length - 1)] ?? 1) : 1;
|
||||
const speedMul = difficulty === 'ABYSS' && round >= 3 ? (table.abyssMoveSpeedMulFromRound3 ?? 1.15) : 1;
|
||||
const supplyHp = cleanNum(1.2 ** Math.max(0, kHp - kAtk) * extra);
|
||||
return {
|
||||
atk: cleanNum(t.atkBase * 1.1 ** kAtk), hp: cleanNum(t.hpBase * 1.2 ** kHp * extra), speed: speedMul, kAtk, kHp,
|
||||
...(supplyHp !== 1 ? { supplyHp } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -68,7 +68,7 @@ import { DataSource } from '../server/sim/simdata.js';
|
||||
import { buildBattleSpec, createBattleFromSpec } from '../server/sim/spec.js';
|
||||
import { createRng, deriveSeed } from '../server/sim/rng.js';
|
||||
import { GameData } from '../server/match/gamedata.js';
|
||||
import { setupMatchWaves, buildNormalWave, buildBossWave, buildUniteWave, isFlyKey, routeByMotion } from '../server/match/waves.js';
|
||||
import { setupMatchWaves, buildNormalWave, buildBossWave, buildUniteWave, isFlyKey, routeByMotion, roundMods } from '../server/match/waves.js';
|
||||
import { uniteStageId } from '../server/match/unite.js';
|
||||
import { buildDeployMap, positionClass, canPlace, ownerRangeKeys, tileKey } from '../server/match/board.js';
|
||||
import { computeBonds, bondSnapshot } from '../server/match/bondsMeta.js';
|
||||
@@ -407,7 +407,7 @@ function extraSpawns(gd, routes, keys, round, pid, t0 = 8, step = 5) {
|
||||
const fly = isFlyKey(gd, key);
|
||||
let routeIndex = routeByMotion(routes, fly);
|
||||
if (!(routeIndex >= 0)) routeIndex = 0;
|
||||
const s = { time: t0 + i * step, enemyKey: key, routeIndex, count: 1, interval: 0, mods: { hpMul: scale.hpMul, atkMul: scale.atkMul, speedMul: scale.speedMul, slot: fly ? 'NF' : 'N' }, ownerPlayerId: pid };
|
||||
const s = { time: t0 + i * step, enemyKey: key, routeIndex, count: 1, interval: 0, mods: { ...roundMods(scale), slot: fly ? 'NF' : 'N' }, ownerPlayerId: pid };
|
||||
if (i % 2 === 0) { s.tag = 'bounty'; s.bounty = { coins: 2, ownerPlayerId: pid }; s.mods.bountyCoins = 2; }
|
||||
return s;
|
||||
});
|
||||
@@ -595,7 +595,7 @@ export function fieldScenarios() {
|
||||
scenarios.push({
|
||||
id: `${hidden ? 'hidden' : 'boss'}-${bossId}-${solo ? 'solo' : 'pair'}`, family: 'fields', kind: hidden ? 'hidden' : 'boss', modeId, round, stageId, seed,
|
||||
rect: { ...GEO.BOSS_RECT }, timeLimit: Infinity, routes: wave.routes, waveId: wave.templateId, enemyOverrides: wave.overrides,
|
||||
flags: { layerGainsEnabled: false, ...gd.dp }, bossId, boss: { poolHp: pool, poolMax: pool }, fieldId: 'b1', cap: 200,
|
||||
flags: { layerGainsEnabled: false, ...gd.dp, enemyScale: gd.enemyScale(round) }, bossId, boss: { poolHp: pool, poolMax: pool }, fieldId: 'b1', cap: 200,
|
||||
players, spawns: wave.spawns.map((s) => ({ ...s })),
|
||||
about: `${data.bosses[bossId].name} ${solo ? 'solo' : 'pair'} pool ${pool}: ${players.map((p) => placeName(p.units).join(' ')).join(' | ')}`,
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user