初次提交
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
## 波次编辑器标签(关卡难度曲线:每波 怪数/血量/类型/精英/金币/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)
|
||||
Reference in New Issue
Block a user