update
This commit is contained in:
@@ -14,6 +14,8 @@ var perspective: Game.Player # der Mensch, dessen Hand unten liegt
|
||||
var fx: BattleFx
|
||||
var selected = null # Game.Creature
|
||||
var pending = null # Cards.Card, wartet auf Ziel
|
||||
var fusing := false # Verschmelzen gewählt: zwei eigene Wesen anklicken
|
||||
var fuse_first = null # Game.Creature, erstes Wesen der Verschmelzung
|
||||
var msg_t := 0.0
|
||||
var ai_delay := 0.75
|
||||
var ai_timer := 0.0
|
||||
@@ -24,7 +26,6 @@ var reward := -1
|
||||
var ended := false
|
||||
var zoom_player = null
|
||||
var preview_timer := 0.0
|
||||
var played_ids: Array = [] # vom Menschen gespielte Karten (Statistik)
|
||||
var pad: BattleGamepad
|
||||
var gp_zone: String:
|
||||
get:
|
||||
@@ -42,9 +43,9 @@ var undo_t := 0.0
|
||||
# Ansichten (auch für Tests)
|
||||
var tiles := {}
|
||||
var hand_views: Array = []
|
||||
var shop_views: Array = []
|
||||
var own_views: Array = []
|
||||
var enemy_views: Array = []
|
||||
var trap_views: Array = []
|
||||
var hero_panels := {} # Player -> Panel
|
||||
var hero_labels := {}
|
||||
var flash_until := {} # Spielerindex -> Zeitpunkt (ms)
|
||||
@@ -52,43 +53,29 @@ var flash_until := {} # Spielerindex -> Zeitpunkt (ms)
|
||||
var hero_layer: Control
|
||||
var tile_layer: Control
|
||||
var hand_layer: Control
|
||||
var trap_layer: Control
|
||||
var shop_layer: Control
|
||||
var zoom_layer: Control
|
||||
var fx_layer: Control
|
||||
var log_box: RichTextLabel
|
||||
var preview_holder: Control
|
||||
var preview_hint: Label
|
||||
var bar_panel: Panel
|
||||
var name_label: Label
|
||||
var life_label: Label
|
||||
var energy_label: Label
|
||||
var deck_label: Label
|
||||
var income_label: Label
|
||||
var status_label: Label
|
||||
var msg_label: Label
|
||||
var b_end: Button
|
||||
var b_fuse: Button
|
||||
var b_reroll: Button
|
||||
var b_giveup: Button
|
||||
var field_label: Label
|
||||
var overlay: Control
|
||||
var result_label: Label
|
||||
var reward_label: Label
|
||||
var notice_label: Label
|
||||
var confirm: Control
|
||||
var b_save_leave: Button
|
||||
var mulligan: BattleMulligan
|
||||
var mulligan_box: Control:
|
||||
get:
|
||||
return mulligan
|
||||
var mulligan_layer: Control:
|
||||
get:
|
||||
return mulligan.layer
|
||||
var b_keep: Button:
|
||||
get:
|
||||
return mulligan.b_keep
|
||||
var b_swap: Button:
|
||||
get:
|
||||
return mulligan.b_swap
|
||||
var mulligan_selected: Array:
|
||||
get:
|
||||
return mulligan.selected
|
||||
var cursor_layer: Control
|
||||
var wait_label: Label
|
||||
var b_skip: Button
|
||||
@@ -110,7 +97,6 @@ static func online(seat: int) -> BattleScreen:
|
||||
## Unterbrochenen Kampf aus der Datei fortsetzen (siehe save_battle).
|
||||
static func resume(data: Dictionary) -> BattleScreen:
|
||||
var s := BattleScreen.new(int(data.get("n_opp", 1)), int(data.get("stage", -1)))
|
||||
s.played_ids = Array(data.get("played_ids", []))
|
||||
s.saved_game = Game.from_snapshot(data.game)
|
||||
return s
|
||||
|
||||
@@ -155,17 +141,19 @@ func _ready() -> void:
|
||||
game = saved_game
|
||||
elif stage >= 0:
|
||||
var r := Game.make_rng()
|
||||
game = Game.new_battle_with(app.profile.deck_cards(), Campaign.opponents(stage, r, app.profile.target_rating()), r, false, own_rules())
|
||||
game = Game.new_battle_with(Campaign.opponents(stage), r, false, own_rules())
|
||||
else:
|
||||
game = Game.new_battle(app.profile.deck_cards(), n_opp, null, own_rules())
|
||||
game = Game.new_battle(n_opp, Game.make_rng(), own_rules())
|
||||
smart_ai = bool(app.profile.difficulty().smart) or not counts_for_profile()
|
||||
_begin()
|
||||
|
||||
|
||||
## Eigenes Merkmal des Spielers (nach Kapitel 1 wählbar) und Zielstärke der Gegner.
|
||||
## Kartenoptik, Gegnerleben (Schwierigkeit) und das eigene Merkmal (nach Kapitel 1).
|
||||
func own_rules() -> Dictionary:
|
||||
var p: Profile = app.profile
|
||||
var rules := {"target_rating": p.target_rating(), "tier": str(p.difficulty().tier)}
|
||||
var rules := {"looks": p.looks()}
|
||||
if stage < 0:
|
||||
rules["opponent_life"] = int(p.difficulty().life)
|
||||
if p.perk != "" and p.perk_unlocked():
|
||||
rules["human_perks"] = [p.perk]
|
||||
return rules
|
||||
@@ -188,11 +176,11 @@ func _begin() -> void:
|
||||
|
||||
|
||||
func _build_static() -> void:
|
||||
Style.panel(self, Rect2(10, 205, 320, 340))
|
||||
Style.panel(self, Rect2(10, 205, 320, 290))
|
||||
Style.label(self, "Verlauf", 14, Style.MUTED, Rect2(20, 209, 200, 20))
|
||||
log_box = RichTextLabel.new()
|
||||
log_box.position = Vector2(18, 230)
|
||||
log_box.size = Vector2(304, 308)
|
||||
log_box.size = Vector2(304, 258)
|
||||
log_box.bbcode_enabled = true
|
||||
log_box.scroll_following = true
|
||||
log_box.add_theme_font_size_override("normal_font_size", 13)
|
||||
@@ -200,13 +188,12 @@ func _build_static() -> void:
|
||||
add_child(log_box)
|
||||
b_giveup = Style.button(self, "Aufgeben", Rect2(10, 553, 150, 40), func(): confirm.visible = true)
|
||||
Style.panel(self, Rect2(950, 205, 320, 380))
|
||||
preview_hint = Style.label(self, "Karte überfahren für Details", 14, Style.MUTED, Rect2(950, 345, 320, 24), "center")
|
||||
Style.panel(self, Rect2(BattleLayout.OWN_X - 10, 240, 5 * 110 + 4 * 10 + 20, 160), Style.darker(Style.PANEL, 0.8), 10)
|
||||
bar_panel = Style.panel(self, BattleLayout.BAR)
|
||||
name_label = Style.label(self, "Du", 20, Style.TEXT, Rect2(349, 421, 120, 30), "left", true)
|
||||
name_label = Style.label(self, "", 20, Style.TEXT, Rect2(349, 421, 120, 30), "left", true)
|
||||
life_label = Style.label(self, "", 24, Style.RED, Rect2(470, 418, 100, 34), "left", true)
|
||||
energy_label = Style.label(self, "", 24, Style.BLUE, Rect2(570, 418, 150, 34), "left", true)
|
||||
deck_label = Style.label(self, "", 16, Style.MUTED, Rect2(780, 424, 150, 24), "right")
|
||||
income_label = Style.label(self, "", 16, Style.MUTED, Rect2(760, 424, 170, 24), "right")
|
||||
status_label = Style.label(self, "", 15, Style.MUTED, Rect2(349, 455, 400, 24))
|
||||
msg_label = Style.label(self, "", 16, Style.ORANGE, Rect2(600, 455, 331, 24), "right", true)
|
||||
b_end = Style.button(self, "Zug beenden", Rect2(1005, 527, 210, 48), end_turn, Color("285a3c"))
|
||||
@@ -215,20 +202,21 @@ func _build_static() -> void:
|
||||
b_skip.visible = false
|
||||
b_undo = Style.button(self, "Rückgängig", Rect2(170, 553, 150, 40), undo)
|
||||
b_undo.visible = false
|
||||
field_label = Style.label(self, "", 15, Style.MUTED, Rect2(340, 211, 600, 24), "center")
|
||||
b_fuse = Style.button(self, "Verschmelzen", Rect2(10, 503, 150, 40), toggle_fuse, Color("3c2858"))
|
||||
b_fuse.visible = false
|
||||
b_reroll = Style.button(self, "", Rect2(170, 503, 150, 40), do_reroll, Color("285a5a"))
|
||||
b_reroll.add_theme_font_size_override("font_size", 14)
|
||||
wait_label = Style.label(self, "Warte auf den Host …", 22, Style.MUTED, Rect2(0, 300, 1280, 40), "center")
|
||||
wait_label.visible = false
|
||||
hero_layer = _layer()
|
||||
tile_layer = _layer()
|
||||
trap_layer = _layer()
|
||||
hand_layer = _layer()
|
||||
shop_layer = _layer()
|
||||
preview_holder = _layer()
|
||||
zoom_layer = _layer()
|
||||
fx_layer = _layer()
|
||||
cursor_layer = _layer()
|
||||
# Mulligan
|
||||
mulligan = BattleMulligan.new()
|
||||
mulligan.decided.connect(do_mulligan)
|
||||
add_child(mulligan)
|
||||
# Spielende
|
||||
overlay = _overlay()
|
||||
result_label = Style.label(overlay, "", 56, Style.GREEN, Rect2(0, 250, 1280, 80), "center", true)
|
||||
@@ -239,7 +227,6 @@ func _build_static() -> void:
|
||||
confirm = Style.overlay(self)
|
||||
Style.panel(confirm, Rect2(340, 290, 600, 200), Style.PANEL, 10, Style.MUTED, 2)
|
||||
Style.label(confirm, "Wirklich aufgeben?", 26, Style.TEXT, Rect2(340, 312, 600, 40), "center", true)
|
||||
Style.label(confirm, tr("Aufgeben beendet den Kampf ohne Münzen.") + "\n" + tr("Speichern hebt ihn für später auf."), 15, Style.MUTED, Rect2(340, 356, 600, 48), "center")
|
||||
Style.button(confirm, "Ja, aufgeben", Rect2(355, 420, 180, 46), leave, Color("5a2828"))
|
||||
b_save_leave = Style.button(confirm, "Speichern und zurück", Rect2(550, 420, 180, 46), save_and_leave, Color("285a3c"))
|
||||
b_save_leave.add_theme_font_size_override("font_size", 14)
|
||||
@@ -265,7 +252,7 @@ func resumable() -> bool:
|
||||
func save_battle() -> void:
|
||||
if not resumable() or game == null or game.winner != "":
|
||||
return
|
||||
var d := {"version": 1, "n_opp": n_opp, "stage": stage, "played_ids": played_ids, "game": game.snapshot(-1)}
|
||||
var d := {"version": 1, "n_opp": n_opp, "stage": stage, "game": game.snapshot(-1)}
|
||||
var f := FileAccess.open(app.battle_save_path(), FileAccess.WRITE)
|
||||
if f != null:
|
||||
f.store_string(JSON.stringify(d))
|
||||
@@ -371,7 +358,7 @@ func my_turn() -> bool:
|
||||
|
||||
|
||||
func any_overlay() -> bool:
|
||||
return confirm.visible or mulligan.visible or overlay.visible
|
||||
return confirm.visible or overlay.visible
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
@@ -389,7 +376,7 @@ func _input(event: InputEvent) -> void:
|
||||
KEY_ESCAPE:
|
||||
if confirm.visible:
|
||||
confirm.visible = false
|
||||
elif selected != null or pending != null or zoom_player != null:
|
||||
elif selected != null or pending != null or fusing or zoom_player != null:
|
||||
cancel_all()
|
||||
elif not any_overlay():
|
||||
confirm.visible = true
|
||||
@@ -402,9 +389,7 @@ func _input(event: InputEvent) -> void:
|
||||
if b_undo.visible:
|
||||
undo()
|
||||
KEY_ENTER, KEY_KP_ENTER:
|
||||
if mulligan.visible:
|
||||
do_mulligan([])
|
||||
elif overlay.visible:
|
||||
if overlay.visible:
|
||||
leave()
|
||||
_:
|
||||
if event.keycode >= KEY_1 and event.keycode <= KEY_9 and my_turn() and not any_overlay():
|
||||
@@ -444,8 +429,6 @@ func _process(delta: float) -> void:
|
||||
return
|
||||
var cur := game.current()
|
||||
if cur.is_human:
|
||||
if cur == perspective and not spectating() and cur.turns == 1 and not cur.mulligan_done and not mulligan.visible:
|
||||
show_mulligan()
|
||||
return
|
||||
if is_client():
|
||||
return
|
||||
@@ -477,7 +460,7 @@ func _process(delta: float) -> void:
|
||||
|
||||
|
||||
func _start_ai(cur: Game.Player) -> void:
|
||||
ai_copy = game.clone_for(cur)
|
||||
ai_copy = game.clone()
|
||||
var copy := ai_copy
|
||||
var idx := game.current_idx
|
||||
var box := ai_box
|
||||
@@ -494,7 +477,7 @@ func _finish() -> void:
|
||||
var won := game.winner == "human"
|
||||
if counts_for_profile():
|
||||
var factor: float = float(app.profile.difficulty().reward) if stage < 0 else 1.0
|
||||
reward = app.profile.record_battle(won, n_opp, app.profile.deck_cards(), stage, played_ids, game.turn, factor, game.human.life)
|
||||
reward = app.profile.record_battle(won, n_opp, stage, factor)
|
||||
app.save()
|
||||
app.sfx.play("win" if won else "lose")
|
||||
app.clear_battle_save()
|
||||
@@ -513,19 +496,21 @@ func say(m: String) -> void:
|
||||
func cancel() -> void:
|
||||
selected = null
|
||||
pending = null
|
||||
fusing = false
|
||||
fuse_first = null
|
||||
|
||||
|
||||
func play(card: Cards.Card, target) -> void:
|
||||
if is_client():
|
||||
net.send_action({"type": "play", "hand": perspective.hand.find(card), "target": Net.ref_dict(target) if target != null else null})
|
||||
return
|
||||
var before: Game = game.clone() if card.is_creature() and not is_online() else null
|
||||
var before: Game = game.clone() if not is_online() else null
|
||||
var log_len := game.log.size()
|
||||
var err := game.play_card(perspective, card, target)
|
||||
if err != "":
|
||||
say(tr(err))
|
||||
return
|
||||
# Rückgängig nur, wenn nichts weiter passiert ist (keine Effekte, Kombos, Fallen)
|
||||
# Rückgängig nur, wenn nichts weiter passiert ist (keine Effekte und keine Kombos)
|
||||
if before != null and game.events.size() == 1 and game.events[0].type == "play":
|
||||
undo_state = before
|
||||
undo_log_len = log_len
|
||||
@@ -534,6 +519,52 @@ func play(card: Cards.Card, target) -> void:
|
||||
clear_undo()
|
||||
|
||||
|
||||
## Verschmelzen an- und abwählen (zwei eigene Wesen, siehe Game.fuse).
|
||||
func toggle_fuse() -> void:
|
||||
var on := not fusing
|
||||
cancel()
|
||||
fusing = on
|
||||
say(tr("Zwei eigene Wesen wählen") if on else tr("Abgebrochen"))
|
||||
after_action()
|
||||
|
||||
|
||||
## Kauft ein Angebot aus dem Laden auf die Hand.
|
||||
func do_buy(slot: int) -> void:
|
||||
clear_undo()
|
||||
if is_client():
|
||||
net.send_action({"type": "buy", "slot": slot})
|
||||
return
|
||||
var err := game.buy(perspective, slot)
|
||||
if err != "":
|
||||
say(tr(err))
|
||||
|
||||
|
||||
## Würfelt den Laden neu (kostet Mana).
|
||||
func do_reroll() -> void:
|
||||
if not my_turn() or any_overlay():
|
||||
return
|
||||
clear_undo()
|
||||
if is_client():
|
||||
net.send_action({"type": "reroll"})
|
||||
after_action()
|
||||
return
|
||||
var err := game.reroll(perspective)
|
||||
if err != "":
|
||||
say(tr(err))
|
||||
after_action()
|
||||
|
||||
|
||||
func do_fuse(a, b) -> void:
|
||||
cancel()
|
||||
clear_undo()
|
||||
if is_client():
|
||||
net.send_action({"type": "fuse", "uid": a.uid, "other": b.uid})
|
||||
return
|
||||
var err := game.fuse(perspective, a, b)
|
||||
if err != "":
|
||||
say(tr(err))
|
||||
|
||||
|
||||
func clear_undo() -> void:
|
||||
undo_state = null
|
||||
undo_t = 0.0
|
||||
@@ -574,26 +605,23 @@ func end_turn() -> void:
|
||||
after_action()
|
||||
|
||||
|
||||
func show_mulligan() -> void:
|
||||
mulligan.open(perspective.hand)
|
||||
|
||||
|
||||
func do_mulligan(idxs: Array) -> void:
|
||||
mulligan.visible = false
|
||||
if is_client():
|
||||
net.send_action({"type": "mulligan", "hand": idxs})
|
||||
return
|
||||
var cards := []
|
||||
for i in idxs:
|
||||
cards.append(perspective.hand[i])
|
||||
game.mulligan(perspective, cards)
|
||||
after_action()
|
||||
|
||||
|
||||
func on_click(kind: String, obj) -> void:
|
||||
var g := game
|
||||
if not my_turn() or any_overlay():
|
||||
return
|
||||
if fusing:
|
||||
if kind != "own":
|
||||
cancel()
|
||||
say(tr("Abgebrochen"))
|
||||
elif fuse_first == null:
|
||||
fuse_first = obj
|
||||
say(tr("Zweites Wesen wählen"))
|
||||
elif obj == fuse_first:
|
||||
fuse_first = null
|
||||
else:
|
||||
do_fuse(fuse_first, obj)
|
||||
after_action()
|
||||
return
|
||||
if pending != null:
|
||||
var card = pending
|
||||
pending = null
|
||||
@@ -619,6 +647,8 @@ func on_click(kind: String, obj) -> void:
|
||||
after_action()
|
||||
return
|
||||
match kind:
|
||||
"shop":
|
||||
do_buy(int(obj))
|
||||
"hand":
|
||||
var ok := g.can_play(perspective, obj)
|
||||
if not ok[0]:
|
||||
@@ -647,61 +677,17 @@ func on_tile_click(cr: Game.Creature) -> void:
|
||||
on_click("enemy", cr)
|
||||
|
||||
|
||||
func show_preview(card, entered: bool) -> void:
|
||||
func show_preview(card, entered: bool, owner_looks: Dictionary = {}) -> void:
|
||||
Style.clear(preview_holder)
|
||||
if entered and card != null:
|
||||
var v := CardView.new(card, Vector2(210, 294))
|
||||
var v := CardView.new(card, Vector2(210, 294), false, Cards.RARITIES[int(owner_looks.get(card.id, 0))])
|
||||
v.position = Vector2(1005, 215)
|
||||
v.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
preview_holder.add_child(v)
|
||||
preview_hint.visible = not (entered and card != null)
|
||||
|
||||
|
||||
## Vorschau einer Handkarte mit Hinweisen auf Resonanz und Feldkombos mit dem eigenen Feld.
|
||||
func show_hand_preview(card: Cards.Card, entered: bool) -> void:
|
||||
Style.clear(preview_holder)
|
||||
preview_hint.visible = not entered
|
||||
if not entered:
|
||||
return
|
||||
var hints: Array[String] = combo_hints(card)
|
||||
var v := CardView.new(card, Vector2(190, 266) if not hints.is_empty() else Vector2(210, 294))
|
||||
v.position = Vector2(1015, 212) if not hints.is_empty() else Vector2(1005, 215)
|
||||
v.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
preview_holder.add_child(v)
|
||||
if not hints.is_empty():
|
||||
var box := RichTextLabel.new()
|
||||
box.position = Vector2(958, 480)
|
||||
box.size = Vector2(304, 46)
|
||||
box.bbcode_enabled = true
|
||||
box.scroll_active = false
|
||||
box.fit_content = false
|
||||
box.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
box.add_theme_font_size_override("normal_font_size", 11)
|
||||
box.add_theme_color_override("default_color", Style.GOLD)
|
||||
box.text = "[center]" + "\n".join(hints.slice(0, 2)) + "[/center]"
|
||||
preview_holder.add_child(box)
|
||||
|
||||
|
||||
func combo_hints(card: Cards.Card) -> Array[String]:
|
||||
var out: Array[String] = []
|
||||
if not card.is_creature():
|
||||
return out
|
||||
var partners: Array[String] = []
|
||||
var combos := {}
|
||||
for other in perspective.board:
|
||||
if other.card.elements.any(func(e): return e in card.elements):
|
||||
partners.append(other.card.title())
|
||||
for e1 in card.elements:
|
||||
for e2 in other.card.elements:
|
||||
if e1 != e2:
|
||||
var name := Cards.combo_name([e1, e2])
|
||||
if not combos.has(name):
|
||||
combos[name] = other.card.title()
|
||||
if not partners.is_empty():
|
||||
out.append("Resonanz +%d mit %s" % [mini(partners.size(), Game.RESONANCE_MAX), ", ".join(partners)])
|
||||
for name in combos:
|
||||
out.append("Feldkombo %s mit %s: %s" % [name, combos[name], Cards.FIELD_COMBO_TEXT[name]])
|
||||
return out
|
||||
show_preview(card, entered, perspective.looks)
|
||||
|
||||
|
||||
# --- Netzwerk -------------------------------------------------------------------------------
|
||||
@@ -751,8 +737,6 @@ func after_action() -> void:
|
||||
net.broadcast()
|
||||
var evs := game.events.duplicate()
|
||||
game.events.clear()
|
||||
if counts_for_profile():
|
||||
_note_events(evs)
|
||||
var centers := {}
|
||||
for ev in evs:
|
||||
for key in ["target", "attacker", "source"]:
|
||||
@@ -763,22 +747,6 @@ func after_action() -> void:
|
||||
save_battle()
|
||||
|
||||
|
||||
func _note_events(evs: Array) -> void:
|
||||
var hi := game.players.find(game.human)
|
||||
for ev in evs:
|
||||
if ev.get("player", -1) != hi:
|
||||
continue
|
||||
match ev.type:
|
||||
"play", "spell":
|
||||
played_ids.append(ev.card.id)
|
||||
if ev.type == "play":
|
||||
app.profile.daily_event("creature_played")
|
||||
"trap_set":
|
||||
app.profile.daily_event("trap_set")
|
||||
"combo":
|
||||
app.profile.daily_event("combo")
|
||||
|
||||
|
||||
# --- Ansicht angleichen --------------------------------------------------------------------
|
||||
|
||||
func refresh() -> void:
|
||||
@@ -790,9 +758,9 @@ func refresh() -> void:
|
||||
var mine := my_turn()
|
||||
var valid: Array = g.valid_targets(h, pending.target_type()) if pending != null else []
|
||||
hand_views = []
|
||||
shop_views = []
|
||||
own_views = []
|
||||
enemy_views = []
|
||||
trap_views = []
|
||||
|
||||
for o in others():
|
||||
var panel: Panel = hero_panels[o]
|
||||
@@ -813,8 +781,8 @@ func refresh() -> void:
|
||||
labels.name.add_theme_color_override("font_color", Style.TEXT if o.alive() else Style.MUTED)
|
||||
if o.alive():
|
||||
labels.life.text = "♥ %d" % maxi(o.life, 0)
|
||||
var traps_txt := (" F %d" if compact() else " Fallen %d") % o.traps.size() if not o.traps.is_empty() else ""
|
||||
labels.stats.text = ("H %d D %d%s ◆ %d" if compact() else "Hand %d Deck %d%s ◆ %d") % [o.hand.size(), o.deck.size(), traps_txt, o.max_energy]
|
||||
labels.stats.text = ("H %d ◆ %d" % [o.hand.size(), o.energy]) if compact() \
|
||||
else ("Hand %d ◆ %d (+%d)" % [o.hand.size(), o.energy, o.max_energy])
|
||||
else:
|
||||
labels.life.text = "besiegt"
|
||||
labels.life.add_theme_color_override("font_color", Style.MUTED)
|
||||
@@ -840,7 +808,8 @@ func refresh() -> void:
|
||||
tile.slot = rect.position
|
||||
tiles[cr.uid] = tile
|
||||
tile_layer.add_child(tile)
|
||||
tile.hover.connect(show_preview)
|
||||
var looks: Dictionary = p.looks
|
||||
tile.hover.connect(func(card, entered): show_preview(card, entered, looks))
|
||||
var uid := cr.uid
|
||||
tile.clicked.connect(func(_v):
|
||||
var c := game.find_creature(uid)
|
||||
@@ -852,9 +821,12 @@ func refresh() -> void:
|
||||
fx.move_to(tile, rect.position)
|
||||
var b = null
|
||||
var w := 2
|
||||
if cr == selected:
|
||||
if cr == selected or cr == fuse_first:
|
||||
b = Style.YELLOW
|
||||
w = 4
|
||||
elif fusing and p == h and mine:
|
||||
b = Style.PURPLE
|
||||
w = 3
|
||||
elif cr in valid or (selected != null and g.can_attack(selected, cr)[0]):
|
||||
b = Style.ORANGE
|
||||
w = 3
|
||||
@@ -874,15 +846,23 @@ func refresh() -> void:
|
||||
tiles.erase(uid)
|
||||
fx.fade_out(t)
|
||||
|
||||
Style.clear(trap_layer)
|
||||
if not h.traps.is_empty():
|
||||
Style.label(trap_layer, "Fallen", 13, Style.MUTED, Rect2(335, 492, 60, 20))
|
||||
for i in h.traps.size():
|
||||
var tv := CardView.new(h.traps[i], BattleLayout.trap_rect(i).size)
|
||||
tv.position = BattleLayout.trap_rect(i).position
|
||||
tv.hover.connect(show_preview)
|
||||
trap_layer.add_child(tv)
|
||||
trap_views.append(tv)
|
||||
Style.clear(shop_layer)
|
||||
if not spectating():
|
||||
for i in h.shop.size():
|
||||
var offer = h.shop[i]
|
||||
var sr := BattleLayout.shop_rect(i)
|
||||
if offer == null:
|
||||
Style.panel(shop_layer, sr, Style.darker(Style.PANEL, 0.8), 8, Style.PANEL_LIGHT, 2)
|
||||
continue
|
||||
var sv := CardView.new(offer, sr.size, false, Cards.RARITIES[int(h.looks.get(offer.id, 0))])
|
||||
sv.position = sr.position
|
||||
sv.dim = not mine or h.energy < offer.cost or h.hand.size() >= Game.MAX_HAND
|
||||
sv.hover.connect(show_hand_preview)
|
||||
var slot := i
|
||||
sv.set_meta("slot", slot) # der Platz im Laden, auch für das Gamepad
|
||||
sv.clicked.connect(func(_view): on_click("shop", slot))
|
||||
shop_layer.add_child(sv)
|
||||
shop_views.append(sv)
|
||||
|
||||
Style.clear(hand_layer)
|
||||
if spectating():
|
||||
@@ -892,7 +872,7 @@ func refresh() -> void:
|
||||
var card: Cards.Card = h.hand[i]
|
||||
var playable: bool = mine and g.can_play(h, card)[0]
|
||||
var r := BattleLayout.hand_rect(h.hand.size(), i)
|
||||
var v := CardView.new(card, r.size)
|
||||
var v := CardView.new(card, r.size, false, Cards.RARITIES[int(h.looks.get(card.id, 0))])
|
||||
v.position = r.position
|
||||
if card == pending:
|
||||
v.border = Style.YELLOW
|
||||
@@ -910,8 +890,8 @@ func refresh() -> void:
|
||||
bar_panel.add_theme_stylebox_override("panel", Style.box(Style.PANEL, 8, bar_border, 3 if bar_border != null else 0))
|
||||
name_label.text = h.name
|
||||
life_label.text = "♥ %d" % maxi(h.life, 0)
|
||||
energy_label.text = "◆ %d/%d" % [h.energy, h.max_energy]
|
||||
deck_label.text = "Deck %d" % h.deck.size()
|
||||
energy_label.text = "◆ %d" % h.energy
|
||||
income_label.text = tr("+%d je Zug") % h.max_energy
|
||||
status_label.text = (tr("Zug %d · Du bist dran") % g.turn) if mine else (tr("Zug %d · %s ist dran …") % [g.turn, g.current().name])
|
||||
if spectating():
|
||||
status_label.text = tr("Zuschauer") + " · " + status_label.text
|
||||
@@ -920,13 +900,29 @@ func refresh() -> void:
|
||||
b_skip.visible = ai_running
|
||||
b_end.visible = not ai_running and not spectating()
|
||||
b_undo.visible = undo_state != null and mine
|
||||
b_fuse.visible = mine and not spectating() and h.board.size() >= 2
|
||||
b_reroll.visible = mine and not spectating()
|
||||
b_reroll.text = tr("Neu würfeln (%d)") % Game.REROLL_COST
|
||||
b_reroll.disabled = h.energy < Game.REROLL_COST
|
||||
b_fuse.text = tr("Abbrechen") if fusing else tr("Verschmelzen")
|
||||
if g.field_element == "":
|
||||
var parts: Array[String] = []
|
||||
for e in Cards.ELEMENTS:
|
||||
parts.append("%s %d" % [tr(e), int(g.field_charge.get(e, 0))])
|
||||
field_label.text = tr("Feld: neutral") + " · " + " ".join(parts)
|
||||
field_label.add_theme_color_override("font_color", Style.MUTED)
|
||||
else:
|
||||
field_label.text = "%s: %s" % [tr(Cards.FIELD_NAMES[g.field_element]), tr(Cards.FIELD_TEXT[g.field_element])]
|
||||
field_label.add_theme_color_override("font_color", Cards.ELEMENT_COLORS[g.field_element])
|
||||
var lines: Array[String] = []
|
||||
var start := maxi(0, g.log.size() - 60)
|
||||
for i in range(start, g.log.size()):
|
||||
var line := g.log[i]
|
||||
if line.begins_with("---"):
|
||||
lines.append("[color=#6eaaf0]%s[/color]" % line)
|
||||
elif line.begins_with("Feldkombo") or line.begins_with("Falle von"):
|
||||
elif line.begins_with("Das Feld wird"):
|
||||
lines.append("[color=#8c78dc]%s[/color]" % line)
|
||||
elif line.begins_with("Feldkombo"):
|
||||
lines.append("[color=#f5c850]%s[/color]" % line)
|
||||
else:
|
||||
lines.append(line)
|
||||
@@ -954,7 +950,6 @@ func refresh() -> void:
|
||||
reward_label.text = "Gemeinsame Partie, keine Münzen"
|
||||
overlay.visible = true
|
||||
confirm.visible = false
|
||||
mulligan.visible = false
|
||||
|
||||
|
||||
func build_zoom(valid: Array) -> void:
|
||||
@@ -963,7 +958,7 @@ func build_zoom(valid: Array) -> void:
|
||||
var box := Rect2(190, 190, 900, 300)
|
||||
var back := Style.panel(zoom_layer, box, Style.PANEL, 10, Style.GOLD, 2)
|
||||
back.mouse_filter = Control.MOUSE_FILTER_STOP
|
||||
Style.label(zoom_layer, "%s · %s ♥ %d Hand %d Deck %d Fallen %d ◆ %d" % [o.name, o.title, o.life, o.hand.size(), o.deck.size(), o.traps.size(), o.max_energy],
|
||||
Style.label(zoom_layer, "%s · %s ♥ %d Hand %d ◆ %d (+%d)" % [o.name, o.title, o.life, o.hand.size(), o.energy, o.max_energy],
|
||||
18, Style.TEXT, Rect2(box.position.x + 20, box.position.y + 12, 800, 30), "left", true)
|
||||
for j in o.board.size():
|
||||
var cr: Game.Creature = o.board[j]
|
||||
|
||||
Reference in New Issue
Block a user