Expand character customization and refine fishing flow

This commit is contained in:
Alexander Sellite 2026-08-05 16:25:16 -04:00
parent 8cc4c0985d
commit 43f57e56a0
144 changed files with 3108 additions and 189 deletions

View file

@ -0,0 +1,113 @@
extends SceneTree
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
var legacy_snapshot: Dictionary = (
CharacterCustomizationCatalog.default_snapshot()
)
legacy_snapshot.erase(CharacterCustomizationCatalog.SCALE_CATEGORY_ID)
var migrated: Dictionary = (
CharacterCustomizationCatalog.sanitized_snapshot(legacy_snapshot)
)
assert(
is_equal_approx(
float(migrated[CharacterCustomizationCatalog.SCALE_CATEGORY_ID]),
CharacterCustomizationCatalog.DEFAULT_CHARACTER_SCALE,
)
)
assert(CharacterCustomizationCatalog.validate_snapshot(migrated))
var small_snapshot := migrated.duplicate(true)
small_snapshot[CharacterCustomizationCatalog.SCALE_CATEGORY_ID] = (
CharacterCustomizationCatalog.MIN_CHARACTER_SCALE
)
assert(CharacterCustomizationCatalog.validate_snapshot(small_snapshot))
var large_snapshot := migrated.duplicate(true)
large_snapshot[CharacterCustomizationCatalog.SCALE_CATEGORY_ID] = (
CharacterCustomizationCatalog.MAX_CHARACTER_SCALE
)
assert(CharacterCustomizationCatalog.validate_snapshot(large_snapshot))
var invalid_snapshot := migrated.duplicate(true)
invalid_snapshot[CharacterCustomizationCatalog.SCALE_CATEGORY_ID] = 2.0
assert(not CharacterCustomizationCatalog.validate_snapshot(invalid_snapshot))
var visuals: Node3D = PlayerVisualPresenter.instantiate_visuals()
root.add_child(visuals)
PlayerVisualPresenter.apply_appearance(visuals, large_snapshot)
assert(visuals.scale.is_equal_approx(
Vector3.ONE * CharacterCustomizationCatalog.MAX_CHARACTER_SCALE
))
var skeleton := visuals.find_child("Skeleton3D", true, false) as Skeleton3D
assert(skeleton != null)
var body := skeleton.get_node_or_null("body_main") as MeshInstance3D
assert(body != null)
var body_material := body.material_override as StandardMaterial3D
assert(body_material != null)
assert(body_material.shading_mode == BaseMaterial3D.SHADING_MODE_UNSHADED)
assert(is_zero_approx(body_material.metallic))
assert(is_zero_approx(body_material.metallic_specular))
assert(is_equal_approx(body_material.roughness, 1.0))
assert(body_material.diffuse_mode == BaseMaterial3D.DIFFUSE_LAMBERT)
assert(not body_material.anisotropy_enabled)
assert(not body_material.clearcoat_enabled)
assert(not body_material.rim_enabled)
var signed_small := {"appearance": small_snapshot}
var signed_large := {"appearance": large_snapshot}
assert(
NetworkProfileProtocol.signature_fields(signed_small)
!= NetworkProfileProtocol.signature_fields(signed_large)
)
assert(
ProfilePreview.calculate_pixelated_grid_size(
Vector2(260.0, 330.0),
Vector2(1280.0, 720.0),
3,
) == Vector2i(130, 165)
)
assert(
ProfilePreview.calculate_pixelated_grid_size(
Vector2(260.0, 330.0),
Vector2(640.0, 480.0),
3,
) == Vector2i(65, 83)
)
var profile_page := ProfilePage.new()
root.add_child(profile_page)
await process_frame
profile_page.call(
"_select_category",
CharacterCustomizationCatalog.SCALE_CATEGORY_ID,
)
await process_frame
var slider := profile_page.find_child(
"CharacterScaleSlider", true, false
) as HSlider
assert(slider != null)
assert(is_equal_approx(
float(slider.min_value),
CharacterCustomizationCatalog.MIN_CHARACTER_SCALE,
))
assert(is_equal_approx(
float(slider.max_value),
CharacterCustomizationCatalog.MAX_CHARACTER_SCALE,
))
slider.value = 1.15
await process_frame
var draft: Dictionary = profile_page.get("_draft_appearance")
assert(is_equal_approx(
float(draft[CharacterCustomizationCatalog.SCALE_CATEGORY_ID]),
1.15,
))
print("Character scale validation: PASS")
profile_page.queue_free()
visuals.queue_free()
await process_frame
quit()

View file

@ -0,0 +1 @@
uid://d0w8gv1i4paii

View file

@ -132,7 +132,7 @@ func _validate_barrier_challenge_curve() -> void:
func _validate_fight_pacing_and_reel_upgrades() -> void:
assert(is_equal_approx(CatchController.CHASE_SPEED, 0.07))
assert(is_equal_approx(CatchController.CHASE_START_DELAY, 0.5))
assert(is_equal_approx(CatchController.CHASE_START_DELAY, 1.0))
assert(is_equal_approx(CatchController.CHASE_START_OFFSET, 0.04))
assert(is_equal_approx(Player.BASE_REEL_SPEED, 0.16))

View file

@ -247,21 +247,21 @@ func _validate_bite_wait_distribution() -> void:
var total_wait_seconds: float = 0.0
for _sample_index: int in 10000:
var wait_seconds: float = fishing_spot.roll_bite_wait_time()
assert(wait_seconds >= 10.0)
assert(wait_seconds <= 240.0)
assert(wait_seconds >= FishingSpotType.BITE_QUICK_MIN_SECONDS)
assert(wait_seconds <= FishingSpotType.BITE_MAX_SECONDS)
total_wait_seconds += wait_seconds
if wait_seconds < 30.0:
if wait_seconds < FishingSpotType.BITE_QUICK_MAX_SECONDS:
quick_count += 1
else:
typical_or_long_count += 1
if wait_seconds >= 180.0:
if wait_seconds >= FishingSpotType.BITE_LONG_MAX_SECONDS:
very_long_count += 1
var average_wait_seconds: float = total_wait_seconds / 10000.0
assert(quick_count >= 2300 and quick_count <= 2700)
assert(typical_or_long_count > quick_count)
assert(very_long_count >= 100 and very_long_count <= 300)
assert(average_wait_seconds >= 57.0)
assert(average_wait_seconds <= 61.0)
assert(average_wait_seconds >= 45.0)
assert(average_wait_seconds <= 49.0)
fishing_spot.queue_free()
await process_frame
@ -297,7 +297,10 @@ func _validate_remote_presentation() -> void:
assert(fish_catch.is_valid())
presentation.play_return(fish_catch)
await create_timer(0.6).timeout
var catch_display := player.get_node("%CatchDisplay") as Node3D
var catch_display := player.find_child(
"CatchDisplay", true, false
) as Node3D
assert(catch_display != null)
assert(catch_display.visible)
await presentation.return_completed
assert(not catch_display.visible)

View file

@ -136,9 +136,10 @@ func _validate_save_round_trip(
player.inventory.get_catches_by_fish_id(fish_id).front()
)
player.begin_catch_showcase(fish_catch)
var catch_sprite := player.get_node(
"%CatchSprite"
var catch_sprite := player.find_child(
"CatchSprite", true, false
) as Sprite3D
assert(catch_sprite != null)
assert(catch_sprite.texture == fish_catch.fish.display_texture)
player.end_catch_showcase(Callable(), true)

View file

@ -119,9 +119,11 @@ func _validate_marker_controls(
player: Player,
) -> void:
var prior_mouse_mode: Input.MouseMode = Input.mouse_mode
service.activate()
var activation_pointer := Vector2(824.0, 318.0)
service.activate(activation_pointer)
assert(service.is_active())
assert(service.is_placement_mode())
assert(service.get_pointer_screen_position() == activation_pointer)
if DisplayServer.get_name() != "headless":
assert(Input.mouse_mode == Input.MOUSE_MODE_VISIBLE)
@ -136,6 +138,15 @@ func _validate_marker_controls(
pointer_motion.position = pointer_before + Vector2(30.0, -12.0)
assert(service.handle_input(pointer_motion, true))
assert(service.get_pointer_screen_position() != pointer_before)
var scaled_ui_motion := InputEventMouseMotion.new()
scaled_ui_motion.position = Vector2(260.0, 140.0)
var root_viewport_pointer := Vector2(960.0, 540.0)
assert(service.handle_input(
scaled_ui_motion,
true,
root_viewport_pointer,
))
assert(service.get_pointer_screen_position() == root_viewport_pointer)
var zoom_event := InputEventMouseButton.new()
zoom_event.button_index = MOUSE_BUTTON_WHEEL_UP
zoom_event.shift_pressed = true