frame-of-mind/src/base-environments/transition/code/fahrplan.gd

99 lines
3.6 KiB
GDScript3
Raw Normal View History

2026-01-20 22:19:20 +00:00
class_name Fahrplan extends Node3D
2026-01-20 21:47:44 +00:00
## easy graph: <station> : [Track1Train1 (next halt), Track1Train2], [Track2Train1(next halt), ...]
## CAVEAT: These must be direct children of the fahrplan!
2026-01-20 21:53:12 +00:00
@onready var fahrplan : Dictionary[Node3D, Array] = {
$station_hirschfeld: [[$station_university_mensa, $station_parity_square],[]],
2026-01-20 21:47:44 +00:00
$station_hirschfeld : [[$station_university_mensa, $station_parity_square],[]],
$station_university_mensa : [[$station_university_main],[]],
$station_university_main: [[$station_ministry],[$station_rosenthal, $station_university_mensa]],
$station_parity_square : [[$station_saint_exupery],[$station_rosenthal]],
$station_saint_exupery : [[$station_saint_exupery],[$station_rosenthal]],
$station_ministry : [null,null], # Endstation
$station_rosenthal : [null,null], # Endstation
2026-01-20 21:47:44 +00:00
}
## List of all registered station nodes, used to unparent them
@onready var stations : Array[Node3D] = fahrplan.keys()
2026-01-20 21:47:44 +00:00
@onready var tracks : Array[Dolly] = [%Track0Dolly, %Track1Dolly]
@export var empty_train_random_delay : Vector2 = Vector2(5.0, 20.0)
2026-01-20 21:47:44 +00:00
func _set_signage_texts(group: StringName, message: String) -> void:
get_tree().call_group(group, "set_text", "")
for i in range(len(message)):
get_tree().call_group(group, "set_text", message.substr(0, i+1))
await get_tree().create_timer(0.05).timeout
func _ready() -> void:
2026-01-20 22:19:20 +00:00
var x : Node3D = $station_hirschfeld
print(x.name)
await get_tree().process_frame
tracks[0].train_left.connect(_player_train_left)
tracks[1].train_left.connect(_player_train_left)
_unparent_all_stations_except($station_hirschfeld)
enter_station(current_station)
2026-01-20 21:47:44 +00:00
var current_station : Node3D = null
var stop := false
var destinations : Array[Node3D] = [null, null]
## Begins the scheduled traffic (looping through the list of destinations) on a given track
func _begin_traffic_loop(track: Dolly, cancel: Array) -> void:
if fahrplan[current_station][track.index] == null: # empty array (just no routes) would be falsy
2026-01-21 00:54:01 +00:00
track.arrive(true)
_set_signage_texts(track.signage_group, "Endstation")
return
2026-01-20 21:47:44 +00:00
var routes : Array = fahrplan[current_station][track.index]
if routes.is_empty():
_set_signage_texts(track.signage_group, "Verkehr z. Zt.\nunregelmäßig")
return
while true:
2026-01-21 00:54:01 +00:00
if cancel.is_empty(): return # abort the loop
2026-01-20 21:47:44 +00:00
var next : Node = routes.pop_front()
routes.append(next) # It's a ring buffer
destinations[track.index] = next
_set_signage_texts(track.signage_group, next.name) # TODO: load nice string
2026-01-20 21:47:44 +00:00
# Vary our schedule a little by making empty trains wait a random amount of time
if not track.player_on_board:
await get_tree().create_timer(randf_range(empty_train_random_delay.x, empty_train_random_delay.y)).timeout
2026-01-21 00:54:01 +00:00
2026-01-20 21:47:44 +00:00
if cancel.is_empty(): return # abort the loop
2026-01-21 00:54:01 +00:00
await track.cycle() # arrive and depart
2026-01-20 21:47:44 +00:00
var cancellation_token : Array
func enter_station(station: Node):
prints("------------", "ENTER STATION", station, station.name, "------------")
remove_child(current_station)
2026-01-20 21:47:44 +00:00
current_station = station
add_child(current_station)
2026-01-20 21:47:44 +00:00
cancellation_token = ["go"] # Allocate a new stopping token
_begin_traffic_loop(tracks[0], cancellation_token)
_begin_traffic_loop(tracks[1], cancellation_token)
2026-01-20 21:47:44 +00:00
func _player_train_left(track: Dolly) -> void:
2026-01-20 21:47:44 +00:00
cancellation_token.clear()
enter_station(destinations[track.index])
func _unparent_all_stations_except(except : Node3D):
for station in stations:
if station == except:
current_station = station
continue
assert(station.get_parent() == self, "A station that isn't a child of Fahrplan is in the Fahrplan: %s" % station.name)
remove_child(station)
station.visible = true # Make visible by default, parenting handles visibility and collision