diff --git a/WebHostLib/templates/timespinnerTracker.html b/WebHostLib/templates/timespinnerTracker.html
index 197b844d..f8d9c453 100644
--- a/WebHostLib/templates/timespinnerTracker.html
+++ b/WebHostLib/templates/timespinnerTracker.html
@@ -38,26 +38,29 @@
 |
- {% if 'Fire Orb' in acquired_items %}
+  |
+  |
+
+ {% if 'Djinn Inferno' in acquired_items %}
+  |
+ {% elif 'Pyro Ring' in acquired_items %}
+  |
+ {% elif 'Fire Orb' in acquired_items %}
 |
{% elif 'Infernal Flames' in acquired_items %}
 |
- {% elif 'Pyro Ring' in acquired_items %}
-  |
- {% elif 'Pyro Ring' in acquired_items %}
-  |
{% else %}
-  |
+  |
{% endif %}
- {% if 'Plasma Orb' in acquired_items %}
-  |
+ {% if 'Royal Ring' in acquired_items %}
+  |
{% elif 'Plasma Geyser' in acquired_items %}
 |
- {% elif 'Royal Ring' in acquired_items %}
-  |
+ {% elif 'Plasma Orb' in acquired_items %}
+  |
{% else %}
-  |
+  |
{% endif %}
diff --git a/WebHostLib/tracker.py b/WebHostLib/tracker.py
index 47def5ec..567257bf 100644
--- a/WebHostLib/tracker.py
+++ b/WebHostLib/tracker.py
@@ -712,6 +712,8 @@ def __renderTimespinnerTracker(multisave: Dict[str, Any], room: Room, locations:
"Royal Ring": "https://timespinnerwiki.com/mediawiki/images/f/f3/Royal_Ring.png",
"Plasma Geyser": "https://timespinnerwiki.com/mediawiki/images/1/12/Plasma_Geyser.png",
"Plasma Orb": "https://timespinnerwiki.com/mediawiki/images/4/44/Plasma_Orb.png",
+ "Kobo": "https://timespinnerwiki.com/mediawiki/images/c/c6/Familiar_Kobo.png",
+ "Merchant Crow": "https://timespinnerwiki.com/mediawiki/images/4/4e/Familiar_Crow.png",
}
timespinner_location_ids = {
@@ -726,7 +728,7 @@ def __renderTimespinnerTracker(multisave: Dict[str, Any], room: Room, locations:
1337070, 1337071, 1337072, 1337073, 1337074, 1337075, 1337076, 1337077, 1337078, 1337079,
1337080, 1337081, 1337082, 1337083, 1337084, 1337085, 1337156, 1337157, 1337159,
1337160, 1337161, 1337162, 1337163, 1337164, 1337165, 1337166, 1337167, 1337168, 1337169,
- 1337170],
+ 1337170, 1337237, 1337238],
"Past": [
1337086, 1337087, 1337088, 1337089,
1337090, 1337091, 1337092, 1337093, 1337094, 1337095, 1337096, 1337097, 1337098, 1337099,
@@ -735,7 +737,8 @@ def __renderTimespinnerTracker(multisave: Dict[str, Any], room: Room, locations:
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],
+ 1337150, 1337151, 1337152, 1337153, 1337154, 1337155,
+ 1337171, 1337172, 1337173, 1337174, 1337175, 1337176],
"Ancient Pyramid": [1337246, 1337247, 1337248, 1337249]
}
diff --git a/worlds/timespinner/Items.py b/worlds/timespinner/Items.py
index ada37630..82958eba 100644
--- a/worlds/timespinner/Items.py
+++ b/worlds/timespinner/Items.py
@@ -24,9 +24,9 @@ item_table: Dict[str, ItemData] = {
'Lab Glasses': ItemData('Equipment', 1337012),
'Empire Crown': ItemData('Equipment', 1337013),
'Viletian Crown': ItemData('Equipment', 1337014),
- 'Sunglasses': ItemData('Equipment', 1337015, 0),
+ 'Sunglasses': ItemData('Equipment', 1337015),
'Old Coat': ItemData('Equipment', 1337016),
- 'Trendy Jacket': ItemData('Equipment', 1337017, 0),
+ 'Trendy Jacket': ItemData('Equipment', 1337017),
'Security Vest': ItemData('Equipment', 1337018, 0),
'Leather Jerkin': ItemData('Equipment', 1337019, 0),
'Copper Breastplate': ItemData('Equipment', 1337020, 0),
@@ -53,15 +53,15 @@ item_table: Dict[str, ItemData] = {
'Filigree Clasp': ItemData('Equipment', 1337041),
'Azure Stole': ItemData('Equipment', 1337042, 0),
'Ancient Coin': ItemData('Equipment', 1337043),
- 'Shiny Rock': ItemData('Equipment', 1337044, 0),
+ 'Shiny Rock': ItemData('Equipment', 1337044),
'Galaxy Earrings': ItemData('Equipment', 1337045, never_exclude=True),
'Selen\'s Bangle': ItemData('Equipment', 1337046, never_exclude=True),
'Glass Pumpkin': ItemData('Equipment', 1337047, never_exclude=True),
'Gilded Egg': ItemData('Equipment', 1337048, never_exclude=True),
'Meyef': ItemData('Familiar', 1337049),
'Griffin': ItemData('Familiar', 1337050),
- 'Merchant Crow': ItemData('Familiar', 1337051),
- 'Kobo': ItemData('Familiar', 1337052),
+ 'Merchant Crow': ItemData('Familiar', 1337051, progression=True),
+ 'Kobo': ItemData('Familiar', 1337052, progression=True),
'Sprite': ItemData('Familiar', 1337053),
'Demon': ItemData('Familiar', 1337054),
'Potion': ItemData('UseItem', 1337055, 0),
@@ -93,7 +93,7 @@ item_table: Dict[str, ItemData] = {
'Filigree Tea': ItemData('UseItem', 1337081),
'Empress Cake': ItemData('UseItem', 1337082, 0),
'Rotten Tail': ItemData('UseItem', 1337083, 0),
- 'Alchemy Tools': ItemData('UseItem', 1337084, 0),
+ 'Alchemy Tools': ItemData('UseItem', 1337084),
'Galaxy Stone': ItemData('UseItem', 1337085),
# 1337086 Used interally
'Essence Crystal': ItemData('UseItem', 1337087, 0),
@@ -101,7 +101,7 @@ item_table: Dict[str, ItemData] = {
'Gold Necklace': ItemData('UseItem', 1337089, 0),
'Herb': ItemData('UseItem', 1337090),
'Mushroom': ItemData('UseItem', 1337091, 0),
- 'Plasma Crystal': ItemData('UseItem', 1337092, 0),
+ 'Plasma Crystal': ItemData('UseItem', 1337092),
'Plasma IV Bag': ItemData('UseItem', 1337093),
'Cheveur Drumstick': ItemData('UseItem', 1337094, 0),
'Wyvern Tail': ItemData('UseItem', 1337095, 0),
diff --git a/worlds/timespinner/Locations.py b/worlds/timespinner/Locations.py
index 5cc107da..921e215e 100644
--- a/worlds/timespinner/Locations.py
+++ b/worlds/timespinner/Locations.py
@@ -1,4 +1,4 @@
-from typing import Tuple, Optional, Callable, NamedTuple
+from typing import List, Tuple, Optional, Callable, NamedTuple
from BaseClasses import MultiWorld
from .Options import is_option_enabled
@@ -11,7 +11,7 @@ class LocationData(NamedTuple):
rule: Callable = lambda state: True
def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[LocationData, ...]:
- location_table: Tuple[LocationData, ...] = (
+ location_table: List[LocationData] = [
# PresentItemLocations
LocationData('Tutorial', 'Yo Momma 1', 1337000),
LocationData('Tutorial', 'Yo Momma 2', 1337001),
@@ -29,8 +29,8 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
LocationData('Upper lake desolation', 'Upper desolation double jump cave platform', 1337013),
LocationData('Upper lake desolation', 'Fire-Locked sparrow chest', 1337014),
LocationData('Upper lake desolation', 'Crash site pedestal', 1337015),
- LocationData('Upper lake desolation', 'Crash site chest 1', 1337016, lambda state: state.has_all(['Killed Maw', 'Gas Mask'], player)),
- LocationData('Upper lake desolation', 'Crash site chest 2', 1337017, lambda state: state.has_all(['Killed Maw', 'Gas Mask'], player)),
+ LocationData('Upper lake desolation', 'Crash site chest 1', 1337016, lambda state: state.has_all({'Killed Maw', 'Gas Mask'}, player)),
+ LocationData('Upper lake desolation', 'Crash site chest 2', 1337017, lambda state: state.has_all({'Killed Maw', 'Gas Mask'}, player)),
LocationData('Upper lake desolation', 'Kitty Boss', 1337018),
LocationData('Library', 'Library Basement', 1337019),
LocationData('Library', 'Library warp gate', 1337020),
@@ -118,8 +118,10 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
LocationData('Upper Lake Serene', 'Upper Serene double jump cave platform', 1337100, lambda state: state._timespinner_has_doublejump(world, player)),
LocationData('Upper Lake Serene', 'Upper Serene double jump cave floor', 1337101),
LocationData('Upper Lake Serene', 'Upper Serene cave secret', 1337102, lambda state: state._timespinner_can_break_walls(world, player)),
+ LocationData('Upper Lake Serene', 'Before Big Bird', 1337175),
LocationData('Upper Lake Serene', 'Serene behind the vines', 1337103),
LocationData('Upper Lake Serene', 'Pyramid keys room', 1337104),
+ LocationData('Upper Lake Serene', 'Chicken ledge', 1337174),
LocationData('Lower Lake Serene', 'Deep dive', 1337105),
LocationData('Lower Lake Serene', 'Under the eels', 1337106),
LocationData('Lower Lake Serene', 'Water spikes room', 1337107),
@@ -137,12 +139,14 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
LocationData('Caves of Banishment (upper)', 'Banishment jackpot room chest 4', 1337119, lambda state: state._timespinner_has_forwarddash_doublejump(world, player)),
LocationData('Caves of Banishment (upper)', 'Banishment pedestal', 1337120),
LocationData('Caves of Banishment (Maw)', 'Last chance before Maw', 1337121, lambda state: state._timespinner_has_doublejump(world, player)),
+ LocationData('Caves of Banishment (Maw)', 'Plasma Crystal', 1337173, lambda state: state.has_any({'Gas Mask', 'Talaria Attachment'}, player)),
LocationData('Caves of Banishment (Maw)', 'Killed Maw', EventId, lambda state: state.has('Gas Mask', player)),
LocationData('Caves of Banishment (Maw)', 'Mineshaft', 1337122, lambda state: state.has('Gas Mask', player)),
LocationData('Caves of Banishment (Sirens)', 'Wyvern room', 1337123),
LocationData('Caves of Banishment (Sirens)', 'Upper banishment above sirens', 1337124),
LocationData('Caves of Banishment (Sirens)', 'Under banishment sirens left', 1337125, lambda state: state.has('Water Mask', player)),
LocationData('Caves of Banishment (Sirens)', 'Under banishment sirens right', 1337126, lambda state: state.has('Water Mask', player)),
+ LocationData('Caves of Banishment (Sirens)', 'Underwater banishment sirens right ground', 1337172, lambda state: state.has('Water Mask', player)),
LocationData('Caves of Banishment (Sirens)', 'Banishment water hook', 1337127, lambda state: state.has('Water Mask', player)),
LocationData('Castle Ramparts', 'Castle bomber chest', 1337128, lambda state: state._timespinner_has_multiple_small_jumps_of_npc(world, player)),
LocationData('Castle Ramparts', 'Ramparts Freeze the engineer', 1337129, lambda state: state.has('Talaria Attachment', player) or state._timespinner_has_timestop(world, player)),
@@ -157,6 +161,7 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
LocationData('Castle Keep', 'Just an egg', 1337138),
LocationData('Castle Keep', 'Under the twins', 1337139),
LocationData('Castle Keep', 'Killed Twins', EventId, lambda state: state._timespinner_has_timestop(world, player)),
+ LocationData('Castle Keep', 'Advisor jump', 1337171, lambda state: state._timespinner_has_timestop(world, player)),
LocationData('Castle Keep', 'Twins', 1337140, lambda state: state._timespinner_has_timestop(world, player)),
LocationData('Castle Keep', 'Royal guard tiny room', 1337141, lambda state: state._timespinner_has_doublejump(world, player) or state._timespinner_has_fastjump_on_npc(world,player)),
LocationData('Royal towers (lower)', 'Royal tower floor secret', 1337142, lambda state: state._timespinner_has_doublejump(world, player) and state._timespinner_can_break_walls(world, player)),
@@ -175,34 +180,35 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
LocationData('Royal towers (upper)', 'Aelana\'s pedestal', 1337154),
LocationData('Royal towers (upper)', 'Aelana\'s chest', 1337155),
- # 1337157 - 1337170 Downloads
+ # 1337176 - 1337176 Cantoran
- # 1337171 - 1337238 Reserved
+ # 1337177 - 1337236 Reserved
+
+ # 1337237 - 1337238 GyreArchives
# PyramidItemLocations
- #LocationData('Temporal Gyre', 'Transition chest 1', 1337239),
- #LocationData('Temporal Gyre', 'Transition chest 2', 1337240),
- #LocationData('Temporal Gyre', 'Transition chest 3', 1337241),
- #LocationData('Temporal Gyre', 'Ravenlord pre fight', 1337242),
- #LocationData('Temporal Gyre', 'Ravenlord post fight', 1337243),
- #LocationData('Temporal Gyre', 'Ifrid pre fight', 1337244),
- #LocationData('Temporal Gyre', 'Ifrid post fight', 1337245),
+ LocationData('Ancient Pyramid (right)', 'Transition chest 1', 1337239),
+ LocationData('Ancient Pyramid (right)', 'Transition chest 2', 1337240),
+ LocationData('Ancient Pyramid (right)', 'Transition chest 3', 1337241),
+
+ # 1337242 - 1337245 GyreArchives
+
LocationData('Ancient Pyramid (left)', 'Why not it\'s right there', 1337246),
LocationData('Ancient Pyramid (left)', 'Conviction guarded room', 1337247),
LocationData('Ancient Pyramid (right)', 'Pit secret room', 1337248, lambda state: state._timespinner_can_break_walls(world, player)),
LocationData('Ancient Pyramid (right)', 'Regret chest', 1337249, lambda state: state._timespinner_can_break_walls(world, player)),
LocationData('Ancient Pyramid (right)', 'Killed Nightmare', EventId)
- )
+ ]
- downloadable_items: Tuple[LocationData, ...] = (
+ downloadable_locations: Tuple[LocationData, ...] = (
# DownloadTerminals
LocationData('Library', 'Library terminal 1', 1337157, lambda state: state.has('Tablet', player)),
LocationData('Library', 'Library terminal 2', 1337156, lambda state: state.has('Tablet', player)),
# 1337158 Is Lost in time
LocationData('Library', 'Library terminal 3', 1337159, lambda state: state.has('Tablet', player)),
- LocationData('Library', 'V terminal 1', 1337160, lambda state: state.has_all(['Tablet', 'Library Keycard V'], player)),
- LocationData('Library', 'V terminal 2', 1337161, lambda state: state.has_all(['Tablet', 'Library Keycard V'], player)),
- LocationData('Library', 'V terminal 3', 1337162, lambda state: state.has_all(['Tablet', 'Library Keycard V'], player)),
+ LocationData('Library', 'V terminal 1', 1337160, lambda state: state.has_all({'Tablet', 'Library Keycard V'}, player)),
+ LocationData('Library', 'V terminal 2', 1337161, lambda state: state.has_all({'Tablet', 'Library Keycard V'}, player)),
+ LocationData('Library', 'V terminal 3', 1337162, lambda state: state.has_all({'Tablet', 'Library Keycard V'}, player)),
LocationData('Library top', 'Backer room terminal', 1337163, lambda state: state.has('Tablet', player)),
LocationData('Varndagroth tower right (elevator)', 'Medbay', 1337164, lambda state: state.has('Tablet', player) and state._timespinner_has_keycard_B(world, player)),
LocationData('The lab (upper)', 'Chest and download terminal', 1337165, lambda state: state.has('Tablet', player)),
@@ -213,10 +219,30 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
LocationData('The lab (power off)', 'Lab terminal right', 1337170, lambda state: state.has('Tablet', player))
)
- if not world or is_option_enabled(world, player, "DownloadableItems"):
- return ( *location_table, *downloadable_items )
- else:
- return location_table
+ gyre_archives_locations: Tuple[LocationData, ...] = (
+ LocationData('The lab (upper)', 'Ravenlord post fight (pedestal)', 1337237, lambda state: state.has('Merchant Crow', player)),
+ LocationData('Library top', 'Ifrit post fight (pedestal)', 1337238, lambda state: state.has('Kobo', player)),
+ LocationData('The lab (upper)', 'Ravenlord pre fight', 1337242, lambda state: state.has('Merchant Crow', player)),
+ LocationData('The lab (upper)', 'Ravenlord post fight (chest)', 1337243, lambda state: state.has('Merchant Crow', player)),
+ LocationData('Library top', 'Ifrit pre fight', 1337244, lambda state: state.has('Kobo', player)),
+ LocationData('Library top', 'Ifrit post fight (chest)', 1337245, lambda state: state.has('Kobo', player)),
+ )
+
+ cantoran_locations: Tuple[LocationData, ...] = (
+ LocationData('Left Side forest Caves', 'Cantoran', 1337176),
+ )
+
+ if not world:
+ return ( *location_table, *downloadable_locations, *gyre_archives_locations, *cantoran_locations )
+
+ if is_option_enabled(world, player, "DownloadableItems"):
+ location_table.extend(downloadable_locations)
+ if is_option_enabled(world, player, "GyreArchives"):
+ location_table.extend(gyre_archives_locations)
+ if is_option_enabled(world, player, "Cantoran"):
+ location_table.extend(cantoran_locations)
+
+ return tuple(location_table)
starter_progression_locations: Tuple[str, ...] = (
diff --git a/worlds/timespinner/LogicMixin.py b/worlds/timespinner/LogicMixin.py
index 7a81c25e..df7e8f6b 100644
--- a/worlds/timespinner/LogicMixin.py
+++ b/worlds/timespinner/LogicMixin.py
@@ -4,10 +4,10 @@ from .Options import is_option_enabled
class TimespinnerLogic(LogicMixin):
def _timespinner_has_timestop(self, world: MultiWorld, player: int) -> bool:
- return self.has_any(['Timespinner Wheel', 'Succubus Hairpin', 'Lightwall', 'Celestial Sash'], player)
+ return self.has_any({'Timespinner Wheel', 'Succubus Hairpin', 'Lightwall', 'Celestial Sash'}, player)
def _timespinner_has_doublejump(self, world: MultiWorld, player: int) -> bool:
- return self.has_any(['Succubus Hairpin', 'Lightwall', 'Celestial Sash'], player)
+ return self.has_any({'Succubus Hairpin', 'Lightwall', 'Celestial Sash'}, player)
def _timespinner_has_forwarddash_doublejump(self, world: MultiWorld, player: int) -> bool:
return self._timespinner_has_upwarddash(world, player) or (self.has('Talaria Attachment', player) and self._timespinner_has_doublejump(world, player))
@@ -16,19 +16,19 @@ class TimespinnerLogic(LogicMixin):
return self._timespinner_has_upwarddash(world, player) or (self.has('Timespinner Wheel', player) and self._timespinner_has_doublejump(world, player))
def _timespinner_has_fastjump_on_npc(self, world: MultiWorld, player: int) -> bool:
- return self.has_all(['Timespinner Wheel', 'Talaria Attachment'], player)
+ return self.has_all({'Timespinner Wheel', 'Talaria Attachment'}, player)
def _timespinner_has_multiple_small_jumps_of_npc(self, world: MultiWorld, player: int) -> bool:
return self.has('Timespinner Wheel', player) or self._timespinner_has_upwarddash(world, player)
def _timespinner_has_upwarddash(self, world: MultiWorld, player: int) -> bool:
- return self.has_any(['Lightwall', 'Celestial Sash'], player)
+ return self.has_any({'Lightwall', 'Celestial Sash'}, player)
def _timespinner_has_fire(self, world: MultiWorld, player: int) -> bool:
- return self.has_any(['Fire Orb', 'Infernal Flames', 'Pyro Ring', 'Djinn Inferno'], player)
+ return self.has_any({'Fire Orb', 'Infernal Flames', 'Pyro Ring', 'Djinn Inferno'}, player)
def _timespinner_has_pink(self, world: MultiWorld, player: int) -> bool:
- return self.has_any(['Plasma Orb', 'Plasma Geyser', 'Royal Ring'], player)
+ return self.has_any({'Plasma Orb', 'Plasma Geyser', 'Royal Ring'}, player)
def _timespinner_has_keycard_A(self, world: MultiWorld, player: int) -> bool:
return self.has('Security Keycard A', player)
@@ -37,19 +37,19 @@ class TimespinnerLogic(LogicMixin):
if is_option_enabled(world, player, "SpecificKeycards"):
return self.has('Security Keycard B', player)
else:
- return self.has_any(['Security Keycard A', 'Security Keycard B'], player)
+ return self.has_any({'Security Keycard A', 'Security Keycard B'}, player)
def _timespinner_has_keycard_C(self, world: MultiWorld, player: int) -> bool:
if is_option_enabled(world, player, "SpecificKeycards"):
return self.has('Security Keycard C', player)
else:
- return self.has_any(['Security Keycard A', 'Security Keycard B', 'Security Keycard C'], player)
+ return self.has_any({'Security Keycard A', 'Security Keycard B', 'Security Keycard C'}, player)
def _timespinner_has_keycard_D(self, world: MultiWorld, player: int) -> bool:
if is_option_enabled(world, player, "SpecificKeycards"):
return self.has('Security Keycard D', player)
else:
- return self.has_any(['Security Keycard A', 'Security Keycard B', 'Security Keycard C', 'Security Keycard D'], player)
+ return self.has_any({'Security Keycard A', 'Security Keycard B', 'Security Keycard C', 'Security Keycard D'}, player)
def _timespinner_can_break_walls(self, world: MultiWorld, player: int) -> bool:
if is_option_enabled(world, player, "FacebookMode"):
@@ -58,4 +58,4 @@ class TimespinnerLogic(LogicMixin):
return True
def _timespinner_can_kill_all_3_bosses(self, world: MultiWorld, player: int) -> bool:
- return self.has_all(['Killed Maw', 'Killed Twins', 'Killed Aelana'], player)
\ No newline at end of file
+ return self.has_all({'Killed Maw', 'Killed Twins', 'Killed Aelana'}, player)
\ No newline at end of file
diff --git a/worlds/timespinner/Options.py b/worlds/timespinner/Options.py
index 60573145..d3a848c6 100644
--- a/worlds/timespinner/Options.py
+++ b/worlds/timespinner/Options.py
@@ -42,6 +42,14 @@ class Inverted(Toggle):
# "Require gasmask for Maw"
# display_name = "Stinky Maw"
+class GyreArchives(Toggle):
+ "Gyre locations are in logic. New warps are gated by Merchant Crow and Kobo"
+ display_name = "Gyre Archives"
+
+class Cantoran(Toggle):
+ "Cantoran's fight and check are available upon revisiting his room"
+ display_name = "Cantoran"
+
# Some options that are available in the timespinner randomizer arent currently implemented
timespinner_options: Dict[str, Toggle] = {
"StartWithJewelryBox": StartWithJewelryBox,
@@ -54,6 +62,8 @@ timespinner_options: Dict[str, Toggle] = {
"SpecificKeycards": SpecificKeycards,
"Inverted": Inverted,
#"StinkyMaw": StinkyMaw,
+ "GyreArchives": GyreArchives,
+ "Cantoran": Cantoran,
"DeathLink": DeathLink,
}
diff --git a/worlds/timespinner/Regions.py b/worlds/timespinner/Regions.py
index 7fa1ec27..b59b8b8c 100644
--- a/worlds/timespinner/Regions.py
+++ b/worlds/timespinner/Regions.py
@@ -88,7 +88,7 @@ def create_regions(world: MultiWorld, player: int, locations: Tuple[LocationData
connect(world, player, names, 'The lab (power off)', 'The lab (upper)', lambda state: state._timespinner_has_forwarddash_doublejump(world, player))
connect(world, player, names, 'The lab (upper)', 'The lab (power off)')
connect(world, player, names, 'The lab (upper)', 'Emperors tower', lambda state: state._timespinner_has_forwarddash_doublejump(world, player))
- connect(world, player, names, 'The lab (upper)', 'Ancient Pyramid (left)', lambda state: state.has_all(['Timespinner Wheel', 'Timespinner Spindle', 'Timespinner Gear 1', 'Timespinner Gear 2', 'Timespinner Gear 3'], player))
+ connect(world, player, names, 'The lab (upper)', 'Ancient Pyramid (left)', lambda state: state.has_all({'Timespinner Wheel', 'Timespinner Spindle', 'Timespinner Gear 1', 'Timespinner Gear 2', 'Timespinner Gear 3'}, player))
connect(world, player, names, 'Emperors tower', 'The lab (upper)')
connect(world, player, names, 'Skeleton Shaft', 'Lake desolation')
connect(world, player, names, 'Skeleton Shaft', 'Sealed Caves (upper)', lambda state: state._timespinner_has_keycard_A(world, player))
diff --git a/worlds/timespinner/__init__.py b/worlds/timespinner/__init__.py
index 4a982ff2..b0602f18 100644
--- a/worlds/timespinner/__init__.py
+++ b/worlds/timespinner/__init__.py
@@ -18,7 +18,7 @@ class TimespinnerWorld(World):
game = "Timespinner"
topology_present = True
remote_items = False
- data_version = 3
+ data_version = 4
item_name_to_id = {name: data.code for name, data in item_table.items()}
location_name_to_id = {location.name: location.code for location in get_locations(None, None)}
@@ -92,7 +92,7 @@ def get_excluded_items_based_on_options(world: MultiWorld, player: int) -> Set[s
excluded_items.add('Meyef')
if is_option_enabled(world, player, "QuickSeed"):
excluded_items.add('Talaria Attachment')
-
+
return excluded_items
@@ -155,7 +155,9 @@ def create_item_with_correct_settings(world: MultiWorld, player: int, name: str)
if (name == 'Tablet' or name == 'Library Keycard V') and not is_option_enabled(world, player, "DownloadableItems"):
item.advancement = False
- if name == 'Oculus Ring' and not is_option_enabled(world, player, "FacebookMode"):
+ elif name == 'Oculus Ring' and not is_option_enabled(world, player, "FacebookMode"):
+ item.advancement = False
+ elif (name == 'Kobo' or name == 'Merchant Crow') and not is_option_enabled(world, player, "GyreArchives"):
item.advancement = False
return item