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:
@@ -954,30 +954,13 @@ if "Timespinner" in network_data_package["games"]:
|
||||
"Lab Glasses": "https://timespinnerwiki.com/mediawiki/images/4/4a/Lab_Glasses.png",
|
||||
"Eye Orb": "https://timespinnerwiki.com/mediawiki/images/a/a4/Eye_Orb.png",
|
||||
"Lab Coat": "https://timespinnerwiki.com/mediawiki/images/5/51/Lab_Coat.png",
|
||||
"Demon": "https://timespinnerwiki.com/mediawiki/images/f/f8/Familiar_Demon.png",
|
||||
"Demon": "https://timespinnerwiki.com/mediawiki/images/f/f8/Familiar_Demon.png",
|
||||
"Cube of Bodie": "https://timespinnerwiki.com/mediawiki/images/1/14/Menu_Icon_Stats.png"
|
||||
}
|
||||
|
||||
timespinner_location_ids = {
|
||||
"Present": [
|
||||
1337000, 1337001, 1337002, 1337003, 1337004, 1337005, 1337006, 1337007, 1337008, 1337009,
|
||||
1337010, 1337011, 1337012, 1337013, 1337014, 1337015, 1337016, 1337017, 1337018, 1337019,
|
||||
1337020, 1337021, 1337022, 1337023, 1337024, 1337025, 1337026, 1337027, 1337028, 1337029,
|
||||
1337030, 1337031, 1337032, 1337033, 1337034, 1337035, 1337036, 1337037, 1337038, 1337039,
|
||||
1337040, 1337041, 1337042, 1337043, 1337044, 1337045, 1337046, 1337047, 1337048, 1337049,
|
||||
1337050, 1337051, 1337052, 1337053, 1337054, 1337055, 1337056, 1337057, 1337058, 1337059,
|
||||
1337060, 1337061, 1337062, 1337063, 1337064, 1337065, 1337066, 1337067, 1337068, 1337069,
|
||||
1337070, 1337071, 1337072, 1337073, 1337074, 1337075, 1337076, 1337077, 1337078, 1337079,
|
||||
1337080, 1337081, 1337082, 1337083, 1337084, 1337085],
|
||||
"Past": [
|
||||
1337086, 1337087, 1337088, 1337089,
|
||||
1337090, 1337091, 1337092, 1337093, 1337094, 1337095, 1337096, 1337097, 1337098, 1337099,
|
||||
1337100, 1337101, 1337102, 1337103, 1337104, 1337105, 1337106, 1337107, 1337108, 1337109,
|
||||
1337110, 1337111, 1337112, 1337113, 1337114, 1337115, 1337116, 1337117, 1337118, 1337119,
|
||||
1337120, 1337121, 1337122, 1337123, 1337124, 1337125, 1337126, 1337127, 1337128, 1337129,
|
||||
1337130, 1337131, 1337132, 1337133, 1337134, 1337135, 1337136, 1337137, 1337138, 1337139,
|
||||
1337140, 1337141, 1337142, 1337143, 1337144, 1337145, 1337146, 1337147, 1337148, 1337149,
|
||||
1337150, 1337151, 1337152, 1337153, 1337154, 1337155,
|
||||
1337171, 1337172, 1337173, 1337174, 1337175],
|
||||
"Present": list(range(1337000, 1337085)),
|
||||
"Past": list(range(1337086, 1337175)),
|
||||
"Ancient Pyramid": [
|
||||
1337236,
|
||||
1337246, 1337247, 1337248, 1337249]
|
||||
@@ -985,26 +968,23 @@ if "Timespinner" in network_data_package["games"]:
|
||||
|
||||
slot_data = tracker_data.get_slot_data(team, player)
|
||||
if (slot_data["DownloadableItems"]):
|
||||
timespinner_location_ids["Present"] += [
|
||||
1337156, 1337157, 1337159,
|
||||
1337160, 1337161, 1337162, 1337163, 1337164, 1337165, 1337166, 1337167, 1337168, 1337169,
|
||||
1337170]
|
||||
timespinner_location_ids["Present"] += [1337156, 1337157] + list(range(1337159, 1337170))
|
||||
if (slot_data["Cantoran"]):
|
||||
timespinner_location_ids["Past"].append(1337176)
|
||||
if (slot_data["LoreChecks"]):
|
||||
timespinner_location_ids["Present"] += [
|
||||
1337177, 1337178, 1337179,
|
||||
1337180, 1337181, 1337182, 1337183, 1337184, 1337185, 1337186, 1337187]
|
||||
timespinner_location_ids["Past"] += [
|
||||
1337188, 1337189,
|
||||
1337190, 1337191, 1337192, 1337193, 1337194, 1337195, 1337196, 1337197, 1337198]
|
||||
timespinner_location_ids["Present"] += list(range(1337177, 1337187))
|
||||
timespinner_location_ids["Past"] += list(range(1337188, 1337198))
|
||||
if (slot_data["GyreArchives"]):
|
||||
timespinner_location_ids["Ancient Pyramid"] += [
|
||||
1337237, 1337238, 1337239,
|
||||
1337240, 1337241, 1337242, 1337243, 1337244, 1337245]
|
||||
timespinner_location_ids["Ancient Pyramid"] += list(range(1337237, 1337245))
|
||||
if (slot_data["PyramidStart"]):
|
||||
timespinner_location_ids["Ancient Pyramid"] += [
|
||||
1337233, 1337234, 1337235]
|
||||
if (slot_data["PureTorcher"]):
|
||||
timespinner_location_ids["Present"] += list(range(1337250, 1337352)) + list(range(1337422, 1337496)) + [1337506] + list(range(1337712, 1337779)) + [1337781, 1337782]
|
||||
timespinner_location_ids["Past"] += list(range(1337497, 1337505)) + list(range(1337507, 1337711)) + [1337780]
|
||||
timespinner_location_ids["Ancient Pyramid"] += list(range(1337369, 1337421))
|
||||
if (slot_data["GyreArchives"]):
|
||||
timespinner_location_ids["Ancient Pyramid"] += list(range(1337353, 1337368))
|
||||
|
||||
display_data = {}
|
||||
|
||||
|
||||
@@ -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