290 lines
8.2 KiB
GDScript
290 lines
8.2 KiB
GDScript
extends Node
|
|
## Prüft die tatsächliche Eingabekette: Events -> GUI -> _unhandled_input.
|
|
var main
|
|
var step := 0
|
|
var wait := 0.0
|
|
var ok := 0
|
|
var fail := 0
|
|
var y0 := 0.0
|
|
var p0 := 0.0
|
|
var s0 := 0.0
|
|
var x0 := 0.0
|
|
var m0 := 0
|
|
var n0 := 0
|
|
|
|
func chk(name: String, cond: bool, info := "") -> void:
|
|
if cond:
|
|
ok += 1
|
|
print(" OK %s %s" % [name, info])
|
|
else:
|
|
fail += 1
|
|
print(" FAIL %s %s" % [name, info])
|
|
|
|
func _key(c: int, d: bool) -> void:
|
|
var e := InputEventKey.new()
|
|
e.physical_keycode = c
|
|
e.keycode = c
|
|
e.pressed = d
|
|
Input.parse_input_event(e)
|
|
|
|
func _mouse(dx: float, dy: float) -> void:
|
|
var e := InputEventMouseMotion.new()
|
|
e.relative = Vector2(dx, dy)
|
|
e.position = get_viewport().get_visible_rect().size * 0.5
|
|
e.global_position = e.position
|
|
Input.parse_input_event(e)
|
|
|
|
## Stellt den Spieler vor einen Hotspot und laesst ihn hinsehen.
|
|
func goto(car_index: int, kind: String) -> bool:
|
|
var car = main.train.cars[car_index]
|
|
for h in car.hotspots:
|
|
if String(h["kind"]) != kind:
|
|
continue
|
|
var pos: Vector3 = h["pos"]
|
|
var hs: float = car.center_s + pos.z
|
|
var p = main.player
|
|
for dz in [-1.0, 1.0, -1.4, 1.4, -0.7, 0.7]:
|
|
for px in [pos.x * 0.35, 0.0, pos.x * 0.6, -pos.x * 0.35]:
|
|
if p._blocked(px, hs + dz):
|
|
continue
|
|
p.x = px
|
|
p.s = hs + dz
|
|
p.yaw = atan2(pos.x - px, hs - p.s)
|
|
p.pitch = clampf(atan2(pos.y - (2.72), Vector2(pos.x - px, hs - p.s).length()), -1.2, 1.2)
|
|
return true
|
|
return false
|
|
|
|
func _process(d):
|
|
if main == null:
|
|
main = get_tree().current_scene
|
|
return
|
|
if not main.started:
|
|
main._start_solo()
|
|
return
|
|
if wait > 0.0:
|
|
wait -= d
|
|
return
|
|
var p = main.player
|
|
match step:
|
|
0:
|
|
chk("Maus gefangen", Input.mouse_mode == Input.MOUSE_MODE_CAPTURED,
|
|
"mode=%d" % Input.mouse_mode)
|
|
y0 = p.yaw
|
|
p0 = p.pitch
|
|
_mouse(120.0, 60.0)
|
|
wait = 0.3
|
|
1:
|
|
chk("Mausblick horizontal", absf(p.yaw - y0) > 0.05,
|
|
"yaw %.3f -> %.3f" % [y0, p.yaw])
|
|
chk("Mausblick vertikal", absf(p.pitch - p0) > 0.05,
|
|
"pitch %.3f -> %.3f" % [p0, p.pitch])
|
|
p.yaw = 0.0
|
|
p.pitch = 0.0
|
|
s0 = p.s
|
|
_key(KEY_W, true)
|
|
wait = 1.0
|
|
2:
|
|
_key(KEY_W, false)
|
|
chk("Vorwärts laufen", p.s - s0 > 0.5, "ds=%.2f" % (p.s - s0))
|
|
x0 = p.x
|
|
_key(KEY_D, true)
|
|
wait = 0.6
|
|
3:
|
|
_key(KEY_D, false)
|
|
chk("Seitwärts laufen", absf(p.x - x0) > 0.2, "dx=%.2f" % (p.x - x0))
|
|
# Ans Fahrpult stellen und E drücken
|
|
var loco = main.train.cars[0]
|
|
p.s = loco.center_s + loco.inner_z1 - 1.7
|
|
p.x = 0.0
|
|
p.yaw = 0.0
|
|
p.pitch = 0.0
|
|
wait = 0.3
|
|
4:
|
|
chk("Hotspot erkannt", String(p.hotspot.get("kind", "")) == "drive",
|
|
"kind=%s" % String(p.hotspot.get("kind", "-")))
|
|
_key(KEY_E, true)
|
|
wait = 0.3
|
|
5:
|
|
_key(KEY_E, false)
|
|
chk("E übernimmt Steuerung", main.driver_id == 1, "driver=%d" % main.driver_id)
|
|
chk("Spieler im Fahrmodus", p.mode == 1, "mode=%d" % p.mode)
|
|
_key(KEY_W, true)
|
|
wait = 1.5
|
|
6:
|
|
_key(KEY_W, false)
|
|
chk("W gibt Gas", main.train.speed > 1.0, "v=%.1f" % main.train.speed)
|
|
_key(KEY_S, true)
|
|
wait = 3.0
|
|
7:
|
|
_key(KEY_S, false)
|
|
chk("S bremst", main.train.speed < 0.05, "v=%.2f" % main.train.speed)
|
|
_key(KEY_E, true)
|
|
wait = 0.3
|
|
8:
|
|
_key(KEY_E, false)
|
|
chk("E gibt Steuerung frei", main.driver_id == 0)
|
|
_key(KEY_V, true)
|
|
_key(KEY_V, false)
|
|
wait = 0.3
|
|
9:
|
|
chk("V schaltet auf Außenkamera", main.cam_rig.is_active())
|
|
_key(KEY_V, true)
|
|
_key(KEY_V, false)
|
|
wait = 0.3
|
|
10:
|
|
chk("V schaltet zurück", p.camera.current)
|
|
_key(KEY_ESCAPE, true)
|
|
_key(KEY_ESCAPE, false)
|
|
wait = 0.3
|
|
11:
|
|
chk("Esc gibt Maus frei", Input.mouse_mode != Input.MOUSE_MODE_CAPTURED)
|
|
p.capture_mouse(true)
|
|
# Zweiter Spieler darf nicht dazwischenfunken
|
|
main._srv_toggle_drive(1)
|
|
main._srv_toggle_drive(2)
|
|
chk("Führerstand exklusiv", main.driver_id == 1, "driver=%d" % main.driver_id)
|
|
main._srv_toggle_drive(1)
|
|
# Zug mit Speisewagen und Gästen ausstatten
|
|
main.train.consist = ["coach", "dining", "freight"] as Array[String]
|
|
main._rebuild_train()
|
|
main._park_at(main.stations[0])
|
|
for i in 4:
|
|
main.spawn_passenger(0, 2)
|
|
wait = 7.0
|
|
12:
|
|
chk("Gäste eingestiegen", _seated() >= 4, "seated=%d" % _seated())
|
|
chk("Zum Depot-Terminal gelaufen", goto(0, "shop"))
|
|
wait = 0.3
|
|
13:
|
|
chk("Terminal im Blick", String(p.hotspot.get("kind", "")) == "shop",
|
|
"kind=%s" % String(p.hotspot.get("kind", "-")))
|
|
_key(KEY_E, true); _key(KEY_E, false)
|
|
wait = 0.4
|
|
14:
|
|
chk("Terminal offen", main.shop.is_open)
|
|
main.shop._tabs.current_tab = 1
|
|
wait = 0.3
|
|
15:
|
|
var btn := _find_button(main.shop, "Kaufen")
|
|
chk("Kaufen-Knopf sichtbar", btn != null)
|
|
m0 = main.money
|
|
n0 = main.train.consist.size()
|
|
if btn != null:
|
|
_click(btn.get_global_rect().get_center())
|
|
wait = 0.5
|
|
16:
|
|
chk("Klick im Laden kauft", main.train.consist.size() == n0 + 1 and main.money < m0,
|
|
"consist %d->%d, geld %d->%d" % [n0, main.train.consist.size(), m0, main.money])
|
|
_key(KEY_ESCAPE, true); _key(KEY_ESCAPE, false)
|
|
wait = 0.4
|
|
17:
|
|
chk("Terminal geschlossen", not main.shop.is_open)
|
|
chk("Gäste überleben den Umbau", _seated() >= 4, "seated=%d" % _seated())
|
|
chk("Maus wieder gefangen", Input.mouse_mode == Input.MOUSE_MODE_CAPTURED)
|
|
chk("Zur Theke gelaufen", goto(_car_of("tap"), "tap"))
|
|
wait = 0.3
|
|
18:
|
|
chk("Theke im Blick", String(p.hotspot.get("kind", "")) == "tap",
|
|
"kind=%s" % String(p.hotspot.get("kind", "-")))
|
|
_key(KEY_E, true); _key(KEY_E, false)
|
|
wait = 0.3
|
|
19:
|
|
chk("Getränk aufgenommen", p.carrying > 0, "carrying=%d" % p.carrying)
|
|
chk("Zum Gast gelaufen", _goto_occupied_seat())
|
|
wait = 0.3
|
|
20:
|
|
chk("Gast im Blick", String(p.hotspot.get("kind", "")) == "seat",
|
|
"kind=%s" % String(p.hotspot.get("kind", "-")))
|
|
m0 = main.money
|
|
_key(KEY_E, true); _key(KEY_E, false)
|
|
wait = 0.3
|
|
21:
|
|
chk("Ticket bringt Geld", main.money > m0, "+%d €" % (main.money - m0))
|
|
var occ = _seat_occupant()
|
|
chk("Gast erreichbar", occ != null)
|
|
if occ != null:
|
|
occ.wants_drink = true
|
|
occ.served = false
|
|
m0 = main.money
|
|
_key(KEY_E, true); _key(KEY_E, false)
|
|
wait = 0.3
|
|
22:
|
|
var occ2 = _seat_occupant()
|
|
chk("Serviert", occ2 != null and occ2.served)
|
|
chk("Trinkgeld", main.money > m0, "+%d €" % (main.money - m0))
|
|
chk("Getränk verbraucht", p.carrying == 0, "carrying=%d" % p.carrying)
|
|
chk("Zur Ladekonsole gelaufen", goto(_car_of("load"), "load"))
|
|
wait = 0.3
|
|
23:
|
|
chk("Konsole im Blick", String(p.hotspot.get("kind", "")) == "load",
|
|
"kind=%s" % String(p.hotspot.get("kind", "-")))
|
|
main.stations[0].stock = 10.0
|
|
_key(KEY_E, true)
|
|
wait = 2.5
|
|
24:
|
|
_key(KEY_E, false)
|
|
chk("E halten lädt Ware", main.train.total_cargo() > 0,
|
|
"cargo=%d" % main.train.total_cargo())
|
|
print("== %d ok, %d fail ==" % [ok, fail])
|
|
get_tree().quit(1 if fail > 0 else 0)
|
|
step += 1
|
|
|
|
func _seated() -> int:
|
|
var n := 0
|
|
for pa in main.passengers:
|
|
if pa.state == 2:
|
|
n += 1
|
|
return n
|
|
|
|
func _seat_occupant():
|
|
var h = main.player.hotspot
|
|
if String(h.get("kind", "")) != "seat":
|
|
return null
|
|
return main.train.cars[int(h["car"])].seats[int(h["seat"])]["occupant"]
|
|
|
|
func _click(pos: Vector2) -> void:
|
|
for pressed in [true, false]:
|
|
var e := InputEventMouseButton.new()
|
|
e.button_index = MOUSE_BUTTON_LEFT
|
|
e.pressed = pressed
|
|
e.position = pos
|
|
e.global_position = pos
|
|
Input.parse_input_event(e)
|
|
|
|
func _find_button(n: Node, text: String) -> Button:
|
|
if n is Button and (n as Button).text == text and not (n as Button).disabled:
|
|
return n
|
|
for c in n.get_children():
|
|
var r := _find_button(c, text)
|
|
if r != null:
|
|
return r
|
|
return null
|
|
|
|
func _car_of(kind: String) -> int:
|
|
for ci in main.train.cars.size():
|
|
for h in main.train.cars[ci].hotspots:
|
|
if String(h["kind"]) == kind:
|
|
return ci
|
|
return -1
|
|
|
|
func _goto_occupied_seat() -> bool:
|
|
var pl = main.player
|
|
for ci in main.train.cars.size():
|
|
var car = main.train.cars[ci]
|
|
for h in car.hotspots:
|
|
if String(h["kind"]) != "seat":
|
|
continue
|
|
if car.seats[int(h["seat"])]["occupant"] == null:
|
|
continue
|
|
var pos: Vector3 = h["pos"]
|
|
var hs: float = car.center_s + pos.z
|
|
for dz in [0.0, -0.8, 0.8, -1.2, 1.2]:
|
|
if pl._blocked(0.0, hs + dz):
|
|
continue
|
|
pl.x = 0.0
|
|
pl.s = hs + dz
|
|
pl.yaw = atan2(pos.x, hs - pl.s)
|
|
pl.pitch = 0.0
|
|
return true
|
|
return false
|