* create building data object and rename ItemSource to Source to be more generic # Conflicts: # worlds/stardew_valley/content/game_content.py # Conflicts: # worlds/stardew_valley/data/artisan.py # worlds/stardew_valley/data/game_item.py # worlds/stardew_valley/data/harvest.py # worlds/stardew_valley/data/shop.py * remove compound sources, replace by other requirements which already handle this usecase * add coops to content packs * add building progression in game features * add shippping bin to starting building; remove has_house * replace config check with feature * add other buildings in content packs * not passing * tests passes, unbelievable * use newly create methods more * use new assets to ease readability * self review * fix flake8 maybe * properly split rule for mapping cave systems * fix tractor garage name * self review * add upgrade_from to farm house buldings * don't override building name variable in logic * remove has_group from buildings * mark some items easy in grinding logic so blueprints buildings can be in more early spheres * move stuff around to maybe avoid future conflicts cuz I have like 10 PRs opened right now * remove price_multiplier, turns out it's unused during generation * disable shop source for mapping cave systems * bunch of code review changes * add petbowl and farmhouse to autobuilding * set min easy items to 300 * fix farm type
		
			
				
	
	
		
			174 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import typing
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
if typing.TYPE_CHECKING:
 | 
						|
    from .logic import StardewLogic
 | 
						|
else:
 | 
						|
    StardewLogic = object
 | 
						|
 | 
						|
 | 
						|
class GoalLogicMixin(BaseLogicMixin):
 | 
						|
    def __init__(self, *args, **kwargs):
 | 
						|
        super().__init__(*args, **kwargs)
 | 
						|
        self.goal = GoalLogic(*args, **kwargs)
 | 
						|
 | 
						|
 | 
						|
class GoalLogic(BaseLogic[StardewLogic]):
 | 
						|
 | 
						|
    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)
 |