178 lines
5.7 KiB
GDScript
178 lines
5.7 KiB
GDScript
extends CanvasLayer
|
|
## Fadenkreuz, Statusleiste, Interaktionshinweis und Meldungen.
|
|
|
|
const Cargo = preload("res://scripts/cargo.gd")
|
|
const Defs = preload("res://scripts/car_defs.gd")
|
|
const PassengerScript = preload("res://scripts/passenger.gd")
|
|
const PlayerScript = preload("res://scripts/player.gd")
|
|
|
|
var _stats := Label.new()
|
|
var _prompt := Label.new()
|
|
var _drive := Label.new()
|
|
var _cross := Panel.new()
|
|
var _toasts: Array = []
|
|
var _toast_box := VBoxContainer.new()
|
|
|
|
const PROMPTS := {
|
|
"drive": "E Steuerung übernehmen",
|
|
"shop": "E Depot-Terminal öffnen",
|
|
"tap": "E Getränke aufnehmen",
|
|
"load": "E halten Be- und entladen",
|
|
"seat": "E Fahrgast",
|
|
}
|
|
|
|
func _ready() -> void:
|
|
layer = 1
|
|
var panel := PanelContainer.new()
|
|
panel.position = Vector2(18, 16)
|
|
panel.add_theme_stylebox_override("panel", _bg(Color(0.08, 0.11, 0.09, 0.55)))
|
|
add_child(panel)
|
|
_stats.add_theme_font_size_override("font_size", 17)
|
|
panel.add_child(_stats)
|
|
|
|
_toast_box.add_theme_constant_override("separation", 4)
|
|
_toast_box.position = Vector2(18, 258)
|
|
add_child(_toast_box)
|
|
|
|
_prompt.add_theme_font_size_override("font_size", 20)
|
|
_prompt.add_theme_color_override("font_color", Color("ffe9a8"))
|
|
_prompt.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
add_child(_prompt)
|
|
|
|
_drive.add_theme_font_size_override("font_size", 22)
|
|
_drive.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
|
add_child(_drive)
|
|
|
|
var cs := StyleBoxFlat.new()
|
|
cs.bg_color = Color(1, 1, 1, 0.75)
|
|
cs.set_corner_radius_all(3)
|
|
_cross.add_theme_stylebox_override("panel", cs)
|
|
_cross.size = Vector2(5, 5)
|
|
add_child(_cross)
|
|
|
|
# Kein HUD-Element darf Eingaben schlucken - sonst stirbt der Mausblick.
|
|
_ignore_mouse(self)
|
|
get_viewport().size_changed.connect(_layout)
|
|
_layout()
|
|
|
|
func _ignore_mouse(n: Node) -> void:
|
|
if n is Control:
|
|
(n as Control).mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
for c in n.get_children():
|
|
_ignore_mouse(c)
|
|
|
|
func _bg(c: Color) -> StyleBoxFlat:
|
|
var s := StyleBoxFlat.new()
|
|
s.bg_color = c
|
|
s.set_corner_radius_all(10)
|
|
s.set_content_margin_all(14)
|
|
return s
|
|
|
|
func _layout() -> void:
|
|
var v := get_viewport().get_visible_rect().size
|
|
_cross.position = v * 0.5 - Vector2(2.5, 2.5)
|
|
_prompt.size = Vector2(v.x, 30)
|
|
_prompt.position = Vector2(0, v.y * 0.58)
|
|
_drive.size = Vector2(v.x, 34)
|
|
_drive.position = Vector2(0, v.y - 96)
|
|
|
|
func refresh(game) -> void:
|
|
var t = game.train
|
|
var lines: Array[String] = []
|
|
lines.append("%d € Ansehen %d" % [game.money, game.reputation])
|
|
lines.append("")
|
|
lines.append("Zug %s + %d Wagen" % [Defs.display_name(t.loco_id), t.consist.size()])
|
|
lines.append("Tempo %3.0f km/h" % t.speed_kmh())
|
|
|
|
var seated := 0
|
|
var thirsty := 0
|
|
var unchecked := 0
|
|
for p in game.passengers:
|
|
if p.state == PassengerScript.State.SEATED:
|
|
seated += 1
|
|
if p.wants_drink and not p.served:
|
|
thirsty += 1
|
|
if not p.ticket_checked:
|
|
unchecked += 1
|
|
lines.append("Gäste %d / %d ohne Ticket %d Durst %d"
|
|
% [seated, t.seat_count(), unchecked, thirsty])
|
|
|
|
var cargo_txt := "leer"
|
|
if t.total_cargo() > 0:
|
|
var parts: Array[String] = []
|
|
for k in t.cargo.keys():
|
|
parts.append("%s %d" % [Cargo.NAMES[int(k)], int(t.cargo[k])])
|
|
cargo_txt = ", ".join(parts)
|
|
lines.append("Ladung %d / %d (%s)" % [t.total_cargo(), t.cargo_capacity(), cargo_txt])
|
|
if game.player.carrying > 0:
|
|
lines.append("Getränke dabei: %d" % game.player.carrying)
|
|
|
|
var st = t.docked_at
|
|
if st != null and t.speed < 0.1:
|
|
var extra := ""
|
|
if st.produces >= 0:
|
|
extra = " Lager: %s %d" % [Cargo.NAMES[st.produces], int(st.stock)]
|
|
lines.append("Halt: %s%s" % [st.station_name, extra])
|
|
else:
|
|
var nxt: Array = t.next_station()
|
|
lines.append("Nächster Halt: %s (%d m)" % [nxt[0].station_name, int(nxt[1])])
|
|
_stats.text = "\n".join(lines)
|
|
|
|
var h: Dictionary = game.player.hotspot
|
|
if game.player.mode == PlayerScript.Mode.DRIVE:
|
|
_prompt.text = "E Steuerung abgeben"
|
|
elif h.is_empty():
|
|
_prompt.text = ""
|
|
elif String(h["kind"]) == "seat":
|
|
_prompt.text = _seat_prompt(game, h)
|
|
else:
|
|
_prompt.text = String(PROMPTS.get(String(h["kind"]), ""))
|
|
|
|
if game.player.mode == PlayerScript.Mode.DRIVE:
|
|
_drive.text = "W Gas S Bremse %3.0f km/h" % t.speed_kmh()
|
|
_drive.add_theme_color_override("font_color",
|
|
Color("aef2a0") if t.speed > 0.2 else Color("ffd978"))
|
|
else:
|
|
_drive.text = ""
|
|
_cross.visible = not game.player.input_locked
|
|
_tick_toasts()
|
|
|
|
func _seat_prompt(game, h: Dictionary) -> String:
|
|
var car = game.train.cars[int(h["car"])]
|
|
var occ = car.seats[int(h["seat"])]["occupant"]
|
|
if occ == null:
|
|
return "Freier Platz"
|
|
if not occ.ticket_checked:
|
|
return "E Ticket kontrollieren (%d €)" % occ.fare
|
|
if occ.wants_drink and not occ.served:
|
|
return "E Getränk servieren" if game.player.carrying > 0 else "Braucht ein Getränk"
|
|
if game.upgrades.has("schedule"):
|
|
return "Ziel: %s - %s" % [game.stations[occ.dest_station].station_name, occ.mood_word()]
|
|
return "E Nachfragen"
|
|
|
|
# --- Meldungen ------------------------------------------------------------
|
|
|
|
func toast(text: String, color: Color = Color("aef2a0")) -> void:
|
|
var l := Label.new()
|
|
l.text = text
|
|
l.add_theme_font_size_override("font_size", 19)
|
|
l.add_theme_color_override("font_color", color)
|
|
l.add_theme_color_override("font_outline_color", Color(0, 0, 0, 0.8))
|
|
l.add_theme_constant_override("outline_size", 5)
|
|
l.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
_toast_box.add_child(l)
|
|
_toasts.append({"node": l, "time": 3.4})
|
|
if _toasts.size() > 5:
|
|
var old: Dictionary = _toasts.pop_front()
|
|
old["node"].queue_free()
|
|
|
|
func _tick_toasts() -> void:
|
|
var dt := get_process_delta_time()
|
|
for e in _toasts.duplicate():
|
|
e["time"] -= dt
|
|
if e["time"] <= 0.0:
|
|
e["node"].queue_free()
|
|
_toasts.erase(e)
|
|
else:
|
|
e["node"].modulate.a = clampf(float(e["time"]) / 0.9, 0.0, 1.0)
|