saumwacht-godot/scripts/luneraria/ui/components/unit_card.gd
Martin Stickelbroeck 1b540f2a55 G3 (Zwischenstand): neues Ingame-HUD; Projekt wechselt nach Unity
Nicht abgenommen: Nach dem ersten Spieltest wurde entschieden, Champions of
Luneraria nach Unity 6 zu portieren. Dieser Stand ist die Referenz für das
HUD im Unity-Projekt (../luneraria-unity).

- HUD neu aus Komponenten mit eigenem Theme, Porträts aus den echten Modellen
  (einmal gerendert, zwischengespeichert), Lane-Übersicht mit deterministischer
  Bedrohung aus öffentlichem Zustand, Bossgrotte, nächste Welle, Ereignisse,
  Minimap mit zusammengefassten Armeen, Held/Items/Talente, Einheitendetails,
  Angriffschampions, Bereit-Sperre, UI-Größe, Team-Formen statt nur Farben
- Privatsphäre über LuneHudModel: fremdes Gold und fremde Entwürfe erscheinen nie
- Keine Regeländerung: Regeln 91/91, M2 73/73, Netz 43/43; verify_g3 715/715;
  verify_m1 38/38 und verify_m2 14/14 mit angepassten UI-Treibern
- Spieltest bis Welle 8 über die echte Oberfläche, Befunde in G3-HUD.md
- HELDEN-KONZEPT.md: vom Projektinhaber vorgegebene Helden (nicht umgesetzt)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 19:59:55 +02:00

104 lines
4.4 KiB
GDScript

class_name LuneUnitCard
extends Button
## Purchase card: real-model portrait, name, role, gold price, hotkey and availability.
## The champion variant uses the copper card style, a hatched portrait field and an
## "EINMALIG" tag, so temporary attack champions never read like permanent troops.
const ROLE_GLYPHS: Dictionary = {"front": "tank", "melee": "melee", "ranged": "ranged", "splash": "splash", "support": "support",
"schutz": "tank", "druck": "tempo", "siege": "siege"}
const ROLE_TEXT: Dictionary = {"front": "Tank", "melee": "Nahkampf", "ranged": "Fernkampf", "splash": "Fläche", "support": "Support",
"schutz": "Schutz", "druck": "Druck", "siege": "Belagerung"}
var type_id: String = ""
var champion: bool = false
var cost: int = 0
var reason: String = ""
var portrait: LunePortraitRect
var _name: Label
var _role_glyph: LuneGlyph
var _role: Label
var _coin: LuneGlyph
var _cost: Label
var _key: Label
var _tag: HBoxContainer
var _lock: LuneGlyph
func _init() -> void:
theme_type_variation = "HudCard"
focus_mode = Control.FOCUS_ALL
mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
custom_minimum_size = Vector2(116, 132)
var column := VBoxContainer.new()
column.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
column.offset_left = 6
column.offset_right = -6
column.offset_top = 6
column.offset_bottom = -5
column.add_theme_constant_override("separation", 1)
column.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(column)
portrait = LunePortraitRect.new()
portrait.custom_minimum_size = Vector2(0, 62)
portrait.size_flags_vertical = Control.SIZE_EXPAND_FILL
column.add_child(portrait)
_key = LuneUiTheme.label("", "HudCaps", portrait)
_key.position = Vector2(4, 1)
_key.add_theme_color_override("font_color", LuneUiTheme.BRONZE_LIGHT)
_tag = HBoxContainer.new()
_tag.add_theme_constant_override("separation", 2)
_tag.mouse_filter = Control.MOUSE_FILTER_IGNORE
_tag.visible = false
portrait.add_child(_tag)
_tag.set_anchors_and_offsets_preset(Control.PRESET_TOP_RIGHT)
_tag.grow_horizontal = Control.GROW_DIRECTION_BEGIN
_tag.offset_right = -3
_tag.offset_top = 1
LuneGlyph.make("hourglass", LuneUiTheme.CHAMPION, 13.0, _tag)
var once := LuneUiTheme.label("1 WELLE", "HudCaps", _tag)
once.add_theme_color_override("font_color", LuneUiTheme.CHAMPION)
_lock = LuneGlyph.make("lock", LuneUiTheme.MUTED, 18.0, portrait)
_lock.set_anchors_and_offsets_preset(Control.PRESET_CENTER)
_lock.visible = false
_name = LuneUiTheme.label("", "HudText", column)
_name.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
_name.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
_name.clip_text = true
var role_row := HBoxContainer.new()
role_row.alignment = BoxContainer.ALIGNMENT_CENTER
role_row.add_theme_constant_override("separation", 4)
role_row.mouse_filter = Control.MOUSE_FILTER_IGNORE
column.add_child(role_row)
_role_glyph = LuneGlyph.make("", LuneUiTheme.MUTED, 14.0, role_row)
_role = LuneUiTheme.label("", "HudMuted", role_row)
var cost_row := HBoxContainer.new()
cost_row.alignment = BoxContainer.ALIGNMENT_CENTER
cost_row.add_theme_constant_override("separation", 4)
cost_row.mouse_filter = Control.MOUSE_FILTER_IGNORE
column.add_child(cost_row)
_coin = LuneGlyph.make("coin", LuneUiTheme.GOLD, 15.0, cost_row)
_cost = LuneUiTheme.label("", "HudValue", cost_row)
func setup(id: String, model_id: String, title: String, role_key: String, price: int, hotkey: String = "", is_champion: bool = false) -> void:
type_id = id
champion = is_champion
cost = price
theme_type_variation = "HudChampionCard" if champion else "HudCard"
portrait.show_model(model_id)
_name.text = title
_role_glyph.glyph = ROLE_GLYPHS.get(role_key, "melee")
_role.text = ROLE_TEXT.get(role_key, role_key)
_cost.text = str(price)
_key.text = hotkey
_key.visible = not hotkey.is_empty()
_tag.visible = champion
portrait.hatch = Color(LuneUiTheme.CHAMPION, .13) if champion else Color(0, 0, 0, 0)
## ok = purchasable now; otherwise `why` explains it (tooltip) and the card greys out.
func set_available(ok: bool, why: String = "", locked: bool = false, unaffordable: bool = false) -> void:
reason = why
if disabled != (not ok):
disabled = not ok
portrait.dimmed = not ok
_lock.visible = locked
_cost.add_theme_color_override("font_color", LuneUiTheme.DANGER if unaffordable else LuneUiTheme.BRIGHT)
_name.add_theme_color_override("font_color", LuneUiTheme.MUTED if not ok else LuneUiTheme.TEXT)