Files
spellforge/docs/design/numerical_design.md
T
joywayerandClaude Opus 5 84c10725e2 docs: 订正 wand_fast 饱和点 0.05→0.0667;roadmap 关闭已决定项并澄清移速表述
【订正】wand_fast(0.25s) 的饱和点按公式 (1/60)/0.25 = 0.0667,不是 0.05。
numerical_design:21 的标注与它自己上一句的公式直接矛盾,spec/plan 另有三处同源
错误标注——均派生自一句口头转述,实测表里记的 0.0667 一直是对的。

结论也随之改对,不只是改数字:hard=0.05 使 wand_basic(饱和 0.0333) 与
circuit_fork(0.0278) 无无效区间,但 wand_fast 仍剩 [0.05, 0.0667) 这段买不到东西
(较原 hard:0.01 的 6.7 倍缩至 1.33 倍)。仍取 0.05 的理由:饱和点 = (1/60)/法杖
基准间隔,随杖而异,不存在对所有杖都最优的单一 hard——取 0.0667 让 wand_fast 干净
会使另两把杖够不到自己的饱和点,反而制造新的不可达区间。hard 数值不变。

顺带说明实测表里 wand_fast@0.0667 读到 2 帧的原因:采样点比真实边界 1/15 高 3.3e-5
(T 上高 8.3e-6 s),再叠加整帧倍数多花一帧的浮点余量效应,故实际 1 帧上界略低于
0.0667。数据没错,是标签错了。

【roadmap】E3-① 下的 cast_delay_mod 条目仍记为「待人定」并指向两个选项,而该决定
已在 ba7c885 关闭——roadmap 是查「E3 还剩什么」的索引,留着会把已关闭的决定重新打开。
改为已处理,并注明彻底消除需让 hard 逐杖化(挪进 cores.json),属独立立项。

【roadmap】「实测 200→300 px/s」读起来像发版移速由 200 改成 300,与同批改动里
numerical_design 的订正(发版是 200,300 是从未被读过的纸面值)直接冲突。改写为
「发版基准仍是 200;实测手段是临时挂 +50% 加成使生效值变 300」。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 13:36:53 +08:00

19 KiB
Raw Blame History

数值策划设计案:魔法工匠 (Arcane Artificer)

0. 设计理念 (Design Philosophy)

本游戏的数值体系服务于 “高自由度构建” 这一核心目标。 数值设计不应教玩家怎么玩,而应提供足够宽广的边界(Boundary)和明确的权衡(Trade-off)。

核心公式: 构建强度 = (基础数值 * 修正系数) ^ 逻辑复杂度

1. 基础资源模型 (Resource Model)

1.1 玩家属性 (Player Stats)

这些属性是全局的,会修正所有法杖的输出。

属性 ID 名称 基准值 软上限 硬上限 说明
hp_max 最大生命 100 2000 -
mana_max 最大魔力 100 1000 - 全局蓝条上限,法杖也有自己的上限,取 Min 值
move_speed 移动速度 200 600 800 像素/秒。⚠️ 2026-07-31 订正:原写 300 从未被任何代码读取过,是纸面孤值;实际实现自 S0 起即为 200(player_manager.gdconst MOVE_SPEED,现已改为读 data/attributes.json),20 波内容、Boss 弹幕密度、无敌帧 0.5 s 均按此值调校。此处以既成事实为准 —— 改回 300 等于用未经验证的数字推翻一整轮已调校的内容。理由详见 docs_dev/specs/2026-07-31-player-attributes-design.md §2.2。
cast_delay_mod 施法延迟修正 1.0 (100%) 0.1 0.05 越低越快,乘算系数。⚠️ 2026-07-31 由 0.01 上调至 0.05player_manager._handle_auto_castif 而非 while每物理帧至多施法一次,故本属性存在饱和点 = (1/60) / 法杖基准间隔 —— wand_basic(0.5 s) ≈ 0.0333wand_fast(0.25 s) ≈ 0.0667circuit_fork(0.6 s) ≈ 0.0278。饱和点随杖而异,故不存在对所有杖都最优的单一 hard:要让 wand_fast 无无效区间需 hard ≥ 0.0667,但那会让 wand_basic 够不到自己的 0.0333,反而制造新的不可达区间。取 0.05 是折中 —— wand_basiccircuit_fork 无无效区间,wand_fast 仍剩 [0.05, 0.0667) 这一小段买不到东西;相对原 0.01(两把主力杖都深陷饱和区、从 0.0333 一路买到 0.01 射速纹丝不动)是大幅改进。实测数据(可达档位是台阶而非曲线、周期恒为 ceil(T×60))见 docs_dev/specs/2026-07-31-player-attributes-design.md §2.2b。
recharge_speed_mod 充能速度修正 1.0 (100%) 5.0 - 越低越快
luck 幸运 0 100 - 影响高阶法术掉率、暴击率
cpu_limit 运算力上限 0(玩家侧) 20 50 SpellEvaluator 实际 MAX_OPS = 生效 cpu_limit × 40,与 implementation_plan.md §2.2MAX_OPS_PER_CPU = 40 常量对应。生效值 = 玩家侧基准 0 + 法杖份额(cores.json 逐杖 38,以 source="core" 的加成来源接入)+ 未来的玩家加成hard(50) 作用于加总后的生效值,故法杖份额也受硬上限约束。玩家侧基准取 0 而非 5 是刻意的:生效值已含法杖的 3–8,取 0 使小木法杖仍为 5 → 200 步(现有平衡零改动),取 5 会让所有法杖的执行预算翻倍;语义上玩家属性是"全局加成",基准 0 正是纯加成语义。 2026-07-31 已修复(原 ⚠️「代码硬编码 MAX_OPS = 40×5 = 200,从不读 cpu_limit」现已失效):spell_evaluator.gd 改读 MAX_OPS_PER_CPU * maxi(PlayerStats.cpu_limit, 1)cores.json 逐杖配置的运算力自此生效(高速法杖 3 → 120 步、小木 5 → 200、矩阵板 8 → 320,运行时实测)。设计见 docs_dev/specs/2026-07-31-player-attributes-design.md §2.2。
attunement_fire 火焰精通 0 50 100 每点:火焰伤害 +3%(乘算),火焰状态(点燃/爆燃)触发概率 +2%。影响 damage_type=FIRE 的所有投射物。
attunement_ice 冰霜精通 0 50 100 每点:冰霜伤害 +3%,冰冻/减速触发概率 +2%。
attunement_lightning 雷电精通 0 50 100 每点:雷电伤害 +3%,麻痹/连锁导电触发概率 +2%。
attunement_poison 毒素精通 0 50 100 每点:毒素 DoT +3%,中毒叠层上限 +1(上限 20)。

1.2 经济系统 (Economy)

  • 金币 (Gold) (代号 G)

    • 来源: 击杀怪物 (1-5G),波次结算 (100G + 10%利息)。
    • 消耗: 购买法术 (50-500G),购买法杖 (200-2000G),刷新商店 (20G*)。
    • 利息上限: 10% 利息计算时,单次波次奖励上限为 100G(即持有 1000G 以上部分不再产生额外利息)。防止后期经济失控膨胀。
    • 膨胀控制: 商店刷新价格每次增加,波次结束后重置。金币不捡 5 秒后消失,逼迫玩家移动拾取。
      • 刷新价格公式(F11 补充,P6-N23)刷新费用 = 20 + (本波已刷新次数 × 10)(单位:G)。 即第 1 次刷新 20G,第 2 次 30G,第 3 次 40G,以此类推;波次结算后重置为 20G。 设计意图:前 1-2 次刷新成本低,鼓励灵活换货;反复刷新代价指数感,抑制"无脑刷新"。 实现:ShopManager 维护 _refresh_count: int(波次内),WAVE_COMPLETE 事件后清零。
  • 经验值 (XP)

    • 升级曲线(权威公式 P6-N16 XP\_required(level) = \lfloor 10 \times 1.4^{level-1} \rfloor
      等级 所需 XP 累计 XP
      1→2 10 10
      5→6 54 234
      10→11 289 1397
      15→16 1551 7174
      20→21 8322 39,343
      • 系数 1.4 使早期升级快速(前 5 级约 4 波内完成),后期升级需要持续 3-5 波,节奏符合 Roguelite 期望。
      • ProfileManager 在关卡加载时预计算前 50 级的阈值表并缓存,避免运行时浮点指数运算。
      • ⚠️ F10 可行性验证(P6-N22Level 21 累计 XP 需求 39,343。20 波 × 60 秒/波 = 1200 秒游戏时长。 设平均每秒击杀 2 只敌人,每只掉 15 XP(Wave 10+ 标准怪),则 1200 × 2 × 15 = 36,000 XP—— 略低于 39,343,意味着理论上最高只能达到 Level 20 左右(不满 21 级)。 若期望玩家在通关时达到 20 级,需将 XP_required 公式中系数从 1.4 调整为约 1.38, 或将波次奖励 XP 提高(每波结算奖励 200 XP)。当前设计定为 Level 20 通关上限,不强制要求 Level 21 Level 21+ 曲线仅服务于 Endless 模式。敌人 XP 掉落参考值:Wave 1 杂鱼 = 5 XPWave 10 精英 = 30 XPBoss = 500 XP。

2. 法术系统数值 (Spell System Metrics)

2.1 核心参数定义

每个法术卡片 (Godot Resource / Json) 包含以下关键数值:

  1. Mana Cost (魔耗): 执行此节点消耗的魔力。
    • 原则: 越强力的效果,蓝耗越高,或者有其他负面代价。
  2. Cast Delay (施法后摇): 执行此节点后,给法杖增加的“冷却时间”。
    • 原则: 强大的单发法术通常有高延迟(如核弹 +2.0s)。
  3. Recharge Time (充能延迟): 这是一个特殊的延迟,只有当完整的一轮(Deck空了)打完正在重置时,才会计算。
    • 原则: 只有极强的终极技能才会增加此值。

2.2 基础法术参考表 (Spell Database)

⚠️ 注意Projectile/Action 类型法术必须在 .tres 中显式设置 damage_typeDamageType 枚举值)。 未填写时 ProjectileDef.reset() 默认 DamageType.PHYSICAL,但设计意图应在此表中明示, 避免内容制作者遗漏火/雷等元素属性导致构建伤害系统无法正常触发。

Tier 1 (新手/平民)

ID 名称 类型 Mana Delay 伤害类型 效果/修正 备注
spark_bolt 魔法飞弹 Projectile 5 +0.05s PHYSICAL Dmg: 3, Speed: 600 最基础的突突突
energy_orb 能量球 Projectile 20 +0.20s PHYSICAL Dmg: 15, Speed: 300 慢速高伤
double_cast 双重施法 Multicast 2 +0.00s Draw: 2 必备插件
spread_mod 散射修正 Modifier 0 -0.10s Spread: +30°, Speed: +10% 这一发打不准,但射得快

Tier 2 (进阶/功能)

ID 名称 类型 Mana Delay 伤害类型 效果/修正 备注
shotgun_blast 霰弹爆破 Projectile 25 +0.40s PHYSICAL 发射3枚 4dmg 的弹片 自带多重效果
damage_plus 伤害增强 Modifier 15 +0.10s Dmg: +10
speed_up 加速推进 Modifier 5 -0.05s Speed: +400, Range: +20% 狙击流必备
trigger_hit 击中触发 Trigger 10 +0.00s Payload Dmg: 0.1x 子母弹核心

Tier 3 (史诗/质变)

ID 名称 类型 Mana Delay 伤害类型 效果/修正 备注
nuke 战术核弹 Projectile 200 +3.00s PHYSICAL Dmg: 500, Radius: 300 屏幕清空,可能会炸死自己
homing 自动追踪 Modifier 40 +0.10s Homing Force: 5.0 只有这一个修正就够改变玩法 ⚠️ 本行已被取代(2026-07-30,见下方注
heavy_cost 鲜血献祭 Modifier 0 -0.50s Dmg: +50, Cost: 10 HP 卖血流
chain_bolt 连锁闪电 Projectile 60 +0.80s LIGHTNING 弹射 5 次 清怪神器

⚠️ homing 行注(2026-07-30E1-③ 归航实装) —— 原行保留不改写,以留存「曾判定其为 Tier 3」这一判断记录。实际发版取代如下:

原表(Tier 3 实际发版(data/spells.json modifier_homing
强度 Homing Force: 5.0 homing: 1.5
Mana 40 8
商店价 18
  1. Homing Force 这一语义已废。 实现的量是最大转向角速度(弧度/秒),不是「转向力」—— 每帧把速度矢量朝锁定目标旋转,单帧转角上限 strength × delta,速率不变。5.01.5 不是同一量纲的数,不可直接比较。
  2. Mana 40 / Tier 3 的定价被同族标准取代:与 modifier_pierce_plusmodifier_bounce 同为 8 蓝 / 18 金。代价是把强度降到 1.5 rad/s 使其名副其实 —— 运动学核算表明原设想的 3.0 rad/s 对本工程敌人速度(45~140 px/s)而言接近「稳定命中」,确实配得上原表 Tier 3 的判断;1.5 rad/s 才是「中度制导」(对最快敌人在 93 px 内会跟丢)。
  3. 该表其余行的 Mana 列与 spells.json 已实现条目逐一吻合,仅此行曾出现偏离,现予记录消解。

权威细节见 spec docs_dev/specs/2026-07-30-bullet-homing-design.md §2.0(运动学核算)与 §2.8(定价决策)。


3. 敌人与战斗数值 (Combat Metrics)

3.1 伤害计算管线

⚠️ 权威公式(Authoritative Formula:所有文档均应引用此处定义,不得出现矛盾版本。

为了支持复杂的 Buff/Debuff,伤害计算必须分步:

  1. Base Damage: 法术面板值 (e.g. 10)
  2. Add Modifiers: 累加修正器 (e.g. +5 +5 -> 20)
  3. Mult Modifiers: 乘法修正器 (e.g. Critical 2.0x, Element Weakness 1.5x)
  4. Flat Reduction: 敌人护甲 (Armor -2)
  5. Percent Reduction: 敌人抗性 (Fire Res 50%)
Damage = ((Base + Add) × Mult) × (1 - Res) - Armor

(最小伤害为 1

3.2 怪物设计标准

我们设定 “标准单位时间伤害 (DPS)” 为基准。

  • 玩家 Lvl 1 预计 DPS: 20
  • 玩家 Lvl 20 预计 DPS: 5000+
怪物等级 怪物类型 HP 移动速度 攻击力 特殊词条
Wave 1 杂鱼土豆 15 100 5 -
Wave 5 冲锋甲虫 80 250 12 击退抗性 50%
Wave 10 坦克巨兽 2000 50 30 护甲 5 (免疫机枪)
Wave 20 虚空领主 50000 ⚠️ 150 100 弹幕反射盾

3.3 波次强度控制 (Pacing)

游戏设计为 20 波 (Wave),每波 60秒。

  • W1-3: 爽局。怪物血量 < 玩家单发伤害。
  • W4-7: 压力局。怪物密度增加,玩家必须拥有至少一个 AOE 手段(穿透/爆炸)。
  • W8: 首领战 (Mini Boss)。考验单体 DPS。
  • W9-15: 资源局。怪物掉落增加,但伴随高护甲怪,考验玩家的“破甲/元素”构建。
  • W20: 最终 Boss

4. 元素反应矩阵 (Elemental Matrix)

为了增加构建深度,引入简单的元素克制/反应。

攻击 \ 如果目标状态 潮湿 (Wet) 油腻 (Oily) 燃烧 (Burning) 冰冻 (Frozen)
火 (Fire) 点燃 蒸发 (AOE) 爆燃 (x3 Dmg) - 融化 (解冻)
冰 (Ice) 减速 冻结 (硬控) - 熄灭 -
雷 (Elec) 麻痹 连锁导电 (AOE) - 过载 (爆炸) 碎冰 (物理Dmg)

数值策划备注:

  • 潮湿:受到雷电伤害 +100%。
  • 油腻:受到火焰伤害 +200%,且持续时间翻倍。
  • 冻结:无法移动,受到物理撞击伤害 +300% (即碎冰机制)。

5. 平衡性隐患与对策 (Balancing Risks)

A. 无限蓝机枪 (Infinite Mana Gun)

  • 问题: 玩家堆积大量 -DelayMana Regen,导致射速突破帧率限制,且蓝不掉。
  • 对策:
    • 最小帧限制: 设定射击间隔至少为 1 帧 (0.016s)。
    • 过热机制 (Overheat): 连续射击超过 5秒,法杖进入“过热”状态,强制冷却 2秒 或 增加散布。
    • 递增蓝耗: 连续快速射击时,每发子弹蓝耗增加 1%,停止射击后快速衰减。

    ⚠️ 实现现状 (2026-07-21 → 已实现):递增蓝耗已落地(PlayerStats.mana_heatbalance.json.mana_heat 可调,平衡页签);未做「最小帧限制/过热强制冷却」(用递增蓝耗替代)。

B. 显卡杀手 (GPU Killer)

  • 问题: 玩家构建出 无限分裂 + 无限粒子
  • 对策:
    • 最大弹道数 (Max Projectiles): 全局限制 2000 个弹道。超过时,新的子弹不再生成(或顶掉旧的)。
    • 双重限制机制
      • MAX_OPS= cpu_limit × MAX_OPS_PER_CPU,默认 5 × 40 = 200,软上限 20 × 40 = 800):SpellEvaluator 每帧单次施法最多执行对应条指令(包括 ACTION/MODIFIER/LOGIC 各类节点)。主要防止线性/循环构建死循环。与 implementation_plan.md §2.2MAX_OPS_PER_CPU = 40 常量对应。
      • 嵌套深度锁 MAX_TRIGGER_DEPTH = 3SpellEvaluator.execute_sub 调用时传入 depth 参数,超过 3 层不再触发新的 SubPayload(即 TRIGGER 内嵌套 TRIGGER 最多 3 层)。两者分工MAX_OPS 管局内指令数量,MAX_TRIGGER_DEPTH 管跨子弹的调用深度。

C. 站桩输出 (AFK Build)

  • 问题: 比如”自动追踪吸血光环”,玩家站着不动就能通关。
  • 对策:
    • 反挂机怪: 设计一种怪物,会向玩家当前位置投掷”毒圈”,逼迫玩家移动。
    • 资源衰减: 掉落的金币如果不捡,5秒后消失(或变少),逼迫玩家去捡钱。

D. W20 Boss Phase 1 DPS 门槛(P6-N17

  • 问题: Phase 1 的 regen_on_physical_hit = 0.005(每次物理命中恢复 Boss 最大 HP 的 0.5%)。 Boss 最大 HP = 50,000,即每次物理命中回血 250 HP

    ⚠️ 实现现状 (2026-07-20 审计):代码 Boss 实际 HP = 450(mini)/1800(final)balance.json,疑为占位),非 50000regen_on_physical_hit 虚空再生、反射盾、元素抗性均未实现。本节 DPS 门槛测算基于 50000 已失真,需统一血量口径后重算。详见 审计报告。 若玩家攻速 10 发/秒(纯物理构建),Boss 每秒净回血 2,500 HP。

  • DPS 突破阈值(最低要求):物理构建需满足以下条件才能有效磨血:

    DPS_{physical} > \frac{250 \times hit\_rate}{1} \Rightarrow DPS > 2500 \text{10发/秒时)}

    等价条件:每发伤害 > 250(单发狙击流),或总 DPS > 2500(高频流)。

    • 设计意图:并非阻止物理构建,而是要求玩家必须达到中后期构建强度(DPS 5000+)才能高效磨血;低配物理构建可用更长时间磨过,但效率不如元素/共鸣流。
    • 数值调整入口res://resources/bosses/boss_w20.json 中的 regen_on_physical_hit 字段,平衡迭代时直接修改数据而无需改代码。

E. infinite_spellsheavy_cost 叠加交互(P6-N18

  • 问题infinite_spells 特性(法力耗尽时每发+1 HP 代价)与 heavy_cost 修正器(每次施法-10 HP)叠加时,HP 代价是否累加?
  • 规则定义:两者独立计算、顺序执行
    1. SpellEvaluator 先执行 heavy_cost MODIFIER(扣 10 HP,归类为”构建设计主动代价”)。
    2. 之后,若 mana 不足,infinite_spells 机制额外扣 1 HP(归类为”资源溢出代价”)。
    3. 两者同帧触发时,单发最大 HP 代价 = heavy_cost 值 + 1(如 10+1=11 HP/发)。
  • UI 提示:法杖编辑界面在检测到 infinite_spells Core + heavy_cost 组合时,显示橙色警告”⚠ 双重 HP 消耗”,并提示预估每秒 HP 消耗量。
  • 上限保护:单次施法 HP 代价上限 = player.hp_max × 0.15(15% 上限),防止极端组合一发即死。

6. 波次生成配置格式 (SpawnConfig Schema — E5 权威定义)

波次内容完全由数据驱动,关卡设计师仅需编辑 JSON 无需改代码。文件位于 res://resources/waves/wave_XX.json

{
  "wave": 5,
  "duration_sec": 60,
  "budget": 200,
  "spawn_groups": [
    {
      "enemy_id": "bug_charger",
      "weight": 3,
      "count_min": 2,
      "count_max": 5,
      "spawn_interval": 3.0,
      "spawn_radius_from_player": [400, 700]
    },
    {
      "enemy_id": "tank_brute",
      "weight": 1,
      "count_min": 1,
      "count_max": 1,
      "spawn_interval": 15.0,
      "spawn_radius_from_player": [500, 800]
    }
  ],
  "elite_overrides": [
    { "at_sec": 45, "enemy_id": "elite_bug_charger", "count": 1 }
  ],
  "boss": null
}
  • budget:本波总"刷怪点数",每个怪物有对应的 cost;实际刷新量 = floor(budget / cost)
  • weight:同时存在多个 group 时,按权重随机选组,而非轮流刷新。
  • elite_overrides:精确时间点强制刷出精英怪,不消耗 budget。
  • boss:非 null 时在波末触发 BossSpawn(见 §6 Boss 设计框架)。