Files
dockipelago/worlds/sms/__init__.py
Jonathan Tinney 7971961166
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
add schedule I, sonic 1/frontiers/heroes, spirit island
2026-04-02 23:46:36 -07:00

174 lines
6.2 KiB
Python

"""
Archipelago init file for Super Mario Sunshine
"""
import random, math
from dataclasses import fields
from typing import Dict, Any
import os
import settings
from BaseClasses import ItemClassification, Tutorial
from worlds.AutoWorld import WebWorld, World
from worlds.LauncherComponents import Component, SuffixIdentifier, Type, components, launch_subprocess
from .items import ALL_ITEMS_TABLE, REGULAR_PROGRESSION_ITEMS, ALL_PROGRESSION_ITEMS, TICKET_ITEMS, JUNK_ITEMS, SmsItem
from .locations import ALL_LOCATIONS_TABLE
from .options import SmsOptions
from .regions import create_regions
from .iso_helper.sms_rom import SMSPlayerContainer
def run_client():
from .SMSClient import main
launch_subprocess(main)
components.append(
Component("Super Mario Sunshine Client", func=run_client, component_type=Type.CLIENT,
file_identifier=SuffixIdentifier(".apsms")))
class SuperMarioSunshineSettings(settings.Group):
class ISOFile(settings.UserFilePath):
description = "Super Mario Sunshine (USA) NTSC-U ISO File"
copy_to = None
iso_file: ISOFile = ISOFile(ISOFile.copy_to)
class SmsWebWorld(WebWorld):
theme = "ocean"
tutorials = [Tutorial(
"Multiworld Setup Guide",
"A guide to playing Super Mario Sunshine. This guide covers single-player, multiworld and related"
" software.",
"English",
"setup_en.md",
"setup/en",
["Black Sliver"]
)]
class SmsWorld(World):
"""
Tohrik made a mess and now he has to clean it up. Or maybe he didn't. Doesn't matter, CLEAN IT.
"""
game = "Super Mario Sunshine"
web = SmsWebWorld()
data_version = 1
options_dataclass = SmsOptions
options: SmsOptions
item_name_to_id = ALL_ITEMS_TABLE
location_name_to_id = ALL_LOCATIONS_TABLE
settings: SuperMarioSunshineSettings
corona_goal = 50
possible_shines = 0
def generate_early(self):
if self.options.starting_nozzle.value == 0:
self.options.start_inventory.value["Spray Nozzle"] = 1
elif self.options.starting_nozzle.value == 1:
self.options.start_inventory.value["Hover Nozzle"] = 1
if self.options.level_access.value == 1:
pick = random.choice(list(TICKET_ITEMS.keys()))
tick = str(pick)
print(tick)
self.options.start_inventory.value[tick] = 1
def create_regions(self):
create_regions(self)
def create_items(self):
pool = [self.create_item(name) for name in REGULAR_PROGRESSION_ITEMS.keys()]
if self.options.level_access == 1:
pool += [self.create_item(name) for name in TICKET_ITEMS.keys()]
if self.options.blue_coin_sanity == "full_shuffle":
for _ in range(0, self.options.blue_coin_maximum):
pool.append((self.create_item("Blue Coin")))
# Adds the minimum amount required of shines for Corona Mountain access
for _ in range(0, self.options.corona_mountain_shines):
pool.append(self.create_item("Shine Sprite"))
self.possible_shines += 1
extra_shines = math.floor(self.options.corona_mountain_shines * 0.30)
# Adds extra shines to the pool if possible
if (len(self.multiworld.get_unfilled_locations(self.player))) > 0:
for _ in range(0, min(len(self.multiworld.get_unfilled_locations(self.player)), extra_shines)):
pool.append(self.create_item("Shine Sprite"))
self.possible_shines += 1
if (len(self.multiworld.get_unfilled_locations(self.player))) > 0:
for _ in range(0, len(self.multiworld.get_unfilled_locations(self.player))):
pool.append(self.create_item(self.random.choice(list(JUNK_ITEMS.keys()))))
self.multiworld.itempool += pool
def create_item(self, name: str):
if name in ALL_PROGRESSION_ITEMS:
classification = ItemClassification.progression
else:
classification = ItemClassification.filler
return SmsItem(name, classification, ALL_ITEMS_TABLE[name], self.player)
def set_rules(self):
self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player)
self.corona_goal = min(self.options.corona_mountain_shines.value, self.possible_shines)
def fill_slot_data(self) -> Dict[str, Any]:
return {
"corona_mountain_shines": self.options.corona_mountain_shines.value,
"blue_coin_sanity": self.options.blue_coin_sanity.value,
"starting_nozzle": self.options.starting_nozzle.value,
"ticket_mode": self.options.level_access.value,
"boathouse_maximum": self.options.trade_shine_maximum.value,
"coin_shine_enabled": self.options.enable_coin_shines.value,
"death_link": self.options.death_link.value,
"seed": self.multiworld.seed
}
def generate_output(self, output_directory: str):
output_data = {
"Seed": self.multiworld.seed,
"Slot": self.player,
"Name": self.player_name,
"Options": {},
"0.6.5": "0.5.1"
}
for field in fields(self.options):
output_data["Options"][field.name] = getattr(self.options, field.name).value
patch_path = os.path.join(output_directory, f"{self.multiworld.get_out_file_name_base(self.player)}"
f"{SMSPlayerContainer.patch_file_ending}")
sms_container = SMSPlayerContainer(output_data, patch_path, self.multiworld.player_name[self.player], self.player)
sms_container.write()
# def launch_client():
# from .SMSClient import main
# launch_subprocess(main, name="SMS client")
# def add_client_to_launcher() -> None:
# version = "0.2.0"
# found = False
# for c in components:
# if c.display_name == "Super Mario Sunshine Client":
# found = True
# if getattr(c, "version", 0) < version:
# c.version = version
# c.func = launch_client
# return
# if not found:
# components.append(Component("Super Mario Sunshine Client", "SMSClient",
# func=launch_client))
# add_client_to_launcher()