 5935093615
			
		
	
	5935093615
	
	
	
		
			
			* Commit for PR * Commit for PR * Update worlds/mlss/Client.py Co-authored-by: Silvris <58583688+Silvris@users.noreply.github.com> * Update worlds/mlss/__init__.py Co-authored-by: Silvris <58583688+Silvris@users.noreply.github.com> * Update worlds/mlss/__init__.py Co-authored-by: Silvris <58583688+Silvris@users.noreply.github.com> * Update worlds/mlss/docs/setup_en.md Co-authored-by: Silvris <58583688+Silvris@users.noreply.github.com> * Remove deprecated import. Updated settings and romfile syntax * Updated Options to new system. Changed all references from MultiWorld to World * Changed switch statements to if else * Update en_Mario & Luigi Superstar Saga.md * Updated client.py * Update Client.py * Update worlds/mlss/docs/en_Mario & Luigi Superstar Saga.md Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com> * Updated logic, Updated patch implementation, Removed unused imports, Cleaned up Code * Update __init__.py * Changed reference from world to mlssworld * Update worlds/mlss/docs/en_Mario & Luigi Superstar Saga.md Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com> * Update worlds/mlss/docs/en_Mario & Luigi Superstar Saga.md Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com> * Update worlds/mlss/docs/en_Mario & Luigi Superstar Saga.md Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com> * Update worlds/mlss/docs/en_Mario & Luigi Superstar Saga.md Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com> * Update worlds/mlss/docs/en_Mario & Luigi Superstar Saga.md Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com> * Update worlds/mlss/docs/en_Mario & Luigi Superstar Saga.md Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com> * Fix merge conflict + update prep * v1.2 * Leftover print commands * Update basepatch.bsdiff * Update basepatch.bsdiff * v1.3 * Update Rom.py * Change tracker locations to serverside, no longer locations. Various code cleanup and logic changes. * Event removal continuation. * Partial Implementation of APPP (Incomplete)) * v1.4 Implemented APPP * Docs Updated * Update Rom.py * Update setup_en.md * Update Rom.py * Update Rules.py * Fix for APPP being broken on webhost * Update Rom.py * Update Rom.py * Location name fixes + pants color fixes * Update Rules.py * Fix for ultra hammer cutscene * Fixed compat. issues with python ver. 3.8 * Updated hidden block yaml option * pre-v1.5 * Update Client.py * Update basepatch.bsdiff * v1.5 * Update XP multiplier to have a minimum of 0 * Update 'Beanfruit' to 'Bean Fruit' * v1.6 * Update Rom.py * Update basepatch.bsdiff * Initial review refactor * Revert state logic changes. Continuation of refactor. * Fixed failed generations. Finished refactor. * Reworked colors. Removed all .txt files * Actually removed the .txt files this time * Update Rom.py * Update README.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mlss/Options.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mlss/Client.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mlss/docs/en_Mario & Luigi Superstar Saga.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mlss/__init__.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mlss/docs/en_Mario & Luigi Superstar Saga.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mlss/Data.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Review refactor. * Update README.md Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Update worlds/mlss/Rules.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * Add coin blocks to LocationName * Refactor. * Update Items.py * Delete mlss.apworld * Small asm bugfix * Update basepatch.bsdiff * Client sends less messages to server * Update basepatch.bsdiff --------- Co-authored-by: Silvris <58583688+Silvris@users.noreply.github.com> Co-authored-by: Nicholas Saylor <79181893+nicholassaylor@users.noreply.github.com> Co-authored-by: NewSoupVi <57900059+NewSoupVi@users.noreply.github.com> Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
		
			
				
	
	
		
			184 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import os
 | |
| import pkgutil
 | |
| import typing
 | |
| import settings
 | |
| from BaseClasses import Tutorial, ItemClassification
 | |
| from worlds.AutoWorld import WebWorld, World
 | |
| from typing import List, Dict, Any
 | |
| from .Locations import all_locations, location_table, bowsers, bowsersMini, hidden, coins
 | |
| from .Options import MLSSOptions
 | |
| from .Items import MLSSItem, itemList, item_frequencies, item_table
 | |
| from .Names.LocationName import LocationName
 | |
| from .Client import MLSSClient
 | |
| from .Regions import create_regions, connect_regions
 | |
| from .Rom import MLSSProcedurePatch, write_tokens
 | |
| from .Rules import set_rules
 | |
| 
 | |
| 
 | |
| class MLSSWebWorld(WebWorld):
 | |
|     theme = "partyTime"
 | |
|     bug_report_page = "https://github.com/jamesbrq/ArchipelagoMLSS/issues"
 | |
|     tutorials = [
 | |
|         Tutorial(
 | |
|             tutorial_name="Setup Guide",
 | |
|             description="A guide to setting up Mario & Luigi: Superstar Saga for Archipelago.",
 | |
|             language="English",
 | |
|             file_name="setup_en.md",
 | |
|             link="setup/en",
 | |
|             authors=["jamesbrq"],
 | |
|         )
 | |
|     ]
 | |
| 
 | |
| 
 | |
| class MLSSSettings(settings.Group):
 | |
|     class RomFile(settings.UserFilePath):
 | |
|         """File name of the MLSS US rom"""
 | |
| 
 | |
|         copy_to = "Mario & Luigi - Superstar Saga (U).gba"
 | |
|         description = "MLSS ROM File"
 | |
|         md5s = ["4b1a5897d89d9e74ec7f630eefdfd435"]
 | |
| 
 | |
|     rom_file: RomFile = RomFile(RomFile.copy_to)
 | |
|     rom_start: bool = True
 | |
| 
 | |
| 
 | |
| class MLSSWorld(World):
 | |
|     """
 | |
|     Adventure with Mario and Luigi together in the Beanbean Kingdom
 | |
|     to stop the evil Cackletta and retrieve the Beanstar.
 | |
|     """
 | |
| 
 | |
|     game = "Mario & Luigi Superstar Saga"
 | |
|     web = MLSSWebWorld()
 | |
|     options_dataclass = MLSSOptions
 | |
|     options: MLSSOptions
 | |
|     settings: typing.ClassVar[MLSSSettings]
 | |
|     item_name_to_id = {name: data.code for name, data in item_table.items()}
 | |
|     location_name_to_id = {loc_data.name: loc_data.id for loc_data in all_locations}
 | |
|     required_client_version = (0, 4, 5)
 | |
| 
 | |
|     disabled_locations: List[str]
 | |
| 
 | |
|     def generate_early(self) -> None:
 | |
|         self.disabled_locations = []
 | |
|         if self.options.chuckle_beans == 0:
 | |
|             self.disabled_locations += [location.name for location in all_locations if "Digspot" in location.name]
 | |
|         if self.options.castle_skip:
 | |
|             self.disabled_locations += [location.name for location in all_locations if "Bowser" in location.name]
 | |
|         if self.options.chuckle_beans == 1:
 | |
|             self.disabled_locations = [location.name for location in all_locations if location.id in hidden]
 | |
|         if self.options.skip_minecart:
 | |
|             self.disabled_locations += [LocationName.HoohooMountainBaseMinecartCaveDigspot]
 | |
|         if self.options.disable_surf:
 | |
|             self.disabled_locations += [LocationName.SurfMinigame]
 | |
|         if self.options.harhalls_pants:
 | |
|             self.disabled_locations += [LocationName.HarhallsPants]
 | |
|         if not self.options.coins:
 | |
|             self.disabled_locations += [location.name for location in all_locations if location in coins]
 | |
| 
 | |
|     def create_regions(self) -> None:
 | |
|         create_regions(self, self.disabled_locations)
 | |
|         connect_regions(self)
 | |
| 
 | |
|         item = self.create_item("Mushroom")
 | |
|         self.get_location(LocationName.ShopStartingFlag1).place_locked_item(item)
 | |
|         item = self.create_item("Syrup")
 | |
|         self.get_location(LocationName.ShopStartingFlag2).place_locked_item(item)
 | |
|         item = self.create_item("1-UP Mushroom")
 | |
|         self.get_location(LocationName.ShopStartingFlag3).place_locked_item(item)
 | |
|         item = self.create_item("Hoo Bean")
 | |
|         self.get_location(LocationName.PantsShopStartingFlag1).place_locked_item(item)
 | |
|         item = self.create_item("Chuckle Bean")
 | |
|         self.get_location(LocationName.PantsShopStartingFlag2).place_locked_item(item)
 | |
| 
 | |
|     def fill_slot_data(self) -> Dict[str, Any]:
 | |
|         return {
 | |
|             "CastleSkip": self.options.castle_skip.value,
 | |
|             "SkipMinecart": self.options.skip_minecart.value,
 | |
|             "DisableSurf": self.options.disable_surf.value,
 | |
|             "HarhallsPants": self.options.harhalls_pants.value,
 | |
|             "ChuckleBeans": self.options.chuckle_beans.value,
 | |
|             "DifficultLogic": self.options.difficult_logic.value,
 | |
|             "Coins": self.options.coins.value,
 | |
|         }
 | |
| 
 | |
|     def create_items(self) -> None:
 | |
|         # First add in all progression and useful items
 | |
|         required_items = []
 | |
|         precollected = [item for item in itemList if item in self.multiworld.precollected_items]
 | |
|         for item in itemList:
 | |
|             if item.classification != ItemClassification.filler and item.classification != ItemClassification.skip_balancing:
 | |
|                 freq = item_frequencies.get(item.itemName, 1)
 | |
|                 if item in precollected:
 | |
|                     freq = max(freq - precollected.count(item), 0)
 | |
|                 if self.options.harhalls_pants and "Harhall's" in item.itemName:
 | |
|                     continue
 | |
|                 required_items += [item.itemName for _ in range(freq)]
 | |
| 
 | |
|         for itemName in required_items:
 | |
|             self.multiworld.itempool.append(self.create_item(itemName))
 | |
| 
 | |
|         # Then, create our list of filler items
 | |
|         filler_items = []
 | |
|         for item in itemList:
 | |
|             if item.classification != ItemClassification.filler:
 | |
|                 continue
 | |
|             if item.itemName == "5 Coins" and not self.options.coins:
 | |
|                 continue
 | |
|             freq = item_frequencies.get(item.itemName, 1)
 | |
|             if self.options.chuckle_beans == 0:
 | |
|                 if item.itemName == "Chuckle Bean":
 | |
|                     continue
 | |
|             if self.options.chuckle_beans == 1:
 | |
|                 if item.itemName == "Chuckle Bean":
 | |
|                     freq -= 59
 | |
|             filler_items += [item.itemName for _ in range(freq)]
 | |
| 
 | |
|         # And finally take as many fillers as we need to have the same amount of items and locations.
 | |
|         remaining = len(all_locations) - len(required_items) - 5
 | |
|         if self.options.castle_skip:
 | |
|             remaining -= len(bowsers) + len(bowsersMini) - (5 if self.options.chuckle_beans == 0 else 0)
 | |
|         if self.options.skip_minecart and self.options.chuckle_beans == 2:
 | |
|             remaining -= 1
 | |
|         if self.options.disable_surf:
 | |
|             remaining -= 1
 | |
|         if self.options.harhalls_pants:
 | |
|             remaining -= 1
 | |
|         if self.options.chuckle_beans == 0:
 | |
|             remaining -= 192
 | |
|         if self.options.chuckle_beans == 1:
 | |
|             remaining -= 59
 | |
|         if not self.options.coins:
 | |
|             remaining -= len(coins)
 | |
| 
 | |
|         self.multiworld.itempool += [
 | |
|             self.create_item(filler_item_name) for filler_item_name in self.random.sample(filler_items, remaining)
 | |
|         ]
 | |
| 
 | |
|     def set_rules(self) -> None:
 | |
|         set_rules(self, self.disabled_locations)
 | |
|         if self.options.castle_skip:
 | |
|             self.multiworld.completion_condition[self.player] = lambda state: state.can_reach(
 | |
|                 "PostJokes", "Region", self.player
 | |
|             )
 | |
|         else:
 | |
|             self.multiworld.completion_condition[self.player] = lambda state: state.can_reach(
 | |
|                 "Bowser's Castle Mini", "Region", self.player
 | |
|             )
 | |
| 
 | |
|     def create_item(self, name: str) -> MLSSItem:
 | |
|         item = item_table[name]
 | |
|         return MLSSItem(item.itemName, item.classification, item.code, self.player)
 | |
| 
 | |
|     def get_filler_item_name(self) -> str:
 | |
|         return self.random.choice(list(filter(lambda item: item.classification == ItemClassification.filler, itemList)))
 | |
| 
 | |
|     def generate_output(self, output_directory: str) -> None:
 | |
|         patch = MLSSProcedurePatch(player=self.player, player_name=self.multiworld.player_name[self.player])
 | |
|         patch.write_file("base_patch.bsdiff4", pkgutil.get_data(__name__, "data/basepatch.bsdiff"))
 | |
|         write_tokens(self, patch)
 | |
|         rom_path = os.path.join(
 | |
|             output_directory, f"{self.multiworld.get_out_file_name_base(self.player)}" f"{patch.patch_file_ending}"
 | |
|         )
 | |
|         patch.write(rom_path)
 |