主表下方加 6原型×5元素(火/冰/雷/毒/奥) SpinBox 网格(-0.9~0.9);_save 汇总 非零抗性写入 resistances,全0则省略键。读写往返 MCP 实测 FAILS=0 (读种子 fire0.5/ice-0.5,写非零、零值省略、负值保留)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
91 lines
3.2 KiB
GDScript
91 lines
3.2 KiB
GDScript
## 敌人原型编辑器标签(表格: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)
|