MOD_SOURCE_CORE 常量取代四处裸字面量(combat_manager:275,276、combat_test:20,21)。 combat_manager:273 的注释自己就警告「漏掉 remove 会累积,且 hard:50 会把它封成一个 看起来合理的数字」——而 remove 那一侧的字面量若打错一个字符,产生的正是这个零诊断 故障:旧份额撤不掉、逐次累积、被硬上限封顶成常数。常量把它变成编译期错误。 _compute_attr 缺定义时返回 0.0 是消费侧的不对称:Task 4 已硬化生产侧(attribute_tab 的 _loaded 拒绝写出零载荷),但手删 JSON 里的 cast_delay_mod 仍会让生效间隔变 0 (每物理帧施法一次)、删 move_speed 则玩家不能动。它有 push_error,但运行时 push_error 到不了任何日志通道(本期已实测),故表现为一块莫名其妙的砖。按 _recompute_attrs 空定义 分支的同款模式补 assert:release 编译掉、开发期立刻中断。 spell_evaluator:332 的新注释说「生效 cpu_limit 已含法杖份额」,读者可能推断整个 VM 都按 cpu_limit 走,但 execute_sub 的子荷载预算仍是独立的 MAX_OPS_PER_CPU * 2(=80)。补一句 注明其独立且属既有行为(改前同样脱节),不改 execute_sub 的行为。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
68 lines
2.3 KiB
GDScript
68 lines
2.3 KiB
GDScript
## CombatTest — S1 最小战斗调试场景
|
||
## 目标:玩家自动发射 spark_bolt,子弹命中敌人,敌人死亡,屏幕显示击杀数
|
||
## 验收:P-S1-01 ~ P-S1-05
|
||
extends Node2D
|
||
|
||
const SPAWN_ENEMIES: int = 50 # S1 验收:50 只散兵(充分验证伤害)
|
||
|
||
var _player_node: Node2D = null
|
||
var _perf_label: Label = null
|
||
var _spawned: bool = false
|
||
|
||
func _ready() -> void:
|
||
_setup_debug_ui()
|
||
PlayerManager.set_player_node(_player_node)
|
||
# 装备法杯:wand_basic + spark_bolt
|
||
var loadout: Dictionary = WandPreset.make_default_loadout()
|
||
# 本场景绕过 CombatManager,故须自行注入法杖运算力份额(否则 cpu_limit=0 → MAX_OPS 退化)
|
||
# 顺序理由见 combat_manager._rebuild_wand:remove 必须先于 add(否则重复进入会累积),
|
||
# 而两者又必须都先于 equip_wand(equip_wand 里的 cpu_limit<=0 守卫读的就是注入结果)
|
||
PlayerStats.remove_modifiers_from(PlayerStats.MOD_SOURCE_CORE)
|
||
PlayerStats.add_modifier("cpu_limit", "flat", float(loadout["core"].cpu_limit), PlayerStats.MOD_SOURCE_CORE)
|
||
PlayerManager.equip_wand(loadout["core"], loadout["compiled"])
|
||
_run_spawn()
|
||
|
||
func _process(_delta: float) -> void:
|
||
_update_perf_ui()
|
||
|
||
func _run_spawn() -> void:
|
||
var arena: float = 600.0
|
||
for _i in SPAWN_ENEMIES:
|
||
EnemyManager.spawn_enemy(
|
||
Vector2(randf_range(-arena, arena), randf_range(-arena, arena)),
|
||
50.0 # P-S1-01: HP = 50,spark_bolt 卷 3 伤
|
||
)
|
||
_spawned = true
|
||
print("[CombatTest S1] 生成完成: %d 敌人, wand_basic+spark_bolt 装备" % SPAWN_ENEMIES)
|
||
|
||
func _update_perf_ui() -> void:
|
||
if not _spawned or not _perf_label:
|
||
return
|
||
_perf_label.text = (
|
||
"FPS: %.1f\n敌人: %d\n击杀: %d\n子弹: %d\nTick: %d\n池: %s" % [
|
||
Engine.get_frames_per_second(),
|
||
EnemyManager.get_active_count(),
|
||
PlayerManager.kill_count,
|
||
BulletManager.get_active_count(),
|
||
TimeManager.game_tick,
|
||
DamageContextPool.get_pool_usage()
|
||
]
|
||
)
|
||
|
||
func _setup_debug_ui() -> void:
|
||
var canvas := CanvasLayer.new()
|
||
canvas.name = "DebugUI"
|
||
add_child(canvas)
|
||
|
||
var perf := Label.new()
|
||
perf.name = "PerfLabel"
|
||
perf.position = Vector2(16, 16)
|
||
perf.add_theme_font_size_override("font_size", 18)
|
||
canvas.add_child(perf)
|
||
_perf_label = perf
|
||
|
||
var p := Node2D.new()
|
||
p.name = "Player"
|
||
add_child(p)
|
||
_player_node = p
|