mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00

This adds the requirement of a void mayo for the Goblin Problem quest. There are also some small adjustments to related rules - Fishing a void mayo is only considered an option during the Goblin Problem quest, as the odds of finding one after the quest drops drastically. - Entrance to the witch hut now requires the goblin problem quest, not just a void mayo. - Fishing rules are all moved to `fishing_logic.py`. - `can_fish_at` no longer check that you have any of the fishing regions and the region you actually want to fish in. - created `can_fish_anywhere` and `can_crab_pot_anywhere` to better illustrate when any fish satisfies the rule.
167 lines
7.8 KiB
Python
167 lines
7.8 KiB
Python
from .base_logic import BaseLogic, BaseLogicMixin
|
|
from ..data.craftable_data import all_crafting_recipes_by_name
|
|
from ..data.recipe_data import all_cooking_recipes_by_name
|
|
from ..locations import LocationTags, locations_by_tag
|
|
from ..mods.mod_data import ModNames
|
|
from ..options import options
|
|
from ..stardew_rule import StardewRule
|
|
from ..strings.building_names import Building
|
|
from ..strings.quest_names import Quest
|
|
from ..strings.season_names import Season
|
|
from ..strings.wallet_item_names import Wallet
|
|
|
|
|
|
class GoalLogicMixin(BaseLogicMixin):
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.goal = GoalLogic(*args, **kwargs)
|
|
|
|
|
|
class GoalLogic(BaseLogic):
|
|
|
|
def can_complete_community_center(self) -> StardewRule:
|
|
return self.logic.bundle.can_complete_community_center
|
|
|
|
def can_finish_grandpa_evaluation(self) -> StardewRule:
|
|
# https://stardewvalleywiki.com/Grandpa
|
|
rules_worth_a_point = [
|
|
self.logic.money.can_have_earned_total(50_000),
|
|
self.logic.money.can_have_earned_total(100_000),
|
|
self.logic.money.can_have_earned_total(200_000),
|
|
self.logic.money.can_have_earned_total(300_000),
|
|
self.logic.money.can_have_earned_total(500_000),
|
|
self.logic.money.can_have_earned_total(1_000_000), # first point
|
|
self.logic.money.can_have_earned_total(1_000_000), # second point
|
|
self.logic.skill.has_total_level(30),
|
|
self.logic.skill.has_total_level(50),
|
|
self.logic.museum.can_complete_museum(),
|
|
# Catching every fish not expected
|
|
# Shipping every item not expected
|
|
self.logic.relationship.can_get_married() & self.logic.building.has_building(Building.kids_room),
|
|
self.logic.relationship.has_hearts_with_n(5, 8), # 5 Friends
|
|
self.logic.relationship.has_hearts_with_n(10, 8), # 10 friends
|
|
self.logic.pet.has_pet_hearts(5), # Max Pet
|
|
self.logic.bundle.can_complete_community_center, # 1 point for Community Center Completion
|
|
self.logic.bundle.can_complete_community_center, # Ceremony first point
|
|
self.logic.bundle.can_complete_community_center, # Ceremony second point
|
|
self.logic.received(Wallet.skull_key),
|
|
self.logic.wallet.has_rusty_key(),
|
|
]
|
|
return self.logic.count(12, *rules_worth_a_point)
|
|
|
|
def can_complete_bottom_of_the_mines(self) -> StardewRule:
|
|
# The location is in the bottom of the mines region, so no actual rule is required
|
|
return self.logic.true_
|
|
|
|
def can_complete_cryptic_note(self) -> StardewRule:
|
|
return self.logic.quest.can_complete_quest(Quest.cryptic_note)
|
|
|
|
def can_complete_master_angler(self) -> StardewRule:
|
|
if not self.content.features.fishsanity.is_enabled:
|
|
return self.logic.fishing.can_catch_every_fish()
|
|
|
|
rules = [self.logic.fishing.has_max_fishing]
|
|
|
|
rules.extend(
|
|
self.logic.fishing.can_catch_fish_for_fishsanity(fish)
|
|
for fish in self.content.fishes.values()
|
|
if self.content.features.fishsanity.is_included(fish)
|
|
)
|
|
|
|
return self.logic.and_(*rules)
|
|
|
|
def can_complete_complete_collection(self) -> StardewRule:
|
|
return self.logic.museum.can_complete_museum()
|
|
|
|
def can_complete_full_house(self) -> StardewRule:
|
|
return self.logic.relationship.has_children(2) & self.logic.relationship.can_reproduce()
|
|
|
|
def can_complete_greatest_walnut_hunter(self) -> StardewRule:
|
|
return self.logic.walnut.has_walnut(130)
|
|
|
|
def can_complete_protector_of_the_valley(self) -> StardewRule:
|
|
return self.logic.monster.can_complete_all_monster_slaying_goals()
|
|
|
|
def can_complete_full_shipment(self, all_location_names_in_slot: list[str]) -> StardewRule:
|
|
if self.options.shipsanity == options.Shipsanity.option_none:
|
|
return self.logic.shipping.can_ship_everything()
|
|
|
|
rules = [self.logic.building.has_building(Building.shipping_bin)]
|
|
|
|
for shipsanity_location in locations_by_tag[LocationTags.SHIPSANITY]:
|
|
if shipsanity_location.name not in all_location_names_in_slot:
|
|
continue
|
|
rules.append(self.logic.region.can_reach_location(shipsanity_location.name))
|
|
return self.logic.and_(*rules)
|
|
|
|
def can_complete_gourmet_chef(self) -> StardewRule:
|
|
cooksanity_prefix = "Cook "
|
|
all_recipes_names = []
|
|
exclude_island = self.options.exclude_ginger_island == options.ExcludeGingerIsland.option_true
|
|
for location in locations_by_tag[LocationTags.COOKSANITY]:
|
|
if exclude_island and LocationTags.GINGER_ISLAND in location.tags:
|
|
continue
|
|
if location.mod_name and location.mod_name not in self.options.mods:
|
|
continue
|
|
all_recipes_names.append(location.name[len(cooksanity_prefix):])
|
|
all_recipes = [all_cooking_recipes_by_name[recipe_name] for recipe_name in all_recipes_names]
|
|
return self.logic.and_(*(self.logic.cooking.can_cook(recipe) for recipe in all_recipes))
|
|
|
|
def can_complete_craft_master(self) -> StardewRule:
|
|
craftsanity_prefix = "Craft "
|
|
all_recipes_names = []
|
|
exclude_island = self.options.exclude_ginger_island == options.ExcludeGingerIsland.option_true
|
|
exclude_masteries = not self.content.features.skill_progression.are_masteries_shuffled
|
|
for location in locations_by_tag[LocationTags.CRAFTSANITY]:
|
|
if not location.name.startswith(craftsanity_prefix):
|
|
continue
|
|
if exclude_island and LocationTags.GINGER_ISLAND in location.tags:
|
|
continue
|
|
# FIXME Remove when recipes are in content packs
|
|
if exclude_masteries and LocationTags.REQUIRES_MASTERIES in location.tags:
|
|
continue
|
|
if location.mod_name and location.mod_name not in self.options.mods:
|
|
continue
|
|
all_recipes_names.append(location.name[len(craftsanity_prefix):])
|
|
all_recipes = [all_crafting_recipes_by_name[recipe_name] for recipe_name in all_recipes_names]
|
|
return self.logic.and_(*(self.logic.crafting.can_craft(recipe) for recipe in all_recipes))
|
|
|
|
def can_complete_legend(self) -> StardewRule:
|
|
return self.logic.money.can_have_earned_total(10_000_000)
|
|
|
|
def can_complete_mystery_of_the_stardrop(self) -> StardewRule:
|
|
other_rules = []
|
|
number_of_stardrops_to_receive = 0
|
|
number_of_stardrops_to_receive += 1 # The Mines level 100
|
|
number_of_stardrops_to_receive += 1 # Old Master Cannoli
|
|
number_of_stardrops_to_receive += 1 # Museum Stardrop
|
|
number_of_stardrops_to_receive += 1 # Krobus Stardrop
|
|
|
|
# Master Angler Stardrop
|
|
if self.content.features.fishsanity.is_enabled:
|
|
number_of_stardrops_to_receive += 1
|
|
else:
|
|
other_rules.append(self.logic.fishing.can_catch_every_fish())
|
|
|
|
if self.options.festival_locations == options.FestivalLocations.option_disabled: # Fair Stardrop
|
|
other_rules.append(self.logic.season.has(Season.fall))
|
|
else:
|
|
number_of_stardrops_to_receive += 1
|
|
|
|
# Spouse Stardrop
|
|
if self.content.features.friendsanity.is_enabled:
|
|
number_of_stardrops_to_receive += 1
|
|
else:
|
|
other_rules.append(self.logic.relationship.has_hearts_with_any_bachelor(13))
|
|
|
|
if ModNames.deepwoods in self.options.mods: # Petting the Unicorn
|
|
number_of_stardrops_to_receive += 1
|
|
|
|
return self.logic.received("Stardrop", number_of_stardrops_to_receive) & self.logic.and_(*other_rules, allow_empty=True)
|
|
|
|
def can_complete_allsanity(self) -> StardewRule:
|
|
return self.logic.has_progress_percent(100)
|
|
|
|
def can_complete_perfection(self) -> StardewRule:
|
|
return self.logic.has_progress_percent(100)
|