forked from mirror/Archipelago
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
174 lines
6.2 KiB
Python
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()
|