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

309 lines
6.6 KiB
Python

from ..assembler import ASM
from ..roomEditor import RoomEditor, ObjectHorizontal, ObjectVertical, Object
from .. import entityData
def addMultiworldShop(rom, this_player, player_count):
# Make a copy of the shop into GrandpaUlrira house
re = RoomEditor(rom, 0x2A9)
re.objects = [
ObjectHorizontal(1,1, 0x00, 8),
ObjectHorizontal(1,2, 0x00, 8),
ObjectHorizontal(1,3, 0xCD, 8),
Object(2, 0, 0xC7),
Object(7, 0, 0xC7),
Object(7, 7, 0xFD),
] + re.getWarps()
re.entities = [(0, 6, 0xD4)]
for n in range(player_count):
if n != this_player:
re.entities.append((n + 1, 6, 0xD4))
re.animation_id = 0x04
re.floor_object = 0x0D
re.store(rom)
# Fix the tileset
rom.banks[0x20][0x2EB3 + 0x2A9 - 0x100] = rom.banks[0x20][0x2EB3 + 0x2A1 - 0x100]
re = RoomEditor(rom, 0x0B1)
re.getWarps()[0].target_x = 128
re.store(rom)
# Load the shopkeeper sprites
entityData.SPRITE_DATA[0xD4] = entityData.SPRITE_DATA[0x4D]
rom.patch(0x03, 0x01CF, "00", "98") # Fix the hitbox of the ghost to be 16x16
# Patch Ghost to work as a multiworld shop
rom.patch(0x19, 0x1E18, 0x20B0, ASM("""
ld a, $01
ld [$C50A], a ; this stops link from using items
ldh a, [$EE] ; X
cp $08
; Jump to other code which is placed on the old owl code. As we do not have enough space here.
jp z, shopItemsHandler
;Draw shopkeeper
ld de, OwnerSpriteData
call $3BC0 ; render sprite pair
ldh a, [$E7] ; frame counter
swap a
and $01
call $3B0C ; set sprite variant
ldh a, [$F0]
and a
jr nz, checkTalkingResult
call $7CA2 ; prevent link from moving into the sprite
call $7CF0 ; check if talking to NPC
call c, talkHandler ; talk handling
ret
checkTalkingResult:
ld a, [$C19F]
and a
ret nz ; still taking
call $3B12 ; increase entity state
ld [hl], $00
ld a, [$C177] ; dialog selection
and a
ret nz
jp TalkResultHandler
OwnerSpriteData:
;db $60, $03, $62, $03, $62, $23, $60, $23 ; down
db $64, $03, $66, $03, $66, $23, $64, $23 ; up
;db $68, $03, $6A, $03, $6C, $03, $6E, $03 ; left
;db $6A, $23, $68, $23, $6E, $23, $6C, $23 ; right
shopItemsHandler:
; Render the shop items
ld h, $00
loop:
; First load links position to render the item at
ldh a, [$98] ; LinkX
ldh [$EE], a ; X
ldh a, [$99] ; LinkY
sub $0E
ldh [$EC], a ; Y
; Check if this is the item we have picked up
ld a, [$C509] ; picked up item in shop
dec a
cp h
jr z, .renderCarry
ld a, h
swap a
add a, $20
ldh [$EE], a ; X
ld a, $30
ldh [$EC], a ; Y
.renderCarry:
ld a, h
push hl
ldh [$F1], a ; variant
cp $03
jr nc, .singleSprite
ld de, ItemsDualSpriteData
call $3BC0 ; render sprite pair
jr .renderDone
.singleSprite:
ld de, ItemsSingleSpriteData
call $3C77 ; render sprite
.renderDone:
pop hl
.skipItem:
inc h
ld a, $07
cp h
jr nz, loop
; check if we want to pickup or drop an item
ldh a, [$CC]
and $30 ; A or B button
call nz, checkForPickup
; check if we have an item
ld a, [$C509] ; carry item
and a
ret z
; Set that link has picked something up
ld a, $01
ld [$C15C], a
call $0CAF ; reset spin attack...
; Check if we are trying to exit the shop and so drop our item.
ldh a, [$99]
cp $78
ret c
xor a
ld [$C509], a
ret
checkForPickup:
ldh a, [$9E] ; direction
cp $02
ret nz
ldh a, [$99] ; LinkY
cp $48
ret nc
ld a, $13
ldh [$F2], a ; play SFX
ld a, [$C509] ; picked up shop item
and a
jr nz, .drop
ldh a, [$98] ; LinkX
sub $08
swap a
and $07
ld [$C509], a ; picked up shop item
ret
.drop:
xor a
ld [$C509], a
ret
ItemsDualSpriteData:
db $60, $08, $60, $28 ; zol
db $68, $09 ; chicken (left)
ItemsSingleSpriteData: ; (first 3 entries are still dual sprites)
db $6A, $09 ; chicken (right)
db $14, $02, $14, $22 ; piece of power
;Real single sprite data starts here
db $00, $0F ; bomb
db $38, $0A ; rupees
db $20, $0C ; medicine
db $28, $0C ; heart
;------------------------------------trying to buy something starts here
talkHandler:
ld a, [$C509] ; carry item
add a, a
ret z ; check if we have something to buy
sub $02
ld hl, itemNames
ld e, a
ld d, b ; b=0
add hl, de
ld e, [hl]
inc hl
ld d, [hl]
ld hl, wCustomMessage
call appendString
dec hl
call padString
ld de, postMessage
call appendString
dec hl
ld a, $fe
ld [hl], a
ld de, $FFEF
add hl, de
ldh a, [$EE]
swap a
and $0F
add a, $30
ld [hl], a
ld a, $C9
call $2385 ; open dialog
call $3B12 ; increase entity state
ret
appendString:
ld a, [de]
inc de
and a
ret z
ldi [hl], a
jr appendString
padString:
ld a, l
and $0F
ret z
ld a, $20
ldi [hl], a
jr padString
itemNames:
dw itemZol
dw itemChicken
dw itemPieceOfPower
dw itemBombs
dw itemRupees
dw itemMedicine
dw itemHealth
postMessage:
db "For player X? Yes No ", $00
itemZol:
db m"Slime storm|100 {RUPEES}", $00
itemChicken:
db m"Coccu party|50 {RUPEES}", $00
itemPieceOfPower:
db m"Piece of Power|50 {RUPEES}", $00
itemBombs:
db m"10 Bombs|50 {RUPEES}", $00
itemRupees:
db m"100 {RUPEES}|200 {RUPEES}", $00
itemMedicine:
db m"Medicine|100 {RUPEES}", $00
itemHealth:
db m"Health refill|10 {RUPEES}", $00
TalkResultHandler:
ld hl, ItemPriceTableBCD
ld a, [$C509]
dec a
add a, a
ld c, a ; b=0
add hl, bc
ldi a, [hl]
ld d, [hl]
ld e, a
ld a, [$DB5D]
cp d
ret c
jr nz, .highEnough
ld a, [$DB5E]
cp e
ret c
.highEnough:
; Got enough money, take it.
ld hl, ItemPriceTableDEC
ld a, [$C509]
dec a
ld c, a ; b=0
add hl, bc
ld a, [hl]
ld [$DB92], a ; set substract buffer
; Set the item to send
ld hl, $DDFE
ld a, [$C509] ; currently picked up item
ldi [hl], a
ldh a, [$EE] ; X position of NPC
ldi [hl], a
ld hl, $DDF7
set 2, [hl]
; No longer picked up item
xor a
ld [$C509], a
ret
ItemPriceTableBCD:
dw $0100, $0050, $0050, $0050, $0200, $0100, $0010
ItemPriceTableDEC:
db $64, $32, $32, $32, $C8, $64, $0A
""", 0x5E18), fill_nop=True)