Add starter RV progression and fishing feedback

This commit is contained in:
Alexander Sellite 2026-08-31 16:03:55 -04:00
parent eed361681a
commit d8bf59bca0
47 changed files with 2268 additions and 467 deletions

View file

@ -21,6 +21,7 @@ const PauseMenuType = preload("res://ui/pause_menu.gd")
const NetworkSessionType = preload("res://network/network_session.gd")
const FishingShopType = preload("res://ui/fishing_shop.gd")
const DecorShopType = preload("res://ui/decor_shop.gd")
const RVUpgradeShopType = preload("res://ui/rv_upgrade_shop.gd")
const SettingsPanelType = preload("res://ui/settings_panel.gd")
const PlayerFishingUpgradesType = preload(
"res://progression/player_fishing_upgrades.gd"
@ -31,6 +32,9 @@ const ShopInteractionType = preload(
const DecorShopInteractionType = preload(
"res://world/decor_shop_interaction.gd"
)
const RVUpgradeInteractionType = preload(
"res://world/rv_upgrade_interaction.gd"
)
const PlayerStorageType = preload("res://ui/player_storage.gd")
const HomeDecorToolbarType = preload("res://ui/home_decor_toolbar.gd")
const PlayerStorageInteractionType = preload(
@ -129,6 +133,7 @@ const FISHING_PANEL_SHOWCASE_BOTTOM_OFFSET: float = -104.0
@onready var _barrier_health: Label = %BarrierHealth
@onready var _showcase_details: Label = %ShowcaseDetails
@onready var _fishing_panel: PanelContainer = %FishingPanel
@onready var _fishing_danger_vignette: ColorRect = %FishingDangerVignette
@onready var _experience_panel: PanelContainer = %ExperienceProgressPanel
@onready var _experience_level_label: Label = %ExperienceLevelLabel
@onready var _experience_award_label: Label = %ExperienceAwardLabel
@ -144,6 +149,8 @@ const SHOP_ANIMALESE_VOICE_ID: String = "natural"
const SHOP_ANIMALESE_BASE_PITCH: float = 1.08
const SHOP_SPEECH_CHARACTERS_PER_SECOND: float = 28.0
const SHOP_NPC_SPEECH_COOLDOWN_MILLISECONDS: int = 5000
const FISHING_DANGER_START_GAP: float = 0.15
const FISHING_DANGER_FULL_GAP: float = 0.025
@onready var _canonical_stage: Control = %CanonicalStage
@ -155,6 +162,7 @@ const SHOP_NPC_SPEECH_COOLDOWN_MILLISECONDS: int = 5000
@onready var _hotbar_ui: HotbarUIType = %Hotbar
@onready var _fishing_shop: FishingShopType = %FishingShop
@onready var _decor_shop: DecorShopType = %DecorShop
@onready var _rv_upgrade_shop: RVUpgradeShopType = %RVUpgradeShop
@onready var _player_storage: PlayerStorageType = %PlayerStorage
@onready var _home_decor_toolbar: HomeDecorToolbarType = %HomeDecorToolbar
@onready var _rv_storage_button: Button = %RVStorageButton
@ -208,6 +216,7 @@ var _player_menu_hotbar_visible: bool = false
var _main_shop_buyer: FishBuyerProfileType
var _shop_interaction: ShopInteractionType
var _decor_shop_interaction: DecorShopInteractionType
var _rv_upgrade_shop_interaction: RVUpgradeInteractionType
var _storage_interaction: PlayerStorageInteractionType
var _surface_drawing: NetworkSurfaceDrawingService
var _surface_drawing_hotbar_selected: bool = false
@ -235,6 +244,12 @@ var _controller_text_entry_is_open: Callable
var _controller_text_entry_close: Callable
var _restore_chat_keyboard_after_fishing: bool = false
var _rv_storage_button_requested_visible: bool = false
var _previous_barrier_health := PackedInt32Array()
var _barrier_feedback_initialized: bool = false
var _fishing_danger_target: float = 0.0
var _fishing_danger_intensity: float = 0.0
var _fishing_danger_pulse_time: float = 0.0
var _catch_track_shake_tween: Tween
func _ready() -> void:
@ -363,6 +378,7 @@ func setup(
shop_interaction: ShopInteractionType,
storage_interaction: PlayerStorageInteractionType,
decor_shop_interaction: DecorShopInteractionType,
rv_upgrade_shop_interaction: RVUpgradeInteractionType,
item_effects: PlayerItemEffectsType,
cooler_capacity: PlayerCoolerCapacityType,
network_session: NetworkSessionType,
@ -506,7 +522,6 @@ func setup(
hotbar,
inventory_layout,
item_catalog,
cooler_capacity,
art_unlocks,
network_shop_service,
network_sale_service,
@ -521,6 +536,14 @@ func setup(
home_state,
network_shop_service,
)
_rv_upgrade_shop.setup(
player,
wallet,
fishing_spot,
rv_upgrade_shop_interaction,
home_state,
network_shop_service,
)
_player_storage.setup(
player,
fishing_spot,
@ -538,6 +561,8 @@ func setup(
_fishing_shop.menu_exit_started.connect(_on_shop_exit_started)
_decor_shop.menu_visibility_changed.connect(_on_shop_visibility_changed)
_decor_shop.menu_exit_started.connect(_on_shop_exit_started)
_rv_upgrade_shop.menu_visibility_changed.connect(_on_shop_visibility_changed)
_rv_upgrade_shop.menu_exit_started.connect(_on_shop_exit_started)
_fishing_shop.sell_fish_requested.connect(_on_shop_sell_fish_requested)
_fishing_shop.shop_cooler_return_requested.connect(
_on_shop_cooler_return_requested
@ -548,6 +573,7 @@ func setup(
_main_shop_buyer = main_shop_buyer
_shop_interaction = shop_interaction
_decor_shop_interaction = decor_shop_interaction
_rv_upgrade_shop_interaction = rv_upgrade_shop_interaction
_storage_interaction = storage_interaction
_surface_drawing = surface_drawing
if (
@ -571,13 +597,16 @@ func set_world_interactions(
shop_interaction: ShopInteractionType,
storage_interaction: PlayerStorageInteractionType,
decor_shop_interaction: DecorShopInteractionType,
rv_upgrade_shop_interaction: RVUpgradeInteractionType,
) -> void:
_shop_interaction = shop_interaction
_storage_interaction = storage_interaction
_decor_shop_interaction = decor_shop_interaction
_rv_upgrade_shop_interaction = rv_upgrade_shop_interaction
_fishing_shop.set_world_interaction(shop_interaction)
_player_storage.set_world_interaction(storage_interaction)
_decor_shop.set_world_interaction(decor_shop_interaction)
_rv_upgrade_shop.set_world_interaction(rv_upgrade_shop_interaction)
func _prioritize_surface_drawing_pointer_input() -> void:
@ -1539,6 +1568,13 @@ func _process(delta: float) -> void:
_update_virtual_mouse(delta)
_update_controller_menu_scroll(delta)
_update_experience_bubble_position()
_update_fishing_danger_vignette(delta)
_try_start_shop_npc_speech()
if _player != null:
_player.set_fishing_reel_camera_active(
_fishing_spot != null
and _fishing_spot.is_reel_input_active()
)
func _update_controller_menu_scroll(delta: float) -> void:
@ -1793,6 +1829,7 @@ func set_gameplay_ui_enabled(enabled: bool) -> void:
close_player_menu_for_session_end()
_fishing_shop.close_for_session_end()
_decor_shop.close_for_session_end()
_rv_upgrade_shop.close_for_session_end()
_player_storage.close_for_session_end()
_fishing_panel.visible = false
_shop_prompt.hide()
@ -1933,6 +1970,10 @@ func get_decor_shop() -> DecorShopType:
return _decor_shop
func get_rv_upgrade_shop() -> RVUpgradeShopType:
return _rv_upgrade_shop
func get_player_storage() -> PlayerStorageType:
return _player_storage
@ -2027,8 +2068,19 @@ func set_shop_prompt_visible(
_position_shop_prompt(world_anchor)
func set_shop_npc_player_in_range(in_range: bool) -> void:
if _shop_npc_player_in_range == in_range:
func set_shop_npc_player_in_range(
in_range: bool,
dialogue_text: String = "",
) -> void:
var dialogue_changed: bool = (
not dialogue_text.is_empty()
and _shop_prompt_message.text != dialogue_text
)
if dialogue_changed:
_shop_prompt_message.text = dialogue_text
_shop_prompt_message.visible_characters = -1
_shop_npc_spoken_for_current_visit = false
if _shop_npc_player_in_range == in_range and not dialogue_changed:
return
_shop_npc_player_in_range = in_range
if not in_range:
@ -2044,10 +2096,10 @@ func _try_start_shop_npc_speech() -> void:
or not _gameplay_ui_enabled
):
return
_shop_npc_spoken_for_current_visit = true
var now_msec: int = Time.get_ticks_msec()
if now_msec < _shop_npc_next_speech_msec:
return
_shop_npc_spoken_for_current_visit = true
_shop_npc_next_speech_msec = (
now_msec + SHOP_NPC_SPEECH_COOLDOWN_MILLISECONDS
)
@ -2310,6 +2362,12 @@ func _on_catch_display_changed(
and _fishing_spot != null
and _fishing_spot.is_fighting()
)
_update_fishing_feedback(
progress,
chase_progress,
barrier_health,
encounter_visible,
)
_green_catch_progress.value = progress * 100.0
_red_chase_progress.value = maxf(chase_progress, 0.0) * 100.0
_catch_track.visible = encounter_visible
@ -2346,6 +2404,93 @@ func _on_catch_display_changed(
_refresh_fishing_panel_visibility()
func _update_fishing_feedback(
progress: float,
chase_progress: float,
barrier_health: PackedInt32Array,
encounter_visible: bool,
) -> void:
if not encounter_visible:
_previous_barrier_health.clear()
_barrier_feedback_initialized = false
_fishing_danger_target = 0.0
return
if _barrier_feedback_initialized:
var comparison_count: int = mini(
_previous_barrier_health.size(),
barrier_health.size(),
)
var barrier_hit: bool = false
var barrier_broken: bool = false
for barrier_index: int in range(comparison_count):
if (
barrier_health[barrier_index]
>= _previous_barrier_health[barrier_index]
):
continue
barrier_hit = true
barrier_broken = (
barrier_broken
or barrier_health[barrier_index] <= 0
)
if barrier_hit:
_play_barrier_feedback(barrier_broken)
_previous_barrier_health = barrier_health.duplicate()
_barrier_feedback_initialized = true
var chase_gap: float = progress - maxf(chase_progress, 0.0)
_fishing_danger_target = clampf(
inverse_lerp(
FISHING_DANGER_START_GAP,
FISHING_DANGER_FULL_GAP,
chase_gap,
),
0.0,
1.0,
)
func _play_barrier_feedback(barrier_broken: bool) -> void:
if _player != null:
_player.play_fishing_barrier_camera_feedback(barrier_broken)
if _catch_track_shake_tween != null:
_catch_track_shake_tween.kill()
_catch_track.rotation = 0.0
var tilt: float = 0.018 if barrier_broken else 0.008
var beat: float = 0.038 if barrier_broken else 0.028
_catch_track_shake_tween = create_tween()
_catch_track_shake_tween.tween_property(
_catch_track, "rotation", -tilt, beat
)
_catch_track_shake_tween.tween_property(
_catch_track, "rotation", tilt, beat
)
_catch_track_shake_tween.tween_property(
_catch_track, "rotation", -tilt * 0.45, beat
)
_catch_track_shake_tween.tween_property(
_catch_track, "rotation", 0.0, beat
)
func _update_fishing_danger_vignette(delta: float) -> void:
_fishing_danger_pulse_time += delta
_fishing_danger_intensity = lerpf(
_fishing_danger_intensity,
_fishing_danger_target,
1.0 - exp(-8.0 * delta),
)
var pulse: float = (
0.88 + sin(_fishing_danger_pulse_time * 5.5) * 0.12
)
var shown_intensity: float = _fishing_danger_intensity * pulse
_fishing_danger_vignette.visible = shown_intensity > 0.01
var vignette_material := (
_fishing_danger_vignette.material as ShaderMaterial
)
if vignette_material != null:
vignette_material.set_shader_parameter("intensity", shown_intensity)
func _update_barrier_markers(
positions: PackedFloat32Array,
health: PackedInt32Array,