## 敌人原型编辑器标签(表格:6 原型 × 速度/护甲/尺寸/颜色) @tool extends VBoxContainer const UI = preload("res://addons/game_designer/designer_ui.gd") const PATH = "res://data/enemies.json" const NAMES = ["杂兵 Basic", "快速 Fast", "护甲 Armored", "精英 Elite", "首领 MiniBoss", "终焉 Boss"] const ELEM_KEYS = ["fire", "ice", "lightning", "poison", "arcane"] const ELEM_LABELS = ["火 Fire", "冰 Ice", "雷 Lightning", "毒 Poison", "奥 Arcane"] var _data: Dictionary = {} var _rows: Array = [] # [{speed:SpinBox, armor:SpinBox, size:SpinBox, color:ColorPickerButton}] var _status: Label func _ready() -> void: add_child(UI.header("👾 敌人原型 — 调速度 / 护甲 / 尺寸 / 颜色")) _load() var grid := GridContainer.new() grid.columns = 5 add_child(grid) # 表头 for h in ["原型", "速度", "护甲", "尺寸(px)", "颜色"]: var hl := Label.new(); hl.text = h; hl.modulate = Color(0.7, 0.8, 1.0) grid.add_child(hl) # 行 for i in 6: var key := str(i) var d: Dictionary = _data.get(key, {}) grid.add_child(UI.cell_label(NAMES[i])) var sp := UI.spin(0, 1000, 1, float(d.get("speed", 80))) var ar := UI.spin(0, 200, 0.5, float(d.get("armor", 0))) var sz := UI.spin(2, 200, 1, float(d.get("size", 14))) var cp := ColorPickerButton.new() var c: Array = d.get("color", [1, 1, 1]) cp.color = Color(float(c[0]), float(c[1]), float(c[2])) cp.custom_minimum_size = Vector2(60, 0) grid.add_child(sp); grid.add_child(ar); grid.add_child(sz); grid.add_child(cp) _rows.append({"speed": sp, "armor": ar, "size": sz, "color": cp}) add_child(HSeparator.new()) add_child(UI.cell_label("元素抗性 Resistances(-0.9~0.9,负=弱点加伤)")) var rgrid := GridContainer.new() rgrid.columns = ELEM_KEYS.size() + 1 add_child(rgrid) var rhead := Label.new(); rhead.text = "原型"; rhead.modulate = Color(0.7, 0.8, 1.0) rgrid.add_child(rhead) for el in ELEM_LABELS: var el_l := Label.new(); el_l.text = el; el_l.modulate = Color(0.7, 0.8, 1.0) rgrid.add_child(el_l) for i in 6: var d2: Dictionary = _data.get(str(i), {}) var res_d: Dictionary = d2.get("resistances", {}) rgrid.add_child(UI.cell_label(NAMES[i])) var res_spins := {} for ei in ELEM_KEYS.size(): var ename: String = ELEM_KEYS[ei] var sp2 := UI.spin(-0.9, 0.9, 0.05, float(res_d.get(ename, 0.0))) rgrid.add_child(sp2) res_spins[ename] = sp2 _rows[i]["resist"] = res_spins add_child(UI.btn("💾 保存 enemies.json", _save)) _status = UI.status_label() add_child(_status) func _load() -> void: var d = UI.load_json(PATH) _data = d if d is Dictionary else {} func _save() -> void: var out: Dictionary = {} for i in 6: var r: Dictionary = _rows[i] var entry := { "name": NAMES[i], "speed": r["speed"].value, "armor": r["armor"].value, "size": r["size"].value, "color": [r["color"].color.r, r["color"].color.g, r["color"].color.b], } var rd := {} for ename in ELEM_KEYS: var v: float = r["resist"][ename].value if absf(v) > 0.0001: rd[ename] = v if not rd.is_empty(): entry["resistances"] = rd out[str(i)] = entry if UI.save_json(PATH, out): UI.set_status(_status, "💾 已保存(重启游戏 F5 生效)") else: UI.set_status(_status, "✗ 保存失败", true)