LuneSession hält den autoritativen Matchzustand; Clients senden nur Absichten. Fremde Sitze, veraltete Befehle und Doppelkäufe sind geprüft, Disconnect führt zur Bot-Übernahme statt zum Kernverlust. Exporte und entpackbare Demos 0.16.0-m4 für Linux und Windows.
119 lines
5 KiB
GDScript
119 lines
5 KiB
GDScript
extends MainMenu
|
|
## The Phase 20A menu shell retitled for Champions of Luneraria. Match options here are
|
|
## the new mode's options (own Bund, lane, seed); they never touch the legacy GameState.
|
|
|
|
signal host_requested(port: int, display_name: String)
|
|
signal join_requested(address: String, port: int, display_name: String)
|
|
|
|
var bund: String = "wurzelbund"
|
|
var lane: String = "mid"
|
|
var lane_choice: ChoiceGroup
|
|
var _net_name: LineEdit
|
|
var _net_address: LineEdit
|
|
var _net_port: LineEdit
|
|
|
|
func _ready() -> void:
|
|
super._ready()
|
|
title_label.text = "CHAMPIONS"
|
|
subtitle_label.text = "OF LUNERARIA"
|
|
subtitle_label.theme_type_variation = "TitleLabel"
|
|
subtitle_label.add_theme_font_size_override("font_size", 54)
|
|
title_label.add_theme_font_size_override("font_size", 64)
|
|
var tagline := Label.new()
|
|
tagline.text = "DREI LANES · 3 GEGEN 3 · AUTOBATTLER"
|
|
tagline.theme_type_variation = "SubtitleLabel"
|
|
brand_names.add_child(tagline)
|
|
lore_label.text = "Führe deine Armee über drei Lanes. Die Partie endet erst, wenn ein Ancient fällt."
|
|
emblem_rect.texture = load("res://assets/ui/emblems/luneraria.svg")
|
|
version_label.text = "Prototyp %s · 1 Mensch + 5 Bots oder 6 über Direktverbindung" % str(ProjectSettings.get_setting("application/config/version", ""))
|
|
_title_caption.text = "Glutpakt und Wurzelbund an den Ufern der Grünen Kluft"
|
|
_retarget_setup()
|
|
|
|
func _retarget_setup() -> void:
|
|
# Replace the Saumwacht-only options (match length, rival, AI level, timed build).
|
|
faction_choice.item_selected.disconnect(faction_choice.item_selected.get_connections()[0].callable)
|
|
faction_choice.item_selected.connect(func(index: int) -> void:
|
|
bund = DataCatalog.FACTIONS[index]
|
|
sync())
|
|
var body: VBoxContainer = mode_choice.get_parent()
|
|
var at: int = mode_choice.get_index() - 1
|
|
for node: Node in [mode_choice, length_summary, _advanced_button.get_parent(), _advanced]:
|
|
node.visible = false
|
|
body.get_child(at).visible = false
|
|
var heading := Label.new()
|
|
heading.text = "DEINE LANE"
|
|
heading.theme_type_variation = "SectionLabel"
|
|
body.add_child(heading)
|
|
body.move_child(heading, at)
|
|
lane_choice = ChoiceGroup.new(true)
|
|
lane_choice.add_option("Top", "oberer Korridor")
|
|
lane_choice.add_option("Mid", "direkter Weg")
|
|
lane_choice.add_option("Bottom", "unterer Korridor")
|
|
body.add_child(lane_choice)
|
|
body.move_child(lane_choice, at + 1)
|
|
lane_choice.item_selected.connect(func(index: int) -> void:
|
|
lane = LuneMap.LANES[index]
|
|
sync())
|
|
var rules := Label.new()
|
|
rules.theme_type_variation = "MutedLabel"
|
|
rules.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
|
rules.text = "Team Blau (Südwest) mit zwei Bot-Verbündeten gegen drei Bots in Team Rot. Kein Rundenlimit: Es gewinnt, wer den gegnerische Ancient zerstört. Für sechs Menschen hosten oder beitreten; freie Plätze bleiben Bots. Der Host ist autoritativ."
|
|
body.add_child(rules)
|
|
body.move_child(rules, at + 2)
|
|
var net_heading := Label.new()
|
|
net_heading.text = "NETZWERK · DIREKTVERBINDUNG"
|
|
net_heading.theme_type_variation = "SectionLabel"
|
|
body.add_child(net_heading)
|
|
_net_name = LineEdit.new()
|
|
_net_name.placeholder_text = "Anzeigename"
|
|
_net_name.text = "Spieler"
|
|
body.add_child(_net_name)
|
|
var net_row := HBoxContainer.new()
|
|
_net_address = LineEdit.new()
|
|
_net_address.placeholder_text = "Host-Adresse"
|
|
_net_address.text = "127.0.0.1"
|
|
_net_address.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
_net_port = LineEdit.new()
|
|
_net_port.placeholder_text = "Port"
|
|
_net_port.text = "24571"
|
|
_net_port.custom_minimum_size.x = 90
|
|
net_row.add_child(_net_address)
|
|
net_row.add_child(_net_port)
|
|
body.add_child(net_row)
|
|
var buttons := HBoxContainer.new()
|
|
var host_btn := Button.new()
|
|
host_btn.text = "Hosten"
|
|
host_btn.tooltip_text = "Partie eröffnen. Freie Plätze sind Bots."
|
|
host_btn.pressed.connect(func() -> void: host_requested.emit(int(_net_port.text), _net_name.text))
|
|
var join_btn := Button.new()
|
|
join_btn.text = "Beitreten"
|
|
join_btn.tooltip_text = "Mit Host und Port verbinden."
|
|
join_btn.pressed.connect(func() -> void: join_requested.emit(_net_address.text.strip_edges(), int(_net_port.text), _net_name.text))
|
|
buttons.add_child(host_btn)
|
|
buttons.add_child(join_btn)
|
|
body.add_child(buttons)
|
|
|
|
func sync() -> void:
|
|
super.sync()
|
|
if lane_choice == null:
|
|
return
|
|
faction_choice.select(DataCatalog.FACTIONS.find(bund))
|
|
lane_choice.select(LuneMap.LANES.find(lane))
|
|
_style_heading.text = "SPIELWEISE · " + DataCatalog.FACTION_NAMES[bund].to_upper()
|
|
var lines: PackedStringArray = []
|
|
for fact: String in FactionChoice.PROFILES[bund].facts:
|
|
lines.append("• " + fact)
|
|
_style_facts.text = "\n".join(lines)
|
|
_timed_hint.text = "Planung wartet auf dich · Leertaste startet den Kampf"
|
|
var names: PackedStringArray = []
|
|
for entry: Array in Stage.SETUPS[bund].figures:
|
|
names.append(str(DataCatalog.get_unit(entry[0]).display_name))
|
|
_setup_caption.text = "IM BILD " + " · ".join(names)
|
|
if screen == Screen.SETUP and _active and stage.current_shot() != bund:
|
|
stage.set_shot_named(bund, reduced_motion)
|
|
|
|
func _setup_shot() -> String:
|
|
return bund
|
|
|
|
func _on_title_primary() -> void:
|
|
show_screen(Screen.SETUP)
|