Archipelago/worlds/ladx/LADXR/patches/goal.py

318 lines
8.7 KiB
Python

from ..assembler import ASM
from ..roomEditor import RoomEditor, Object, ObjectVertical, ObjectHorizontal, ObjectWarp
from ..utils import formatText
def setRequiredInstrumentCount(rom, count):
rom.texts[0x1A3] = formatText("You need %d instruments" % (count))
if count >= 8:
return
if count < 0:
rom.patch(0x00, 0x31f5, ASM("ld a, [$D806]\nand $10\njr z, $25"), ASM(""), fill_nop=True)
rom.patch(0x20, 0x2dea, ASM("ld a, [$D806]\nand $10\njr z, $29"), ASM(""), fill_nop=True)
count = 0
# TODO: Music bugs out at the end, unless you have all instruments.
rom.patch(0x19, 0x0B79, None, "0000") # always spawn all instruments, we need the last one as that handles opening the egg.
rom.patch(0x19, 0x0BF4, ASM("jp $3BC0"), ASM("jp $7FE0")) # instead of rendering the instrument, jump to the code below.
rom.patch(0x19, 0x0BFE, ASM("""
; Normal check fo all instruments
ld e, $08
ld hl, $DB65
loop:
ldi a, [hl]
and $02
jr z, $12
dec e
jr nz, loop
"""), ASM("""
jp $7F2B ; jump to the end of the bank, where there is some space for code.
"""), fill_nop=True)
# Add some code at the end of the bank, as we do not have enough space to do this "in place"
rom.patch(0x19, 0x3F2B, "0000000000000000000000000000000000000000000000000000", ASM("""
ld d, $00
ld e, $08
ld hl, $DB65 ; start of has instrument memory
loop:
ld a, [hl]
and $02
jr z, noinc
inc d
noinc:
inc hl
dec e
jr nz, loop
ld a, d
cp $%02x ; check if we have a minimal of this amount of instruments.
jp c, $4C1A ; not enough instruments
jp $4C0B ; enough instruments
""" % (count)), fill_nop=True)
rom.patch(0x19, 0x3FE0, "0000000000000000000000000000000000000000000000000000", ASM("""
; Entry point of render code
ld hl, $DB65 ; table of having instruments
push bc
ldh a, [$F1]
ld c, a
add hl, bc
pop bc
ld a, [hl]
and $02 ; check if we have this instrument
ret z
jp $3BC0 ; jump to render code
"""), fill_nop=True)
def setSeashellGoal(rom, count):
rom.texts[0x1A3] = formatText("You need %d {SEASHELL}s" % (count))
# Remove the seashell mansion handler (as it will take your seashells) but put a heartpiece instead
re = RoomEditor(rom, 0x2E9)
re.entities = [(4, 4, 0x35)]
re.store(rom)
rom.patch(0x19, 0x0ACB, 0x0C21, ASM("""
ldh a, [$F8] ; room status
and $10
ret nz
ldh a, [$F0] ; active entity state
rst 0
dw state0, state1, state2, state3, state4
state0:
ld a, [$C124] ; room transition state
and a
ret nz
ldh a, [$99] ; link position Y
cp $70
ret nc
jp $3B12 ; increase entity state
state1:
call $0C05 ; get entity transition countdown
jr nz, renderShells
ld [hl], $10
call renderShells
ld hl, $C2B0 ; private state 1 table
add hl, bc
ld a, [wSeashellsCount]
cp [hl]
jp z, $3B12 ; increase entity state
ld a, [hl] ; increase the amount of compared shells
inc a
daa
ld [hl], a
ld hl, $C2C0 ; private state 2 table
add hl, bc
inc [hl] ; increase amount of displayed shells
ld a, $2B
ldh [$F4], a ; SFX
ret
state2:
ld a, [wSeashellsCount]
cp $%02d
jr c, renderShells
; got enough shells
call $3B12 ; increase entity state
call $0C05 ; get entity transition countdown
ld [hl], $40
jp renderShells
state3:
ld a, $23
ldh [$F2], a ; SFX: Dungeon opened
ld hl, $D806 ; egg room status
set 4, [hl]
ld a, [hl]
ldh [$F8], a ; current room status
call $3B12 ; increase entity state
ld a, $00
jp $4C2E
state4:
ret
renderShells:
ld hl, $C2C0 ; private state 2 table
add hl, bc
ld a, [hl]
cp $14
jr c, .noMax
ld a, $14
.noMax:
and a
ret z
ld c, a
ld hl, spriteRect
call $3CE6 ; RenderActiveEntitySpritesRect
ret
spriteRect:
db $10, $1E, $1E, $0C
db $10, $2A, $1E, $0C
db $10, $36, $1E, $0C
db $10, $42, $1E, $0C
db $10, $4E, $1E, $0C
db $10, $5A, $1E, $0C
db $10, $66, $1E, $0C
db $10, $72, $1E, $0C
db $10, $7E, $1E, $0C
db $10, $8A, $1E, $0C
db $24, $1E, $1E, $0C
db $24, $2A, $1E, $0C
db $24, $36, $1E, $0C
db $24, $42, $1E, $0C
db $24, $4E, $1E, $0C
db $24, $5A, $1E, $0C
db $24, $66, $1E, $0C
db $24, $72, $1E, $0C
db $24, $7E, $1E, $0C
db $24, $8A, $1E, $0C
""" % (count), 0x4ACB), fill_nop=True)
def setRaftGoal(rom):
rom.texts[0x1A3] = formatText("Just sail away.")
# Remove the egg and egg event handler.
re = RoomEditor(rom, 0x006)
for x in range(4, 7):
for y in range(0, 4):
re.removeObject(x, y)
re.objects.append(ObjectHorizontal(4, 1, 0x4d, 3))
re.objects.append(ObjectHorizontal(4, 2, 0x03, 3))
re.objects.append(ObjectHorizontal(4, 3, 0x03, 3))
re.entities = []
re.updateOverlay()
re.store(rom)
re = RoomEditor(rom, 0x08D)
re.objects[6].count = 4
re.objects[7].x += 2
re.objects[7].type_id = 0x2B
re.objects[8].x += 2
re.objects[8].count = 2
re.objects[9].x += 1
re.objects[11] = ObjectVertical(7, 5, 0x37, 2)
re.objects[12].x -= 1
re.objects[13].x -= 1
re.objects[14].x -= 1
re.objects[14].type_id = 0x34
re.objects[17].x += 3
re.objects[17].count -= 3
re.updateOverlay()
re.overlay[7 + 60] = 0x33
re.store(rom)
re = RoomEditor(rom, 0x0E9)
re.objects[30].count = 1
re.objects[30].x += 2
re.overlay[7 + 70] = 0x0E
re.overlay[8 + 70] = 0x0E
re.store(rom)
re = RoomEditor(rom, 0x0F9)
re.objects = [
ObjectHorizontal(4, 0, 0x0E, 6),
ObjectVertical(9, 0, 0xCA, 8),
ObjectVertical(8, 0, 0x0E, 8),
Object(3, 0, 0x38),
Object(3, 1, 0x32),
ObjectHorizontal(4, 1, 0x2C, 3),
Object(7, 1, 0x2D),
ObjectVertical(7, 2, 0x38, 5),
Object(7, 7, 0x34),
ObjectHorizontal(0, 7, 0x2F, 7),
ObjectVertical(2, 3, 0xE8, 4),
ObjectVertical(3, 2, 0xE8, 5),
ObjectVertical(4, 2, 0xE8, 2),
ObjectVertical(4, 4, 0x5C, 3),
ObjectVertical(5, 2, 0x5C, 5),
ObjectVertical(6, 2, 0x5C, 5),
Object(6, 4, 0xC6),
ObjectWarp(1, 0x1F, 0xF6, 136, 112)
]
re.updateOverlay(True)
re.entities.append((0, 0, 0x41))
re.store(rom)
re = RoomEditor(rom, 0x1F6)
re.objects[-1].target_x -= 16
re.store(rom)
# Fix the raft graphics (this overrides some unused graphic tiles)
rom.banks[0x31][0x21C0:0x2200] = rom.banks[0x2E][0x07C0:0x0800]
# Patch the owl entity to run our custom end handling.
rom.patch(0x06, 0x27F5, 0x2A77, ASM("""
ld a, [$DB95]
cp $0B
ret nz
; If map is not fully loaded, return
ld a, [$C124]
and a
ret nz
; Check if we are moving off the bottom of the map
ldh a, [$99]
cp $7D
ret c
; Move link back so it does not move off the map
ld a, $7D
ldh [$99], a
xor a
ld e, a
ld d, a
raftSearchLoop:
ld hl, $C280
add hl, de
ld a, [hl]
and a
jr z, .skipEntity
ld hl, $C3A0
add hl, de
ld a, [hl]
cp $6A
jr nz, .skipEntity
; Raft found, check if near the bottom of the screen.
ld hl, $C210
add hl, de
ld a, [hl]
cp $70
jr nc, raftOffWorld
.skipEntity:
inc e
ld a, e
cp $10
jr nz, raftSearchLoop
ret
raftOffWorld:
; Switch to the end credits
ld a, $01
ld [$DB95], a
ld a, $00
ld [$DB96], a
ret
"""), fill_nop=True)
# We need to run quickly trough part of the credits, or else it bugs out
# Skip the whole windfish part.
rom.patch(0x17, 0x0D39, None, ASM("ld a, $18\nld [$D00E], a\nret"))
# And skip the zoomed out laying on the log
rom.patch(0x17, 0x20ED, None, ASM("ld a, $00"))
# Finally skip some waking up on the log.
rom.patch(0x17, 0x23BC, None, ASM("jp $4CD9"))
rom.patch(0x17, 0x2476, None, ASM("jp $4CD9"))