class_name LuneChampionPanel extends HBoxContainer ## Attack champions: target lane, the three champion cards (copper, hatched, "1 WELLE") and ## the own bookings ("Einsatz in Welle 15 – MID"). Champions are bought in planning n, fight ## once in wave n+1 and then vanish; they never join the permanent army. signal command_requested(command: Dictionary) var target_lane: String = "mid" var cards: Dictionary = {} var _lane_buttons: Dictionary = {} var _bookings: VBoxContainer var _count: Label var _signature: String = "" func _init() -> void: add_theme_constant_override("separation", 10) var lanes := VBoxContainer.new() lanes.add_theme_constant_override("separation", 4) add_child(lanes) LuneUiTheme.label("ZIEL", "HudCaps", lanes) for lane: String in LuneMap.LANES: var button := LuneUiTheme.button(LuneMap.LANE_NAMES[lane].to_upper(), "HudToggle", lanes) button.toggle_mode = true button.custom_minimum_size = Vector2(86, 0) button.set_pressed_no_signal(lane == target_lane) button.pressed.connect(func() -> void: target_lane = lane _signature = "" for other: String in _lane_buttons: (_lane_buttons[other] as Button).set_pressed_no_signal(other == lane)) _lane_buttons[lane] = button LuneTooltip.attach(button, func() -> Dictionary: return {"title": "Ziel-Lane %s" % LuneMap.LANE_NAMES[lane], "text": "Gebuchte Champions greifen in der nächsten Welle auf dieser Lane an."}) var row := HBoxContainer.new() row.add_theme_constant_override("separation", 6) add_child(row) for champion_id: String in LuneContent.CHAMPIONS: var spec: Dictionary = LuneContent.CHAMPIONS[champion_id] var card := LuneUnitCard.new() row.add_child(card) var role_key: String = {"ch_schutz": "schutz", "ch_druck": "druck", "ch_belagerung": "siege"}.get(champion_id, "melee") card.setup(champion_id, str(spec.model), str(spec.name), role_key, int(spec.cost), "", true) card.pressed.connect(func() -> void: command_requested.emit({"type": "champion_book", "champion_id": champion_id, "lane": target_lane})) cards[champion_id] = card LuneTooltip.attach(card, _tip.bind(champion_id)) var right := VBoxContainer.new() right.add_theme_constant_override("separation", 4) right.size_flags_horizontal = Control.SIZE_EXPAND_FILL right.custom_minimum_size.x = 200 add_child(right) var head := HBoxContainer.new() right.add_child(head) LuneUiTheme.label("EINSÄTZE", "HudCaps", head).size_flags_horizontal = Control.SIZE_EXPAND_FILL _count = LuneUiTheme.label("", "HudMuted", head) _bookings = VBoxContainer.new() _bookings.add_theme_constant_override("separation", 3) right.add_child(_bookings) var _model: LuneHudModel func apply(model: LuneHudModel) -> void: _model = model var bookings: Array = model.own_bookings() var fresh: int = (model.me().draft.new_bookings as Array).size() if model.planning() else 0 var gold: int = model.own_gold() var signature: String = "%s|%d|%s|%s|%s|%d" % [str(bookings), gold, model.planning(), model.locked(), target_lane, model.state.round_number] if signature == _signature: return _signature = signature var can_act: bool = model.planning() and not model.locked() for champion_id: String in cards: var card: LuneUnitCard = cards[champion_id] var cost: int = int(LuneContent.CHAMPIONS[champion_id].cost) var why: String = "" if not model.planning(): why = "Buchungen nur in der Planung." elif model.locked(): why = "Bereit gemeldet – die Planung ist verbindlich." elif fresh >= LuneContent.MAX_BOOKINGS: why = "Höchstens %d Champions pro Runde." % LuneContent.MAX_BOOKINGS elif gold < cost: why = "Es fehlen %d Gold." % (cost - gold) card.set_available(why.is_empty(), why, not can_act, gold < cost) _count.text = "%d/%d diese Runde" % [fresh, LuneContent.MAX_BOOKINGS] for child: Node in _bookings.get_children(): child.free() if bookings.is_empty(): var hint := LuneUiTheme.label("Keine Champions gebucht. Kauf jetzt – Einsatz in Welle %d." % (model.state.round_number + (1 if model.planning() else 2)), "HudMuted", _bookings) hint.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART return for booking: Dictionary in bookings: var line := HBoxContainer.new() line.add_theme_constant_override("separation", 6) _bookings.add_child(line) LuneGlyph.make("hourglass", LuneUiTheme.CHAMPION, 14.0, line) var running: bool = int(booking.deploy_round) == model.state.round_number var texts := VBoxContainer.new() texts.add_theme_constant_override("separation", -2) texts.size_flags_horizontal = Control.SIZE_EXPAND_FILL line.add_child(texts) LuneUiTheme.label(str(LuneContent.CHAMPIONS[booking.champion_id].name), "HudText", texts) LuneUiTheme.label("Einsatz in Welle %d – %s%s" % [int(booking.deploy_round), LuneMap.LANE_NAMES[booking.lane].to_upper(), " (jetzt)" if running else ""], "HudMuted", texts) if bool(booking.get("fresh", false)): var cancel := LuneUiTheme.button("×", "HudIconButton", line) cancel.disabled = not can_act var uid: String = str(booking.uid) cancel.pressed.connect(func() -> void: command_requested.emit({"type": "champion_cancel", "uid": uid})) LuneTooltip.attach(cancel, func() -> Dictionary: return {"title": "Buchung zurücknehmen", "text": "Volle Erstattung, solange die Planung läuft."}) func _tip(champion_id: String) -> Dictionary: var spec: Dictionary = LuneContent.CHAMPIONS[champion_id] var round_number: int = _model.state.round_number + 1 if _model != null else 2 var definition: Dictionary = LuneContent.champion_definition(champion_id, round_number, _model.state.balance if _model != null else LuneBalance.default_balance()) var card: LuneUnitCard = cards[champion_id] return {"title": "%s · Angriffschampion" % spec.name, "glyph": "champion", "glyph_color": LuneUiTheme.CHAMPION, "subtitle": "%s · %d Gold · Einsatz in Welle %d – %s" % [spec.role, int(spec.cost), round_number, LuneMap.LANE_NAMES[target_lane].to_upper()], "stats": LuneStats.rows(definition), "text": str(spec.text), "note": "Einmaliger Einsatz: kämpft eine Welle lang und verschwindet danach. Die Ankündigung ist für alle sichtbar; sein Tod bringt dem Gegner %d Gold." % int(definition.bounty), "warn": card.reason}