first commit
This commit is contained in:
507
scripts/hud.gd
Normal file
507
scripts/hud.gd
Normal file
@@ -0,0 +1,507 @@
|
||||
extends CanvasLayer
|
||||
## Komplettes Spiel-UI (programmatisch aufgebaut).
|
||||
|
||||
signal bid_pressed(count: int, face: int)
|
||||
signal challenge_pressed
|
||||
signal booster_chosen(id: String, target: int)
|
||||
signal quit_pressed
|
||||
signal pause_changed(paused: bool)
|
||||
|
||||
const ACCENT := Color(1.0, 0.82, 0.32)
|
||||
const DIM := Color(0.62, 0.64, 0.70)
|
||||
const PLAYERS_W := 300.0 ## feste Breite der Übersicht oben rechts
|
||||
|
||||
var root: Control
|
||||
var players_box: VBoxContainer
|
||||
var bid_row: HBoxContainer
|
||||
var hint_label: Label
|
||||
var banner_label: Label
|
||||
var log_label: Label
|
||||
|
||||
var count_spin: SpinBox
|
||||
var face_buttons: Array[Button] = []
|
||||
var bid_btn: Button
|
||||
var challenge_btn: Button
|
||||
var action_panel: PanelContainer
|
||||
|
||||
var boost_slot: CenterContainer
|
||||
var pause_slot: Control
|
||||
var pause_hint: Label
|
||||
var boost_panel: PanelContainer
|
||||
var boost_cards: HBoxContainer
|
||||
var boost_title: Label
|
||||
var timer_bid: Label
|
||||
var timer_boost: Label
|
||||
var target_row: HBoxContainer
|
||||
|
||||
var _face := 1
|
||||
|
||||
|
||||
## Ein gezeichnetes Würfelbild: Augen 1-6 oder ein Fragezeichen bei unbekanntem
|
||||
## Wert. Wird überall dort benutzt, wo früher Ziffern oder Sternchen standen.
|
||||
class DieIcon extends Control:
|
||||
const PIPS := {
|
||||
1: [Vector2(0, 0)],
|
||||
2: [Vector2(-1, -1), Vector2(1, 1)],
|
||||
3: [Vector2(-1, -1), Vector2(0, 0), Vector2(1, 1)],
|
||||
4: [Vector2(-1, -1), Vector2(-1, 1), Vector2(1, -1), Vector2(1, 1)],
|
||||
5: [Vector2(-1, -1), Vector2(-1, 1), Vector2(0, 0), Vector2(1, -1), Vector2(1, 1)],
|
||||
6: [Vector2(-1, -1), Vector2(-1, 0), Vector2(-1, 1),
|
||||
Vector2(1, -1), Vector2(1, 0), Vector2(1, 1)],
|
||||
}
|
||||
|
||||
var value := 0
|
||||
var _box := StyleBoxFlat.new()
|
||||
|
||||
func _init(v: int, px: float = 0.0) -> void:
|
||||
value = v
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
if px > 0.0:
|
||||
custom_minimum_size = Vector2(px, px)
|
||||
# sonst zieht der Container das Symbol in die Höhe und es wird unrund
|
||||
size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
_box.bg_color = Color(0.93, 0.92, 0.88) if v > 0 else Color(0.26, 0.28, 0.34)
|
||||
_box.set_corner_radius_all(4)
|
||||
_box.border_color = Color(0, 0, 0, 0.35)
|
||||
_box.set_border_width_all(1)
|
||||
|
||||
func _draw() -> void:
|
||||
# Immer im grössten Quadrat zeichnen, das in die Fläche passt.
|
||||
var s := minf(size.x, size.y)
|
||||
var mid := size * 0.5
|
||||
draw_style_box(_box, Rect2(mid - Vector2(s, s) * 0.5, Vector2(s, s)))
|
||||
if value <= 0:
|
||||
var f := get_theme_default_font()
|
||||
var fs := int(s * 0.66)
|
||||
var w := f.get_string_size("?", HORIZONTAL_ALIGNMENT_LEFT, -1, fs).x
|
||||
draw_string(f, Vector2(mid.x - w * 0.5, mid.y + fs * 0.35), "?",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, fs, Color(0.85, 0.88, 0.94))
|
||||
return
|
||||
for p: Vector2 in PIPS[value]:
|
||||
draw_circle(mid + p * (s * 0.24), s * 0.105, Color(0.09, 0.08, 0.1))
|
||||
var _deadline := 0.0 ## lokaler Zeitstempel, 0 = keine Frist
|
||||
var _phase := ""
|
||||
var _my_turn := false
|
||||
var _pending_boost := ""
|
||||
var _my_values: Array = []
|
||||
var _my_seat := 0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
layer = 1
|
||||
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
root = Control.new()
|
||||
root.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
root.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
add_child(root)
|
||||
_build()
|
||||
|
||||
|
||||
func _panel(col := Color(0.06, 0.07, 0.10, 0.86)) -> PanelContainer:
|
||||
var p := PanelContainer.new()
|
||||
var sb := StyleBoxFlat.new()
|
||||
sb.bg_color = col
|
||||
sb.set_corner_radius_all(8)
|
||||
sb.set_content_margin_all(10)
|
||||
sb.border_color = Color(1, 1, 1, 0.10)
|
||||
sb.set_border_width_all(1)
|
||||
p.add_theme_stylebox_override("panel", sb)
|
||||
return p
|
||||
|
||||
|
||||
func _label(text: String, size: int, col := Color.WHITE) -> Label:
|
||||
var l := Label.new()
|
||||
l.text = text
|
||||
l.add_theme_font_size_override("font_size", size)
|
||||
l.add_theme_color_override("font_color", col)
|
||||
return l
|
||||
|
||||
|
||||
func _place(c: Control, al: float, at: float, ar: float, ab: float,
|
||||
ol: float, ot: float, orr: float, ob: float) -> void:
|
||||
c.anchor_left = al
|
||||
c.anchor_top = at
|
||||
c.anchor_right = ar
|
||||
c.anchor_bottom = ab
|
||||
c.offset_left = ol
|
||||
c.offset_top = ot
|
||||
c.offset_right = orr
|
||||
c.offset_bottom = ob
|
||||
|
||||
|
||||
func _slot(al: float, at: float, ar: float, ab: float,
|
||||
ol: float, ot: float, orr: float, ob: float) -> CenterContainer:
|
||||
var cc := CenterContainer.new()
|
||||
cc.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_place(cc, al, at, ar, ab, ol, ot, orr, ob)
|
||||
root.add_child(cc)
|
||||
return cc
|
||||
|
||||
|
||||
func _build() -> void:
|
||||
# --- Spielerliste oben rechts
|
||||
var pl := _panel()
|
||||
_place(pl, 1, 0, 1, 0, -16 - PLAYERS_W, 16, -16, 16)
|
||||
pl.grow_horizontal = Control.GROW_DIRECTION_BEGIN
|
||||
pl.custom_minimum_size = Vector2(PLAYERS_W, 0)
|
||||
root.add_child(pl)
|
||||
players_box = VBoxContainer.new()
|
||||
players_box.add_theme_constant_override("separation", 4)
|
||||
pl.add_child(players_box)
|
||||
|
||||
# --- Aktuelles Gebot oben mittig
|
||||
var bp := _panel()
|
||||
_slot(0, 0, 1, 0, 300, 12, -300, 120).add_child(bp)
|
||||
var bv := VBoxContainer.new()
|
||||
bp.add_child(bv)
|
||||
bid_row = HBoxContainer.new()
|
||||
bid_row.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
bid_row.add_theme_constant_override("separation", 8)
|
||||
bv.add_child(bid_row)
|
||||
hint_label = _label("", 14, DIM)
|
||||
hint_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
bv.add_child(hint_label)
|
||||
|
||||
# --- Banner in der Bildmitte
|
||||
var banner_slot := _slot(0, 0, 1, 0, 140, 126, -140, 210)
|
||||
banner_label = _label("", 28, ACCENT)
|
||||
banner_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
banner_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
banner_label.custom_minimum_size = Vector2(1000, 0)
|
||||
banner_slot.add_child(banner_label)
|
||||
|
||||
# --- Verlauf unten links
|
||||
var lp := _panel()
|
||||
_place(lp, 0, 1, 0, 1, 16, -252, 376, -16)
|
||||
root.add_child(lp)
|
||||
log_label = _label("", 13, Color(0.82, 0.84, 0.9))
|
||||
log_label.vertical_alignment = VERTICAL_ALIGNMENT_BOTTOM
|
||||
log_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
lp.add_child(log_label)
|
||||
|
||||
# --- Aktionen unten rechts
|
||||
action_panel = _panel()
|
||||
_place(action_panel, 1, 1, 1, 1, -296, -282, -16, -16)
|
||||
action_panel.grow_vertical = Control.GROW_DIRECTION_BEGIN
|
||||
root.add_child(action_panel)
|
||||
var av := VBoxContainer.new()
|
||||
av.add_theme_constant_override("separation", 6)
|
||||
action_panel.add_child(av)
|
||||
|
||||
var head := HBoxContainer.new()
|
||||
av.add_child(head)
|
||||
var head_title := _label("Deine Ansage", 18, ACCENT)
|
||||
head_title.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
head.add_child(head_title)
|
||||
timer_bid = _label("", 18, DIM)
|
||||
head.add_child(timer_bid)
|
||||
|
||||
var row := HBoxContainer.new()
|
||||
av.add_child(row)
|
||||
var cl := _label("Anzahl", 15)
|
||||
cl.custom_minimum_size = Vector2(80, 0)
|
||||
row.add_child(cl)
|
||||
count_spin = SpinBox.new()
|
||||
count_spin.min_value = 1
|
||||
count_spin.max_value = 30
|
||||
count_spin.value = 1
|
||||
count_spin.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
row.add_child(count_spin)
|
||||
|
||||
av.add_child(_label("Augenzahl", 15))
|
||||
var frow := HBoxContainer.new()
|
||||
frow.add_theme_constant_override("separation", 4)
|
||||
av.add_child(frow)
|
||||
for f in range(1, 7):
|
||||
var b := Button.new()
|
||||
b.toggle_mode = true
|
||||
b.custom_minimum_size = Vector2(40, 40)
|
||||
b.pressed.connect(_on_face.bind(f))
|
||||
var ic := DieIcon.new(f)
|
||||
ic.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
ic.offset_left = 7
|
||||
ic.offset_top = 7
|
||||
ic.offset_right = -7
|
||||
ic.offset_bottom = -7
|
||||
b.add_child(ic)
|
||||
frow.add_child(b)
|
||||
face_buttons.append(b)
|
||||
face_buttons[0].button_pressed = true
|
||||
|
||||
bid_btn = Button.new()
|
||||
bid_btn.text = "Ansagen"
|
||||
bid_btn.custom_minimum_size = Vector2(0, 36)
|
||||
bid_btn.pressed.connect(_on_bid)
|
||||
av.add_child(bid_btn)
|
||||
|
||||
challenge_btn = Button.new()
|
||||
challenge_btn.text = "Anfechten"
|
||||
challenge_btn.custom_minimum_size = Vector2(0, 36)
|
||||
challenge_btn.pressed.connect(_on_challenge)
|
||||
av.add_child(challenge_btn)
|
||||
|
||||
# --- Booster-Overlay
|
||||
boost_slot = _slot(0, 0, 1, 1, 0, 0, 0, 0)
|
||||
boost_slot.visible = false
|
||||
boost_panel = _panel(Color(0.05, 0.06, 0.09, 0.97))
|
||||
boost_slot.add_child(boost_panel)
|
||||
var bvv := VBoxContainer.new()
|
||||
bvv.add_theme_constant_override("separation", 12)
|
||||
boost_panel.add_child(bvv)
|
||||
boost_title = _label("Wähle einen Booster", 24, ACCENT)
|
||||
boost_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
bvv.add_child(boost_title)
|
||||
timer_boost = _label("", 16, DIM)
|
||||
timer_boost.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
bvv.add_child(timer_boost)
|
||||
boost_cards = HBoxContainer.new()
|
||||
boost_cards.add_theme_constant_override("separation", 12)
|
||||
bvv.add_child(boost_cards)
|
||||
target_row = HBoxContainer.new()
|
||||
target_row.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
target_row.add_theme_constant_override("separation", 6)
|
||||
target_row.visible = false
|
||||
bvv.add_child(target_row)
|
||||
|
||||
# --- Pausenmenü (Esc)
|
||||
pause_slot = Control.new()
|
||||
pause_slot.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
pause_slot.visible = false
|
||||
root.add_child(pause_slot)
|
||||
var dim := ColorRect.new()
|
||||
dim.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
dim.color = Color(0, 0, 0, 0.55)
|
||||
pause_slot.add_child(dim)
|
||||
var pc := CenterContainer.new()
|
||||
pc.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
pause_slot.add_child(pc)
|
||||
var pp := _panel(Color(0.05, 0.06, 0.09, 0.98))
|
||||
pc.add_child(pp)
|
||||
var pv := VBoxContainer.new()
|
||||
pv.custom_minimum_size = Vector2(280, 0)
|
||||
pv.add_theme_constant_override("separation", 10)
|
||||
pp.add_child(pv)
|
||||
var pt := _label("Pause", 26, ACCENT)
|
||||
pt.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
pv.add_child(pt)
|
||||
pause_hint = _label("", 13, DIM)
|
||||
pause_hint.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
pv.add_child(pause_hint)
|
||||
var resume := Button.new()
|
||||
resume.text = "Fortsetzen"
|
||||
resume.custom_minimum_size = Vector2(0, 42)
|
||||
resume.pressed.connect(_set_paused.bind(false))
|
||||
pv.add_child(resume)
|
||||
var leave := Button.new()
|
||||
leave.text = "Verlassen"
|
||||
leave.custom_minimum_size = Vector2(0, 42)
|
||||
leave.pressed.connect(_on_quit)
|
||||
pv.add_child(leave)
|
||||
|
||||
|
||||
func _on_quit() -> void:
|
||||
quit_pressed.emit()
|
||||
|
||||
|
||||
func _on_bid() -> void:
|
||||
bid_pressed.emit(int(count_spin.value), _face)
|
||||
|
||||
|
||||
func _on_challenge() -> void:
|
||||
challenge_pressed.emit()
|
||||
|
||||
|
||||
func _unhandled_key_input(event: InputEvent) -> void:
|
||||
if event is InputEventKey and event.pressed and not event.echo \
|
||||
and event.keycode == KEY_ESCAPE:
|
||||
_set_paused(not pause_slot.visible)
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
func _set_paused(on: bool) -> void:
|
||||
pause_slot.visible = on
|
||||
if on:
|
||||
pause_hint.text = "Die Runde läuft weiter." if multiplayer.get_peers().size() > 0 \
|
||||
else "Das Spiel ist angehalten."
|
||||
pause_changed.emit(on)
|
||||
|
||||
|
||||
func _on_face(f: int) -> void:
|
||||
_face = f
|
||||
for i in face_buttons.size():
|
||||
face_buttons[i].button_pressed = (i + 1 == f)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- Updates
|
||||
|
||||
func update_state(st: Dictionary, my_seat: int) -> void:
|
||||
_my_seat = my_seat
|
||||
_my_values = st.values
|
||||
_phase = st.phase
|
||||
var left := float(st.get("time_left", 0.0))
|
||||
_deadline = 0.0 if left <= 0.0 else Time.get_ticks_msec() / 1000.0 + left
|
||||
|
||||
for c in players_box.get_children():
|
||||
c.queue_free()
|
||||
for i in st.seats.size():
|
||||
var s: Dictionary = st.seats[i]
|
||||
var turn: bool = st.phase == "bid" and i == st.turn
|
||||
var col := ACCENT if turn else (Color.WHITE if s.alive else DIM)
|
||||
var row := HBoxContainer.new()
|
||||
row.add_theme_constant_override("separation", 4)
|
||||
players_box.add_child(row)
|
||||
var nm := _label(("▸ " if turn else " ") + s.name + (" (KI)" if s.ai else ""), 15, col)
|
||||
# Der Name teilt sich den Rest der festen Panelbreite und wird
|
||||
# notfalls mit Auslassungspunkten gekürzt.
|
||||
nm.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
nm.clip_text = true
|
||||
nm.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
||||
row.add_child(nm)
|
||||
if not s.alive:
|
||||
row.add_child(_label("ausgeschieden", 14, DIM))
|
||||
continue
|
||||
for v: int in _seat_dice(st, i, my_seat):
|
||||
row.add_child(DieIcon.new(v, 22.0))
|
||||
|
||||
for c in bid_row.get_children():
|
||||
c.queue_free()
|
||||
if st.bid.is_empty():
|
||||
bid_row.add_child(_label("Noch kein Gebot", 26, ACCENT))
|
||||
else:
|
||||
bid_row.add_child(_label("%s: %d ×" % [st.seats[st.bid.seat].name, st.bid.count], 26, ACCENT))
|
||||
bid_row.add_child(DieIcon.new(int(st.bid.face), 30.0))
|
||||
|
||||
var hints: Array = []
|
||||
hints.append("Würfel im Spiel: %d" % st.total)
|
||||
if st.boost != "":
|
||||
hints.append("Dein Booster: %s" % BoosterDB.get_booster(st.boost).get("name", ""))
|
||||
if int(st.min_raise) > 1:
|
||||
hints.append("Störfeuer: du musst um mind. %d erhöhen" % st.min_raise)
|
||||
if st.must_bid:
|
||||
hints.append("Maulkorb: du musst bieten")
|
||||
hint_label.text = " | ".join(hints)
|
||||
|
||||
log_label.text = "\n".join(st.log)
|
||||
banner_label.text = st.banner
|
||||
|
||||
var my_turn: bool = st.phase == "bid" and st.turn == my_seat and st.seats[my_seat].alive
|
||||
_my_turn = my_turn
|
||||
action_panel.modulate = Color(1, 1, 1, 1.0 if my_turn else 0.45)
|
||||
bid_btn.disabled = not my_turn
|
||||
challenge_btn.disabled = not my_turn or st.bid.is_empty() or st.must_bid
|
||||
count_spin.max_value = maxi(1, int(st.total))
|
||||
var low := 1
|
||||
if not st.bid.is_empty():
|
||||
low = int(st.bid.count) + (int(st.min_raise) if int(st.min_raise) > 1 else 0)
|
||||
count_spin.min_value = clampi(low, 1, int(count_spin.max_value))
|
||||
if count_spin.value < count_spin.min_value:
|
||||
count_spin.value = count_spin.min_value
|
||||
|
||||
if st.phase != "boost":
|
||||
boost_slot.visible = false
|
||||
|
||||
|
||||
## Läuft die Restzeit herunter, solange eine Eingabe von dir erwartet wird.
|
||||
## Nach Ablauf entscheidet der Host automatisch.
|
||||
func _process(_delta: float) -> void:
|
||||
if pause_slot != null and pause_slot.visible:
|
||||
return
|
||||
var wants_boost := boost_slot != null and boost_slot.visible
|
||||
var wants_bid := _my_turn and _phase == "bid"
|
||||
if _deadline <= 0.0 or not (wants_boost or wants_bid):
|
||||
timer_bid.text = ""
|
||||
timer_boost.text = ""
|
||||
return
|
||||
var left := maxf(0.0, _deadline - Time.get_ticks_msec() / 1000.0)
|
||||
var text := "%d s" % ceili(left)
|
||||
var col := Color(0.95, 0.45, 0.4) if left <= 10.0 else DIM
|
||||
timer_bid.text = text if wants_bid else ""
|
||||
timer_bid.add_theme_color_override("font_color", col)
|
||||
timer_boost.text = "Noch %s - danach wird zufällig gewählt" % text if wants_boost else ""
|
||||
timer_boost.add_theme_color_override("font_color", col)
|
||||
|
||||
|
||||
## Eigene Würfel sind bekannt, gegnerische nicht - ausser sie wurden gespäht
|
||||
## oder es wird gerade aufgedeckt.
|
||||
func _seat_dice(st: Dictionary, seat: int, my_seat: int) -> Array:
|
||||
if seat == my_seat:
|
||||
return st.values
|
||||
var open: Array = st.get("open", [])
|
||||
if seat < open.size() and not open[seat].is_empty():
|
||||
return open[seat]
|
||||
var out: Array = []
|
||||
for _k in int(st.seats[seat].count):
|
||||
out.append(-1)
|
||||
var peek: Dictionary = st.peek
|
||||
if peek.has(seat):
|
||||
var idx := int(peek[seat][0])
|
||||
if idx >= 0 and idx < out.size():
|
||||
out[idx] = int(peek[seat][1])
|
||||
return out
|
||||
|
||||
|
||||
func set_banner(text: String) -> void:
|
||||
banner_label.text = text
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- Booster
|
||||
|
||||
func show_booster_offer(ids: Array, values: Array) -> void:
|
||||
_my_values = values
|
||||
_pending_boost = ""
|
||||
target_row.visible = false
|
||||
boost_title.text = "Wähle einen Booster"
|
||||
for c in boost_cards.get_children():
|
||||
c.queue_free()
|
||||
for id: String in ids:
|
||||
var b: Dictionary = BoosterDB.get_booster(id)
|
||||
var card := _panel(Color(0.10, 0.12, 0.17, 0.98))
|
||||
card.custom_minimum_size = Vector2(210, 170)
|
||||
var v := VBoxContainer.new()
|
||||
v.add_theme_constant_override("separation", 6)
|
||||
card.add_child(v)
|
||||
var kind_col := Color(0.5, 0.9, 0.6) if b.kind == BoosterDB.Kind.BUFF else Color(0.95, 0.5, 0.5)
|
||||
v.add_child(_label("BUFF" if b.kind == BoosterDB.Kind.BUFF else "DEBUFF", 12, kind_col))
|
||||
v.add_child(_label(b.name, 20, ACCENT))
|
||||
var d := _label(b.desc, 14, Color(0.8, 0.82, 0.88))
|
||||
d.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
d.custom_minimum_size = Vector2(190, 60)
|
||||
v.add_child(d)
|
||||
var btn := Button.new()
|
||||
btn.text = "Wählen"
|
||||
btn.pressed.connect(_pick.bind(id))
|
||||
v.add_child(btn)
|
||||
boost_cards.add_child(card)
|
||||
boost_slot.visible = true
|
||||
|
||||
|
||||
func _pick(id: String) -> void:
|
||||
if not BoosterDB.needs_target(id) or _my_values.is_empty():
|
||||
booster_chosen.emit(id, 0)
|
||||
boost_slot.visible = false
|
||||
return
|
||||
_pending_boost = id
|
||||
boost_title.text = "%s - welchen Würfel?" % BoosterDB.get_booster(id).name
|
||||
for c in boost_cards.get_children():
|
||||
c.queue_free()
|
||||
for c in target_row.get_children():
|
||||
c.queue_free()
|
||||
for i in _my_values.size():
|
||||
var b := Button.new()
|
||||
b.custom_minimum_size = Vector2(56, 56)
|
||||
b.pressed.connect(_pick_target.bind(i))
|
||||
var ic := DieIcon.new(int(_my_values[i]))
|
||||
ic.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
ic.offset_left = 10
|
||||
ic.offset_top = 10
|
||||
ic.offset_right = -10
|
||||
ic.offset_bottom = -10
|
||||
b.add_child(ic)
|
||||
target_row.add_child(b)
|
||||
target_row.visible = true
|
||||
|
||||
|
||||
func _pick_target(idx: int) -> void:
|
||||
booster_chosen.emit(_pending_boost, idx)
|
||||
boost_slot.visible = false
|
||||
target_row.visible = false
|
||||
Reference in New Issue
Block a user