87 lines
3.2 KiB
GDScript
87 lines
3.2 KiB
GDScript
## 波次编辑器标签(关卡难度曲线:每波 怪数/血量/类型/精英/金币/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 = ["无 None", "首领 MiniBoss", "终焉 Boss"] # 映射到 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)
|