Beispiel #1
0
def removeOwlEvents(rom):
    # Remove all the owl events from the entity tables.
    for room in range(0x100):
        re = RoomEditor(rom, room)
        if re.hasEntity(0x41):
            re.removeEntities(0x41)
            re.store(rom)
    # Clear texts used by the owl. Potentially reused somewhere else.
    rom.texts[0x0D9] = b'\xff'  # used by boomerang
    # 1 Used by empty chest (master stalfos message)
    # 9 used by keysanity items
    # 1 used by bowwow in chest
    # 1 used by item for other player message
    # 2 used by arrow chest messages
    # 2 used by tunics
    for idx in range(0x0BE, 0x0CE):
        rom.texts[idx] = b'\xff'
Beispiel #2
0
def doubleTrouble(rom):
    for n in range(0x316):
        if n == 0x2FF:
            continue
        re = RoomEditor(rom, n)
        # Bosses
        if re.hasEntity(0x59):  # Moldorm (TODO; double heart container drop)
            re.removeEntities(0x59)
            re.entities += [(3, 2, 0x59), (4, 2, 0x59)]
            re.store(rom)
        if re.hasEntity(0x5C):  # Ghini
            re.removeEntities(0x5C)
            re.entities += [(3, 2, 0x5C), (4, 2, 0x5C)]
            re.store(rom)
        if re.hasEntity(0x5B):  # slime eye
            re.removeEntities(0x5B)
            re.entities += [(3, 2, 0x5B), (6, 2, 0x5B)]
            re.store(rom)
        if re.hasEntity(0x65):  # angler fish
            re.removeEntities(0x65)
            re.entities += [(6, 2, 0x65), (6, 5, 0x65)]
            re.store(rom)
        # Slime eel bugs out on death if duplicated.
        # if re.hasEntity(0x5D):  # slime eel
        #     re.removeEntities(0x5D)
        #     re.entities += [(6, 2, 0x5D), (6, 5, 0x5D)]
        #     re.store(rom)
        if re.hasEntity(
                0x5A):  # facade (TODO: Drops two hearts, shared health?)
            re.removeEntities(0x5A)
            re.entities += [(2, 3, 0x5A), (6, 3, 0x5A)]
            re.store(rom)
        # Evil eagle causes a crash, and messes up the intro sequence and generally is just a mess if I spawn multiple
        # if re.hasEntity(0x63):  # evil eagle
        #     re.removeEntities(0x63)
        #     re.entities += [(3, 4, 0x63), (2, 4, 0x63)]
        #     re.store(rom)
        #     # Remove that links movement is blocked
        #     rom.patch(0x05, 0x2258, ASM("ldh [$A1], a"), "0000")
        #     rom.patch(0x05, 0x1AE3, ASM("ldh [$A1], a"), "0000")
        #     rom.patch(0x05, 0x1C5D, ASM("ldh [$A1], a"), "0000")
        #     rom.patch(0x05, 0x1C8D, ASM("ldh [$A1], a"), "0000")
        #     rom.patch(0x05, 0x1CAF, ASM("ldh [$A1], a"), "0000")
        if re.hasEntity(0x62):  # hot head (TODO: Drops thwo hearts)
            re.removeEntities(0x62)
            re.entities += [(2, 2, 0x62), (4, 4, 0x62)]
            re.store(rom)
        if re.hasEntity(0xF9):  # hardhit beetle
            re.removeEntities(0xF9)
            re.entities += [(2, 2, 0xF9), (5, 4, 0xF9)]
            re.store(rom)
        # Minibosses
        if re.hasEntity(0x89):
            re.removeEntities(0x89)
            re.entities += [(2, 3, 0x89), (6, 3, 0x89)]
            re.store(rom)
        if re.hasEntity(0x81):
            re.removeEntities(0x81)
            re.entities += [(2, 3, 0x81), (6, 3, 0x81)]
            re.store(rom)
        if re.hasEntity(0x60):
            dodongo = [e for e in re.entities if e[2] == 0x60]
            x = (dodongo[0][0] + dodongo[1][0]) // 2
            y = (dodongo[0][1] + dodongo[1][1]) // 2
            re.entities += [(x, y, 0x60)]
            re.store(rom)
        if re.hasEntity(0x8e):
            re.removeEntities(0x8e)
            re.entities += [(1, 1, 0x8e), (7, 1, 0x8e)]
            re.store(rom)
        if re.hasEntity(0x92):
            re.removeEntities(0x92)
            re.entities += [(2, 3, 0x92), (4, 3, 0x92)]
            re.store(rom)
        if re.hasEntity(0xf4):
            re.removeEntities(0xf4)
            re.entities += [(2, 1, 0xf4), (6, 1, 0xf4)]
            re.store(rom)
        if re.hasEntity(0xf8):
            re.removeEntities(0xf8)
            re.entities += [(2, 2, 0xf8), (6, 2, 0xf8)]
            re.store(rom)
        if re.hasEntity(0xe4):
            re.removeEntities(0xe4)
            re.entities += [(5, 2, 0xe4), (5, 5, 0xe4)]
            re.store(rom)

        if re.hasEntity(0x88):  # Armos knight (TODO: double item drop)
            re.removeEntities(0x88)
            re.entities += [(3, 3, 0x88), (6, 3, 0x88)]
            re.store(rom)
        if re.hasEntity(
                0x87
        ):  # Lanmola (TODO: killing one drops the item, and marks as done)
            re.removeEntities(0x87)
            re.entities += [(2, 2, 0x87), (1, 1, 0x87)]
            re.store(rom)
Beispiel #3
0
def removeOwlEvents(rom):
    # Remove all the owl events from the entity tables.
    for room in range(0x100):
        re = RoomEditor(rom, room)
        if re.hasEntity(0x41):
            re.removeEntities(0x41)
            re.store(rom)
    # Clear texts used by the owl. Potentially reused somewhere o else.
    rom.texts[0x0D9] = b'\xff'  # used by boomerang
    # 1 Used by empty chest (master stalfos message)
    # 8 unused (0x0C0-0x0C7)
    # 1 used by bowwow in chest
    # 1 used by item for other player message
    # 2 used by arrow chest messages
    # 2 used by tunics
    for idx in range(0x0BE, 0x0CE):
        rom.texts[idx] = b'\xff'


    # Patch the owl entity into a ghost to allow refill of powder/bombs/arrows
    rom.texts[0xC0] = formatText("Everybody hates me, so I give away free things in the hope people will love me. Want something?", ask="Okay No")
    rom.texts[0xC1] = formatText("Good for you.")
    rom.patch(0x06, 0x27F5, 0x2A77, ASM("""
    ; Check if we have powder or bombs.
    ld   e, INV_SIZE
    ld   hl, $DB00
loop:
    ldi  a, [hl]
    cp   $02 ; bombs
    jr   z, hasProperItem
    cp   $0C ; powder
    jr   z, hasProperItem
    cp   $05 ; bow
    jr   z, hasProperItem
    dec  e
    jr   nz, loop
    ret
hasProperItem:
    
    ; Render ghost
    ld de, sprite
    call $3BC0

    call $64C6 ; check if game is busy (pops this stack frame if busy)

    ldh a, [$E7] ; frame counter
    swap a
    and  $01
    call $3B0C ; set entity sprite variant
    call $641A ; check collision
    ldh  a, [$F0] ;entity state
    rst 0
    dw  waitForTalk
    dw  talking

waitForTalk:
    call $645D ; check if talked to
    ret  nc
    ld   a, $C0
    call $2385 ; open dialog
    call $3B12 ; increase entity state
    ret

talking:
    ; Check if we are still talking
    ld   a, [$C19F]
    and  a
    ret  nz
    call $3B12 ; increase entity state
    ld   [hl], $00 ; set to state 0
    ld   a, [$C177] ; get which option we selected
    and  a
    ret  nz

    ; Give powder
    ld   a, [$DB4C]
    cp   $10
    jr   nc, doNotGivePowder
    ld   a, $10
    ld   [$DB4C], a
doNotGivePowder:

    ld   a, [$DB4D]
    cp   $10
    jr   nc, doNotGiveBombs
    ld   a, $10
    ld   [$DB4D], a
doNotGiveBombs:

    ld   a, [$DB45]
    cp   $10
    jr   nc, doNotGiveArrows
    ld   a, $10
    ld   [$DB45], a
doNotGiveArrows:

    ld   a, $C1
    call $2385 ; open dialog
    ret

sprite:
    db   $76, $09, $78, $09, $7A, $09, $7C, $09
""", 0x67F5), fill_nop=True)
    rom.patch(0x20, 0x0322 + 0x41 * 2, "734A", "564B")  # Remove the owl init handler

    re = RoomEditor(rom, 0x2A3)
    re.entities.append((7, 6, 0x41))
    re.store(rom)
Beispiel #4
0
 def read(self, rom):
     re = RoomEditor(rom, 0x0F2)
     if re.hasEntity(0x31):
         return SWORD
     return super().read(rom)
Beispiel #5
0
def removeOwlEvents(rom):
    # Remove all the owl events from the entity tables.
    for room in range(0x100):
        re = RoomEditor(rom, room)
        if re.hasEntity(0x41):
            re.removeEntities(0x41)
            re.store(rom)
    # Clear texts used by the owl. Potentially reused somewhere else.
    rom.texts[0x0D9] = b'\xff'  # used by boomerang
    # 1 Used by empty chest (master stalfos message)
    # 8 unused (0x0C0-0x0C7)
    # 1 used by bowwow in chest
    # 1 used by item for other player message
    # 2 used by arrow chest messages
    # 2 used by tunics
    for idx in range(0x0BE, 0x0CE):
        rom.texts[idx] = b'\xff'

    # Patch the owl entity to allow refill of powder/bombs
    rom.texts[0xC0] = formatText("Hoot!\nHoot!\nOut of stock?", ask="Okay No")
    rom.texts[0xC1] = formatText(
        "Hoot!\nHoot! Hoot!\nHoot!\nHere are a few things for you.")
    rom.patch(0x06,
              0x27F5,
              0x2A77,
              ASM(
                  """
    ; Render owl
    ld de, sprite
    call $3BC0

    call $64C6 ; check if game is busy (pops this stack frame if busy)

    ldh a, [$E7] ; frame counter
    cp $F0
    jr c, eyesOpen
    ld a, $01
    jr setSpriteVariant
eyesOpen:
    xor a
setSpriteVariant:
    call $3B0C ; set entity sprite variant
    call $641A ; check collision
    ldh  a, [$F0] ;entity state
    rst 0
    dw  waitForTalk
    dw  talking

waitForTalk:
    call $645D ; check if talked to
    ret  nc
    ld   a, $C0
    call $2385 ; open dialog
    call $3B12 ; increase entity state
    ret

talking:
    ; Check if we are still talking
    ld   a, [$C19F]
    and  a
    ret  nz
    call $3B12 ; increase entity state
    ld   [hl], $00 ; set to state 0
    ld   a, [$C177] ; get which option we selected
    and  a
    ret  nz

    ; Give powder
    ld   a, [$DB4C]
    cp   $10
    jr   nc, doNotGivePowder
    ld   a, $10
    ld   [$DB4C], a
doNotGivePowder:

    ld   a, [$DB4D]
    cp   $10
    jr   nc, doNotGiveBombs
    ld   a, $10
    ld   [$DB4D], a
doNotGiveBombs:

    ld   a, $C1
    call $2385 ; open dialog
    ret

sprite:
    db   $78, $01, $78, $21, $7A, $01, $7A, $21
""", 0x67F5),
              fill_nop=True)