Timespinner: Adds Lantern Check flags, Missing Traps (#5188)
* Timespinner: Add Torch Flags * Add comment of all torch locations * Add gyre and dark forest lanterns * Add Ancient Pyramid * Don't make cube default progression * Add Emperors Tower * Add lake desolation, forest * Add lab * Add library, varndagroth * Add hangar * Add ramparts * Add Xarion * Add castle keep * Add royal towers * Add lake serene * Add remaining checks * Add missing region * Fix region names * Fix location id * Add traps to settings * Add restriction to elevator keycard torch * Set new traps to have quantity 0 by default * Scythe is now useful due to torch shredding * Add additional lantern * Un-disable missing lantern * Include location ids in tracker * Remove additional space * Fix paren * Add missing lantern * Remove tablet requirement for torches * Update filler V card * Fix brackets * Address feedback
This commit is contained in:
@@ -174,7 +174,7 @@ item_table: Dict[str, ItemData] = {
|
||||
'Corruption': ItemData('Orb Spell', 1337161),
|
||||
'Lightwall': ItemData('Orb Spell', 1337162, progression=True),
|
||||
'Bleak Ring': ItemData('Orb Passive', 1337163, useful=True),
|
||||
'Scythe Ring': ItemData('Orb Passive', 1337164),
|
||||
'Scythe Ring': ItemData('Orb Passive', 1337164, useful=True),
|
||||
'Pyro Ring': ItemData('Orb Passive', 1337165, progression=True),
|
||||
'Royal Ring': ItemData('Orb Passive', 1337166, progression=True),
|
||||
'Shield Ring': ItemData('Orb Passive', 1337167),
|
||||
@@ -208,9 +208,11 @@ item_table: Dict[str, ItemData] = {
|
||||
'Lab Access Research': ItemData('Lab Access', 1337196, progression=True),
|
||||
'Lab Access Dynamo': ItemData('Lab Access', 1337197, progression=True),
|
||||
'Drawbridge Key': ItemData('Key', 1337198, progression=True),
|
||||
# 1337199 Reserved
|
||||
'Cube of Bodie': ItemData('Relic', 1337199, progression=True),
|
||||
'Spider Trap': ItemData('Trap', 1337200, 0, trap=True),
|
||||
# 1337201 - 1337248 Reserved
|
||||
'Lights Out Trap': ItemData('Trap', 1337201, 0, trap=True),
|
||||
'Palm Punch Trap': ItemData('Trap', 1337202, 0, trap=True),
|
||||
# 1337203 - 1337248 Reserved
|
||||
'Max Sand': ItemData('Stat', 1337249, 14)
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,7 @@ class TimespinnerLogic:
|
||||
self.flag_eye_spy = bool(options and options.eye_spy)
|
||||
self.flag_unchained_keys = bool(options and options.unchained_keys)
|
||||
self.flag_prism_break = bool(options and options.prism_break)
|
||||
self.flag_find_the_flame = bool(options and options.find_the_flame)
|
||||
|
||||
if precalculated_weights:
|
||||
if self.flag_unchained_keys:
|
||||
@@ -93,6 +94,12 @@ class TimespinnerLogic:
|
||||
else:
|
||||
return True
|
||||
|
||||
def can_break_lanterns(self, state: CollectionState) -> bool:
|
||||
if self.flag_find_the_flame:
|
||||
return state.has('Cube of Bodie', self.player)
|
||||
else:
|
||||
return True
|
||||
|
||||
def can_kill_all_3_bosses(self, state: CollectionState) -> bool:
|
||||
if self.flag_prism_break:
|
||||
return state.has_all({'Laser Access M', 'Laser Access I', 'Laser Access A'}, self.player)
|
||||
|
||||
@@ -367,8 +367,8 @@ class TrapChance(Range):
|
||||
class Traps(OptionList):
|
||||
"""List of traps that may be in the item pool to find"""
|
||||
display_name = "Traps Types"
|
||||
valid_keys = { "Meteor Sparrow Trap", "Poison Trap", "Chaos Trap", "Neurotoxin Trap", "Bee Trap", "Throw Stun Trap", "Spider Trap" }
|
||||
default = [ "Meteor Sparrow Trap", "Poison Trap", "Chaos Trap", "Neurotoxin Trap", "Bee Trap", "Throw Stun Trap", "Spider Trap" ]
|
||||
valid_keys = { "Meteor Sparrow Trap", "Poison Trap", "Chaos Trap", "Neurotoxin Trap", "Bee Trap", "Throw Stun Trap", "Spider Trap", "Lights Out Trap", "Palm Punch Trap" }
|
||||
default = [ "Meteor Sparrow Trap", "Poison Trap", "Chaos Trap", "Neurotoxin Trap", "Bee Trap", "Throw Stun Trap", "Spider Trap", "Lights Out Trap", "Palm Punch Trap" ]
|
||||
|
||||
class PresentAccessWithWheelAndSpindle(Toggle):
|
||||
"""When inverted, allows using the refugee camp warp when both the Timespinner Wheel and Spindle is acquired."""
|
||||
@@ -399,6 +399,14 @@ class RoyalRoadblock(Toggle):
|
||||
"""The Royal Towers entrance door requires a royal orb (Plasma Orb, Plasma Geyser, or Royal Ring) to enter."""
|
||||
display_name = "Royal Roadblock"
|
||||
|
||||
class PureTorcher(Toggle):
|
||||
"""All lanterns contain checks. (Except tutorial)"""
|
||||
display_name = "Pure Torcher"
|
||||
|
||||
class FindTheFlame(Toggle):
|
||||
"""Lanterns in 'Pure Torcher' will not break without new item 'Cube of Bodie'."""
|
||||
display_name = "Find the Flame"
|
||||
|
||||
@dataclass
|
||||
class TimespinnerOptions(PerGameCommonOptions, DeathLinkMixin):
|
||||
start_with_jewelry_box: StartWithJewelryBox
|
||||
@@ -441,6 +449,8 @@ class TimespinnerOptions(PerGameCommonOptions, DeathLinkMixin):
|
||||
pyramid_start: PyramidStart
|
||||
gate_keep: GateKeep
|
||||
royal_roadblock: RoyalRoadblock
|
||||
pure_torcher: PureTorcher
|
||||
find_the_flame: FindTheFlame
|
||||
trap_chance: TrapChance
|
||||
traps: Traps
|
||||
|
||||
|
||||
@@ -28,9 +28,11 @@ def create_regions_and_locations(world: MultiWorld, player: int, options: Timesp
|
||||
create_region(world, player, locations_per_region, 'Sealed Caves (Sirens)'),
|
||||
create_region(world, player, locations_per_region, 'Military Fortress'),
|
||||
create_region(world, player, locations_per_region, 'Military Fortress (hangar)'),
|
||||
create_region(world, player, locations_per_region, 'The lab'),
|
||||
create_region(world, player, locations_per_region, 'The lab (power off)'),
|
||||
create_region(world, player, locations_per_region, 'Lab Entrance'),
|
||||
create_region(world, player, locations_per_region, 'Main Lab'),
|
||||
create_region(world, player, locations_per_region, 'Lab Research'),
|
||||
create_region(world, player, locations_per_region, 'The lab (upper)'),
|
||||
create_region(world, player, locations_per_region, 'Emperors tower (courtyard)'),
|
||||
create_region(world, player, locations_per_region, 'Emperors tower'),
|
||||
create_region(world, player, locations_per_region, 'Skeleton Shaft'),
|
||||
create_region(world, player, locations_per_region, 'Sealed Caves (Xarion)'),
|
||||
@@ -41,6 +43,7 @@ def create_regions_and_locations(world: MultiWorld, player: int, options: Timesp
|
||||
create_region(world, player, locations_per_region, 'Lower Lake Serene'),
|
||||
create_region(world, player, locations_per_region, 'Caves of Banishment (upper)'),
|
||||
create_region(world, player, locations_per_region, 'Caves of Banishment (Maw)'),
|
||||
create_region(world, player, locations_per_region, 'Caves of Banishment (Flooded)'),
|
||||
create_region(world, player, locations_per_region, 'Caves of Banishment (Sirens)'),
|
||||
create_region(world, player, locations_per_region, 'Castle Ramparts'),
|
||||
create_region(world, player, locations_per_region, 'Castle Keep'),
|
||||
@@ -109,16 +112,19 @@ def create_regions_and_locations(world: MultiWorld, player: int, options: Timesp
|
||||
connect(world, player, 'Military Fortress', 'Temporal Gyre', lambda state: state.has('Timespinner Wheel', player) and logic.can_kill_all_3_bosses(state))
|
||||
connect(world, player, 'Military Fortress', 'Military Fortress (hangar)', logic.has_doublejump)
|
||||
connect(world, player, 'Military Fortress (hangar)', 'Military Fortress')
|
||||
connect(world, player, 'Military Fortress (hangar)', 'The lab', lambda state: logic.has_keycard_B(state) and (state.has('Water Mask', player) if flooded.flood_lab else logic.has_doublejump(state)))
|
||||
connect(world, player, 'Military Fortress (hangar)', 'Lab Entrance', lambda state: state.has('Water Mask', player) if flooded.flood_lab else logic.has_doublejump(state))
|
||||
connect(world, player, 'Lab Entrance', 'Main Lab', lambda state: logic.has_keycard_B(state))
|
||||
connect(world, player, 'Main Lab', 'Lab Entrance')
|
||||
connect(world, player, 'Lab Entrance', 'Military Fortress (hangar)')
|
||||
connect(world, player, 'Temporal Gyre', 'Military Fortress')
|
||||
connect(world, player, 'The lab', 'Military Fortress')
|
||||
connect(world, player, 'The lab', 'The lab (power off)', lambda state: options.lock_key_amadeus or logic.has_doublejump_of_npc(state))
|
||||
connect(world, player, 'The lab (power off)', 'The lab', lambda state: not flooded.flood_lab or state.has('Water Mask', player))
|
||||
connect(world, player, 'The lab (power off)', 'The lab (upper)', lambda state: logic.has_forwarddash_doublejump(state) and ((not options.lock_key_amadeus) or state.has('Lab Access Genza', player)))
|
||||
connect(world, player, 'The lab (upper)', 'The lab (power off)', lambda state: options.lock_key_amadeus and state.has('Lab Access Genza', player))
|
||||
connect(world, player, 'The lab (upper)', 'Emperors tower', logic.has_forwarddash_doublejump)
|
||||
connect(world, player, 'Main Lab', 'Lab Research', lambda state: state.has('Lab Access Research', player) if options.lock_key_amadeus else logic.has_doublejump_of_npc(state))
|
||||
connect(world, player, 'Main Lab', 'The lab (upper)', lambda state: logic.has_forwarddash_doublejump(state) and ((not options.lock_key_amadeus) or state.has('Lab Access Genza', player)))
|
||||
connect(world, player, 'The lab (upper)', 'Main Lab', lambda state: options.lock_key_amadeus and state.has('Lab Access Genza', player))
|
||||
connect(world, player, 'The lab (upper)', 'Emperors tower (courtyard)', logic.has_forwarddash_doublejump)
|
||||
connect(world, player, 'The lab (upper)', 'Ancient Pyramid (entrance)', lambda state: state.has_all({'Timespinner Wheel', 'Timespinner Spindle', 'Timespinner Gear 1', 'Timespinner Gear 2', 'Timespinner Gear 3'}, player))
|
||||
connect(world, player, 'Emperors tower', 'The lab (upper)')
|
||||
connect(world, player, 'Emperors tower (courtyard)', 'The lab (upper)')
|
||||
connect(world, player, 'Emperors tower (courtyard)', 'Emperors tower', logic.has_doublejump)
|
||||
connect(world, player, 'Emperors tower', 'Emperors tower (courtyard)')
|
||||
connect(world, player, 'Skeleton Shaft', 'Lake desolation')
|
||||
connect(world, player, 'Skeleton Shaft', 'Sealed Caves (Xarion)', logic.has_keycard_A)
|
||||
connect(world, player, 'Skeleton Shaft', 'Space time continuum', logic.has_teleport)
|
||||
@@ -145,6 +151,7 @@ def create_regions_and_locations(world: MultiWorld, player: int, options: Timesp
|
||||
connect(world, player, 'Caves of Banishment (upper)', 'Space time continuum', logic.has_teleport)
|
||||
connect(world, player, 'Caves of Banishment (Maw)', 'Caves of Banishment (upper)', lambda state: logic.has_doublejump(state) if not flooded.flood_maw else state.has('Water Mask', player))
|
||||
connect(world, player, 'Caves of Banishment (Maw)', 'Caves of Banishment (Sirens)', lambda state: state.has_any({'Gas Mask', 'Talaria Attachment'}, player) )
|
||||
connect(world, player, 'Caves of Banishment (Maw)', 'Caves of Banishment (Flooded)', lambda state: flooded.flood_maw or state.has('Water Mask', player))
|
||||
connect(world, player, 'Caves of Banishment (Maw)', 'Space time continuum', logic.has_teleport)
|
||||
connect(world, player, 'Caves of Banishment (Sirens)', 'Forest')
|
||||
connect(world, player, 'Castle Ramparts', 'Forest')
|
||||
|
||||
@@ -132,6 +132,8 @@ class TimespinnerWorld(World):
|
||||
"PyramidStart": self.options.pyramid_start.value,
|
||||
"GateKeep": self.options.gate_keep.value,
|
||||
"RoyalRoadblock": self.options.royal_roadblock.value,
|
||||
"PureTorcher": self.options.pure_torcher.value,
|
||||
"FindTheFlame": self.options.find_the_flame.value,
|
||||
"Traps": self.options.traps.value,
|
||||
"DeathLink": self.options.death_link.value,
|
||||
"StinkyMaw": True,
|
||||
@@ -298,7 +300,9 @@ class TimespinnerWorld(World):
|
||||
if not item.advancement:
|
||||
return item
|
||||
|
||||
if (name == 'Tablet' or name == 'Library Keycard V') and not self.options.downloadable_items:
|
||||
if name == 'Tablet' and not self.options.downloadable_items:
|
||||
item.classification = ItemClassification.filler
|
||||
elif name == 'Library Keycard V' and not (self.options.downloadable_items or self.options.pure_torcher):
|
||||
item.classification = ItemClassification.filler
|
||||
elif name == 'Oculus Ring' and not self.options.eye_spy:
|
||||
item.classification = ItemClassification.filler
|
||||
@@ -315,6 +319,8 @@ class TimespinnerWorld(World):
|
||||
item.classification = ItemClassification.filler
|
||||
elif name == "Drawbridge Key" and not self.options.gate_keep:
|
||||
item.classification = ItemClassification.filler
|
||||
elif name == "Cube of Bodie" and not self.options.find_the_flame:
|
||||
item.classification = ItemClassification.filler
|
||||
|
||||
return item
|
||||
|
||||
@@ -361,6 +367,9 @@ class TimespinnerWorld(World):
|
||||
if not self.options.gate_keep:
|
||||
excluded_items.add('Drawbridge Key')
|
||||
|
||||
if not self.options.find_the_flame:
|
||||
excluded_items.add('Cube of Bodie')
|
||||
|
||||
for item in self.multiworld.precollected_items[self.player]:
|
||||
if item.name not in self.item_name_groups['UseItem']:
|
||||
excluded_items.add(item.name)
|
||||
|
||||
Reference in New Issue
Block a user