[Slay the Spire] Enable support for modded characters, and add downfall support (#1368)

* add ability to choose custom characters in STS

* bump required protocol (client?) version.

* fix slot data fill.

* add downfall mode, as well as characters.

* small change in documentation for character choice as it now uses internal ID's instead of visible titles... because other languages are a thing.
This commit is contained in:
KonoTyran 2023-03-08 20:14:54 -08:00 committed by GitHub
parent 5e1aa52373
commit 942d689093
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 24 deletions

View File

@ -1,15 +1,34 @@
import typing import typing
from Options import Choice, Option, Range, Toggle from Options import TextChoice, Option, Range, Toggle
class Character(Choice): class Character(TextChoice):
"""Pick What Character you wish to play with.""" """Enter the internal ID of the character to use.
if you don't know the exact ID to enter with the mod installed go to
`Mods -> Archipelago Multi-world -> config` to view a list of installed modded character IDs.
the downfall characters will only work if you have downfall installed.
Spire Take the Wheel will have your client pick a random character from the list of all your installed characters
including custom ones.
if the chosen character mod is not installed it will default back to 'The Ironclad'
"""
display_name = "Character" display_name = "Character"
option_ironclad = 0 option_The_Ironclad = 0
option_silent = 1 option_The_Silent = 1
option_defect = 2 option_The_Defect = 2
option_watcher = 3 option_The_Watcher = 3
default = 0 option_The_Hermit = 4
option_The_Slime_Boss = 5
option_The_Guardian = 6
option_The_Hexaghost = 7
option_The_Champ = 8
option_The_Gremlins = 9
option_The_Automaton = 10
option_The_Snecko = 11
option_spire_take_the_wheel = 12
class Ascension(Range): class Ascension(Range):
@ -20,10 +39,17 @@ class Ascension(Range):
default = 0 default = 0
class HeartRun(Toggle): class FinalAct(Toggle):
"""Whether or not you will need to collect the 3 keys and enter the final act to """Whether you will need to collect the 3 keys and beat the final act to complete the game."""
complete the game. The Heart does not need to be defeated.""" display_name = "Final Act"
display_name = "Heart Run" option_true = 1
option_false = 0
default = 0
class Downfall(Toggle):
"""When Downfall is Installed this will switch the played mode to Downfall"""
display_name = "Downfall"
option_true = 1 option_true = 1
option_false = 0 option_false = 0
default = 0 default = 0
@ -32,5 +58,6 @@ class HeartRun(Toggle):
spire_options: typing.Dict[str, type(Option)] = { spire_options: typing.Dict[str, type(Option)] = {
"character": Character, "character": Character,
"ascension": Ascension, "ascension": Ascension,
"heart_run": HeartRun "final_act": FinalAct,
"downfall": Downfall,
} }

View File

@ -32,18 +32,11 @@ class SpireWorld(World):
topology_present = False topology_present = False
data_version = 1 data_version = 1
web = SpireWeb() web = SpireWeb()
required_client_version = (0, 3, 7)
item_name_to_id = {name: data.code for name, data in item_table.items()} item_name_to_id = {name: data.code for name, data in item_table.items()}
location_name_to_id = location_table location_name_to_id = location_table
def _get_slot_data(self):
return {
'seed': "".join(self.multiworld.per_slot_randoms[self.player].choice(string.ascii_letters) for i in range(16)),
'character': self.multiworld.character[self.player],
'ascension': self.multiworld.ascension[self.player],
'heart_run': self.multiworld.heart_run[self.player]
}
def generate_basic(self): def generate_basic(self):
# Fill out our pool with our items from item_pool, assuming 1 item if not present in item_pool # Fill out our pool with our items from item_pool, assuming 1 item if not present in item_pool
pool = [] pool = []
@ -63,7 +56,6 @@ class SpireWorld(World):
if self.multiworld.logic[self.player] != 'no logic': if self.multiworld.logic[self.player] != 'no logic':
self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player) self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player)
def set_rules(self): def set_rules(self):
set_rules(self.multiworld, self.player) set_rules(self.multiworld, self.player)
@ -74,10 +66,12 @@ class SpireWorld(World):
create_regions(self.multiworld, self.player) create_regions(self.multiworld, self.player)
def fill_slot_data(self) -> dict: def fill_slot_data(self) -> dict:
slot_data = self._get_slot_data() slot_data = {
'seed': "".join(self.multiworld.slot_seeds[self.player].choice(string.ascii_letters) for i in range(16))
}
for option_name in spire_options: for option_name in spire_options:
option = getattr(self.multiworld, option_name)[self.player] option = getattr(self.multiworld, option_name)[self.player]
slot_data[option_name] = int(option.value) slot_data[option_name] = option.value
return slot_data return slot_data
def get_filler_item_name(self) -> str: def get_filler_item_name(self) -> str: