class_name LuneNextWave extends PanelContainer ## What the coming wave brings: monster types with counts (identical for both sides and every ## lane), new types, announced attack champions and an announced boss. Dangers for the own ## team are highlighted. In combat the panel shrinks to one line about the following wave. var _title: Label var _round: Label var _rows: VBoxContainer var _extra: VBoxContainer var _note: Label var _signature: String = "" var compact: bool = false func _init() -> void: theme_type_variation = "HudPanelTight" mouse_filter = Control.MOUSE_FILTER_STOP var column := VBoxContainer.new() column.add_theme_constant_override("separation", 4) column.mouse_filter = Control.MOUSE_FILTER_IGNORE add_child(column) var head := HBoxContainer.new() head.mouse_filter = Control.MOUSE_FILTER_IGNORE column.add_child(head) _title = LuneUiTheme.label("NÄCHSTE WELLE", "HudCaps", head) _title.size_flags_horizontal = Control.SIZE_EXPAND_FILL _round = LuneUiTheme.label("", "HudValue", head) _rows = VBoxContainer.new() _rows.add_theme_constant_override("separation", 2) _rows.mouse_filter = Control.MOUSE_FILTER_IGNORE column.add_child(_rows) _note = LuneUiTheme.label("", "HudMuted", column) _note.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART _extra = VBoxContainer.new() _extra.add_theme_constant_override("separation", 3) _extra.mouse_filter = Control.MOUSE_FILTER_IGNORE column.add_child(_extra) func apply(wave: Dictionary, own_team: int, fighting: bool) -> void: var signature: String = "%s|%d|%s" % [str(wave), own_team, fighting] if signature == _signature: return _signature = signature compact = fighting _title.text = "DANACH" if fighting else "NÄCHSTE WELLE" _round.text = "WELLE %d" % int(wave.round) for child: Node in _rows.get_children(): child.free() for child: Node in _extra.get_children(): child.free() var monsters: Array = wave.monsters if fighting: var parts: PackedStringArray = [] for monster: Dictionary in monsters: parts.append("%d× %s%s" % [int(monster.count), monster.name, " (neu)" if monster.new else ""]) _note.text = ", ".join(parts) + " je Lane" return for monster: Dictionary in monsters: var row := HBoxContainer.new() row.add_theme_constant_override("separation", 7) row.mouse_filter = Control.MOUSE_FILTER_PASS _rows.add_child(row) var portrait := LunePortraitRect.new() portrait.custom_minimum_size = Vector2(30, 30) row.add_child(portrait) portrait.show_model(str(monster.id)) var count := LuneUiTheme.label("%d×" % int(monster.count), "HudValue", row) count.custom_minimum_size.x = 30 var title := LuneUiTheme.label(str(monster.name), "HudText", row) title.size_flags_horizontal = Control.SIZE_EXPAND_FILL title.clip_text = true title.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS LuneGlyph.make("armor", LuneUiTheme.MUTED, 13.0, row) LuneUiTheme.label(DataCatalog.ARMOR_NAMES[int(monster.armor)], "HudMuted", row) if monster.new: var badge := LuneStatusBadge.new() badge.set_state("NEU", LuneUiTheme.WARN) row.add_child(badge) var data: Dictionary = monster LuneTooltip.attach(row, func() -> Dictionary: return {"title": str(data.name), "subtitle": "Monster der Welle %d" % int(wave.round), "stats": [["heart", "Leben", LuneUiTheme.number(data.hp)], ["sword", "Schaden/Treffer", LuneUiTheme.decimal(data.damage)], ["range", "Reichweite", "%s m" % LuneUiTheme.decimal(data.range)], ["armor", "Rüstung", DataCatalog.ARMOR_NAMES[int(data.armor)]]], "note": "Beide Teams erhalten auf jeder Lane dieselbe Welle."}) # Counter hint as in Legion TD 2: the armour most of the wave wears and the damage type # that hits it for 130 % (LuneUnit.DAMAGE_MATRIX). var armour_count: Array[int] = [0, 0, 0] for monster: Dictionary in monsters: armour_count[int(monster.armor)] += int(monster.count) var main_armour: int = armour_count.find(armour_count.max()) var counter: int = 0 for attack: int in range(3): if is_equal_approx(float(LuneUnit.DAMAGE_MATRIX[attack][main_armour]), 1.30): counter = attack _note.text = "%d Monster je Lane · beide Seiten gleich\nMeist %s: %s trifft stark" % [int(wave.count), DataCatalog.ARMOR_NAMES[main_armour], DataCatalog.DAMAGE_NAMES[counter]] var champions: Array = wave.champions var boss: Dictionary = wave.boss if champions.is_empty() and boss.is_empty(): return LuneUiTheme.label("ANGEKÜNDIGT", "HudCaps", _extra) for entry: Dictionary in champions: var hostile: bool = not bool(entry.own) var row := HBoxContainer.new() row.add_theme_constant_override("separation", 6) row.mouse_filter = Control.MOUSE_FILTER_IGNORE _extra.add_child(row) LuneGlyph.make("champion", LuneUiTheme.DANGER if hostile else LuneUiTheme.CHAMPION, 15.0, row) var text := LuneUiTheme.label("%s → %s" % [entry.name, LuneMap.LANE_NAMES[entry.lane].to_upper()], "HudText", row) text.size_flags_horizontal = Control.SIZE_EXPAND_FILL var badge := LuneStatusBadge.new() badge.set_state("GEGEN EUCH" if hostile else "FÜR EUCH", LuneUiTheme.DANGER if hostile else LuneUiTheme.GOOD) row.add_child(badge) if not boss.is_empty(): var hostile_boss: bool = not bool(boss.own) var row := HBoxContainer.new() row.add_theme_constant_override("separation", 6) row.mouse_filter = Control.MOUSE_FILTER_IGNORE _extra.add_child(row) LuneGlyph.make("crown", LuneUiTheme.DANGER if hostile_boss else LuneUiTheme.team_color(own_team), 16.0, row) var text := LuneUiTheme.label("Schlundkrone → %s" % LuneMap.LANE_NAMES[boss.lane].to_upper(), "HudText", row) text.size_flags_horizontal = Control.SIZE_EXPAND_FILL var badge := LuneStatusBadge.new() badge.set_state("GEGEN EUCH" if hostile_boss else "FÜR EUCH", LuneUiTheme.DANGER if hostile_boss else LuneUiTheme.GOOD, "crown") row.add_child(badge)