LADX: Implement remake style warp selection (#1587)
This commit is contained in:
parent
d5d630dcf0
commit
e08deff6f9
|
@ -55,6 +55,9 @@ from .patches import tradeSequence as _
|
||||||
from . import hints
|
from . import hints
|
||||||
|
|
||||||
from .patches import bank34
|
from .patches import bank34
|
||||||
|
from .utils import formatText
|
||||||
|
from ..Options import TrendyGame, Palette
|
||||||
|
from .roomEditor import RoomEditor, Object
|
||||||
from .patches.aesthetics import rgb_to_bin, bin_to_rgb
|
from .patches.aesthetics import rgb_to_bin, bin_to_rgb
|
||||||
|
|
||||||
from .locations.keyLocation import KeyLocation
|
from .locations.keyLocation import KeyLocation
|
||||||
|
@ -323,7 +326,7 @@ def generateRom(args, settings, ap_settings, auth, seed_name, logic, rnd=None, m
|
||||||
|
|
||||||
# TODO: if 0 or 4, 5, remove inaccurate conveyor tiles
|
# TODO: if 0 or 4, 5, remove inaccurate conveyor tiles
|
||||||
|
|
||||||
from .roomEditor import RoomEditor, Object
|
|
||||||
room_editor = RoomEditor(rom, 0x2A0)
|
room_editor = RoomEditor(rom, 0x2A0)
|
||||||
|
|
||||||
if ap_settings["trendy_game"] == TrendyGame.option_easy:
|
if ap_settings["trendy_game"] == TrendyGame.option_easy:
|
||||||
|
@ -380,6 +383,8 @@ def generateRom(args, settings, ap_settings, auth, seed_name, logic, rnd=None, m
|
||||||
for channel in range(3):
|
for channel in range(3):
|
||||||
color[channel] = color[channel] * 31 // 0xbc
|
color[channel] = color[channel] * 31 // 0xbc
|
||||||
|
|
||||||
|
if ap_settings["warp_improvements"]:
|
||||||
|
patches.core.addWarpImprovements(rom, ap_settings["additional_warp_points"])
|
||||||
|
|
||||||
palette = ap_settings["palette"]
|
palette = ap_settings["palette"]
|
||||||
if palette != Palette.option_normal:
|
if palette != Palette.option_normal:
|
||||||
|
|
|
@ -255,8 +255,9 @@ noWrapDown:
|
||||||
""" % (type, map, room, x, y)), fill_nop=True)
|
""" % (type, map, room, x, y)), fill_nop=True)
|
||||||
|
|
||||||
# Patch the RAM clear not to delete our custom dialog when we screen transition
|
# Patch the RAM clear not to delete our custom dialog when we screen transition
|
||||||
|
# This is kind of horrible as it relies on bank 1 being loaded, lol
|
||||||
rom.patch(0x01, 0x042C, "C629", "6B7E")
|
rom.patch(0x01, 0x042C, "C629", "6B7E")
|
||||||
rom.patch(0x01, 0x3E6B, 0x3FFF, ASM("""
|
rom.patch(0x01, 0x3E6B, 0x3E7B, ASM("""
|
||||||
ld bc, $A0
|
ld bc, $A0
|
||||||
call $29DC
|
call $29DC
|
||||||
ld bc, $1200
|
ld bc, $1200
|
||||||
|
@ -537,3 +538,205 @@ OAMData:
|
||||||
gfx_low = "\n".join([line.split(" ")[n] for line in tile_graphics.split("\n")[8:]])
|
gfx_low = "\n".join([line.split(" ")[n] for line in tile_graphics.split("\n")[8:]])
|
||||||
rom.banks[0x38][0x1400+n*0x20:0x1410+n*0x20] = utils.createTileData(gfx_high)
|
rom.banks[0x38][0x1400+n*0x20:0x1410+n*0x20] = utils.createTileData(gfx_high)
|
||||||
rom.banks[0x38][0x1410+n*0x20:0x1420+n*0x20] = utils.createTileData(gfx_low)
|
rom.banks[0x38][0x1410+n*0x20:0x1420+n*0x20] = utils.createTileData(gfx_low)
|
||||||
|
|
||||||
|
def addWarpImprovements(rom, extra_warps):
|
||||||
|
# Patch in a warp icon
|
||||||
|
tile = utils.createTileData( \
|
||||||
|
"""11111111
|
||||||
|
10000000
|
||||||
|
10200320
|
||||||
|
10323200
|
||||||
|
10033300
|
||||||
|
10023230
|
||||||
|
10230020
|
||||||
|
10000000""", key="0231")
|
||||||
|
MINIMAP_BASE = 0x3800
|
||||||
|
|
||||||
|
# This is replacing a junk tile never used on the minimap
|
||||||
|
rom.banks[0x2C][MINIMAP_BASE + len(tile) * 0x65 : MINIMAP_BASE + len(tile) * 0x66] = tile
|
||||||
|
|
||||||
|
# Allow using ENTITY_WARP for finding which map sections are warps
|
||||||
|
# Interesting - 3CA0 should be free, but something has pushed all the code forward a byte
|
||||||
|
rom.patch(0x02, 0x3CA1, None, ASM("""
|
||||||
|
ld e, $0F
|
||||||
|
ld d, $00
|
||||||
|
warp_search_loop:
|
||||||
|
; Warp search loop
|
||||||
|
ld hl, $C3A0
|
||||||
|
add hl, de ; $5FE1: $19
|
||||||
|
ld a, [hl] ; $5FE2: $7E
|
||||||
|
cp $61 ; ENTITY_WARP
|
||||||
|
jr nz, search_continue ; if it's not a warp, check the next one
|
||||||
|
ld hl, $C280
|
||||||
|
add hl, de
|
||||||
|
ld a, [hl]
|
||||||
|
and a
|
||||||
|
jr z, search_continue ; if this is despawned, check the next one
|
||||||
|
found:
|
||||||
|
jp $511B ; found
|
||||||
|
search_continue:
|
||||||
|
dec e
|
||||||
|
ld a, e
|
||||||
|
cp $FF
|
||||||
|
jr nz, warp_search_loop
|
||||||
|
|
||||||
|
not_found:
|
||||||
|
jp $512B
|
||||||
|
|
||||||
|
"""))
|
||||||
|
|
||||||
|
# Insert redirect to above code
|
||||||
|
rom.patch(0x02, 0x1109, ASM("""
|
||||||
|
ldh a, [$F6]
|
||||||
|
cp 1
|
||||||
|
|
||||||
|
"""), ASM("""
|
||||||
|
jp $7CA1
|
||||||
|
nop
|
||||||
|
"""))
|
||||||
|
# Leaves some extra bytes behind, if we need more space in 0x02
|
||||||
|
|
||||||
|
# On warp hole, open map instead
|
||||||
|
rom.patch(0x19, 0x1DB9, None, ASM("""
|
||||||
|
ld a, 7 ; Set GAMEPLAY_MAP
|
||||||
|
ld [$DB95], a
|
||||||
|
ld a, 0 ; reset subtype
|
||||||
|
ld [$DB96], a
|
||||||
|
ld a, 1 ; Set flag for using teleport
|
||||||
|
ld [$FFDD], a
|
||||||
|
|
||||||
|
ret
|
||||||
|
"""), fill_nop=True)
|
||||||
|
|
||||||
|
# Patch over some instructions that decided if we are in debug mode holding some
|
||||||
|
# buttons with instead checking for FFDD (why FFDD? It appears to be never used anywhere, so we repurpose it for "is in teleport mode")
|
||||||
|
rom.banks[0x01][0x17B8] = 0xDD
|
||||||
|
rom.banks[0x01][0x17B9] = 0xFF
|
||||||
|
rom.banks[0x01][0x17FD] = 0xDD
|
||||||
|
rom.banks[0x01][0x17FE] = 0xFF
|
||||||
|
|
||||||
|
# If in warp mode, don't allow manual exit
|
||||||
|
rom.patch(0x01, 0x1800, "20021E60", ASM("jp nz, $5818"), fill_nop=True)
|
||||||
|
|
||||||
|
# Allow warp with just B
|
||||||
|
rom.banks[0x01][0x17C0] = 0x20
|
||||||
|
|
||||||
|
# Allow cursor to move over black squares
|
||||||
|
# This allows warping to undiscovered areas - a fine cheat, but needs a check for wOverworldRoomStatus in the warp code
|
||||||
|
CHEAT_WARP_ANYWHERE = False
|
||||||
|
if CHEAT_WARP_ANYWHERE:
|
||||||
|
rom.patch(0x01, 0x1AE8, None, ASM("jp $5AF5"))
|
||||||
|
|
||||||
|
# This disables the arrows around the selection bubble
|
||||||
|
#rom.patch(0x01, 0x1B6F, None, ASM("ret"), fill_nop=True)
|
||||||
|
|
||||||
|
# Fix lag when moving the cursor
|
||||||
|
# One option - just disable the delay code
|
||||||
|
#rom.patch(0x01, 0x1A76, 0x1A76+3, ASM("xor a"), fill_nop=True)
|
||||||
|
#rom.banks[0x01][0x1A7C] = 0
|
||||||
|
# Another option - just remove the animation
|
||||||
|
rom.banks[0x01][0x1B20] = 0
|
||||||
|
rom.banks[0x01][0x1B3B] = 0
|
||||||
|
|
||||||
|
# Patch the icon for all teleports
|
||||||
|
all_warps = [0x01, 0x95, 0x2C, 0xEC]
|
||||||
|
|
||||||
|
|
||||||
|
if extra_warps:
|
||||||
|
# mamu
|
||||||
|
all_warps.append(0x45)
|
||||||
|
# Tweak the flute location
|
||||||
|
rom.banks[0x14][0x0E95] += 0x10
|
||||||
|
rom.banks[0x14][0x0EA3] += 0x01
|
||||||
|
|
||||||
|
mamu_pond = RoomEditor(rom, 0x45)
|
||||||
|
# Remove some tall grass so we can add a warp instead
|
||||||
|
mamu_pond.changeObject(1, 6, 0xE8)
|
||||||
|
mamu_pond.moveObject(1, 6, 3, 5)
|
||||||
|
mamu_pond.addEntity(3, 5, 0x61)
|
||||||
|
|
||||||
|
mamu_pond.store(rom)
|
||||||
|
|
||||||
|
# eagle
|
||||||
|
all_warps.append(0x0F)
|
||||||
|
room = RoomEditor(rom, 0x0F)
|
||||||
|
# Move one cliff edge and change it into a pit
|
||||||
|
room.changeObject(7, 6, 0xE8)
|
||||||
|
room.moveObject(7, 6, 6, 4)
|
||||||
|
|
||||||
|
# Add the warp
|
||||||
|
room.addEntity(6, 4, 0x61)
|
||||||
|
# move the two corners
|
||||||
|
room.moveObject(6, 7, 7, 7)
|
||||||
|
room.moveObject(6, 6, 7, 6)
|
||||||
|
for object in room.objects:
|
||||||
|
# Extend the lower wall
|
||||||
|
if ((object.x == 0 and object.y == 7)
|
||||||
|
# Extend the lower floor
|
||||||
|
or (object.x == 0 and object.y == 6)):
|
||||||
|
room.overlay[object.x + object.count + object.y * 10] = object.type_id
|
||||||
|
object.count += 1
|
||||||
|
room.store(rom)
|
||||||
|
|
||||||
|
for warp in all_warps:
|
||||||
|
# Set icon
|
||||||
|
rom.banks[0x20][0x168B + warp] = 0x55
|
||||||
|
# Set text
|
||||||
|
if not rom.banks[0x01][0x1959 + warp]:
|
||||||
|
rom.banks[0x01][0x1959 + warp] = 0x42
|
||||||
|
# Set palette
|
||||||
|
# rom.banks[0x20][0x178B + 0x95] = 0x1
|
||||||
|
|
||||||
|
# Setup [?!] icon on map and associated text
|
||||||
|
rom.banks[0x01][0x1909 + 0x42] = 0x2B
|
||||||
|
rom.texts[0x02B] = utils.formatText('Warp')
|
||||||
|
|
||||||
|
# call warp function (why not just jmp?!)
|
||||||
|
rom.patch(0x01, 0x17C3, None, ASM("""
|
||||||
|
call $7E7B
|
||||||
|
ret
|
||||||
|
"""))
|
||||||
|
|
||||||
|
# Build a switch statement by hand
|
||||||
|
warp_jump = "".join(f"cp ${hex(warp)[2:]}\njr z, success\n" for warp in all_warps)
|
||||||
|
|
||||||
|
rom.patch(0x01, 0x3E7B, None, ASM(f"""
|
||||||
|
TeleportHandler:
|
||||||
|
|
||||||
|
ld a, [$DBB4] ; Load the current selected tile
|
||||||
|
; TODO: check if actually revealed so we can have free movement
|
||||||
|
; Check cursor against different tiles to see if we are selecting a warp
|
||||||
|
{warp_jump}
|
||||||
|
jr exit
|
||||||
|
|
||||||
|
success:
|
||||||
|
ld a, $0B
|
||||||
|
ld [$DB95], a ; Gameplay type
|
||||||
|
xor a
|
||||||
|
ld [$D401], a ; wWarp0MapCategory
|
||||||
|
ldh [$DD], a ; unset teleport flag(!!!)
|
||||||
|
ld [$D402], a ; wWarp0Map
|
||||||
|
ld a, [$DBB4] ; wDBB4
|
||||||
|
ld [$D403], a ; wWarp0Room
|
||||||
|
|
||||||
|
ld a, $68
|
||||||
|
ld [$D404], a ; wWarp0DestinationX
|
||||||
|
ldh [$98], a ; LinkPositionY
|
||||||
|
ld [$D475], a
|
||||||
|
ld a, $70
|
||||||
|
ld [$D405], a ; wWarp0DestinationY
|
||||||
|
ldh [$99], a ; LinkPositionX
|
||||||
|
ld a, $66
|
||||||
|
ld [$D416], a ; wWarp0PositionTileIndex
|
||||||
|
ld a, $07
|
||||||
|
ld [$DB96], a ; wGameplaySubtype
|
||||||
|
ldh a, [$A2]
|
||||||
|
ld [$DBC8], a
|
||||||
|
call $0C83 ; ApplyMapFadeOutTransition
|
||||||
|
xor a ; $5DF3: $AF
|
||||||
|
ld [$C167], a ; $5DF4: $EA $67 $C1
|
||||||
|
|
||||||
|
exit:
|
||||||
|
ret
|
||||||
|
"""))
|
||||||
|
|
||||||
|
|
|
@ -379,6 +379,19 @@ class Palette(Choice):
|
||||||
option_pink = 4
|
option_pink = 4
|
||||||
option_inverted = 5
|
option_inverted = 5
|
||||||
|
|
||||||
|
class WarpImprovements(DefaultOffToggle):
|
||||||
|
"""
|
||||||
|
[On] Adds remake style warp screen to the game. Choose your warp destination on the map after jumping in a portal and press B to select.
|
||||||
|
[Off] No change
|
||||||
|
"""
|
||||||
|
|
||||||
|
class AdditionalWarpPoints(DefaultOffToggle):
|
||||||
|
"""
|
||||||
|
[On] (requires warp improvements) Adds a warp point at Crazy Tracy's house (the Mambo teleport spot) and Eagle's Tower
|
||||||
|
[Off] No change
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
links_awakening_options: typing.Dict[str, typing.Type[Option]] = {
|
links_awakening_options: typing.Dict[str, typing.Type[Option]] = {
|
||||||
'logic': Logic,
|
'logic': Logic,
|
||||||
# 'heartpiece': DefaultOnToggle, # description='Includes heart pieces in the item pool'),
|
# 'heartpiece': DefaultOnToggle, # description='Includes heart pieces in the item pool'),
|
||||||
|
@ -400,6 +413,8 @@ links_awakening_options: typing.Dict[str, typing.Type[Option]] = {
|
||||||
# 'bowwow': Bowwow,
|
# 'bowwow': Bowwow,
|
||||||
# 'overworld': Overworld,
|
# 'overworld': Overworld,
|
||||||
'link_palette': LinkPalette,
|
'link_palette': LinkPalette,
|
||||||
|
'warp_improvements': WarpImprovements,
|
||||||
|
'additional_warp_points': AdditionalWarpPoints,
|
||||||
'trendy_game': TrendyGame,
|
'trendy_game': TrendyGame,
|
||||||
'gfxmod': GfxMod,
|
'gfxmod': GfxMod,
|
||||||
'palette': Palette,
|
'palette': Palette,
|
||||||
|
|
Loading…
Reference in New Issue