diff --git a/worlds/ahit/Items.py b/worlds/ahit/Items.py index 9c0df4a062..cdc1ce9a44 100644 --- a/worlds/ahit/Items.py +++ b/worlds/ahit/Items.py @@ -10,8 +10,7 @@ if TYPE_CHECKING: def create_itempool(world: "HatInTimeWorld") -> List[Item]: itempool: List[Item] = [] - if not world.is_dw_only() and world.options.HatItems.value == 0: - calculate_yarn_costs(world) + if world.has_yarn(): yarn_pool: List[Item] = create_multiple_items(world, "Yarn", world.options.YarnAvailable.value, ItemClassification.progression_skip_balancing) @@ -90,13 +89,12 @@ def create_itempool(world: "HatInTimeWorld") -> List[Item]: def calculate_yarn_costs(world: "HatInTimeWorld"): - mw = world.multiworld min_yarn_cost = int(min(world.options.YarnCostMin.value, world.options.YarnCostMax.value)) max_yarn_cost = int(max(world.options.YarnCostMin.value, world.options.YarnCostMax.value)) max_cost = 0 for i in range(5): - cost: int = mw.random.randint(min(min_yarn_cost, max_yarn_cost), max(max_yarn_cost, min_yarn_cost)) + cost: int = world.random.randint(min(min_yarn_cost, max_yarn_cost), max(max_yarn_cost, min_yarn_cost)) world.hat_yarn_costs[HatType(i)] = cost max_cost += cost diff --git a/worlds/ahit/Options.py b/worlds/ahit/Options.py index 40b737468c..0cc80bf902 100644 --- a/worlds/ahit/Options.py +++ b/worlds/ahit/Options.py @@ -306,7 +306,7 @@ class FinalChapterMaxCost(Range): class MaxExtraTimePieces(Range): - """Maximum amount of extra Time Pieces from the DLCs. + """Maximum number of extra Time Pieces from the DLCs. Arctic Cruise will add up to 6. Nyakuza Metro will add up to 10. The absolute maximum is 56.""" display_name = "Max Extra Time Pieces" range_start = 0 @@ -339,8 +339,8 @@ class YarnAvailable(Range): class MinExtraYarn(Range): - """The minimum amount of extra yarn in the item pool. - There must be at least this much more yarn over the total amount of yarn needed to craft all hats. + """The minimum number of extra yarn in the item pool. + There must be at least this much more yarn over the total number of yarn needed to craft all hats. For example, if this option's value is 10, and the total yarn needed to craft all hats is 40, there must be at least 50 yarn in the pool.""" display_name = "Max Extra Yarn" @@ -355,7 +355,7 @@ class HatItems(Toggle): class MinPonCost(Range): - """The minimum amount of Pons that any shop item can cost.""" + """The minimum number of Pons that any shop item can cost.""" display_name = "Minimum Shop Pon Cost" range_start = 10 range_end = 800 @@ -363,7 +363,7 @@ class MinPonCost(Range): class MaxPonCost(Range): - """The maximum amount of Pons that any shop item can cost.""" + """The maximum number of Pons that any shop item can cost.""" display_name = "Maximum Shop Pon Cost" range_start = 10 range_end = 800 @@ -371,7 +371,7 @@ class MaxPonCost(Range): class BadgeSellerMinItems(Range): - """The smallest amount of items that the Badge Seller can have for sale.""" + """The smallest number of items that the Badge Seller can have for sale.""" display_name = "Badge Seller Minimum Items" range_start = 0 range_end = 10 @@ -379,7 +379,7 @@ class BadgeSellerMinItems(Range): class BadgeSellerMaxItems(Range): - """The largest amount of items that the Badge Seller can have for sale.""" + """The largest number of items that the Badge Seller can have for sale.""" display_name = "Badge Seller Maximum Items" range_start = 0 range_end = 10 @@ -421,7 +421,7 @@ class ExcludeTour(Toggle): class ShipShapeCustomTaskGoal(Range): - """Change the amount of tasks required to complete Ship Shape. This will not affect Cruisin' for a Bruisin'.""" + """Change the number of tasks required to complete Ship Shape. This will not affect Cruisin' for a Bruisin'.""" display_name = "Ship Shape Custom Task Goal" range_start = 1 range_end = 30 @@ -451,7 +451,7 @@ class MetroMaxPonCost(Range): class NyakuzaThugMinShopItems(Range): - """The smallest amount of items that the thugs in Nyakuza Metro can have for sale.""" + """The smallest number of items that the thugs in Nyakuza Metro can have for sale.""" display_name = "Nyakuza Thug Minimum Shop Items" range_start = 0 range_end = 5 @@ -459,7 +459,7 @@ class NyakuzaThugMinShopItems(Range): class NyakuzaThugMaxShopItems(Range): - """The largest amount of items that the thugs in Nyakuza Metro can have for sale.""" + """The largest number of items that the thugs in Nyakuza Metro can have for sale.""" display_name = "Nyakuza Thug Maximum Shop Items" range_start = 0 range_end = 5 diff --git a/worlds/ahit/Rules.py b/worlds/ahit/Rules.py index 0965146fcc..0f8f2c6aaf 100644 --- a/worlds/ahit/Rules.py +++ b/worlds/ahit/Rules.py @@ -452,6 +452,11 @@ def set_moderate_rules(world: "HatInTimeWorld"): # No Dweller, Hookshot, or Time Stop for these set_rule(world.multiworld.get_location("Pink Paw Station - Cat Vacuum", world.player), lambda state: True) set_rule(world.multiworld.get_location("Pink Paw Station - Behind Fan", world.player), lambda state: True) + set_rule(world.multiworld.get_location("Pink Paw Station - Pink Ticket Booth", world.player), lambda state: True) + set_rule(world.multiworld.get_location("Act Completion (Pink Paw Station)", world.player), lambda state: True) + for key in shop_locations.keys(): + if "Pink Paw Station Thug" in key and is_location_valid(world, key): + set_rule(world.multiworld.get_location(key, world.player), lambda state: True) # Moderate: clear Rush Hour without Hookshot set_rule(world.multiworld.get_location("Act Completion (Rush Hour)", world.player), diff --git a/worlds/ahit/__init__.py b/worlds/ahit/__init__.py index dd16a87489..c0caf019cf 100644 --- a/worlds/ahit/__init__.py +++ b/worlds/ahit/__init__.py @@ -1,5 +1,6 @@ from BaseClasses import Item, ItemClassification, Tutorial, Location, MultiWorld -from .Items import item_table, create_item, relic_groups, act_contracts, create_itempool, get_shop_trap_name +from .Items import item_table, create_item, relic_groups, act_contracts, create_itempool, get_shop_trap_name, \ + calculate_yarn_costs from .Regions import create_regions, randomize_act_entrances, chapter_act_info, create_events, get_shuffled_region from .Locations import location_table, contract_locations, is_location_valid, get_location_names, TASKSANITY_START_ID, \ get_total_locations @@ -124,11 +125,14 @@ class HatInTimeWorld(World): self.multiworld.get_location(name, self.player).place_locked_item(create_item(self, name)) def create_items(self): - if self.options.HatItems.value == 0 and self.options.RandomizeHatOrder.value > 0: - self.random.shuffle(self.hat_craft_order) - if self.options.RandomizeHatOrder.value == 2: - self.hat_craft_order.remove(HatType.TIME_STOP) - self.hat_craft_order.append(HatType.TIME_STOP) + if self.has_yarn(): + calculate_yarn_costs(self) + + if self.options.RandomizeHatOrder.value > 0: + self.random.shuffle(self.hat_craft_order) + if self.options.RandomizeHatOrder.value == 2: + self.hat_craft_order.remove(HatType.TIME_STOP) + self.hat_craft_order.append(HatType.TIME_STOP) self.multiworld.itempool += create_itempool(self) @@ -180,7 +184,7 @@ class HatInTimeWorld(World): "SeedName": self.multiworld.seed_name, "TotalLocations": get_total_locations(self)} - if self.options.HatItems.value == 0: + if self.has_yarn(): slot_data.setdefault("SprintYarnCost", self.hat_yarn_costs[HatType.SPRINT]) slot_data.setdefault("BrewingYarnCost", self.hat_yarn_costs[HatType.BREWING]) slot_data.setdefault("IceYarnCost", self.hat_yarn_costs[HatType.ICE]) @@ -287,6 +291,9 @@ class HatInTimeWorld(World): for hat in self.hat_craft_order: spoiler_handle.write("Hat Cost: %s: %i\n" % (hat, self.hat_yarn_costs[hat])) + def has_yarn(self) -> bool: + return not self.is_dw_only() and self.options.HatItems.value == 0 + def is_dlc1(self) -> bool: return self.options.EnableDLC1.value > 0