Fix fishing and chat interaction regressions
This commit is contained in:
parent
66ae8c8be7
commit
e4ddf4e5a6
11 changed files with 256 additions and 43 deletions
|
|
@ -27,6 +27,7 @@ func _run() -> void:
|
|||
await physics_frame
|
||||
|
||||
var player := main.get("_player") as Player
|
||||
var session := main.get_node("%NetworkSession") as NetworkSession
|
||||
var sprint_dust := player.get_node("%SprintDust") as SprintDustTrail
|
||||
assert(sprint_dust != null)
|
||||
assert(sprint_dust.get_active_puff_count() == 0)
|
||||
|
|
@ -310,6 +311,55 @@ func _run() -> void:
|
|||
right_stick_motion.axis_value = 0.0
|
||||
Input.parse_input_event(right_stick_motion)
|
||||
await process_frame
|
||||
|
||||
# Chat owns all movement while text entry is active, including developer
|
||||
# freecam movement which reads the same WASD actions as the player.
|
||||
var free_camera_body := player.get("_free_camera_body") as CharacterBody3D
|
||||
assert(free_camera_body != null)
|
||||
chat_ui.open_chat()
|
||||
assert(chat_ui.is_open())
|
||||
var free_camera_position_before: Vector3 = free_camera_body.global_position
|
||||
Input.action_press("move_forward")
|
||||
for _frame: int in 3:
|
||||
await physics_frame
|
||||
Input.action_release("move_forward")
|
||||
assert(free_camera_body.global_position.is_equal_approx(
|
||||
free_camera_position_before
|
||||
))
|
||||
chat_ui.refocus_gameplay()
|
||||
|
||||
# Typewriter speech cycles the shared open-mouth faceplates, then restores
|
||||
# the player's authored mouth. World speech also follows the active freecam,
|
||||
# not the inactive normal gameplay camera.
|
||||
var normal_camera := player.get_gameplay_camera()
|
||||
var normal_camera_transform: Transform3D = normal_camera.global_transform
|
||||
var chat_anchor: Vector3 = player.get_chat_anchor_position()
|
||||
normal_camera.look_at(
|
||||
normal_camera.global_position
|
||||
- (chat_anchor - normal_camera.global_position),
|
||||
Vector3.UP,
|
||||
)
|
||||
assert(normal_camera.is_position_behind(chat_anchor))
|
||||
assert(not free_camera.is_position_behind(chat_anchor))
|
||||
chat_ui.show_local_speech("hello there friend")
|
||||
await process_frame
|
||||
assert(bool(player.get("_speech_mouth_active")))
|
||||
var first_speech_mouth: String = str(player.get("_speech_mouth_id"))
|
||||
await create_timer(0.12).timeout
|
||||
var second_speech_mouth: String = str(player.get("_speech_mouth_id"))
|
||||
assert(not first_speech_mouth.is_empty())
|
||||
assert(not second_speech_mouth.is_empty())
|
||||
assert(first_speech_mouth != second_speech_mouth)
|
||||
chat_ui.call("_update_speech")
|
||||
var speech: Dictionary = chat_ui.get("_speech")
|
||||
var local_speech: Dictionary = speech.get(session.get_local_peer_id(), {})
|
||||
var speech_bubble := local_speech.get("bubble") as PanelContainer
|
||||
assert(speech_bubble != null and speech_bubble.visible)
|
||||
normal_camera.global_transform = normal_camera_transform
|
||||
await create_timer(0.6).timeout
|
||||
assert(not bool(player.get("_speech_mouth_active")))
|
||||
chat_ui.call("_on_peer_removed", session.get_local_peer_id())
|
||||
|
||||
game_ui.call("_on_quick_action_selected", &"freecam")
|
||||
assert(not player.is_free_camera_active())
|
||||
game_ui.call("_on_quick_action_selected", &"hud")
|
||||
|
|
@ -754,7 +804,6 @@ func _run() -> void:
|
|||
assert(not service.is_active() and not toolbar.visible)
|
||||
|
||||
print("Art tools validation: PASS")
|
||||
var session := main.get_node("%NetworkSession") as NetworkSession
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
for _frame: int in 4:
|
||||
|
|
|
|||
|
|
@ -35,10 +35,17 @@ func _run() -> void:
|
|||
var fishing_status := game_ui.get_node("%StatusLabel") as Label
|
||||
var fishing_panel := game_ui.get_node("%FishingPanel") as PanelContainer
|
||||
var player := main.get("_player") as Player
|
||||
var item_catalog := main.get("item_catalog") as ItemCatalog
|
||||
assert(session.is_host())
|
||||
assert(not session.is_open_host())
|
||||
assert(service != null and fishing_spot != null and player != null)
|
||||
assert(player.hotbar.get_selected_item_id() == &"basic_fishing_rod")
|
||||
var worms: ItemData = item_catalog.get_item_by_id(&"worms")
|
||||
assert(worms != null)
|
||||
if player.bag.get_quantity(&"worms") == 0:
|
||||
assert(player.bag.add_item(&"worms", 2))
|
||||
assert(player.equip_bait(worms))
|
||||
var bait_quantity_before: int = player.bag.get_quantity(&"worms")
|
||||
var fresh_root := main.get_node(
|
||||
"TestWorld/Regions/GeneratedWorldRegion/WaterBodies/FreshWaterBodies"
|
||||
) as Node3D
|
||||
|
|
@ -90,6 +97,7 @@ func _run() -> void:
|
|||
await process_frame
|
||||
assert(fishing_spot.state == FishingSpotType.FishingState.WAITING_FOR_BITE)
|
||||
assert(service.has_local_attempt())
|
||||
assert(player.bag.get_quantity(&"worms") == bait_quantity_before)
|
||||
assert(fishing_status.text.is_empty())
|
||||
assert(not fishing_status.visible)
|
||||
assert(not fishing_panel.visible)
|
||||
|
|
@ -124,6 +132,7 @@ func _run() -> void:
|
|||
assert(fishing_spot.state == FishingSpotType.FishingState.READY)
|
||||
assert(player.is_movement_enabled())
|
||||
assert(not bobber.visible)
|
||||
assert(player.bag.get_quantity(&"worms") == bait_quantity_before)
|
||||
|
||||
# A private host rolls and retains the authoritative catch before the fight
|
||||
# so its quality selects the barrier band clients receive in snapshots.
|
||||
|
|
@ -141,9 +150,11 @@ func _run() -> void:
|
|||
attempts = service.get("_attempts")
|
||||
attempt = attempts.get(session.get_local_peer_id())
|
||||
assert(attempt != null)
|
||||
assert(player.bag.get_quantity(&"worms") == bait_quantity_before)
|
||||
service.call("_start_bite", attempt)
|
||||
await process_frame
|
||||
assert(attempt.phase == NetworkFishingAttempt.Phase.FIGHTING)
|
||||
assert(player.bag.get_quantity(&"worms") == bait_quantity_before - 1)
|
||||
var catalog: FishPool = main.get("fish_catalog") as FishPool
|
||||
assert(catalog != null)
|
||||
var fish: FishData = catalog.get_fish_by_id(attempt.fish_id)
|
||||
|
|
@ -218,6 +229,29 @@ func _run() -> void:
|
|||
assert(fishing_spot.can_change_hotbar_selection())
|
||||
assert(fishing_spot.can_open_fishing_shop())
|
||||
|
||||
# Escape can put the rod into RETURNING immediately before deep-water
|
||||
# recovery begins. Recovery must finish that return before snapshotting its
|
||||
# movement state, otherwise the respawn restores a permanent cast lock.
|
||||
var water_recovery := main.get_node("%WaterRecovery") as WaterRecoveryController
|
||||
assert(water_recovery != null)
|
||||
var pause_menu: PauseMenu = game_ui.get_pause_menu()
|
||||
pause_menu.open_menu()
|
||||
assert(pause_menu.visible)
|
||||
player.set_movement_enabled(false)
|
||||
fishing_spot.set("_active_player", player)
|
||||
fishing_spot.state = FishingSpotType.FishingState.RETURNING
|
||||
water_recovery.call(
|
||||
"_on_recovery_requested",
|
||||
player,
|
||||
player.global_position.y,
|
||||
)
|
||||
assert(fishing_spot.state == FishingSpotType.FishingState.READY)
|
||||
assert(bool(water_recovery.get("_prior_movement_enabled")))
|
||||
assert(bool(water_recovery.get("_prior_camera_input_enabled")))
|
||||
assert(not pause_menu.visible)
|
||||
water_recovery.call("_finish_recovery")
|
||||
assert(player.is_movement_enabled())
|
||||
|
||||
print("Fishing authority validation: PASS")
|
||||
session.disconnect_session("")
|
||||
main.queue_free()
|
||||
|
|
|
|||
|
|
@ -302,7 +302,9 @@ func _run_client() -> void:
|
|||
]
|
||||
)
|
||||
assert(service.has_local_attempt())
|
||||
assert(player.bag.get_quantity(&"worms") == worms_before_cast - 1)
|
||||
# Bait remains available while the bobber is waiting. It is consumed only
|
||||
# once the authoritative bite begins.
|
||||
assert(player.bag.get_quantity(&"worms") == worms_before_cast)
|
||||
var fishing_deadline: int = Time.get_ticks_msec() + 5000
|
||||
while (
|
||||
Time.get_ticks_msec() < fishing_deadline
|
||||
|
|
|
|||
|
|
@ -59,6 +59,11 @@ func _run() -> void:
|
|||
assert(fishing_spot.present_external_catch(crab_catch))
|
||||
assert(fishing_spot.state == FishingSpot.FishingState.SHOWING_CATCH)
|
||||
assert(not player.is_movement_enabled())
|
||||
# Network attempt cleanup may restore the base movement flag before the
|
||||
# presentation finishes. The showcase owns a separate local-input lock.
|
||||
player.set_movement_enabled(true)
|
||||
assert(not bool(player.call("_is_movement_input_enabled")))
|
||||
assert(not bool(player.call("_is_camera_input_enabled")))
|
||||
Input.action_release("fish_primary")
|
||||
await process_frame
|
||||
assert(not bool(fishing_spot.get("_put_away_press_armed")))
|
||||
|
|
@ -85,6 +90,8 @@ func _run() -> void:
|
|||
await process_frame
|
||||
assert(fishing_spot.state == FishingSpot.FishingState.READY)
|
||||
assert(player.is_movement_enabled())
|
||||
assert(bool(player.call("_is_movement_input_enabled")))
|
||||
assert(bool(player.call("_is_camera_input_enabled")))
|
||||
assert(player.inventory.contains_catch_id(crab_catch.catch_id))
|
||||
assert(bool(player.get("_active_item_is_net")))
|
||||
print("Gathering showcase validation: PASS")
|
||||
|
|
|
|||
|
|
@ -181,6 +181,20 @@ func _run() -> void:
|
|||
catch_profile.barrier_count_min = 0
|
||||
catch_profile.barrier_count_max = 0
|
||||
catch_controller.start_encounter(catch_profile, 1.0, 1)
|
||||
var alternate_echo := InputEventKey.new()
|
||||
alternate_echo.physical_keycode = KEY_QUOTELEFT
|
||||
alternate_echo.pressed = true
|
||||
alternate_echo.echo = true
|
||||
assert(alternate_echo.is_action(&"reel_alternate"))
|
||||
fishing_spot._unhandled_input(alternate_echo)
|
||||
assert(not bool(catch_controller.get("_reel_input_held")))
|
||||
var alternate_key_press := InputEventKey.new()
|
||||
alternate_key_press.physical_keycode = KEY_QUOTELEFT
|
||||
alternate_key_press.pressed = true
|
||||
assert(alternate_key_press.is_action(&"reel_alternate"))
|
||||
fishing_spot._unhandled_input(alternate_key_press)
|
||||
assert(bool(catch_controller.get("_reel_input_held")))
|
||||
catch_controller.set_reel_input(false)
|
||||
var alternate_press := InputEventAction.new()
|
||||
alternate_press.action = &"reel_alternate"
|
||||
alternate_press.pressed = true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue