Expand fish catalog and add bait system

This commit is contained in:
Alexander Sellite 2026-08-06 01:00:52 -04:00
parent 43f57e56a0
commit 954042fd1d
134 changed files with 3134 additions and 127 deletions

View file

@ -48,7 +48,7 @@ func _run() -> void:
as PlayerAssetReservationService
)
assert(player != null)
assert(catalog != null and catalog.candidates.size() == 19)
assert(catalog != null and catalog.candidates.size() == 53)
assert(sale_service != null)
assert(shop_service != null)
assert(session != null and session.is_host())

View file

@ -55,6 +55,20 @@ const SALT_WATER_IDS: Array[StringName] = [
&"salmon_coho",
&"salmon_pink",
&"salmon_sockeye",
&"anchovy_european", &"anchovy_northern",
&"grouper_gulf", &"grouper_red",
&"mackerel_atlantic", &"mackerel_cero", &"mackerel_chub",
&"mackerel_king", &"mackerel_spanish",
&"marlin_black", &"marlin_blue", &"marlin_white",
&"pomfret_black", &"pomfret_chinese", &"pomfret_golden",
&"pomfret_white", &"sailfish",
&"snapper_lane", &"snapper_mangrove", &"snapper_mutton",
&"snapper_red", &"swordfish",
]
const NEW_FRESH_WATER_IDS: Array[StringName] = [
&"chub_european", &"chub_flame", &"chub_lake", &"goldfish",
&"goldfish_bubbleeye", &"sauger", &"saugeye", &"trout_cutthroat",
&"trout_golden", &"trout_rainbow", &"trout_steelhead", &"walleye",
]
@ -64,6 +78,7 @@ func _initialize() -> void:
func _run() -> void:
_validate_catalog_and_pools()
_validate_weight_based_display_scale()
_validate_starter_water_bodies()
_validate_authoritative_water_filter()
_validate_catches_and_authoritative_sale()
@ -71,10 +86,42 @@ func _run() -> void:
quit()
func _validate_weight_based_display_scale() -> void:
var previous_scale: float = 0.0
for fish: FishDataType in Catalog.candidates:
assert(fish.is_selectable())
assert(fish.weight_min_lb > 0.0)
assert(fish.weight_max_lb <= 1000.0)
var minimum_scale: float = fish.get_display_scale_for_weight(
fish.weight_min_lb
)
var maximum_scale: float = fish.get_display_scale_for_weight(
fish.weight_max_lb
)
assert(minimum_scale >= FishDataType.DISPLAY_MIN_SCALE)
assert(maximum_scale <= FishDataType.DISPLAY_MAX_SCALE)
assert(maximum_scale >= minimum_scale)
var midpoint_weight: float = lerpf(
fish.weight_min_lb,
fish.weight_max_lb,
0.5,
)
assert(
fish.get_display_scale_for_weight(midpoint_weight)
>= minimum_scale
)
# A one-pound catch is a shared visual reference, not a per-species
# texture-size decision.
var reference_scale: float = fish.get_display_scale_for_weight(1.0)
assert(is_equal_approx(reference_scale, FishDataType.DISPLAY_REFERENCE_SCALE))
previous_scale = maxf(previous_scale, maximum_scale)
assert(previous_scale <= FishDataType.DISPLAY_MAX_SCALE)
func _validate_catalog_and_pools() -> void:
assert(Catalog.candidates.size() == 19)
assert(PondPool.candidates.size() == 7)
assert(OceanPool.candidates.size() == 12)
assert(Catalog.candidates.size() == 53)
assert(PondPool.candidates.size() == 19)
assert(OceanPool.candidates.size() == 34)
for fish_id: StringName in ORIGINAL_IDS:
var original_fish: FishDataType = Catalog.get_fish_by_id(fish_id)
assert(original_fish != null)
@ -101,6 +148,12 @@ func _validate_catalog_and_pools() -> void:
assert(OceanPool.get_fish_by_id(fish_id) == null)
assert(fish.availability.allowed_location_tags == [&"starter_pond"])
assert(LogbookCatalog.category_for(fish) == WaterType.Type.FRESH_WATER)
for fish_id: StringName in NEW_FRESH_WATER_IDS:
var fish: FishDataType = Catalog.get_fish_by_id(fish_id)
assert(fish != null and fish.is_selectable())
assert(PondPool.get_fish_by_id(fish_id) == fish)
assert(OceanPool.get_fish_by_id(fish_id) == null)
assert(LogbookCatalog.category_for(fish) == WaterType.Type.FRESH_WATER)
var expected_values: Dictionary[StringName, Array] = {
&"catfish_blue": [1, 1.25, 3.0, 12.0, 6, 9],
@ -302,6 +355,12 @@ func _validate_catches_and_authoritative_sale() -> void:
assert(loaded != null)
assert(loaded.fish_id == fish.id)
assert(loaded.fish == fish)
assert(
is_equal_approx(
loaded.display_scale,
fish.get_display_scale_for_weight(loaded.weight_lb),
)
)
var replicated: FishCatch = FishCatchType.from_network_dict(
fish_catch.to_network_dict(), Catalog.get_fish_by_id(fish.id)
@ -309,6 +368,12 @@ func _validate_catches_and_authoritative_sale() -> void:
assert(replicated != null)
assert(replicated.fish_id == fish.id)
assert(replicated.fish.display_texture == fish.display_texture)
assert(
is_equal_approx(
replicated.display_scale,
fish.get_display_scale_for_weight(replicated.weight_lb),
)
)
inventory.add_catch(loaded)
assert(inventory.contains_catch_id(loaded.catch_id))

View file

@ -79,15 +79,38 @@ func _validate_barrier_challenge_curve() -> void:
FishQualityType.BARRIER_HEALTH_MULTIPLIERS.size()
== FishQualityType.TIER_COUNT
)
var expected_health: Array[int] = [8, 10, 13, 18, 26]
var expected_minimums: Array[int] = [1, 10, 50, 100, 200]
var expected_maximums: Array[int] = [9, 50, 100, 200, 400]
var previous_health: int = 0
for quality: int in FishQualityType.TIER_COUNT:
var health: int = FishQualityType.apply_barrier_health(8, quality)
assert(health == expected_health[quality])
assert(health > previous_health)
previous_health = health
assert(FishQualityType.apply_barrier_health(8, -1) == 8)
assert(FishQualityType.apply_barrier_health(0, FishQualityType.Tier.SHINY) == 4)
var impressive_low_input: int = FishQualityType.barrier_health_for_catch(
FishQualityType.Tier.IMPRESSIVE,
0,
0.0,
1.0,
)
var impressive_high_input: int = FishQualityType.barrier_health_for_catch(
FishQualityType.Tier.IMPRESSIVE,
4,
1.0,
1.0,
)
assert(impressive_low_input >= 50 and impressive_low_input <= 100)
assert(impressive_high_input > impressive_low_input)
assert(impressive_high_input <= 100)
assert(
FishQualityType.barrier_health_for_catch(
FishQualityType.Tier.BORING,
4,
1.0,
1.0,
) <= 9
)
var profile := CatchDifficultyProfile.new()
profile.barrier_count_min = 1
@ -113,20 +136,24 @@ func _validate_barrier_challenge_curve() -> void:
assert(barriers.size() == 1)
var barrier := barriers[0] as RefCounted
assert(barrier != null)
assert(int(barrier.get("maximum_health")) == expected_health[quality])
var health: int = int(barrier.get("maximum_health"))
assert(health >= expected_minimums[quality])
assert(health <= expected_maximums[quality])
controller.queue_free()
var shiny_health: int = FishQualityType.apply_barrier_health(
8,
var shiny_health: int = FishQualityType.barrier_health_for_catch(
FishQualityType.Tier.SHINY,
4,
1.0,
1.0,
)
var base_power_clicks: int = ceili(float(shiny_health) / 1.0)
var max_power_clicks: int = ceili(
float(shiny_health)
/ float(PlayerFishingUpgrades.MAX_BARRIER_POWER_LEVEL + 1)
)
assert(base_power_clicks == 26)
assert(max_power_clicks == 7)
assert(base_power_clicks == 400)
assert(max_power_clicks == 100)
assert(max_power_clicks < base_power_clicks)
@ -191,7 +218,7 @@ func _validate_catch_round_trip_and_sale() -> void:
selector.deterministic_test_seed = 9911
selector.quality_weight_multipliers = [0.0, 0.0, 0.0, 0.0, 1.0]
selector.begin_roll()
var fish_catch: FishCatch = selector.create_catch(fish)
var fish_catch: FishCatch = selector.create_catch(fish, [&"worm"])
assert(fish_catch != null)
assert(fish_catch.quality == FishQualityType.Tier.SHINY)
assert(

View file

@ -49,20 +49,20 @@ func _run() -> void:
assert(not hotbar.visible)
var entry_buttons: Dictionary = logbook.get("_entry_buttons")
assert(entry_buttons.size() == 7)
assert(entry_buttons.size() == 19)
await _capture_if_requested("-unknown")
logbook.call(
"_select_category", WaterType.Type.FRESH_WATER
)
await create_timer(0.25).timeout
assert((logbook.get("_entry_buttons") as Dictionary).size() == 7)
assert((logbook.get("_entry_buttons") as Dictionary).size() == 19)
await _capture_if_requested("-fresh")
logbook.call("_select_category", WaterType.Type.SALT_WATER)
await create_timer(0.25).timeout
assert((logbook.get("_entry_buttons") as Dictionary).size() == 12)
assert((logbook.get("_entry_buttons") as Dictionary).size() == 34)
logbook.call("_select_category", WaterType.Type.FRESH_WATER)
await create_timer(0.25).timeout
assert((logbook.get("_entry_buttons") as Dictionary).size() == 7)
assert((logbook.get("_entry_buttons") as Dictionary).size() == 19)
player.collection_log.mark_discovered(&"bluegill")
await process_frame
logbook.call("_select_entry", &"bluegill", &"bluegill")
@ -101,7 +101,7 @@ func _validate_save_round_trip(
var player := main.get("_player") as Player
var catalog := main.get("fish_catalog") as FishPool
assert(catalog != null)
assert(catalog.candidates.size() == 19)
assert(catalog.candidates.size() == 53)
for index: int in 4:
_add_test_catch(player, catalog.candidates[index])
assert(save_manager.save_now())
@ -122,7 +122,7 @@ func _validate_save_round_trip(
assert(player.inventory.replace_all_catches(no_catches, 1))
assert(player.collection_log.replace_discovered_ids(no_discoveries))
assert(save_manager.load_player_data())
assert(player.inventory.get_all_catches().size() == 19)
assert(player.inventory.get_all_catches().size() == 53)
for fish: FishData in catalog.candidates:
assert(player.inventory.get_count(fish.id) == 1)
assert(player.collection_log.has_discovered(fish.id))

View file

@ -60,17 +60,54 @@ func _validate_catalog() -> void:
&"salmon_coho",
&"salmon_pink",
&"salmon_sockeye",
&"anchovy_european",
&"anchovy_northern",
&"chub_european",
&"chub_flame",
&"chub_lake",
&"goldfish",
&"goldfish_bubbleeye",
&"grouper_gulf",
&"grouper_red",
&"mackerel_atlantic",
&"mackerel_cero",
&"mackerel_chub",
&"mackerel_king",
&"mackerel_spanish",
&"marlin_black",
&"marlin_blue",
&"marlin_white",
&"pomfret_black",
&"pomfret_chinese",
&"pomfret_golden",
&"pomfret_white",
&"sailfish",
&"sauger",
&"saugeye",
&"snapper_lane",
&"snapper_mangrove",
&"snapper_mutton",
&"snapper_red",
&"swordfish",
&"trout_cutthroat",
&"trout_golden",
&"trout_rainbow",
&"trout_steelhead",
&"walleye",
]
assert(LogbookCatalog.CATALOG_ORDER == expected_ids)
for index: int in expected_ids.size():
var fish := CatalogResource.get_fish_by_id(expected_ids[index])
assert(fish != null)
assert(LogbookCatalog.facts_for(fish.id) != "unknown")
assert(not LogbookCatalog.facts_for(fish.id).is_empty())
assert(
LogbookCatalog.facts_for(fish.id)
== LogbookCatalog.facts_for(fish.id).to_lower()
)
if LogbookCatalog.FISH_FACTS.has(fish.id):
assert(LogbookCatalog.facts_for(fish.id) != "unknown")
else:
assert(LogbookCatalog.facts_for(fish.id) == "unknown")
var expected_category: WaterType.Type = (
WaterType.Type.SALT_WATER
if expected_ids[index] in [
@ -86,6 +123,28 @@ func _validate_catalog() -> void:
&"salmon_coho",
&"salmon_pink",
&"salmon_sockeye",
&"anchovy_european",
&"anchovy_northern",
&"grouper_gulf",
&"grouper_red",
&"mackerel_atlantic",
&"mackerel_cero",
&"mackerel_chub",
&"mackerel_king",
&"mackerel_spanish",
&"marlin_black",
&"marlin_blue",
&"marlin_white",
&"pomfret_black",
&"pomfret_chinese",
&"pomfret_golden",
&"pomfret_white",
&"sailfish",
&"snapper_lane",
&"snapper_mangrove",
&"snapper_mutton",
&"snapper_red",
&"swordfish",
]
else WaterType.Type.FRESH_WATER
)
@ -129,7 +188,7 @@ func _validate_page() -> void:
page.call("_select_category", category)
await create_timer(0.25).timeout
var entries: Dictionary = page.get("_entry_buttons")
assert(entries.size() == (7 if category == WaterType.Type.FRESH_WATER else 12))
assert(entries.size() == (19 if category == WaterType.Type.FRESH_WATER else 34))
for fish: FishDataType in LogbookCatalog.ordered_species(
CatalogResource.candidates
):
@ -179,7 +238,7 @@ func _validate_page() -> void:
candidate.display_name
)
)
assert(silhouette_count == 19)
assert(silhouette_count == 53)
page.call("_select_category", WaterType.Type.OTHER)
await create_timer(0.25).timeout