Skip to content

Commit

Permalink
- Implement new Power user feature: Bundle Plando, available from the…
Browse files Browse the repository at this point in the history
… yaml template

- Add grind logic to bundles that require a lot of something
  • Loading branch information
agilbert1412 committed Jun 19, 2024
1 parent 975752f commit b2f3b61
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 125 deletions.
20 changes: 8 additions & 12 deletions worlds/stardew_valley/bundles/bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ def extend_from(template, items: List[BundleItem]):
return BundleTemplate(template.room, template.name, items, template.number_possible_items,
template.number_required_items)

def create_bundle(self, bundle_price_option: BundlePrice, random: Random, content: StardewContent,
options: StardewValleyOptions) -> Bundle:
number_required, price_multiplier = get_bundle_final_prices(bundle_price_option, self.number_required_items, False)
def create_bundle(self, random: Random, content: StardewContent, options: StardewValleyOptions) -> Bundle:
number_required, price_multiplier = get_bundle_final_prices(options.bundle_price, self.number_required_items, False)
filtered_items = [item for item in self.items if item.can_appear(content, options)]
number_items = len(filtered_items)
number_chosen_items = self.number_possible_items
Expand All @@ -68,9 +67,8 @@ def __init__(self, room: str, name: str, item: BundleItem):
super().__init__(room, name, [item], 1, 1)
self.item = item

def create_bundle(self, bundle_price_option: BundlePrice, random: Random, content: StardewContent,
options: StardewValleyOptions) -> Bundle:
currency_amount = self.get_currency_amount(bundle_price_option)
def create_bundle(self, random: Random, content: StardewContent, options: StardewValleyOptions) -> Bundle:
currency_amount = self.get_currency_amount(options.bundle_price)
return Bundle(self.room, self.name, [BundleItem(self.item.item_name, currency_amount)], 1)

def get_currency_amount(self, bundle_price_option: BundlePrice):
Expand All @@ -93,9 +91,8 @@ class MoneyBundleTemplate(CurrencyBundleTemplate):
def __init__(self, room: str, item: BundleItem):
super().__init__(room, "", item)

def create_bundle(self, bundle_price_option: BundlePrice, random: Random, content: StardewContent,
options: StardewValleyOptions) -> Bundle:
currency_amount = self.get_currency_amount(bundle_price_option)
def create_bundle(self, random: Random, content: StardewContent, options: StardewValleyOptions) -> Bundle:
currency_amount = self.get_currency_amount(options.bundle_price)
currency_name = "g"
if currency_amount >= 1000:
unit_amount = currency_amount % 1000
Expand Down Expand Up @@ -130,9 +127,8 @@ def __init__(self, room: str, name: str, categories: List[List[BundleItem]], num
super().__init__(room, name, [], number_possible_items, number_required_items)
self.categories = categories

def create_bundle(self, bundle_price_option: BundlePrice, random: Random, content: StardewContent,
options: StardewValleyOptions) -> Bundle:
number_required, price_multiplier = get_bundle_final_prices(bundle_price_option, self.number_required_items, False)
def create_bundle(self, random: Random, content: StardewContent, options: StardewValleyOptions) -> Bundle:
number_required, price_multiplier = get_bundle_final_prices(options.bundle_price, self.number_required_items, False)
number_categories = len(self.categories)
number_chosen_categories = self.number_possible_items
if number_chosen_categories < number_required:
Expand Down
25 changes: 19 additions & 6 deletions worlds/stardew_valley/bundles/bundle_room.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,25 @@ class BundleRoomTemplate:
bundles: List[BundleTemplate]
number_bundles: int

def create_bundle_room(self, bundle_price_option: BundlePrice, random: Random, content: StardewContent, options: StardewValleyOptions):
def create_bundle_room(self, random: Random, content: StardewContent, options: StardewValleyOptions):
filtered_bundles = [bundle for bundle in self.bundles if bundle.can_appear(options)]

if self.number_bundles > len(filtered_bundles):
chosen_bundles = random.choices(filtered_bundles, k=self.number_bundles)
else:
chosen_bundles = random.sample(filtered_bundles, self.number_bundles)
priority_bundles = []
unpriority_bundles = []
for bundle in filtered_bundles:
if bundle.name in options.bundle_plando:
priority_bundles.append(bundle)
else:
unpriority_bundles.append(bundle)

return BundleRoom(self.name, [bundle.create_bundle(bundle_price_option, random, content, options) for bundle in chosen_bundles])
if self.number_bundles <= len(priority_bundles):
chosen_bundles = random.sample(priority_bundles, self.number_bundles)
else:
chosen_bundles = priority_bundles
num_remaining_bundles = self.number_bundles - len(priority_bundles)
if num_remaining_bundles > len(unpriority_bundles):
chosen_bundles.extend(random.choices(unpriority_bundles, k=num_remaining_bundles))
else:
chosen_bundles.extend(random.sample(unpriority_bundles, num_remaining_bundles))

return BundleRoom(self.name, [bundle.create_bundle(random, content, options) for bundle in chosen_bundles])
50 changes: 25 additions & 25 deletions worlds/stardew_valley/bundles/bundles.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,40 +25,40 @@ def get_all_bundles(random: Random, logic: StardewLogic, content: StardewContent


def get_vanilla_bundles(random: Random, content: StardewContent, options: StardewValleyOptions) -> List[BundleRoom]:
pantry = pantry_vanilla.create_bundle_room(options.bundle_price, random, content, options)
crafts_room = crafts_room_vanilla.create_bundle_room(options.bundle_price, random, content, options)
fish_tank = fish_tank_vanilla.create_bundle_room(options.bundle_price, random, content, options)
boiler_room = boiler_room_vanilla.create_bundle_room(options.bundle_price, random, content, options)
bulletin_board = bulletin_board_vanilla.create_bundle_room(options.bundle_price, random, content, options)
vault = vault_vanilla.create_bundle_room(options.bundle_price, random, content, options)
abandoned_joja_mart = abandoned_joja_mart_vanilla.create_bundle_room(options.bundle_price, random, content, options)
raccoon = raccoon_vanilla.create_bundle_room(options.bundle_price, random, content, options)
pantry = pantry_vanilla.create_bundle_room(random, content, options)
crafts_room = crafts_room_vanilla.create_bundle_room(random, content, options)
fish_tank = fish_tank_vanilla.create_bundle_room(random, content, options)
boiler_room = boiler_room_vanilla.create_bundle_room(random, content, options)
bulletin_board = bulletin_board_vanilla.create_bundle_room(random, content, options)
vault = vault_vanilla.create_bundle_room(random, content, options)
abandoned_joja_mart = abandoned_joja_mart_vanilla.create_bundle_room(random, content, options)
raccoon = raccoon_vanilla.create_bundle_room(random, content, options)
fix_raccoon_bundle_names(raccoon)
return [pantry, crafts_room, fish_tank, boiler_room, bulletin_board, vault, abandoned_joja_mart, raccoon]


def get_thematic_bundles(random: Random, content: StardewContent, options: StardewValleyOptions) -> List[BundleRoom]:
pantry = pantry_thematic.create_bundle_room(options.bundle_price, random, content, options)
crafts_room = crafts_room_thematic.create_bundle_room(options.bundle_price, random, content, options)
fish_tank = fish_tank_thematic.create_bundle_room(options.bundle_price, random, content, options)
boiler_room = boiler_room_thematic.create_bundle_room(options.bundle_price, random, content, options)
bulletin_board = bulletin_board_thematic.create_bundle_room(options.bundle_price, random, content, options)
vault = vault_thematic.create_bundle_room(options.bundle_price, random, content, options)
abandoned_joja_mart = abandoned_joja_mart_thematic.create_bundle_room(options.bundle_price, random, content, options)
raccoon = raccoon_thematic.create_bundle_room(options.bundle_price, random, content, options)
pantry = pantry_thematic.create_bundle_room(random, content, options)
crafts_room = crafts_room_thematic.create_bundle_room(random, content, options)
fish_tank = fish_tank_thematic.create_bundle_room(random, content, options)
boiler_room = boiler_room_thematic.create_bundle_room(random, content, options)
bulletin_board = bulletin_board_thematic.create_bundle_room(random, content, options)
vault = vault_thematic.create_bundle_room(random, content, options)
abandoned_joja_mart = abandoned_joja_mart_thematic.create_bundle_room(random, content, options)
raccoon = raccoon_thematic.create_bundle_room(random, content, options)
fix_raccoon_bundle_names(raccoon)
return [pantry, crafts_room, fish_tank, boiler_room, bulletin_board, vault, abandoned_joja_mart, raccoon]


def get_remixed_bundles(random: Random, content: StardewContent, options: StardewValleyOptions) -> List[BundleRoom]:
pantry = pantry_remixed.create_bundle_room(options.bundle_price, random, content, options)
crafts_room = crafts_room_remixed.create_bundle_room(options.bundle_price, random, content, options)
fish_tank = fish_tank_remixed.create_bundle_room(options.bundle_price, random, content, options)
boiler_room = boiler_room_remixed.create_bundle_room(options.bundle_price, random, content, options)
bulletin_board = bulletin_board_remixed.create_bundle_room(options.bundle_price, random, content, options)
vault = vault_remixed.create_bundle_room(options.bundle_price, random, content, options)
abandoned_joja_mart = abandoned_joja_mart_remixed.create_bundle_room(options.bundle_price, random, content, options)
raccoon = raccoon_remixed.create_bundle_room(options.bundle_price, random, content, options)
pantry = pantry_remixed.create_bundle_room(random, content, options)
crafts_room = crafts_room_remixed.create_bundle_room(random, content, options)
fish_tank = fish_tank_remixed.create_bundle_room(random, content, options)
boiler_room = boiler_room_remixed.create_bundle_room(random, content, options)
bulletin_board = bulletin_board_remixed.create_bundle_room(random, content, options)
vault = vault_remixed.create_bundle_room(random, content, options)
abandoned_joja_mart = abandoned_joja_mart_remixed.create_bundle_room(random, content, options)
raccoon = raccoon_remixed.create_bundle_room(random, content, options)
fix_raccoon_bundle_names(raccoon)
return [pantry, crafts_room, fish_tank, boiler_room, bulletin_board, vault, abandoned_joja_mart, raccoon]

Expand All @@ -84,7 +84,7 @@ def get_shuffled_bundles(random: Random, logic: StardewLogic, content: StardewCo
bundle.items = chosen_bundle_items[:num_items]
chosen_bundle_items = chosen_bundle_items[num_items:]

vault = vault_remixed.create_bundle_room(options.bundle_price, random, content, options)
vault = vault_remixed.create_bundle_room(random, content, options)
return [*rooms, vault]


Expand Down
9 changes: 7 additions & 2 deletions worlds/stardew_valley/logic/bundle_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .received_logic import ReceivedLogicMixin
from .region_logic import RegionLogicMixin
from .skill_logic import SkillLogicMixin
from .time_logic import TimeLogicMixin
from ..bundles.bundle import Bundle
from ..stardew_rule import StardewRule, True_
from ..strings.ap_names.community_upgrade_names import CommunityUpgrade
Expand All @@ -26,22 +27,26 @@ def __init__(self, *args, **kwargs):
self.bundle = BundleLogic(*args, **kwargs)


class BundleLogic(BaseLogic[Union[ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, MoneyLogicMixin, QualityLogicMixin, FishingLogicMixin, SkillLogicMixin,
class BundleLogic(BaseLogic[Union[ReceivedLogicMixin, HasLogicMixin, TimeLogicMixin, RegionLogicMixin, MoneyLogicMixin, QualityLogicMixin, FishingLogicMixin, SkillLogicMixin,
QuestLogicMixin]]):
# Should be cached
def can_complete_bundle(self, bundle: Bundle) -> StardewRule:
item_rules = []
qualities = []
time_to_grind = 0
can_speak_junimo = self.logic.region.can_reach(Region.wizard_tower)
for bundle_item in bundle.items:
if Currency.is_currency(bundle_item.get_item()):
return can_speak_junimo & self.logic.money.can_trade(bundle_item.get_item(), bundle_item.amount)

item_rules.append(bundle_item.get_item())
if bundle_item.amount > 50:
time_to_grind = bundle_item.amount // 50
qualities.append(bundle_item.quality)
quality_rules = self.get_quality_rules(qualities)
item_rules = self.logic.has_n(*item_rules, count=bundle.number_required)
return can_speak_junimo & item_rules & quality_rules
time_rule = True_() if time_to_grind <= 0 else self.logic.time.has_lived_months(time_to_grind)
return can_speak_junimo & item_rules & quality_rules & time_rule

def get_quality_rules(self, qualities: List[str]) -> StardewRule:
crop_quality = CropQuality.get_highest(qualities)
Expand Down
13 changes: 12 additions & 1 deletion worlds/stardew_valley/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
from dataclasses import dataclass
from typing import Protocol, ClassVar

from Options import Range, NamedRange, Toggle, Choice, OptionSet, PerGameCommonOptions, DeathLink, OptionList
from Options import Range, NamedRange, Toggle, Choice, OptionSet, PerGameCommonOptions, DeathLink, OptionList, Visibility
from .mods.mod_data import ModNames
from .strings.ap_names.ap_option_names import OptionName
from .strings.bundle_names import all_cc_bundle_names


class StardewValleyOption(Protocol):
Expand Down Expand Up @@ -777,6 +778,15 @@ class Mods(OptionSet):
ModNames.alecto, ModNames.lacey, ModNames.boarding_house}.difference(disabled_mods)


class BundlePlando(OptionSet):
"""If using Remixed bundles, this garantees some of them will show up in your community center.
If more bundles are specified than what fits in a given room, they will be randomly picked but only from the plando ones"""
internal_name = "bundle_plando"
display_name = "Bundle Plando"
visibility = Visibility.template | Visibility.spoiler
valid_keys = set(all_cc_bundle_names)


@dataclass
class StardewValleyOptions(PerGameCommonOptions):
goal: Goal
Expand Down Expand Up @@ -820,4 +830,5 @@ class StardewValleyOptions(PerGameCommonOptions):
multiple_day_sleep_cost: MultipleDaySleepCost
gifting: Gifting
mods: Mods
bundle_plando: BundlePlando
death_link: DeathLink
Loading

0 comments on commit b2f3b61

Please sign in to comment.