Files
Grinch-AP/worlds/stardew_valley/logic/grind_logic.py
Jérémie Bolduc 9ac921380f Stardew Valley: Refactor buildings to use content packs (#4239)
* 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
2025-04-08 12:37:45 -04:00

99 lines
4.4 KiB
Python

from typing import Union, TYPE_CHECKING
from Utils import cache_self1
from .base_logic import BaseLogic, BaseLogicMixin
from .book_logic import BookLogicMixin
from .has_logic import HasLogicMixin
from .received_logic import ReceivedLogicMixin
from .region_logic import RegionLogicMixin
from .time_logic import TimeLogicMixin
from ..stardew_rule import StardewRule, HasProgressionPercent
from ..strings.book_names import Book
from ..strings.craftable_names import Consumable
from ..strings.currency_names import Currency
from ..strings.fish_names import WaterChest
from ..strings.geode_names import Geode
from ..strings.material_names import Material
from ..strings.region_names import Region
from ..strings.tool_names import Tool
if TYPE_CHECKING:
from .tool_logic import ToolLogicMixin
else:
ToolLogicMixin = object
MIN_MEDIUM_ITEMS = 10
MAX_MEDIUM_ITEMS = 999
PERCENT_REQUIRED_FOR_MAX_MEDIUM_ITEM = 24
EASY_ITEMS = {Material.wood, Material.stone, Material.fiber, Material.sap}
MIN_EASY_ITEMS = 300
MAX_EASY_ITEMS = 2997
PERCENT_REQUIRED_FOR_MAX_EASY_ITEM = 6
class GrindLogicMixin(BaseLogicMixin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.grind = GrindLogic(*args, **kwargs)
class GrindLogic(BaseLogic[Union[GrindLogicMixin, HasLogicMixin, ReceivedLogicMixin, RegionLogicMixin, BookLogicMixin, TimeLogicMixin, ToolLogicMixin]]):
def can_grind_mystery_boxes(self, quantity: int) -> StardewRule:
opening_rule = self.logic.region.can_reach(Region.blacksmith)
mystery_box_rule = self.logic.has(Consumable.mystery_box)
book_of_mysteries_rule = self.logic.true_ \
if not self.content.features.booksanity.is_enabled \
else self.logic.book.has_book_power(Book.book_of_mysteries)
# Assuming one box per day, but halved because we don't know how many months have passed before Mr. Qi's Plane Ride.
time_rule = self.logic.time.has_lived_months(quantity // 14)
return self.logic.and_(opening_rule, mystery_box_rule,
book_of_mysteries_rule, time_rule, )
def can_grind_artifact_troves(self, quantity: int) -> StardewRule:
opening_rule = self.logic.region.can_reach(Region.blacksmith)
return self.logic.and_(opening_rule, self.logic.has(Geode.artifact_trove),
# Assuming one per month if the player does not grind it.
self.logic.time.has_lived_months(quantity))
def can_grind_prize_tickets(self, quantity: int) -> StardewRule:
claiming_rule = self.logic.region.can_reach(Region.mayor_house)
return self.logic.and_(claiming_rule, self.logic.has(Currency.prize_ticket),
# Assuming two per month if the player does not grind it.
self.logic.time.has_lived_months(quantity // 2))
def can_grind_fishing_treasure_chests(self, quantity: int) -> StardewRule:
return self.logic.and_(self.logic.has(WaterChest.fishing_chest),
# Assuming one per week if the player does not grind it.
self.logic.time.has_lived_months(quantity // 4))
def can_grind_artifact_spots(self, quantity: int) -> StardewRule:
return self.logic.and_(self.logic.tool.has_tool(Tool.hoe),
# Assuming twelve per month if the player does not grind it.
self.logic.time.has_lived_months(quantity // 12))
def can_grind_item(self, quantity: int, item: str | None = None) -> StardewRule:
if item in EASY_ITEMS:
return self.logic.grind.can_grind_easy_item(quantity)
else:
return self.logic.grind.can_grind_medium_item(quantity)
@cache_self1
def can_grind_medium_item(self, quantity: int) -> StardewRule:
if quantity <= MIN_MEDIUM_ITEMS:
return self.logic.true_
quantity = min(quantity, MAX_MEDIUM_ITEMS)
price = max(1, quantity * PERCENT_REQUIRED_FOR_MAX_MEDIUM_ITEM // MAX_MEDIUM_ITEMS)
return HasProgressionPercent(self.player, price)
@cache_self1
def can_grind_easy_item(self, quantity: int) -> StardewRule:
if quantity <= MIN_EASY_ITEMS:
return self.logic.true_
quantity = min(quantity, MAX_EASY_ITEMS)
price = max(1, quantity * PERCENT_REQUIRED_FOR_MAX_EASY_ITEM // MAX_EASY_ITEMS)
return HasProgressionPercent(self.player, price)