Skip to content

Commit

Permalink
Initial implementation of tome randomization
Browse files Browse the repository at this point in the history
  • Loading branch information
SunnyBat committed Jun 17, 2024
1 parent 5070788 commit bc3f367
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 23 deletions.
5 changes: 5 additions & 0 deletions worlds/yooka_laylee/Options.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ class PagiesRequiredForCapitalB(Range):
range_end = 145
default = 100

class GrandTomeRandomization(Toggle):
"""If enabled, randomizes the order of the Grand Tome worlds. This does not change the location of the Grand Tomes within Hivory Towers or the cost of the Grand Tomes, only the world you go to when entering a Grand Tome. Galleon Galaxy will never be randomized in place of Tribalstack Tropics."""
display_name = "Randomize Grand Tome World Order"

class DisableQuizzes(Toggle):
"""If enabled, causes the quizzes to be completely skipped."""
display_name = "Disable Quizzes"
Expand All @@ -33,6 +37,7 @@ class DisableQuizzes(Toggle):
"prevent_tropics_bk": PreventTropicsBK,
"flappy_flight_location": FlappyFlightLocation,
"capital_b_pagie_count": PagiesRequiredForCapitalB,
"randomize_grand_tomes": GrandTomeRandomization,
"disable_quizzes": DisableQuizzes,
"death_link": DeathLink
}
55 changes: 35 additions & 20 deletions worlds/yooka_laylee/Rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
import pkgutil

cashinotokens_table = json.loads(pkgutil.get_data(__name__, "cashinotokens.json").decode())
requiredPagiesPerTomeVanillaOrder = [
[1, 4],
[7, 12],
[19, 27],
[37, 48],
[60, 75]
]
randomizedWorldOrder = []

class YookaLayleeLogic(LogicMixin):
yookaLaylee_specialRequirements = {
Expand Down Expand Up @@ -35,6 +43,19 @@ class YookaLayleeLogic(LogicMixin):
"<GalaxyEntry>": lambda state, player: state.has("Flappy Flight", player) or state.has("Glide", player) or state.has("Health Booster", player, 5)
}

yookaLaylee_tomeRequirementsVanillaOrder = [
lambda self, player: self.yookaLaylee_can_access_HT_hub_entrance(player) and (self.has("Reptile Roll", player) or self.has("Flappy Flight", player)),
lambda self, player: self.yookaLaylee_can_access_HT_hub_B(player) and (self.has("Glide", player) or self.has("Flappy Flight", player)),
lambda self, player: self.yookaLaylee_can_access_HT_waterworks(player) and (self.has("Buddy Bubble", player) or self.has("Lizard Lash", player) or self.has("Flappy Flight", player)),
lambda self, player: self.yookaLaylee_can_access_HT_outside(player) and self.has("Camo Cloak", player),
lambda self, player: self.yookaLaylee_can_access_HT_finalArea(player)
]

def yookaLaylee_checkRequirementsForWorld(self, player, worldIdentifier, expanded = False):
worldOrderIndex = randomizedWorldOrder.index(worldIdentifier)
return (self.has("Pagie", player, requiredPagiesPerTomeVanillaOrder[worldOrderIndex][0 if expanded else 1])
and self.yookaLaylee_tomeRequirementsVanillaOrder[worldOrderIndex](self, player))

def yookaLaylee_can_access_HT_hub_entrance(self, player):
return self.yookaLaylee_has_requirements("<DamagingAbility>", player)

Expand All @@ -55,45 +76,37 @@ def yookaLaylee_can_access_HT_finalArea(self, player):
return self.yookaLaylee_can_access_HT_outside(player) and self.has("Flappy Flight", player)

def yookaLaylee_can_access_tropics(self, player):
return (self.has("Pagie", player, 1)
and self.yookaLaylee_can_access_HT_hub_entrance(player)
and (self.has("Reptile Roll", player) or self.has("Flappy Flight", player)))
return self.yookaLaylee_checkRequirementsForWorld(player, "TT")

def yookaLaylee_can_access_tropics_exp(self, player):
return self.has("Pagie", player, 4) and self.yookaLaylee_can_access_tropics(player)
return self.yookaLaylee_checkRequirementsForWorld(player, "TT", True)

def yookaLaylee_can_access_glacier(self, player):
return (self.has("Pagie", player, 7)
and self.yookaLaylee_can_access_HT_hub_B(player)
and (self.has("Glide", player) or self.has("Flappy Flight", player)))
return self.yookaLaylee_checkRequirementsForWorld(player, "GG")

def yookaLaylee_can_access_glacier_exp(self, player):
return self.has("Pagie", player, 12) and self.yookaLaylee_can_access_glacier(player)
return self.yookaLaylee_checkRequirementsForWorld(player, "GG", True)

def yookaLaylee_can_access_marsh(self, player):
return (self.has("Pagie", player, 19)
and self.yookaLaylee_can_access_HT_waterworks(player)
and (self.has("Buddy Bubble", player) or self.has("Lizard Lash", player) or self.has("Flappy Flight", player)))
return self.yookaLaylee_checkRequirementsForWorld(player, "MM")

def yookaLaylee_can_access_marsh_exp(self, player):
return self.has("Pagie", player, 27) and self.yookaLaylee_can_access_marsh(player)
return self.yookaLaylee_checkRequirementsForWorld(player, "MM", True)

def yookaLaylee_can_access_cashino(self, player):
return (self.has("Pagie", player, 37)
and self.yookaLaylee_can_access_HT_outside(player)
and self.has("Camo Cloak", player))
return self.yookaLaylee_checkRequirementsForWorld(player, "CC")

def yookaLaylee_can_access_cashino_exp(self, player):
return self.has("Pagie", player, 48) and self.yookaLaylee_can_access_cashino(player)
return self.yookaLaylee_checkRequirementsForWorld(player, "CC", True)

def yookaLaylee_can_access_galaxy(self, player):
return self.has("Pagie", player, 60) and self.yookaLaylee_can_access_HT_finalArea(player)
return self.yookaLaylee_checkRequirementsForWorld(player, "GY")

def yookaLaylee_can_access_galaxy_exp(self, player):
return self.has("Pagie", player, 75) and self.yookaLaylee_can_access_galaxy(player)
return self.yookaLaylee_checkRequirementsForWorld(player, "GY", True)

def yookaLaylee_can_access_end(self, player): # Technically don't need Tail Twirl and Sonar Shield, but the final boss is pretty miserable without it
return (self.has("Pagie", player, 100)
return (self.has("Pagie", player, 100) # Pagie count should not affect item placement, since endgame is locked. TODO Verify this.
and self.yookaLaylee_can_access_HT_finalArea(player)
and self.yookaLaylee_has_requirements("Sonar Shield", player)
and self.has("Tail Twirl", player))
Expand Down Expand Up @@ -141,7 +154,9 @@ def yookaLaylee_has_requirements(self, requirements, player, searchMode = 0):
else:
raise Exception(f"Invalid requirements: {str(requirements)}")

def set_rules(world, player):
def set_rules(world, player, regionOrder):
global randomizedWorldOrder
randomizedWorldOrder = regionOrder
regionChecks = {
"Shipwreck Creek": lambda state: True,
"Hivory Towers Entrance": lambda state: state.yookaLaylee_can_access_HT_hub_entrance(player),
Expand Down
13 changes: 10 additions & 3 deletions worlds/yooka_laylee/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from BaseClasses import Region, Entrance, Location, MultiWorld, Item, ItemClassification, Tutorial
from ..AutoWorld import World, WebWorld


class YookaWeb(WebWorld):
tutorials = [Tutorial(
"Multiworld Setup Guide",
Expand All @@ -35,10 +34,17 @@ class YookaWorld(World):

location_name_to_id = locations_lookup_name_to_id
option_definitions = yooka_options
grandTomeOrder = ["TT", "GG", "MM", "CC", "GY"]

data_version = 2
data_version = 3
required_client_version = (1, 0, 0)

def generate_early(self):
if self.options.randomize_grand_tomes:
self.random.shuffle(self.grandTomeOrder)
while self.grandTomeOrder[0] is "GY":
self.random.shuffle(self.grandTomeOrder)

def create_items(self):
# Set up prefill data for later
if not hasattr(self.multiworld, "yookaLaylee_prefillItems"):
Expand Down Expand Up @@ -102,7 +108,7 @@ def create_items(self):
self.multiworld.itempool += pool

def set_rules(self):
set_rules(self.multiworld, self.player)
set_rules(self.multiworld, self.player, self.grandTomeOrder)

def create_regions(self):
create_regions(self.multiworld, self.player)
Expand Down Expand Up @@ -135,6 +141,7 @@ def pre_fill(self):
def fill_slot_data(self):
return {
"CapitalBPagieCount": self.options.capital_b_pagie_count.value,
"WorldOrder": self.grandTomeOrder,
"DisableQuizzes": bool(self.options.disable_quizzes.value),
"DeathLink": bool(self.options.death_link.value)
}
Expand Down

0 comments on commit bc3f367

Please sign in to comment.