; NAME: Pay to Warp (MP1)
; GAMES: MP1_USA
; EXECUTION: Direct
; PARAM: Number|Price
; PARAM: Space|SpaceToFace
; PARAM: Space[]|Destinations
; PARAM: Space[]|DestNext

; This event is designed to warp the player to another space by paying
; a number of coins, decided by the parameter "Price". If the player
; doesn't have enough coins, they will be denied. If the player has
; enough coins, they will be given a yes/no prompt to warp. During
; the event, the player will face the space designated by the
; parameter "SpaceToFace".

; This event supports any number of destinations. The parameter
; "Destinations" should be set to each of the target spaces, while the
; parameter "DestNext" should be the next space the player will walk
; toward once they've warped. Ensure that the order of spaces set for
; both of these parameter arrays is the same.

ADDIU SP SP -48
SW RA 44(SP)
SW S0 40(SP)
SW S1 36(SP)
SW S2 32(SP)

; S0 = Current Player Struct
; S1 = Destination Array
; S2 = Price / Randomised Destination

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

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

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

LI S2 Price ; Store price into S2
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 price to text string

LBU A0 0x18(S0) ; Pass current player index on A0
JAL PlayerHasCoins
MOVE A1 S2 ; Check for coins

BEQZ V0 NoCoins ; If V0 = 0, go to NoCoins
NOP

;===Start Prompt===
StartPrompt:
LUI A0 hi(MessagePlaceholder)
ADDIU A0 A0 lo(MessagePlaceholder) ; Parse destination
LUI A1 hi(Prompt)
ADDIU A1 A1 lo(Prompt) ; String formatter (%s)
LUI A2 hi(CoinString)
ADDIU A2 A2 lo(CoinString) ; Pass CoinString on A2
JAL sprintf
LI A3 0 ; Terminator byte

LI A0 1 ; Display prompt
LUI A1 hi(MessagePlaceholder)
ADDIU A1 A1 lo(MessagePlaceholder) ; Display Prompt with strings
MOVE A2 S0 ; Pass current player struct on A2
JAL DisplayMessage
LI A3 4 ; Pass y axis length on A3

; Change the player's destination based on the choice.
BEQZ V0 SayYes ; If V0 = 0, say yes
NOP
LI T0 1
BEQ V0 T0 SayNo ; If V0 = 1, say no
NOP

;===Say Yes===
SayYes:
LBU A0 0x18(S0) ; Pass current player index on A0
JAL AdjustPlayerCoinsGradual
SUBU A1 R0 S2 ; Lose coins

LBU A0 0x18(S0) ; Pass current player index on A0
JAL ShowPlayerCoinChange
SUBU A1 R0 S2 ; Lose coins

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

;===Say Yes Message===
LI A0 0 ; Display message
LUI A1 hi(YesMessage)
ADDIU A1 A1 lo(YesMessage) ; Display YesMessage
MOVE A2 S0 ; Pass current player struct on A2
JAL DisplayMessage
LI A3 1 ; Pass y axis length on A3

;===Fade-out and Sound===
LI A0 1 ; Assigns circle fade-out
JAL 0x800726AC ; InitFadeOut
LI A1 16 ; Assigns 16 frames of fade-out

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

JAL PlaySound
LI A0 0x47 ; Warp Block sound

JAL SleepProcess
LI A0 20 ; Wait 20 frames for sound

;===Determine Destination===
JAL GetRandomByte ; Get random byte (0-255) at V0
NOP
LI T0 Destinations_length ; Load no. of destinations into T0
DIVU V0 T0 ; Divide V0 by T0
MFHI S2 ; Move the remainder (T0 - 1) into S2
SLL S2 S2 1 ; Shift left by 1 (multiply by 2)

LUI S1 hi(DestinationArray)
ADDIU S1 S1 lo(DestinationArray)
ADDU S1 S1 S2 ; Add random number to DestinationArray

;===Set Destination===
LUI T1 hi(DestChainArray)
ADDIU T1 T1 lo(DestChainArray)
ADDU T1 T1 S2 ; Add random number to DestChainArray

LUI T2 hi(DestChainSpaceArray)
ADDIU T2 T2 lo(DestChainSpaceArray)
ADDU T2 T2 S2 ; Add random number to DestChainSpaceArray

LI A0 -1 ; Set current player
LHU A1 0(T1) ; Pass Destination chain index on A1
JAL SetPlayerOntoChain
LHU A2 0(T2) ; Pass Destination chain space index on A2

;===Set Dest Next===
LUI T1 hi(DestNextChainArray)
ADDIU T1 T1 lo(DestNextChainArray)
ADDU T1 T1 S2 ; Add random number to DestNextChainArray

LUI T2 hi(DestNextChainSpaceArray)
ADDIU T2 T2 lo(DestNextChainSpaceArray)
ADDU T2 T2 S2 ; Add random number to DestNextChainSpaceArray

LI A0 -1 ; Set current player
LHU A1 0(T1) ; Pass Destination next chain index on A1
JAL SetNextChainAndSpace
LHU A2 0(T2) ; Pass Destination next chain space index on A2

;===Set Player Coords===
JAL GetSpaceData
LHU A0 0(S1) ; Get Destination space data at V0
LW T0 4(V0) ; Load space x coords into T0
LW T1 12(V0) ; Load space y coords into T1

LW T2 0x20(S0) ; Load coords pointer from offset of player struct
SW T0 12(T2) ; Store space x coords into player coords
SW T1 20(T2) ; Store space y coords into player coords

;===Finish Warp===
LI A0 -1 ; Set current player
LI A1 1 ; Rotate in 1 frame
JAL 0x8004D2A4 ; RotatePlayerModel
LHU A2 0(S1) ; Face Destination space

LI A0 1 ; Assigns circle fade-in
JAL 0x80072644 ; InitFadeIn
LI A1 16 ; Assigns 16 frames of fade-in

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

LI A0 0 ; Display message
LUI A1 hi(WarpedMessage)
ADDIU A1 A1 lo(WarpedMessage) ; Display WarpedMessage
MOVE A2 S0 ; Pass current player struct on A2
JAL DisplayMessage
LI A3 2 ; Pass y axis length on A3

J exit
NOP

;===Say No===
SayNo:
LI A0 0 ; Display message
LUI A1 hi(NoMessage)
ADDIU A1 A1 lo(NoMessage) ; Display NoMessage
MOVE A2 S0 ; Pass current player struct on A2
JAL DisplayMessage
LI A3 2 ; Pass y axis length on A3

J exit
NOP

;===No Coins Message===
NoCoins:
LUI A0 hi(MessagePlaceholder)
ADDIU A0 A0 lo(MessagePlaceholder) ; Parse destination
LUI A1 hi(NoCoinsMessage)
ADDIU A1 A1 lo(NoCoinsMessage) ; String formatter (%s)
LUI A2 hi(CoinString)
ADDIU A2 A2 lo(CoinString) ; Pass CoinString on A2
JAL sprintf
LI A3 0 ; Terminator byte

LI A0 0 ; Display message
LUI A1 hi(MessagePlaceholder)
ADDIU A1 A1 lo(MessagePlaceholder) ; Display NoCoinsMessage with strings
MOVE A2 S0 ; Pass current player struct on A2
JAL DisplayMessage
LI A3 2 ; Pass y axis length on A3

exit:
LW RA 44(SP)
LW S0 40(SP)
LW S1 36(SP)
LW S2 32(SP)
JR RA
ADDIU SP SP 48

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

.align 4
CoinString:
.fill 16

;===Mini Func to Display Message===
.align 4
DisplayMessage:
ADDIU SP SP -48
SW RA 44(SP)
SW S0 40(SP)
SW S1 36(SP)
SW S2 32(SP)
SW S3 28(SP)

; A0 / S0 = Message or Prompt / Prompt Choice
; A1 / S1 = Message Address
; A2 / S2 = Current Player Struct
; A3 = Y Axis Length
; S3 = Window ID

MOVE S0 A0 ; Copy A0 to S0
MOVE S1 A1 ; Copy A1 to S1
MOVE S2 A2 ; Copy A2 to S2

; Pass y axis length on A3
LI A0 40 ; Upper left x coord
LI A1 60 ; Upper left y coord
JAL CreateTextWindow
LI A2 20 ; X Axis length
MOVE S3 V0 ; Copy V0 to S3

MOVE A0 S3 ; Pass window ID on A0
MOVE A1 S1 ; Pass message address on A1
LI A2 -1
JAL LoadStringIntoWindow
LI A3 -1

MOVE A0 S3 ; Pass window ID on A0
JAL SetTextCharsPerFrame
LI A1 0 ; 0 frames between characters

JAL ShowTextWindow
MOVE A0 S3 ; Pass window ID on A0

BEQZ S0 SkipSelection ; If displaying message, skip selection
NOP
JAL ABPrompt
MOVE A0 S2 ; Pass current player struct on A0
MOVE S0 V0 ; Copy V0 to S0

JAL PlaySound
ADDIU A0 V0 0xF7 ; Confirmation or Decline sound

SkipSelection:
MOVE A0 S3 ; Pass window ID on A0
JAL 0x8004DBD4 ; BasicTextConfirmation
LBU A1 0x18(S2) ; Pass current player index on A1

JAL HideTextWindow
MOVE A0 S3 ; Pass window ID on A0
MOVE V0 S0 ; Copy S0 to V0

LW RA 44(SP)
LW S0 40(SP)
LW S1 36(SP)
LW S2 32(SP)
LW S3 28(SP)
JR RA
ADDIU SP SP 48

;===Mini Func for A/B Prompt===
.align 4
ABPrompt:
ADDIU SP SP -40
SW RA 36(SP)
SW S0 32(SP)

; A0 / S0 = Current Player Struct
; V0 = Prompt Choice

MOVE S0 A0 ; Copy A0 to S0
JAL PlayerIsCPU
LBU A0 0x18(S0) ; Pass current player index on A0

BNEZ V0 CPULogic ; If V0 = 1, go to CPULogic
NOP
; else, player is human, check for button inputs

ABPromptLoop:
JAL DetectABInput
LBU A0 3(S0) ; Pass player controller port on A0

LI T0 1
BEQ V0 T0 ABPromptExit ; If V0 = 1, player pressed B, exit
NOP
LI T0 2
BEQL V0 T0 ABPromptExit ; If V0 = 2, player pressed A, exit
LI V0 0 ; Select yes (on likely)
; else, no button was pressed

JAL SleepProcess
LI A0 3 ; Wait 3 frames

J ABPromptLoop
NOP

CPULogic:
JAL SleepProcess
LI A0 10 ; Wait 10 frames for textbox to show

JAL RNGPercentChance
LI A0 50 ; 50% chance of V0 = 1

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

;===Mini Func to Detect A/B Input===
.align 4
DetectABInput:
ADDIU SP SP -32
SW RA 28(SP)

; A0 = Player Controller Port
; V0 = Button Press (1 for B, 2 for A)

LUI T0 0x800E ; 0x800E0000
ORI T0 T0 0xD3F4 ; 0x800ED3F4, P1 Button Input Address
SLL A0 A0 3 ; Shift left by 3 (multiply by 8)
ADDU T0 T0 A0 ; Add to get current player's button input address

LBU V0 0(T0) ; Load player button input into V0
SRL V0 V0 6 ; Shift right by 6 (0x80 > 0x02, 0x40 > 0x01)

LW RA 28(SP)
JR RA
ADDIU SP SP 32

;===Destination Arrays===
.align 16
DestinationArray:
.halfword Destinations ; Destination space indexes

.align 16
DestChainArray:
.halfword Destinations_chain_indices ; Destination chain indexes

.align 16
DestChainSpaceArray:
.halfword Destinations_chain_space_indices ; Destination chain space indexes

.align 16
DestNextChainArray:
.halfword DestNext_chain_indices ; Destination next chain indexes

.align 16
DestNextChainSpaceArray:
.halfword DestNext_chain_space_indices ; Destination next chain space indexes

;===Message Text===
.align 16
Prompt:
.ascii "Do you want to"
.byte 0x04 ; Purple font
.ascii " warp"
.byte 0x08,0x0A ; White font, New line (writes below)
.ascii "to another space"
.byte 0xC3 ; Question mark (?)
.byte 0x0A,0x0E,0x0E ; New line + option indent
.byte 0x21,0x0E ; A button, Tab
.ascii "Sure"
.byte 0x82 ; Comma (,)
.ascii " let"
.byte 0x5C ; Apostrophe (')
.ascii "s go"
.byte 0xC2,0x0E ; Exclamation mark (!), Tab
.byte 0x29,0x3E,0x10 ; Coin icon, Multiply (x), Space
.ascii "%s" ; Price
.byte 0x0A,0x0E,0x0E ; New line + option indent
.byte 0x22,0x0E ; B button, Tab
.ascii "No thanks"
.byte 0x85 ; Period (.)
.byte 0 ; End prompt

.align 16
YesMessage:
.ascii "Okay"
.byte 0x82 ; Comma (,)
.ascii " let"
.byte 0x5C ; Apostrophe (')
.ascii "s"
.byte 0x04 ; Purple font
.ascii " warp"
.byte 0x08,0xC2,0xC2 ; White font, Two exclamation marks (!!)
.byte 0xFF,0 ; Wait, press A to confirm

.align 16
WarpedMessage:
.ascii "You were"
.byte 0x04 ; Purple font
.ascii " warped"
.byte 0x08,0x0A ; White font, New line (writes below)
.ascii "to another space"
.byte 0xC2 ; Exclamation mark (!)
.byte 0xFF,0 ; Wait, press A to confirm

.align 16
NoMessage:
.ascii "Well"
.byte 0x82 ; Comma (,)
.ascii " if you ever want to"
.byte 0x04 ; Purple font
.ascii " warp"
.byte 0x08,0x82,0x0A ; White font, Comma (,), New line (writes below)
.ascii "you know where to go"
.byte 0xC2 ; Exclamation mark (!)
.byte 0xFF,0 ; Wait, press A to confirm

.align 16
NoCoinsMessage:
.ascii "If you don"
.byte 0x5C ; Apostrophe (')
.ascii "t have "
.byte 0x03 ; Red font
.ascii "%s" ; Price
.ascii " coins"
.byte 0x08,0x82 ; White font, Comma (,)
.ascii " you can"
.byte 0x5C ; Apostrophe (')
.ascii "t"
.byte 0x0A ; New line (writes below)
.byte 0x04 ; Purple font
.ascii "warp"
.byte 0x08 ; White font
.ascii " to another space"
.byte 0x85 ; Period (.)
.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

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