Add freshwater habitats and saltwater tide ribbons

This commit is contained in:
Alexander Sellite 2026-07-31 16:05:44 -04:00
parent 53fdc9ef21
commit 69b7969e25
40 changed files with 1323 additions and 148 deletions

View file

@ -10,15 +10,22 @@ const FishingContextType = preload("res://fishing/fishing_context.gd")
const NetworkSaleServiceType = preload(
"res://network/network_sale_service.gd"
)
const NetworkFishingServiceType = preload(
"res://network/network_fishing_service.gd"
)
const FishingSpotType = preload("res://fishing/fishing_spot.gd")
const Catalog: FishPoolType = preload("res://fish/pools/fish_catalog.tres")
const PondPool: FishPoolType = preload(
"res://fish/pools/starter_pond_pool.tres"
)
const OceanPool: FishPoolType = preload(
"res://fish/pools/test_water_pool.tres"
"res://fish/pools/starter_ocean_pool.tres"
)
const PelicanBuyer = preload("res://economy/buyers/pelicans.tres")
const StarterRegionScene = preload(
"res://world/regions/starter_island_region.tscn"
)
const ORIGINAL_IDS: Array[StringName] = [
&"bluegill", &"bass", &"carp", &"sunfish",
@ -29,6 +36,11 @@ const CATFISH_IDS: Array[StringName] = [
&"catfish_flathead",
&"catfish_white",
]
const FRESH_WATER_IDS: Array[StringName] = [
&"bluegill", &"carp", &"catfish_blue", &"catfish_channel",
&"catfish_flathead", &"catfish_white",
]
const SALT_WATER_IDS: Array[StringName] = [&"bass", &"sunfish"]
func _initialize() -> void:
@ -37,6 +49,8 @@ func _initialize() -> void:
func _run() -> void:
_validate_catalog_and_pools()
_validate_starter_water_bodies()
_validate_authoritative_water_filter()
_validate_catches_and_authoritative_sale()
print("Fish catalog content validation: PASS")
quit()
@ -44,14 +58,26 @@ func _run() -> void:
func _validate_catalog_and_pools() -> void:
assert(Catalog.candidates.size() == 8)
assert(PondPool.candidates.size() == 8)
assert(OceanPool.candidates.size() == 4)
assert(PondPool.candidates.size() == 6)
assert(OceanPool.candidates.size() == 2)
for fish_id: StringName in ORIGINAL_IDS:
var original_fish: FishDataType = Catalog.get_fish_by_id(fish_id)
assert(original_fish != null)
assert(original_fish.is_selectable())
assert(PondPool.get_fish_by_id(fish_id) != null)
assert(OceanPool.get_fish_by_id(fish_id) != null)
for fish_id: StringName in FRESH_WATER_IDS:
var fresh_fish: FishDataType = Catalog.get_fish_by_id(fish_id)
assert(PondPool.get_fish_by_id(fish_id) == fresh_fish)
assert(OceanPool.get_fish_by_id(fish_id) == null)
assert(fresh_fish.is_allowed_in_water(WaterType.Type.FRESH_WATER))
assert(not fresh_fish.is_allowed_in_water(WaterType.Type.SALT_WATER))
assert(LogbookCatalog.category_for(fresh_fish) == WaterType.Type.FRESH_WATER)
for fish_id: StringName in SALT_WATER_IDS:
var salt_fish: FishDataType = Catalog.get_fish_by_id(fish_id)
assert(OceanPool.get_fish_by_id(fish_id) == salt_fish)
assert(PondPool.get_fish_by_id(fish_id) == null)
assert(salt_fish.is_allowed_in_water(WaterType.Type.SALT_WATER))
assert(not salt_fish.is_allowed_in_water(WaterType.Type.FRESH_WATER))
assert(LogbookCatalog.category_for(salt_fish) == WaterType.Type.SALT_WATER)
for fish_id: StringName in CATFISH_IDS:
var fish: FishDataType = Catalog.get_fish_by_id(fish_id)
assert(fish != null)
@ -59,9 +85,7 @@ func _validate_catalog_and_pools() -> void:
assert(PondPool.get_fish_by_id(fish_id) == fish)
assert(OceanPool.get_fish_by_id(fish_id) == null)
assert(fish.availability.allowed_location_tags == [&"starter_pond"])
assert(LogbookCatalog.category_for(fish) == (
LogbookCatalog.Category.FRESH_WATER
))
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],
@ -81,8 +105,10 @@ func _validate_catalog_and_pools() -> void:
var pond_context := FishingContextType.new()
pond_context.location_tags = [&"starter_pond"]
pond_context.water_type = WaterType.Type.FRESH_WATER
var ocean_context := FishingContextType.new()
ocean_context.location_tags = [&"coast", &"ocean"]
ocean_context.water_type = WaterType.Type.SALT_WATER
for fish_id: StringName in CATFISH_IDS:
var fish: FishDataType = Catalog.get_fish_by_id(fish_id)
assert(fish.availability.is_available(pond_context))
@ -99,6 +125,94 @@ func _validate_catalog_and_pools() -> void:
) == fish
)
collection.free()
for fish_id: StringName in SALT_WATER_IDS:
var fish: FishDataType = Catalog.get_fish_by_id(fish_id)
var single_species_pool := FishPoolType.new()
single_species_pool.candidates = [fish]
var collection := CollectionLogType.new()
var selector := FishSelectorType.new()
selector.use_deterministic_test_seed = true
selector.begin_roll()
assert(
selector.select_fish(single_species_pool, pond_context, collection)
== null
)
assert(
selector.select_fish(single_species_pool, ocean_context, collection)
== fish
)
collection.free()
func _validate_authoritative_water_filter() -> void:
var fishing_spot := FishingSpotType.new()
var service := NetworkFishingServiceType.new()
service.set("_fish_catalog", Catalog)
service.set("_fishing_spot", fishing_spot)
var pond_region := FishableWaterRegion.new()
pond_region.water_type = WaterType.Type.FRESH_WATER
pond_region.fish_pool = PondPool
pond_region.location_tags = [&"starter_pond"]
var ocean_region := FishableWaterRegion.new()
ocean_region.water_type = WaterType.Type.SALT_WATER
ocean_region.fish_pool = OceanPool
ocean_region.location_tags = [&"coast", &"ocean"]
var stale_salt_pool_region := FishableWaterRegion.new()
stale_salt_pool_region.water_type = WaterType.Type.FRESH_WATER
stale_salt_pool_region.fish_pool = OceanPool
stale_salt_pool_region.location_tags = [&"starter_pond"]
var stale_fresh_pool_region := FishableWaterRegion.new()
stale_fresh_pool_region.water_type = WaterType.Type.SALT_WATER
stale_fresh_pool_region.fish_pool = PondPool
stale_fresh_pool_region.location_tags = [&"coast", &"ocean"]
var evidence := {"discovered_fish_ids": []}
assert(
service.call("_select_authoritative_fish", pond_region, evidence, null)
!= null
)
assert(
service.call("_select_authoritative_fish", ocean_region, evidence, null)
!= null
)
assert(
service.call(
"_select_authoritative_fish", stale_salt_pool_region, evidence, null
) == null
)
assert(
service.call(
"_select_authoritative_fish", stale_fresh_pool_region, evidence, null
) == null
)
service.free()
fishing_spot.free()
pond_region.free()
ocean_region.free()
stale_salt_pool_region.free()
stale_fresh_pool_region.free()
func _validate_starter_water_bodies() -> void:
var region := StarterRegionScene.instantiate()
var pond := region.get_node("WaterBodies/Pond/FishingRegion") as FishableWaterRegion
var ocean := region.get_node(
"WaterBodies/Ocean/FishingRegions/OceanFishingRegion"
) as FishableWaterRegion
assert(pond.water_type == WaterType.Type.FRESH_WATER)
assert(ocean.water_type == WaterType.Type.SALT_WATER)
assert(pond.fish_pool == PondPool)
assert(ocean.fish_pool == OceanPool)
assert(region.get_node_or_null("ShorelineRibbons/Pond") == null)
assert(region.get_node_or_null("ShorelineRibbons/Ocean") != null)
var pond_material := (
region.get_node("WaterBodies/Pond/VisualWater") as MeshInstance3D
).material_override as ShaderMaterial
var ocean_material := (
region.get_node("WaterBodies/Ocean/VisualWater") as MeshInstance3D
).material_override as ShaderMaterial
assert(not bool(pond_material.get_shader_parameter("tide_effect_enabled")))
assert(bool(ocean_material.get_shader_parameter("tide_effect_enabled")))
region.free()
func _validate_catches_and_authoritative_sale() -> void:

View file

@ -45,20 +45,20 @@ func _run() -> void:
assert(not hotbar.visible)
var entry_buttons: Dictionary = logbook.get("_entry_buttons")
assert(entry_buttons.size() == 4)
assert(entry_buttons.size() == 0)
await _capture_if_requested("-unknown")
logbook.call(
"_select_category", LogbookCatalog.Category.FRESH_WATER
"_select_category", WaterType.Type.FRESH_WATER
)
await create_timer(0.25).timeout
assert((logbook.get("_entry_buttons") as Dictionary).size() == 4)
assert((logbook.get("_entry_buttons") as Dictionary).size() == 6)
await _capture_if_requested("-fresh")
logbook.call("_select_category", LogbookCatalog.Category.SALT_WATER)
logbook.call("_select_category", WaterType.Type.SALT_WATER)
await create_timer(0.25).timeout
assert((logbook.get("_entry_buttons") as Dictionary).is_empty())
logbook.call("_select_category", LogbookCatalog.Category.OTHER)
assert((logbook.get("_entry_buttons") as Dictionary).size() == 2)
logbook.call("_select_category", WaterType.Type.FRESH_WATER)
await create_timer(0.25).timeout
assert((logbook.get("_entry_buttons") as Dictionary).size() == 4)
assert((logbook.get("_entry_buttons") as Dictionary).size() == 6)
player.collection_log.mark_discovered(&"bluegill")
await process_frame
logbook.call("_select_entry", &"bluegill", &"bluegill")

View file

@ -48,10 +48,10 @@ func _validate_catalog() -> void:
for index: int in expected_ids.size():
var fish := CatalogResource.get_fish_by_id(expected_ids[index])
assert(fish != null)
var expected_category: LogbookCatalog.Category = (
LogbookCatalog.Category.OTHER
if index < 4
else LogbookCatalog.Category.FRESH_WATER
var expected_category: WaterType.Type = (
WaterType.Type.SALT_WATER
if expected_ids[index] in [&"bass", &"sunfish"]
else WaterType.Type.FRESH_WATER
)
assert(
LogbookCatalog.category_for(fish)
@ -59,7 +59,7 @@ func _validate_catalog() -> void:
)
assert(LogbookCatalog.catalog_number(fish.id) == index + 1)
assert(
LogbookCatalog.empty_state(LogbookCatalog.Category.SALT_WATER)
LogbookCatalog.empty_state(WaterType.Type.SALT_WATER)
== "No saltwater catches cataloged yet."
)
@ -78,14 +78,14 @@ func _validate_page() -> void:
var shared_material: Material
var silhouette_count: int = 0
for category: LogbookCatalog.Category in [
LogbookCatalog.Category.FRESH_WATER,
LogbookCatalog.Category.OTHER,
for category: WaterType.Type in [
WaterType.Type.FRESH_WATER,
WaterType.Type.SALT_WATER,
]:
page.call("_select_category", category)
await create_timer(0.25).timeout
var entries: Dictionary = page.get("_entry_buttons")
assert(entries.size() == 4)
assert(entries.size() == (6 if category == WaterType.Type.FRESH_WATER else 2))
for fish: FishDataType in LogbookCatalog.ordered_species(
CatalogResource.candidates
):
@ -133,14 +133,14 @@ func _validate_page() -> void:
)
assert(silhouette_count == 8)
page.call("_select_category", LogbookCatalog.Category.SALT_WATER)
page.call("_select_category", WaterType.Type.OTHER)
await create_timer(0.25).timeout
assert((page.get("_entry_buttons") as Dictionary).is_empty())
assert(
(page.get("_empty_state") as Label).text
== "No saltwater catches cataloged yet."
== "No entries available."
)
page.call("_select_category", LogbookCatalog.Category.OTHER)
page.call("_select_category", WaterType.Type.FRESH_WATER)
await create_timer(0.25).timeout
var bluegill = CatalogResource.get_fish_by_id(&"bluegill")
@ -175,7 +175,7 @@ func _validate_page() -> void:
await process_frame
assert(_detail_text(page).contains("number owned\n1"))
assert(_detail_text(page).contains("number caught\nUnknown"))
assert(_detail_text(page).contains("body of water\nUnknown"))
assert(_detail_text(page).contains("body of water\nFresh Water"))
assert(_detail_text(page).contains("catalog number\n#001"))
inventory.remove_catch_by_id(fish_catch.catch_id)