stop only if station is available on chunk

This commit is contained in:
2026-07-01 17:59:50 +02:00
parent d47bc26583
commit bdca270dca
4 changed files with 79 additions and 19 deletions

View File

@@ -2,6 +2,7 @@ extends Path3D
const STEAM_DISTANCE_STAT: String = "stat_distance_km"
const DISTANCE_KM_PER_UNIT: float = 0.01
const STATION_STOP_GROUP: StringName = &"railway_station"
@export_group("Train")
##train speed
@@ -48,6 +49,10 @@ const DISTANCE_KM_PER_UNIT: float = 0.01
@export_group("Train Stops")
##if true the train stop the ran on stops
@export var enable_stops: bool = true
##if true the train only stops on markers with a generated station nearby
@export var require_station_for_stop: bool = true
##max horizontal distance between a stop marker and a station chunk
@export var station_stop_detection_radius: float = 35.0
##time of stop
@export var stop_time: float = 4.0
##distance when the train start to brake
@@ -284,6 +289,9 @@ func build_rails() -> void:
rail_piece.add_child(rail_dx)
func _plan_stops() -> void:
stop_offset.clear()
stops_position.clear()
var current_stops = []
for child in get_children():
if child is Marker3D:
@@ -297,6 +305,53 @@ func _plan_stops() -> void:
stop_offset.append(data["offset"])
stops_position.append(data["position"])
func _advance_next_stop_index(go_forward: bool) -> void:
if stop_offset.is_empty():
next_stop_index = 0
return
if go_forward:
next_stop_index += 1
if next_stop_index >= stop_offset.size():
next_stop_index = 0
else:
next_stop_index -= 1
if next_stop_index < 0:
next_stop_index = stop_offset.size() - 1
func _find_next_valid_stop(go_forward: bool) -> bool:
if stop_offset.is_empty():
return false
for i in range(stop_offset.size()):
if _is_stop_valid(next_stop_index):
return true
_advance_next_stop_index(go_forward)
return false
func _is_stop_valid(stop_index: int) -> bool:
if not require_station_for_stop:
return true
if stop_index < 0 or stop_index >= stops_position.size():
return false
return _has_station_near_position(stops_position[stop_index])
func _has_station_near_position(stop_position: Vector3) -> bool:
var radius_sq := station_stop_detection_radius * station_stop_detection_radius
for station in get_tree().get_nodes_in_group(STATION_STOP_GROUP):
var station_node := station as Node3D
if station_node == null or not is_instance_valid(station_node):
continue
var delta := station_node.global_position - stop_position
var horizontal_dist_sq := delta.x * delta.x + delta.z * delta.z
if horizontal_dist_sq <= radius_sq:
return true
return false
func _input(event: InputEvent) -> void:
if EnvironmentManagerRoot.is_keyboard_input_blocked(get_tree()):
return
@@ -329,6 +384,9 @@ func _test_manual_fireworks() -> void:
func _goto_next_stop() -> void:
if stop_offset.size() == 0 or stop_ongoing or is_restarting:
return
if not _find_next_valid_stop(train_speed >= 0.0):
return
var target_offset = stop_offset[next_stop_index]
train_progress = target_offset
_execute_stop(train_speed >= 0)
@@ -355,15 +413,20 @@ func train_move(delta: float) -> void:
if not stop_ongoing:
var last_progress = train_progress
var has_valid_stop := false
if enable_stops and stop_offset.size() > 0 and not is_restarting:
var target_offset = stop_offset[next_stop_index]
var dist = target_offset - train_progress
dist = wrapf(dist + total_length / 2.0, 0.0, total_length) - total_length / 2.0
if abs(dist) < brake_distance and sign(dist) == sign(train_speed):
var t = abs(dist) / brake_distance
stop_multiply = max(smoothstep(0.0, 1.0, t), 0.05)
has_valid_stop = _find_next_valid_stop(train_speed >= 0.0)
if has_valid_stop:
var target_offset = stop_offset[next_stop_index]
var dist = target_offset - train_progress
dist = wrapf(dist + total_length / 2.0, 0.0, total_length) - total_length / 2.0
if abs(dist) < brake_distance and sign(dist) == sign(train_speed):
var t = abs(dist) / brake_distance
stop_multiply = max(smoothstep(0.0, 1.0, t), 0.05)
else:
stop_multiply = 1.0
else:
stop_multiply = 1.0
@@ -371,7 +434,7 @@ func train_move(delta: float) -> void:
train_progress += current_speed * delta
_track_steam_distance(abs(current_speed) * delta)
if enable_stops and stop_offset.size() > 0:
if enable_stops and stop_offset.size() > 0 and has_valid_stop:
var target_offset = stop_offset[next_stop_index]
var exceeded_forward = (current_speed > 0 and last_progress < target_offset and train_progress >= target_offset)
var exceeded_back = (current_speed < 0 and last_progress > target_offset and train_progress <= target_offset)
@@ -458,19 +521,16 @@ func _check_distance_achievements(total_distance_km: int) -> void:
AchievementManager.unlock("ACH_DISTANCE_200")
func _execute_stop(go_forward: bool = true) -> void:
if not _find_next_valid_stop(go_forward):
stop_multiply = 1.0
return
stop_ongoing = true
stop_multiply = 0.0
var current_stop_index = next_stop_index
if go_forward:
next_stop_index += 1
if next_stop_index >= stop_offset.size():
next_stop_index = 0
else:
next_stop_index -= 1
if next_stop_index < 0:
next_stop_index = stop_offset.size() - 1
_advance_next_stop_index(go_forward)
if fireworks_scene != null:
var marker_position = stops_position[current_stop_index]

File diff suppressed because one or more lines are too long

View File

@@ -119,7 +119,7 @@ shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[node name="chunk_railway_station_doubleside" unique_id=1591869611 groups=["weather_node"] instance=ExtResource("1_nkssc")]
[node name="chunk_railway_station_doubleside" unique_id=1591869611 groups=["railway_station", "weather_node"] instance=ExtResource("1_nkssc")]
script = ExtResource("2_i3rfy")
chunk_type = 1
est = true

View File

@@ -78,7 +78,7 @@ shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0, 0, 0, 1)
shader_parameter/emission_energy = 0.0
[node name="chunk_railway_station_oneside" unique_id=310632835 node_paths=PackedStringArray("connection_left", "connection_right") groups=["weather_node"] instance=ExtResource("1_38ujo")]
[node name="chunk_railway_station_oneside" unique_id=310632835 node_paths=PackedStringArray("connection_left", "connection_right") groups=["railway_station", "weather_node"] instance=ExtResource("1_38ujo")]
script = ExtResource("2_a8mxs")
chunk_type = 1
west = true