8 Commits

23 changed files with 830 additions and 94 deletions

View File

@@ -86,7 +86,7 @@ const RIVER_NEIGHBOUR_OFFSETS: Dictionary = {
##max cells to search around a lamppost chunk ##max cells to search around a lamppost chunk
@export_range(1, 6, 1) var lamppost_search_radius_cells: int = 3 @export_range(1, 6, 1) var lamppost_search_radius_cells: int = 3
##max allowed distance between lamppost pairs ##max allowed distance between lamppost pairs
@export var lamppost_max_wire_distance: float = 60.0 @export var lamppost_max_wire_distance: float = 35.0
##if true wire connections blocked by colliders are discarded ##if true wire connections blocked by colliders are discarded
@export var lamppost_obstacle_check_enabled: bool = true @export var lamppost_obstacle_check_enabled: bool = true

View File

@@ -1,7 +1,7 @@
extends Path3D extends Path3D
const STEAM_DISTANCE_STAT: String = "stat_distance_km" const STEAM_DISTANCE_STAT: String = "stat_distance_km"
const DISTANCE_KM_PER_UNIT: float = 0.001 const DISTANCE_KM_PER_UNIT: float = 0.01
@export_group("Train") @export_group("Train")
##train speed ##train speed
@@ -83,17 +83,20 @@ var environment_config: EnvironmentConfig
var wagon_instances: Array[Node3D] = [] var wagon_instances: Array[Node3D] = []
var wagon_progress_offsets: Array[float] = [] var wagon_progress_offsets: Array[float] = []
var _pending_steam_distance_km: float = 0.0 var _pending_steam_distance_km: float = 0.0
var _initial_is_inmotion: bool = true
func _ready() -> void: func _ready() -> void:
randomize() randomize()
_cache_environment_config() _cache_environment_config()
_initial_is_inmotion = is_inmotion
if curve != null and curve.get_baked_length() > 0: if curve != null and curve.get_baked_length() > 0:
build_rails() build_rails()
build_train() build_train()
_plan_stops() _plan_stops()
_apply_initial_train_start() _apply_initial_train_start()
_apply_train_start_delay()
else: else:
print("WARNING: Draw Path3D for rails!") print("WARNING: Draw Path3D for rails!")
@@ -138,6 +141,23 @@ func _apply_initial_train_start() -> void:
_snap_train_to_progress() _snap_train_to_progress()
func _apply_train_start_delay() -> void:
if not _initial_is_inmotion:
return
var start_delay_seconds: float = 0.0
if environment_config != null:
start_delay_seconds = maxf(environment_config.train_start_delay_seconds, 0.0)
if start_delay_seconds <= 0.0:
return
is_inmotion = false
await get_tree().create_timer(start_delay_seconds).timeout
if not is_inside_tree():
return
is_inmotion = _initial_is_inmotion
func _set_next_stop_index_from_current(current_stop_index: int) -> void: func _set_next_stop_index_from_current(current_stop_index: int) -> void:
if stop_offset.is_empty(): if stop_offset.is_empty():
next_stop_index = 0 next_stop_index = 0

View File

@@ -39,6 +39,7 @@ var weather_controller: WeatherController
var day_tween: Tween var day_tween: Tween
var day_time: float = 0.0 var day_time: float = 0.0
var pending_environment_nodes: Dictionary = {} var pending_environment_nodes: Dictionary = {}
var weather_shader_no_noise: Material
func _ready() -> void: func _ready() -> void:
@@ -80,6 +81,9 @@ func _ready() -> void:
weather_controller.name = "WeatherController" weather_controller.name = "WeatherController"
add_child(weather_controller) add_child(weather_controller)
if day_night_controller != null:
select_day_time(day_night_controller.current_time)
func _process(_delta: float) -> void: func _process(_delta: float) -> void:
_process_pending_environment_nodes() _process_pending_environment_nodes()
@@ -135,10 +139,10 @@ func _apply_dynamic_environment_materials(node: Node) -> void:
if node.is_in_group("wind_node"): if node.is_in_group("wind_node"):
_apply_wind_noise_to_node(node, NOISE_TEXTURE) _apply_wind_noise_to_node(node, NOISE_TEXTURE)
if node.is_in_group("weather_node"): if node.is_in_group("weather_node") or node.is_in_group("weather_vegetables_node"):
_apply_weather_overlay_to_node(node, WEATHER_SHADER) _apply_weather_overlay_to_node(node, _get_weather_overlay_material(node))
if _should_clear_weather_overlay(node): if _should_ignore_weather_overlay(node):
_clear_weather_overlay_from_node(node) _clear_weather_overlay_from_node(node)
func ApplyWindNoiseToMaterials(): func ApplyWindNoiseToMaterials():
@@ -162,19 +166,30 @@ func _apply_wind_noise_to_node(node: Node, noise_tex: Texture2D) -> void:
func ApplyWeatherShaderToMaterials(): func ApplyWeatherShaderToMaterials():
for node in get_tree().get_nodes_in_group("weather_node"): for node in get_tree().get_nodes_in_group("weather_node"):
_apply_weather_overlay_to_node(node, WEATHER_SHADER) _apply_weather_overlay_to_node(node, _get_weather_overlay_material(node))
for node in get_tree().get_nodes_in_group("weather_vegetables_node"): for node in get_tree().get_nodes_in_group("weather_vegetables_node"):
if _should_clear_weather_overlay(node): _apply_weather_overlay_to_node(node, _get_weather_overlay_material(node))
_clear_weather_overlay_from_node(node)
func _get_weather_overlay_material(node: Node) -> Material:
if not node.is_in_group("weather_overlay_no_noise"):
return WEATHER_SHADER
if weather_shader_no_noise == null:
weather_shader_no_noise = WEATHER_SHADER.duplicate() as Material
var shader_material := weather_shader_no_noise as ShaderMaterial
if shader_material:
shader_material.set_shader_parameter("snow_noise_enabled", false)
return weather_shader_no_noise
func _apply_weather_overlay_to_node(node: Node, material: Material) -> void: func _apply_weather_overlay_to_node(node: Node, material: Material) -> void:
if _should_clear_weather_overlay(node): if _should_ignore_weather_overlay(node):
_clear_weather_overlay_from_node(node) _clear_weather_overlay_from_node(node)
return return
if node is GeometryInstance3D: if node is GeometryInstance3D:
if _geometry_uses_alpha_texture(node): if _should_clear_weather_overlay(node) or _geometry_uses_alpha_texture(node):
node.material_overlay = null node.material_overlay = null
else: else:
node.material_overlay = material node.material_overlay = material
@@ -214,6 +229,9 @@ func _shader_material_uses_alpha_texture(material: ShaderMaterial) -> bool:
return material.shader.code.find("alpha_texture") != -1 return material.shader.code.find("alpha_texture") != -1
func _should_ignore_weather_overlay(node: Node) -> bool:
return node.is_in_group("weather_overlay_ignore")
func _should_clear_weather_overlay(node: Node) -> bool: func _should_clear_weather_overlay(node: Node) -> bool:
return node.is_in_group("weather_vegetables_node") return node.is_in_group("weather_vegetables_node")

View File

@@ -53,7 +53,7 @@ var is_storm: bool = false
var cold_tween: Tween var cold_tween: Tween
var wind_tween: Tween var wind_tween: Tween
var is_windy: bool = false var is_windy: bool = false
var thereare_fireflies: bool = false var thereare_fireflies: bool = true
var current_wind_speed: float = 0.0 var current_wind_speed: float = 0.0
var current_wind_strength: float = 0.0 var current_wind_strength: float = 0.0
var current_wind_fade: float = 0.0 var current_wind_fade: float = 0.0
@@ -128,9 +128,7 @@ func _process(delta: float) -> void:
_follow_camera() _follow_camera()
var is_night = day_time >= 2.5 _update_fireflies_visibility()
if particles_fireflies:
particles_fireflies.emitting = thereare_fireflies and is_night and not is_raining and not is_snowing and not is_storm
var base_tint: Color var base_tint: Color
var base_sky_top: Color var base_sky_top: Color
@@ -197,11 +195,9 @@ func _process(delta: float) -> void:
var final_fog_color = base_fog_color.lerp(base_fog_color * weather_color, clamp(rain_intensity, 0.0, 1.0)) var final_fog_color = base_fog_color.lerp(base_fog_color * weather_color, clamp(rain_intensity, 0.0, 1.0))
var final_fog_density = lerp(base_fog_density, base_fog_density * 4.0, clamp(rain_intensity, 0.0, 1.0)) var final_fog_density = lerp(base_fog_density, base_fog_density * 4.0, clamp(rain_intensity, 0.0, 1.0))
var final_water_color = base_water_color.darkened(clamp(environment_config.water_darkening_rain, 0.0, 1.0) * clamp(rain_intensity, 0.0, 1.0)) var final_water_color = base_water_color.darkened(clamp(environment_config.water_darkening_rain, 0.0, 1.0) * clamp(rain_intensity, 0.0, 1.0))
var rain_weather_amount: float = 0.0 var rain_weather_amount: float = clamp(rain_intensity, 0.0, 1.0)
if is_raining:
rain_weather_amount = clamp(rain_intensity, 0.0, 1.0)
var storm_weather_amount: float = 0.0 var storm_weather_amount: float = 0.0
if is_raining and is_storm: if is_storm:
if environment_config.storm_rain_intensity_multiplier > 1.0: if environment_config.storm_rain_intensity_multiplier > 1.0:
storm_weather_amount = clamp((rain_intensity - 1.0) / (environment_config.storm_rain_intensity_multiplier - 1.0), 0.0, 1.0) storm_weather_amount = clamp((rain_intensity - 1.0) / (environment_config.storm_rain_intensity_multiplier - 1.0), 0.0, 1.0)
else: else:
@@ -389,9 +385,7 @@ func _follow_camera() -> void:
func toggle_fireflies(value: bool): func toggle_fireflies(value: bool):
thereare_fireflies = value thereare_fireflies = value
var is_night = day_time >= 2.5 _update_fireflies_visibility()
if particles_fireflies:
particles_fireflies.emitting = thereare_fireflies and is_night and not is_raining
#disable fireflies and set default values and materials #disable fireflies and set default values and materials
func init_fireflies(): func init_fireflies():
@@ -402,6 +396,15 @@ func init_fireflies():
var proc_mat = particles_fireflies.process_material as ParticleProcessMaterial var proc_mat = particles_fireflies.process_material as ParticleProcessMaterial
if proc_mat: if proc_mat:
proc_mat.emission_box_extents = Vector3(environment_config.fireflies_spawn_ray, environment_config.fireflies_spawn_height, environment_config.fireflies_spawn_ray) proc_mat.emission_box_extents = Vector3(environment_config.fireflies_spawn_ray, environment_config.fireflies_spawn_height, environment_config.fireflies_spawn_ray)
_update_fireflies_visibility()
func _should_show_fireflies() -> bool:
var is_night: bool = day_time >= 2.5
return thereare_fireflies and is_night and not is_raining and not is_snowing and not is_storm
func _update_fireflies_visibility() -> void:
if particles_fireflies:
particles_fireflies.emitting = _should_show_fireflies()
#endregion #endregion
@@ -410,7 +413,7 @@ func init_fireflies():
func toggle_wind(value: bool): func toggle_wind(value: bool):
is_windy = value is_windy = value
if particles_wind: if particles_wind:
particles_wind.emitting = is_windy particles_wind.emitting = true
_apply_wind_state() _apply_wind_state()
_emit_weather_event_label() _emit_weather_event_label()
@@ -420,7 +423,7 @@ func init_wind():
_update_wind_amount_from_strength(environment_config.wind_strength) _update_wind_amount_from_strength(environment_config.wind_strength)
if particles_wind: if particles_wind:
particles_wind.visible = true particles_wind.visible = true
particles_wind.emitting = false particles_wind.emitting = true
particles_wind.amount = environment_config.wind_amount particles_wind.amount = environment_config.wind_amount
var proc_mat_wind = particles_wind.process_material as ParticleProcessMaterial var proc_mat_wind = particles_wind.process_material as ParticleProcessMaterial
if proc_mat_wind: if proc_mat_wind:
@@ -451,6 +454,11 @@ func _apply_wind_config() -> void:
_apply_wind_state(true) _apply_wind_state(true)
func _get_target_wind_strength() -> float:
if is_windy:
return environment_config.wind_boost_strength
return environment_config.wind_strength
func _apply_wind_state(immediate: bool = false) -> void: func _apply_wind_state(immediate: bool = false) -> void:
if environment_config == null: if environment_config == null:
return return
@@ -458,20 +466,23 @@ func _apply_wind_state(immediate: bool = false) -> void:
if wind_tween and wind_tween.is_valid(): if wind_tween and wind_tween.is_valid():
wind_tween.kill() wind_tween.kill()
var active_wind_speed := environment_config.wind_speed if is_windy else 0.0 if particles_wind:
var active_wind_strength := environment_config.wind_strength if is_windy else 0.0 particles_wind.emitting = true
var active_wind_fade := 1.0 if is_windy else 0.0
var active_wind_speed := environment_config.wind_speed
var active_wind_strength := _get_target_wind_strength()
var active_wind_fade := 1.0
if immediate: if immediate:
_set_current_wind_speed(active_wind_speed) _set_current_wind_speed(active_wind_speed)
_set_current_wind_strength(active_wind_strength) _set_current_wind_strength(active_wind_strength)
_set_current_wind_fade(active_wind_fade) _set_current_wind_fade(active_wind_fade)
return return
_set_current_wind_speed(environment_config.wind_speed) _set_current_wind_speed(active_wind_speed)
_set_current_wind_strength(environment_config.wind_strength) _set_current_wind_fade(active_wind_fade)
wind_tween = create_tween() wind_tween = create_tween()
wind_tween.tween_method(_set_current_wind_fade, current_wind_fade, active_wind_fade, environment_config.wind_fade_in_out_time) wind_tween.tween_method(_set_current_wind_strength, current_wind_strength, active_wind_strength, environment_config.wind_fade_in_out_time)
wind_tween.tween_callback(_finish_wind_fade_out) wind_tween.tween_callback(_finish_wind_transition)
func _set_current_wind_speed(value: float) -> void: func _set_current_wind_speed(value: float) -> void:
current_wind_speed = value current_wind_speed = value
@@ -481,6 +492,7 @@ func _set_current_wind_speed(value: float) -> void:
func _set_current_wind_strength(value: float) -> void: func _set_current_wind_strength(value: float) -> void:
current_wind_strength = value current_wind_strength = value
RenderingServer.global_shader_parameter_set("global_wind_strength", value) RenderingServer.global_shader_parameter_set("global_wind_strength", value)
_set_wind_particles_amount_from_strength(value)
_sync_wind_event_state() _sync_wind_event_state()
func _set_current_wind_fade(value: float) -> void: func _set_current_wind_fade(value: float) -> void:
@@ -494,13 +506,10 @@ func _sync_wind_event_state() -> void:
#used to notify wind_decoration when wind change state #used to notify wind_decoration when wind change state
wind_parameters_changed.emit(current_wind_speed, current_wind_strength, current_wind_fade, environment_config.wind_direction) wind_parameters_changed.emit(current_wind_speed, current_wind_strength, current_wind_fade, environment_config.wind_direction)
func _finish_wind_fade_out() -> void: func _finish_wind_transition() -> void:
if is_windy: _set_current_wind_speed(environment_config.wind_speed)
return _set_current_wind_strength(_get_target_wind_strength())
_set_current_wind_fade(1.0)
_set_current_wind_speed(0.0)
_set_current_wind_strength(0.0)
_set_current_wind_fade(0.0)
func change_wind_strength(value: float) -> void: func change_wind_strength(value: float) -> void:
if environment_config == null: if environment_config == null:
@@ -508,10 +517,11 @@ func change_wind_strength(value: float) -> void:
environment_config.wind_strength = value environment_config.wind_strength = value
_update_wind_amount_from_strength(value) _update_wind_amount_from_strength(value)
if is_windy or current_wind_fade > 0.0: if current_wind_fade > 0.0 and not is_windy:
_set_current_wind_strength(value) _set_current_wind_strength(value)
if particles_wind: if particles_wind:
particles_wind.amount = environment_config.wind_amount particles_wind.amount = environment_config.wind_amount
_apply_wind_state()
func _update_wind_amount_from_strength(value: float) -> void: func _update_wind_amount_from_strength(value: float) -> void:
if environment_config == null: if environment_config == null:
@@ -519,12 +529,22 @@ func _update_wind_amount_from_strength(value: float) -> void:
if max_wind_amount <= 0: if max_wind_amount <= 0:
max_wind_amount = max(environment_config.wind_amount, 1) max_wind_amount = max(environment_config.wind_amount, 1)
environment_config.wind_amount = _get_wind_particles_amount_from_strength(value)
func _get_wind_particles_amount_from_strength(value: float) -> int:
if max_wind_amount <= 0:
max_wind_amount = 1
var normalized_strength: float = clamp(value, 0.0, 1.0) var normalized_strength: float = clamp(value, 0.0, 1.0)
var amount_ratio: float = normalized_strength var amount_ratio: float = normalized_strength
if normalized_strength > 0.0 and normalized_strength < 0.3: if normalized_strength > 0.0 and normalized_strength < 0.3:
amount_ratio = lerp(0.08, 0.25, normalized_strength / 0.3) amount_ratio = lerp(0.08, 0.25, normalized_strength / 0.3)
environment_config.wind_amount = roundi(max_wind_amount * amount_ratio) return roundi(max_wind_amount * amount_ratio)
func _set_wind_particles_amount_from_strength(value: float) -> void:
if particles_wind:
particles_wind.amount = _get_wind_particles_amount_from_strength(value)
func trigger_random_weather_event(duration: float = 0.0) -> void: func trigger_random_weather_event(duration: float = 0.0) -> void:
if random_weather_restore_tween and random_weather_restore_tween.is_valid(): if random_weather_restore_tween and random_weather_restore_tween.is_valid():

View File

@@ -17,6 +17,7 @@ global uniform float global_snow_cap_flatness_end = 0.96;
global uniform float global_snow_cap_noise_scale = 0.22; global uniform float global_snow_cap_noise_scale = 0.22;
global uniform float global_snow_cap_noise_strength = 0.18; global uniform float global_snow_cap_noise_strength = 0.18;
const float SNOW_VISUAL_RESPONSE = 0.55; const float SNOW_VISUAL_RESPONSE = 0.55;
uniform bool snow_noise_enabled = true;
uniform float snow_noise_scale : hint_range(0.01, 1.0) = 0.15; uniform float snow_noise_scale : hint_range(0.01, 1.0) = 0.15;
uniform float snow_edge_softness : hint_range(0.01, 0.5) = 0.2; uniform float snow_edge_softness : hint_range(0.01, 0.5) = 0.2;
uniform float snow_roughness_variation : hint_range(0.0, 0.3) = 0.15; uniform float snow_roughness_variation : hint_range(0.0, 0.3) = 0.15;
@@ -92,6 +93,10 @@ float get_visual_snow_progress(float snow_progress) {
} }
float get_snow_noise_mask(vec3 world_pos, float snow_progress) { float get_snow_noise_mask(vec3 world_pos, float snow_progress) {
if (!snow_noise_enabled) {
return 1.0;
}
float detail_noise = texture(noise_texture, world_pos.xz * snow_noise_scale).r; float detail_noise = texture(noise_texture, world_pos.xz * snow_noise_scale).r;
float broad_noise = texture(noise_texture, world_pos.xz * snow_noise_scale * 0.35 + vec2(19.1, 7.4)).r; float broad_noise = texture(noise_texture, world_pos.xz * snow_noise_scale * 0.35 + vec2(19.1, 7.4)).r;
float combined_noise = mix(detail_noise, broad_noise, 0.35); float combined_noise = mix(detail_noise, broad_noise, 0.35);
@@ -118,7 +123,7 @@ void vertex() {
world_normal.y world_normal.y
); );
float accumulation_growth = smoothstep(0.02, 0.45, snow_progress); float accumulation_growth = smoothstep(0.02, 0.45, snow_progress);
float cap_noise = fbm(world_pos.xz * global_snow_cap_noise_scale + vec2(11.3, 4.7)); float cap_noise = snow_noise_enabled ? fbm(world_pos.xz * global_snow_cap_noise_scale + vec2(11.3, 4.7)) : 0.5;
float cap_variation = mix(1.0 - global_snow_cap_noise_strength, 1.0 + global_snow_cap_noise_strength, cap_noise); float cap_variation = mix(1.0 - global_snow_cap_noise_strength, 1.0 + global_snow_cap_noise_strength, cap_noise);
v_snow_amount = snow_progress; v_snow_amount = snow_progress;
@@ -133,7 +138,7 @@ void fragment() {
float facing_up = clamp(world_normal.y, 0.0, 1.0); float facing_up = clamp(world_normal.y, 0.0, 1.0);
vec3 geometric_normal = normalize(cross(dFdx(world_pos), dFdy(world_pos))); vec3 geometric_normal = normalize(cross(dFdx(world_pos), dFdy(world_pos)));
float snow_facing_up = max(facing_up, abs(geometric_normal.y)); float snow_facing_up = max(facing_up, abs(geometric_normal.y));
float noise_val = texture(noise_texture, world_pos.xz * snow_noise_scale).r; float noise_val = snow_noise_enabled ? texture(noise_texture, world_pos.xz * snow_noise_scale).r : 0.5;
//Snow //Snow
float snow_progress = v_snow_amount; float snow_progress = v_snow_amount;

View File

@@ -158,6 +158,8 @@ extends Resource
@export_group("Train Start") @export_group("Train Start")
@export var train_start_from_random_position: bool = true #When enabled the train starts from a random offset on the rail curve instead of a stop @export var train_start_from_random_position: bool = true #When enabled the train starts from a random offset on the rail curve instead of a stop
@export_range(0, 64, 1, "or_greater") var train_start_stop_index: int = 1 #Stop index used for the train start when random start is disabled @export_range(0, 64, 1, "or_greater") var train_start_stop_index: int = 1 #Stop index used for the train start when random start is disabled
@export var train_start_delay_seconds: float = 3.0 #Seconds the train waits before starting at game launch
@export var train_start_acceleration_seconds: float = 4.0 #Seconds used to progressively reach normal train speed after launch
#Snow settings #Snow settings
@export_group("Snow") @export_group("Snow")
@@ -185,7 +187,8 @@ extends Resource
@export var wind_direction: Vector2 = Vector2(0.5, 0.4) #Global wind direction (XZ) @export var wind_direction: Vector2 = Vector2(0.5, 0.4) #Global wind direction (XZ)
@export var wind_speed: float = 0.2 #Global wind animation speed @export var wind_speed: float = 0.2 #Global wind animation speed
@export var wind_scale: float = 0.025 #Global wind noise scale @export var wind_scale: float = 0.025 #Global wind noise scale
@export var wind_strength: float = 0.3 #Global wind displacement strength @export var wind_strength: float = 0.12 #Low ambient wind displacement strength
@export var wind_boost_strength: float = 1.0 #Wind displacement strength while wind event is active
@export var cloud_scale: float = 0.5 #Cloud noise scale in sky shader @export var cloud_scale: float = 0.5 #Cloud noise scale in sky shader
@export var cloud_speed: float = 0.05 #Cloud movement speed in sky shader @export var cloud_speed: float = 0.05 #Cloud movement speed in sky shader
@export_range(0.01, 1.0) var cloud_scale_envshadows_rate: float = 0.01 #Cloud scale multiplier for environment shadows @export_range(0.01, 1.0) var cloud_scale_envshadows_rate: float = 0.01 #Cloud scale multiplier for environment shadows

View File

@@ -1,21 +1,48 @@
extends Control extends Control
const TRAIN_WHISTLE_STREAM: AudioStream = preload("res://tgcc/train/sounds/train_whistle2.mp3")
@onready var play_button: Button = $%PlayButton @onready var play_button: Button = $%PlayButton
@onready var resume_button: Button = $%ResumeButton @onready var resume_button: Button = $%ResumeButton
@onready var settings_button: Button = $%SettingsButton @onready var settings_button: Button = $%SettingsButton
@onready var save_button: Button = $%SaveButton @onready var save_button: Button = $%SaveButton
@onready var quit_button: Button = $%QuitButton @onready var quit_button: Button = $%QuitButton
@export var fade_time: float = 0.5
@export var menu_whistle_volume_db: float = -12.0
var _fallback_whistle_player: AudioStreamPlayer
func _ready() -> void: func _ready() -> void:
_create_fallback_whistle_player()
play_button.pressed.connect(_on_play_button_pressed) play_button.pressed.connect(_on_play_button_pressed)
save_button.pressed.connect(_on_save_button_pressed) save_button.pressed.connect(_on_save_button_pressed)
quit_button.pressed.connect(_on_quit_button_pressed) quit_button.pressed.connect(_on_quit_button_pressed)
resume_button.pressed.connect(func(): UIEvents.resume_game_requested.emit()) resume_button.pressed.connect(func(): UIEvents.resume_game_requested.emit())
func _on_play_button_pressed() -> void: func _on_play_button_pressed() -> void:
_play_train_horn()
await get_tree().create_timer(fade_time).timeout
SceneManager.change_scene(SceneConfig.SceneName.GAME) SceneManager.change_scene(SceneConfig.SceneName.GAME)
func _create_fallback_whistle_player() -> void:
_fallback_whistle_player = AudioStreamPlayer.new()
_fallback_whistle_player.name = "FallbackTrainWhistlePlayer"
_fallback_whistle_player.bus = &"SFX"
_fallback_whistle_player.volume_db = menu_whistle_volume_db
_fallback_whistle_player.stream = TRAIN_WHISTLE_STREAM
add_child(_fallback_whistle_player)
func _play_train_horn() -> void:
if not UIEvents.toot_toot.get_connections().is_empty():
UIEvents.toot_toot.emit(false)
return
if _fallback_whistle_player == null:
return
_fallback_whistle_player.stop()
_fallback_whistle_player.play()
func _on_save_button_pressed() -> void: func _on_save_button_pressed() -> void:
GameState.save_game() GameState.save_game()

View File

@@ -35,8 +35,6 @@ func _set_selected_color(index: int, material_index: int) -> void:
else: else:
color_pickers[i].deselect() color_pickers[i].deselect()
AchievementManager.is_unlocked("ACH_CHANGE_TRAIN_COLOR")
func _on_color_selected(selected_color_picker: TrainColorPicker, material_index: int) -> void: func _on_color_selected(selected_color_picker: TrainColorPicker, material_index: int) -> void:
var color_pickers = color_pickers_1 if material_index == 0 else color_pickers_2 var color_pickers = color_pickers_1 if material_index == 0 else color_pickers_2
for i in range(color_pickers.size()): for i in range(color_pickers.size()):

View File

@@ -195,8 +195,8 @@ func _on_photo_taken_finished() -> void:
StatsManager.store() StatsManager.store()
func _on_choo_choo_button_pressed() -> void: func _on_choo_choo_button_pressed() -> void:
#play sfx UIEvents.toot_toot.emit(true)
pass AchievementManager.is_unlocked("ACH_CHANGE_TRAIN_COLOR")
func _set_buttons_mouse_filter(ignore: bool) -> void: func _set_buttons_mouse_filter(ignore: bool) -> void:
var filter = Control.MOUSE_FILTER_IGNORE if ignore else Control.MOUSE_FILTER_STOP var filter = Control.MOUSE_FILTER_IGNORE if ignore else Control.MOUSE_FILTER_STOP

View File

@@ -3,8 +3,9 @@ extends CanvasLayer
@export var config: SceneConfig @export var config: SceneConfig
@onready var color_rect = $ColorRect @onready var color_rect = $ColorRect
@onready var loading_screen = $LoadingScreen @onready var loading_screen = $LoadingScreen
@export var transition_duration: float = 1 @export var transition_duration: float = 3
const SHADER_PATH := "res://core/transition.gdshader" const SHADER_PATH := "res://core/transition.gdshader"
var transaction_material: ShaderMaterial
func _ready() -> void: func _ready() -> void:
_build_material() _build_material()
@@ -14,10 +15,10 @@ func _ready() -> void:
color_rect.visible = false color_rect.visible = false
func _build_material() -> void: func _build_material() -> void:
var mat := ShaderMaterial.new() transaction_material = ShaderMaterial.new()
mat.shader = load(SHADER_PATH) transaction_material.shader = load(SHADER_PATH)
#directional gradient: botto-left-> black; top-right -> white #directional gradient: bottom-left-> black; top-right -> white
var g := Gradient.new() var g := Gradient.new()
g.set_color(0, Color.BLACK) g.set_color(0, Color.BLACK)
g.set_color(1, Color.WHITE) g.set_color(1, Color.WHITE)
@@ -41,25 +42,27 @@ func _build_material() -> void:
shape_tex.width = 64 shape_tex.width = 64
shape_tex.height = 64 shape_tex.height = 64
mat.set_shader_parameter("base_color", Color.BLACK) transaction_material.set_shader_parameter("base_color", Color.BLACK)
mat.set_shader_parameter("gradient_texture", grad_tex) transaction_material.set_shader_parameter("gradient_texture", grad_tex)
mat.set_shader_parameter("gradient_fixed", false) transaction_material.set_shader_parameter("gradient_fixed", false)
mat.set_shader_parameter("shape_texture", shape_tex) transaction_material.set_shader_parameter("shape_texture", shape_tex)
mat.set_shader_parameter("shape_tiling", 16.0) transaction_material.set_shader_parameter("shape_tiling", 16.0)
mat.set_shader_parameter("shape_rotation", 0.0) transaction_material.set_shader_parameter("shape_rotation", 0.0)
mat.set_shader_parameter("shape_scroll", Vector2.ZERO) transaction_material.set_shader_parameter("shape_scroll", Vector2.ZERO)
mat.set_shader_parameter("shape_feathering", 0.05) transaction_material.set_shader_parameter("shape_feathering", 0.05)
mat.set_shader_parameter("shape_treshold", 1.0) # >=1 -> full at the end of the transation transaction_material.set_shader_parameter("shape_treshold", 1.0) # >=1 -> full at the end of the transation
mat.set_shader_parameter("width", 0.5) transaction_material.set_shader_parameter("width", 0.5)
color_rect.material = mat color_rect.material = transaction_material
func _update_resolution() -> void: func _update_resolution() -> void:
var s := get_viewport().get_visible_rect().size var s := get_viewport().get_visible_rect().size
color_rect.material.set_shader_parameter("node_resolution", s) if color_rect.material:
color_rect.material.set_shader_parameter("node_resolution", s)
func _set_factor(v: float) -> void: func _set_factor(v: float) -> void:
color_rect.material.set_shader_parameter("factor", v) if color_rect.material:
color_rect.material.set_shader_parameter("factor", v)
func cover(duration := 0.5) -> void: func cover(duration := 0.5) -> void:
color_rect.visible = true color_rect.visible = true
@@ -73,20 +76,44 @@ func reveal(duration := 0.5) -> void:
await t.finished await t.finished
color_rect.visible = false color_rect.visible = false
func change_scene(scene_enum: SceneConfig.SceneName) -> void: func change_scene_with_standard_fade(scene_enum: SceneConfig.SceneName, duration: float = transition_duration, show_loading_label: bool = false) -> void:
if not config or not config.scenes.has(scene_enum): if not config or not config.scenes.has(scene_enum):
return return
color_rect.material = null
color_rect.color = Color(0,0,0)
var target_scene: PackedScene = config.scenes[scene_enum] var target_scene: PackedScene = config.scenes[scene_enum]
color_rect.mouse_filter = Control.MOUSE_FILTER_STOP color_rect.mouse_filter = Control.MOUSE_FILTER_STOP
loading_screen.visible = true if show_loading_label:
loading_screen.visible = true
await cover(transition_duration) await cover(duration)
get_tree().change_scene_to_packed(target_scene) get_tree().change_scene_to_packed(target_scene)
await reveal(transition_duration) await reveal(duration)
loading_screen.visible = false if show_loading_label:
loading_screen.visible = false
color_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
func change_scene(scene_enum: SceneConfig.SceneName, duration: float = transition_duration, show_loading_label: bool = false) -> void:
if not config or not config.scenes.has(scene_enum):
return
color_rect.material = transaction_material
color_rect.color = Color(0,0,0,0)
var target_scene: PackedScene = config.scenes[scene_enum]
color_rect.mouse_filter = Control.MOUSE_FILTER_STOP
if show_loading_label:
loading_screen.visible = true
await cover(duration)
get_tree().change_scene_to_packed(target_scene)
await reveal(duration)
if show_loading_label:
loading_screen.visible = false
color_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE color_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
func quit_game() -> void: func quit_game() -> void:

View File

@@ -20,6 +20,7 @@ mouse_filter = 2
color = Color(0, 0, 0, 0) color = Color(0, 0, 0, 0)
[node name="LoadingScreen" type="Control" parent="." unique_id=1075176512] [node name="LoadingScreen" type="Control" parent="." unique_id=1075176512]
visible = false
layout_mode = 3 layout_mode = 3
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0

View File

@@ -1,8 +1,17 @@
extends Control extends Control
@export var main_menu_scene: PackedScene @export var main_menu_scene: PackedScene
@export var display_time: float = 3.0 @export var display_time: float = 2.0
@export var fade_in_time: float = 0.5
@onready var logo: Sprite2D = $ColorRect/JMPLogo
func _ready() -> void: func _ready() -> void:
logo.modulate.a = 0.0
await get_tree().create_timer(fade_in_time).timeout
var tween := create_tween()
tween.tween_property(logo, "modulate:a", 1.0, fade_in_time).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
await get_tree().create_timer(display_time).timeout await get_tree().create_timer(display_time).timeout
SceneManager.change_scene(SceneConfig.SceneName.MAIN_MENU) #tween = create_tween()
#tween.tween_property(logo, "modulate:a", 0.0, fade_in_time).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
SceneManager.change_scene_with_standard_fade(SceneConfig.SceneName.MAIN_MENU, 0.5)

View File

@@ -12,7 +12,16 @@ grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
script = ExtResource("1_elsnp") script = ExtResource("1_elsnp")
[node name="JMPLogo" type="Sprite2D" parent="." unique_id=1244888940] [node name="ColorRect" type="ColorRect" parent="." unique_id=1599828641]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 1)
[node name="JMPLogo" type="Sprite2D" parent="ColorRect" unique_id=1244888940]
position = Vector2(980.99994, 556) position = Vector2(980.99994, 556)
scale = Vector2(0.37799045, 0.37799042) scale = Vector2(0.37799045, 0.37799042)
texture = ExtResource("1_jkpgl") texture = ExtResource("1_jkpgl")

View File

@@ -35,6 +35,8 @@ func _on_global_percentages_ready(_game: int, _result: int) -> void:
pass pass
func unlock(api_name: String) -> void: func unlock(api_name: String) -> void:
if not SteamManager.is_on_steam:
return
if not KNOWN.has(api_name): if not KNOWN.has(api_name):
push_warning("Achievement unknown: %s" % api_name) push_warning("Achievement unknown: %s" % api_name)
return return
@@ -47,17 +49,25 @@ func unlock(api_name: String) -> void:
unlocked.emit(api_name) unlocked.emit(api_name)
func is_unlocked(api_name: String) -> bool: func is_unlocked(api_name: String) -> bool:
if not SteamManager.is_on_steam:
return false
var data: Dictionary = Steam.getAchievement(api_name) var data: Dictionary = Steam.getAchievement(api_name)
return data.get("achieved", false) return data.get("achieved", false)
func get_display_name(api_name: String) -> String: func get_display_name(api_name: String) -> String:
if not SteamManager.is_on_steam:
return ""
return Steam.getAchievementDisplayAttribute(api_name, "name") return Steam.getAchievementDisplayAttribute(api_name, "name")
func get_description(api_name: String) -> String: func get_description(api_name: String) -> String:
if not SteamManager.is_on_steam:
return ""
return Steam.getAchievementDisplayAttribute(api_name, "desc") return Steam.getAchievementDisplayAttribute(api_name, "desc")
#Global percentage of player who have unlocked the achievement #Global percentage of player who have unlocked the achievement
func get_global_percent(api_name: String) -> float: func get_global_percent(api_name: String) -> float:
if not SteamManager.is_on_steam:
return 0.0
var data: Dictionary = Steam.getAchievementAchievedPercent(api_name) var data: Dictionary = Steam.getAchievementAchievedPercent(api_name)
if not data.get("ret", false): if not data.get("ret", false):
return -1.0 #global percentage not yet available return -1.0 #global percentage not yet available
@@ -65,9 +75,10 @@ func get_global_percent(api_name: String) -> float:
#for development only: reset an achievement #for development only: reset an achievement
func clear(api_name: String) -> void: func clear(api_name: String) -> void:
if not SteamManager.is_on_steam:
return
Steam.clearAchievement(api_name) Steam.clearAchievement(api_name)
Steam.storeStats() Steam.storeStats()
func _on_achievement_stored(_game: int, _group: bool, api_name: String, func _on_achievement_stored(_game: int, _group: bool, api_name: String, current: int, maximum: int) -> void:
current: int, maximum: int) -> void:
print("Achievement confirmed by server: %s (%d/%d)" % [api_name, current, maximum]) print("Achievement confirmed by server: %s (%d/%d)" % [api_name, current, maximum])

View File

@@ -30,15 +30,21 @@ func _ready() -> void:
Steam.user_stats_stored.connect(_on_stats_stored) Steam.user_stats_stored.connect(_on_stats_stored)
func get_int(stat: String) -> int: func get_int(stat: String) -> int:
if not SteamManager.is_on_steam:
return 0
return Steam.getStatInt(stat) return Steam.getStatInt(stat)
func get_float(stat: String) -> float: func get_float(stat: String) -> float:
if not SteamManager.is_on_steam:
return 0.0
return Steam.getStatFloat(stat) return Steam.getStatFloat(stat)
func set_int(stat: String, value: int) -> void: func set_int(stat: String, value: int) -> void:
if not KNOWN.has(stat): if not KNOWN.has(stat):
push_warning("Stat not found: %s" % stat) push_warning("Stat not found: %s" % stat)
return return
if not SteamManager.is_on_steam:
return
if not Steam.setStatInt(stat, value): if not Steam.setStatInt(stat, value):
push_error("setStatInt failed (incremental with value less than current value? is published on steam?): %s" % stat) push_error("setStatInt failed (incremental with value less than current value? is published on steam?): %s" % stat)
@@ -52,18 +58,26 @@ func set_float(stat: String, value: float) -> void:
push_error("setStatFloat failed: %s" % stat) push_error("setStatFloat failed: %s" % stat)
func add_int(stat: String, amount: int = 1) -> void: func add_int(stat: String, amount: int = 1) -> void:
if not SteamManager.is_on_steam:
return
set_int(stat, get_int(stat) + amount) set_int(stat, get_int(stat) + amount)
func update_avg_rate(stat: String, count_this_session: float, session_length: float) -> void: func update_avg_rate(stat: String, count_this_session: float, session_length: float) -> void:
if not SteamManager.is_on_steam:
return
Steam.updateAvgRateStat(stat, count_this_session, session_length) Steam.updateAvgRateStat(stat, count_this_session, session_length)
#Send all data to server; call it at the end of the game of when exit #Send all data to server; call it at the end of the game of when exit
func store() -> void: func store() -> void:
if not SteamManager.is_on_steam:
return
if not Steam.storeStats(): if not Steam.storeStats():
push_error("storeStats failed; data saved locally") push_error("storeStats failed; data saved locally")
#Development only: reset stats #Development only: reset stats
func reset_all(include_achievements: bool = false) -> void: func reset_all(include_achievements: bool = false) -> void:
if not SteamManager.is_on_steam:
return
if !Steam.resetAllStats(include_achievements): if !Steam.resetAllStats(include_achievements):
push_error("resetAllStats failed") push_error("resetAllStats failed")

View File

@@ -46,8 +46,6 @@ signal day_time_option_changed(index: int)
#train signals #train signals
@warning_ignore("unused_signal") @warning_ignore("unused_signal")
signal toot_toot() signal toot_toot(update_stats: bool)
#game menu signals
@warning_ignore("unused_signal") @warning_ignore("unused_signal")
signal resume_game_requested() signal resume_game_requested

View File

@@ -109,7 +109,7 @@ func _on_update_rails_pressed() -> void:
UIEvents.update_rail_chunks.emit() UIEvents.update_rail_chunks.emit()
func _on_toot_toot_pressed() -> void: func _on_toot_toot_pressed() -> void:
UIEvents.toot_toot.emit() UIEvents.toot_toot.emit(true)
func _on_reset_stats_ach_pressed() -> void: func _on_reset_stats_ach_pressed() -> void:
StatsManager.reset_all(true) StatsManager.reset_all(true)

View File

@@ -189,9 +189,9 @@ data = PackedByteArray("//vQZAAOhpd2PgtGR7JsJPfgYSYSJ6387g9rgIGKF+EZgxxoAM4TYIWm
[sub_resource type="Curve3D" id="Curve3D_ndco5"] [sub_resource type="Curve3D" id="Curve3D_ndco5"]
closed = true closed = true
bake_interval = 50.0 bake_interval = 60.0
_data = { _data = {
"points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, -4.372, 0, 140, 0, 0, 0, 0, 0, 0, -20.963, 0, 160, 0, 0, 0, 0, 0, 0, -40.62518, 0, 168.52754, 0, 0, 0, 0, 0, 0, -60, 0, 170, 0, 0, 0, 0, 0, 0, -80, 0, 170, 0, 0, 0, 0, 0, 0, -100, 0, 170, 0, 0, 0, 0, 0, 0, -120.42937, 0, 171.50279, 0, 0, 0, 0, 0, 0, -141.41747, 7.6293945e-06, 180.5982, 0, 0, 0, 0, 0, 0, -155.77005, 7.6293945e-06, 198.35184, 0, 0, 0, 0, 0, 0, -160.14105, 7.6293945e-06, 219.80951, 0, 0, 0, 0, 0, 0, -163.99007, 7.6293945e-06, 239.36005, 0, 0, 0, 0, 0, 0, -175.77509, 7.6293945e-06, 256.16028, 0, 0, 0, 0, 0, 0, -195.62283, 7.6293945e-06, 267.46912, 0, 0, 0, 0, 0, 0, -219.9999, 7.6293945e-06, 270.11758, 0, 0, 0, 0, 0, 0, -240, 0, 270.118, 0, 0, 0, 0, 0, 0, -260, 0, 270.118, 0, 0, 0, 0, 0, 0, -275.19666, 7.6293945e-06, 270.55228, 0, 0, 0, 0, 0, 0, -294.2925, 7.6293945e-06, 276.05307, 0, 0, 0, 0, 0, 0, -307.19006, 7.6293945e-06, 286.9095, 0, 0, 0, 0, 0, 0, -317.32443, 7.6293945e-06, 303.14682, 0, 0, 0, 0, 0, 0, -320, 0, 320, 0, 0, 0, 0, 0, 0, -320, 0, 340, 0, 0, 0, 0, 0, 0, -320, 0, 360, 0, 0, 0, 0, 0, 0, -320, 0, 380, 0, 0, 0, 0, 0, 0, -316.78876, 7.6293945e-06, 396.91193, 0, 0, 0, 0, 0, 0, -307.68207, 7.6293945e-06, 412.70596, 0, 0, 0, 0, 0, 0, -291.08273, 7.6293945e-06, 424.7491, 0, 0, 0, 0, 0, 0, -270, 0, 429.994, 0, 0, 0, 0, 0, 0, -250, 0, 429.994, 0, 0, 0, 0, 0, 0, -229.90146, 7.6293945e-06, 433.90823, 0, 0, 0, 0, 0, 0, -217.15442, 7.6293945e-06, 442.98242, 0, 0, 0, 0, 0, 0, -204.60803, 7.6293945e-06, 459.93704, 0, 0, 0, 0, 0, 0, -200, 0, 480, 0, 0, 0, 0, 0, 0, -200, 0, 500, 0, 0, 0, 0, 0, 0, -195.5338, 7.6293945e-06, 520.0368, 0, 0, 0, 0, 0, 0, -184.9173, 7.6293945e-06, 535.07776, 0, 0, 0, 0, 0, 0, -170.36423, 7.6293945e-06, 545.0799, 0, 0, 0, 0, 0, 0, -150.56184, 0, 549.8127, 0, 0, 0, 0, 0, 0, -130, 0, 550, 0, 0, 0, 0, 0, 0, -110, 0, 550, 0, 0, 0, 0, 0, 0, -90, 0, 550, 0, 0, 0, 0, 0, 0, -70, 0, 550, 0, 0, 0, 0, 0, 0, -50, 0, 550, 0, 0, 0, 0, 0, 0, -29.862535, 7.6293945e-06, 545.3371, 0, 0, 0, 0, 0, 0, -13.215244, 7.6293945e-06, 533.0626, 0, 0, 0, 0, 0, 0, -4.098665, 7.6293945e-06, 519.6814, 0, 0, 0, 0, 0, 0, -0.048213482, 7.6293945e-06, 500.107, 0, 0, 0, 0, 0, 0, 3.7920675, 7.6293945e-06, 480.64902, 0, 0, 0, 0, 0, 0, 13.513225, 7.6293945e-06, 465.9133, 0, 0, 0, 0, 0, 0, 29.76715, 7.6293945e-06, 454.41486, 0, 0, 0, 0, 0, 0, 49.711926, 7.6293945e-06, 450.12488, 0, 0, 0, 0, 0, 0, 70, 0, 450, 0, 0, 0, 0, 0, 0, 90, 0, 450, 0, 0, 0, 0, 0, 0, 110.055405, 7.6293945e-06, 445.42627, 0, 0, 0, 0, 0, 0, 126.975784, 7.6293945e-06, 432.8683, 0, 0, 0, 0, 0, 0, 136.95703, 7.6293945e-06, 417.5506, 0, 0, 0, 0, 0, 0, 140, 0, 400, 0, 0, 0, 0, 0, 0, 140, 0, 380, 0, 0, 0, 0, 0, 0, 140, 0, 360, 0, 0, 0, 0, 0, 0, 140, 0, 340, 0, 0, 0, 0, 0, 0, 140, 0, 320, 0, 0, 0, 0, 0, 0, 140, 0, 300, 0, 0, 0, 0, 0, 0, 140, 0, 280, 0, 0, 0, 0, 0, 0, 140, 0, 260, 0, 0, 0, 0, 0, 0, 140, 0, 240, 0, 0, 0, 0, 0, 0, 140, 0, 220, 0, 0, 0, 0, 0, 0, 140, 0, 200, 0, 0, 0, 0, 0, 0, 140, 0, 180, 0, 0, 0, 0, 0, 0, 140, 0, 160, 0, 0, 0, 0, 0, 0, 140, 0, 140, 0, 0, 0, 0, 0, 0, 140, 0, 120, 0, 0, 0, 0, 0, 0, 140, 0, 100, 0, 0, 0, 0, 0, 0, 140, 0, 80, 0, 0, 0, 0, 0, 0, 140, 0, 60, 0, 0, 0, 0, 0, 0, 140, 0, 40, 0, 0, 0, 0, 0, 0, 140, 0, 20, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 0, 136.2151, 7.6293945e-06, -18.930761, 0, 0, 0, 0, 0, 0, 124.47424, 7.6293945e-06, -35.771675, 0, 0, 0, 0, 0, 0, 109.556854, 7.6293945e-06, -45.911987, 0, 0, 0, 0, 0, 0, 90, 0, -50, 0, 0, 0, 0, 0, 0, 70, 0, -50, 0, 0, 0, 0, 0, 0, 50, 0, -50, 0, 0, 0, 0, 0, 0, 30.626865, 7.6293945e-06, -46.35706, 0, 0, 0, 0, 0, 0, 14.519331, 7.6293945e-06, -35.468895, 0, 0, 0, 0, 0, 0, 3.52941, 7.6293945e-06, -19.590664), "points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, -4.372, 0, 140, 0, 0, 0, 0, 0, 0, -20.963, 0, 160, 0, 0, 0, 0, 0, 0, -40.62518, 0, 168.52754, 0, 0, 0, 0, 0, 0, -60, 0, 170, 0, 0, 0, 0, 0, 0, -80, 0, 170, 0, 0, 0, 0, 0, 0, -100, 0, 170, 0, 0, 0, 0, 0, 0, -120.42937, 0, 171.50279, 0, 0, 0, 0, 0, 0, -141.41747, 7.6293945e-06, 180.5982, 0, 0, 0, 0, 0, 0, -155.77005, 7.6293945e-06, 198.35184, 0, 0, 0, 0, 0, 0, -160.14105, 7.6293945e-06, 219.80951, 0, 0, 0, 0, 0, 0, -163.99007, 7.6293945e-06, 239.36005, 0, 0, 0, 0, 0, 0, -175.77509, 7.6293945e-06, 256.16028, 0, 0, 0, 0, 0, 0, -195.62283, 7.6293945e-06, 267.46912, 0, 0, 0, 0, 0, 0, -219.9999, 7.6293945e-06, 270.11758, 0, 0, 0, 0, 0, 0, -240, 0, 270.118, 0, 0, 0, 0, 0, 0, -260, 0, 270.118, 0, 0, 0, 0, 0, 0, -275.19666, 7.6293945e-06, 270.55228, 0, 0, 0, 0, 0, 0, -294.2925, 7.6293945e-06, 276.05307, 0, 0, 0, 0, 0, 0, -307.19006, 7.6293945e-06, 286.9095, 0, 0, 0, 0, 0, 0, -317.32443, 7.6293945e-06, 303.14682, 0, 0, 0, 0, 0, 0, -320, 0, 320, 0, 0, 0, 0, 0, 0, -320, 0, 340, 0, 0, 0, 0, 0, 0, -320, 0, 360, 0, 0, 0, 0, 0, 0, -320, 0, 380, 0, 0, 0, 0, 0, 0, -316.78876, 7.6293945e-06, 396.91193, 0, 0, 0, 0, 0, 0, -307.68207, 7.6293945e-06, 412.70596, 0, 0, 0, 0, 0, 0, -291.08273, 7.6293945e-06, 424.7491, 0, 0, 0, 0, 0, 0, -270, 0, 429.994, 0, 0, 0, 0, 0, 0, -250, 0, 429.994, 0, 0, 0, 0, 0, 0, -229.90146, 7.6293945e-06, 433.90823, 0, 0, 0, 0, 0, 0, -217.15442, 7.6293945e-06, 442.98242, 0, 0, 0, 0, 0, 0, -204.60803, 7.6293945e-06, 459.93704, 0, 0, 0, 0, 0, 0, -200, 0, 480, 0, 0, 0, 0, 0, 0, -200, 0, 500, 0, 0, 0, 0, 0, 0, -195.5338, 7.6293945e-06, 520.0368, 0, 0, 0, 0, 0, 0, -184.9173, 7.6293945e-06, 535.07776, 0, 0, 0, 0, 0, 0, -170.36423, 7.6293945e-06, 545.0799, 0, 0, 0, 0, 0, 0, -150.56184, 0, 549.8127, 0, 0, 0, 0, 0, 0, -130, 0, 550, 0, 0, 0, 0, 0, 0, -110, 0, 550, 0, 0, 0, 0, 0, 0, -90, 0, 550, 0, 0, 0, 0, 0, 0, -70, 0, 550, 0, 0, 0, 0, 0, 0, -50, 0, 550, 0, 0, 0, 0, 0, 0, -29.862535, 7.6293945e-06, 545.3371, 0, 0, 0, 0, 0, 0, -13.215244, 7.6293945e-06, 533.0626, 0, 0, 0, 0, 0, 0, -4.098665, 7.6293945e-06, 519.6814, 0, 0, 0, 0, 0, 0, -0.048213482, 7.6293945e-06, 500.107, 0, 0, 0, 0, 0, 0, 3.7920675, 7.6293945e-06, 480.64902, 0, 0, 0, 0, 0, 0, 13.513225, 7.6293945e-06, 465.9133, 0, 0, 0, 0, 0, 0, 29.76715, 7.6293945e-06, 454.41486, 0, 0, 0, 0, 0, 0, 49.711926, 7.6293945e-06, 450.12488, 0, 0, 0, 0, 0, 0, 70, 0, 450, 0, 0, 0, 0, 0, 0, 90, 0, 450, 0, 0, 0, 0, 0, 0, 110.055405, 7.6293945e-06, 445.42627, 0, 0, 0, 0, 0, 0, 126.975784, 7.6293945e-06, 432.8683, 0, 0, 0, 0, 0, 0, 136.95703, 7.6293945e-06, 417.5506, 0, 0, 0, 0, 0, 0, 140, 0, 400, 0, 0, 0, 0, 0, 0, 140, 0, 380, 0, 0, 0, 0, 0, 0, 140, 0, 360, 0, 0, 0, 0, 0, 0, 140, 0, 340, 0, 0, 0, 0, 0, 0, 140, 0, 320, 0, 0, 0, 0, 0, 0, 140, 0, 300, 0, 0, 0, 0, 0, 0, 140, 0, 280, 0, 0, 0, 0, 0, 0, 140, 0, 260, 0, 0, 0, 0, 0, 0, 140, 0, 240, 0, 0, 0, 0, 0, 0, 140, 0, 220, 0, 0, 0, 0, 0, 0, 140, 0, 200, 0, 0, 0, 0, 0, 0, 140, 0, 180, 0, 0, 0, 0, 0, 0, 140, 0, 160, 0, 0, 0, 0, 0, 0, 140, 0, 140, 0, 0, 0, 0, 0, 0, 140, 0, 120, 0, 0, 0, 0, 0, 0, 140, 0, 100, 0, 0, 0, 0, 0, 0, 140, 0, 80, 0, 0, 0, 0, 0, 0, 140, 0, 60, 0, 0, 0, 0, 0, 0, 140, 0, 40, 0, 0, 0, 0, 0, 0, 140.26848, 0, 20, 0, 0, 0, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 0, 136.2151, 7.6293945e-06, -18.930761, 0, 0, 0, 0, 0, 0, 124.47424, 7.6293945e-06, -35.771675, 0, 0, 0, 0, 0, 0, 109.556854, 7.6293945e-06, -45.911987, 0, 0, 0, 0, 0, 0, 90, 0, -50, 0, 0, 0, 0, 0, 0, 70, 0, -50, 0, 0, 0, 0, 0, 0, 50, 0, -50, 0, 0, 0, 0, 0, 0, 30.626865, 7.6293945e-06, -46.35706, 0, 0, 0, 0, 0, 0, 14.519331, 7.6293945e-06, -35.468895, 0, 0, 0, 0, 0, 0, 3.52941, 7.6293945e-06, -19.590664),
"tilts": PackedFloat32Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) "tilts": PackedFloat32Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
} }
point_count = 93 point_count = 93
@@ -268,6 +268,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -91.191925, 0, 539.03174)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -312.19193, 0, 349.03174) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -312.19193, 0, 349.03174)
[node name="Control" type="Control" parent="." unique_id=630650980] [node name="Control" type="Control" parent="." unique_id=630650980]
visible = false
layout_mode = 3 layout_mode = 3
anchors_preset = 0 anchors_preset = 0
offset_right = 40.0 offset_right = 40.0

File diff suppressed because one or more lines are too long

View File

@@ -17,12 +17,10 @@ func _ready() -> void:
if not UIEvents.toot_toot.is_connected(_on_toot_toot): if not UIEvents.toot_toot.is_connected(_on_toot_toot):
UIEvents.toot_toot.connect(_on_toot_toot) UIEvents.toot_toot.connect(_on_toot_toot)
func _exit_tree() -> void: func _exit_tree() -> void:
if UIEvents.toot_toot.is_connected(_on_toot_toot): if UIEvents.toot_toot.is_connected(_on_toot_toot):
UIEvents.toot_toot.disconnect(_on_toot_toot) UIEvents.toot_toot.disconnect(_on_toot_toot)
func _create_whistle_player() -> void: func _create_whistle_player() -> void:
_whistle_player = AudioStreamPlayer3D.new() _whistle_player = AudioStreamPlayer3D.new()
_whistle_player.name = "TrainWhistlePlayer" _whistle_player.name = "TrainWhistlePlayer"
@@ -33,14 +31,13 @@ func _create_whistle_player() -> void:
_whistle_player.stream = TRAIN_WHISTLE_STREAM _whistle_player.stream = TRAIN_WHISTLE_STREAM
add_child(_whistle_player) add_child(_whistle_player)
func _on_toot_toot(update_stats: bool = true) -> void:
func _on_toot_toot() -> void:
if _whistle_player == null: if _whistle_player == null:
return return
print("stat_toottoot_number") if update_stats:
StatsManager.add_int("stat_toottoot_number", 1) StatsManager.add_int("stat_toottoot_number", 1)
StatsManager.store() StatsManager.store()
_whistle_player.stop() _whistle_player.stop()
_whistle_player.play() _whistle_player.play()

View File

@@ -52,7 +52,7 @@ shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0.26628578, 0.030174213, 0.015801903, 1) shader_parameter/emission_color = Color(0.26628578, 0.030174213, 0.015801903, 1)
shader_parameter/emission_energy = 10.000000475 shader_parameter/emission_energy = 10.000000475
[node name="Treno" unique_id=1182090923 groups=["weather_node"] instance=ExtResource("1_33mei")] [node name="Treno" unique_id=1182090923 groups=["weather_node", "weather_overlay_no_noise"] instance=ExtResource("1_33mei")]
script = ExtResource("9_4qk3b") script = ExtResource("9_4qk3b")
[node name="Finestrini" parent="." index="0" unique_id=755457549] [node name="Finestrini" parent="." index="0" unique_id=755457549]

View File

@@ -30,7 +30,7 @@ shader_parameter/glint_sharpness = 32.0
shader_parameter/emission_color = Color(0.5882353, 0.06666667, 0.10980392, 1) shader_parameter/emission_color = Color(0.5882353, 0.06666667, 0.10980392, 1)
shader_parameter/emission_energy = 6.50000030875 shader_parameter/emission_energy = 6.50000030875
[node name="wagon" unique_id=14655460 groups=["weather_node"] instance=ExtResource("1_ud2nc")] [node name="wagon" unique_id=14655460 groups=["weather_node", "weather_overlay_no_noise"] instance=ExtResource("1_ud2nc")]
[node name="Finestrini_001" parent="." index="0" unique_id=1279718063] [node name="Finestrini_001" parent="." index="0" unique_id=1279718063]
surface_material_override/0 = ExtResource("2_upuw2") surface_material_override/0 = ExtResource("2_upuw2")