mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 12:11:33 -06:00
Stardew valley: Fix Aurora Vineyard Tablet logic (#4512)
* - Add requirement on Aurora Vineyard tablet to start the quest * - Add rule for using the aurora vineyard staircase * - Added a test for the tablet * - Add a few missing items to the test * - Introduce a new item to split the quest from the door and avoir ER issues * - Optimize imports * - Forgot to generate the item * fix Aurora mess # Conflicts: # worlds/stardew_valley/rules.py # worlds/stardew_valley/test/mods/TestMods.py * fix a couple errors in the cherry picked commit, added a method to improve readability and reduce chance of human error on story quest conditions * - remove blank line * - Code review comments * - fixed weird assert name * - fixed accidentally surviving line * - Fixed imports --------- Co-authored-by: Jouramie <16137441+Jouramie@users.noreply.github.com>
This commit is contained in:
@@ -928,6 +928,7 @@ id,name,classification,groups,mod_name
|
||||
10518,Aurora Vineyard Tablet,progression,,Stardew Valley Expanded
|
||||
10519,Scarlett's Job Offer,progression,,Stardew Valley Expanded
|
||||
10520,Morgan's Schooling,progression,,Stardew Valley Expanded
|
||||
10521,Aurora Vineyard Reclamation,progression,,Stardew Valley Expanded
|
||||
10601,Magic Elixir Recipe,progression,"CHEFSANITY,CHEFSANITY_PURCHASE",Magic
|
||||
10602,Travel Core Recipe,progression,CRAFTSANITY,Magic
|
||||
10603,Haste Elixir Recipe,progression,CRAFTSANITY,Stardew Valley Expanded
|
||||
|
|
@@ -41,7 +41,7 @@ def setup_early_items(multiworld, options: stardew_options.StardewValleyOptions,
|
||||
if fishing is not None and content.features.skill_progression.is_progressive:
|
||||
early_forced.append(fishing.level_name)
|
||||
|
||||
if options.quest_locations >= 0:
|
||||
if options.quest_locations.has_story_quests():
|
||||
early_candidates.append(Wallet.magnifying_glass)
|
||||
|
||||
if options.special_order_locations & stardew_options.SpecialOrderLocations.option_board:
|
||||
|
@@ -264,7 +264,7 @@ def create_unique_items(item_factory: StardewItemFactory, options: StardewValley
|
||||
|
||||
def create_raccoons(item_factory: StardewItemFactory, options: StardewValleyOptions, items: List[Item]):
|
||||
number_progressive_raccoons = 9
|
||||
if options.quest_locations < 0:
|
||||
if options.quest_locations.has_no_story_quests():
|
||||
number_progressive_raccoons = number_progressive_raccoons - 1
|
||||
|
||||
items.extend(item_factory(item) for item in [CommunityUpgrade.raccoon] * number_progressive_raccoons)
|
||||
@@ -387,7 +387,7 @@ def create_quest_rewards(item_factory: StardewItemFactory, options: StardewValle
|
||||
|
||||
|
||||
def create_special_quest_rewards(item_factory: StardewItemFactory, options: StardewValleyOptions, items: List[Item]):
|
||||
if options.quest_locations < 0:
|
||||
if options.quest_locations.has_no_story_quests():
|
||||
return
|
||||
# items.append(item_factory("Adventurer's Guild")) # Now unlocked always!
|
||||
items.append(item_factory(Wallet.club_card))
|
||||
@@ -698,7 +698,7 @@ def create_quest_rewards_sve(item_factory: StardewItemFactory, options: StardewV
|
||||
if not exclude_ginger_island:
|
||||
items.extend([item_factory(item) for item in SVEQuestItem.sve_always_quest_items_ginger_island])
|
||||
|
||||
if options.quest_locations < 0:
|
||||
if options.quest_locations.has_no_story_quests():
|
||||
return
|
||||
|
||||
items.extend([item_factory(item) for item in SVEQuestItem.sve_quest_items])
|
||||
|
@@ -191,7 +191,7 @@ def extend_cropsanity_locations(randomized_locations: List[LocationData], conten
|
||||
|
||||
|
||||
def extend_quests_locations(randomized_locations: List[LocationData], options: StardewValleyOptions, content: StardewContent):
|
||||
if options.quest_locations < 0:
|
||||
if options.quest_locations.has_no_story_quests():
|
||||
return
|
||||
|
||||
story_quest_locations = locations_by_tag[LocationTags.STORY_QUEST]
|
||||
@@ -317,7 +317,7 @@ def extend_mandatory_locations(randomized_locations: List[LocationData], options
|
||||
|
||||
|
||||
def extend_situational_quest_locations(randomized_locations: List[LocationData], options: StardewValleyOptions):
|
||||
if options.quest_locations < 0:
|
||||
if options.quest_locations.has_no_story_quests():
|
||||
return
|
||||
if ModNames.distant_lands in options.mods:
|
||||
if ModNames.alecto in options.mods:
|
||||
|
@@ -76,7 +76,7 @@ SkillLogicMixin, QuestLogicMixin]]):
|
||||
self.logic.region.can_reach_location("Complete Boiler Room"))
|
||||
|
||||
def can_access_raccoon_bundles(self) -> StardewRule:
|
||||
if self.options.quest_locations < 0:
|
||||
if self.options.quest_locations.has_no_story_quests():
|
||||
return self.logic.received(CommunityUpgrade.raccoon, 1) & self.logic.quest.can_complete_quest(Quest.giant_stump)
|
||||
|
||||
# 1 - Break the tree
|
||||
|
@@ -48,7 +48,7 @@ SkillLogicMixin, SpecialOrderLogicMixin, CraftingLogicMixin, QuestLogicMixin]]):
|
||||
else:
|
||||
return self.logic.crafting.received_recipe(recipe.item)
|
||||
if isinstance(recipe.source, QuestSource):
|
||||
if self.options.quest_locations < 0:
|
||||
if self.options.quest_locations.has_no_story_quests():
|
||||
return self.logic.crafting.can_learn_recipe(recipe)
|
||||
else:
|
||||
return self.logic.crafting.received_recipe(recipe.item)
|
||||
|
@@ -118,25 +118,24 @@ class QuestLogic(BaseLogic[Union[HasLogicMixin, ReceivedLogicMixin, MoneyLogicMi
|
||||
return Has(quest, self.registry.quest_rules, "quest")
|
||||
|
||||
def has_club_card(self) -> StardewRule:
|
||||
if self.options.quest_locations < 0:
|
||||
return self.logic.quest.can_complete_quest(Quest.the_mysterious_qi)
|
||||
return self.logic.received(Wallet.club_card)
|
||||
if self.options.quest_locations.has_story_quests():
|
||||
return self.logic.received(Wallet.club_card)
|
||||
return self.logic.quest.can_complete_quest(Quest.the_mysterious_qi)
|
||||
|
||||
def has_magnifying_glass(self) -> StardewRule:
|
||||
if self.options.quest_locations < 0:
|
||||
return self.logic.quest.can_complete_quest(Quest.a_winter_mystery)
|
||||
return self.logic.received(Wallet.magnifying_glass)
|
||||
if self.options.quest_locations.has_story_quests():
|
||||
return self.logic.received(Wallet.magnifying_glass)
|
||||
return self.logic.quest.can_complete_quest(Quest.a_winter_mystery)
|
||||
|
||||
def has_dark_talisman(self) -> StardewRule:
|
||||
if self.options.quest_locations < 0:
|
||||
return self.logic.quest.can_complete_quest(Quest.dark_talisman)
|
||||
return self.logic.received(Wallet.dark_talisman)
|
||||
if self.options.quest_locations.has_story_quests():
|
||||
return self.logic.received(Wallet.dark_talisman)
|
||||
return self.logic.quest.can_complete_quest(Quest.dark_talisman)
|
||||
|
||||
def has_raccoon_shop(self) -> StardewRule:
|
||||
if self.options.quest_locations < 0:
|
||||
return self.logic.received(CommunityUpgrade.raccoon, 2) & self.logic.quest.can_complete_quest(Quest.giant_stump)
|
||||
|
||||
# 1 - Break the tree
|
||||
# 2 - Build the house, which summons the bundle racoon. This one is done manually if quests are turned off
|
||||
# 3 - Raccoon's wife opens the shop
|
||||
return self.logic.received(CommunityUpgrade.raccoon, 3)
|
||||
if self.options.quest_locations.has_story_quests():
|
||||
# 1 - Break the tree
|
||||
# 2 - Build the house, which summons the bundle racoon. This one is done manually if quests are turned off
|
||||
# 3 - Raccoon's wife opens the shop
|
||||
return self.logic.received(CommunityUpgrade.raccoon, 3)
|
||||
return self.logic.received(CommunityUpgrade.raccoon, 2) & self.logic.quest.can_complete_quest(Quest.giant_stump)
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import math
|
||||
import typing
|
||||
from typing import Union
|
||||
|
||||
from Utils import cache_self1
|
||||
@@ -14,13 +15,18 @@ from ..content.feature import friendsanity
|
||||
from ..data.villagers_data import Villager
|
||||
from ..stardew_rule import StardewRule, True_, false_, true_
|
||||
from ..strings.ap_names.mods.mod_items import SVEQuestItem
|
||||
from ..strings.crop_names import Fruit
|
||||
from ..strings.generic_names import Generic
|
||||
from ..strings.gift_names import Gift
|
||||
from ..strings.quest_names import ModQuest
|
||||
from ..strings.region_names import Region
|
||||
from ..strings.season_names import Season
|
||||
from ..strings.villager_names import NPC, ModNPC
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from ..mods.logic.mod_logic import ModLogicMixin
|
||||
else:
|
||||
ModLogicMixin = object
|
||||
|
||||
possible_kids = ("Cute Baby", "Ugly Baby")
|
||||
|
||||
|
||||
@@ -38,7 +44,7 @@ class RelationshipLogicMixin(BaseLogicMixin):
|
||||
|
||||
|
||||
class RelationshipLogic(BaseLogic[Union[RelationshipLogicMixin, BuildingLogicMixin, SeasonLogicMixin, TimeLogicMixin, GiftLogicMixin, RegionLogicMixin,
|
||||
ReceivedLogicMixin, HasLogicMixin]]):
|
||||
ReceivedLogicMixin, HasLogicMixin, ModLogicMixin]]):
|
||||
|
||||
def can_date(self, npc: str) -> StardewRule:
|
||||
return self.logic.relationship.has_hearts(npc, 8) & self.logic.has(Gift.bouquet)
|
||||
@@ -141,7 +147,7 @@ ReceivedLogicMixin, HasLogicMixin]]):
|
||||
rules.append(self.logic.region.can_reach(Region.volcano_floor_10))
|
||||
|
||||
elif npc == ModNPC.apples:
|
||||
rules.append(self.logic.has(Fruit.starfruit))
|
||||
rules.append(self.logic.mod.quest.has_completed_aurora_vineyard_bundle())
|
||||
|
||||
elif npc == ModNPC.scarlett:
|
||||
scarlett_job = self.logic.received(SVEQuestItem.scarlett_job_offer)
|
||||
|
@@ -12,6 +12,7 @@ from ...logic.season_logic import SeasonLogicMixin
|
||||
from ...logic.time_logic import TimeLogicMixin
|
||||
from ...stardew_rule import StardewRule
|
||||
from ...strings.animal_product_names import AnimalProduct
|
||||
from ...strings.ap_names.mods.mod_items import SVEQuestItem
|
||||
from ...strings.artisan_good_names import ArtisanGood
|
||||
from ...strings.crop_names import Fruit, SVEFruit, SVEVegetable, Vegetable
|
||||
from ...strings.fertilizer_names import Fertilizer
|
||||
@@ -83,7 +84,8 @@ TimeLogicMixin, SeasonLogicMixin, RelationshipLogicMixin, MonsterLogicMixin]]):
|
||||
self.logic.region.can_reach(SVERegion.grandpas_shed),
|
||||
ModQuest.MarlonsBoat: self.logic.has_all(*(Loot.void_essence, Loot.solar_essence, Loot.slime, Loot.bat_wing, Loot.bug_meat)) &
|
||||
self.logic.relationship.can_meet(ModNPC.lance) & self.logic.region.can_reach(SVERegion.guild_summit),
|
||||
ModQuest.AuroraVineyard: self.logic.has(Fruit.starfruit) & self.logic.region.can_reach(SVERegion.aurora_vineyard),
|
||||
ModQuest.AuroraVineyard: self.logic.region.can_reach(SVERegion.aurora_vineyard) & self.logic.received(SVEQuestItem.aurora_vineyard_tablet) &
|
||||
self.logic.has(Fruit.starfruit) & self.logic.region.can_reach(Region.forest),
|
||||
ModQuest.MonsterCrops: self.logic.has_all(*(SVEVegetable.monster_mushroom, SVEFruit.slime_berry, SVEFruit.monster_fruit, SVEVegetable.void_root)),
|
||||
ModQuest.VoidSoul: self.logic.has(ModLoot.void_soul) & self.logic.region.can_reach(Region.farm) &
|
||||
self.logic.season.has_any_not_winter() & self.logic.region.can_reach(SVERegion.badlands_entrance) &
|
||||
@@ -91,6 +93,12 @@ TimeLogicMixin, SeasonLogicMixin, RelationshipLogicMixin, MonsterLogicMixin]]):
|
||||
self.logic.monster.can_kill_any((Monster.shadow_brute, Monster.shadow_shaman, Monster.shadow_sniper)),
|
||||
}
|
||||
|
||||
def has_completed_aurora_vineyard_bundle(self):
|
||||
if self.options.quest_locations.has_story_quests():
|
||||
return self.logic.received(SVEQuestItem.aurora_vineyard_reclamation)
|
||||
return self.logic.quest.can_complete_quest(ModQuest.AuroraVineyard)
|
||||
|
||||
|
||||
def _get_distant_lands_quest_rules(self):
|
||||
if ModNames.distant_lands not in self.options.mods:
|
||||
return {}
|
||||
|
@@ -41,24 +41,24 @@ class SVELogic(BaseLogic[Union[HasLogicMixin, ReceivedLogicMixin, QuestLogicMixi
|
||||
return self.logic.or_(*(self.logic.received(rune) for rune in rune_list))
|
||||
|
||||
def has_iridium_bomb(self):
|
||||
if self.options.quest_locations < 0:
|
||||
return self.logic.quest.can_complete_quest(ModQuest.RailroadBoulder)
|
||||
return self.logic.received(SVEQuestItem.iridium_bomb)
|
||||
if self.options.quest_locations.has_story_quests():
|
||||
return self.logic.received(SVEQuestItem.iridium_bomb)
|
||||
return self.logic.quest.can_complete_quest(ModQuest.RailroadBoulder)
|
||||
|
||||
def has_marlon_boat(self):
|
||||
if self.options.quest_locations < 0:
|
||||
return self.logic.quest.can_complete_quest(ModQuest.MarlonsBoat)
|
||||
return self.logic.received(SVEQuestItem.marlon_boat_paddle)
|
||||
if self.options.quest_locations.has_story_quests():
|
||||
return self.logic.received(SVEQuestItem.marlon_boat_paddle)
|
||||
return self.logic.quest.can_complete_quest(ModQuest.MarlonsBoat)
|
||||
|
||||
def has_grandpa_shed_repaired(self):
|
||||
if self.options.quest_locations < 0:
|
||||
return self.logic.quest.can_complete_quest(ModQuest.GrandpasShed)
|
||||
return self.logic.received(SVEQuestItem.grandpa_shed)
|
||||
if self.options.quest_locations.has_story_quests():
|
||||
return self.logic.received(SVEQuestItem.grandpa_shed)
|
||||
return self.logic.quest.can_complete_quest(ModQuest.GrandpasShed)
|
||||
|
||||
def has_bear_knowledge(self):
|
||||
if self.options.quest_locations < 0:
|
||||
return self.logic.quest.can_complete_quest(Quest.strange_note)
|
||||
return self.logic.received(Wallet.bears_knowledge)
|
||||
if self.options.quest_locations.has_story_quests():
|
||||
return self.logic.received(Wallet.bears_knowledge)
|
||||
return self.logic.quest.can_complete_quest(Quest.strange_note)
|
||||
|
||||
def can_buy_bear_recipe(self):
|
||||
access_rule = (self.logic.quest.can_complete_quest(Quest.strange_note) & self.logic.tool.has_tool(Tool.axe, ToolMaterial.basic) &
|
||||
|
@@ -384,6 +384,12 @@ class QuestLocations(NamedRange):
|
||||
"maximum": 56,
|
||||
}
|
||||
|
||||
def has_story_quests(self) -> bool:
|
||||
return self.value >= 0
|
||||
|
||||
def has_no_story_quests(self) -> bool:
|
||||
return not self.has_story_quests()
|
||||
|
||||
|
||||
class Fishsanity(Choice):
|
||||
"""Locations for catching each fish the first time?
|
||||
|
@@ -149,7 +149,7 @@ def set_bundle_rules(bundle_rooms: List[BundleRoom], logic: StardewLogic, multiw
|
||||
bundle_rules = logic.bundle.can_complete_bundle(bundle)
|
||||
if bundle_room.name == CCRoom.raccoon_requests:
|
||||
num = int(bundle.name[-1])
|
||||
extra_raccoons = 1 if world_options.quest_locations >= 0 else 0
|
||||
extra_raccoons = 1 if world_options.quest_locations.has_story_quests() else 0
|
||||
extra_raccoons = extra_raccoons + num
|
||||
bundle_rules = logic.received(CommunityUpgrade.raccoon, extra_raccoons) & bundle_rules
|
||||
if num > 1:
|
||||
@@ -505,7 +505,7 @@ def set_cropsanity_rules(logic: StardewLogic, multiworld, player, world_content:
|
||||
|
||||
|
||||
def set_story_quests_rules(all_location_names: Set[str], logic: StardewLogic, multiworld, player, world_options: StardewValleyOptions):
|
||||
if world_options.quest_locations < 0:
|
||||
if world_options.quest_locations.has_no_story_quests():
|
||||
return
|
||||
for quest in locations.locations_by_tag[LocationTags.STORY_QUEST]:
|
||||
if quest.name in all_location_names and (quest.mod_name is None or quest.mod_name in world_options.mods):
|
||||
@@ -540,9 +540,9 @@ slay_monsters = "Slay Monsters"
|
||||
|
||||
|
||||
def set_help_wanted_quests_rules(logic: StardewLogic, multiworld, player, world_options: StardewValleyOptions):
|
||||
help_wanted_number = world_options.quest_locations.value
|
||||
if help_wanted_number < 0:
|
||||
if world_options.quest_locations.has_no_story_quests():
|
||||
return
|
||||
help_wanted_number = world_options.quest_locations.value
|
||||
for i in range(0, help_wanted_number):
|
||||
set_number = i // 7
|
||||
month_rule = logic.time.has_lived_months(set_number)
|
||||
@@ -973,6 +973,7 @@ def set_sve_rules(logic: StardewLogic, multiworld: MultiWorld, player: int, worl
|
||||
set_entrance_rule(multiworld, player, SVEEntrance.use_bear_shop, (logic.mod.sve.can_buy_bear_recipe()))
|
||||
set_entrance_rule(multiworld, player, SVEEntrance.railroad_to_grampleton_station, logic.received(SVEQuestItem.scarlett_job_offer))
|
||||
set_entrance_rule(multiworld, player, SVEEntrance.museum_to_gunther_bedroom, logic.relationship.has_hearts(ModNPC.gunther, 2))
|
||||
set_entrance_rule(multiworld, player, SVEEntrance.to_aurora_basement, logic.mod.quest.has_completed_aurora_vineyard_bundle())
|
||||
logic.mod.sve.initialize_rules()
|
||||
for location in logic.registry.sve_location_rules:
|
||||
MultiWorldRules.set_rule(multiworld.get_location(location, player),
|
||||
|
@@ -19,6 +19,12 @@ class SkillLevel:
|
||||
|
||||
class SVEQuestItem:
|
||||
aurora_vineyard_tablet = "Aurora Vineyard Tablet"
|
||||
"""Triggers the apparition of the bundle tablet in the Aurora Vineyard, so you can do the Aurora Vineyard quest.
|
||||
This aim to break dependencies on completing the Community Center.
|
||||
"""
|
||||
aurora_vineyard_reclamation = "Aurora Vineyard Reclamation"
|
||||
"""Triggers the unlock of the Aurora Vineyard basement, so you can meet Apples.
|
||||
"""
|
||||
iridium_bomb = "Iridium Bomb"
|
||||
void_soul = "Void Spirit Peace Agreement"
|
||||
kittyfish_spell = "Kittyfish Spell"
|
||||
@@ -29,10 +35,10 @@ class SVEQuestItem:
|
||||
fable_reef_portal = "Fable Reef Portal"
|
||||
grandpa_shed = "Grandpa's Shed"
|
||||
|
||||
sve_always_quest_items: List[str] = [kittyfish_spell, scarlett_job_offer, morgan_schooling]
|
||||
sve_always_quest_items_ginger_island: List[str] = [fable_reef_portal]
|
||||
sve_quest_items: List[str] = [aurora_vineyard_tablet, iridium_bomb, void_soul, grandpa_shed]
|
||||
sve_quest_items_ginger_island: List[str] = [marlon_boat_paddle]
|
||||
sve_always_quest_items: list[str] = [kittyfish_spell, scarlett_job_offer, morgan_schooling, aurora_vineyard_tablet, ]
|
||||
sve_always_quest_items_ginger_island: list[str] = [fable_reef_portal, ]
|
||||
sve_quest_items: list[str] = [iridium_bomb, void_soul, grandpa_shed, aurora_vineyard_reclamation, ]
|
||||
sve_quest_items_ginger_island: list[str] = [marlon_boat_paddle, ]
|
||||
|
||||
|
||||
class SVELocation:
|
||||
@@ -53,4 +59,3 @@ class SVERunes:
|
||||
nexus_wizard = "Nexus: Wizard Runes"
|
||||
|
||||
nexus_items: List[str] = [nexus_farm, nexus_wizard, nexus_spring, nexus_aurora, nexus_guild, nexus_junimo, nexus_outpost]
|
||||
|
||||
|
@@ -1,10 +1,9 @@
|
||||
import random
|
||||
|
||||
from BaseClasses import get_seed
|
||||
from BaseClasses import get_seed, ItemClassification
|
||||
from .. import SVTestBase, SVTestCase, allsanity_mods_6_x_x, fill_dataclass_with_default
|
||||
from ..assertion import ModAssertMixin, WorldAssertMixin
|
||||
from ... import items, Group, ItemClassification, create_content
|
||||
from ... import options
|
||||
from ... import options, items, Group, create_content
|
||||
from ...mods.mod_data import ModNames
|
||||
from ...options import SkillProgression, Walnutsanity
|
||||
from ...options.options import all_mods
|
||||
@@ -188,3 +187,17 @@ class TestModEntranceRando(SVTestCase):
|
||||
|
||||
self.assertEqual(len(set(randomized_connections.values())), len(randomized_connections.values()),
|
||||
f"Connections are duplicated in randomization.")
|
||||
|
||||
|
||||
class TestVanillaLogicAlternativeWhenQuestsAreNotRandomized(WorldAssertMixin, SVTestBase):
|
||||
"""We often forget to add an alternative rule that works when quests are not randomized. When this happens, some
|
||||
Location are not reachable because they depend on items that are only added to the pool when quests are randomized.
|
||||
"""
|
||||
options = allsanity_mods_6_x_x() | {
|
||||
options.QuestLocations.internal_name: options.QuestLocations.special_range_names["none"],
|
||||
options.Goal.internal_name: options.Goal.option_perfection,
|
||||
}
|
||||
|
||||
def test_given_no_quest_all_mods_when_generate_then_can_reach_everything(self):
|
||||
self.collect_everything()
|
||||
self.assert_can_reach_everything(self.multiworld)
|
||||
|
29
worlds/stardew_valley/test/mods/TestSVE.py
Normal file
29
worlds/stardew_valley/test/mods/TestSVE.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from .. import SVTestBase
|
||||
from ... import options
|
||||
from ...mods.mod_data import ModNames
|
||||
from ...strings.ap_names.mods.mod_items import SVEQuestItem
|
||||
from ...strings.quest_names import ModQuest
|
||||
from ...strings.region_names import SVERegion
|
||||
|
||||
|
||||
class TestAuroraVineyard(SVTestBase):
|
||||
options = {
|
||||
options.Cropsanity.internal_name: options.Cropsanity.option_enabled,
|
||||
options.Mods.internal_name: frozenset({ModNames.sve})
|
||||
}
|
||||
|
||||
def test_need_tablet_to_do_quest(self):
|
||||
self.collect("Starfruit Seeds")
|
||||
self.collect("Bus Repair")
|
||||
self.collect("Shipping Bin")
|
||||
self.collect("Summer")
|
||||
location_name = ModQuest.AuroraVineyard
|
||||
self.assert_cannot_reach_location(location_name, self.multiworld.state)
|
||||
self.collect(SVEQuestItem.aurora_vineyard_tablet)
|
||||
self.assert_can_reach_location(location_name, self.multiworld.state)
|
||||
|
||||
def test_need_reclamation_to_go_downstairs(self):
|
||||
region_name = SVERegion.aurora_vineyard_basement
|
||||
self.assert_cannot_reach_region(region_name, self.multiworld.state)
|
||||
self.collect(SVEQuestItem.aurora_vineyard_reclamation, 1)
|
||||
self.assert_can_reach_region(region_name, self.multiworld.state)
|
Reference in New Issue
Block a user