; NAME: Kamek's Cauldron (MP2) v1.1
; GAMES: MP2_USA
; EXECUTION: Direct
; PARAM: Space|SpaceToFace

; This event is designed to trade the player's item for coins. The
; coins given for each item depends on the array below in the code.
; Please refer to the array to edit the prices. During the event, the
; player will face the space designated by the parameter "SpaceToFace".

; If multiple item slots are turned ON, the player will be able to
; choose which item will be converted to coins. Since this event uses
; custom AI logic, the cursor will not appear when they select the
; prompt.

ADDIU SP SP -64
SW RA 60(SP)
SW S0 56(SP)
SW S1 52(SP)
SW S2 48(SP)
SW S3 44(SP)

; S0 = Current Player Struct
; S1 = Prompt Choice / Item Slot Offset
; S2 = Item Array
; S3 = Item String

;===Check for Bowser===
JAL GetCurrentPlayerIndex ; Get current player index at V0
NOP
SLTI T0 V0 4 ; If V0 < 4, T0 = 1
BEQZ T0 epilogue ; If T0 = 0, player is Bowser, go to epilogue
NOP

;===Set Player Idle Animation===
LI A0 -1 ; Set current player
LI A1 -1 ; Set idle animation
JAL SetBoardPlayerAnimation
LI A2 2 ; Loop the animation

;===Rotate Toward Space===
LI A0 -1 ; Set current player
LI A1 8 ; Rotate in 8 frames
JAL RotateCharacterModel
LI A2 SpaceToFace ; Face Space

JAL SleepProcess
LI A0 8 ; Wait 8 frames for player to rotate

;===Check Inventory===
JAL GetPlayerStruct
LI A0 -1 ; Get current player struct at V0
MOVE S0 V0 ; Copy V0 to S0

LUI S2 hi(ItemArray)
ADDIU S2 S2 lo(ItemArray) ; Load ItemArray into S2
LUI S3 hi(ItemStrings)
ADDIU S3 S3 lo(ItemStrings) ; Load ItemStrings into S3
LUI T3 0x800F ; 0x800F0000
ORI T3 T3 0x8CE2 ; 0x800F8CE2, Multiple Item Slots Flag
LBU T3 0(T3) ; Load flag into T3

LBU T0 0x19(S0) ; Load item value from offset of player struct
SB T0 0(S2) ; Store main item into item array
BEQZ T3 CheckOFF ; If multiple item slots are OFF, check
NOP
LBU T1 0x1E(S0) ; Load reserve item #1 from offset of player struct
SB T1 1(S2) ; Store reserve item #1 into item array
LBU T2 0x1F(S0) ; Load reserve item #2 from offset of player struct
SB T2 2(S2) ; Store reserve item #2 into item array

LW T4 0(S2) ; Load item array read into T4
LUI T3 0xFFFF ; 0xFFFF0000
ORI T3 T3 0xFF00 ; 0xFFFFFF00
BEQ T3 T4 NoItems ; If player has no items, go to NoItems
NOP
; else, player has at least one item

;===Prepare Item Prompt===
LUI A2 hi(BlackColour)
ADDIU A2 A2 lo(BlackColour) ; Default to black font
MOVE T4 A2 ; Copy A2 to T4
MOVE T6 A2 ; Copy A2 to T6
LUI T9 hi(BlueColour)
ADDIU T9 T9 lo(BlueColour) ; Load blue colour pointer into T9

LUI A3 hi(NullString)
ADDIU A3 A3 lo(NullString) ; Default to NullString
MOVE T5 A3 ; Copy A3 to T5
MOVE T7 A3 ; Copy A3 to T7

LI T0 0xFF ; No item index
LBU T2 0(S2) ; Load main item index into T2
BEQ T2 T0 ItemStringTwo ; If main item slot is empty, check next slot
NOP
MOVE A2 T9 ; Use blue font for main item
SLL T2 T2 5 ; Multiply item index by 32 (distance between item strings)
ADDU A3 S3 T2 ; Add to get main item string

ItemStringTwo:
LBU T2 1(S2) ; Load reserve item index #1 into T2
BEQ T2 T0 ItemStringThree ; If reserve slot is empty, check next slot
NOP
MOVE T4 T9 ; Use blue font for reserve item #1
SLL T2 T2 5 ; Multiply item index by 32 (distance between item strings)
ADDU T5 S3 T2 ; Add to get reserve item string #1

ItemStringThree:
LBU T2 2(S2) ; Load reserve item index #2 into T2
BEQ T2 T0 PrintItemPrompt ; If reserve slot is empty, print item prompt
NOP
MOVE T6 T9 ; Use blue font for reserve item #2
SLL T2 T2 5 ; Multiply item index by 32 (distance between item strings)
ADDU T7 S3 T2 ; Add to get reserve item string #2

;===Print Item Prompt===
PrintItemPrompt:
LUI A0 hi(PromptPlaceholder)
ADDIU A0 A0 lo(PromptPlaceholder) ; Parse destination
LUI A1 hi(ItemPrompt)
ADDIU A1 A1 lo(ItemPrompt) ; String formatter (%s)
; Pass main item font on A2
; Pass main item string on A3
SW T4 16(SP) ; Pass reserve item font #1 on A4
SW T5 20(SP) ; Pass reserve item string #1 on A5
SW T6 24(SP) ; Pass reserve item font #2 on A6
SW T7 28(SP) ; Pass reserve item string #2 on A7
JAL sprintf ; Convert strings to text
SW R0 32(SP) ; Terminator byte

;===Start Item Prompt===
StartPrompt:
LI A0 1 ; Display prompt
LUI A1 hi(PromptPlaceholder)
ADDIU A1 A1 lo(PromptPlaceholder) ; Display ItemPrompt with strings
JAL CallMessage
LI A2 0 ; No string

JAL DisableItems
MOVE A0 S2 ; Pass item logic array on A0

JAL PlayerIsCPU
LBU A0 0x1C(S0) ; Pass current player index on A0

BEQZ V0 WaitOnPrompt ; If V0 = 0, wait on prompt
NOP
JAL SleepProcess
LI A0 10 ; Wait 10 frames for textbox to show

JAL PlaySound
LI A0 3 ; Selection sound

LI T1 0xFF ; No item index
LBU T0 2(S2) ; Load reserve item #2 into T0
BNEL T0 T1 GetSelection ; If player has item, get selection
LI V0 2 ; Select reserve item #2 (on likely)

LBU T0 1(S2) ; Load reserve item #1 into T0
BNEL T0 T1 GetSelection ; If player has item, get selection
LI V0 1 ; Select reserve item #1 (on likely)

J GetSelection
LI V0 0 ; Select main item

WaitOnPrompt:
; Get the selection, either from the player or CPU.
JAL GetRandPromptSelection
NOP
GetSelection:
MOVE S1 V0 ; S1 now has the chosen option index

; Obligatory message box closing/cleanup calls.
JAL CloseMessage
NOP
JAL 0x80056168
NOP

; Change the outcome based on the choice.
LI T0 3
BNE S1 T0 ConvertItem ; If S1 = 0-2, convert item
NOP
; else pick "View map"
JAL 0x80103A64 ; ViewBoardMap
NOP
J StartPrompt
NOP

;===Check Inventory (Slots OFF)===
CheckOFF:
LI T3 0xFF ; No item index
BEQ T0 T3 NoItems ; If player has no main item, go to NoItems
NOP
; else, player has an item
LI S1 0 ; Convert main item

;===Greeting Message===
LI A0 0 ; Display message
LUI A1 hi(GreetingMessage)
ADDIU A1 A1 lo(GreetingMessage) ; Display GreetingMessage
JAL CallMessage
LI A2 0 ; No string

;===Convert Item===
ConvertItem:
LI A0 4 ; Assigns Happening fade-out
JAL InitFadeOut ; Fade to black
LI A1 16 ; Assigns 16 frames of fade-out

JAL SleepProcess
LI A0 17 ; Wait 17 frames for fade-out

JAL PlaySound
LI A0 0x36C ; Flash

JAL SleepProcess
LI A0 20 ; Wait 20 frames for sound

;===Remove Item===
LI T1 0xFF ; No item index
BEQL S1 R0 GetPrices ; If S1 = 0, get prices
SB T1 0x19(S0) ; Store no item into main item slot (on likely)
LI T0 1
BEQL S1 T0 GetPrices ; If S1 = 1, get prices
SB T1 0x1E(S0) ; Store no item into reserve slot #1 (on likely)
SB T1 0x1F(S0) ; Store no item into reserve slot #2

;===Get Item Price===
GetPrices:
ADDU S2 S2 S1 ; Add item offset to item logic array
LBU S2 0(S2) ; Load selected item index into S2
SLL T2 S2 5 ; Shift left by 5 (multiply by 32)
ADDU S3 S3 T2 ; Add distance between item strings

LUI T2 hi(ItemPriceTable)
ADDIU T2 T2 lo(ItemPriceTable) ; Load ItemPriceTable into T2
ADDU S2 S2 T2 ; Add distance between items
LBU S2 0(S2) ; Load item price into S2

;===Fade-in===
LI A0 4 ; Assigns Happening fade-in
JAL InitFadeIn ; Fade from black
LI A1 16 ; Assigns 16 frames of fade-in

JAL SleepProcess
LI A0 17 ; Wait 17 frames for fade-in

;===Coin Change===
LBU A0 0x1C(S0) ; Give current player coins
JAL AdjustPlayerCoinsGradual
MOVE A1 S2 ; Give coins

LBU A0 0x1C(S0) ; Give current player coins
JAL ShowPlayerCoinChange
MOVE A1 S2 ; Give coins

JAL SleepProcess
LI A0 30 ; Wait 30 frames for coin change

;===Happy Voice and Animation===
LBU A0 4(S0) ; Load character value from offset of player struct
JAL PlaySound
ADDIU A0 A0 0x103 ; Add character value to Mario's happy voice
; Character voices are their "character value" distance away from
; Mario's, e.g. Luigi's character value = 1, so Luigi's happy voice
; is 1 away from Mario's.
; 0x103 = Happy Voice, 0xFC = Sad Voice, 0x111 = Scream

LI A0 -1 ; Set current player
LI A1 5 ; Set joy animation
JAL SetBoardPlayerAnimation
LI A2 0 ; Do not loop animation

JAL SleepProcess
LI A0 40 ; Wait 40 frames for animation

;===Prepare Coins Message===
LUI A0 hi(CoinString)
ADDIU A0 A0 lo(CoinString) ; Parse destination
LUI A1 hi(percent_d)
ADDIU A1 A1 lo(percent_d) ; String formatter
JAL sprintf
MOVE A2 S2 ; Convert coins to text string

LUI A0 hi(MessagePlaceholder)
ADDIU A0 A0 lo(MessagePlaceholder) ; Parse destination
LUI A1 hi(CoinsMessage)
ADDIU A1 A1 lo(CoinsMessage) ; String formatter (%s)
MOVE A2 S3 ; Pass item string on A2
JAL sprintf
LI A3 0 ; Terminator byte

;===Display Coins Message===
LI A0 0 ; Display message
LUI A1 hi(MessagePlaceholder)
ADDIU A1 A1 lo(MessagePlaceholder) ; Display CoinsMessage with strings
LUI A2 hi(CoinString)
JAL CallMessage
ADDIU A2 A2 lo(CoinString) ; Pass CoinString on A2

J epilogue
NOP

;===No Items Message===
NoItems:
LI A0 0 ; Display Message
LUI A1 hi(NoItemsMessage)
ADDIU A1 A1 lo(NoItemsMessage) ; Display NoItemsMessage
JAL CallMessage
LI A2 0 ; No string

epilogue:
LW RA 60(SP)
LW S0 56(SP)
LW S1 52(SP)
LW S2 48(SP)
LW S3 44(SP)
JR RA
ADDIU SP SP 64

.align 4
ItemArray:
.fill 4

.align 4
BlackColour:
.byte 0x01,0

.align 4
BlueColour:
.byte 0x06,0

;===Prep for Displaying Coin String===
.align 16
percent_d:
.asciiz "%d" ; 0x25640000

.align 16
CoinString:
.fill 8

;===Mini Func to Call Message===
.align 4
CallMessage:
ADDIU SP SP -40
SW RA 36(SP)
SW S0 32(SP)

; A0 / S0 = Message or Prompt
; A1 = Message Address
; A2 = String #1

MOVE S0 A0 ; Copy A0 to S0
SW R0 16(SP) ; A4
SW R0 20(SP) ; A5
SW R0 24(SP) ; A6
LI A0 0x22 ; Character image (-1 for none, 0x22 for Kamek)
; Visit the following link to get the full list of Character Images
; https://github.com/PartyPlanner64/PartyPlanner64/wiki/Displaying-Messages
; If you use a character image, check the bottom of the code
; Pass message address on A1
; Pass string #1 on A2
JAL ShowMessage
LI A3 0

BNEZ S0 CallMessageExit ; If displaying a prompt, exit
NOP

; Obligatory message box closing/cleanup calls.
JAL CloseMessage
NOP
JAL 0x80056168
NOP

CallMessageExit:
LW RA 36(SP)
LW S0 32(SP)
JR RA
ADDIU SP SP 40

;===Mini Func to Disable Items===
.align 4
DisableItems:
ADDIU SP SP -40
SW RA 36(SP)
SW S0 32(SP)
SW S1 28(SP)

; A0 / S0 = Item Logic Array
; S1 = Option Counter

MOVE S0 A0 ; Copy A0 to S0
LI S1 0 ; Start with 0th option
DisableItemsLoop:
LBU T0 0(S0) ; Load option logic into T0
LI T1 0xFF ; No item index
BNE T0 T1 SkipDisable ; If T0 =/= 0xFF, skip disable
LI A0 2 ; Window ID
JAL 0x8008D854 ; DisablePromptOption
MOVE A1 S1 ; Disable nth option
SkipDisable:
LI T0 2
BEQ S1 T0 DisableItemsExit ; If all options checked, exit
NOP
ADDIU S0 S0 1 ; Add 1 to get next option logic
J DisableItemsLoop
ADDIU S1 S1 1 ; Add 1 to check next option

DisableItemsExit:
LW RA 36(SP)
LW S0 32(SP)
LW S1 28(SP)
JR RA
ADDIU SP SP 40

;===Item Price Table===
.align 16
ItemPriceTable:
.byte 20 ; Mushroom price
.byte 20 ; Skeleton Key price
.byte 30 ; Plunder Chest price
.byte 30 ; Bowser Bomb price
.byte 30 ; Dueling Glove price
.byte 30 ; Warp Block price
.byte 40 ; Golden Mushroom price
.byte 40 ; Boo Bell price
.byte 40 ; Bowser Suit price
.byte 60 ; Magic Lamp price
; To set each item's price, set the corresponding byte number to the
; price you want (e.g. a Mushroom is converted to 20 coins). Note
; that the order must match the order of item strings.

;===Message Text===
.align 16
ItemPrompt:
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Would you pass me your"
.byte 0x06 ; Blue font
.ascii " item"
.byte 0x08,0xC3 ; Question mark (?)
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "I"
.byte 0x5C ; Apostrophe (')
.ascii "ll transform it into"
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "something nice within my brew"
.byte 0x85 ; Period (.)
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "Kekeke"
.byte 0x85,0x85,0x85 ; Three periods (...)
.ascii " Which"
.byte 0x5C ; Apostrophe (')
.ascii "ll it be"
.byte 0xC3 ; Question mark (?)
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A,0x1A,0x1A ; Character image + option indent
.byte 0x0C ; Start option
.ascii "%s" ; Main item font colour
.ascii "%s" ; Main item string
.byte 0x0D ; End option
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A,0x1A,0x1A ; Character image + option indent
.byte 0x0C ; Start option
.ascii "%s" ; Reserve item font colour #1
.ascii "%s" ; Reserve item string #1
.byte 0x0D ; End option
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A,0x1A,0x1A ; Character image + option indent
.byte 0x0C ; Start option
.ascii "%s" ; Reserve item font colour #2
.ascii "%s" ; Reserve item string #2
.byte 0x0D ; End option
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A,0x1A,0x1A ; Character image + option indent
.byte 0x0C ; Start option
.byte 0x08 ; White font
.ascii "View map"
.byte 0x0D ; End option
.byte 0 ; End prompt

.align 16
GreetingMessage:
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Would you pass me your"
.byte 0x06 ; Blue font
.ascii " item"
.byte 0x08,0xC3 ; Question mark (?)
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "I"
.byte 0x5C ; Apostrophe (')
.ascii "ll transform it into"
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "something nice within my brew"
.byte 0x85 ; Period (.)
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "Kekeke"
.byte 0x85,0x85,0x85 ; Three periods (...)
.byte 0xFF,0 ; Wait, press A to confirm

.align 16
CoinsMessage:
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Excellent"
.byte 0xC2,0xC2 ; Two exclamation marks (!!)
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "See"
.byte 0x82 ; Comma (,)
.ascii " your "
.byte 0x06 ; Blue font
.ascii "%s" ; Item string
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.byte 0x08 ; White font
.ascii "turned into "
.byte 0x07 ; Yellow font
.byte 0x11 ; String #1 stored in A2 of ShowMessage (CoinString)
.ascii " coins"
.byte 0x08,0xC2 ; White font, Exclamation mark (!)
.byte 0xFF,0 ; Wait, press A to confirm

.align 16
NoItemsMessage:
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Come back with an"
.byte 0x06 ; Blue font
.ascii " item"
.byte 0x08,0x82 ; White font, Comma (,)
.ascii " and"
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "I"
.byte 0x5C ; Apostrophe (')
.ascii "ll turn it into"
.byte 0x07 ; Yellow font
.ascii " coins"
.byte 0x08,0xC2 ; White font, Exclamation mark (!)
.byte 0xFF,0 ; Wait, press A to confirm

; Here's a list of the most common bytes you'll need
; .byte 0x01 ; Black font
; .byte 0x03 ; Red font
; .byte 0x04 ; Purple font
; .byte 0x05 ; Green font
; .byte 0x06 ; Blue font
; .byte 0x07 ; Yellow font
; .byte 0x08 ; White font
; .byte 0x85 ; Period (.)
; .byte 0xC2 ; Exclamation mark (!)
; .byte 0xC3 ; Question mark (?)
; .byte 0x82 ; Comma (,)
; .byte 0x0A ; New line (writes below)
; .byte 0x5C ; Apostrophe (')
; .byte 0x29 ; Coin icon
; .byte 0x3D ; Minus (-)
; .byte 0x3E ; Multiply (x)
; .byte 0xFF,0 ; Wait, press A to confirm

; If your message has an image, use this at the start of each line
; .byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image

;===Item Strings===
.align 32
NullString:
.asciiz "No item available" ; 0xFF
.align 32
ItemStrings:
.asciiz "Mushroom" ; 0x00
.align 32
.asciiz "Skeleton Key" ; 0x01
.align 32
.asciiz "Plunder Chest" ; 0x02
.align 32
.asciiz "Bowser Bomb" ; 0x03
.align 32
.asciiz "Dueling Glove" ; 0x04
.align 32
.asciiz "Warp Block" ; 0x05
.align 32
.asciiz "Golden Mushroom" ; 0x06
.align 32
.asciiz "Boo Bell" ; 0x07
.align 32
.asciiz "Bowser Suit" ; 0x08
.align 32
.asciiz "Magic Lamp" ; 0x09

;===Message Placeholders===
.align 16
PromptPlaceholder:
.fill 0x1024,0

.align 16
MessagePlaceholder:
.fill 0x1024,0