update
This commit is contained in:
414
scripts/hud.gd
414
scripts/hud.gd
@@ -18,6 +18,9 @@ const TIMER_W := 52.0 ## Breite der Zeitanzeige in der Ansage-Leiste
|
||||
const INFO_W := 280.0 ## Textbreite im Erklärfeld beim Überfahren
|
||||
const GRUEN := Color(0.55, 0.84, 0.55) ## überzähliger Würfel beim Aufdecken
|
||||
const ROT := Color(0.94, 0.55, 0.52) ## fehlender Würfel beim Aufdecken
|
||||
const Icons = preload("res://scripts/icons.gd")
|
||||
## Vorrat, Topf, Erklärung, Verlauf, Protokoll - ausgelagert nach hud_panels.gd.
|
||||
var panels := preload("res://scripts/hud_panels.gd").new(self)
|
||||
|
||||
var root: Control
|
||||
var players_box: VBoxContainer
|
||||
@@ -75,162 +78,6 @@ var target_row: HBoxContainer
|
||||
var _face := 1
|
||||
|
||||
|
||||
## Gezeichnete Münze. Bilder als Dateien gibt es im Projekt nicht; alles wird
|
||||
## zur Laufzeit gemalt, so wie die Würfel auch. Vorn das Sinnbild der Wirkung
|
||||
## (Wappen), hinten die glatte Zahlseite.
|
||||
class MuenzIcon extends Control:
|
||||
const RAND := Color(0.40, 0.29, 0.11) ## Prägekante
|
||||
const FLAECHE := Color(0.78, 0.60, 0.26) ## Messing
|
||||
const GLANZ := Color(0.91, 0.75, 0.39) ## Lichtkante
|
||||
const GRAVUR := Color(0.19, 0.13, 0.04) ## eingeschlagenes Zeichen
|
||||
|
||||
var id := ""
|
||||
var farbe := GRAVUR ## Zeichenfarbe, von den Zeichenhilfen benutzt
|
||||
var kind_col := Color.WHITE
|
||||
var seite := 0 ## 0 = Wappen (Sinnbild), 1 = Zahl
|
||||
|
||||
func _init(muenze: String, col: Color, px: float) -> void:
|
||||
id = muenze
|
||||
kind_col = col
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
custom_minimum_size = Vector2(px, px)
|
||||
size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||
pivot_offset = Vector2(px, px) * 0.5
|
||||
|
||||
func _draw() -> void:
|
||||
var s := minf(size.x, size.y)
|
||||
var m := size * 0.5
|
||||
var r := s * 0.5
|
||||
draw_circle(m, r, RAND)
|
||||
draw_circle(m - Vector2(r, r) * 0.05, r * 0.95, GLANZ)
|
||||
draw_circle(m, r * 0.89, FLAECHE)
|
||||
# Der Farbring sagt, ob die Münze dir hilft oder den anderen schadet.
|
||||
draw_arc(m, r * 0.79, 0, TAU, 40, kind_col, maxf(1.0, s * 0.05))
|
||||
if seite == 1:
|
||||
draw_arc(m, r * 0.52, 0, TAU, 32, GRAVUR, maxf(1.0, s * 0.04))
|
||||
draw_circle(m, s * 0.09, GRAVUR)
|
||||
return
|
||||
_zeichen(m, s * 0.74)
|
||||
|
||||
func _zeichen(m: Vector2, s: float) -> void:
|
||||
match id:
|
||||
"peek":
|
||||
_auge(m, s)
|
||||
"count":
|
||||
_striche(m, s)
|
||||
"set_face":
|
||||
_schiefer_wuerfel(m, s * 0.50)
|
||||
"gain_die":
|
||||
_wuerfel(m + Vector2(-s * 0.10, 0), s * 0.46, 4)
|
||||
_plus(m + Vector2(s * 0.26, -s * 0.20), s * 0.20)
|
||||
"bid_up":
|
||||
_pfeil(m, s * 0.52, true)
|
||||
"gag":
|
||||
var r := Rect2(m - Vector2(s * 0.28, s * 0.16), Vector2(s * 0.56, s * 0.32))
|
||||
draw_rect(r, farbe, false, s * 0.07)
|
||||
draw_line(m + Vector2(-s * 0.28, s * 0.22), m + Vector2(s * 0.28, -s * 0.22),
|
||||
farbe, s * 0.08)
|
||||
_:
|
||||
draw_circle(m, s * 0.26, farbe)
|
||||
|
||||
## Vier Striche und einer quer - eine Strichliste, das Zeichen fürs Zählen.
|
||||
func _striche(mitte: Vector2, s: float) -> void:
|
||||
var w := maxf(1.5, s * 0.07)
|
||||
for i in 4:
|
||||
var x: float = mitte.x + (float(i) - 1.5) * s * 0.16
|
||||
draw_line(Vector2(x, mitte.y - s * 0.26), Vector2(x, mitte.y + s * 0.26), farbe, w)
|
||||
draw_line(mitte + Vector2(-s * 0.32, s * 0.20), mitte + Vector2(s * 0.32, -s * 0.20), farbe, w)
|
||||
|
||||
## Ein gekippter Würfel mit einem Auge - der wird gerade umgedreht.
|
||||
func _schiefer_wuerfel(mitte: Vector2, kante: float) -> void:
|
||||
var h := kante * 0.5
|
||||
var ecken := PackedVector2Array()
|
||||
for e: Vector2 in [Vector2(-h, -h), Vector2(h, -h), Vector2(h, h), Vector2(-h, h)]:
|
||||
ecken.append(mitte + e.rotated(0.35))
|
||||
draw_colored_polygon(ecken, farbe)
|
||||
draw_circle(mitte, kante * 0.11, FLAECHE)
|
||||
|
||||
func _wuerfel(mitte: Vector2, kante: float, augen: int) -> void:
|
||||
var r := Rect2(mitte - Vector2(kante, kante) * 0.5, Vector2(kante, kante))
|
||||
draw_rect(r, farbe, true)
|
||||
var punkt := kante * 0.10
|
||||
var weg := kante * 0.26
|
||||
for p: Vector2 in DieIcon.PIPS[augen]:
|
||||
draw_circle(mitte + p * weg, punkt, FLAECHE)
|
||||
|
||||
func _plus(mitte: Vector2, r: float) -> void:
|
||||
draw_rect(Rect2(mitte - Vector2(r, r * 0.28), Vector2(r * 2, r * 0.56)), farbe, true)
|
||||
draw_rect(Rect2(mitte - Vector2(r * 0.28, r), Vector2(r * 0.56, r * 2)), farbe, true)
|
||||
|
||||
## Der Schaft sitzt hinter der Spitze, sonst überlagern sich beide zu
|
||||
## einem Klecks.
|
||||
func _pfeil(mitte: Vector2, h: float, hoch: bool) -> void:
|
||||
var d := -1.0 if hoch else 1.0
|
||||
var schaft_y: float = mitte.y - d * h * 0.48
|
||||
var oben: float = minf(mitte.y, schaft_y)
|
||||
draw_rect(Rect2(Vector2(mitte.x - h * 0.13, oben),
|
||||
Vector2(h * 0.26, absf(mitte.y - schaft_y))), farbe, true)
|
||||
draw_colored_polygon([mitte + Vector2(0, d * h * 0.50),
|
||||
mitte + Vector2(-h * 0.34, d * h * 0.02),
|
||||
mitte + Vector2(h * 0.34, d * h * 0.02)], farbe)
|
||||
|
||||
func _auge(mitte: Vector2, s: float) -> void:
|
||||
var punkte := PackedVector2Array()
|
||||
for i in 17:
|
||||
var t := -1.0 + 2.0 * i / 16.0
|
||||
punkte.append(mitte + Vector2(t * s * 0.34, -sqrt(maxf(0.0, 1.0 - t * t)) * s * 0.20))
|
||||
for i in 17:
|
||||
var t := 1.0 - 2.0 * i / 16.0
|
||||
punkte.append(mitte + Vector2(t * s * 0.34, sqrt(maxf(0.0, 1.0 - t * t)) * s * 0.20))
|
||||
draw_polyline(punkte, farbe, s * 0.05, true)
|
||||
draw_circle(mitte, s * 0.11, farbe)
|
||||
|
||||
|
||||
## 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, bg := Color.TRANSPARENT) -> 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
|
||||
if bg.a > 0.0:
|
||||
_box.bg_color = bg
|
||||
else:
|
||||
_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
|
||||
@@ -411,7 +258,7 @@ func _build() -> void:
|
||||
b.add_theme_stylebox_override("pressed", gewaehlt)
|
||||
b.add_theme_stylebox_override("hover_pressed", gewaehlt)
|
||||
b.pressed.connect(_on_face.bind(f))
|
||||
var ic := DieIcon.new(f)
|
||||
var ic := Icons.DieIcon.new(f)
|
||||
ic.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
ic.offset_left = 7
|
||||
ic.offset_top = 7
|
||||
@@ -714,7 +561,7 @@ func update_state(st: Dictionary, my_seat: int) -> void:
|
||||
row.add_theme_constant_override("separation", 4)
|
||||
entry.add_child(row)
|
||||
for v: int in _seat_dice(st, i, my_seat):
|
||||
row.add_child(DieIcon.new(v, 21.0))
|
||||
row.add_child(Icons.DieIcon.new(v, 21.0))
|
||||
|
||||
_clear(bid_row)
|
||||
if st.bid.is_empty():
|
||||
@@ -737,12 +584,12 @@ func update_state(st: Dictionary, my_seat: int) -> void:
|
||||
bg = GRUEN
|
||||
elif i >= _actual:
|
||||
bg = ROT
|
||||
bid_row.add_child(DieIcon.new(int(st.bid.face), px, bg))
|
||||
bid_row.add_child(Icons.DieIcon.new(int(st.bid.face), px, bg))
|
||||
|
||||
_zeichne_hand(st)
|
||||
_zeichne_mitte(st, my_seat)
|
||||
_zeichne_verlauf(st, my_seat)
|
||||
_zeichne_log(st)
|
||||
panels._zeichne_hand(st)
|
||||
panels._zeichne_mitte(st, my_seat)
|
||||
panels._zeichne_verlauf(st, my_seat)
|
||||
panels._zeichne_log(st)
|
||||
|
||||
# Am Ende steht der Sieger im Endbildschirm; das Banner darüber wäre doppelt.
|
||||
banner_label.text = "" if st.phase == "over" else st.banner
|
||||
@@ -850,245 +697,6 @@ func set_banner(text: String) -> void:
|
||||
|
||||
# ---------------------------------------------------------------- Booster
|
||||
|
||||
## Der Vorrat liegt offen unten links. Ein Klick wirft die Münze sofort; nur
|
||||
## Münzen mit eigenem Ziel fragen noch nach dem Würfel. Die Wirkung steht im
|
||||
## Tooltip - auf eine Münze passt nur das Sinnbild.
|
||||
func _zeichne_hand(st: Dictionary) -> void:
|
||||
if hand_box == null:
|
||||
return
|
||||
var muenzen: Array = st.get("hand", [])
|
||||
# Wer raus ist, schaut nur noch zu. Münzen, die er nie werfen kann,
|
||||
# stünden nur klickbar im Weg.
|
||||
var dabei: bool = _my_seat < st.seats.size() and st.seats[_my_seat].alive
|
||||
hand_panel.visible = dabei and not muenzen.is_empty()
|
||||
# Geworfen wird nur am eigenen Zug. Was eine Ansage braucht, wartet auf eine.
|
||||
var spielbar: bool = st.phase == "bid" and int(st.turn) == _my_seat
|
||||
var gebot: bool = not st.bid.is_empty()
|
||||
# Jeder Zustand kommt mehrmals an. Ein Neuaufbau würde die Münze unter dem
|
||||
# Zeiger wegreissen und die Erklärung mitnehmen.
|
||||
var sig := "%s|%s|%s" % [muenzen, spielbar, gebot]
|
||||
if sig == _hand_sig:
|
||||
return
|
||||
_hand_sig = sig
|
||||
_clear(hand_box)
|
||||
for id: String in muenzen:
|
||||
var b: Dictionary = BoosterDB.get_booster(id)
|
||||
if b.is_empty():
|
||||
continue
|
||||
var col := _kind_col(b)
|
||||
|
||||
var btn := Button.new()
|
||||
btn.custom_minimum_size = Vector2(104, 120)
|
||||
btn.disabled = not spielbar or (BoosterDB.needs_bid(id) and not gebot)
|
||||
# Der gesperrte Knopf dunkelt nur seinen Rand ab; Münze und Name darauf
|
||||
# blieben sonst so hell wie bei einer werfbaren.
|
||||
btn.modulate = Color(1, 1, 1, 1.0 if not btn.disabled else 0.4)
|
||||
# Ein gesperrter Knopf meldet keine Maus mehr; die Erklärung soll aber
|
||||
# auch dann kommen, wenn gerade nicht geworfen werden darf.
|
||||
btn.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
btn.pressed.connect(_pick.bind(id))
|
||||
hand_box.add_child(btn)
|
||||
_info_an(btn, id, false, hand_panel)
|
||||
|
||||
var v := VBoxContainer.new()
|
||||
v.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
v.offset_top = 8
|
||||
v.offset_bottom = -6
|
||||
v.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
v.add_theme_constant_override("separation", 4)
|
||||
btn.add_child(v)
|
||||
|
||||
var ic := MuenzIcon.new(id, col, 72.0)
|
||||
ic.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
v.add_child(ic)
|
||||
|
||||
var name_l := _label(String(b.name), 14, col)
|
||||
name_l.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
name_l.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
v.add_child(name_l)
|
||||
|
||||
|
||||
## Der Topf: was diese Runde geworfen wurde und wem es gehört, wenn er
|
||||
## das Aufdecken gewinnt. Darunter, was gerade auf einem selbst liegt.
|
||||
## Auch hier gilt: nur neu bauen, wenn sich etwas geändert hat.
|
||||
func _zeichne_mitte(st: Dictionary, my_seat: int) -> void:
|
||||
var boosts: Array = st.get("boosts", [])
|
||||
# Der neueste Wurf muss bei jedem Zustand geprüft werden, auch ohne Neubau.
|
||||
var neu := {}
|
||||
for m in boosts:
|
||||
if int(m.get("nr", 0)) > int(neu.get("nr", 0)):
|
||||
neu = m
|
||||
_pruefe_wurf(neu, st)
|
||||
|
||||
var zaehlung: Dictionary = st.get("zaehlung", {})
|
||||
var sig := "%s|%s|%s" % [boosts, zaehlung, st.must_bid]
|
||||
if sig == _mitte_sig:
|
||||
return
|
||||
_mitte_sig = sig
|
||||
_clear(boosts_box)
|
||||
|
||||
boosts_box.add_child(_label("Topf" if not boosts.is_empty() else "Topf: leer", 13, DIM))
|
||||
for m in boosts:
|
||||
var id := String(m.get("id", ""))
|
||||
var b: Dictionary = BoosterDB.get_booster(id)
|
||||
if b.is_empty():
|
||||
continue
|
||||
var wer := int(m.get("seat", 0))
|
||||
var line := HBoxContainer.new()
|
||||
line.add_theme_constant_override("separation", 5)
|
||||
# Der Container muss die Maus annehmen, sonst gibt es kein Überfahren.
|
||||
line.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
boosts_box.add_child(line)
|
||||
_info_an(line, id, true)
|
||||
line.add_child(MuenzIcon.new(id, _kind_col(b), 22.0))
|
||||
line.add_child(_label(String(b.get("name", "")), 14, _kind_col(b)))
|
||||
if bool(m.get("stark", false)):
|
||||
line.add_child(_label("· Wappen", 14, ACCENT))
|
||||
if wer < st.seats.size():
|
||||
line.add_child(_label("von " + _short(String(st.seats[wer].name)), 13,
|
||||
ACCENT if wer == my_seat else DIM))
|
||||
# Ergebnis vom Zählen: so oft liegt die Augenzahl am Tisch.
|
||||
for f in zaehlung:
|
||||
var line := HBoxContainer.new()
|
||||
line.add_theme_constant_override("separation", 5)
|
||||
boosts_box.add_child(line)
|
||||
var von := int(zaehlung[f][0])
|
||||
var bis := int(zaehlung[f][1])
|
||||
var text := "Am Tisch: %d ×" % von if von == bis else "Am Tisch: %d–%d ×" % [von, bis]
|
||||
line.add_child(_label(text, 14, ACCENT))
|
||||
line.add_child(DieIcon.new(int(f), 18.0))
|
||||
if st.must_bid:
|
||||
boosts_box.add_child(_label("Maulkorb: du musst bieten", 14, ACCENT))
|
||||
|
||||
|
||||
## Die letzten Ansagen der Runde, die jüngste unten und hervorgehoben.
|
||||
func _zeichne_verlauf(st: Dictionary, my_seat: int) -> void:
|
||||
var verlauf: Array = st.get("verlauf", [])
|
||||
var sig := str(verlauf)
|
||||
if sig == _verlauf_sig:
|
||||
return
|
||||
_verlauf_sig = sig
|
||||
_clear(verlauf_box)
|
||||
if verlauf.is_empty():
|
||||
return
|
||||
verlauf_box.add_child(_label("Verlauf", 13, DIM))
|
||||
var ab := maxi(0, verlauf.size() - 6)
|
||||
for i in range(ab, verlauf.size()):
|
||||
var e: Dictionary = verlauf[i]
|
||||
var wer := int(e.get("seat", 0))
|
||||
if wer >= st.seats.size():
|
||||
continue
|
||||
var letzte: bool = i == verlauf.size() - 1
|
||||
var col := ACCENT if letzte else (Color(0.85, 0.87, 0.92) if wer != my_seat else Color(0.95, 0.85, 0.55))
|
||||
var line := HBoxContainer.new()
|
||||
line.add_theme_constant_override("separation", 5)
|
||||
verlauf_box.add_child(line)
|
||||
var nm := _label(_short(String(st.seats[wer].name)), 13, col)
|
||||
nm.custom_minimum_size = Vector2(64, 0)
|
||||
line.add_child(nm)
|
||||
line.add_child(_label("%d ×" % int(e.get("count", 0)), 13, col))
|
||||
line.add_child(DieIcon.new(int(e.get("face", 1)), 16.0))
|
||||
if bool(e.get("erhoeht", false)):
|
||||
line.add_child(_label("erhöht", 12, DIM))
|
||||
|
||||
|
||||
## Erklärung zu einer Münze, sobald die Maus daraufliegt. `unter` legt sie
|
||||
## unter das Feld statt darüber - oben links wäre sonst kein Platz. `anker`
|
||||
## ist, woran sie sich ausrichtet: beim Vorrat das ganze Feld, sonst läge sie
|
||||
## halb über dessen Überschrift.
|
||||
func _info_an(ctrl: Control, id: String, unter: bool, anker: Control = null) -> void:
|
||||
var an: Control = anker if anker != null else ctrl
|
||||
ctrl.mouse_entered.connect(_info_zeigen.bind(ctrl, id, unter, an))
|
||||
ctrl.mouse_exited.connect(_info_weg.bind(ctrl))
|
||||
|
||||
|
||||
func _info_zeigen(ctrl: Control, id: String, unter: bool, anker: Control) -> void:
|
||||
var b: Dictionary = BoosterDB.get_booster(id)
|
||||
if b.is_empty():
|
||||
return
|
||||
_info_ctrl = ctrl
|
||||
info_panel.visible = false
|
||||
info_name.text = String(b.name)
|
||||
info_desc.text = String(b.desc)
|
||||
info_stark.text = "Wappen: %s" % b.get("stark", "")
|
||||
# Die Höhe steht erst nach dem Umbruch fest, deshalb ein Bild später
|
||||
# setzen. Bis dahin bleibt das Feld unsichtbar, sonst springt es.
|
||||
await get_tree().process_frame
|
||||
if _info_ctrl != ctrl or not is_instance_valid(ctrl) or not is_instance_valid(anker):
|
||||
return
|
||||
info_panel.reset_size()
|
||||
var gr := info_panel.size
|
||||
var r := anker.get_global_rect()
|
||||
var y: float = r.position.y + r.size.y + 8.0 if unter else r.position.y - gr.y - 8.0
|
||||
info_panel.position = Vector2(
|
||||
clampf(r.position.x, 8.0, maxf(8.0, root.size.x - gr.x - 8.0)),
|
||||
clampf(y, 8.0, maxf(8.0, root.size.y - gr.y - 8.0)))
|
||||
info_panel.visible = true
|
||||
|
||||
|
||||
func _info_weg(ctrl: Control) -> void:
|
||||
if _info_ctrl != ctrl:
|
||||
return
|
||||
_info_ctrl = null
|
||||
info_panel.visible = false
|
||||
|
||||
|
||||
func _kind_col(b: Dictionary) -> Color:
|
||||
return Color(0.5, 0.9, 0.6) if b.kind == BoosterDB.Kind.BUFF else Color(0.95, 0.5, 0.5)
|
||||
|
||||
|
||||
## Jeder Wurf hat eine laufende Nummer. Steigt sie, ist eine neue Münze
|
||||
## gefallen und wird gezeigt. Zu Rundenbeginn ist die Mitte leer, dann faengt
|
||||
## die Zählung wieder bei null an.
|
||||
func _pruefe_wurf(neu: Dictionary, st: Dictionary) -> void:
|
||||
var nr := int(neu.get("nr", 0))
|
||||
if nr == 0:
|
||||
_letzter_wurf = 0
|
||||
return
|
||||
if nr <= _letzter_wurf:
|
||||
return
|
||||
_letzter_wurf = nr
|
||||
var seat := int(neu.get("seat", 0))
|
||||
if seat >= st.seats.size():
|
||||
return
|
||||
_zeig_wurf(String(neu.get("id", "")), bool(neu.get("stark", false)),
|
||||
_short(String(st.seats[seat].name)))
|
||||
|
||||
|
||||
## Der Ausgang steht schon fest - der Host hat ihn ausgewürfelt. Die Münze
|
||||
## fällt in 3D auf den Tisch; hier steht der Text dazu, kurz und dann weg.
|
||||
func _zeig_wurf(id: String, stark: bool, wer: String) -> void:
|
||||
var b: Dictionary = BoosterDB.get_booster(id)
|
||||
if b.is_empty():
|
||||
return
|
||||
wurf_label.text = "%s wirft %s\n%s" % [wer, b.name,
|
||||
"Wappen - " + String(b.get("stark", "")) if stark else "Zahl - Grundwirkung"]
|
||||
wurf_label.add_theme_color_override("font_color", ACCENT if stark else DIM)
|
||||
wurf_slot.visible = true
|
||||
Klang.muenze()
|
||||
if _wurf_tween != null and _wurf_tween.is_valid():
|
||||
_wurf_tween.kill()
|
||||
_wurf_tween = create_tween()
|
||||
_wurf_tween.tween_interval(2.6)
|
||||
_wurf_tween.tween_callback(func() -> void: wurf_slot.visible = false)
|
||||
|
||||
|
||||
## Die letzten Zeilen des Spielprotokolls.
|
||||
func _zeichne_log(st: Dictionary) -> void:
|
||||
var zeilen: Array = st.get("log", [])
|
||||
var sig := str(zeilen)
|
||||
if sig == _log_sig:
|
||||
return
|
||||
_log_sig = sig
|
||||
_clear(log_box)
|
||||
var ab := maxi(0, zeilen.size() - 5)
|
||||
for i in range(ab, zeilen.size()):
|
||||
var l := _label(String(zeilen[i]), 13, ACCENT if i == zeilen.size() - 1 else DIM)
|
||||
l.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
l.custom_minimum_size = Vector2(340, 0)
|
||||
log_box.add_child(l)
|
||||
|
||||
|
||||
|
||||
func _pick(id: String) -> void:
|
||||
# Handy: erster Tipp öffnet nur die Erklärung (die kommt über den
|
||||
@@ -1110,7 +718,7 @@ func _pick(id: String) -> void:
|
||||
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]))
|
||||
var ic := Icons.DieIcon.new(int(_my_values[i]))
|
||||
ic.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
ic.offset_left = 10
|
||||
ic.offset_top = 10
|
||||
|
||||
Reference in New Issue
Block a user