mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 12:11:33 -06:00
Timespinner: Support new flags and settings from the randomizer (#4559)
* Timespinner: Add "no hell spiders" enemy rando option that is present in upstream settings * Timespinner: Prism Break support tweaks (including tracker support) * Timespinner: Add support for upstream Lock Key Amadeus flag * Timespinner: Add support for upstream Risky Warps flag * Timespinner: Add support for upstream Pyramid Start flag * Timespinner: fix error in lab connectivity logic * Timespinner: use has_all to simplify one check Per PR suggestion. Co-authored-by: Scipio Wright <scipiowright@gmail.com> * Timespinner: fix apparent logic error inherited from in-rando logic * Timespinner: adjust "Origins" location logic slightly further to account for a Risky Warps case * Timespinner: remove the backward compat options for the recent flag additions * Timespinner: add newly added Gate Keep option from rando * Timespinner: adjust the laser access colours in the tracker * Timespinner: fix an item description in the tracker * Timespinner: based on testing feedback, put Laser Access items in their own category * Timespinner: add support for new upstream flag Royal Roadblock * Timespinner: also ensure the new flag gets put in slot data * Timespinner: fix bug in universal tracker support indicating castle basement is accessible at the lower Rising Tides flooding level * Timespinner: exclude Talaria Attachment and Timespinner Wheel from pyramid start starter progression items * Timespinner: fix region logic for the left pyramid warp * Timespinner: fix main Gyre access logic when Risky Warps warps you behind the lasers * Timespinner: apply suggested spacing fix Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --------- Co-authored-by: sgrunt <sgrunt1987@gmail.com> Co-authored-by: Scipio Wright <scipiowright@gmail.com>
This commit is contained in:
@@ -75,6 +75,27 @@
|
||||
#inventory-table img.acquired.green{ /*32CD32*/
|
||||
filter: hue-rotate(84deg) saturate(10) brightness(0.7);
|
||||
}
|
||||
#inventory-table img.acquired.hotpink{ /*FF69B4*/
|
||||
filter: sepia(100%) hue-rotate(300deg) saturate(10);
|
||||
}
|
||||
#inventory-table img.acquired.lightsalmon{ /*FFA07A*/
|
||||
filter: sepia(100%) hue-rotate(347deg) saturate(10);
|
||||
}
|
||||
#inventory-table img.acquired.crimson{ /*DB143B*/
|
||||
filter: sepia(100%) hue-rotate(318deg) saturate(10) brightness(0.86);
|
||||
}
|
||||
|
||||
#inventory-table span{
|
||||
color: #B4B4A0;
|
||||
font-size: 40px;
|
||||
max-width: 40px;
|
||||
max-height: 40px;
|
||||
filter: grayscale(100%) contrast(75%) brightness(30%);
|
||||
}
|
||||
|
||||
#inventory-table span.acquired{
|
||||
filter: none;
|
||||
}
|
||||
|
||||
#inventory-table div.image-stack{
|
||||
display: grid;
|
||||
|
@@ -99,6 +99,52 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if 'PrismBreak' in options or 'LockKeyAmadeus' in options or 'GateKeep' in options %}
|
||||
<div class="table-row">
|
||||
{% if 'PrismBreak' in options %}
|
||||
<div class="C1">
|
||||
<div class="image-stack">
|
||||
<div class="stack-front">
|
||||
<div class="stack-top-left">
|
||||
<img src="{{ icons['Laser Access'] }}" class="hotpink {{ 'acquired' if 'Laser Access A' in acquired_items }}" title="Laser Access A" />
|
||||
</div>
|
||||
<div class="stack-top-right">
|
||||
<img src="{{ icons['Laser Access'] }}" class="lightsalmon {{ 'acquired' if 'Laser Access I' in acquired_items }}" title="Laser Access I" />
|
||||
</div>
|
||||
<div class="stack-bottum-left">
|
||||
<img src="{{ icons['Laser Access'] }}" class="crimson {{ 'acquired' if 'Laser Access M' in acquired_items }}" title="Laser Access M" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if 'LockKeyAmadeus' in options %}
|
||||
<div class="C2">
|
||||
<div class="image-stack">
|
||||
<div class="stack-front">
|
||||
<div class="stack-top-left">
|
||||
<img src="{{ icons['Lab Glasses'] }}" class="{{ 'acquired' if 'Lab Access Genza' in acquired_items }}" title="Lab Access Genza" />
|
||||
</div>
|
||||
<div class="stack-top-right">
|
||||
<img src="{{ icons['Eye Orb'] }}" class="{{ 'acquired' if 'Lab Access Dynamo' in acquired_items }}" title="Lab Access Dynamo" />
|
||||
</div>
|
||||
<div class="stack-bottum-left">
|
||||
<img src="{{ icons['Lab Coat'] }}" class="{{ 'acquired' if 'Lab Access Research' in acquired_items }}" title="Lab Access Research" />
|
||||
</div>
|
||||
<div class="stack-bottum-right">
|
||||
<img src="{{ icons['Demon'] }}" class="{{ 'acquired' if 'Lab Access Experiment' in acquired_items }}" title="Lab Access Experiment" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if 'GateKeep' in options %}
|
||||
<div class="C3">
|
||||
<span class="{{ 'acquired' if 'Drawbridge Key' in acquired_items }}" title="Drawbridge Key">❖</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<table id="location-table">
|
||||
|
@@ -1071,6 +1071,11 @@ if "Timespinner" in network_data_package["games"]:
|
||||
"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",
|
||||
"Laser Access": "https://timespinnerwiki.com/mediawiki/images/9/99/Historical_Documents.png",
|
||||
"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",
|
||||
}
|
||||
|
||||
timespinner_location_ids = {
|
||||
@@ -1118,6 +1123,9 @@ if "Timespinner" in network_data_package["games"]:
|
||||
timespinner_location_ids["Ancient Pyramid"] += [
|
||||
1337237, 1337238, 1337239,
|
||||
1337240, 1337241, 1337242, 1337243, 1337244, 1337245]
|
||||
if (slot_data["PyramidStart"]):
|
||||
timespinner_location_ids["Ancient Pyramid"] += [
|
||||
1337233, 1337234, 1337235]
|
||||
|
||||
display_data = {}
|
||||
|
||||
|
@@ -199,11 +199,16 @@ item_table: Dict[str, ItemData] = {
|
||||
'Chaos Trap': ItemData('Trap', 1337186, 0, trap=True),
|
||||
'Neurotoxin Trap': ItemData('Trap', 1337187, 0, trap=True),
|
||||
'Bee Trap': ItemData('Trap', 1337188, 0, trap=True),
|
||||
'Laser Access A': ItemData('Relic', 1337189, progression=True),
|
||||
'Laser Access I': ItemData('Relic', 1337191, progression=True),
|
||||
'Laser Access M': ItemData('Relic', 1337192, progression=True),
|
||||
'Laser Access A': ItemData('Laser Access', 1337189, progression=True),
|
||||
'Laser Access I': ItemData('Laser Access', 1337191, progression=True),
|
||||
'Laser Access M': ItemData('Laser Access', 1337192, progression=True),
|
||||
'Throw Stun Trap': ItemData('Trap', 1337193, 0, trap=True),
|
||||
# 1337194 - 1337248 Reserved
|
||||
'Lab Access Genza': ItemData('Lab Access', 1337194, progression=True),
|
||||
'Lab Access Experiment': ItemData('Lab Access', 1337195, progression=True),
|
||||
'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 - 1337248 Reserved
|
||||
'Max Sand': ItemData('Stat', 1337249, 14)
|
||||
}
|
||||
|
||||
@@ -259,6 +264,17 @@ starter_progression_items: Tuple[str, ...] = (
|
||||
'Mysterious Warp Beacon'
|
||||
)
|
||||
|
||||
pyramid_start_starter_progression_items: Tuple[str, ...] = (
|
||||
'Succubus Hairpin',
|
||||
'Succubus Hairpin',
|
||||
'Twin Pyramid Key',
|
||||
'Celestial Sash',
|
||||
'Lightwall',
|
||||
'Modern Warp Beacon',
|
||||
'Timeworn Warp Beacon',
|
||||
'Mysterious Warp Beacon'
|
||||
)
|
||||
|
||||
filler_items: Tuple[str, ...] = (
|
||||
'Potion',
|
||||
'Ether',
|
||||
|
@@ -92,15 +92,15 @@ def get_location_datas(player: Optional[int], options: Optional[TimespinnerOptio
|
||||
LocationData('Military Fortress (hangar)', 'Military Fortress: Pedestal', 1337065, lambda state: state.has('Water Mask', player) if flooded.flood_lab else (logic.has_doublejump_of_npc(state) or logic.has_forwarddash_doublejump(state))),
|
||||
LocationData('The lab', 'Lab: Coffee break', 1337066),
|
||||
LocationData('The lab', 'Lab: Lower trash right', 1337067, logic.has_doublejump),
|
||||
LocationData('The lab', 'Lab: Lower trash left', 1337068, logic.has_upwarddash),
|
||||
LocationData('The lab', 'Lab: Lower trash left', 1337068, lambda state: logic.has_doublejump_of_npc(state) if options.lock_key_amadeus else logic.has_upwarddash ),
|
||||
LocationData('The lab', 'Lab: Below lab entrance', 1337069, logic.has_doublejump),
|
||||
LocationData('The lab (power off)', 'Lab: Trash jump room', 1337070),
|
||||
LocationData('The lab (power off)', 'Lab: Dynamo Works', 1337071),
|
||||
LocationData('The lab (power off)', 'Lab: Trash jump room', 1337070, lambda state: not options.lock_key_amadeus or logic.has_doublejump_of_npc(state) ),
|
||||
LocationData('The lab (power off)', 'Lab: Dynamo Works', 1337071, lambda state: not options.lock_key_amadeus or (state.has_all(('Lab Access Research', 'Lab Access Dynamo'), player)) ),
|
||||
LocationData('The lab (upper)', 'Lab: Genza (Blob Mom)', 1337072),
|
||||
LocationData('The lab (power off)', 'Lab: Experiment #13', 1337073),
|
||||
LocationData('The lab (power off)', 'Lab: Experiment #13', 1337073, lambda state: not options.lock_key_amadeus or state.has('Lab Access Experiment', player) ),
|
||||
LocationData('The lab (upper)', 'Lab: Download and chest room chest', 1337074),
|
||||
LocationData('The lab (upper)', 'Lab: Lab secret', 1337075, logic.can_break_walls),
|
||||
LocationData('The lab (power off)', 'Lab: Spider Hell', 1337076, logic.has_keycard_A),
|
||||
LocationData('The lab (power off)', 'Lab: Spider Hell', 1337076, lambda state: logic.has_keycard_A and not options.lock_key_amadeus or state.has('Lab Access Research', player)),
|
||||
LocationData('Emperors tower', 'Emperor\'s Tower: Courtyard bottom chest', 1337077),
|
||||
LocationData('Emperors tower', 'Emperor\'s Tower: Courtyard floor secret', 1337078, lambda state: logic.has_upwarddash(state) and logic.can_break_walls(state)),
|
||||
LocationData('Emperors tower', 'Emperor\'s Tower: Courtyard upper chest', 1337079, lambda state: logic.has_upwarddash(state)),
|
||||
@@ -214,11 +214,11 @@ def get_location_datas(player: Optional[int], options: Optional[TimespinnerOptio
|
||||
LocationData('Library top', 'Library: Backer room terminal (Vandagray Metropolis Map)', 1337163, lambda state: state.has('Tablet', player)),
|
||||
LocationData('Varndagroth tower right (elevator)', 'Varndagroth Towers (Right): Medbay terminal (Bleakness Research)', 1337164, lambda state: state.has('Tablet', player) and logic.has_keycard_B(state)),
|
||||
LocationData('The lab (upper)', 'Lab: Download and chest room terminal (Experiment #13)', 1337165, lambda state: state.has('Tablet', player)),
|
||||
LocationData('The lab (power off)', 'Lab: Middle terminal (Amadeus Laboratory Map)', 1337166, lambda state: state.has('Tablet', player)),
|
||||
LocationData('The lab (power off)', 'Lab: Sentry platform terminal (Origins)', 1337167, lambda state: state.has('Tablet', player)),
|
||||
LocationData('The lab (power off)', 'Lab: Middle terminal (Amadeus Laboratory Map)', 1337166, lambda state: state.has('Tablet', player) and (not options.lock_key_amadeus or state.has('Lab Access Research', player))),
|
||||
LocationData('The lab (power off)', 'Lab: Sentry platform terminal (Origins)', 1337167, lambda state: state.has('Tablet', player) and (not options.lock_key_amadeus or state.has('Lab Access Genza', player) or logic.can_teleport_to(state, "Time", "GateDadsTower"))),
|
||||
LocationData('The lab', 'Lab: Experiment 13 terminal (W.R.E.C Farewell)', 1337168, lambda state: state.has('Tablet', player)),
|
||||
LocationData('The lab', 'Lab: Left terminal (Biotechnology)', 1337169, lambda state: state.has('Tablet', player)),
|
||||
LocationData('The lab (power off)', 'Lab: Right terminal (Experiment #11)', 1337170, lambda state: state.has('Tablet', player))
|
||||
LocationData('The lab (power off)', 'Lab: Right terminal (Experiment #11)', 1337170, lambda state: state.has('Tablet', player) and (not options.lock_key_amadeus or state.has('Lab Access Research', player)))
|
||||
)
|
||||
|
||||
# 1337176 - 1337176 Cantoran
|
||||
@@ -254,7 +254,17 @@ def get_location_datas(player: Optional[int], options: Optional[TimespinnerOptio
|
||||
LocationData('Caves of Banishment (Maw)', 'Caves of Banishment (Maw): Journal - Lower Left Caves (Naivety)', 1337198, lambda state: not flooded.flood_maw or state.has('Water Mask', player))
|
||||
)
|
||||
|
||||
# 1337199 - 1337236 Reserved for future use
|
||||
# 1337199 - 1337232 Reserved for future use
|
||||
|
||||
# 1337233 - 1337235 Pyramid Start checks
|
||||
if not options or options.pyramid_start:
|
||||
location_table += (
|
||||
LocationData('Ancient Pyramid (entrance)', 'Dark Forest: Training Dummy', 1337233),
|
||||
LocationData('Ancient Pyramid (entrance)', 'Temporal Gyre: Forest Entrance', 1337234, lambda state: logic.has_upwarddash(state) or logic.can_teleport_to(state, "Time", "GateGyre")),
|
||||
LocationData('Ancient Pyramid (entrance)', 'Ancient Pyramid: Rubble', 1337235),
|
||||
)
|
||||
|
||||
# 1337236 Nightmare door
|
||||
|
||||
# 1337237 - 1337245 GyreArchives
|
||||
if not options or options.gyre_archives:
|
||||
|
@@ -10,6 +10,7 @@ class TimespinnerLogic:
|
||||
flag_unchained_keys: bool
|
||||
flag_eye_spy: bool
|
||||
flag_specific_keycards: bool
|
||||
flag_prism_break: bool
|
||||
pyramid_keys_unlock: Optional[str]
|
||||
present_keys_unlock: Optional[str]
|
||||
past_keys_unlock: Optional[str]
|
||||
|
@@ -60,6 +60,7 @@ class EnemyRando(Choice):
|
||||
option_scaled = 1
|
||||
option_unscaled = 2
|
||||
option_ryshia = 3
|
||||
option_no_hell_spiders = 4
|
||||
alias_true = 1
|
||||
|
||||
class DamageRando(Choice):
|
||||
@@ -378,6 +379,26 @@ class PrismBreak(Toggle):
|
||||
instead of needing to beat the Golden Idol, Aelana, and The Maw."""
|
||||
display_name = "Prism Break"
|
||||
|
||||
class LockKeyAmadeus(Toggle):
|
||||
"""Lasers in Amadeus' Laboratory are disabled via items, rather than by de-powering the lab. Experiments will spawn in the lab."""
|
||||
display_name = "Lock Key Amadeus"
|
||||
|
||||
class RiskyWarps(Toggle):
|
||||
"""Expanded free-warp eligible locations, including Azure Queen, Xarion, Amadeus' Laboratory, and Emperor's Tower."""
|
||||
display_name = "Risky Warps"
|
||||
|
||||
class PyramidStart(Toggle):
|
||||
"""Start in ???. Takes priority over Inverted. Additional chests in Dark Forest and Pyramid. Sandman door behaves as it does in Enter Sandman."""
|
||||
display_name = "Pyramid Start"
|
||||
|
||||
class GateKeep(Toggle):
|
||||
"""The castle drawbridge starts raised, and can be lowered via item."""
|
||||
display_name = "Gate Keep"
|
||||
|
||||
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"
|
||||
|
||||
@dataclass
|
||||
class TimespinnerOptions(PerGameCommonOptions, DeathLinkMixin):
|
||||
start_with_jewelry_box: StartWithJewelryBox
|
||||
@@ -415,6 +436,11 @@ class TimespinnerOptions(PerGameCommonOptions, DeathLinkMixin):
|
||||
unchained_keys: UnchainedKeys
|
||||
back_to_the_future: PresentAccessWithWheelAndSpindle
|
||||
prism_break: PrismBreak
|
||||
lock_key_amadeus: LockKeyAmadeus
|
||||
risky_warps: RiskyWarps
|
||||
pyramid_start: PyramidStart
|
||||
gate_keep: GateKeep
|
||||
royal_roadblock: RoyalRoadblock
|
||||
trap_chance: TrapChance
|
||||
traps: Traps
|
||||
|
||||
|
@@ -52,11 +52,12 @@ class PreCalculatedWeights:
|
||||
self.flood_lab = False
|
||||
|
||||
self.pyramid_keys_unlock, self.present_key_unlock, self.past_key_unlock, self.time_key_unlock = \
|
||||
self.get_pyramid_keys_unlocks(options, random, self.flood_maw, self.flood_xarion)
|
||||
self.get_pyramid_keys_unlocks(options, random, self.flood_maw, self.flood_xarion, self.flood_lab)
|
||||
|
||||
@staticmethod
|
||||
def get_pyramid_keys_unlocks(options: TimespinnerOptions, random: Random,
|
||||
is_maw_flooded: bool, is_xarion_flooded: bool) -> Tuple[str, str, str, str]:
|
||||
is_maw_flooded: bool, is_xarion_flooded: bool,
|
||||
is_lab_flooded: bool) -> Tuple[str, str, str, str]:
|
||||
|
||||
present_teleportation_gates: List[str] = [
|
||||
"GateKittyBoss",
|
||||
@@ -85,10 +86,15 @@ class PreCalculatedWeights:
|
||||
if not is_maw_flooded:
|
||||
past_teleportation_gates.append("GateMaw")
|
||||
|
||||
if not is_xarion_flooded:
|
||||
present_teleportation_gates.append("GateXarion")
|
||||
if options.risky_warps:
|
||||
past_teleportation_gates.append("GateLakeSereneLeft")
|
||||
present_teleportation_gates.append("GateDadsTower")
|
||||
if not is_xarion_flooded:
|
||||
present_teleportation_gates.append("GateXarion")
|
||||
if not is_lab_flooded:
|
||||
present_teleportation_gates.append("GateLabEntrance")
|
||||
|
||||
if options.inverted:
|
||||
if options.inverted or (options.pyramid_start and not options.back_to_the_future):
|
||||
all_gates: Tuple[str, ...] = present_teleportation_gates
|
||||
else:
|
||||
all_gates: Tuple[str, ...] = past_teleportation_gates + present_teleportation_gates
|
||||
|
@@ -106,15 +106,15 @@ def create_regions_and_locations(world: MultiWorld, player: int, options: Timesp
|
||||
connect(world, player, 'Sealed Caves (Sirens)', 'Varndagroth tower right (lower)', lambda state: state.has('Elevator Keycard', player))
|
||||
connect(world, player, 'Sealed Caves (Sirens)', 'Space time continuum', logic.has_teleport)
|
||||
connect(world, player, 'Military Fortress', 'Varndagroth tower right (lower)', logic.can_kill_all_3_bosses)
|
||||
connect(world, player, 'Military Fortress', 'Temporal Gyre', lambda state: state.has('Timespinner Wheel', player))
|
||||
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, 'Temporal Gyre', 'Military Fortress')
|
||||
connect(world, player, 'The lab', 'Military Fortress')
|
||||
connect(world, player, 'The lab', 'The lab (power off)', logic.has_doublejump_of_npc)
|
||||
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)', logic.has_forwarddash_doublejump)
|
||||
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)')
|
||||
connect(world, player, 'The lab (upper)', 'Emperors tower', 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))
|
||||
@@ -125,12 +125,12 @@ def create_regions_and_locations(world: MultiWorld, player: int, options: Timesp
|
||||
connect(world, player, 'Sealed Caves (Xarion)', 'Skeleton Shaft')
|
||||
connect(world, player, 'Sealed Caves (Xarion)', 'Space time continuum', logic.has_teleport)
|
||||
connect(world, player, 'Refugee Camp', 'Forest')
|
||||
connect(world, player, 'Refugee Camp', 'Library', lambda state: options.inverted and options.back_to_the_future and state.has_all({'Timespinner Wheel', 'Timespinner Spindle'}, player))
|
||||
connect(world, player, 'Refugee Camp', 'Library', lambda state: (options.pyramid_start or options.inverted) and options.back_to_the_future and state.has_all({'Timespinner Wheel', 'Timespinner Spindle'}, player))
|
||||
connect(world, player, 'Refugee Camp', 'Space time continuum', logic.has_teleport)
|
||||
connect(world, player, 'Forest', 'Refugee Camp')
|
||||
connect(world, player, 'Forest', 'Left Side forest Caves', lambda state: flooded.flood_lake_serene_bridge or state.has('Talaria Attachment', player) or logic.has_timestop(state))
|
||||
connect(world, player, 'Forest', 'Caves of Banishment (Sirens)')
|
||||
connect(world, player, 'Forest', 'Castle Ramparts')
|
||||
connect(world, player, 'Forest', 'Castle Ramparts', lambda state: not options.gate_keep or state.has('Drawbridge Key', player) or logic.has_upwarddash(state))
|
||||
connect(world, player, 'Left Side forest Caves', 'Forest')
|
||||
connect(world, player, 'Left Side forest Caves', 'Upper Lake Serene', logic.has_timestop)
|
||||
connect(world, player, 'Left Side forest Caves', 'Lower Lake Serene', lambda state: not flooded.flood_lake_serene or state.has('Water Mask', player))
|
||||
@@ -152,7 +152,7 @@ def create_regions_and_locations(world: MultiWorld, player: int, options: Timesp
|
||||
connect(world, player, 'Castle Ramparts', 'Space time continuum', logic.has_teleport)
|
||||
connect(world, player, 'Castle Keep', 'Castle Ramparts')
|
||||
connect(world, player, 'Castle Keep', 'Castle Basement', lambda state: not flooded.flood_basement or state.has('Water Mask', player))
|
||||
connect(world, player, 'Castle Keep', 'Royal towers (lower)', logic.has_doublejump)
|
||||
connect(world, player, 'Castle Keep', 'Royal towers (lower)', lambda state: logic.has_doublejump(state) and (not options.royal_roadblock or logic.has_pink(state)))
|
||||
connect(world, player, 'Castle Keep', 'Space time continuum', logic.has_teleport)
|
||||
connect(world, player, 'Royal towers (lower)', 'Castle Keep')
|
||||
connect(world, player, 'Royal towers (lower)', 'Royal towers', lambda state: state.has('Timespinner Wheel', player) or logic.has_forwarddash_doublejump(state))
|
||||
@@ -162,9 +162,12 @@ def create_regions_and_locations(world: MultiWorld, player: int, options: Timesp
|
||||
connect(world, player, 'Royal towers (upper)', 'Royal towers')
|
||||
#connect(world, player, 'Ancient Pyramid (entrance)', 'The lab (upper)', lambda state: not is_option_enabled(world, player, "EnterSandman"))
|
||||
connect(world, player, 'Ancient Pyramid (entrance)', 'Ancient Pyramid (left)', logic.has_doublejump)
|
||||
connect(world, player, 'Ancient Pyramid (entrance)', 'Space time continuum', logic.has_teleport)
|
||||
connect(world, player, 'Ancient Pyramid (left)', 'Ancient Pyramid (entrance)')
|
||||
connect(world, player, 'Ancient Pyramid (left)', 'Ancient Pyramid (right)', lambda state: flooded.flood_pyramid_shaft or logic.has_upwarddash(state))
|
||||
connect(world, player, 'Ancient Pyramid (left)', 'Space time continuum', logic.has_teleport)
|
||||
connect(world, player, 'Ancient Pyramid (right)', 'Ancient Pyramid (left)', lambda state: flooded.flood_pyramid_shaft or logic.has_upwarddash(state))
|
||||
connect(world, player, 'Ancient Pyramid (right)', 'Space time continuum', logic.has_teleport)
|
||||
connect(world, player, 'Space time continuum', 'Lake desolation', lambda state: logic.can_teleport_to(state, "Present", "GateLakeDesolation"))
|
||||
connect(world, player, 'Space time continuum', 'Lower lake desolation', lambda state: logic.can_teleport_to(state, "Present", "GateKittyBoss"))
|
||||
connect(world, player, 'Space time continuum', 'Library', lambda state: logic.can_teleport_to(state, "Present", "GateLeftLibrary"))
|
||||
@@ -180,8 +183,9 @@ def create_regions_and_locations(world: MultiWorld, player: int, options: Timesp
|
||||
connect(world, player, 'Space time continuum', 'Royal towers (lower)', lambda state: logic.can_teleport_to(state, "Past", "GateRoyalTowers"))
|
||||
connect(world, player, 'Space time continuum', 'Caves of Banishment (Maw)', lambda state: logic.can_teleport_to(state, "Past", "GateMaw"))
|
||||
connect(world, player, 'Space time continuum', 'Caves of Banishment (upper)', lambda state: logic.can_teleport_to(state, "Past", "GateCavesOfBanishment"))
|
||||
connect(world, player, 'Space time continuum', 'Ancient Pyramid (entrance)', lambda state: logic.can_teleport_to(state, "Time", "GateGyre") or (not options.unchained_keys and options.enter_sandman))
|
||||
connect(world, player, 'Space time continuum', 'Ancient Pyramid (left)', lambda state: logic.can_teleport_to(state, "Time", "GateLeftPyramid"))
|
||||
connect(world, player, 'Space time continuum', 'Military Fortress (hangar)', lambda state: logic.can_teleport_to(state, "Present", "GateLabEntrance"))
|
||||
connect(world, player, 'Space time continuum', 'The lab (upper)', lambda state: logic.can_teleport_to(state, "Present", "GateDadsTower"))
|
||||
connect(world, player, 'Space time continuum', 'Ancient Pyramid (entrance)', lambda state: logic.can_teleport_to(state, "Time", "GateGyre") or logic.can_teleport_to(state, "Time", "GateLeftPyramid") or (not options.unchained_keys and options.enter_sandman))
|
||||
connect(world, player, 'Space time continuum', 'Ancient Pyramid (right)', lambda state: logic.can_teleport_to(state, "Time", "GateRightPyramid"))
|
||||
|
||||
if options.gyre_archives:
|
||||
@@ -227,7 +231,9 @@ def connectStartingRegion(world: MultiWorld, player: int, options: TimespinnerOp
|
||||
tutorial = world.get_region('Tutorial', player)
|
||||
space_time_continuum = world.get_region('Space time continuum', player)
|
||||
|
||||
if options.inverted:
|
||||
if options.pyramid_start:
|
||||
starting_region = world.get_region('Ancient Pyramid (entrance)', player)
|
||||
elif options.inverted:
|
||||
starting_region = world.get_region('Refugee Camp', player)
|
||||
else:
|
||||
starting_region = world.get_region('Lake desolation', player)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
from typing import Dict, List, Set, Tuple, TextIO, Any, Optional
|
||||
from BaseClasses import Item, Tutorial, ItemClassification
|
||||
from .Items import get_item_names_per_category
|
||||
from .Items import item_table, starter_melee_weapons, starter_spells, filler_items, starter_progression_items
|
||||
from .Items import item_table, starter_melee_weapons, starter_spells, filler_items, starter_progression_items, pyramid_start_starter_progression_items
|
||||
from .Locations import get_location_datas, EventId
|
||||
from .Options import BackwardsCompatiableTimespinnerOptions, Toggle
|
||||
from .PreCalculatedWeights import PreCalculatedWeights
|
||||
@@ -126,6 +126,11 @@ class TimespinnerWorld(World):
|
||||
"UnchainedKeys": self.options.unchained_keys.value,
|
||||
"PresentAccessWithWheelAndSpindle": self.options.back_to_the_future.value,
|
||||
"PrismBreak": self.options.prism_break.value,
|
||||
"LockKeyAmadeus": self.options.lock_key_amadeus.value,
|
||||
"RiskyWarps": self.options.risky_warps.value,
|
||||
"PyramidStart": self.options.pyramid_start.value,
|
||||
"GateKeep": self.options.gate_keep.value,
|
||||
"RoyalRoadblock": self.options.royal_roadblock.value,
|
||||
"Traps": self.options.traps.value,
|
||||
"DeathLink": self.options.death_link.value,
|
||||
"StinkyMaw": True,
|
||||
@@ -203,7 +208,7 @@ class TimespinnerWorld(World):
|
||||
self.precalculated_weights.past_key_unlock = slot_data["PastGate"]
|
||||
self.precalculated_weights.time_key_unlock = slot_data["TimeGate"]
|
||||
# rising tides
|
||||
if (slot_data["Basement"] > 1):
|
||||
if (slot_data["Basement"] > 0):
|
||||
self.precalculated_weights.flood_basement = True
|
||||
if (slot_data["Basement"] == 2):
|
||||
self.precalculated_weights.flood_basement_high = True
|
||||
@@ -304,6 +309,11 @@ class TimespinnerWorld(World):
|
||||
elif name in {"Laser Access A", "Laser Access I", "Laser Access M"} \
|
||||
and not self.options.prism_break:
|
||||
item.classification = ItemClassification.filler
|
||||
elif name in {"Lab Access Genza", "Lab Access Experiment", "Lab Access Research", "Lab Access Dynamo"} \
|
||||
and not self.options.lock_key_amadeus:
|
||||
item.classification = ItemClassification.filler
|
||||
elif name == "Drawbridge Key" and not self.options.gate_keep:
|
||||
item.classification = ItemClassification.filler
|
||||
|
||||
return item
|
||||
|
||||
@@ -341,6 +351,15 @@ class TimespinnerWorld(World):
|
||||
excluded_items.add('Laser Access I')
|
||||
excluded_items.add('Laser Access M')
|
||||
|
||||
if not self.options.lock_key_amadeus:
|
||||
excluded_items.add('Lab Access Genza')
|
||||
excluded_items.add('Lab Access Experiment')
|
||||
excluded_items.add('Lab Access Research')
|
||||
excluded_items.add('Lab Access Dynamo')
|
||||
|
||||
if not self.options.gate_keep:
|
||||
excluded_items.add('Drawbridge Key')
|
||||
|
||||
for item in self.multiworld.precollected_items[self.player]:
|
||||
if item.name not in self.item_name_groups['UseItem']:
|
||||
excluded_items.add(item.name)
|
||||
@@ -376,15 +395,18 @@ class TimespinnerWorld(World):
|
||||
self.place_locked_item(excluded_items, location, item_name)
|
||||
|
||||
def place_first_progression_item(self, excluded_items: Set[str]) -> None:
|
||||
if self.options.quick_seed or self.options.inverted or self.precalculated_weights.flood_lake_desolation:
|
||||
if (self.options.quick_seed or self.options.inverted or self.precalculated_weights.flood_lake_desolation) \
|
||||
and not self.options.pyramid_start:
|
||||
return
|
||||
|
||||
enabled_starter_progression_items = pyramid_start_starter_progression_items if self.options.pyramid_start else starter_progression_items
|
||||
|
||||
for item_name in self.options.start_inventory.value.keys():
|
||||
if item_name in starter_progression_items:
|
||||
if item_name in enabled_starter_progression_items:
|
||||
return
|
||||
|
||||
local_starter_progression_items = tuple(
|
||||
item for item in starter_progression_items
|
||||
item for item in enabled_starter_progression_items
|
||||
if item not in excluded_items and item not in self.options.non_local_items.value)
|
||||
|
||||
if not local_starter_progression_items:
|
||||
|
Reference in New Issue
Block a user