mirror of
				https://github.com/MarioSpore/Grinch-AP.git
				synced 2025-10-21 20:21:32 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			247 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from typing import Dict, List, Any
 | |
| from BaseClasses import Region, Entrance, Location, Item, Tutorial, ItemClassification
 | |
| from worlds.generic.Rules import set_rule
 | |
| from . import Exits, Items, Locations, Options, Rules
 | |
| from ..AutoWorld import WebWorld, World
 | |
| 
 | |
| 
 | |
| class Hylics2Web(WebWorld):
 | |
|     theme = "ocean"
 | |
|     tutorials = [Tutorial(
 | |
|         "Multiworld Setup Guide",
 | |
|         "A guide to settings up the Hylics 2 randomizer connected to an Archipelago Multiworld",
 | |
|         "English",
 | |
|         "setup_en.md",
 | |
|         "setup/en",
 | |
|         ["TRPG"]
 | |
|     )]
 | |
| 
 | |
| 
 | |
| class Hylics2World(World):
 | |
|     """
 | |
|     Hylics 2 is a surreal and unusual RPG, with a bizarre yet unique visual style. Play as Wayne,
 | |
|     travel the world, and gather your allies to defeat the nefarious Gibby in his Hylemxylem!
 | |
|     """
 | |
|     game: str = "Hylics 2"
 | |
|     web = Hylics2Web()
 | |
| 
 | |
|     all_items = {**Items.item_table, **Items.gesture_item_table, **Items.party_item_table,
 | |
|         **Items.medallion_item_table}
 | |
|     all_locations = {**Locations.location_table, **Locations.tv_location_table, **Locations.party_location_table,
 | |
|         **Locations.medallion_location_table}
 | |
| 
 | |
|     item_name_to_id = {data["name"]: item_id for item_id, data in all_items.items()}
 | |
|     location_name_to_id = {data["name"]: loc_id for loc_id, data in all_locations.items()}
 | |
|     option_definitions = Options.hylics2_options
 | |
| 
 | |
|     topology_present: bool = True
 | |
| 
 | |
|     data_version = 3
 | |
| 
 | |
|     start_location = "Waynehouse"
 | |
| 
 | |
| 
 | |
|     def set_rules(self):
 | |
|         Rules.set_rules(self)
 | |
| 
 | |
| 
 | |
|     def create_item(self, name: str) -> "Hylics2Item":
 | |
|         item_id: int = self.item_name_to_id[name]
 | |
| 
 | |
|         return Hylics2Item(name, self.all_items[item_id]["classification"], item_id, player=self.player)
 | |
| 
 | |
| 
 | |
|     def add_item(self, name: str, classification: ItemClassification, code: int) -> "Item":
 | |
|         return Hylics2Item(name, classification, code, self.player)
 | |
| 
 | |
| 
 | |
|     def create_event(self, event: str):
 | |
|         return Hylics2Item(event, ItemClassification.progression_skip_balancing, None, self.player)
 | |
| 
 | |
| 
 | |
|     # set random starting location if option is enabled
 | |
|     def generate_early(self):
 | |
|         if self.multiworld.random_start[self.player]:
 | |
|             i = self.multiworld.random.randint(0, 3)
 | |
|             if i == 0:
 | |
|                 self.start_location = "Waynehouse"
 | |
|             elif i == 1:
 | |
|                 self.start_location = "Viewax's Edifice"
 | |
|             elif i == 2:
 | |
|                 self.start_location = "TV Island"
 | |
|             elif i == 3:
 | |
|                 self.start_location = "Shield Facility"
 | |
| 
 | |
|     def create_items(self):
 | |
|         # create item pool
 | |
|         pool = []
 | |
| 
 | |
|         # add regular items
 | |
|         for i, data in Items.item_table.items():
 | |
|             if data["count"] > 0:
 | |
|                 for j in range(data["count"]):
 | |
|                     pool.append(self.add_item(data["name"], data["classification"], i))
 | |
| 
 | |
|         # add party members if option is enabled
 | |
|         if self.multiworld.party_shuffle[self.player]:
 | |
|             for i, data in Items.party_item_table.items():
 | |
|                 pool.append(self.add_item(data["name"], data["classification"], i))
 | |
| 
 | |
|         # handle gesture shuffle
 | |
|         if not self.multiworld.gesture_shuffle[self.player]: # add gestures to pool like normal
 | |
|             for i, data in Items.gesture_item_table.items():
 | |
|                 pool.append(self.add_item(data["name"], data["classification"], i))
 | |
| 
 | |
|         # add '10 Bones' items if medallion shuffle is enabled
 | |
|         if self.multiworld.medallion_shuffle[self.player]:
 | |
|             for i, data in Items.medallion_item_table.items():
 | |
|                 for j in range(data["count"]):
 | |
|                     pool.append(self.add_item(data["name"], data["classification"], i))
 | |
| 
 | |
|         # add to world's pool
 | |
|         self.multiworld.itempool += pool
 | |
| 
 | |
| 
 | |
|     def pre_fill(self):
 | |
|         # handle gesture shuffle options
 | |
|         if self.multiworld.gesture_shuffle[self.player] == 2: # vanilla locations
 | |
|             gestures = Items.gesture_item_table
 | |
|             self.multiworld.get_location("Waynehouse: TV", self.player)\
 | |
|                 .place_locked_item(self.add_item(gestures[200678]["name"], gestures[200678]["classification"], 200678))
 | |
|             self.multiworld.get_location("Afterlife: TV", self.player)\
 | |
|                 .place_locked_item(self.add_item(gestures[200683]["name"], gestures[200683]["classification"], 200683))
 | |
|             self.multiworld.get_location("New Muldul: TV", self.player)\
 | |
|                 .place_locked_item(self.add_item(gestures[200679]["name"], gestures[200679]["classification"], 200679))
 | |
|             self.multiworld.get_location("Viewax's Edifice: TV", self.player)\
 | |
|                 .place_locked_item(self.add_item(gestures[200680]["name"], gestures[200680]["classification"], 200680))
 | |
|             self.multiworld.get_location("TV Island: TV", self.player)\
 | |
|                 .place_locked_item(self.add_item(gestures[200681]["name"], gestures[200681]["classification"], 200681))
 | |
|             self.multiworld.get_location("Juice Ranch: TV", self.player)\
 | |
|                 .place_locked_item(self.add_item(gestures[200682]["name"], gestures[200682]["classification"], 200682))
 | |
|             self.multiworld.get_location("Foglast: TV", self.player)\
 | |
|                 .place_locked_item(self.add_item(gestures[200684]["name"], gestures[200684]["classification"], 200684))
 | |
|             self.multiworld.get_location("Drill Castle: TV", self.player)\
 | |
|                 .place_locked_item(self.add_item(gestures[200688]["name"], gestures[200688]["classification"], 200688))
 | |
|             self.multiworld.get_location("Sage Airship: TV", self.player)\
 | |
|                 .place_locked_item(self.add_item(gestures[200685]["name"], gestures[200685]["classification"], 200685))
 | |
| 
 | |
|         elif self.multiworld.gesture_shuffle[self.player] == 1: # TVs only
 | |
|             gestures = list(Items.gesture_item_table.items())
 | |
|             tvs = list(Locations.tv_location_table.items())
 | |
| 
 | |
|             # if Extra Items in Logic is enabled place CHARGE UP first and make sure it doesn't get
 | |
|             # placed at Sage Airship: TV
 | |
|             if self.multiworld.extra_items_in_logic[self.player]:
 | |
|                 tv = self.multiworld.random.choice(tvs)
 | |
|                 gest = gestures.index((200681, Items.gesture_item_table[200681]))
 | |
|                 while tv[1]["name"] == "Sage Airship: TV":
 | |
|                     tv = self.multiworld.random.choice(tvs)
 | |
|                 self.multiworld.get_location(tv[1]["name"], self.player)\
 | |
|                     .place_locked_item(self.add_item(gestures[gest][1]["name"], gestures[gest][1]["classification"],
 | |
|                     gestures[gest]))
 | |
|                 gestures.remove(gestures[gest])
 | |
|                 tvs.remove(tv)
 | |
| 
 | |
|             for i in range(len(gestures)):
 | |
|                 gest = self.multiworld.random.choice(gestures)
 | |
|                 tv = self.multiworld.random.choice(tvs)
 | |
|                 self.multiworld.get_location(tv[1]["name"], self.player)\
 | |
|                     .place_locked_item(self.add_item(gest[1]["name"], gest[1]["classification"], gest[1]))
 | |
|                 gestures.remove(gest)
 | |
|                 tvs.remove(tv)
 | |
| 
 | |
| 
 | |
|     def fill_slot_data(self) -> Dict[str, Any]:
 | |
|         slot_data: Dict[str, Any] = {
 | |
|             "party_shuffle": self.multiworld.party_shuffle[self.player].value,
 | |
|             "medallion_shuffle": self.multiworld.medallion_shuffle[self.player].value,
 | |
|             "random_start" : self.multiworld.random_start[self.player].value,
 | |
|             "start_location" : self.start_location,
 | |
|             "death_link": self.multiworld.death_link[self.player].value
 | |
|         }
 | |
|         return slot_data
 | |
| 
 | |
| 
 | |
|     def create_regions(self) -> None:
 | |
| 
 | |
|         region_table: Dict[int, Region] = {
 | |
|             0: Region("Menu", self.player, self.multiworld),
 | |
|             1: Region("Afterlife", self.player, self.multiworld),
 | |
|             2: Region("Waynehouse", self.player, self.multiworld),
 | |
|             3: Region("World", self.player, self.multiworld),
 | |
|             4: Region("New Muldul", self.player, self.multiworld),
 | |
|             5: Region("New Muldul Vault", self.player, self.multiworld),
 | |
|             6: Region("Viewax", self.player, self.multiworld, "Viewax's Edifice"),
 | |
|             7: Region("Airship", self.player, self.multiworld),
 | |
|             8: Region("Arcade Island", self.player, self.multiworld),
 | |
|             9: Region("TV Island", self.player, self.multiworld),
 | |
|             10: Region("Juice Ranch", self.player, self.multiworld),
 | |
|             11: Region("Shield Facility", self.player, self.multiworld),
 | |
|             12: Region("Worm Pod", self.player, self.multiworld),
 | |
|             13: Region("Foglast", self.player, self.multiworld),
 | |
|             14: Region("Drill Castle", self.player, self.multiworld),
 | |
|             15: Region("Sage Labyrinth", self.player, self.multiworld),
 | |
|             16: Region("Sage Airship", self.player, self.multiworld),
 | |
|             17: Region("Hylemxylem", self.player, self.multiworld)
 | |
|         }
 | |
| 
 | |
|         # create regions from table
 | |
|         for i, reg in region_table.items():
 | |
|             self.multiworld.regions.append(reg)
 | |
|             # get all exits per region
 | |
|             for j, exits in Exits.region_exit_table.items():
 | |
|                 if j == i:
 | |
|                     for k in exits:
 | |
|                         # create entrance and connect it to parent and destination regions
 | |
|                         ent = Entrance(self.player, k, reg)
 | |
|                         reg.exits.append(ent)
 | |
|                         if k == "New Game" and self.multiworld.random_start[self.player]:
 | |
|                             if self.start_location == "Waynehouse":
 | |
|                                 ent.connect(region_table[2])
 | |
|                             elif self.start_location == "Viewax's Edifice":
 | |
|                                 ent.connect(region_table[6])
 | |
|                             elif self.start_location == "TV Island":
 | |
|                                 ent.connect(region_table[9])
 | |
|                             elif self.start_location == "Shield Facility":
 | |
|                                 ent.connect(region_table[11])
 | |
|                         else:
 | |
|                             for name, num in Exits.exit_lookup_table.items():
 | |
|                                 if k == name:
 | |
|                                     ent.connect(region_table[num])
 | |
| 
 | |
|         # add regular locations
 | |
|         for i, data in Locations.location_table.items():
 | |
|             region_table[data["region"]].locations\
 | |
|                 .append(Hylics2Location(self.player, data["name"], i, region_table[data["region"]]))
 | |
|         for i, data in Locations.tv_location_table.items():
 | |
|             region_table[data["region"]].locations\
 | |
|                 .append(Hylics2Location(self.player, data["name"], i, region_table[data["region"]]))
 | |
| 
 | |
|         # add party member locations if option is enabled
 | |
|         if self.multiworld.party_shuffle[self.player]:
 | |
|             for i, data in Locations.party_location_table.items():
 | |
|                 region_table[data["region"]].locations\
 | |
|                     .append(Hylics2Location(self.player, data["name"], i, region_table[data["region"]]))
 | |
| 
 | |
|         # add medallion locations if option is enabled
 | |
|         if self.multiworld.medallion_shuffle[self.player]:
 | |
|             for i, data in Locations.medallion_location_table.items():
 | |
|                 region_table[data["region"]].locations\
 | |
|                     .append(Hylics2Location(self.player, data["name"], i, region_table[data["region"]]))
 | |
| 
 | |
|         # create location for beating the game and place Victory event there
 | |
|         loc = Location(self.player, "Defeat Gibby", None, self.multiworld.get_region("Hylemxylem", self.player))
 | |
|         loc.place_locked_item(self.create_event("Victory"))
 | |
|         set_rule(loc, lambda state: state._hylics2_has_upper_chamber_key(self.player)
 | |
|             and state._hylics2_has_vessel_room_key(self.player))
 | |
|         self.multiworld.get_region("Hylemxylem", self.player).locations.append(loc)
 | |
|         self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player)
 | |
| 
 | |
| 
 | |
| class Hylics2Location(Location):
 | |
|     game: str = "Hylics 2"
 | |
| 
 | |
| 
 | |
| class Hylics2Item(Item):
 | |
|     game: str = "Hylics 2"
 | 
