## 波次编辑器标签(关卡难度曲线:每波 怪数/血量/类型/精英/金币/XP/Boss) @tool extends VBoxContainer const UI = preload("res://addons/game_designer/designer_ui.gd") const PATH = "res://data/waves.json" const TYPE_NAMES = ["Basic", "Fast", "Armored", "Elite", "MiniBoss", "Boss"] const BOSS_NAMES = ["无", "MiniBoss(4)", "Boss(5)"] # 映射到 boss 值 -1/4/5 const BOSS_VALS = [-1, 4, 5] var _waves: Array = [] var _rows: Array = [] var _status: Label func _ready() -> void: _build() func _build() -> void: add_child(UI.header("🌊 波次编辑器 — 关卡难度曲线(点行号添加/删除波次)")) _load() var scroll := ScrollContainer.new() scroll.custom_minimum_size = Vector2(0, 260) scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED add_child(scroll) var grid := GridContainer.new() grid.columns = 8 scroll.add_child(grid) for h in ["波", "怪数", "血量", "类型", "精英", "金币", "XP", "Boss"]: var hl := Label.new(); hl.text = h; hl.modulate = Color(0.7, 0.8, 1.0) grid.add_child(hl) for i in _waves.size(): _add_row(grid, i, _waves[i]) add_child(HSeparator.new()) var row := HBoxContainer.new(); add_child(row) row.add_child(UI.btn("➕ 末尾加一波", _on_add)) row.add_child(UI.btn("💾 保存 waves.json", _save)) _status = UI.status_label() add_child(_status) func _add_row(grid: GridContainer, idx: int, w: Dictionary) -> void: grid.add_child(UI.cell_label("W%d" % (idx + 1))) var count := UI.spin(0, 2000, 1, float(w.get("count", 20))) var hp := UI.spin(1, 99999, 1, float(w.get("hp", 15))) var type_o := UI.opt(TYPE_NAMES, int(w.get("type", 0))) var elite := UI.spin(0, 100, 1, float(w.get("elite", 0))) var gold := UI.spin(0, 99999, 1, float(w.get("gold", 10))) var xp := UI.spin(0, 99999, 1, float(w.get("xp", 20))) var boss_idx := BOSS_VALS.find(int(w.get("boss", -1))) var boss_o := UI.opt(BOSS_NAMES, max(0, boss_idx)) grid.add_child(count); grid.add_child(hp); grid.add_child(type_o) grid.add_child(elite); grid.add_child(gold); grid.add_child(xp); grid.add_child(boss_o) _rows.append({"count": count, "hp": hp, "type": type_o, "elite": elite, "gold": gold, "xp": xp, "boss": boss_o}) func _load() -> void: var d = UI.load_json(PATH) _waves = d if d is Array else [] func _on_add() -> void: _waves = _read_rows() _waves.append({"count": 30, "hp": 50, "type": 0, "elite": 0, "gold": 30, "xp": 40, "boss": -1}) _rebuild() func _rebuild() -> void: # 简易重建:清空后重新 _init 逻辑(移除所有子节点重建) for c in get_children(): c.queue_free() _rows.clear() call_deferred("_build") func _read_rows() -> Array: var out: Array = [] for r in _rows: out.append({ "count": int(r["count"].value), "hp": r["hp"].value, "type": r["type"].selected, "elite": int(r["elite"].value), "gold": int(r["gold"].value), "xp": int(r["xp"].value), "boss": BOSS_VALS[r["boss"].selected], }) return out func _save() -> void: if UI.save_json(PATH, _read_rows()): UI.set_status(_status, "💾 已保存 %d 波(重启游戏 F5 生效)" % _rows.size()) else: UI.set_status(_status, "✗ 保存失败", true)