diff --git a/assembler.const b/assembler.const index 35bc5f18..51e68949 100644 --- a/assembler.const +++ b/assembler.const @@ -171,6 +171,15 @@ DE11:wCuccoSpawnCount DE12:wDropBombSpawnCount DE13:wLinkSpawnDelay +DD20:wQuickswapSlot +DD21:wQuickswapIndex +DD22:wQuickswapPreviewB1 +DD23:wQuickswapPreviewB2 +DD24:wQuickswapPreviewA1 +DD25:wQuickswapPreviewA2 +B030:wRecentItemListSlotB ; length of 16 bytes +B040:wRecentItemListSlotA ; length of 16 bytes + FF00:rP1 FF01:rSB FF02:rSC diff --git a/generator.py b/generator.py index f15035cc..f02b73e7 100644 --- a/generator.py +++ b/generator.py @@ -55,6 +55,7 @@ import patches.tradeSequence import patches.alttp import patches.colorBook +import patches.quickswap import hints import locations.keyLocation @@ -251,9 +252,11 @@ def generateRom(args, settings, seed, logic, *, rnd=None): patches.inventory.songSelectAfterOcarinaSelect(rom) if settings.quickswap == 'a': - patches.core.quickswap(rom, 1) + patches.quickswap.simple_quickswap(rom, 1) elif settings.quickswap == 'b': - patches.core.quickswap(rom, 0) + patches.quickswap.simple_quickswap(rom, 0) + elif settings.quickswap == 'dynamic': + patches.quickswap.dynamic_quickswap(rom, settings) hints.addHints(rom, rnd, logic.iteminfo_list) diff --git a/patches/bank3e.asm/main.asm b/patches/bank3e.asm/main.asm index bdf77828..a91ebd62 100644 --- a/patches/bank3e.asm/main.asm +++ b/patches/bank3e.asm/main.asm @@ -26,6 +26,17 @@ MainJumpTable: dw EvilShopQuestion ; 13 dw EvilShopBuy ; 14 dw OverrideShopMessage ; 15 + dw QuickswapDraw ; 16 + dw QuickswapResetB ; 17 + dw QuickswapResetA ; 18 + dw QuickswapResetMenuB ; 19 + dw QuickswapResetMenuA ; 1A + dw QuickswapResetOnNewItem ; 1B + dw Quickswap ; 1C + dw QuickswapRemoveArrow ; 1D + dw QuickswapResetOnGrab ; 1E + dw QuickswapUpdatePreview ; 1F + dw QuickswapResetOnFileLoad ; 20 StartGameMarinMessage: ; Injection to reset our frame counter @@ -43,6 +54,18 @@ StartGameMarinMessage: ldi [hl], a ;check counter low ldi [hl], a ;check counter high + push bc + ld hl, wRecentItemListSlotB + ld bc, wRecentItemListSlotA + ld d, $10 +.loop: + ldi [hl], a + ld [bc], a + inc bc + dec d + jr nz, .loop + pop bc + ; Show the normal message ld a, $01 jp $2385 @@ -155,4 +178,5 @@ WriteToVRAM: #INCLUDE "message.asm" #INCLUDE "owl.asm" #INCLUDE "evilshop.asm" -#INCLUDE "nightmareminiboss.asm" \ No newline at end of file +#INCLUDE "nightmareminiboss.asm" +#INCLUDE "quickswap.asm" \ No newline at end of file diff --git a/patches/bank3e.asm/quickswap.asm b/patches/bank3e.asm/quickswap.asm new file mode 100644 index 00000000..c0949a1b --- /dev/null +++ b/patches/bank3e.asm/quickswap.asm @@ -0,0 +1,316 @@ +QuickswapDraw: + ld bc, $2000 + call DrawQuickswapIndicator + ld bc, $2501 + jr DrawQuickswapIndicator + +QuickswapRemoveArrow: + ld bc, $2002 + call DrawQuickswapIndicator + ld bc, $2502 + +DrawQuickswapIndicator: + ld a, [wDrawCommandsSize] + ld e, a + ld d, $00 + add $04 + ld [wDrawCommandsSize], a + ld hl, wDrawCommand + add hl, de + ld a, $9C + ldi [hl], a + ld a, b + ldi [hl], a + xor a + ldi [hl], a + push hl + ld a, [wQuickswapSlot] + cp c + jr nz, .blank + ld a, $A3 + jr .arrow +.blank: + ld a, $BC +.arrow: + pop hl + ldi [hl], a + xor a + ldi [hl], a + ret + +QuickswapResetB: + ld a, [wQuickswapSlot] + and a + ret nz + call EnableSRAM + inc a + ld [wQuickswapSlot], a + xor a + ld [wQuickswapIndex], a + ld a, [$DB00] + ld hl, wRecentItemListSlotB + push bc + call QuickswapInsertItemInFront + call QuickswapDraw + pop bc + ret + +QuickswapResetA: + ld a, [wQuickswapSlot] + and a + ret z + call EnableSRAM + xor a + ld [wQuickswapSlot], a + ld [wQuickswapIndex], a + ld a, [$DB01] + ld hl, wRecentItemListSlotA + push bc + call QuickswapInsertItemInFront + call QuickswapDraw + pop bc + ret + +QuickswapResetOnGrab: + ld a, $01 + ldh [$FFA1], a + ld a, [$DB00] + cp $03 + jr z, QuickswapResetB + ld a, [$DB01] + cp $03 + jr z, QuickswapResetA + ret + +QuickswapResetMenuB: + call EnableSRAM + ld a, $01 + ld [wQuickswapSlot], a + xor a + ld [wQuickswapIndex], a + ld a, [$DB00] + ld hl, wRecentItemListSlotB + jr QuickswapInsertItemInFront + +QuickswapResetMenuA: + call EnableSRAM + xor a + ld [wQuickswapSlot], a + ld [wQuickswapIndex], a + ld a, [$DB01] + ld hl, wRecentItemListSlotA + jr QuickswapInsertItemInFront + +QuickswapResetOnNewItem: + call EnableSRAM + ld a, c + ld hl, wRecentItemListSlotB + call QuickswapInsertItemInFront + ld a, c + ld hl, wRecentItemListSlotA + +QuickswapInsertItemInFront: + and a + ret z + ld b, a + ld d, $08 +.loop: + ld e, [hl] + ldi [hl], a + ld a, e + cp b + ret z + ld a, [hl] + ld [hl], e + cp b + ret z + inc hl + dec d + jr nz, .loop + ret + +Quickswap: + ; Check for how many frames the Select button has been held + ld a, [$D45F] + cp $01 + jr z, .normalSwap + cp $14 + jr z, .resetSwap + ret c + ; Prevent the counter from overflowing + ld a, $15 + ld [$D45F], a + ret +.resetSwap: + xor a + ld [wQuickswapIndex], a +.normalSwap: + call EnableSRAM + ld a, [$DB00] + ld b, a + ld a, [$DB01] + ld c, a + ld a, [wQuickswapSlot] + and a + jr z, .recentItemsB + ld hl, wRecentItemListSlotA + jr .recentItemsA +.recentItemsB: + ld hl, wRecentItemListSlotB +.recentItemsA: + ld a, [wQuickswapIndex] + call QuickswapGetNextItem + and a + ret z + ; Perform swap + ld a, d + inc a + cp $10 + jr c, .storeNewIndex + xor a +.storeNewIndex: + ld [wQuickswapIndex], a + ld b, h + ld c, l + ld a, [wQuickswapSlot] + and a + jr z, .swapB + ld hl, $DB01 + jr .swapA +.swapB: + ld hl, $DB00 +.swapA: + ld a, [bc] + ld e, a + ld a, [hl] + ld [bc], a + ld [hl], e + ; Play sound + ld hl, $FFF2 + ld [hl], $0A + ret + +QuickswapUpdatePreview: + call EnableSRAM + ld a, c + and a + ld a, [$DB00] + ld b, a + ld a, [$DB01] + ld c, a + jr nz, .previewA + ld hl, wRecentItemListSlotB + ld a, [wQuickswapSlot] + and a + jr z, .useIndex + xor a + jr .startOfListB +.useIndex: + ld a, [wQuickswapIndex] +.startOfListB: + call QuickswapGetNextItem + ld [wQuickswapPreviewB1], a + ld b, a ; for the second swap, consider which item would be in the B slot after the first swap + and a + jr z, .endB + ld a, d + inc a + cp $10 + jr c, .nextPreviewB + xor a +.nextPreviewB: + ld hl, wRecentItemListSlotB + call QuickswapGetNextItem +.endB: + ld [wQuickswapPreviewB2], a + ret + +.previewA: + ld hl, wRecentItemListSlotA + ld a, [wQuickswapSlot] + and a + jr z, .startOfListA + ld a, [wQuickswapIndex] +.startOfListA: + call QuickswapGetNextItem + ld [wQuickswapPreviewA1], a + ld c, a ; for the second swap, consider which item would be in the A slot after the first swap + and a + jr z, .endA + ld a, d + inc a + cp $10 + jr c, .nextPreviewA + xor a +.nextPreviewA: + ld hl, wRecentItemListSlotA + call QuickswapGetNextItem +.endA: + ld [wQuickswapPreviewA2], a + ret + + ; Input: + ; a: index in recent items list where the search should start + ; bc: items that should not get equipped + ; hl: recent items list + ; Output: + ; a: which item is next, or 0 + ; d: index in recent items list of the next item if it exists +QuickswapGetNextItem: + and a, $0F + ld e, a + ld d, a + add a, l + ld l, a +.loop: + ldi a, [hl] + and a + jr z, .continue + cp b + jr z, .continue + cp c + jr z, .continue + ; Check if the selected item is still in the inventory + push de + push hl + ld e, a + ld hl, $DB00 + ld d, $10 +.checkInventorySlot: + ld a, [hl] + cp e + jr z, .foundInventorySlot + inc hl + dec d + jr nz, .checkInventorySlot + ; The selected item is not in the inventory + pop hl + pop de +.continue: + inc d + ld a, d + cp $10 + jr c, .checkFullLoop + ; Hacky way to loop hl back to the start of the list + ld a, l + dec a + and $F0 + ld l, a + xor a + ld d, a +.checkFullLoop: + cp e + jr nz, .loop + xor a + ret +.foundInventorySlot: + ld a, e + pop de + pop de + ret + +QuickswapResetOnFileLoad: + ld a, $02 + ld [$D6FF], a + call QuickswapResetMenuB + jp QuickswapResetMenuA \ No newline at end of file diff --git a/patches/bomb.py b/patches/bomb.py index 1be89db7..bba7934d 100644 --- a/patches/bomb.py +++ b/patches/bomb.py @@ -4,7 +4,7 @@ def onlyDropBombsWhenHaveBombs(rom): rom.patch(0x03, 0x1FC5, ASM("call $608C"), ASM("call $50B2")) # We use some of the unused chest code space here to remove the bomb if you do not have bombs in your inventory. - rom.patch(0x03, 0x10B2, 0x112A, ASM(""" + rom.patch(0x03, 0x10B2, "00" * 20, ASM(""" ld e, INV_SIZE ld hl, $DB00 ld a, $02 diff --git a/patches/core.py b/patches/core.py index e41e7431..92e4ed58 100644 --- a/patches/core.py +++ b/patches/core.py @@ -77,6 +77,8 @@ def cleanup(rom): rom.texts[0x02B] = b'' # unused text + rom.patch(0x03, 0x10B2, 0x112A, "", fill_nop=True) # unused chest code + def disablePhotoPrint(rom): rom.patch(0x28, 0x07CC, ASM("ldh [$FF01], a\nldh [$FF02], a"), "", fill_nop=True) # do not reset the serial link @@ -99,19 +101,6 @@ def fixMarinFollower(rom): rom.patch(0x18, 0x214F, ASM("ld a, [$C50F]"), ASM("ld a, [$C5AA]")) rom.patch(0x18, 0x2166, ASM("ld a, [$C50F]"), ASM("ld a, [$C5AA]")) -def quickswap(rom, button): - rom.patch(0x00, 0x1094, ASM("jr c, $49"), ASM("jr nz, $49")) # prevent agressive key repeat - rom.patch(0x00, 0x10BC, # Patch the open minimap code to swap the your items instead - ASM("xor a\nld [$C16B], a\nld [$C16C], a\nld [$DB96], a\nld a, $07\nld [$DB95], a"), ASM(""" - ld a, [$DB%02X] - ld e, a - ld a, [$DB%02X] - ld [$DB%02X], a - ld a, e - ld [$DB%02X], a - ret - """ % (button, button + 2, button, button + 2))) - def injectMainLoop(rom): rom.patch(0x00, 0x0346, ASM(""" ldh a, [$FFFE] @@ -434,7 +423,7 @@ def addFrameCounter(rom, check_count): ld a, [$B011] ; check count high call updateOAM - ld a, [$B010] ; death count low + ld a, [$B010] ; check count low call updateOAM ret diff --git a/patches/inventory.py b/patches/inventory.py index 2a963f9c..bb2808b2 100644 --- a/patches/inventory.py +++ b/patches/inventory.py @@ -36,8 +36,8 @@ def songSelectAfterOcarinaSelect(rom): ret """), fill_nop=True) # More code that opens the menu, use this to close the menu - rom.patch(0x20, 0x200D, 0x2027, ASM(""" - jp $6027 + rom.patch(0x20, 0x200D, 0x2020, ASM(""" + jp $6036 closeOcarinaMenu: ld a, [$C1B5] and a @@ -48,7 +48,7 @@ def songSelectAfterOcarinaSelect(rom): ld [$C1B9], a ; shows the closing animation ret """), fill_nop=True) - rom.patch(0x20, 0x2027, 0x2036, "", fill_nop=True) # Code that closes the ocarina menu on item select + # Code that closes the ocarina menu from $6020 to $6035 is now unused and overwritten by Quickswap rom.patch(0x20, 0x22A2, ASM(""" ld a, [$C159] @@ -337,7 +337,7 @@ def advancedInventorySubscreen(rom): # instead of doing an GBC specific check, jump to our custom handling rom.patch(0x20, 0x19DE, ASM("ldh a, [$FFFE]\nand a\njr z, $40"), ASM("call $7F00"), fill_nop=True) - rom.patch(0x20, 0x3F00, "00" * 0x100, ASM(""" + rom.patch(0x20, 0x3F00, "00" * 0x90, ASM(""" ld a, [wIsIndoor] and a jr z, RenderKeysCounts diff --git a/patches/quickswap.py b/patches/quickswap.py new file mode 100644 index 00000000..9e9aea45 --- /dev/null +++ b/patches/quickswap.py @@ -0,0 +1,286 @@ +from assembler import ASM + +def simple_quickswap(rom, button): + rom.patch(0x00, 0x1094, ASM("jr c, $49"), ASM("jr nz, $49")) # prevent agressive key repeat + rom.patch(0x00, 0x10BC, # Patch the open minimap code to swap the your items instead + ASM("xor a\nld [$C16B], a\nld [$C16C], a\nld [$DB96], a\nld a, $07\nld [$DB95], a"), ASM(""" + ld a, [$DB%02X] + ld e, a + ld a, [$DB%02X] + ld [$DB%02X], a + ld a, e + ld [$DB%02X], a + ret + """ % (button, button + 2, button, button + 2))) + +def dynamic_quickswap(rom, settings): + rom.patch(0x00, 0x3E47, ASM("call $6414"), ASM(""" + call $7D00 + """)) # when drawing the current hearts and rupees, also draw the Quickswap arrow + + rom.patch(0x02, 0x3D00, "00" * 8, ASM(""" + call $6414 + ld a, $16 ; QuickswapDraw + rst 8 + ret + """), fill_nop=True) + + rom.patch(0x00, 0x1258, ASM("ld a, [$DB00]"), ASM(""" + call $7D08 + """)) # when using the B item, move it to the front of the list and put the arrow on the A button + + rom.patch(0x02, 0x3D08, "00" * 8, ASM(""" + ld a, $17 ; QuickswapResetB + rst 8 + ld a, [$DB00] + ret + """), fill_nop=True) + + rom.patch(0x00, 0x126F, ASM("ld a, [$DB01]"), ASM(""" + call $7D10 + """)) # when using the A item, move it to the front of the list and put the arrow on the B button + + rom.patch(0x02, 0x3D10, "00" * 8, ASM(""" + ld a, $18 ; QuickswapResetA + rst 8 + ld a, [$DB01] + ret + """), fill_nop=True) + + # When equipping an item from the menu, move it to the front of the respective list + rom.patch(0x20, 0x2007, ASM("ld c, $00\nld b, $00"), ASM("call $6020"), fill_nop=True) + rom.patch(0x20, 0x1FE5, ASM("ld c, $01\nld b, $00"), ASM("call $6028"), fill_nop=True) + rom.patch(0x20, 0x2020, 0x2028, ASM(""" + ld a, $19 ; QuickswapResetMenuB + rst 8 + ld c, $00 + ld b, c + ret + """), fill_nop=True) + rom.patch(0x20, 0x2028, 0x2036, ASM(""" + ld a, $1A ; QuickswapResetMenuA + rst 8 + ld c, $01 + ld b, $00 + ret + """), fill_nop=True) + + rom.patch(0x03, 0x247E, ASM("ld hl, $DB00"), ASM(""" + call $50C6 + """)) # when obtaining a new item, put it at the front of the lists + + rom.patch(0x03, 0x10C6, "00" * 25, ASM(""" + push bc + push de + ld c, d + ld a, [$DBAF] + push af + ld a, $03 + ld [$DBAF], a + ld a, $1B ; QuickswapResetOnNewItem + rst 8 + pop af + ld [$DBAF], a + pop de + pop bc + ld hl, $DB00 + ret + """), fill_nop=True) + + rom.patch(0x00, 0x1081, ASM("and $B0"), ASM("and $80")) # enable use of Quickswap while A or B is pressed + + rom.patch(0x00, 0x1092, ASM("cp $04"), ASM("cp $01")) # trigger on first instead of fourth frame of holding Select + + rom.patch(0x00, 0x10BC, # patch the open minimap code to swap your items instead + ASM("xor a\nld [$C16B], a\nld [$C16C], a\nld [$DB96], a\nld a, $07\nld [$DB95], a"), ASM(""" + ld a, $1C ; Quickswap + rst 8 + jp $10DF + """), fill_nop=True) + + # When Select is being held, but the Quickswap action interrupted, do not trigger a new Quickswap as soon as it becomes available again + rom.patch(0x00, 0x109A, ASM("jr z, $3F"), ASM("jr z, $2F")) + rom.patch(0x00, 0x10A0, ASM("jr z, $39"), ASM("jr z, $29")) + rom.patch(0x00, 0x10A7, ASM("jr nc, $32"), ASM("jr nc, $22")) + rom.patch(0x00, 0x10B4, ASM("jr nz, $25"), ASM("jr nz, $15")) + rom.patch(0x00, 0x10BA, ASM("jr nz, $1F"), ASM("jr nz, $0F")) + rom.patch(0x00, 0x10CB, ASM("ld a, $02\nld [$2100], a\ncall $755B"), ASM(""" + ld a, $15 + ld [$D45F], a + jp $10DF + """), fill_nop=True) + + rom.patch(0x01, 0x138E, ASM("ld a, $02\nld [$D6FF], a\nret"), ASM(""" + ld a, $20 ; QuickswapResetOnFileLoad + rst 8 + ret + """), fill_nop=True) # when loading a file, ensure the currently equipped items are at the front of the respective lists + + rom.patch(0x20, 0x1AFD, ASM("ldh a, [$FFFE]\nand a\njr z, $3B"), ASM(""" + ld a, $1D ; QuickswapRemoveArrow + rst 8 + """), fill_nop=True) # remove the arrow when the inventory is opened + + rom.patch(0x00, 0x20F4, ASM("ld a, $01\nldh [$FFA1], a"), ASM(""" + ld a, $1E ; QuickswapResetOnGrab + rst 8 + """), fill_nop=True) # grab something using the Power Bracelets + + if settings.boomerang != "gift": + rom.patch(0x19, 0x06D5, ASM("ld a, $10\nld [$D368], a\nret"), ASM(""" + ld a, [$DB00] + jp $7F70 + """), fill_nop=True) # trade an item for the boomerang + + rom.patch(0x19, 0x071F, ASM("ld a, $10\nld [$D368], a\nret"), ASM(""" + ld a, [$DB7D] + jp $7F70 + """), fill_nop=True) # trade the boomerang back + + rom.patch(0x19, 0x3F70, "00" * 0x10, ASM(""" + push bc + ld c, a + ld a, $10 + ld [$D368], a + ld a, $1B ; QuickswapResetOnNewItem + rst 8 + pop bc + ret + """), fill_nop=True) + + # Draw a preview for the next equippable items by using Quickswap + rom.patch(0x20, 0x1CAD, ASM("ldh a, [$FFFE]\nand a\njr z, $03"), ASM(""" + call $7F90 + """), fill_nop=True) # load the next items in the rotations and update the tile attributes + + rom.patch(0x20, 0x3F90, "00" * 0x30, ASM(""" + ld a, c + cp $02 + ret nc + push bc + ld a, [$DBAF] + push af + ld a, $20 + ld [$DBAF], a + dec a ; QuickswapUpdatePreview + rst 8 + pop af + ld [$DBAF], a + pop bc + push bc + ld a, c + and a + jr nz, updateASlot + ld de, wQuickswapPreviewB1 + ld bc, $9C02 + call $7FC0 + pop bc + ret + + updateASlot: + ld de, wQuickswapPreviewA1 + ld bc, $9C07 + call $7FC0 + pop bc + ret + """), fill_nop=True) + + rom.patch(0x20, 0x3FC0, "00" * 0x21, ASM(""" + push de + ld a, [$DC90] + ld e, a + ld d, $00 + ld hl, $DC91 + add hl, de + add $05 + ld [$DC90], a + ld a, b + ldi [hl], a + ld a, c + ldi [hl], a + ld a, $01 + ldi [hl], a + pop de + call $7FE1 + call $7FE1 + xor a + ld [hl], a + ret + """), fill_nop=True) + + rom.patch(0x20, 0x3FE1, "00" * 0x1F, ASM(""" + ld a, [de] + inc de + cp $03 + jr nz, notLevel2Bracelet + ld a, [$DB43] + cp $02 + jr nz, notLevel2Bracelet + ldi [hl], a + ret + notLevel2Bracelet: + sla a + ld c, a + push hl + ld hl, $5C14 + ld b, $00 + add hl, bc + ld b, h + ld c, l + pop hl + ld a, [bc] + ldi [hl], a + ret + """), fill_nop=True) + + rom.patch(0x20, 0x1CE5, ASM("ld a, [de]\ninc de\nldi [hl], a\nld a, [de]\ninc de\nldi [hl], a"), ASM(""" + jp $7EC0 + """), fill_nop=True) # draw the item tiles + + rom.patch(0x20, 0x3EB0, "00" * 16, ASM(""" + ld bc, $5C36 + sla a + ld e, a + sla a + add e + add c ; should not overflow + ld c, a + ld a, [bc] + ldi [hl], a + ret + """), fill_nop=True) + + rom.patch(0x20, 0x3EC0, "00" * 64, ASM(""" + pop bc + push bc + ld a, c + and a + jr z, bSlot + dec a + jr z, aSlot + ld a, [de] + inc de + ldi [hl], a + ld a, [de] + inc de + ldi [hl], a + jp $5CEB + bSlot: + push de + ld a, [wQuickswapPreviewB1] + call $7EB0 + ld a, [wQuickswapPreviewB2] + call $7EB0 + jr end + aSlot: + push de + ld a, [wQuickswapPreviewA1] + call $7EB0 + ld a, [wQuickswapPreviewA2] + call $7EB0 + end: + pop de + inc de + inc de + jp $5CEB + """), fill_nop=True) \ No newline at end of file diff --git a/patches/seashell.py b/patches/seashell.py index 1384cffc..3620d417 100644 --- a/patches/seashell.py +++ b/patches/seashell.py @@ -71,7 +71,7 @@ def upgradeMansion(rom): rom.patch(0x19, 0x32A2, ASM("ld a, [wSeashellsCount]"), ASM("call $7F50")) rom.patch(0x19, 0x38B3, ASM("ld a, [wSeashellsCount]"), ASM("call $7F50")) # This is using free space in bank 0x19 because we need to return a value in A when called - rom.patch(0x19, 0x3F50, "00" * 0x30, ASM(""" + rom.patch(0x19, 0x3F50, "00" * 0x20, ASM(""" ; Maybe pretend like we have fewer seashells to prevent skipping a reward, ; or to prevent giving the final reward multiple times ld a, [$DAE9] ; event flags for seashell mansion diff --git a/settings.py b/settings.py index ded42f16..6daeba89 100644 --- a/settings.py +++ b/settings.py @@ -263,9 +263,13 @@ def __init__(self): '''), Setting('superweapons', 'Special', 'q', 'Enable super weapons', default=False, description='All items will be more powerful, faster, harder, bigger stronger. You name it.'), - Setting('quickswap', 'User options', 'Q', 'Quickswap', options=[('none', '', 'Disabled'), ('a', 'a', 'Swap A button'), ('b', 'b', 'Swap B button')], default='none', - description='Adds that the select button swaps with either A or B. The item is swapped with the top inventory slot. The map is not available when quickswap is enabled.', - aesthetic=True), + Setting('quickswap', 'User options', 'Q', 'Quickswap', options=[('none', '', 'Disabled'), ('a', 'a', 'Swap A button'), ('b', 'b', 'Swap B button'), ('dynamic', 'd', 'Dynamic')], default='none', + description=''' +Adds that the select button swaps with either A or B. The map is not available when quickswap is enabled. +[Swap A button] Press select to swap the A button item with the top-right inventory item. +[Swap B button] Press select to swap the B button item with the top-left inventory item. +[Dynamic] Press select to swap whichever equipped item was not used last with any inventory item, sorted by recently used on that button, cycling through them with repeated select presses. + ''', aesthetic=True), Setting('textmode', 'User options', 'f', 'Text mode', options=[('fast', '', 'Fast'), ('default', 'd', 'Normal'), ('none', 'n', 'No-text')], default='fast', description="""[Fast] Makes text appear twice as fast. [No-Text] Removes all text from the game""", aesthetic=True), diff --git a/www/js/options.js b/www/js/options.js index 24b8b422..095dfd7c 100755 --- a/www/js/options.js +++ b/www/js/options.js @@ -951,7 +951,7 @@ var options = "category": "User options", "short_key": "Q", "label": "Quickswap", - "description": "Adds that the select button swaps with either A or B. The item is swapped with the top inventory slot. The map is not available when quickswap is enabled.", + "description": "\nAdds that the select button swaps with either A or B. The map is not available when quickswap is enabled.\n[Swap A button] Press select to swap the A button item with the top-right inventory item.\n[Swap B button] Press select to swap the B button item with the top-left inventory item.\n[Dynamic] Press select to swap whichever equipped item was not used last with any inventory item, sorted by recently used on that button, cycling through them with repeated select presses.\n ", "aesthetic": true, "default": "none", "options": [ @@ -969,6 +969,11 @@ var options = "key": "b", "short": "b", "label": "Swap B button" + }, + { + "key": "dynamic", + "short": "d", + "label": "Dynamic" } ] }, @@ -1061,11 +1066,6 @@ var options = "short": "AgesGirl.bin>", "label": "AgesGirl" }, - { - "key": "BasicNew.png", - "short": "BasicNew.png>", - "label": "BasicNew" - }, { "key": "Bowwow.bin", "short": "Bowwow.bin>", @@ -1086,16 +1086,6 @@ var options = "short": "Kirby.bin>", "label": "Kirby" }, - { - "key": "LuckwurstJoe.png", - "short": "LuckwurstJoe.png>", - "label": "LuckwurstJoe" - }, - { - "key": "LuckwurstJoe2.png", - "short": "LuckwurstJoe2.png>", - "label": "LuckwurstJoe2" - }, { "key": "Luigi.bin", "short": "Luigi.bin>",