lili 6ca44e3b2c feat(shanhai): M5 代码灌装(占位资产)——5图/敌32/Boss10/sim参数化/meta解锁
- balance.js: MAPS 5图(裂谷原+不周山/昆仑墟/归墟/钟山占位)+ENEMIES 32+BOSSES 10+D2-D5解锁占位+各图波表占位
- sim.js: createSim mapId 参数化(按图取数,map1零变化硬证三局逐字节一致)+_debugFill限定敌混
- meta.js: unlockedMaps解锁持久化(存档data内,schemaVersion=1向后兼容)+胜局解锁下一图
- meta-tables.js: dex_full阈值gte:51->DEX_TOTAL动态(修既有硬编码双写bug)
- game-logic.js: 出击页地图行驱动MAPS+isMapUnlocked接meta
- 占位数值/sprite标待美术待平衡;map2-5占位pacing待平衡;选图入局接线待后续
- 回归全绿:真实13/13+meta11/11+build-tables9/9+meta-tables6/6;ui-trigger2 test4 pre-existing渲染层失败非M5引入
- M5完整验收需美术资产(图2-5/29兽sprite/BGM6)+真平衡扫描
2026-07-25 04:07:08 -07:00

736 lines
46 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* balance.js — 《山海行纪》M3 数值表(纯数据 · 零魔法数唯一来源)
* owner:北极星顶级线②(开发设计书 §8.1「所有常量集中在 balance 层数据表」纪律)
*
* 【口径】
* - 本表是 sim.js(纯逻辑核心)唯一的数值来源:游戏代码里不允许出现裸数值(渲染布局常量除外);
* - 快进仿真器(scripts/sim-scan.mjs)直接吃本表跑参数扫描——改数值=改这里,逻辑结构零改动;
* - 全部量值为草案锚〔按四判据扫描收敛锁值,修订走质量轨校准〕;
* - 距离单位 = 逻辑像素(视口 390×844 基准),时间单位 = 秒。
*
* 【M2 增量】武器 12(各 8 级,五族索敌)/ 被动 14(各 5 级)/ 进化 12(满级+对应被动≥3,
* 机制跃迁非纯数值)/ 难度表 D0D5(本期启用 D0/D1)/ 暴击(手 4 事件源)/
* 全屏收割道具「聚灵珠」(手 6/手 8 事件源)。派生语义单一实现 = src/build-model.js。
* 【M3 增量】20 分钟正式波表(WAVES 重排,含 18:00 放量收割期)/ 潮汐脉冲(TIDE)/
* 精英词缀(ELITE+AFFIXES 6)/ 图 1 双 Boss(BOSSES,战技组入表)/ 局内事件 4 种(EVENTS)/
* XP 经济二次曲线(单局升级 2228 次锚)/ 难度表增词缀密度轴(eliteMul/affixMax)。
* 【M5 增量·检查点1=数据层灌表(占位)】MAPS 5 图(裂谷原/不周山/昆仑墟/归墟/钟山,各带波表引用/
* 敌混/Boss 引用/解锁条件)/ 敌表扩至 32 兽(ENEMIES,山海经兽谱五图分布)/ Boss 扩至 10(5 图×2,
* BOSSES)/ 难度 D2D5 解锁条件占位 + 波表压缩轴占位(waveCompress)/ map25 占位波表(WAVES_MAP2..5)。
* ⚠️ 本检查点只灌数据层:sim.js 仍硬编码图 1(读全局 WAVES + 全 BOSSES 表按 atS 出场),不读 MAPS/
* 新图波表;新增兽/新图 Boss 均不进图 1 行为路径(新 Boss atS 占位超图 1 局时长 ROUND_S=1200、新兽
* 不进图 1 波表 mix)→ 游戏行为零变化,回归安全。占位数值/占位 sprite 均注释标「待平衡/待美术」,
* sim mapId 参数化 + meta 解锁接线 + 真平衡扫描留待后续检查点。
*/
'use strict';
/** 逻辑视口(竖屏 390×844,与 L1 host-config 同值;sim 只用来推镜头与出怪环)。 */
export const VIEW = { w: 390, h: 844 };
/**
* M3 一局时长(秒):20 分钟正式局。胜利线 = 击杀终 Boss(§3.1「标准局 20:00 出终 Boss,
* 击杀即胜利结算」),不再按撑时结算;ROUND_S 作为终 Boss 出场时刻与 UI 进度基准。
*/
export const ROUND_S = 1200;
/** 玩家(持符巡山使)。 */
export const PLAYER = {
hp: 100, // 生命上限
speed: 120, // 移速(px/s;被动乘区放大)
r: 12, // 碰撞半径
hurtIframe: 0.25, // 受击后短无敌窗(秒)——防同帧多怪叠伤秒杀
};
/**
* 竞技场边界(图 1 战场世界尺寸)。中心对称原点:玩家出生点 (0,0) = 场心,
* 世界坐标范围 x∈[-w/2, w/2]、y∈[-h/2, h/2]。
* - sim 用它给玩家走位 clamp(留 player.r 边距,贴边不穿墙);
* - render 用它做镜头 clamp(竞技场≥视口,镜头不出世界边)+ 整幅战场背景图铺设范围。
* 尺寸 1560×2960 = 竖屏战场(约 4 视口宽 × 3.5 视口高),与背景图 bg-map1-arena-01 同尺寸。
*/
export const ARENA = { w: 1560, h: 2960 };
/** 虚拟摇杆(手 13 断言的参数面;UI 层消费,sim 只收归一化方向)。 */
export const JOYSTICK = {
radius: 64, // 摇杆逻辑半径(px)
deadzoneRatio: 0.12, // 死区 = 半径的 12%(手 1:死区 ≤12%)
};
/** 暴击(手 4 事件源):总暴击率 = 被动 crit + 武器 innate critAdd,伤害 ×mul。 */
export const CRIT = { mul: 2.0, chanceCap: 0.8 };
/** build 槽位(§11 暂停 build 总览:武器 6 槽 + 被动 6 槽)。 */
export const SLOTS = { weapons: 6, passives: 6 };
/**
* 三选一权重池(进化项按条件强制进池)。
* ownedWeight:持有件(升级项)的抽取权重(新件恒 1)——偏向已持有 = 构筑能成型;
* 均匀池实测(M2 首轮扫描)定向 build 常整局抽不到主打件,新件洪水稀释构筑。
*/
export const OFFER = { count: 3, ownedWeight: 2 };
/** 进化条件:武器满级 且 对应被动 ≥ 本级(§3.1 验收用例原文口径)。 */
export const EVO_PASSIVE_MIN = 3;
/** 链式跳击索敌半径(进化机制「链」共用)。 */
export const CHAIN_R = 130;
/**
* 全屏收割道具「聚灵珠」(手 8:触发全图磁吸;手 6 族:拾取闪屏+音效档)。
* 击杀掉落:冷却窗(minIntervalS)过后每杀 dropChance 概率掉 1 颗;
* 不受磁吸(必须走位踩取=拾取决策),接触即触发:全部散落灵晶转飞行态。
*/
export const HARVEST = {
dropChance: 0.03, // 冷却后每次击杀的掉落概率
minIntervalS: 40, // 两颗之间的最短间隔(秒)
ttlS: 30, // 珠在场存续(秒;过期消散腾出场上限,防远珠堵死后续掉落)
r: 14, // 道具半径(接触拾取判定 = r + player.r)
};
/**
* ══════════════════ 武器表(12 件 × 8 级,五族索敌全覆盖)══════════════════
* family:nearest 最近敌 | random 随机敌 | movedir 朝移动方向 | orbit 环绕自身 | place 原地投放
* kind:proj 投射物 | zone 区域(orbit/place 都是 zone:按 tick 对半径内敌结算)
* levels:8 行,dm=伤害乘区(等级系数,Lv1=1.0→Lv8 合成 ≈3.2,§8.1)/ ca=+弹数(累计)。
* evo:进化(条件=满级+passive≥EVO_PASSIVE_MIN):mods 数值面 + 机制跃迁字段(chain/explode/
* dot/slow/mirror/gemPull——非纯数值,§5.2);理论 DPS 跃迁带 1.82.5(build-model 单测锁死)。
* 命名纪律(山海设定 v1 §1):武器=符箓法器,从符箓五行取名;进化名用古籍公版意象
* (毕方=山海经异兽,白虹贯日/荧惑=古天文语),零现代作品词。
*/
const LV = [1.0, 1.22, 1.45, 1.7, 2.0, 2.35, 2.75, 3.2]; // 标准等级系数(纯伤害路)
/**
* 生成 8 级行。caAt = {级: +弹数};respreadCount 给定(proj 族)时,
* 加弹级之后的伤害乘区按弹数回摊(dm×合成弹数/基础弹数 恒 = 标准曲线,等级系数不超 3.2 带);
* zone 族不回摊(理论 DPS 用单触点模型,加环/加桩是群体收益,不进等级系数)。
*/
const lvRows = (caAt, respreadCount) => LV.map((target, i) => {
const ca = Object.keys(caAt || {}).filter((k) => Number(k) <= i + 1).reduce((s, k) => s + caAt[k], 0);
const dm = respreadCount ? target * respreadCount / (respreadCount + ca) : target;
return { dm: Math.round(dm * 1000) / 1000, ca };
});
export const WEAPONS = [
{
id: 'leifu', name: '雷符链', desc: '掷出雷符,追击最近的异兽',
family: 'nearest', kind: 'proj', maxLv: 8,
base: { dmg: 13, interval: 0.55, count: 1, projSpeed: 420, projR: 6, pierce: 1, life: 1.6, searchR: 560 },
levels: lvRows(),
evo: {
id: 'evo_leifu', name: '九霄雷契', passive: 'haste',
desc: '雷符成契,一化为二,命中处雷光链跳',
mods: { dmgMul: 1.0, countAdd: 1, chain: { n: 2, dmgPct: 0.5 } },
},
},
{
id: 'jinge', name: '金戈符', desc: '重金之符,贯穿成列的兽潮',
family: 'nearest', kind: 'proj', maxLv: 8,
base: { dmg: 30, interval: 1.15, count: 1, projSpeed: 520, projR: 7, pierce: 3, life: 1.2, searchR: 560 },
levels: lvRows(),
evo: {
id: 'evo_jinge', name: '白虹贯日', passive: 'atk',
desc: '金气化虹,直贯到底,无物可挡',
mods: { dmgMul: 2.1, pierceAdd: 96, projRMul: 1.6 },
},
},
{
id: 'hanyuan', name: '寒渊符', desc: '寒渊之水凝箭,中者滞行',
family: 'nearest', kind: 'proj', maxLv: 8,
base: { dmg: 11.5, interval: 0.6, count: 1, projSpeed: 400, projR: 6, pierce: 2, life: 1.5, searchR: 560, slow: { pct: 0.22, s: 0.9 } },
levels: lvRows(),
evo: {
id: 'evo_hanyuan', name: '玄冰锁渊', passive: 'duration',
desc: '寒气入髓,冰晶炸裂,群兽皆缓',
mods: { dmgMul: 1.9, slow: { pct: 0.4, s: 1.6 }, explode: { r: 44, dmgPct: 0.35 } },
},
},
{
id: 'fentian', name: '焚天羽', desc: '火羽自天而落,炸开一团焚焰',
family: 'random', kind: 'proj', maxLv: 8,
base: { dmg: 19, interval: 0.9, count: 2, projSpeed: 340, projR: 7, pierce: 1, life: 1.8, searchR: 520, explode: { r: 36, dmgPct: 0.6 } },
levels: lvRows({ 5: 1 }, 2),
evo: {
id: 'evo_fentian', name: '毕方燎原', passive: 'area',
desc: '毕方振翅,焰羽成原,余火灼烧',
mods: { dmgMul: 1.6, explode: { r: 64, dmgPct: 0.8 }, dot: { dpsPct: 0.6, s: 2.0 } },
},
},
{
id: 'xinghuo', name: '星火符', desc: '撒出一把星火,四下点射',
family: 'random', kind: 'proj', maxLv: 8,
base: { dmg: 6.6, interval: 0.5, count: 3, projSpeed: 380, projR: 5, pierce: 1, life: 1.4, searchR: 520 },
levels: lvRows({ 4: 1, 7: 1 }, 3),
evo: {
id: 'evo_xinghuo', name: '荧惑连珠', passive: 'multi',
desc: '星火连珠,溅火跳灼近旁',
mods: { dmgMul: 1.45, countAdd: 2, chain: { n: 1, dmgPct: 0.6 } },
},
},
{
id: 'tianlei', name: '天雷引', desc: '引天雷落于随机异兽,天生易出重击',
family: 'random', kind: 'proj', maxLv: 8,
base: { dmg: 32, interval: 0.8, count: 1, projSpeed: 1600, projR: 8, pierce: 1, life: 0.5, searchR: 520, critAdd: 0.10, explode: { r: 40, dmgPct: 0.35 } },
levels: lvRows(),
evo: {
id: 'evo_tianlei', name: '九天惊雷', passive: 'crit',
desc: '雷霆落处炸开雷环,重击更烈',
mods: { dmgMul: 1.7, explode: { r: 52, dmgPct: 0.5 }, critAdd: 0.15 },
},
},
{
id: 'fengren', name: '风刃符', desc: '沿走位方向斩出风刃,穿行而过',
family: 'movedir', kind: 'proj', maxLv: 8,
base: { dmg: 18, interval: 0.7, count: 1, projSpeed: 460, projR: 7, pierce: 4, life: 1.5 },
levels: lvRows({ 6: 1 }, 1),
evo: {
id: 'evo_fengren', name: '罡风裂空', passive: 'speed',
desc: '罡风前后齐出,刃幅更阔',
mods: { dmgMul: 1.9, projRMul: 1.4, mirror: true },
},
},
{
id: 'poyue', name: '破岳戟', desc: '掷出沉重戟符,推碾一线',
family: 'movedir', kind: 'proj', maxLv: 8,
base: { dmg: 44, interval: 1.5, count: 1, projSpeed: 300, projR: 10, pierce: 5, life: 1.6 },
levels: lvRows(),
evo: {
id: 'evo_poyue', name: '崩山裂岳', passive: 'pierce',
desc: '戟落如山崩,每击震裂四旁',
mods: { dmgMul: 1.9, explode: { r: 56, dmgPct: 0.6 }, pierceAdd: 4 },
},
},
{
id: 'shanzi', name: '山字盾环', desc: '山字符化盾,绕身而转',
family: 'orbit', kind: 'zone', maxLv: 8,
base: { dmg: 10.5, tick: 0.4, count: 2, interval: 4.0, life: 4.0, zoneR: 18, orbitR: 70, orbitAv: 2.4 },
levels: lvRows({ 4: 1, 7: 1 }),
evo: {
id: 'evo_shanzi', name: '五岳镇环', passive: 'armor',
desc: '盾环化岳,环阔而沉,触者皆缓',
mods: { dmgMul: 2.0, orbitRMul: 1.25, zoneRMul: 1.3, slow: { pct: 0.25, s: 0.8 } },
},
},
{
id: 'xuanming', name: '玄冥轮', desc: '玄水成轮,急旋割群',
family: 'orbit', kind: 'zone', maxLv: 8,
base: { dmg: 7, tick: 0.3, count: 3, interval: 3.5, life: 3.5, zoneR: 15, orbitR: 52, orbitAv: 3.6, slow: { pct: 0.15, s: 0.5 } },
levels: lvRows({ 5: 1 }),
evo: {
id: 'evo_xuanming', name: '玄冥噬月', passive: 'cooldown',
desc: '轮影蚀物,沾者溺蚀不止',
mods: { dmgMul: 1.7, dot: { dpsPct: 0.5, s: 1.5 }, slow: { pct: 0.3, s: 1.0 } },
},
},
{
id: 'fuling', name: '缚灵桩', desc: '就地立桩,桩阵电缚近旁异兽',
family: 'place', kind: 'zone', maxLv: 8,
base: { dmg: 19, tick: 0.45, count: 1, interval: 3.5, life: 3.0, zoneR: 110 },
levels: lvRows({ 5: 1 }),
evo: {
id: 'evo_fuling', name: '锁山镇桩', passive: 'regen',
desc: '桩成锁山之阵,阵内皆滞',
mods: { dmgMul: 1.75, zoneRMul: 1.3, lifeMul: 7 / 6, slow: { pct: 0.3, s: 0.6 } },
},
},
{
id: 'zhendi', name: '震地符', desc: '按符入地,周身地脉阵阵震荡',
family: 'place', kind: 'zone', maxLv: 8,
base: { dmg: 38, tick: 0.6, count: 1, interval: 4.0, life: 3.4, zoneR: 110 },
levels: lvRows(),
evo: {
id: 'evo_zhendi', name: '撼山符阵', passive: 'magnet',
desc: '地脉长鸣,震波连绵,灵晶应震而聚',
mods: { dmgMul: 1.4, tickMul: 0.8, lifeMul: 4 / 3, gemPull: true },
},
},
];
/**
* ══════════════════ 被动表(14 件 × 5 级)══════════════════
* effect 语义由 build-model.deriveWeapon / derivePlayer 消费(每级线性叠,数值全在 per):
* dmg 伤害乘区 | interval 投射间隔乘区(proj 族) | extraChance 每轮追加一发概率 |
* area 半径乘区(弹半径/区域半径/爆裂半径) | crit 暴击率 | move 移速 | armor 受伤减免 |
* regen 每秒回复 | magnet 磁吸半径 | cycle 区域族循环间隔乘区(zone 族) |
* projSpeed 弹速/环转速 | pierce +穿透(proj 族) | duration 存续乘区 | xpGain 灵晶价值乘区。
* M0 池 5(atk/rate/count/speed/magnet)重调进 14 池:命名沿用,量值按 14 轴乘区重标。
*/
export const PASSIVES = [
{ id: 'atk', name: '符力灌注', desc: '所有符器伤害 +12%', maxLv: 5, effect: 'dmg', per: 0.12 },
{ id: 'haste', name: '疾雷咒', desc: '投射符器施放间隔 -6%', maxLv: 5, effect: 'interval', per: 0.06 },
{ id: 'multi', name: '连环符', desc: '每轮 15% 概率追加一发', maxLv: 5, effect: 'extraChance', per: 0.15 },
{ id: 'area', name: '扩符纹', desc: '符器作用范围 +10%', maxLv: 5, effect: 'area', per: 0.10 },
{ id: 'crit', name: '破煞诀', desc: '重击率 +6%(重击伤害翻倍)', maxLv: 5, effect: 'crit', per: 0.06 },
{ id: 'speed', name: '踏山步', desc: '移速 +7%', maxLv: 5, effect: 'move', per: 0.07 },
{ id: 'armor', name: '山纹甲', desc: '受到的接触伤害 -7%', maxLv: 5, effect: 'armor', per: 0.07 },
{ id: 'regen', name: '回春露', desc: '每秒回复 0.5 点生命', maxLv: 5, effect: 'regen', per: 0.5 },
{ id: 'magnet', name: '引灵纹', desc: '灵晶吸取半径 +30%', maxLv: 5, effect: 'magnet', per: 0.30 },
{ id: 'cooldown', name: '凝息诀', desc: '盾环/桩阵类循环间隔 -6%', maxLv: 5, effect: 'cycle', per: 0.06 },
{ id: 'projspeed', name: '疾风引', desc: '弹速与环转速 +12%', maxLv: 5, effect: 'projSpeed', per: 0.12 },
{ id: 'pierce', name: '透甲箓', desc: '投射符器穿透 +1', maxLv: 5, effect: 'pierce', per: 1 },
{ id: 'duration', name: '驻灵符', desc: '符器存续时长 +12%', maxLv: 5, effect: 'duration', per: 0.12 },
{ id: 'xpgain', name: '纳灵诀', desc: '灵晶价值 +8%', maxLv: 5, effect: 'xpGain', per: 0.08 },
];
/**
* 难度表 D0D5(§5.2「数值曲线抬升+词缀密度+波表压缩」)。
* M3 增词缀密度轴:eliteMul = 精英出现概率乘区;affixMax = 单个精英词缀叠加上限(§5.2「词缀可叠加」)。
* M5 检查点1 增量(占位):
* 【waveCompress 波表压缩轴·占位待平衡】§5.2「波表压缩」第三轴的表化——高难度把波表时间轴压缩
* (同量怪在更短局内时长涌出,节奏更紧)。1.0 = 不压缩(基准 20 分钟局);越小节奏越压。
* d0/d1 恒 1.0(本期启用档不压);d2d5 占位递减值,真值待 M5 平衡线扫描。sim 当前不读本轴
* (波表时间轴接线留待 sim mapId 参数化同期),故加此字段零行为变化。
* 【unlock 解锁条件·占位待 meta 解锁逻辑】d2d5 的 meta 解锁条件声明,结构对齐 ROLES.unlock
* ({stat,gte}),供后续 meta 解锁接线复用 isUnlocked 模式;note 标明占位语义。locked 本检查点
* 保持 true 不动——出击页可选难度门(game-logic.js:119/134/337/467 消费 locked)行为零变化,
* 待 meta 解锁逻辑接线后按 unlock 条件动态置 locked=false。 pacing 锚 §5.3:D2D3 = 第10h 攻坚,
* D4/D5 = 超承诺长尾。
*/
export const DIFFICULTY = {
d0: { name: '平潮', hpMul: 1.0, dpsMul: 1.0, rateMul: 1.0, speedMul: 1.0, eliteMul: 1.0, affixMax: 1, waveCompress: 1.0, locked: false },
d1: { name: '涌潮', hpMul: 1.15, dpsMul: 1.2, rateMul: 1.45, speedMul: 1.08, eliteMul: 1.3, affixMax: 2, waveCompress: 1.0, locked: false },
d2: { name: '怒潮', hpMul: 2.0, dpsMul: 1.9, rateMul: 1.7, speedMul: 1.18, eliteMul: 1.6, affixMax: 2, waveCompress: 0.9, locked: true,
unlock: { stat: 'mapWin', gte: 2, note: '占位待 meta 解锁逻辑(通关 2 图解怒潮)' } },
d3: { name: '狂潮', hpMul: 2.8, dpsMul: 2.1, rateMul: 2.0, speedMul: 1.22, eliteMul: 2.0, affixMax: 3, waveCompress: 0.82, locked: true,
unlock: { stat: 'mapWin', gte: 4, note: '占位待 meta 解锁逻辑(通关 4 图解狂潮)' } },
d4: { name: '噬潮', hpMul: 3.8, dpsMul: 2.4, rateMul: 2.5, speedMul: 1.26, eliteMul: 2.5, affixMax: 4, waveCompress: 0.74, locked: true,
unlock: { stat: 'diffClear', gte: 2, note: '占位待 meta 解锁逻辑(D2/D3 各通关若干解噬潮,长尾)' } },
d5: { name: '灭潮', hpMul: 5.0, dpsMul: 2.7, rateMul: 3.1, speedMul: 1.3, eliteMul: 3.0, affixMax: 5, waveCompress: 0.66, locked: true,
unlock: { stat: 'diffClear', gte: 4, note: '占位待 meta 解锁逻辑(D2D4 深通解灭潮,超承诺长尾)' } },
};
/**
* 经验/等级曲线:升到 L+1 需要的灵晶价值 = base + step×(L-1) + quad×(L-1)²。
* M3 加二次项:20 分钟局收入随波表/build 超线性增长,线性曲线会把升级次数推到 40+;
* 目标锚 = §8.1「升级间隔开局 ~15s 缓升到 15 分钟 ~45s,单局升级 2228 次」〔扫描回填校准〕。
*/
export const XP = {
base: 6,
step: 3,
quad: 0.35,
gemMagnetR: 80, // 基础磁吸半径(px;引灵纹被动放大;M2 调:60→80,风筝路过可收)
flyMin: 0.35, // 磁吸飞行最短时长(秒)——手 8:0.350.6s ease-in 到达
flyMax: 0.6, // 磁吸飞行最长时长(秒;全图收割统一取此值)
};
/**
* 敌表(M5 扩至 32 兽 = 图 1 基础三兽 + 29 兽占位;词缀精英/双 Boss 见 AFFIXES/BOSSES)。
* dps = 接触时对玩家的每秒伤害;gem = 掉落灵晶价值(×波表 gemMul 经济乘区)。
* 五图分布(§5.2 各图专属敌表;map 字段 = 该兽主属图,供 MAPS.enemyMix 与后续 sim 参数化引用):
* map1 裂谷原:狰/梼杌/穷奇(现 3 兽,行为锁定不变);map2 不周山 6;map3 昆仑墟 6;
* map4 归墟 6;map5 钟山 11。每个新兽都被某图 MAPS.enemyMix 引用,无孤儿条目。
*
* ── 占位纪律(M5 检查点1)──
* 【数值占位·待平衡】新兽 hp/speed/dps/r/gem 均按「图序基础抬升 + 定位(快脆/中坚/坦克)」铺的
* 草案锚,非真平衡值;真值待 M5 平衡线按 §8.1 单位 HP(w)=H0×g^w 曲线逐图扫描收敛。图 1 三兽
* 数值保持 M3 原值不动(已随金标收敛,改动会破坏 sim 硬编码图 1 行为与既有测试)。
* 【sprite 占位·待美术】现有 render 层按 type 查内置帧表,查不到自动 fallback 到 BEAST.zheng
* (render.js:554)/程序色块 C.qiongqi(render.js:558),故新兽暂无专属帧也不崩渲染——即当前
* sprite 占位策略 = 复用 beasts 图集帧循环(zheng 帧)+ 程序色兜底。各兽专属 6 帧(§9 异兽 32×6)
* 待美术管线批产后补进 render BEAST 帧表;balance 层不内联 sprite 字段(渲染映射归 render 单点)。
*/
export const ENEMIES = {
// ── map1 裂谷原(基础三兽,M3 原值锁定;sim 图 1 波表 mix 实际敌混,改动破坏现行为)──
zheng: { name: '狰', hp: 22, speed: 88, r: 10, dps: 9, gem: 1, map: 'map1' }, // 快而脆:压走位
taowu: { name: '梼杌', hp: 50, speed: 60, r: 14, dps: 13, gem: 2, map: 'map1' }, // 中坚
qiongqi: { name: '穷奇', hp: 140, speed: 40, r: 20, dps: 18, gem: 4, map: 'map1' }, // 慢坦克:压火力
// ── map2 不周山(天柱折·焦土火山;基础血量 ≈图1×1.3。数值占位待平衡)──
bifang: { name: '毕方', hp: 30, speed: 92, r: 10, dps: 11, gem: 1, map: 'map2' }, // 火鸟·快脆(占位)
gudiao: { name: '蛊雕', hp: 65, speed: 58, r: 15, dps: 15, gem: 2, map: 'map2' }, // 雕身·中坚(占位)
zhuyan: { name: '朱厌', hp: 45, speed: 80, r: 12, dps: 13, gem: 2, map: 'map2' }, // 兆兵·快中(占位)
dangkang: { name: '当康', hp: 26, speed: 95, r: 9, dps: 8, gem: 1, map: 'map2' }, // 兆丰·脆(占位)
mingshe: { name: '鸣蛇', hp: 55, speed: 66, r: 13, dps: 14, gem: 2, map: 'map2' }, // 蛇·中(占位)
taotie: { name: '饕餮', hp: 180, speed: 38, r: 21, dps: 20, gem: 4, map: 'map2' }, // 贪食·坦克(占位)
// ── map3 昆仑墟(昆仑守卫;基础血量 ≈图1×1.7。数值占位待平衡)──
yingzhao: { name: '英招', hp: 40, speed: 90, r: 11, dps: 14, gem: 2, map: 'map3' }, // 昆仑卫·快(占位)
liwu: { name: '陆吾', hp: 85, speed: 55, r: 16, dps: 18, gem: 3, map: 'map3' }, // 昆仑神·中坚(占位)
zhujian: { name: '诸犍', hp: 36, speed: 96, r: 10, dps: 13, gem: 2, map: 'map3' }, // 快(占位)
zhuai: { name: '诸怀', hp: 70, speed: 62, r: 15, dps: 16, gem: 3, map: 'map3' }, // 中(占位)
yayu: { name: '猰貐', hp: 240, speed: 36, r: 22, dps: 23, gem: 5, map: 'map3' }, // 食人·坦克(占位)
xiezhi: { name: '獬豸', hp: 90, speed: 58, r: 16, dps: 17, gem: 3, map: 'map3' }, // 中坚(占位)
// ── map4 归墟(深渊之水;基础血量 ≈图1×2.2。数值占位待平衡)──
huashe: { name: '化蛇', hp: 50, speed: 94, r: 11, dps: 16, gem: 2, map: 'map4' }, // 水蛇·快(占位)
feiyi: { name: '肥遗', hp: 95, speed: 60, r: 16, dps: 20, gem: 3, map: 'map4' }, // 双头蛇·中(占位)
luoyu: { name: '蠃鱼', hp: 40, speed: 88, r: 10, dps: 14, gem: 2, map: 'map4' }, // 鱼·脆(占位)
fuzhu: { name: '夫诸', hp: 55, speed: 90, r: 12, dps: 17, gem: 2, map: 'map4' }, // 兆水·快(占位)
changyou: { name: '长右', hp: 110, speed: 56, r: 17, dps: 21, gem: 3, map: 'map4' }, // 中(占位)
xiangliu: { name: '相柳', hp: 320, speed: 34, r: 24, dps: 26, gem: 6, map: 'map4' }, // 九首·坦克(占位)
// ── map5 钟山(终图·混沌;基础血量 ≈图1×3。数值占位待平衡)──
hundun: { name: '混沌', hp: 420, speed: 32, r: 26, dps: 30, gem: 7, map: 'map5' }, // 巨坦(占位)
jiuwei: { name: '九尾', hp: 60, speed: 98, r: 11, dps: 18, gem: 2, map: 'map5' }, // 九尾狐·快脆(占位)
tiangou: { name: '天狗', hp: 70, speed: 95, r: 12, dps: 19, gem: 3, map: 'map5' }, // 快(占位)
bashe: { name: '巴蛇', hp: 500, speed: 30, r: 28, dps: 32, gem: 8, map: 'map5' }, // 吞象·巨坦(占位)
fei: { name: '蜚', hp: 120, speed: 64, r: 17, dps: 23, gem: 3, map: 'map5' }, // 兆疫·中(占位)
qitu: { name: '鵸鵌', hp: 55, speed: 92, r: 11, dps: 17, gem: 2, map: 'map5' }, // 鸟·快(占位)
shusi: { name: '数斯', hp: 45, speed: 86, r: 10, dps: 15, gem: 2, map: 'map5' }, // 脆(占位)
yong: { name: '颙', hp: 130, speed: 58, r: 18, dps: 24, gem: 4, map: 'map5' }, // 中(占位)
lilu: { name: '狸力', hp: 65, speed: 90, r: 12, dps: 18, gem: 2, map: 'map5' }, // 快(占位)
huahuai: { name: '猾褢', hp: 140, speed: 60, r: 18, dps: 25, gem: 4, map: 'map5' }, // 中(占位)
baize: { name: '白泽', hp: 160, speed: 56, r: 19, dps: 26, gem: 5, map: 'map5' }, // 瑞兽·中坚(占位)
};
/**
* 波表(M3:20 分钟正式局):分段线性到达率 λ(t),rate 全程只升不降
* (§3.1「波表驱动的同屏敌数按分钟单调不减,直到 18:00 后放量收割期」——收割期 rate 跳升、
* 个体 hpMul 回落 = 割草爽感放量,rate 单调性含收割期整段成立,机验断言在 build-tables 测试);
* mix = 各敌种权重(rng 按权重抽);hpMul/speedMul/gemMul = 该波出生个体的成长与掉晶乘区(经济随波走:后期灵晶增值,等级供给跟上压力需求)
* (§8.1 单位 HP(w)=H0×g^w 的表化,本表逐行 g≈1.101.13;速度爬坡是反风筝压力源——
* 后期快敌须能追上基础移速的玩家,否则纪律走位可无伤挂机)。潮汐脉冲(×2.5)另见 TIDE,不进本表。
* 校准锚:静止玩家(P0)须在 90 秒内被压死(§3.1);D0 前 60s 快敌速度 < 玩家基速(S2 锚);
* 首杀 ≤10s 由首段 rate 保证(手 11)。
*/
export const WAVES = [
{ t: 0, rate: 0.9, hpMul: 1.0, speedMul: 1.0, gemMul: 1.0, mix: { zheng: 1.0 } },
{ t: 45, rate: 1.5, hpMul: 1.1, speedMul: 1.02, gemMul: 1.0, mix: { zheng: 0.9, taowu: 0.1 } },
{ t: 90, rate: 1.9, hpMul: 1.2, speedMul: 1.05, gemMul: 1.15, mix: { zheng: 0.85, taowu: 0.15 } },
{ t: 150, rate: 2.3, hpMul: 1.32, speedMul: 1.08, gemMul: 1.3, mix: { zheng: 0.75, taowu: 0.25 } },
{ t: 240, rate: 2.7, hpMul: 1.42, speedMul: 1.1, gemMul: 1.45, mix: { zheng: 0.65, taowu: 0.3, qiongqi: 0.05 } },
{ t: 330, rate: 3.1, hpMul: 1.55, speedMul: 1.13, gemMul: 1.55, mix: { zheng: 0.6, taowu: 0.3, qiongqi: 0.1 } },
{ t: 420, rate: 3.5, hpMul: 1.68, speedMul: 1.15, gemMul: 1.65, mix: { zheng: 0.55, taowu: 0.32, qiongqi: 0.13 } },
{ t: 540, rate: 3.9, hpMul: 1.82, speedMul: 1.18, gemMul: 1.75, mix: { zheng: 0.5, taowu: 0.34, qiongqi: 0.16 } },
{ t: 660, rate: 4.3, hpMul: 1.95, speedMul: 1.2, gemMul: 1.85, mix: { zheng: 0.5, taowu: 0.32, qiongqi: 0.18 } },
{ t: 780, rate: 4.7, hpMul: 2.05, speedMul: 1.22, gemMul: 1.95, mix: { zheng: 0.48, taowu: 0.32, qiongqi: 0.2 } },
{ t: 900, rate: 5.1, hpMul: 2.15, speedMul: 1.24, gemMul: 2.05, mix: { zheng: 0.46, taowu: 0.32, qiongqi: 0.22 } },
{ t: 1020, rate: 5.5, hpMul: 2.25, speedMul: 1.26, gemMul: 2.15, mix: { zheng: 0.45, taowu: 0.33, qiongqi: 0.22 } },
// ── 18:00 放量收割期(§3.1):密度跳升 + 个体血量回落 + 多出脆皮(割草放量)──
{ t: 1080, rate: 8.5, hpMul: 1.9, speedMul: 1.24, gemMul: 2.15, mix: { zheng: 0.6, taowu: 0.28, qiongqi: 0.12 } },
{ t: 1140, rate: 9.5, hpMul: 2.0, speedMul: 1.25, gemMul: 2.15, mix: { zheng: 0.6, taowu: 0.28, qiongqi: 0.12 } },
];
/**
* 潮汐脉冲(§8.1:λ(t) 爬坡 + 潮汐脉冲 ×2.5,6090s 一次):
* 自 startS 起,每隔 [minGapS,maxGapS](受控 rng 取)触发一次,持续 durS 内出怪率 ×mul。
*/
export const TIDE = { startS: 60, minGapS: 60, maxGapS: 90, mul: 2.5, durS: 8 };
/**
* 精英(§5.2 精英词缀;词缀强化个体):普通敌种 × 基础精英乘区 + 1..affixMax 个词缀。
* 出现概率自 startS 起从 baseChance 线性爬到 maxChance(rampEndS 处),×难度 eliteMul。
*/
export const ELITE = {
startS: 120,
baseChance: 0.015,
maxChance: 0.08,
rampEndS: 900,
extraAffixChance: 0.35, // 第 2+ 个词缀的逐个追加概率(受难度 affixMax 封顶)
hpMul: 2.8, dmgMul: 1.4, gemMul: 4, rMul: 1.3, speedMul: 0.95,
};
/** 词缀池(6 种,§5.2;命名半文半白,设定 v1 构词)。字段即效果,sim 按键消费。 */
export const AFFIXES = [
{ id: 'xunji', name: '迅疾', speedMul: 1.4 }, // 快:压走位
{ id: 'tiejia', name: '铁甲', hpMul: 2.0 }, // 厚:压火力
{ id: 'baolie', name: '暴烈', dpsMul: 1.7 }, // 疼:压贴身
{ id: 'zaisheng', name: '再生', regenPctPerS: 0.025 }, // 磨:压持续输出
{ id: 'panshi', name: '磐石', slowResist: 0.7 }, // 稳:克减速流(减速效果 ×0.3)
{ id: 'liebian', name: '裂变', onDeathSpawn: { type: 'zheng', n: 2, hpMul: 0.5, gemMul: 0 } }, // 分:死后裂出小兽
];
/**
* 图 1「裂谷原」双 Boss(§3.1:10:00 中 Boss / 20:00 终 Boss,击杀终 Boss 即胜利)。
* 战技组全入表:charge(蓄势定向冲撞:telegraphS 减速蓄势 → 锁定蓄势起点方向冲刺 durS,可侧移躲)/
* summon(周身召唤小兽)/ enrage(血量阈值狂化,一次性乘区)。
* 命名(设定 v1 §1):狰为图 1 基础兽族 → 中 Boss「狰王·赤鬣」;终 Boss 取山海经公版
* 异兽「九婴」原创演绎。Boss 个体吃难度 hpMul/dpsMul;slowResist 防减速流把 Boss 钉死;
* 不进同屏活敌上限、不受软分离推挤;gem 掉落拆成 gemPer/颗的灵晶堆(磁吸玩法)。
*/
/*
* ── 金标⑧win「九婴数值调到普通人可用」调参(round-8,2026-07-24)──────────────────────────
* 只动数值、不动机制(机制本就全表驱动:sim.js 按本表 charge/summon/enrage 键消费,玩法逻辑零改)。
* 依据 round-7 实测的「dps/存活窗不等式」:普通 build 在安全距(≥250px)的 sustained dps ≈107,
* 而九婴原 hp7400 → 击杀需 ≈69s,远 ≫ 普通人在贴身/冲撞下的存活窗(≈20s),故 win 不可达。
* 调法 = 双向收口(降击杀时间 + 抬存活窗),不碰武器/被动以免扰动⑦c2 收敛:
* ① 降击杀时间:九婴 hp 7400→3600(107dps 下 ≈34s 可斩,落进存活窗)。
* ② 抬存活窗:九婴 dps 60→30(贴身毙命 1.67s→3.3s);冲撞四件——cooldown 8→12(更疏)、
* telegraphS 0.8→1.3(预警拉长,普通人读得出 + 侧闪)、speedMul 5.5→3.6(264→173px/s,可侧移躲)、
* durS 0.75→0.6(横扫行程更窄);狂化削平 speedMul 1.35→1.2 / dpsMul 1.4→1.25。
* ③ 狰王(伴随中 Boss)hp 3000→2000、charge speedMul 5.2→3.8:让普通人在 6001200 窗就能斩杀,
* 避免九婴战两 Boss 分火力、把本就不富裕的存活窗再撕一道。
*/
export const BOSSES = [
{
id: 'zhengwang', name: '狰王·赤鬣', atS: 600,
hp: 2000, speed: 55, r: 30, dps: 38, gem: 60, gemPer: 4, // hp 3000→2000:⑧win 让普通人在 6001200 窗斩杀,免与九婴分火力
slowResist: 0.8, dropHarvest: true, final: false, map: 'map1',
skills: {
charge: { cooldown: 9, telegraphS: 0.9, speedMul: 3.8, durS: 0.7 }, // speedMul 5.2→3.8:冲撞减速,普通人可侧移躲
summon: { cooldown: 14, n: 6, type: 'zheng' },
},
},
{
id: 'jiuying', name: '九婴', atS: 1200,
hp: 3600, speed: 48, r: 38, dps: 30, gem: 100, gemPer: 4, // hp 7400→3600(降击杀时间,107dps≈34s)/ dps 60→30(抬存活窗,贴身毙命 1.67s→3.3s)
slowResist: 0.8, dropHarvest: false, final: true, map: 'map1',
skills: {
charge: { cooldown: 12, telegraphS: 1.3, speedMul: 3.6, durS: 0.6 }, // 冲撞四件:cd 8→12(更疏)/预警 0.8→1.3(可读+侧闪)/速 5.5→3.6(264→173px/s 可躲)/程 0.75→0.6(横扫更窄)
summon: { cooldown: 18, n: 5, type: 'taowu' },
enrage: { hpPct: 0.3, speedMul: 1.2, dpsMul: 1.25 }, // 狂化削平:speedMul 1.35→1.2 / dpsMul 1.4→1.25
},
},
/*
* ── M5 检查点1:map25 各双 Boss 占位(共 8,5 图×2 = 10 含图1 双 Boss)──────────────────
* 【atS 占位超界·保回归】新 Boss atS 全设 100000(≫ 图1 局时长 ROUND_S=1200),sim 硬编码图1
* 按全 BOSSES 表 atS 出场(sim.js:637),故新 Boss 在图1 局永不 spawn → 行为零变化、测试不破。
* map 字段标归属图;真 atS(中 Boss≈600 / 终 Boss≈1200)待 sim mapId 参数化后按图配。
* 【final 语义】每图终 Boss 击杀即该图胜利(对齐图1 jiuying final:true):map2 天柱 / map3 陆吾 /
* map4 共工 / map5 烛龙 为各图终 Boss(final:true);中 Boss final:false。新 Boss 不 spawn 图1,
* final 标记不触发图1 判胜 → 安全。
* 【数值/战技占位待平衡】hp/dps/charge/summon/enrage 均按图序抬升铺草案锚,非真值;真值待 M5
* 平衡线参照图1 九婴「dps/存活窗不等式」(本表顶部 round-8 调参注)逐图校准。
* 【sprite 占位待美术】render 按 bossDef.id 查 BOSS_SPRITE,查不到 fallback 到 'luwu'(render.js:535),
* 故新 Boss 暂无专属帧也不崩渲染;各 Boss 专属 10 帧(§9 Boss 10×10)待美术批产补 render BOSS_SPRITE。
* 【命名】id 前缀 boss_ 与敌表 key 区分(避免与敌表 xiangliu/hundun 等同名兽混淆);名取山海经公版
* 大兽原创演绎,代理定名,最终命名待文案。
*/
// ── map2 不周山双 Boss(占位)──
{
id: 'boss_yanling', name: '炎灵·毕方', atS: 100000, map: 'map2',
hp: 2600, speed: 58, r: 30, dps: 42, gem: 60, gemPer: 4,
slowResist: 0.8, dropHarvest: true, final: false,
skills: {
charge: { cooldown: 9, telegraphS: 0.9, speedMul: 4.0, durS: 0.7 },
summon: { cooldown: 14, n: 6, type: 'bifang' },
},
},
{
id: 'boss_tianzhu', name: '天柱·不周守', atS: 100000, map: 'map2',
hp: 4200, speed: 50, r: 38, dps: 34, gem: 100, gemPer: 4,
slowResist: 0.8, dropHarvest: false, final: true,
skills: {
charge: { cooldown: 12, telegraphS: 1.2, speedMul: 3.6, durS: 0.6 },
summon: { cooldown: 18, n: 5, type: 'gudiao' },
enrage: { hpPct: 0.3, speedMul: 1.2, dpsMul: 1.25 },
},
},
// ── map3 昆仑墟双 Boss(占位)──
{
id: 'boss_yingzhao', name: '英招·昆仑卫', atS: 100000, map: 'map3',
hp: 3200, speed: 60, r: 31, dps: 46, gem: 60, gemPer: 4,
slowResist: 0.8, dropHarvest: true, final: false,
skills: {
charge: { cooldown: 9, telegraphS: 0.9, speedMul: 4.2, durS: 0.7 },
summon: { cooldown: 14, n: 6, type: 'yingzhao' },
},
},
{
id: 'boss_luwu', name: '陆吾·昆仑君', atS: 100000, map: 'map3',
hp: 5000, speed: 52, r: 39, dps: 38, gem: 100, gemPer: 4,
slowResist: 0.8, dropHarvest: false, final: true,
skills: {
charge: { cooldown: 12, telegraphS: 1.2, speedMul: 3.6, durS: 0.6 },
summon: { cooldown: 18, n: 5, type: 'liwu' },
enrage: { hpPct: 0.3, speedMul: 1.22, dpsMul: 1.28 },
},
},
// ── map4 归墟双 Boss(占位)──
{
id: 'boss_xiangliu', name: '相柳·九首蛇', atS: 100000, map: 'map4',
hp: 4000, speed: 56, r: 33, dps: 50, gem: 60, gemPer: 4,
slowResist: 0.8, dropHarvest: true, final: false,
skills: {
charge: { cooldown: 9, telegraphS: 0.85, speedMul: 4.2, durS: 0.7 },
summon: { cooldown: 14, n: 6, type: 'huashe' },
},
},
{
id: 'boss_gonggong', name: '共工·怒触山', atS: 100000, map: 'map4',
hp: 6000, speed: 48, r: 42, dps: 42, gem: 100, gemPer: 4,
slowResist: 0.8, dropHarvest: false, final: true,
skills: {
charge: { cooldown: 12, telegraphS: 1.2, speedMul: 3.8, durS: 0.6 },
summon: { cooldown: 18, n: 5, type: 'xiangliu' },
enrage: { hpPct: 0.3, speedMul: 1.24, dpsMul: 1.3 },
},
},
// ── map5 钟山双 Boss(占位;终图终 Boss = 烛龙)──
{
id: 'boss_hundun', name: '浑沌·无面', atS: 100000, map: 'map5',
hp: 5200, speed: 54, r: 36, dps: 54, gem: 60, gemPer: 4,
slowResist: 0.8, dropHarvest: true, final: false,
skills: {
charge: { cooldown: 9, telegraphS: 0.85, speedMul: 4.4, durS: 0.7 },
summon: { cooldown: 14, n: 6, type: 'hundun' },
},
},
{
id: 'boss_zhulong', name: '烛龙·钟山神', atS: 100000, map: 'map5',
hp: 7500, speed: 46, r: 44, dps: 45, gem: 120, gemPer: 4,
slowResist: 0.8, dropHarvest: false, final: true, // 终图终 Boss:击杀即全篇胜利(占位,数值待平衡)
skills: {
charge: { cooldown: 12, telegraphS: 1.2, speedMul: 3.8, durS: 0.6 },
summon: { cooldown: 18, n: 5, type: 'jiuwei' },
enrage: { hpPct: 0.3, speedMul: 1.26, dpsMul: 1.32 },
},
},
];
/**
* ══════════════════ 地图表(5 图;M5 检查点1 数据层接入点声明)══════════════════
* §5.2 地图 5,各带 1 个空间机制 / 专属敌表 / 双 Boss / 专属 BGM / 专属背景。本表是后续 sim mapId
* 参数化的**单一接入点**:每图声明 id/name/主题/战场(arena)/波表(waves)/敌混(enemyMix)/
* 双 Boss(bossIds)/背景(bg)/解锁条件(unlock)。
*
* ── 当前不接线(保回归)──
* sim.js 本检查点仍硬编码图 1:波次读**全局 WAVES**(=MAPS[0].waves 同一对象)、Boss 按全 BOSSES
* 表 atS 出场、敌按图 1 波表 mix 抽——均不经由本表。故 MAPS 是纯新增声明数据,sim/meta 都不读,
* 游戏行为零变化。sim mapId 参数化后改读 MAPS[mapId].{waves,arena,bossIds,…}(留待后续检查点)。
*
* ── 占位纪律 ──
* map1 裂谷原:映射现状(现主题/现波表/现敌混/现双 Boss/现背景),行为锁定不变。
* map25:主题为代理定名(待美术/文案);波表 = 图1 波表缩放变体(wavesVariant,占位待平衡);
* 敌混/Boss 引用本图 ENEMIES/BOSSES 条目;arena 暂复用图1 尺寸(各图专属战场待 M5 定);
* bg 占位待美术(各图专属背景图集);unlock 为 meta 解锁条件占位(结构对齐 ROLES.unlock,待接线)。
*/
/**
* map25 占位波表变体工厂(占位待平衡):以图 1 波表 WAVES 为基线,按图序做到达率(rate×rateScale)/
* 个体血量(hpMul×hpScale)缩放 + 敌混替换为该图敌种;时刻点(t)与经济/速度乘区沿用图1(占位)。
* 纯占位——真波表待 M5 平衡线逐图扫描收敛;此处只为让 MAPS 各图有可读波表引用。sim 不读本表。
*/
const wavesVariant = (mix, rateScale, hpScale) => WAVES.map((row) => ({
...row,
rate: Math.round(row.rate * rateScale * 100) / 100,
hpMul: Math.round(row.hpMul * hpScale * 1000) / 1000,
mix,
}));
/** map2 不周山波表(占位:图1 节奏 ×1.1 到达 / ×1.15 血量;敌混=不周山六兽)。 */
export const WAVES_MAP2 = wavesVariant(
{ bifang: 0.45, gudiao: 0.22, zhuyan: 0.13, dangkang: 0.08, mingshe: 0.08, taotie: 0.04 }, 1.1, 1.15);
/** map3 昆仑墟波表(占位:×1.2 到达 / ×1.35 血量;敌混=昆仑墟六兽)。 */
export const WAVES_MAP3 = wavesVariant(
{ yingzhao: 0.4, liwu: 0.22, zhujian: 0.13, zhuai: 0.12, xiezhi: 0.08, yayu: 0.05 }, 1.2, 1.35);
/** map4 归墟波表(占位:×1.3 到达 / ×1.6 血量;敌混=归墟六兽)。 */
export const WAVES_MAP4 = wavesVariant(
{ huashe: 0.38, fuzhu: 0.2, feiyi: 0.17, luoyu: 0.1, changyou: 0.1, xiangliu: 0.05 }, 1.3, 1.6);
/** map5 钟山波表(占位:×1.45 到达 / ×2.0 血量;敌混=钟山十一兽,终图最高压)。 */
export const WAVES_MAP5 = wavesVariant(
{ jiuwei: 0.2, tiangou: 0.15, qitu: 0.12, lilu: 0.12, shusi: 0.1, fei: 0.1, yong: 0.07,
huahuai: 0.06, baize: 0.04, hundun: 0.02, bashe: 0.02 }, 1.45, 2.0);
/** 5 图表(序 = 解锁序;map1 首图恒解锁,map25 依 meta 进度顺序解锁〔占位待 meta 接线〕)。 */
export const MAPS = [
{
id: 'map1', name: '裂谷原',
theme: '山海裂隙,百兽潮涌出处;赭石裂谷、岩画图腾(现图1,主题/行为锁定不变)',
arena: ARENA, // 现图1 战场 1560×2960
waves: WAVES, // 现图1 波表(sim 当前读全局 WAVES,与此同一对象)
enemyMix: ['zheng', 'taowu', 'qiongqi'], // sim 图1 波表实际敌混(保持现行为;M5 扩混占位待平衡)
bossIds: ['zhengwang', 'jiuying'], // 图1 双 Boss(中=狰王 / 终=九婴)
bg: 'bg-map1-arena-01', // 现图1 背景(资产一期已入库)
bgm: '占位待美术(map1 专属 BGM,M5 BGM6 之一)',
unlock: { always: true }, // 首图恒解锁
},
{
id: 'map2', name: '不周山',
theme: '天柱折、地维绝;焦土火山,毕方衔火而行(占位主题,代理定名·待美术/文案)',
arena: ARENA, // 占位:暂复用图1 战场尺寸(各图专属 arena 待 M5 定)
waves: WAVES_MAP2, // 占位波表(图1 缩放变体,待平衡)
enemyMix: ['bifang', 'gudiao', 'zhuyan', 'dangkang', 'mingshe', 'taotie'],
bossIds: ['boss_yanling', 'boss_tianzhu'], // 中=炎灵·毕方 / 终=天柱·不周守
bg: '占位待美术(map2 专属背景图集)',
bgm: '占位待美术(map2 专属 BGM)',
unlock: { stat: 'mapWin', gte: 1, note: '占位待 meta 解锁逻辑(通关图1解锁不周山)' },
},
{
id: 'map3', name: '昆仑墟',
theme: '昆仑之墟,神明所守;英招陆吾,巡卫天柱(占位主题,代理定名·待美术/文案)',
arena: ARENA,
waves: WAVES_MAP3,
enemyMix: ['yingzhao', 'liwu', 'zhujian', 'zhuai', 'yayu', 'xiezhi'],
bossIds: ['boss_yingzhao', 'boss_luwu'], // 中=英招·昆仑卫 / 终=陆吾·昆仑君
bg: '占位待美术(map3 专属背景图集)',
bgm: '占位待美术(map3 专属 BGM)',
unlock: { stat: 'mapWin', gte: 2, note: '占位待 meta 解锁逻辑(通关图2解锁昆仑墟)' },
},
{
id: 'map4', name: '归墟',
theme: '归墟无底,众水所归;深渊化蛇,相柳盘波(占位主题,代理定名·待美术/文案)',
arena: ARENA,
waves: WAVES_MAP4,
enemyMix: ['huashe', 'feiyi', 'luoyu', 'fuzhu', 'changyou', 'xiangliu'],
bossIds: ['boss_xiangliu', 'boss_gonggong'], // 中=相柳·九首蛇 / 终=共工·怒触山
bg: '占位待美术(map4 专属背景图集)',
bgm: '占位待美术(map4 专属 BGM)',
unlock: { stat: 'mapWin', gte: 3, note: '占位待 meta 解锁逻辑(通关图3解锁归墟)' },
},
{
id: 'map5', name: '钟山',
theme: '钟山之巅,烛龙司昼夜;混沌未凿,终局之所(占位主题,代理定名·待美术/文案;终图)',
arena: ARENA,
waves: WAVES_MAP5,
enemyMix: ['hundun', 'jiuwei', 'tiangou', 'bashe', 'fei', 'qitu', 'shusi', 'yong', 'lilu', 'huahuai', 'baize'],
bossIds: ['boss_hundun', 'boss_zhulong'], // 中=浑沌·无面 / 终=烛龙·钟山神(全篇终 Boss)
bg: '占位待美术(map5 专属背景图集)',
bgm: '占位待美术(map5 专属 BGM)',
unlock: { stat: 'mapWin', gte: 4, note: '占位待 meta 解锁逻辑(通关图4解锁钟山·终图)' },
},
];
/**
* 局内事件(M3 先落 4 种,池 8 归 M5;§3.1 验收用例:每局 ≥3 次、种类 ≥2,奖励值回风险)。
* 调度:firstAtS 后每隔 [minGapS,maxGapS](受控 rng)按权重抽一种;终 Boss 出场后不再起新事件。
*/
export const EVENTS = {
firstAtS: 100, minGapS: 200, maxGapS: 260, maxPerRun: 5,
pool: [
// 宝箱怪:驮宝异兽逃跑(不攻击),限时追杀;击杀 = 聚灵珠 + 灵晶堆(追离安全区 = 冒险)
{ id: 'chest', name: '宝箱怪', weight: 3, durS: 22,
beast: { hp: 260, speed: 150, r: 12 }, reward: { harvest: true, gems: { n: 10, value: 3 } } },
// 流星雨:玩家周域随机落火(先预警圈后炸),炸玩家也炸兽(风险与收益同源:引兽入雨)
{ id: 'meteor', name: '流星雨', weight: 3, durS: 18,
strikes: { gapS: 0.9, r: 68, telegraphS: 1.1, scatterR: 300, dmgPlayer: 18, dmgEnemy: 220 } },
// 祭坛充能:远处符坛,站内充能(离开暂停不清零);充满 = 治疗 + 灵晶雨(站桩 = 冒险)
{ id: 'altar', name: '祭坛充能', weight: 2, durS: 26,
altar: { dist: 260, r: 80, channelS: 6, reward: { heal: 35, gems: { n: 12, value: 2 } } } },
// 裂谷涌兽:定点涌出精英+小兽群,中心灵晶堆(冲进去打 = 冒险)
{ id: 'rift', name: '裂谷涌兽', weight: 2, durS: 20,
rift: { dist: 300, elites: 3, minions: 10, loot: { n: 14, value: 2 } } },
],
};
/** 同屏活敌上限(玩法帧预算的逻辑闸;压测另行合成 600,见 stress-test)。 */
export const MAX_ALIVE = 220;
/** 同场区域(zone)实体上限(盾环/桩阵合计;超出丢最旧,防被动叠出失控)。 */
export const MAX_ZONES = 40;
/** 出怪环半径(px):以玩家为圆心、视口对角线外(390×844 对角 ≈465),怪从屏外进场。 */
export const SPAWN_R = 520;
/** 空间网格 cell(px):≈ 2×最大敌半径(穷奇 r20)+余量;索敌/分离/弹命中/区域结算共享。 */
export const GRID_CELL = 48;
/** 敌-敌软分离:邻域上限 8(O(n) 软推挤,不做全对碰撞——设计书 §7.3)。 */
export const SEPARATION = { neighborCap: 8, push: 0.5 };
/**
* 手感反馈档位表(hit-feedback 插件直接吃表——设计书 §6 手 4/5/6/7/10 的量值面)。
* 全部量值为首版草案〔真机校准后锁〕;推导基准=帧级反馈惯例(30ms≈2帧@60fps、闪白 80ms≈5帧)。
* M2:crit 档事件源随暴击轴落地(破煞诀/天雷引);harvest 档随聚灵珠落地;bossKill 事件源仍归 M3。
*/
export const FEEDBACK = {
mergeWindowMs: 500, // 手 4:顿帧 0.5s 窗口内合并(防连锁卡顿)
maxShakeAmpPx: 8, // 手 5:震屏幅度上限(防晕;Boss 登场档=上限值)
maxTexts: 40, // 手 7:屏内飘字上限(可读性上限)
textTtlMs: 700, // 飘字寿命
// sfx 名 = 内容音效引擎(src/sfx.js)配方键,一事件一贴合音色(去芯片音;M4 由 ZzFX 单振荡器名细分而来)
tiers: {
hit: { text: true }, // 普通命中:顿帧 0(手 4)+ 飘字
crit: { hitStopMs: 30, text: true }, // 暴击 30ms(M2 事件源已落:破煞诀/天雷引)
bossKill: { hitStopMs: 80, shakeAmpPx: 8, shakeMs: 150, sfx: 'bosskill' },// Boss 伏诛:轰然崩解(M3 事件源已落:双 Boss)
bossSpawn: { shakeAmpPx: 8, shakeMs: 300, sfx: 'bossroar' }, // 手 5:Boss 登场威压上涌
eventStart: { sfx: 'event' }, // 局内异象开场:玄秘微光
kill: { sfx: 'kill' }, // 击破/击毁:碎裂闷响;爆浆粒子走 juice.burst
playerHurt: { shakeAmpPx: 5, shakeMs: 150, flashMs: 80, flashPeak: 0.3, sfx: 'hurt' }, // 手 5:受击低闷撞击+下坠
pickup: { sfx: 'gem' }, // 灵晶进账:清脆水晶叮
levelup: { sfx: 'levelup' }, // 升级:上行叠泛音编钟
harvest: { flashMs: 80, flashPeak: 0.2, sfx: 'harvest' }, // 聚灵珠全图磁吸:上扫流光(手 6 族闪屏 ≤80ms)
},
/** 手 6:死亡爆浆粒子 814/只(池化在 juice maxParticles;数量按 eid 确定性取带内值)。 */
burstPerKill: { min: 8, max: 14 },
};