Stardew Valley: Fix Daggerfish, Cropsanity; Move Some Rules to Content Packs; Add Missing Shipsanity Location (#3626)

* Fix logic bug on daggerfish

* Make new region for pond.

* Fix SVE logic for crops

* Fix Distant Lands Cropsanity

* Fix failing tests.

* Reverting removing these for now.

* Fix bugs, add combat requirement

* convert str into tuple directly

* add ginger island to mod tests

* Move a lot of mod item logic to content pack

* Gut the rules from DL while we're at it.

* Import nuke

* Fix alecto

* Move back some rules for now.

* Move archaeology rules

* Add some comments why its done.

* Clean up archaeology and fix sve

* Moved dulse to water item class

* Remove digging like worms for now

* fix

* Add missing shipsanity location

* Move background names around or something idk

* Revert ArchaeologyTrash for now

---------

Co-authored-by: Jouramie <jouramie@hotmail.com>
This commit is contained in:
Witchybun 2024-07-25 02:22:46 -05:00 committed by GitHub
parent 8949e21565
commit 205ca7fa37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 258 additions and 163 deletions

View File

@ -0,0 +1,33 @@
from ..game_content import ContentPack, StardewContent
from ..mod_registry import register_mod_content_pack
from ...data import villagers_data
from ...data.harvest import ForagingSource
from ...data.requirement import QuestRequirement
from ...mods.mod_data import ModNames
from ...strings.quest_names import ModQuest
from ...strings.region_names import Region
from ...strings.seed_names import DistantLandsSeed
class AlectoContentPack(ContentPack):
def harvest_source_hook(self, content: StardewContent):
if ModNames.distant_lands in content.registered_packs:
content.game_items.pop(DistantLandsSeed.void_mint)
content.game_items.pop(DistantLandsSeed.vile_ancient_fruit)
content.source_item(DistantLandsSeed.void_mint,
ForagingSource(regions=(Region.witch_swamp,), other_requirements=(QuestRequirement(ModQuest.WitchOrder),)),),
content.source_item(DistantLandsSeed.vile_ancient_fruit,
ForagingSource(regions=(Region.witch_swamp,), other_requirements=(QuestRequirement(ModQuest.WitchOrder),)), ),
register_mod_content_pack(ContentPack(
ModNames.alecto,
weak_dependencies=(
ModNames.distant_lands, # For Witch's order
),
villagers=(
villagers_data.alecto,
)
))

View File

@ -1,20 +1,34 @@
from ..game_content import ContentPack
from ..game_content import ContentPack, StardewContent
from ..mod_registry import register_mod_content_pack
from ...data.game_item import ItemTag, Tag
from ...data.shop import ShopSource
from ...data.artisan import MachineSource
from ...data.skill import Skill
from ...mods.mod_data import ModNames
from ...strings.book_names import ModBook
from ...strings.region_names import LogicRegion
from ...strings.craftable_names import ModMachine
from ...strings.fish_names import ModTrash
from ...strings.metal_names import all_artifacts, all_fossils
from ...strings.skill_names import ModSkill
register_mod_content_pack(ContentPack(
class ArchaeologyContentPack(ContentPack):
def artisan_good_hook(self, content: StardewContent):
# Done as honestly there are too many display items to put into the initial registration traditionally.
display_items = all_artifacts + all_fossils
for item in display_items:
self.source_display_items(item, content)
content.source_item(ModTrash.rusty_scrap, *(MachineSource(item=artifact, machine=ModMachine.grinder) for artifact in all_artifacts))
def source_display_items(self, item: str, content: StardewContent):
wood_display = f"Wooden Display: {item}"
hardwood_display = f"Hardwood Display: {item}"
if item == "Trilobite":
wood_display = f"Wooden Display: Trilobite Fossil"
hardwood_display = f"Hardwood Display: Trilobite Fossil"
content.source_item(wood_display, MachineSource(item=str(item), machine=ModMachine.preservation_chamber))
content.source_item(hardwood_display, MachineSource(item=str(item), machine=ModMachine.hardwood_preservation_chamber))
register_mod_content_pack(ArchaeologyContentPack(
ModNames.archaeology,
shop_sources={
ModBook.digging_like_worms: (
Tag(ItemTag.BOOK, ItemTag.BOOK_SKILL),
ShopSource(money_price=500, shop_region=LogicRegion.bookseller_1),),
},
skills=(Skill(name=ModSkill.archaeology, has_mastery=False),),
))

View File

@ -1,9 +1,26 @@
from ..game_content import ContentPack
from ..game_content import ContentPack, StardewContent
from ..mod_registry import register_mod_content_pack
from ...data import villagers_data, fish_data
from ...data.game_item import ItemTag, Tag
from ...data.harvest import ForagingSource, HarvestCropSource
from ...data.requirement import QuestRequirement
from ...mods.mod_data import ModNames
from ...strings.crop_names import DistantLandsCrop
from ...strings.forageable_names import DistantLandsForageable
from ...strings.quest_names import ModQuest
from ...strings.region_names import Region
from ...strings.season_names import Season
from ...strings.seed_names import DistantLandsSeed
register_mod_content_pack(ContentPack(
class DistantLandsContentPack(ContentPack):
def harvest_source_hook(self, content: StardewContent):
content.untag_item(DistantLandsSeed.void_mint, tag=ItemTag.CROPSANITY_SEED)
content.untag_item(DistantLandsSeed.vile_ancient_fruit, tag=ItemTag.CROPSANITY_SEED)
register_mod_content_pack(DistantLandsContentPack(
ModNames.distant_lands,
fishes=(
fish_data.void_minnow,
@ -13,5 +30,13 @@ register_mod_content_pack(ContentPack(
),
villagers=(
villagers_data.zic,
)
),
harvest_sources={
DistantLandsForageable.swamp_herb: (ForagingSource(regions=(Region.witch_swamp,)),),
DistantLandsForageable.brown_amanita: (ForagingSource(regions=(Region.witch_swamp,)),),
DistantLandsSeed.void_mint: (ForagingSource(regions=(Region.witch_swamp,), other_requirements=(QuestRequirement(ModQuest.CorruptedCropsTask),)),),
DistantLandsCrop.void_mint: (Tag(ItemTag.VEGETABLE), HarvestCropSource(seed=DistantLandsSeed.void_mint, seasons=(Season.spring, Season.summer, Season.fall)),),
DistantLandsSeed.vile_ancient_fruit: (ForagingSource(regions=(Region.witch_swamp,), other_requirements=(QuestRequirement(ModQuest.CorruptedCropsTask),)),),
DistantLandsCrop.vile_ancient_fruit: (Tag(ItemTag.FRUIT), HarvestCropSource(seed=DistantLandsSeed.vile_ancient_fruit, seasons=(Season.spring, Season.summer, Season.fall)),)
}
))

View File

@ -73,13 +73,6 @@ register_mod_content_pack(ContentPack(
)
))
register_mod_content_pack(ContentPack(
ModNames.alecto,
villagers=(
villagers_data.alecto,
)
))
register_mod_content_pack(ContentPack(
ModNames.lacey,
villagers=(

View File

@ -3,15 +3,27 @@ from ..mod_registry import register_mod_content_pack
from ..override import override
from ..vanilla.ginger_island import ginger_island_content_pack as ginger_island_content_pack
from ...data import villagers_data, fish_data
from ...data.harvest import ForagingSource
from ...data.requirement import YearRequirement
from ...data.game_item import ItemTag, Tag
from ...data.harvest import ForagingSource, HarvestCropSource
from ...data.requirement import YearRequirement, CombatRequirement, RelationshipRequirement, ToolRequirement, SkillRequirement, FishingRequirement
from ...data.shop import ShopSource
from ...mods.mod_data import ModNames
from ...strings.crop_names import Fruit
from ...strings.fish_names import WaterItem
from ...strings.craftable_names import ModEdible
from ...strings.crop_names import Fruit, SVEVegetable, SVEFruit
from ...strings.fish_names import WaterItem, SVEFish, SVEWaterItem
from ...strings.flower_names import Flower
from ...strings.forageable_names import Mushroom, Forageable
from ...strings.region_names import Region, SVERegion
from ...strings.food_names import SVEMeal, SVEBeverage
from ...strings.forageable_names import Mushroom, Forageable, SVEForage
from ...strings.gift_names import SVEGift
from ...strings.metal_names import Ore
from ...strings.monster_drop_names import ModLoot, Loot
from ...strings.performance_names import Performance
from ...strings.region_names import Region, SVERegion, LogicRegion
from ...strings.season_names import Season
from ...strings.seed_names import SVESeed
from ...strings.skill_names import Skill
from ...strings.tool_names import Tool, ToolMaterial
from ...strings.villager_names import ModNPC
class SVEContentPack(ContentPack):
@ -38,6 +50,24 @@ class SVEContentPack(ContentPack):
# Remove Lance if Ginger Island is not in content since he is first encountered in Volcano Forge
content.villagers.pop(villagers_data.lance.name)
def harvest_source_hook(self, content: StardewContent):
content.untag_item(SVESeed.shrub, tag=ItemTag.CROPSANITY_SEED)
content.untag_item(SVESeed.fungus, tag=ItemTag.CROPSANITY_SEED)
content.untag_item(SVESeed.slime, tag=ItemTag.CROPSANITY_SEED)
content.untag_item(SVESeed.stalk, tag=ItemTag.CROPSANITY_SEED)
content.untag_item(SVESeed.void, tag=ItemTag.CROPSANITY_SEED)
content.untag_item(SVESeed.ancient_fern, tag=ItemTag.CROPSANITY_SEED)
if ginger_island_content_pack.name not in content.registered_packs:
# Remove Highlands seeds as these are behind Lance existing.
content.game_items.pop(SVESeed.void)
content.game_items.pop(SVEVegetable.void_root)
content.game_items.pop(SVESeed.stalk)
content.game_items.pop(SVEFruit.monster_fruit)
content.game_items.pop(SVESeed.fungus)
content.game_items.pop(SVEVegetable.monster_mushroom)
content.game_items.pop(SVESeed.slime)
content.game_items.pop(SVEFruit.slime_berry)
register_mod_content_pack(SVEContentPack(
ModNames.sve,
@ -45,12 +75,24 @@ register_mod_content_pack(SVEContentPack(
ginger_island_content_pack.name,
ModNames.jasper, # To override Marlon and Gunther
),
shop_sources={
SVEGift.aged_blue_moon_wine: (ShopSource(money_price=28000, shop_region=SVERegion.blue_moon_vineyard),),
SVEGift.blue_moon_wine: (ShopSource(money_price=3000, shop_region=SVERegion.blue_moon_vineyard),),
ModEdible.lightning_elixir: (ShopSource(money_price=12000, shop_region=SVERegion.galmoran_outpost),),
ModEdible.barbarian_elixir: (ShopSource(money_price=22000, shop_region=SVERegion.galmoran_outpost),),
ModEdible.gravity_elixir: (ShopSource(money_price=4000, shop_region=SVERegion.galmoran_outpost),),
SVEMeal.grampleton_orange_chicken: (ShopSource(money_price=650, shop_region=Region.saloon, other_requirements=(RelationshipRequirement(ModNPC.sophia, 6),)),),
ModEdible.hero_elixir: (ShopSource(money_price=8000, shop_region=SVERegion.isaac_shop),),
ModEdible.aegis_elixir: (ShopSource(money_price=28000, shop_region=SVERegion.galmoran_outpost),),
SVEBeverage.sports_drink: (ShopSource(money_price=750, shop_region=Region.hospital),),
SVEMeal.stamina_capsule: (ShopSource(money_price=4000, shop_region=Region.hospital),),
},
harvest_sources={
Mushroom.red: (
ForagingSource(regions=(SVERegion.forest_west,), seasons=(Season.summer, Season.fall)), ForagingSource(regions=(SVERegion.sprite_spring_cave,), )
),
Mushroom.purple: (
ForagingSource(regions=(SVERegion.forest_west,), seasons=(Season.fall,)), ForagingSource(regions=(SVERegion.sprite_spring_cave,), )
ForagingSource(regions=(SVERegion.forest_west,), seasons=(Season.fall,)), ForagingSource(regions=(SVERegion.sprite_spring_cave, SVERegion.junimo_woods), )
),
Mushroom.morel: (
ForagingSource(regions=(SVERegion.forest_west,), seasons=(Season.fall,)), ForagingSource(regions=(SVERegion.sprite_spring_cave,), )
@ -64,17 +106,59 @@ register_mod_content_pack(SVEContentPack(
Flower.sunflower: (ForagingSource(regions=(SVERegion.sprite_spring,), seasons=(Season.summer,)),),
Flower.fairy_rose: (ForagingSource(regions=(SVERegion.sprite_spring,), seasons=(Season.fall,)),),
Fruit.ancient_fruit: (
ForagingSource(regions=(SVERegion.sprite_spring,), seasons=(Season.spring, Season.summer, Season.fall), other_requirements=(YearRequirement(3),)),
ForagingSource(regions=(SVERegion.sprite_spring,), seasons=Season.not_winter, other_requirements=(YearRequirement(3),)),
ForagingSource(regions=(SVERegion.sprite_spring_cave,)),
),
Fruit.sweet_gem_berry: (
ForagingSource(regions=(SVERegion.sprite_spring,), seasons=(Season.spring, Season.summer, Season.fall), other_requirements=(YearRequirement(3),)),
ForagingSource(regions=(SVERegion.sprite_spring,), seasons=Season.not_winter, other_requirements=(YearRequirement(3),)),
),
# New items
ModLoot.green_mushroom: (ForagingSource(regions=(SVERegion.highlands_pond,), seasons=Season.not_winter),),
ModLoot.ornate_treasure_chest: (ForagingSource(regions=(SVERegion.highlands_outside,),
other_requirements=(CombatRequirement(Performance.galaxy), ToolRequirement(Tool.axe, ToolMaterial.iron))),),
ModLoot.swirl_stone: (ForagingSource(regions=(SVERegion.crimson_badlands,), other_requirements=(CombatRequirement(Performance.galaxy),)),),
ModLoot.void_soul: (ForagingSource(regions=(SVERegion.crimson_badlands,), other_requirements=(CombatRequirement(Performance.good),)),),
SVEForage.winter_star_rose: (ForagingSource(regions=(SVERegion.summit,), seasons=(Season.winter,)),),
SVEForage.bearberry: (ForagingSource(regions=(Region.secret_woods,), seasons=(Season.winter,)),),
SVEForage.poison_mushroom: (ForagingSource(regions=(Region.secret_woods,), seasons=(Season.summer, Season.fall)),),
SVEForage.red_baneberry: (ForagingSource(regions=(Region.secret_woods,), seasons=(Season.summer, Season.summer)),),
SVEForage.ferngill_primrose: (ForagingSource(regions=(SVERegion.summit,), seasons=(Season.spring,)),),
SVEForage.goldenrod: (ForagingSource(regions=(SVERegion.summit,), seasons=(Season.summer, Season.fall)),),
SVEForage.conch: (ForagingSource(regions=(Region.beach, SVERegion.fable_reef,)),),
SVEForage.dewdrop_berry: (ForagingSource(regions=(SVERegion.enchanted_grove,)),),
SVEForage.sand_dollar: (ForagingSource(regions=(Region.beach, SVERegion.fable_reef,), seasons=(Season.spring, Season.summer)),),
SVEForage.golden_ocean_flower: (ForagingSource(regions=(SVERegion.fable_reef,)),),
SVEForage.four_leaf_clover: (ForagingSource(regions=(Region.secret_woods, SVERegion.forest_west,), seasons=(Season.summer, Season.fall)),),
SVEForage.mushroom_colony: (ForagingSource(regions=(Region.secret_woods, SVERegion.junimo_woods, SVERegion.forest_west,), seasons=(Season.fall,)),),
SVEForage.rusty_blade: (ForagingSource(regions=(SVERegion.crimson_badlands,), other_requirements=(CombatRequirement(Performance.great),)),),
SVEForage.rafflesia: (ForagingSource(regions=(Region.secret_woods,), seasons=Season.not_winter),),
SVEForage.thistle: (ForagingSource(regions=(SVERegion.summit,)),),
ModLoot.void_pebble: (ForagingSource(regions=(SVERegion.crimson_badlands,), other_requirements=(CombatRequirement(Performance.great),)),),
ModLoot.void_shard: (ForagingSource(regions=(SVERegion.crimson_badlands,),
other_requirements=(CombatRequirement(Performance.galaxy), SkillRequirement(Skill.combat, 10), YearRequirement(3),)),),
SVEWaterItem.dulse_seaweed: (ForagingSource(regions=(Region.beach,), other_requirements=(FishingRequirement(Region.beach),)),),
# Fable Reef
WaterItem.coral: (ForagingSource(regions=(SVERegion.fable_reef,)),),
Forageable.rainbow_shell: (ForagingSource(regions=(SVERegion.fable_reef,)),),
WaterItem.sea_urchin: (ForagingSource(regions=(SVERegion.fable_reef,)),),
# Crops
SVESeed.shrub: (ForagingSource(regions=(Region.secret_woods,), other_requirements=(CombatRequirement(Performance.good),)),),
SVEFruit.salal_berry: (Tag(ItemTag.FRUIT), HarvestCropSource(seed=SVESeed.shrub, seasons=(Season.spring,)),),
SVESeed.slime: (ForagingSource(regions=(SVERegion.highlands_outside,), other_requirements=(CombatRequirement(Performance.good),)),),
SVEFruit.slime_berry: (Tag(ItemTag.FRUIT), HarvestCropSource(seed=SVESeed.slime, seasons=(Season.spring,)),),
SVESeed.ancient_fern: (ForagingSource(regions=(Region.secret_woods,)),),
SVEVegetable.ancient_fiber: (Tag(ItemTag.VEGETABLE), HarvestCropSource(seed=SVESeed.ancient_fern, seasons=(Season.summer,)),),
SVESeed.stalk: (ForagingSource(regions=(SVERegion.highlands_outside,), other_requirements=(CombatRequirement(Performance.good),)),),
SVEFruit.monster_fruit: (Tag(ItemTag.FRUIT), HarvestCropSource(seed=SVESeed.stalk, seasons=(Season.summer,)),),
SVESeed.fungus: (ForagingSource(regions=(SVERegion.highlands_pond,), other_requirements=(CombatRequirement(Performance.good),)),),
SVEVegetable.monster_mushroom: (Tag(ItemTag.VEGETABLE), HarvestCropSource(seed=SVESeed.fungus, seasons=(Season.fall,)),),
SVESeed.void: (ForagingSource(regions=(SVERegion.highlands_cavern,), other_requirements=(CombatRequirement(Performance.good),)),),
SVEVegetable.void_root: (Tag(ItemTag.VEGETABLE), HarvestCropSource(seed=SVESeed.void, seasons=(Season.winter,)),),
},
fishes=(
fish_data.baby_lunaloo, # Removed when no ginger island

View File

@ -229,7 +229,7 @@ pelican_town = ContentPack(
ShopSource(money_price=20000, shop_region=LogicRegion.bookseller_3),),
Book.mapping_cave_systems: (
Tag(ItemTag.BOOK, ItemTag.BOOK_POWER),
GenericSource(regions=Region.adventurer_guild_bedroom),
GenericSource(regions=(Region.adventurer_guild_bedroom,)),
ShopSource(money_price=20000, shop_region=LogicRegion.bookseller_3),),
Book.monster_compendium: (
Tag(ItemTag.BOOK, ItemTag.BOOK_POWER),
@ -243,12 +243,12 @@ pelican_town = ContentPack(
ShopSource(money_price=3000, shop_region=LogicRegion.bookseller_2),),
Book.the_alleyway_buffet: (
Tag(ItemTag.BOOK, ItemTag.BOOK_POWER),
GenericSource(regions=Region.town,
GenericSource(regions=(Region.town,),
other_requirements=(ToolRequirement(Tool.axe, ToolMaterial.iron), ToolRequirement(Tool.pickaxe, ToolMaterial.iron))),
ShopSource(money_price=20000, shop_region=LogicRegion.bookseller_3),),
Book.the_art_o_crabbing: (
Tag(ItemTag.BOOK, ItemTag.BOOK_POWER),
GenericSource(regions=Region.beach,
GenericSource(regions=(Region.beach,),
other_requirements=(ToolRequirement(Tool.fishing_rod, ToolMaterial.iridium),
SkillRequirement(Skill.fishing, 6),
SeasonRequirement(Season.winter))),

View File

@ -46,7 +46,8 @@ pirate_cove = (Region.pirate_cove,)
crimson_badlands = (SVERegion.crimson_badlands,)
shearwater = (SVERegion.shearwater,)
highlands = (SVERegion.highlands_outside,)
highlands_pond = (SVERegion.highlands_pond,)
highlands_cave = (SVERegion.highlands_cavern,)
sprite_spring = (SVERegion.sprite_spring,)
fable_reef = (SVERegion.fable_reef,)
vineyard = (SVERegion.blue_moon_vineyard,)
@ -133,9 +134,9 @@ bonefish = create_fish(SVEFish.bonefish, crimson_badlands, season.all_seasons, 7
bull_trout = create_fish(SVEFish.bull_trout, forest_river, season.not_spring, 45, mod_name=ModNames.sve)
butterfish = create_fish(SVEFish.butterfish, shearwater, season.not_winter, 75, mod_name=ModNames.sve)
clownfish = create_fish(SVEFish.clownfish, ginger_island_ocean, season.all_seasons, 45, mod_name=ModNames.sve)
daggerfish = create_fish(SVEFish.daggerfish, highlands, season.all_seasons, 50, mod_name=ModNames.sve)
daggerfish = create_fish(SVEFish.daggerfish, highlands_pond, season.all_seasons, 50, mod_name=ModNames.sve)
frog = create_fish(SVEFish.frog, mountain_lake, (season.spring, season.summer), 70, mod_name=ModNames.sve)
gemfish = create_fish(SVEFish.gemfish, highlands, season.all_seasons, 100, mod_name=ModNames.sve)
gemfish = create_fish(SVEFish.gemfish, highlands_cave, season.all_seasons, 100, mod_name=ModNames.sve)
goldenfish = create_fish(SVEFish.goldenfish, sprite_spring, season.all_seasons, 60, mod_name=ModNames.sve)
grass_carp = create_fish(SVEFish.grass_carp, secret_woods, (season.spring, season.summer), 85, mod_name=ModNames.sve)
king_salmon = create_fish(SVEFish.king_salmon, forest_river, (season.spring, season.summer), 80, mod_name=ModNames.sve)

View File

@ -2900,7 +2900,6 @@ id,region,name,tags,mod_name
7055,Abandoned Mines - 3,Abandoned Treasure - Floor 3,MANDATORY,Boarding House and Bus Stop Extension
7056,Abandoned Mines - 4,Abandoned Treasure - Floor 4,MANDATORY,Boarding House and Bus Stop Extension
7057,Abandoned Mines - 5,Abandoned Treasure - Floor 5,MANDATORY,Boarding House and Bus Stop Extension
7351,Farm,Read Digging Like Worms,"BOOKSANITY,BOOKSANITY_SKILL",Archaeology
7401,Farm,Cook Magic Elixir,COOKSANITY,Magic
7402,Farm,Craft Travel Core,CRAFTSANITY,Magic
7403,Farm,Craft Haste Elixir,CRAFTSANITY,Stardew Valley Expanded
@ -3280,10 +3279,10 @@ id,region,name,tags,mod_name
8237,Shipping,Shipsanity: Pterodactyl R Wing Bone,SHIPSANITY,Boarding House and Bus Stop Extension
8238,Shipping,Shipsanity: Scrap Rust,SHIPSANITY,Archaeology
8239,Shipping,Shipsanity: Rusty Path,SHIPSANITY,Archaeology
8240,Shipping,Shipsanity: Digging Like Worms,SHIPSANITY,Archaeology
8241,Shipping,Shipsanity: Digger's Delight,SHIPSANITY,Archaeology
8242,Shipping,Shipsanity: Rocky Root Coffee,SHIPSANITY,Archaeology
8243,Shipping,Shipsanity: Ancient Jello,SHIPSANITY,Archaeology
8244,Shipping,Shipsanity: Bone Fence,SHIPSANITY,Archaeology
8245,Shipping,Shipsanity: Grilled Cheese,SHIPSANITY,Binning Skill
8246,Shipping,Shipsanity: Fish Casserole,SHIPSANITY,Binning Skill
8247,Shipping,Shipsanity: Snatcher Worm,SHIPSANITY,Stardew Valley Expanded

1 id region name tags mod_name
2900 7055 Abandoned Mines - 3 Abandoned Treasure - Floor 3 MANDATORY Boarding House and Bus Stop Extension
2901 7056 Abandoned Mines - 4 Abandoned Treasure - Floor 4 MANDATORY Boarding House and Bus Stop Extension
2902 7057 Abandoned Mines - 5 Abandoned Treasure - Floor 5 MANDATORY Boarding House and Bus Stop Extension
7351 Farm Read Digging Like Worms BOOKSANITY,BOOKSANITY_SKILL Archaeology
2903 7401 Farm Cook Magic Elixir COOKSANITY Magic
2904 7402 Farm Craft Travel Core CRAFTSANITY Magic
2905 7403 Farm Craft Haste Elixir CRAFTSANITY Stardew Valley Expanded
3279 8237 Shipping Shipsanity: Pterodactyl R Wing Bone SHIPSANITY Boarding House and Bus Stop Extension
3280 8238 Shipping Shipsanity: Scrap Rust SHIPSANITY Archaeology
3281 8239 Shipping Shipsanity: Rusty Path SHIPSANITY Archaeology
8240 Shipping Shipsanity: Digging Like Worms SHIPSANITY Archaeology
3282 8241 Shipping Shipsanity: Digger's Delight SHIPSANITY Archaeology
3283 8242 Shipping Shipsanity: Rocky Root Coffee SHIPSANITY Archaeology
3284 8243 Shipping Shipsanity: Ancient Jello SHIPSANITY Archaeology
3285 8244 Shipping Shipsanity: Bone Fence SHIPSANITY Archaeology
3286 8245 Shipping Shipsanity: Grilled Cheese SHIPSANITY Binning Skill
3287 8246 Shipping Shipsanity: Fish Casserole SHIPSANITY Binning Skill
3288 8247 Shipping Shipsanity: Snatcher Worm SHIPSANITY Stardew Valley Expanded

View File

@ -5,7 +5,7 @@ from ..strings.animal_product_names import AnimalProduct
from ..strings.artisan_good_names import ArtisanGood
from ..strings.craftable_names import ModEdible, Edible
from ..strings.crop_names import Fruit, Vegetable, SVEFruit, DistantLandsCrop
from ..strings.fish_names import Fish, SVEFish, WaterItem, DistantLandsFish
from ..strings.fish_names import Fish, SVEFish, WaterItem, DistantLandsFish, SVEWaterItem
from ..strings.flower_names import Flower
from ..strings.forageable_names import Forageable, SVEForage, DistantLandsForageable, Mushroom
from ..strings.ingredient_names import Ingredient
@ -195,7 +195,7 @@ mixed_berry_pie = shop_recipe(SVEMeal.mixed_berry_pie, Region.saloon, 3500, {Fru
ModNames.sve)
mushroom_berry_rice = friendship_and_shop_recipe(SVEMeal.mushroom_berry_rice, ModNPC.marlon, 6, Region.adventurer_guild, 1500, {SVEForage.poison_mushroom: 3, SVEForage.red_baneberry: 10,
Ingredient.rice: 1, Ingredient.sugar: 2}, ModNames.sve)
seaweed_salad = shop_recipe(SVEMeal.seaweed_salad, Region.fish_shop, 1250, {SVEFish.dulse_seaweed: 2, WaterItem.seaweed: 2, Ingredient.oil: 1}, ModNames.sve)
seaweed_salad = shop_recipe(SVEMeal.seaweed_salad, Region.fish_shop, 1250, {SVEWaterItem.dulse_seaweed: 2, WaterItem.seaweed: 2, Ingredient.oil: 1}, ModNames.sve)
void_delight = friendship_and_shop_recipe(SVEMeal.void_delight, NPC.krobus, 10, Region.sewer, 5000,
{SVEFish.void_eel: 1, Loot.void_essence: 50, Loot.solar_essence: 20}, ModNames.sve)
void_salmon_sushi = friendship_and_shop_recipe(SVEMeal.void_salmon_sushi, NPC.krobus, 10, Region.sewer, 5000,

View File

@ -31,6 +31,27 @@ class YearRequirement(Requirement):
year: int
@dataclass(frozen=True)
class CombatRequirement(Requirement):
level: str
@dataclass(frozen=True)
class QuestRequirement(Requirement):
quest: str
@dataclass(frozen=True)
class RelationshipRequirement(Requirement):
npc: str
hearts: int
@dataclass(frozen=True)
class FishingRequirement(Requirement):
region: str
@dataclass(frozen=True)
class WalnutRequirement(Requirement):
amount: int

View File

@ -16,8 +16,8 @@ class ShopSource(ItemSource):
other_requirements: Tuple[Requirement, ...] = ()
def __post_init__(self):
assert self.money_price or self.items_price, "At least money price or items price need to be defined."
assert self.items_price is None or all(type(p) == tuple for p in self.items_price), "Items price should be a tuple."
assert self.money_price is not None or self.items_price is not None, "At least money price or items price need to be defined."
assert self.items_price is None or all(isinstance(p, tuple) for p in self.items_price), "Items price should be a tuple."
@dataclass(frozen=True, **kw_only)

View File

@ -3,15 +3,20 @@ from typing import Union, Iterable
from .base_logic import BaseLogicMixin, BaseLogic
from .book_logic import BookLogicMixin
from .combat_logic import CombatLogicMixin
from .fishing_logic import FishingLogicMixin
from .has_logic import HasLogicMixin
from .quest_logic import QuestLogicMixin
from .received_logic import ReceivedLogicMixin
from .relationship_logic import RelationshipLogicMixin
from .season_logic import SeasonLogicMixin
from .skill_logic import SkillLogicMixin
from .time_logic import TimeLogicMixin
from .tool_logic import ToolLogicMixin
from .walnut_logic import WalnutLogicMixin
from ..data.game_item import Requirement
from ..data.requirement import ToolRequirement, BookRequirement, SkillRequirement, SeasonRequirement, YearRequirement, WalnutRequirement
from ..data.requirement import ToolRequirement, BookRequirement, SkillRequirement, SeasonRequirement, YearRequirement, CombatRequirement, QuestRequirement, \
RelationshipRequirement, FishingRequirement, WalnutRequirement
class RequirementLogicMixin(BaseLogicMixin):
@ -21,7 +26,7 @@ class RequirementLogicMixin(BaseLogicMixin):
class RequirementLogic(BaseLogic[Union[RequirementLogicMixin, HasLogicMixin, ReceivedLogicMixin, ToolLogicMixin, SkillLogicMixin, BookLogicMixin,
SeasonLogicMixin, TimeLogicMixin, WalnutLogicMixin]]):
SeasonLogicMixin, TimeLogicMixin, CombatLogicMixin, QuestLogicMixin, RelationshipLogicMixin, FishingLogicMixin, WalnutLogicMixin]]):
def meet_all_requirements(self, requirements: Iterable[Requirement]):
if not requirements:
@ -55,3 +60,21 @@ SeasonLogicMixin, TimeLogicMixin, WalnutLogicMixin]]):
@meet_requirement.register
def _(self, requirement: WalnutRequirement):
return self.logic.walnut.has_walnut(requirement.amount)
@meet_requirement.register
def _(self, requirement: CombatRequirement):
return self.logic.combat.can_fight_at_level(requirement.level)
@meet_requirement.register
def _(self, requirement: QuestRequirement):
return self.logic.quest.can_complete_quest(requirement.quest)
@meet_requirement.register
def _(self, requirement: RelationshipRequirement):
return self.logic.relationship.has_hearts(requirement.npc, requirement.hearts)
@meet_requirement.register
def _(self, requirement: FishingRequirement):
return self.logic.fishing.can_fish_at(requirement.region)

View File

@ -23,24 +23,15 @@ from ...logic.tool_logic import ToolLogicMixin
from ...options import Cropsanity
from ...stardew_rule import StardewRule, True_
from ...strings.artisan_good_names import ModArtisanGood
from ...strings.craftable_names import ModCraftable, ModEdible, ModMachine
from ...strings.crop_names import SVEVegetable, SVEFruit, DistantLandsCrop
from ...strings.fish_names import ModTrash, SVEFish
from ...strings.food_names import SVEMeal, SVEBeverage
from ...strings.forageable_names import SVEForage, DistantLandsForageable
from ...strings.gift_names import SVEGift
from ...strings.craftable_names import ModCraftable, ModMachine
from ...strings.fish_names import ModTrash
from ...strings.ingredient_names import Ingredient
from ...strings.material_names import Material
from ...strings.metal_names import all_fossils, all_artifacts, Ore, ModFossil
from ...strings.monster_drop_names import ModLoot, Loot
from ...strings.monster_drop_names import Loot
from ...strings.performance_names import Performance
from ...strings.quest_names import ModQuest
from ...strings.region_names import Region, SVERegion, DeepWoodsRegion, BoardingHouseRegion
from ...strings.season_names import Season
from ...strings.seed_names import SVESeed, DistantLandsSeed
from ...strings.skill_names import Skill
from ...strings.region_names import SVERegion, DeepWoodsRegion, BoardingHouseRegion
from ...strings.tool_names import Tool, ToolMaterial
from ...strings.villager_names import ModNPC
display_types = [ModCraftable.wooden_display, ModCraftable.hardwood_display]
display_items = all_artifacts + all_fossils
@ -58,12 +49,6 @@ FarmingLogicMixin]]):
def get_modded_item_rules(self) -> Dict[str, StardewRule]:
items = dict()
if ModNames.sve in self.options.mods:
items.update(self.get_sve_item_rules())
if ModNames.archaeology in self.options.mods:
items.update(self.get_archaeology_item_rules())
if ModNames.distant_lands in self.options.mods:
items.update(self.get_distant_lands_item_rules())
if ModNames.boarding_house in self.options.mods:
items.update(self.get_boarding_house_item_rules())
return items
@ -75,61 +60,6 @@ FarmingLogicMixin]]):
item_rule.update(self.get_modified_item_rules_for_deep_woods(item_rule))
return item_rule
def get_sve_item_rules(self):
return {SVEGift.aged_blue_moon_wine: self.logic.money.can_spend_at(SVERegion.sophias_house, 28000),
SVEGift.blue_moon_wine: self.logic.money.can_spend_at(SVERegion.sophias_house, 3000),
SVESeed.fungus: self.logic.region.can_reach(SVERegion.highlands_cavern) & self.logic.combat.has_good_weapon,
ModLoot.green_mushroom: self.logic.region.can_reach(SVERegion.highlands_outside) &
self.logic.tool.has_tool(Tool.axe, ToolMaterial.iron) & self.logic.season.has_any_not_winter(),
SVEFruit.monster_fruit: self.logic.season.has(Season.summer) & self.logic.has(SVESeed.stalk),
SVEVegetable.monster_mushroom: self.logic.season.has(Season.fall) & self.logic.has(SVESeed.fungus),
ModLoot.ornate_treasure_chest: self.logic.region.can_reach(SVERegion.highlands_outside) & self.logic.combat.has_galaxy_weapon &
self.logic.tool.has_tool(Tool.axe, ToolMaterial.iron),
SVEFruit.slime_berry: self.logic.season.has(Season.spring) & self.logic.has(SVESeed.slime),
SVESeed.slime: self.logic.region.can_reach(SVERegion.highlands_outside) & self.logic.combat.has_good_weapon,
SVESeed.stalk: self.logic.region.can_reach(SVERegion.highlands_outside) & self.logic.combat.has_good_weapon,
ModLoot.swirl_stone: self.logic.region.can_reach(SVERegion.crimson_badlands) & self.logic.combat.has_great_weapon,
SVEVegetable.void_root: self.logic.season.has(Season.winter) & self.logic.has(SVESeed.void),
SVESeed.void: self.logic.region.can_reach(SVERegion.highlands_cavern) & self.logic.combat.has_good_weapon,
ModLoot.void_soul: self.logic.region.can_reach(
SVERegion.crimson_badlands) & self.logic.combat.has_good_weapon & self.logic.cooking.can_cook(),
SVEForage.winter_star_rose: self.logic.region.can_reach(SVERegion.summit) & self.logic.season.has(Season.winter),
SVEForage.bearberry: self.logic.region.can_reach(Region.secret_woods) & self.logic.season.has(Season.winter),
SVEForage.poison_mushroom: self.logic.region.can_reach(Region.secret_woods) & self.logic.season.has_any([Season.summer, Season.fall]),
SVEForage.red_baneberry: self.logic.region.can_reach(Region.secret_woods) & self.logic.season.has(Season.summer),
SVEForage.ferngill_primrose: self.logic.region.can_reach(SVERegion.summit) & self.logic.season.has(Season.spring),
SVEForage.goldenrod: self.logic.region.can_reach(SVERegion.summit) & (
self.logic.season.has(Season.summer) | self.logic.season.has(Season.fall)),
SVESeed.shrub: self.logic.region.can_reach(Region.secret_woods) & self.logic.tool.has_tool(Tool.hoe, ToolMaterial.basic),
SVEFruit.salal_berry: self.logic.farming.can_plant_and_grow_item((Season.spring, Season.summer)) & self.logic.has(SVESeed.shrub),
ModEdible.aegis_elixir: self.logic.money.can_spend_at(SVERegion.galmoran_outpost, 28000),
ModEdible.lightning_elixir: self.logic.money.can_spend_at(SVERegion.galmoran_outpost, 12000),
ModEdible.barbarian_elixir: self.logic.money.can_spend_at(SVERegion.galmoran_outpost, 22000),
ModEdible.gravity_elixir: self.logic.money.can_spend_at(SVERegion.galmoran_outpost, 4000),
SVESeed.ancient_fern: self.logic.region.can_reach(Region.secret_woods) & self.logic.tool.has_tool(Tool.hoe, ToolMaterial.basic),
SVEVegetable.ancient_fiber: self.logic.farming.can_plant_and_grow_item(Season.summer) & self.logic.has(SVESeed.ancient_fern),
SVEForage.conch: self.logic.region.can_reach_any((Region.beach, SVERegion.fable_reef)),
SVEForage.dewdrop_berry: self.logic.region.can_reach(SVERegion.enchanted_grove),
SVEForage.sand_dollar: self.logic.region.can_reach(SVERegion.fable_reef) | (self.logic.region.can_reach(Region.beach) &
self.logic.season.has_any([Season.summer, Season.fall])),
SVEForage.golden_ocean_flower: self.logic.region.can_reach(SVERegion.fable_reef),
SVEMeal.grampleton_orange_chicken: self.logic.money.can_spend_at(Region.saloon, 650) & self.logic.relationship.has_hearts(ModNPC.sophia, 6),
ModEdible.hero_elixir: self.logic.money.can_spend_at(SVERegion.isaac_shop, 8000),
SVEForage.four_leaf_clover: self.logic.region.can_reach_any((Region.secret_woods, SVERegion.forest_west)) &
self.logic.season.has_any([Season.spring, Season.summer]),
SVEForage.mushroom_colony: self.logic.region.can_reach_any((Region.secret_woods, SVERegion.junimo_woods, SVERegion.forest_west)) &
self.logic.season.has(Season.fall),
SVEForage.rusty_blade: self.logic.region.can_reach(SVERegion.crimson_badlands) & self.logic.combat.has_great_weapon,
SVEForage.rafflesia: self.logic.region.can_reach(Region.secret_woods),
SVEBeverage.sports_drink: self.logic.money.can_spend_at(Region.hospital, 750),
"Stamina Capsule": self.logic.money.can_spend_at(Region.hospital, 4000),
SVEForage.thistle: self.logic.region.can_reach(SVERegion.summit),
ModLoot.void_pebble: self.logic.region.can_reach(SVERegion.crimson_badlands) & self.logic.combat.has_great_weapon,
ModLoot.void_shard: self.logic.region.can_reach(SVERegion.crimson_badlands) & self.logic.combat.has_galaxy_weapon &
self.logic.skill.has_level(Skill.combat, 10) & self.logic.region.can_reach(Region.saloon) & self.logic.time.has_year_three
}
# @formatter:on
def get_modified_item_rules_for_sve(self, items: Dict[str, StardewRule]):
return {
Loot.void_essence: items[Loot.void_essence] | self.logic.region.can_reach(SVERegion.highlands_cavern) | self.logic.region.can_reach(
@ -141,7 +71,7 @@ FarmingLogicMixin]]):
self.logic.combat.can_fight_at_level(Performance.great)),
Ore.iridium: items[Ore.iridium] | (self.logic.tool.can_use_tool_at(Tool.pickaxe, ToolMaterial.basic, SVERegion.crimson_badlands) &
self.logic.combat.can_fight_at_level(Performance.maximum)),
SVEFish.dulse_seaweed: self.logic.fishing.can_fish_at(Region.beach) & self.logic.season.has_any([Season.spring, Season.summer, Season.winter])
}
def get_modified_item_rules_for_deep_woods(self, items: Dict[str, StardewRule]):
@ -160,36 +90,6 @@ FarmingLogicMixin]]):
return options_to_update
def get_archaeology_item_rules(self):
archaeology_item_rules = {}
preservation_chamber_rule = self.logic.has(ModMachine.preservation_chamber)
hardwood_preservation_chamber_rule = self.logic.has(ModMachine.hardwood_preservation_chamber)
for item in display_items:
for display_type in display_types:
if item == "Trilobite":
location_name = f"{display_type}: Trilobite Fossil"
else:
location_name = f"{display_type}: {item}"
display_item_rule = self.logic.crafting.can_craft(all_crafting_recipes_by_name[display_type]) & self.logic.has(item)
if "Wooden" in display_type:
archaeology_item_rules[location_name] = display_item_rule & preservation_chamber_rule
else:
archaeology_item_rules[location_name] = display_item_rule & hardwood_preservation_chamber_rule
archaeology_item_rules[ModTrash.rusty_scrap] = self.logic.has(ModMachine.grinder) & self.logic.has_any(*all_artifacts)
return archaeology_item_rules
def get_distant_lands_item_rules(self):
return {
DistantLandsForageable.swamp_herb: self.logic.region.can_reach(Region.witch_swamp),
DistantLandsForageable.brown_amanita: self.logic.region.can_reach(Region.witch_swamp),
DistantLandsSeed.vile_ancient_fruit: self.logic.quest.can_complete_quest(ModQuest.WitchOrder) | self.logic.quest.can_complete_quest(
ModQuest.CorruptedCropsTask),
DistantLandsSeed.void_mint: self.logic.quest.can_complete_quest(ModQuest.WitchOrder) | self.logic.quest.can_complete_quest(
ModQuest.CorruptedCropsTask),
DistantLandsCrop.void_mint: self.logic.season.has_any_not_winter() & self.logic.has(DistantLandsSeed.void_mint),
DistantLandsCrop.vile_ancient_fruit: self.logic.season.has_any_not_winter() & self.logic.has(DistantLandsSeed.vile_ancient_fruit),
}
def get_boarding_house_item_rules(self):
return {
# Mob Drops from lost valley enemies
@ -251,8 +151,3 @@ FarmingLogicMixin]]):
BoardingHouseRegion.lost_valley_house_2,)) & self.logic.combat.can_fight_at_level(
Performance.great),
}
def has_seed_unlocked(self, seed_name: str):
if self.options.cropsanity == Cropsanity.option_disabled:
return True_()
return self.logic.received(seed_name)

View File

@ -183,7 +183,8 @@ stardew_valley_expanded_regions = [
RegionData(SVERegion.first_slash_guild, [SVEEntrance.first_slash_guild_to_hallway], is_ginger_island=True),
RegionData(SVERegion.first_slash_hallway, [SVEEntrance.first_slash_hallway_to_room], is_ginger_island=True),
RegionData(SVERegion.first_slash_spare_room, is_ginger_island=True),
RegionData(SVERegion.highlands_outside, [SVEEntrance.highlands_to_lance, SVEEntrance.highlands_to_cave], is_ginger_island=True),
RegionData(SVERegion.highlands_outside, [SVEEntrance.highlands_to_lance, SVEEntrance.highlands_to_cave, SVEEntrance.highlands_to_pond], is_ginger_island=True),
RegionData(SVERegion.highlands_pond, is_ginger_island=True),
RegionData(SVERegion.highlands_cavern, [SVEEntrance.to_dwarf_prison], is_ginger_island=True),
RegionData(SVERegion.dwarf_prison, is_ginger_island=True),
RegionData(SVERegion.lances_house, [SVEEntrance.lance_to_ladder], is_ginger_island=True),
@ -276,6 +277,7 @@ mandatory_sve_connections = [
ConnectionData(SVEEntrance.sprite_spring_to_cave, SVERegion.sprite_spring_cave, flag=RandomizationFlag.BUILDINGS),
ConnectionData(SVEEntrance.fish_shop_to_willy_bedroom, SVERegion.willy_bedroom, flag=RandomizationFlag.BUILDINGS),
ConnectionData(SVEEntrance.museum_to_gunther_bedroom, SVERegion.gunther_bedroom, flag=RandomizationFlag.BUILDINGS),
ConnectionData(SVEEntrance.highlands_to_pond, SVERegion.highlands_pond),
]
alecto_regions = [

View File

@ -1031,6 +1031,7 @@ def set_sve_ginger_island_rules(logic: StardewLogic, multiworld: MultiWorld, pla
set_entrance_rule(multiworld, player, SVEEntrance.wizard_to_fable_reef, logic.received(SVEQuestItem.fable_reef_portal))
set_entrance_rule(multiworld, player, SVEEntrance.highlands_to_cave,
logic.tool.has_tool(Tool.pickaxe, ToolMaterial.iron) & logic.tool.has_tool(Tool.axe, ToolMaterial.iron))
set_entrance_rule(multiworld, player, SVEEntrance.highlands_to_pond, logic.tool.has_tool(Tool.axe, ToolMaterial.iron))
def set_boarding_house_rules(logic: StardewLogic, multiworld: MultiWorld, player: int, world_options: StardewValleyOptions):

View File

@ -27,10 +27,6 @@ class Book:
the_diamond_hunter = "The Diamond Hunter"
class ModBook:
digging_like_worms = "Digging Like Worms"
ordered_lost_books = []
all_lost_books = set()

View File

@ -358,6 +358,7 @@ class SVEEntrance:
sprite_spring_to_cave = "Sprite Spring to Sprite Spring Cave"
fish_shop_to_willy_bedroom = "Willy's Fish Shop to Willy's Bedroom"
museum_to_gunther_bedroom = "Museum to Gunther's Bedroom"
highlands_to_pond = "Highlands to Highlands Pond"
class AlectoEntrance:

View File

@ -137,7 +137,6 @@ class SVEFish:
void_eel = "Void Eel"
water_grub = "Water Grub"
sea_sponge = "Sea Sponge"
dulse_seaweed = "Dulse Seaweed"
class DistantLandsFish:
@ -147,6 +146,10 @@ class DistantLandsFish:
giant_horsehoe_crab = "Giant Horsehoe Crab"
class SVEWaterItem:
dulse_seaweed = "Dulse Seaweed"
class ModTrash:
rusty_scrap = "Scrap Rust"

View File

@ -102,6 +102,7 @@ class SVEMeal:
void_delight = "Void Delight"
void_salmon_sushi = "Void Salmon Sushi"
grampleton_orange_chicken = "Grampleton Orange Chicken"
stamina_capsule = "Stamina Capsule"
class TrashyMeal:

View File

@ -296,6 +296,7 @@ class SVERegion:
sprite_spring_cave = "Sprite Spring Cave"
willy_bedroom = "Willy's Bedroom"
gunther_bedroom = "Gunther's Bedroom"
highlands_pond = "Highlands Pond"
class AlectoRegion:

View File

@ -14,7 +14,8 @@ class TestGenerateModsOptions(WorldAssertMixin, ModAssertMixin, SVTestCase):
def test_given_single_mods_when_generate_then_basic_checks(self):
for mod in options.Mods.valid_keys:
with self.solo_world_sub_test(f"Mod: {mod}", {options.Mods: mod}) as (multi_world, _):
world_options = {options.Mods: mod, options.ExcludeGingerIsland: options.ExcludeGingerIsland.option_false}
with self.solo_world_sub_test(f"Mod: {mod}", world_options) as (multi_world, _):
self.assert_basic_checks(multi_world)
self.assert_stray_mod_items(mod, multi_world)
@ -22,8 +23,9 @@ class TestGenerateModsOptions(WorldAssertMixin, ModAssertMixin, SVTestCase):
for option in options.EntranceRandomization.options:
for mod in options.Mods.valid_keys:
world_options = {
options.EntranceRandomization.internal_name: options.EntranceRandomization.options[option],
options.Mods: mod
options.EntranceRandomization: options.EntranceRandomization.options[option],
options.Mods: mod,
options.ExcludeGingerIsland: options.ExcludeGingerIsland.option_false
}
with self.solo_world_sub_test(f"entrance_randomization: {option}, Mod: {mod}", world_options) as (multi_world, _):
self.assert_basic_checks(multi_world)