mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Stardew Valley: 4.x.x - The Ginger Update (#1931)
## What is this fixing or adding? Major content update for Stardew Valley ## How was this tested? One large-scale public Beta on the archipelago server, plus several smaller private asyncs and test runs You can go to https://github.com/agilbert1412/StardewArchipelago/releases to grab the mod (latest 4.x.x version), the supported mods and the apworld, to test this PR ## New Features: - Festival Checks [Easy mode or Hard Mode] - Special Orders [Both Board and Qi] - Willy's Boat - Ginger Island Parrots - TV Channels - Trap Items [Available in various difficulty levels] - Entrance Randomizer: Buildings and Chaos - New Fishsanity options: Exclude Legendaries, Exclude Hard fish, Only easy fish - Resource Pack overhaul [Resource packs are now more enjoyable and varied] - Goal: Greatest Walnut Hunter [Find every single Golden Walnut] - Goal: Perfection [Achieve Perfection] - Option: Profit Margin [Multiplier over all earnings] - Option: Friendsanity Heart Size [Reduce clutter from friendsanity hearts] - Option: Exclude Ginger Island - will exclude many locations and items to generate a playthrough that does not go to the island - Mod Support [Curated list of mods] ## New Contributors: @Witchybun for the mod support --------- Co-authored-by: Witchybun <embenham05@gmail.com> Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> Co-authored-by: Fabian Dill <Berserker66@users.noreply.github.com>
This commit is contained in:
@@ -5,85 +5,59 @@ from BaseClasses import MultiWorld
|
||||
from worlds.generic import Rules as MultiWorldRules
|
||||
from . import options, locations
|
||||
from .bundles import Bundle
|
||||
from .data.crops_data import crops_by_name
|
||||
from .strings.entrance_names import dig_to_mines_floor, dig_to_skull_floor, Entrance, move_to_woods_depth, \
|
||||
DeepWoodsEntrance, AlecEntrance, MagicEntrance
|
||||
from .data.museum_data import all_museum_items, all_mineral_items, all_artifact_items, \
|
||||
dwarf_scrolls, skeleton_front, \
|
||||
skeleton_middle, skeleton_back, all_museum_items_by_name
|
||||
from .strings.region_names import Region
|
||||
from .mods.mod_data import ModNames
|
||||
from .mods.logic import magic, skills, deepwoods
|
||||
from .locations import LocationTags
|
||||
from .logic import StardewLogic, And, month_end_per_skill_level, tool_prices, week_days
|
||||
from .logic import StardewLogic, And, tool_upgrade_prices
|
||||
from .options import StardewOptions
|
||||
from .strings.ap_names.transport_names import Transportation
|
||||
from .strings.artisan_good_names import ArtisanGood
|
||||
from .strings.calendar_names import Weekday
|
||||
from .strings.craftable_names import Craftable
|
||||
from .strings.material_names import Material
|
||||
from .strings.metal_names import MetalBar
|
||||
from .strings.spells import MagicSpell
|
||||
from .strings.skill_names import ModSkill, Skill
|
||||
from .strings.tool_names import Tool, ToolMaterial
|
||||
from .strings.villager_names import NPC, ModNPC
|
||||
from .strings.wallet_item_names import Wallet
|
||||
|
||||
|
||||
def set_rules(multi_world: MultiWorld, player: int, world_options: StardewOptions, logic: StardewLogic,
|
||||
current_bundles: Dict[str, Bundle]):
|
||||
all_location_names = list(location.name for location in multi_world.get_locations(player))
|
||||
|
||||
for floor in range(5, 120 + 5, 5):
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(f"Dig to The Mines - Floor {floor}", player),
|
||||
logic.can_mine_to_floor(floor).simplify())
|
||||
set_entrance_rules(logic, multi_world, player, world_options)
|
||||
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Enter Tide Pools", player),
|
||||
logic.received("Beach Bridge").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Enter Quarry", player),
|
||||
logic.received("Bridge Repair").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Enter Secret Woods", player),
|
||||
logic.has_tool("Axe", "Iron").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Forest to Sewers", player),
|
||||
logic.has_rusty_key().simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Town to Sewers", player),
|
||||
logic.has_rusty_key().simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Take Bus to Desert", player),
|
||||
logic.received("Bus Repair").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Enter Skull Cavern", player),
|
||||
logic.received("Skull Key").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Mine to Skull Cavern Floor 100", player),
|
||||
logic.can_mine_perfectly_in_the_skull_cavern().simplify())
|
||||
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Use Desert Obelisk", player),
|
||||
logic.received("Desert Obelisk").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Use Island Obelisk", player),
|
||||
logic.received("Island Obelisk").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Talk to Traveling Merchant", player),
|
||||
logic.has_traveling_merchant())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance("Enter Greenhouse", player),
|
||||
logic.received("Greenhouse"))
|
||||
set_ginger_island_rules(logic, multi_world, player, world_options)
|
||||
|
||||
# Those checks do not exist if ToolProgression is vanilla
|
||||
if world_options[options.ToolProgression] != options.ToolProgression.option_vanilla:
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Purchase Fiberglass Rod", player),
|
||||
(logic.has_skill_level("Fishing", 2) & logic.can_spend_money(1800)).simplify())
|
||||
(logic.has_skill_level(Skill.fishing, 2) & logic.can_spend_money(1800)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Purchase Iridium Rod", player),
|
||||
(logic.has_skill_level("Fishing", 6) & logic.can_spend_money(7500)).simplify())
|
||||
(logic.has_skill_level(Skill.fishing, 6) & logic.can_spend_money(7500)).simplify())
|
||||
|
||||
materials = [None, "Copper", "Iron", "Gold", "Iridium"]
|
||||
tool = ["Hoe", "Pickaxe", "Axe", "Watering Can", "Trash Can"]
|
||||
tool = [Tool.hoe, Tool.pickaxe, Tool.axe, Tool.watering_can, Tool.watering_can, Tool.trash_can]
|
||||
for (previous, material), tool in itertools.product(zip(materials[:4], materials[1:]), tool):
|
||||
if previous is None:
|
||||
MultiWorldRules.add_rule(multi_world.get_location(f"{material} {tool} Upgrade", player),
|
||||
(logic.has(f"{material} Ore") &
|
||||
logic.can_spend_money(tool_prices[material])).simplify())
|
||||
logic.can_spend_money(tool_upgrade_prices[material])).simplify())
|
||||
else:
|
||||
MultiWorldRules.add_rule(multi_world.get_location(f"{material} {tool} Upgrade", player),
|
||||
(logic.has(f"{material} Ore") & logic.has_tool(tool, previous) &
|
||||
logic.can_spend_money(tool_prices[material])).simplify())
|
||||
logic.can_spend_money(tool_upgrade_prices[material])).simplify())
|
||||
|
||||
# Skills
|
||||
if world_options[options.SkillProgression] != options.SkillProgression.option_vanilla:
|
||||
for i in range(1, 11):
|
||||
MultiWorldRules.set_rule(multi_world.get_location(f"Level {i} Farming", player),
|
||||
(logic.received("Month End", month_end_per_skill_level["Farming", i])).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_location(f"Level {i} Fishing", player),
|
||||
(logic.can_get_fishing_xp() &
|
||||
logic.received("Month End", month_end_per_skill_level["Fishing", i])).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location(f"Level {i} Foraging", player),
|
||||
logic.received("Month End", month_end_per_skill_level["Foraging", i]).simplify())
|
||||
if i >= 6:
|
||||
MultiWorldRules.add_rule(multi_world.get_location(f"Level {i} Foraging", player),
|
||||
logic.has_tool("Axe", "Iron").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_location(f"Level {i} Mining", player),
|
||||
logic.received("Month End", month_end_per_skill_level["Mining", i]).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_location(f"Level {i} Combat", player),
|
||||
(logic.received("Month End", month_end_per_skill_level["Combat", i]) &
|
||||
logic.has_any_weapon()).simplify())
|
||||
set_skills_rules(logic, multi_world, player, world_options)
|
||||
|
||||
# Bundles
|
||||
for bundle in current_bundles.values():
|
||||
@@ -114,46 +88,294 @@ def set_rules(multi_world: MultiWorld, player: int, world_options: StardewOption
|
||||
# Buildings
|
||||
if world_options[options.BuildingProgression] != options.BuildingProgression.option_vanilla:
|
||||
for building in locations.locations_by_tag[LocationTags.BUILDING_BLUEPRINT]:
|
||||
if building.mod_name is not None and building.mod_name not in world_options[options.Mods]:
|
||||
continue
|
||||
MultiWorldRules.set_rule(multi_world.get_location(building.name, player),
|
||||
logic.building_rules[building.name.replace(" Blueprint", "")].simplify())
|
||||
|
||||
# Story Quests
|
||||
for quest in locations.locations_by_tag[LocationTags.QUEST]:
|
||||
MultiWorldRules.set_rule(multi_world.get_location(quest.name, player),
|
||||
logic.quest_rules[quest.name].simplify())
|
||||
|
||||
# Help Wanted Quests
|
||||
desired_number_help_wanted: int = world_options[options.HelpWantedLocations] // 7
|
||||
for i in range(0, desired_number_help_wanted):
|
||||
prefix = "Help Wanted:"
|
||||
delivery = "Item Delivery"
|
||||
rule = logic.received("Month End", i)
|
||||
fishing_rule = rule & logic.can_fish()
|
||||
slay_rule = rule & logic.has_any_weapon()
|
||||
item_delivery_index = (i * 4) + 1
|
||||
for j in range(item_delivery_index, item_delivery_index + 4):
|
||||
location_name = f"{prefix} {delivery} {j}"
|
||||
MultiWorldRules.set_rule(multi_world.get_location(location_name, player), rule.simplify())
|
||||
|
||||
MultiWorldRules.set_rule(multi_world.get_location(f"{prefix} Gathering {i+1}", player),
|
||||
rule.simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_location(f"{prefix} Fishing {i+1}", player),
|
||||
fishing_rule.simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_location(f"{prefix} Slay Monsters {i+1}", player),
|
||||
slay_rule.simplify())
|
||||
|
||||
set_cropsanity_rules(all_location_names, logic, multi_world, player, world_options)
|
||||
set_story_quests_rules(all_location_names, logic, multi_world, player, world_options)
|
||||
set_special_order_rules(all_location_names, logic, multi_world, player, world_options)
|
||||
set_help_wanted_quests_rules(logic, multi_world, player, world_options)
|
||||
set_fishsanity_rules(all_location_names, logic, multi_world, player)
|
||||
set_museumsanity_rules(all_location_names, logic, multi_world, player, world_options)
|
||||
set_friendsanity_rules(all_location_names, logic, multi_world, player)
|
||||
set_backpack_rules(logic, multi_world, player, world_options)
|
||||
set_festival_rules(all_location_names, logic, multi_world, player)
|
||||
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Old Master Cannoli", player),
|
||||
logic.has("Sweet Gem Berry").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Galaxy Sword Shrine", player),
|
||||
logic.has("Prismatic Shard").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Have a Baby", player),
|
||||
logic.can_reproduce(1).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Have Another Baby", player),
|
||||
logic.can_reproduce(2).simplify())
|
||||
|
||||
set_traveling_merchant_rules(logic, multi_world, player)
|
||||
set_arcade_machine_rules(logic, multi_world, player, world_options)
|
||||
set_deepwoods_rules(logic, multi_world, player, world_options)
|
||||
set_magic_spell_rules(logic, multi_world, player, world_options)
|
||||
|
||||
|
||||
def set_skills_rules(logic, multi_world, player, world_options):
|
||||
# Skills
|
||||
if world_options[options.SkillProgression] != options.SkillProgression.option_vanilla:
|
||||
for i in range(1, 11):
|
||||
set_skill_rule(logic, multi_world, player, Skill.farming, i)
|
||||
set_skill_rule(logic, multi_world, player, Skill.fishing, i)
|
||||
set_skill_rule(logic, multi_world, player, Skill.foraging, i)
|
||||
set_skill_rule(logic, multi_world, player, Skill.mining, i)
|
||||
set_skill_rule(logic, multi_world, player, Skill.combat, i)
|
||||
|
||||
# Modded Skills
|
||||
if ModNames.luck_skill in world_options[options.Mods]:
|
||||
set_skill_rule(logic, multi_world, player, ModSkill.luck, i)
|
||||
if ModNames.magic in world_options[options.Mods]:
|
||||
set_skill_rule(logic, multi_world, player, ModSkill.magic, i)
|
||||
if ModNames.binning_skill in world_options[options.Mods]:
|
||||
set_skill_rule(logic, multi_world, player, ModSkill.binning, i)
|
||||
if ModNames.cooking_skill in world_options[options.Mods]:
|
||||
set_skill_rule(logic, multi_world, player, ModSkill.cooking, i)
|
||||
if ModNames.socializing_skill in world_options[options.Mods]:
|
||||
set_skill_rule(logic, multi_world, player, ModSkill.socializing, i)
|
||||
if ModNames.archaeology in world_options[options.Mods]:
|
||||
set_skill_rule(logic, multi_world, player, ModSkill.archaeology, i)
|
||||
|
||||
|
||||
def set_skill_rule(logic, multi_world, player, skill: str, level: int):
|
||||
location_name = f"Level {level} {skill}"
|
||||
location = multi_world.get_location(location_name, player)
|
||||
rule = logic.can_earn_skill_level(skill, level).simplify()
|
||||
MultiWorldRules.set_rule(location, rule)
|
||||
|
||||
|
||||
def set_entrance_rules(logic, multi_world, player, world_options: StardewOptions):
|
||||
for floor in range(5, 120 + 5, 5):
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(dig_to_mines_floor(floor), player),
|
||||
logic.can_mine_to_floor(floor).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_tide_pools, player),
|
||||
logic.received("Beach Bridge") | (magic.can_blink(logic)).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_quarry, player),
|
||||
logic.received("Bridge Repair") | (magic.can_blink(logic)).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_secret_woods, player),
|
||||
logic.has_tool(Tool.axe, "Iron") | (magic.can_blink(logic)).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.forest_to_sewer, player),
|
||||
logic.has_rusty_key().simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.town_to_sewer, player),
|
||||
logic.has_rusty_key().simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.take_bus_to_desert, player),
|
||||
logic.received("Bus Repair").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_skull_cavern, player),
|
||||
logic.received(Wallet.skull_key).simplify())
|
||||
for floor in range(25, 200 + 25, 25):
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(dig_to_skull_floor(floor), player),
|
||||
logic.can_mine_to_skull_cavern_floor(floor).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.talk_to_mines_dwarf, player),
|
||||
logic.can_speak_dwarf() & logic.has_tool(Tool.pickaxe, ToolMaterial.iron))
|
||||
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.use_desert_obelisk, player),
|
||||
logic.received(Transportation.desert_obelisk).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.use_island_obelisk, player),
|
||||
logic.received(Transportation.island_obelisk).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.use_farm_obelisk, player),
|
||||
logic.received(Transportation.farm_obelisk).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.buy_from_traveling_merchant, player),
|
||||
logic.has_traveling_merchant())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_greenhouse, player),
|
||||
logic.received("Greenhouse"))
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.mountain_to_adventurer_guild, player),
|
||||
logic.received("Adventurer's Guild"))
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.mountain_to_railroad, player),
|
||||
logic.has_lived_months(2))
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_witch_warp_cave, player),
|
||||
logic.received(Wallet.dark_talisman) | (magic.can_blink(logic)).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_witch_hut, player),
|
||||
(logic.has(ArtisanGood.void_mayonnaise) | magic.can_blink(logic)).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_mutant_bug_lair, player),
|
||||
((logic.has_rusty_key() & logic.can_reach_region(Region.railroad) &
|
||||
logic.can_meet(NPC.krobus) | magic.can_blink(logic)).simplify()))
|
||||
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_harvey_room, player),
|
||||
logic.has_relationship(NPC.harvey, 2))
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.mountain_to_maru_room, player),
|
||||
logic.has_relationship(NPC.maru, 2))
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_sebastian_room, player),
|
||||
(logic.has_relationship(NPC.sebastian, 2) | magic.can_blink(logic)).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.forest_to_leah_cottage, player),
|
||||
logic.has_relationship(NPC.leah, 2))
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_elliott_house, player),
|
||||
logic.has_relationship(NPC.elliott, 2))
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_sunroom, player),
|
||||
logic.has_relationship(NPC.caroline, 2))
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.enter_wizard_basement, player),
|
||||
logic.has_relationship(NPC.wizard, 4))
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.mountain_to_leo_treehouse, player),
|
||||
logic.has_relationship(NPC.leo, 6) & logic.can_reach_region(Region.island_south))
|
||||
if ModNames.alec in world_options[options.Mods]:
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(AlecEntrance.petshop_to_bedroom, player),
|
||||
(logic.has_relationship(ModNPC.alec, 2) | magic.can_blink(logic)).simplify())
|
||||
|
||||
|
||||
def set_ginger_island_rules(logic: StardewLogic, multi_world, player, world_options: StardewOptions):
|
||||
set_island_entrances_rules(logic, multi_world, player)
|
||||
if world_options[options.ExcludeGingerIsland] == options.ExcludeGingerIsland.option_true:
|
||||
return
|
||||
|
||||
set_boat_repair_rules(logic, multi_world, player)
|
||||
set_island_parrot_rules(logic, multi_world, player)
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Open Professor Snail Cave", player),
|
||||
logic.has(Craftable.cherry_bomb).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Complete Island Field Office", player),
|
||||
logic.can_complete_field_office().simplify())
|
||||
|
||||
|
||||
def set_boat_repair_rules(logic: StardewLogic, multi_world, player):
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Repair Boat Hull", player),
|
||||
logic.has(Material.hardwood).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Repair Boat Anchor", player),
|
||||
logic.has(MetalBar.iridium).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Repair Ticket Machine", player),
|
||||
logic.has(ArtisanGood.battery_pack).simplify())
|
||||
|
||||
|
||||
def set_island_entrances_rules(logic: StardewLogic, multi_world, player):
|
||||
boat_repaired = logic.received(Transportation.boat_repair).simplify()
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.fish_shop_to_boat_tunnel, player),
|
||||
boat_repaired)
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.boat_to_ginger_island, player),
|
||||
boat_repaired)
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.island_south_to_west, player),
|
||||
logic.received("Island West Turtle").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.island_south_to_north, player),
|
||||
logic.received("Island North Turtle").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.island_west_to_islandfarmhouse, player),
|
||||
logic.received("Island Farmhouse").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.island_west_to_gourmand_cave, player),
|
||||
logic.received("Island Farmhouse").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.island_north_to_dig_site, player),
|
||||
logic.received("Dig Site Bridge").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.dig_site_to_professor_snail_cave, player),
|
||||
logic.received("Open Professor Snail Cave").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.talk_to_island_trader, player),
|
||||
logic.received("Island Trader").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.island_south_to_southeast, player),
|
||||
logic.received("Island Resort").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.use_island_resort, player),
|
||||
logic.received("Island Resort").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.island_west_to_qi_walnut_room, player),
|
||||
logic.received("Qi Walnut Room").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.island_north_to_volcano, player),
|
||||
(logic.can_water(0) | logic.received("Volcano Bridge") |
|
||||
magic.can_blink(logic)).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.volcano_to_secret_beach, player),
|
||||
logic.can_water(2).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.climb_to_volcano_5, player),
|
||||
(logic.can_mine_perfectly() & logic.can_water(1)).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.talk_to_volcano_dwarf, player),
|
||||
logic.can_speak_dwarf())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(Entrance.climb_to_volcano_10, player),
|
||||
(logic.can_mine_perfectly() & logic.can_water(1) & logic.received("Volcano Exit Shortcut")).simplify())
|
||||
parrots = [Entrance.parrot_express_docks_to_volcano, Entrance.parrot_express_jungle_to_volcano,
|
||||
Entrance.parrot_express_dig_site_to_volcano, Entrance.parrot_express_docks_to_dig_site,
|
||||
Entrance.parrot_express_jungle_to_dig_site, Entrance.parrot_express_volcano_to_dig_site,
|
||||
Entrance.parrot_express_docks_to_jungle, Entrance.parrot_express_dig_site_to_jungle,
|
||||
Entrance.parrot_express_volcano_to_jungle, Entrance.parrot_express_jungle_to_docks,
|
||||
Entrance.parrot_express_dig_site_to_docks, Entrance.parrot_express_volcano_to_docks]
|
||||
for parrot in parrots:
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(parrot, player), logic.received(Transportation.parrot_express).simplify())
|
||||
|
||||
|
||||
def set_island_parrot_rules(logic: StardewLogic, multi_world, player):
|
||||
has_walnut = logic.has_walnut(1).simplify()
|
||||
has_5_walnut = logic.has_walnut(5).simplify()
|
||||
has_10_walnut = logic.has_walnut(10).simplify()
|
||||
has_20_walnut = logic.has_walnut(20).simplify()
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Leo's Parrot", player),
|
||||
has_walnut)
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Island West Turtle", player),
|
||||
has_10_walnut & logic.received("Island North Turtle"))
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Island Farmhouse", player),
|
||||
has_20_walnut)
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Island Mailbox", player),
|
||||
has_5_walnut & logic.received("Island Farmhouse"))
|
||||
MultiWorldRules.add_rule(multi_world.get_location(Transportation.farm_obelisk, player),
|
||||
has_20_walnut & logic.received("Island Mailbox"))
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Dig Site Bridge", player),
|
||||
has_10_walnut & logic.received("Island West Turtle"))
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Island Trader", player),
|
||||
has_10_walnut & logic.received("Island Farmhouse"))
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Volcano Bridge", player),
|
||||
has_5_walnut & logic.received("Island West Turtle") &
|
||||
logic.can_reach_region(Region.volcano_floor_10))
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Volcano Exit Shortcut", player),
|
||||
has_5_walnut & logic.received("Island West Turtle"))
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Island Resort", player),
|
||||
has_20_walnut & logic.received("Island Farmhouse"))
|
||||
MultiWorldRules.add_rule(multi_world.get_location(Transportation.parrot_express, player),
|
||||
has_10_walnut)
|
||||
|
||||
|
||||
def set_cropsanity_rules(all_location_names: List[str], logic, multi_world, player, world_options: StardewOptions):
|
||||
if world_options[options.Cropsanity] == options.Cropsanity.option_disabled:
|
||||
return
|
||||
|
||||
harvest_prefix = "Harvest "
|
||||
harvest_prefix_length = len(harvest_prefix)
|
||||
for harvest_location in locations.locations_by_tag[LocationTags.CROPSANITY]:
|
||||
if harvest_location.name in all_location_names and (harvest_location.mod_name is None or harvest_location.mod_name in world_options[options.Mods]):
|
||||
crop_name = harvest_location.name[harvest_prefix_length:]
|
||||
MultiWorldRules.set_rule(multi_world.get_location(harvest_location.name, player),
|
||||
logic.has(crop_name).simplify())
|
||||
|
||||
|
||||
def set_story_quests_rules(all_location_names: List[str], logic, multi_world, player, world_options: StardewOptions):
|
||||
for quest in locations.locations_by_tag[LocationTags.QUEST]:
|
||||
if quest.name in all_location_names and (quest.mod_name is None or quest.mod_name in world_options[options.Mods]):
|
||||
MultiWorldRules.set_rule(multi_world.get_location(quest.name, player),
|
||||
logic.quest_rules[quest.name].simplify())
|
||||
|
||||
|
||||
def set_special_order_rules(all_location_names: List[str], logic: StardewLogic, multi_world, player,
|
||||
world_options: StardewOptions):
|
||||
if world_options[options.SpecialOrderLocations] == options.SpecialOrderLocations.option_disabled:
|
||||
return
|
||||
board_rule = logic.received("Special Order Board") & logic.has_lived_months(4)
|
||||
for board_order in locations.locations_by_tag[LocationTags.SPECIAL_ORDER_BOARD]:
|
||||
if board_order.name in all_location_names:
|
||||
order_rule = board_rule & logic.special_order_rules[board_order.name]
|
||||
MultiWorldRules.set_rule(multi_world.get_location(board_order.name, player), order_rule.simplify())
|
||||
|
||||
if world_options[options.ExcludeGingerIsland] == options.ExcludeGingerIsland.option_true:
|
||||
return
|
||||
if world_options[options.SpecialOrderLocations] == options.SpecialOrderLocations.option_board_only:
|
||||
return
|
||||
qi_rule = logic.can_reach_region(Region.qi_walnut_room) & logic.has_lived_months(8)
|
||||
for qi_order in locations.locations_by_tag[LocationTags.SPECIAL_ORDER_QI]:
|
||||
if qi_order.name in all_location_names:
|
||||
order_rule = qi_rule & logic.special_order_rules[qi_order.name]
|
||||
MultiWorldRules.set_rule(multi_world.get_location(qi_order.name, player), order_rule.simplify())
|
||||
|
||||
|
||||
def set_help_wanted_quests_rules(logic: StardewLogic, multi_world, player, world_options):
|
||||
desired_number_help_wanted: int = world_options[options.HelpWantedLocations] // 7
|
||||
for i in range(0, desired_number_help_wanted):
|
||||
prefix = "Help Wanted:"
|
||||
delivery = "Item Delivery"
|
||||
rule = logic.has_lived_months(i).simplify()
|
||||
fishing_rule = rule & logic.can_fish()
|
||||
slay_rule = rule & logic.can_do_combat_at_level("Basic")
|
||||
item_delivery_index = (i * 4) + 1
|
||||
for j in range(item_delivery_index, item_delivery_index + 4):
|
||||
location_name = f"{prefix} {delivery} {j}"
|
||||
MultiWorldRules.set_rule(multi_world.get_location(location_name, player), rule)
|
||||
|
||||
MultiWorldRules.set_rule(multi_world.get_location(f"{prefix} Gathering {i + 1}", player),
|
||||
rule)
|
||||
MultiWorldRules.set_rule(multi_world.get_location(f"{prefix} Fishing {i + 1}", player),
|
||||
fishing_rule.simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_location(f"{prefix} Slay Monsters {i + 1}", player),
|
||||
slay_rule.simplify())
|
||||
|
||||
|
||||
def set_fishsanity_rules(all_location_names: List[str], logic: StardewLogic, multi_world: MultiWorld, player: int):
|
||||
@@ -175,7 +397,7 @@ def set_museumsanity_rules(all_location_names: List[str], logic: StardewLogic, m
|
||||
set_museum_individual_donations_rules(all_location_names, logic, multi_world, museum_prefix, player)
|
||||
|
||||
|
||||
def set_museum_individual_donations_rules(all_location_names, logic, multi_world, museum_prefix, player):
|
||||
def set_museum_individual_donations_rules(all_location_names, logic: StardewLogic, multi_world, museum_prefix, player):
|
||||
all_donations = sorted(locations.locations_by_tag[LocationTags.MUSEUM_DONATIONS],
|
||||
key=lambda x: all_museum_items_by_name[x.name[len(museum_prefix):]].difficulty, reverse=True)
|
||||
counter = 0
|
||||
@@ -219,7 +441,7 @@ def set_museum_milestone_rule(logic: StardewLogic, multi_world: MultiWorld, muse
|
||||
MultiWorldRules.set_rule(multi_world.get_location(museum_milestone.name, player), rule.simplify())
|
||||
|
||||
|
||||
def get_museum_item_count_rule(logic, suffix, milestone_name, accepted_items):
|
||||
def get_museum_item_count_rule(logic: StardewLogic, suffix, milestone_name, accepted_items):
|
||||
metal_detector = "Traveling Merchant Metal Detector"
|
||||
num = int(milestone_name[:milestone_name.index(suffix)])
|
||||
required_detectors = (num - 1) * 5 // len(accepted_items)
|
||||
@@ -233,10 +455,24 @@ def set_backpack_rules(logic: StardewLogic, multi_world: MultiWorld, player: int
|
||||
logic.can_spend_money(2000).simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_location("Deluxe Pack", player),
|
||||
(logic.can_spend_money(10000) & logic.received("Progressive Backpack")).simplify())
|
||||
if ModNames.big_backpack in world_options[options.Mods]:
|
||||
MultiWorldRules.set_rule(multi_world.get_location("Premium Pack", player),
|
||||
(logic.can_spend_money(150000) &
|
||||
logic.received("Progressive Backpack", 2)).simplify())
|
||||
|
||||
|
||||
def set_festival_rules(all_location_names: List[str], logic: StardewLogic, multi_world, player):
|
||||
festival_locations = []
|
||||
festival_locations.extend(locations.locations_by_tag[LocationTags.FESTIVAL])
|
||||
festival_locations.extend(locations.locations_by_tag[LocationTags.FESTIVAL_HARD])
|
||||
for festival in festival_locations:
|
||||
if festival.name in all_location_names:
|
||||
MultiWorldRules.set_rule(multi_world.get_location(festival.name, player),
|
||||
logic.festival_rules[festival.name].simplify())
|
||||
|
||||
|
||||
def set_traveling_merchant_rules(logic: StardewLogic, multi_world: MultiWorld, player: int):
|
||||
for day in week_days:
|
||||
for day in Weekday.all_days:
|
||||
item_for_day = f"Traveling Merchant: {day}"
|
||||
for i in range(1, 4):
|
||||
location_name = f"Traveling Merchant {day} Item {i}"
|
||||
@@ -245,23 +481,27 @@ def set_traveling_merchant_rules(logic: StardewLogic, multi_world: MultiWorld, p
|
||||
|
||||
|
||||
def set_arcade_machine_rules(logic: StardewLogic, multi_world: MultiWorld, player: int, world_options):
|
||||
if world_options[options.ArcadeMachineLocations] == options.ArcadeMachineLocations.option_full_shuffling:
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance("Play Junimo Kart", player),
|
||||
(logic.received("Skull Key") & logic.has("Junimo Kart Small Buff")).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance("Reach Junimo Kart 2", player),
|
||||
logic.has("Junimo Kart Medium Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance("Reach Junimo Kart 3", player),
|
||||
logic.has("Junimo Kart Big Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Junimo Kart: Sunset Speedway (Victory)", player),
|
||||
logic.has("Junimo Kart Max Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance("Play Journey of the Prairie King", player),
|
||||
logic.has("JotPK Small Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance("Reach JotPK World 2", player),
|
||||
logic.has("JotPK Medium Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance("Reach JotPK World 3", player),
|
||||
logic.has("JotPK Big Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Journey of the Prairie King Victory", player),
|
||||
logic.has("JotPK Max Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance(Entrance.play_junimo_kart, player),
|
||||
logic.received(Wallet.skull_key).simplify())
|
||||
if world_options[options.ArcadeMachineLocations] != options.ArcadeMachineLocations.option_full_shuffling:
|
||||
return
|
||||
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance(Entrance.play_junimo_kart, player),
|
||||
logic.has("Junimo Kart Small Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance(Entrance.reach_junimo_kart_2, player),
|
||||
logic.has("Junimo Kart Medium Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance(Entrance.reach_junimo_kart_3, player),
|
||||
logic.has("Junimo Kart Big Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Junimo Kart: Sunset Speedway (Victory)", player),
|
||||
logic.has("Junimo Kart Max Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance(Entrance.play_journey_of_the_prairie_king, player),
|
||||
logic.has("JotPK Small Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance(Entrance.reach_jotpk_world_2, player),
|
||||
logic.has("JotPK Medium Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_entrance(Entrance.reach_jotpk_world_3, player),
|
||||
logic.has("JotPK Big Buff").simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Journey of the Prairie King Victory", player),
|
||||
logic.has("JotPK Max Buff").simplify())
|
||||
|
||||
|
||||
def set_friendsanity_rules(all_location_names: List[str], logic: StardewLogic, multi_world: MultiWorld, player: int):
|
||||
@@ -272,8 +512,93 @@ def set_friendsanity_rules(all_location_names: List[str], logic: StardewLogic, m
|
||||
continue
|
||||
friend_location_without_prefix = friend_location.name[len(friend_prefix):]
|
||||
friend_location_trimmed = friend_location_without_prefix[:friend_location_without_prefix.index(friend_suffix)]
|
||||
parts = friend_location_trimmed.split(" ")
|
||||
friend_name = parts[0]
|
||||
num_hearts = int(parts[1])
|
||||
split_index = friend_location_trimmed.rindex(" ")
|
||||
friend_name = friend_location_trimmed[:split_index]
|
||||
num_hearts = int(friend_location_trimmed[split_index + 1:])
|
||||
MultiWorldRules.set_rule(multi_world.get_location(friend_location.name, player),
|
||||
logic.can_earn_relationship(friend_name, num_hearts).simplify())
|
||||
|
||||
|
||||
def set_deepwoods_rules(logic: StardewLogic, multi_world: MultiWorld, player: int, world_options: StardewOptions):
|
||||
if ModNames.deepwoods in world_options[options.Mods]:
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Breaking Up Deep Woods Gingerbread House", player),
|
||||
logic.has_tool(Tool.axe, "Gold") & deepwoods.can_reach_woods_depth(logic, 50).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Chop Down a Deep Woods Iridium Tree", player),
|
||||
logic.has_tool(Tool.axe, "Iridium").simplify())
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(DeepWoodsEntrance.use_woods_obelisk, player),
|
||||
logic.received("Woods Obelisk").simplify())
|
||||
for depth in range(10, 100 + 10, 10):
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(move_to_woods_depth(depth), player),
|
||||
deepwoods.can_chop_to_depth(logic, depth).simplify())
|
||||
|
||||
|
||||
def set_magic_spell_rules(logic: StardewLogic, multi_world: MultiWorld, player: int, world_options: StardewOptions):
|
||||
if ModNames.magic not in world_options[options.Mods]:
|
||||
return
|
||||
|
||||
MultiWorldRules.set_rule(multi_world.get_entrance(MagicEntrance.store_to_altar, player),
|
||||
(logic.has_relationship(NPC.wizard, 3) &
|
||||
logic.can_reach_region(Region.wizard_tower)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Clear Debris", player),
|
||||
((logic.has_tool("Axe", "Basic") | logic.has_tool("Pickaxe", "Basic"))
|
||||
& magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Till", player),
|
||||
(logic.has_tool("Hoe", "Basic") & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Water", player),
|
||||
(logic.has_tool("Watering Can", "Basic") & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze All Toil School Locations", player),
|
||||
(logic.has_tool("Watering Can", "Basic") & logic.has_tool("Hoe", "Basic")
|
||||
& (logic.has_tool("Axe", "Basic") | logic.has_tool("Pickaxe", "Basic"))
|
||||
& magic.can_use_altar(logic)).simplify())
|
||||
# Do I *want* to add boots into logic when you get them even in vanilla without effort? idk
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Evac", player),
|
||||
(logic.can_mine_perfectly() & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Haste", player),
|
||||
(logic.has("Coffee") & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Heal", player),
|
||||
(logic.has("Life Elixir") & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze All Life School Locations", player),
|
||||
(logic.has("Coffee") & logic.has("Life Elixir")
|
||||
& logic.can_mine_perfectly() & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Descend", player),
|
||||
(logic.can_reach_region(Region.mines) & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Fireball", player),
|
||||
(logic.has("Fire Quartz") & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Frostbite", player),
|
||||
(logic.can_mine_to_floor(70) & logic.can_fish(85) & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze All Elemental School Locations", player),
|
||||
(logic.can_reach_region(Region.mines) & logic.has("Fire Quartz")
|
||||
& logic.can_reach_region(Region.mines_floor_70) & logic.can_fish(85) &
|
||||
magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Lantern", player),
|
||||
magic.can_use_altar(logic).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Tendrils", player),
|
||||
(logic.can_reach_region(Region.farm) & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Shockwave", player),
|
||||
(logic.has("Earth Crystal") & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze All Nature School Locations", player),
|
||||
(logic.has("Earth Crystal") & logic.can_reach_region("Farm") &
|
||||
magic.can_use_altar(logic)).simplify()),
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Meteor", player),
|
||||
(logic.can_reach_region(Region.farm) & logic.has_lived_months(12)
|
||||
& magic.can_use_altar(logic)).simplify()),
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Lucksteal", player),
|
||||
(logic.can_reach_region(Region.witch_hut) & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze: Bloodmana", player),
|
||||
(logic.can_reach_region(Region.mines_floor_100) & magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze All Eldritch School Locations", player),
|
||||
(logic.can_reach_region(Region.witch_hut) &
|
||||
logic.can_reach_region(Region.mines_floor_100) &
|
||||
logic.can_reach_region(Region.farm) & logic.has_lived_months(12) &
|
||||
magic.can_use_altar(logic)).simplify())
|
||||
MultiWorldRules.add_rule(multi_world.get_location("Analyze Every Magic School Location", player),
|
||||
(logic.has_tool("Watering Can", "Basic") & logic.has_tool("Hoe", "Basic")
|
||||
& (logic.has_tool("Axe", "Basic") | logic.has_tool("Pickaxe", "Basic")) &
|
||||
logic.has("Coffee") & logic.has("Life Elixir")
|
||||
& logic.can_mine_perfectly() & logic.has("Earth Crystal") &
|
||||
logic.can_reach_region(Region.mines) &
|
||||
logic.has("Fire Quartz") & logic.can_fish(85) &
|
||||
logic.can_reach_region(Region.witch_hut) &
|
||||
logic.can_reach_region(Region.mines_floor_100) &
|
||||
logic.can_reach_region(Region.farm) & logic.has_lived_months(12) &
|
||||
magic.can_use_altar(logic)).simplify())
|
||||
|
||||
Reference in New Issue
Block a user