Files
dockipelago/worlds/duke3d/levels/e1l5.py
Jonathan Tinney 7971961166
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
add schedule I, sonic 1/frontiers/heroes, spirit island
2026-04-02 23:46:36 -07:00

426 lines
15 KiB
Python

from BaseClasses import Region
from ..base_classes import D3DLevel
class E1L5(D3DLevel):
name = "The Abyss"
levelnum = 4
volumenum = 0
keys = ["Blue"]
location_defs = [
{"name": "Battlelord Medkit", "id": 4, "type": "sprite", "density": 0},
{
"name": "Battlelord Atomic Health 1",
"id": 11,
"type": "sprite",
"density": 4,
},
{
"name": "Battlelord Atomic Health 2",
"id": 12,
"type": "sprite",
"density": 4,
},
{"name": "Waterfall Chaingun", "id": 24, "type": "sprite", "density": 0},
{"name": "MP Start Chaingun", "id": 78, "type": "sprite", "density": 5},
{"name": "Battlelord Jetpack", "id": 79, "type": "sprite", "density": 3},
{"name": "Battlelord Armor", "id": 80, "type": "sprite", "density": 4},
{
"name": "Cracked Wall End Atomic Health",
"id": 112,
"type": "sprite",
"density": 4,
},
{"name": "Fire Pit Pipe Bombs", "id": 131, "type": "sprite", "density": 3},
{
"name": "Top of Spaceship Atomic Health",
"id": 216,
"type": "sprite",
"density": 2,
},
{"name": "Spaceship Shaft RPG", "id": 221, "type": "sprite", "density": 1},
{"name": "Spaceship Shaft Chaingun", "id": 222, "type": "sprite", "density": 3},
{
"name": "Fire Pit Night Vision Goggles",
"id": 262,
"type": "sprite",
"density": 1,
},
{"name": "Canyon Chaingun", "id": 291, "type": "sprite", "density": 3},
{"name": "MP Secret Fire Pit Armor", "id": 294, "type": "sprite", "density": 5},
{"name": "Pipebombs near Blue Gate", "id": 311, "type": "sprite", "density": 1},
{"name": "Start Shotgun", "id": 316, "type": "sprite", "density": 1},
{
"name": "Earthquake Atomic Health 1",
"id": 373,
"type": "sprite",
"density": 1,
},
{
"name": "Earthquake Atomic Health 2",
"id": 374,
"type": "sprite",
"density": 3,
},
{"name": "Blue Key Card", "id": 375, "type": "sprite", "density": 0},
{
"name": "Cracked Wall Middle Atomic Health",
"id": 410,
"type": "sprite",
"density": 0,
},
{"name": "Fire Pit RPG", "id": 439, "type": "sprite", "density": 0},
{
"name": "Dancing Shaman Atomic Health 1",
"id": 466,
"type": "sprite",
"density": 2,
},
{
"name": "Dancing Shaman Atomic Health 2",
"id": 472,
"type": "sprite",
"density": 4,
},
{
"name": "Dancing Shaman Atomic Health 3",
"id": 473,
"type": "sprite",
"density": 4,
},
{"name": "Red Waterfall Pipe Bombs", "id": 524, "type": "sprite", "density": 0},
{"name": "Start Protective Boots", "id": 604, "type": "sprite", "density": 0},
{
"name": "Bottom of Ruins Protective Boots",
"id": 682,
"type": "sprite",
"density": 1,
},
{"name": "Fire Place Medkit", "id": 689, "type": "sprite", "density": 0},
{
"name": "Toxic River Protective Boots",
"id": 698,
"type": "sprite",
"density": 4,
},
{"name": "Start RPG", "id": 718, "type": "sprite", "density": 3},
{
"name": "Secret Fire Pit Night Vision Goggles",
"id": 726,
"type": "sprite",
"density": 3,
},
{"name": "Secret Fire Pit Medkit", "id": 727, "type": "sprite", "density": 0},
{"name": "Toxic River Holo Duke", "id": 733, "type": "sprite", "density": 4},
{"name": "Toxic River Medkit", "id": 734, "type": "sprite", "density": 1},
{"name": "Ruins Staircase Shotgun", "id": 737, "type": "sprite", "density": 1},
{"name": "Fire Pit Steroids", "id": 738, "type": "sprite", "density": 2},
{
"name": "Cracked Wall Bottom Atomic Health",
"id": 740,
"type": "sprite",
"density": 3,
},
{
"name": "Cracked Wall Protective Boots",
"id": 741,
"type": "sprite",
"density": 3,
},
{"name": "Cracked Wall Medkit", "id": 742, "type": "sprite", "density": 1},
{"name": "Spaceship Entrance Armor", "id": 744, "type": "sprite", "density": 3},
{
"name": "Earthquake Night Vision Goggles",
"id": 817,
"type": "sprite",
"density": 3,
},
{
"name": "Red Waterfall Cave Protective Boots",
"id": 868,
"type": "sprite",
"density": 3,
},
{
"name": "MP Shrinker Room Steroids",
"id": 876,
"type": "sprite",
"density": 5,
},
{
"name": "MP Cracked Wall Bottom Pipebombs",
"id": 879,
"type": "sprite",
"density": 5,
},
{"name": "Canyon Pillars RPG", "id": 884, "type": "sprite", "density": 0},
{"name": "MP Fire Pit Jetpack", "id": 1032, "type": "sprite", "density": 5},
{"name": "MP Fire Place RPG", "id": 1039, "type": "sprite", "density": 5},
{
"name": "MP Ruins Staircase Atomic Health",
"id": 1041,
"type": "sprite",
"density": 5,
},
{
"name": "MP Ruins Staircase Armor",
"id": 1042,
"type": "sprite",
"density": 5,
},
{
"name": "MP Bottom of Ruins Shotgun",
"id": 1044,
"type": "sprite",
"density": 5,
},
{"name": "Fire Pit Atomic Health", "id": 1046, "type": "sprite", "density": 3},
{
"name": "Secret Fire Pit Atomic Health 1",
"id": 1047,
"type": "sprite",
"density": 2,
},
{
"name": "Secret Fire Pit Atomic Health 2",
"id": 1048,
"type": "sprite",
"density": 4,
},
{"name": "Secret Red Waterfall Passage", "id": 7, "type": "sector"},
{"name": "Secret Dancing Shaman", "id": 21, "type": "sector"},
{"name": "Secret Top of Spaceship", "id": 257, "type": "sector"},
{"name": "Secret Fire Pit Hidden Wall", "id": 354, "type": "sector"},
{"name": "Secret Fire Pit Teleporter", "id": 440, "type": "sector"},
{"name": "Secret Fire Pit Ledge", "id": 441, "type": "sector"},
{"name": "Exit", "id": 0, "type": "exit"},
]
events = ["Earthquake", "Canyon Explosion"]
has_boss = True
def main_region(self) -> Region:
r = self.rules
ret = self.region(
self.name,
[
"Start RPG",
"Start Shotgun",
"Start Protective Boots",
"MP Start Chaingun",
"Blue Key Card",
"Canyon Chaingun",
"Toxic River Medkit",
"Toxic River Holo Duke",
"Toxic River Protective Boots",
"Earthquake Night Vision Goggles",
],
)
# Can pick it up pushing into the pillar from the back left at just the right angle
self.restrict("Blue Key Card", r.jump | r.difficulty("medium"))
self.restrict("Earthquake Night Vision Goggles", r.jump)
# Tripclip
self.restrict(
"Start Protective Boots",
r.can_open
| (
r.glitched
& r.tripmine
& r.fast_sprint
& r.can_jump
& r.difficulty("extreme")
),
)
blue_gate = self.region("Beyond Blue Key Gate", ["Pipebombs near Blue Gate"])
# Gate opens automatically, no Open required
# Crouch jump has a reliable setup, very hard to time without one
# Easier path is just to trooper hop around the outside on hard difficulty
# which removes any need for glitched
self.connect(
ret,
blue_gate,
self.blue_key | (r.difficulty("hard") & r.can_jump) | r.jetpack(50),
)
fault_trigger = self.region(
"Earthquake Trigger",
[
"Earthquake",
"Secret Fire Pit Night Vision Goggles",
"Secret Fire Pit Medkit",
],
)
self.connect(
blue_gate, fault_trigger, r.jump
) # jetpack also gets here without blue key by above logic
beyond_fault = self.region(
"After Earthquake",
[
"Earthquake Atomic Health 1",
"Earthquake Atomic Health 2",
"Ruins Staircase Shotgun",
"MP Fire Place RPG",
# TODO: Test if these belongs to beyond_fault or small_ledges
# "MP Ruins Staircase Atomic Health",
# "MP Ruins Staircase Armor",
"Fire Pit Pipe Bombs",
"Fire Pit Atomic Health",
"Secret Fire Pit Teleporter",
"Bottom of Ruins Protective Boots",
"MP Bottom of Ruins Shotgun",
"Fire Pit RPG",
"Waterfall Chaingun",
],
)
self.connect(fault_trigger, beyond_fault, self.event("Earthquake"))
# can clip through, skipping the hand trigger
self.restrict("Fire Pit RPG", (r.jump & r.can_use) | r.crouch_jump)
# Can sr50 or sprint onto the waterfall alcove
self.restrict("Waterfall Chaingun", r.jump | r.sr50)
fault_doors = self.region(
"Doors after Earthquake",
["Fire Pit Steroids", "Secret Fire Pit Hidden Wall"],
)
self.connect(beyond_fault, fault_doors, r.can_open)
fault_buttons = self.region("Buttons after Earthquake", ["Fire Place Medkit"])
self.connect(beyond_fault, fault_buttons, r.can_use)
secret_fire_pit_ledge = self.region(
"Secret Fire Pit Ledge",
[
"Secret Fire Pit Atomic Health 1",
"Secret Fire Pit Atomic Health 2",
"MP Secret Fire Pit Armor",
],
)
# you can clip up here somehow, I just don't know how to reproduce it
self.connect(
beyond_fault, secret_fire_pit_ledge, r.jump | r.difficulty("extreme")
)
small_ledges = self.region(
"Ledges after Earthquake",
[
"MP Ruins Staircase Atomic Health",
"MP Ruins Staircase Armor",
"Secret Fire Pit Ledge",
],
)
# always have like 20 jetpack left from earthquake at this point, should all be fine
self.connect(beyond_fault, small_ledges, r.jump)
fire_pit_ledge = self.region(
"Fire Pit Ledge", ["Fire Pit Night Vision Goggles", "MP Fire Pit Jetpack"]
)
# Can SR50 over with sprint speed
self.connect(
beyond_fault,
fire_pit_ledge,
r.jump | r.fast_sprint | (r.difficulty("hard") & r.sprint),
)
shrinker_ledge = self.region(
"Shrinker Room Ledge", ["MP Shrinker Room Steroids", "Canyon Explosion"]
)
self.connect(
beyond_fault, shrinker_ledge, r.can_use | (r.crouch_jump & r.jetpack(50))
)
# Would get stuck in the room afterward otherwise if we can't leave
self.restrict(
"Canyon Explosion", (r.can_shrink & r.jump & r.can_use) | r.crouch_jump
)
# anything beyond here on pure jetpack uses 50 fuel to get to the red canyon area and make progress
# it might be possible in just 50 to get here, but that seems a harsh requirement
red_waterfall = self.region(
"Red Waterfall",
[
"Red Waterfall Cave Protective Boots",
"Red Waterfall Pipe Bombs",
"Secret Red Waterfall Passage",
],
)
# some more leniency on easy logic
self.connect(
beyond_fault,
red_waterfall,
r.can_jump | r.jetpack(150) | (r.jetpack(100) & r.difficulty("medium")),
)
self.restrict("Secret Red Waterfall Passage", r.explosives)
shaman_secret = self.region(
"Shaman Secret",
[
"Dancing Shaman Atomic Health 1",
"Dancing Shaman Atomic Health 2",
"Dancing Shaman Atomic Health 3",
"Secret Dancing Shaman",
],
)
# Can clip through the right side lava waterfall
self.connect(red_waterfall, shaman_secret, r.can_use | r.crouch_jump)
ship_entrance = self.region(
"Ship Entrance",
[
"MP Cracked Wall Bottom Pipebombs",
"Cracked Wall Bottom Atomic Health",
"Cracked Wall Middle Atomic Health",
"Cracked Wall Protective Boots",
"Cracked Wall Medkit",
"Cracked Wall End Atomic Health",
"Canyon Pillars RPG",
"Spaceship Entrance Armor",
],
)
# some leniency on easy
self.connect(
beyond_fault,
ship_entrance,
self.event("Canyon Explosion")
& (r.can_jump | r.jetpack(150) | (r.jetpack(100) & r.difficulty("medium"))),
)
top_of_spaceship = self.region(
"Top of Spaceship",
["Secret Top of Spaceship", "Top of Spaceship Atomic Health"],
)
self.connect(
ship_entrance,
top_of_spaceship,
r.can_open
| r.jetpack(250)
| (r.jetpack(200) & r.difficulty("medium"))
| r.fast_crouch_jump,
)
spaceship = self.region(
"Spaceship",
[
"Spaceship Shaft RPG",
"Spaceship Shaft Chaingun",
"Battlelord Medkit",
"Battlelord Atomic Health 1",
"Battlelord Atomic Health 2",
"Battlelord Jetpack",
"Battlelord Armor",
"Exit",
],
)
# Big drop, can't get back
self.connect(ship_entrance, spaceship, r.can_open)
# Clip to DM exit near boss drop
self.restrict(
"Exit",
r.can_kill_boss_1
| (r.glitched & r.difficulty("hard") & r.fast_sprint & r.can_jump),
)
self.restrict("Spaceship Shaft RPG", r.jump)
self.restrict("Spaceship Shaft Chaingun", r.jump)
return ret