From 134ece4a10fdb49d3242a57b1b969e1abb7a5048 Mon Sep 17 00:00:00 2001 From: Voyager Date: Tue, 1 Sep 2026 17:30:18 -0400 Subject: [PATCH] Reduce fog and suppress weather indoors --- jobs/job_catalog.gd | 20 ++++++++++++++++---- tests/world_weather_validation.gd | 22 ++++++++++++++++++++++ world/rain_ambience.gd | 21 +++++++++++++++++++-- world/shoreline_ambience.gd | 21 +++++++++++++++++++-- world/world_time_visual_controller.gd | 25 +++++++++++++++++++++++++ world/world_weather_service.gd | 6 ++++-- 6 files changed, 105 insertions(+), 10 deletions(-) diff --git a/jobs/job_catalog.gd b/jobs/job_catalog.gd index eb3ea02..b88fcbf 100644 --- a/jobs/job_catalog.gd +++ b/jobs/job_catalog.gd @@ -28,6 +28,10 @@ const WEATHER_SEGMENT_COUNT: int = ( ) const LEGACY_WEATHER_SEGMENT_HOURS: float = 2.0 const LEGACY_WEATHER_SEGMENT_COUNT: int = 12 +const SUNNY_WEATHER_WEIGHT: float = 0.48 +const CLOUDY_WEATHER_WEIGHT: float = 0.29 +const RAINY_WEATHER_WEIGHT: float = 0.19 +const FOGGY_WEATHER_WEIGHT: float = 0.04 const MAX_JOB_REWARD_COINS: int = 100000 const MAX_JOB_REWARD_EXPERIENCE: int = 10000 @@ -159,13 +163,21 @@ static func generate_weather_schedule( rng.seed = plan_id.hash() ^ 0x57454154 var weather_values: Array[int] = [] for index: int in WEATHER_SEGMENT_COUNT: - var roll: float = rng.randf() + var total_weight: float = ( + SUNNY_WEATHER_WEIGHT + + CLOUDY_WEATHER_WEIGHT + + RAINY_WEATHER_WEIGHT + + FOGGY_WEATHER_WEIGHT + ) + var roll: float = rng.randf() * total_weight var weather: int = int(WorldWeatherService.Weather.SUNNY) - if roll >= 0.42 and roll < 0.70: + var cloudy_end: float = SUNNY_WEATHER_WEIGHT + CLOUDY_WEATHER_WEIGHT + var rainy_end: float = cloudy_end + RAINY_WEATHER_WEIGHT + if roll >= SUNNY_WEATHER_WEIGHT and roll < cloudy_end: weather = int(WorldWeatherService.Weather.CLOUDY) - elif roll >= 0.70 and roll < 0.88: + elif roll >= cloudy_end and roll < rainy_end: weather = int(WorldWeatherService.Weather.RAINY) - elif roll >= 0.88: + elif roll >= rainy_end: weather = int(WorldWeatherService.Weather.FOGGY) weather_values.append(weather) for requirement_index: int in required.size(): diff --git a/tests/world_weather_validation.gd b/tests/world_weather_validation.gd index 57be98d..f3c41a3 100644 --- a/tests/world_weather_validation.gd +++ b/tests/world_weather_validation.gd @@ -39,6 +39,16 @@ func _run() -> void: func _validate_weather_scheduler() -> void: + assert(JobCatalog.FOGGY_WEATHER_WEIGHT < JobCatalog.SUNNY_WEATHER_WEIGHT) + assert(JobCatalog.FOGGY_WEATHER_WEIGHT < JobCatalog.CLOUDY_WEATHER_WEIGHT) + assert(JobCatalog.FOGGY_WEATHER_WEIGHT < JobCatalog.RAINY_WEATHER_WEIGHT) + assert(is_equal_approx( + JobCatalog.SUNNY_WEATHER_WEIGHT + + JobCatalog.CLOUDY_WEATHER_WEIGHT + + JobCatalog.RAINY_WEATHER_WEIGHT + + JobCatalog.FOGGY_WEATHER_WEIGHT, + 1.0, + )) var weather := WorldWeatherServiceType.new() root.add_child(weather) weather.begin_authoritative_session(20260802) @@ -526,6 +536,18 @@ func _validate_weather_presentation() -> void: assert(rain.emitting) assert(rain.amount_ratio > 0.99) assert(rain.amount == WorldTimeVisualControllerType.RAIN_PARTICLE_AMOUNT) + visuals.set_local_home_interior_active(true) + assert(not rain.visible) + assert(not rain.emitting) + assert(is_zero_approx(rain.amount_ratio)) + assert(not runtime_environment.fog_enabled) + assert(not storm_clouds.visible) + assert(is_zero_approx(float(storm_clouds.call("get_storm_amount")))) + visuals.set_local_home_interior_active(false) + assert(rain.visible) + assert(rain.emitting) + assert(rain.amount_ratio > 0.99) + assert(storm_clouds.visible) var rain_emitter_offset: Vector3 = ( WorldTimeVisualControllerType.RAIN_EMITTER_OFFSET ) diff --git a/world/rain_ambience.gd b/world/rain_ambience.gd index 0a3a9a1..f308827 100644 --- a/world/rain_ambience.gd +++ b/world/rain_ambience.gd @@ -13,6 +13,7 @@ var _weather_service: WorldWeatherService var _fade_tween: Tween var _is_active: bool = false var _audio_enabled: bool = false +var _suppressed: bool = false func _ready() -> void: @@ -77,6 +78,18 @@ func set_active(active: bool) -> void: ) +func set_suppressed(suppressed: bool) -> void: + if _suppressed == suppressed: + return + _suppressed = suppressed + if suppressed: + _silence_immediately() + return + _transition_to_rain( + _weather_service != null and _weather_service.is_raining() + ) + + func _on_weather_changed( weather: WorldWeatherService.Weather, _seconds_remaining: float, @@ -85,7 +98,7 @@ func _on_weather_changed( func _transition_to_rain(is_raining: bool) -> void: - if not _is_active or not _audio_enabled: + if not _is_active or not _audio_enabled or _suppressed: return _stop_fade() if is_raining: @@ -120,7 +133,11 @@ func _fade_volume_to(target_volume_db: float, stop_after_fade: bool) -> void: func _finish_fade_out() -> void: - if _weather_service != null and _weather_service.is_raining(): + if ( + not _suppressed + and _weather_service != null + and _weather_service.is_raining() + ): return stop() volume_db = SILENT_VOLUME_DB diff --git a/world/shoreline_ambience.gd b/world/shoreline_ambience.gd index b86da69..9bda5f6 100644 --- a/world/shoreline_ambience.gd +++ b/world/shoreline_ambience.gd @@ -18,6 +18,7 @@ var _distance_update_remaining: float = 0.0 var _target_volume_db: float = -80.0 var _is_active := false var _audio_enabled: bool = false +var _suppressed: bool = false func _ready() -> void: @@ -58,8 +59,8 @@ func configure(listener: Node3D, shoreline_mesh: MeshInstance3D) -> void: func set_active(active: bool) -> void: _is_active = active - set_process(active and _audio_enabled) - if active: + set_process(active and _audio_enabled and not _suppressed) + if active and not _suppressed: if not _audio_enabled: return _distance_update_remaining = 0.0 @@ -72,6 +73,22 @@ func set_active(active: bool) -> void: _waves_audio.volume_db = -80.0 +func set_suppressed(suppressed: bool) -> void: + if _suppressed == suppressed: + return + _suppressed = suppressed + set_process(_is_active and _audio_enabled and not suppressed) + if suppressed: + _waves_audio.stop() + _waves_audio.volume_db = -80.0 + elif _is_active and _audio_enabled: + _distance_update_remaining = 0.0 + _update_target_volume() + _waves_audio.volume_db = _target_volume_db + if _waves_audio.stream != null: + _waves_audio.play() + + func _process(delta: float) -> void: if not _is_active: return diff --git a/world/world_time_visual_controller.gd b/world/world_time_visual_controller.gd index 92614c5..bc1e4d2 100644 --- a/world/world_time_visual_controller.gd +++ b/world/world_time_visual_controller.gd @@ -115,6 +115,7 @@ var _weather_to: WorldWeatherService.Weather = ( ) var _weather_transition: float = 1.0 var _light_performance_profile: bool = false +var _local_home_interior_active: bool = false func setup( @@ -185,6 +186,28 @@ func apply_weather_immediately( _apply_time(_time_service.get_time_hours()) +func set_local_home_interior_active(active: bool) -> void: + if _local_home_interior_active == active: + return + _local_home_interior_active = active + if _rain != null: + _rain.visible = not active + _rain.process_mode = ( + Node.PROCESS_MODE_DISABLED if active else Node.PROCESS_MODE_INHERIT + ) + if _rain_collision != null: + _rain_collision.visible = not active + _rain_collision.process_mode = ( + Node.PROCESS_MODE_DISABLED if active else Node.PROCESS_MODE_INHERIT + ) + if _storm_clouds != null: + _storm_clouds.process_mode = ( + Node.PROCESS_MODE_DISABLED if active else Node.PROCESS_MODE_INHERIT + ) + if _time_service != null: + _apply_time(_time_service.get_time_hours()) + + func _prepare_runtime_environment() -> bool: if ( _time_service == null @@ -700,6 +723,8 @@ func _weather_value( rainy: float, foggy: float, ) -> float: + if _local_home_interior_active: + return sunny return lerpf( _weather_state_value(_weather_from, sunny, cloudy, rainy, foggy), _weather_state_value(_weather_to, sunny, cloudy, rainy, foggy), diff --git a/world/world_weather_service.gd b/world/world_weather_service.gd index 9c8d995..74b1f4b 100644 --- a/world/world_weather_service.gd +++ b/world/world_weather_service.gd @@ -27,6 +27,8 @@ const FOGGY_DURATION_RANGE := Vector2( const MAX_PERSISTED_SECONDS: float = WEATHER_PERIOD_SECONDS const DAILY_PLAN_SEGMENT_HOURS: float = 1.0 const DAILY_PLAN_SEGMENT_COUNT: int = 24 +const CLOUDY_TO_SUNNY_THRESHOLD: float = 0.50 +const CLOUDY_TO_RAINY_THRESHOLD: float = 0.95 var _weather: Weather = DEFAULT_WEATHER var _seconds_remaining: float = SUNNY_DURATION_RANGE.x @@ -328,9 +330,9 @@ func _choose_next_weather() -> Weather: return Weather.CLOUDY Weather.CLOUDY: var roll: float = _rng.randf() - if roll < 0.45: + if roll < CLOUDY_TO_SUNNY_THRESHOLD: return Weather.SUNNY - if roll < 0.80: + if roll < CLOUDY_TO_RAINY_THRESHOLD: return Weather.RAINY return Weather.FOGGY return Weather.SUNNY