[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:
parent
5e1aa52373
commit
942d689093
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue