# SafeboxUI (P8) —— 仓库窗。 # # var bu := preload("res://ui/safebox_ui.gd").new() # add_child(bu) # bu.setup(m2client, canvas_parent, proto) # proto 可空 # # `safebox_changed` 刷新(size>0 → 打开)。列出仓库道具 + [取出]。 # inventory_ui 在仓库开着时右键道具 → 调 bu.deposit(win, cell)。 # 取出/存入用第一个空位(简版:deposit 用 safe_pos = 下一个空格;checkout 用道具 cell)。 extends Node var client: Node var proto: Node var _root: Control var _list: VBoxContainer var _gold: Label var _title: Label func setup(m2client: Node, parent: Node, proto_node: Node = null) -> void: client = m2client proto = proto_node _build(parent) if client.has_signal("safebox_changed"): client.safebox_changed.connect(refresh) func is_open() -> bool: return _root != null and _root.visible func deposit(inv_window: int, inv_cell: int) -> void: if is_open(): client.safebox_checkin(_next_free_slot(), inv_window, inv_cell) func _next_free_slot() -> int: var used := {} for it in client.get_safebox_items(): used[int(it.get("cell", -1))] = true var cap: int = maxi(1, client.get_safebox_size()) * 45 for i in range(cap): if not used.has(i): return i return 0 func _name_of(vnum: int) -> String: if proto and proto.has_method("item"): var d: Dictionary = proto.item(vnum) var n := String(d.get("locale_name", d.get("name", ""))) if n != "": return n return "#%d" % vnum func refresh() -> void: if client == null: return _root.visible = client.is_safebox_open() if not _root.visible: return _title.text = "仓库(%d 页)" % client.get_safebox_size() _gold.text = "仓库金币: %d" % client.get_safebox_gold() for c in _list.get_children(): c.queue_free() var items: Array = client.get_safebox_items() if items.is_empty(): var e := Label.new() e.text = "(空)" _list.add_child(e) return for it in items: _list.add_child(_row(it)) func _row(it: Dictionary) -> Control: var row := HBoxContainer.new() row.custom_minimum_size = Vector2(300, 0) var nm := Label.new() nm.text = "%s ×%d" % [_name_of(int(it.get("vnum", 0))), int(it.get("count", 1))] nm.custom_minimum_size = Vector2(220, 0) nm.add_theme_font_size_override("font_size", 12) row.add_child(nm) var out := Button.new() out.text = "取出" var cell := int(it.get("cell", 0)) out.pressed.connect(func() -> void: client.safebox_checkout(cell, 1, _first_free_inv())) row.add_child(out) return row func _first_free_inv() -> int: var used := {} for it in client.get_inventory(): used[int(it.get("cell", -1))] = true for i in range(90): if not used.has(i): return i return 0 func _build(parent: Node) -> void: _root = Control.new() _root.set_anchors_preset(Control.PRESET_CENTER) _root.position = Vector2(-170, -200) _root.size = Vector2(340, 400) _root.visible = false _root.set_meta("is_titlebar", true) parent.add_child(_root) var panel := Panel.new() panel.set_anchors_preset(Control.PRESET_FULL_RECT) var sb := StyleBoxFlat.new() sb.bg_color = Color(0.06, 0.08, 0.09, 0.97) sb.set_corner_radius_all(4) panel.add_theme_stylebox_override("panel", sb) _root.add_child(panel) _title = Label.new() _title.text = "仓库" _title.position = Vector2(12, 8) _root.add_child(_title) _gold = Label.new() _gold.text = "仓库金币: 0" _gold.position = Vector2(12, 30) _gold.modulate = Color(0.95, 0.85, 0.5) _gold.add_theme_font_size_override("font_size", 12) _root.add_child(_gold) _list = VBoxContainer.new() _list.position = Vector2(12, 54) _list.add_theme_constant_override("separation", 4) _root.add_child(_list)