; NAME: Warp to Opponent (MP2) v1.1
; GAMES: MP2_USA
; EXECUTION: Direct
; PARAM: Space|SpaceToFace

; This event is designed to warp the player to an opponent's space.
; The player is able to choose their opponent. For CPU players, there
; will be no cursor when they select an opponent - this is an
; intentional decision as it allows them to randomly choose an
; opponent to warp to.

; During the event, the player will face the space designated by the
; parameter "SpaceToFace".

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 = Prompt Choice / Opponent Player Struct
; S2 = Hitlist Address

;===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, current 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

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

LUI S2 hi(Hitlist)
ADDIU S2 S2 lo(Hitlist)
LBU T2 0x1C(S0) ; Load current player index into T2
ADDU T2 S2 T2 ; Add to hitlist to get current player's flag
SB R0 0(T2) ; Set player's hitlist flag OFF

;===Get Font Colours===
LUI T0 hi(BlackColour)
ADDIU T0 T0 lo(BlackColour) ; Load pointer to black font
LBU T1 0(S2) ; Load P1 hitlist flag
SLL T1 T1 4 ; Shift left by 4 (multiply by 16)
ADDU A2 T0 T1 ; Add distance between font colours

LBU T1 1(S2) ; Load P2 hitlist flag
SLL T1 T1 4 ; Shift left by 4 (multiply by 16)
ADDU A3 T0 T1 ; Add distance between font colours

LBU T1 2(S2) ; Load P3 hitlist flag
SLL T1 T1 4 ; Shift left by 4 (multiply by 16)
ADDU T4 T0 T1 ; Add distance between font colours

LBU T1 3(S2) ; Load P4 hitlist flag
SLL T1 T1 4 ; Shift left by 4 (multiply by 16)
ADDU T5 T0 T1 ; Add distance between font colours

;===Prepare Prompt===
LUI A0 hi(PromptHolder)
ADDIU A0 A0 lo(PromptHolder) ; Parse destination
LUI A1 hi(Prompt)
ADDIU A1 A1 lo(Prompt) ; String formatter (%s)
; Pass P1 colour on A2
; Pass P2 colour on A3
SW T4 16(SP) ; Pass P3 colour on A4
SW T5 20(SP) ; Pass P4 colour on A5
JAL sprintf
SW R0 24(SP) ; Terminator byte

;===Start Prompt===
StartPrompt:
JAL GetPlayerNames ; Get player names at V0, V1, T2, T3
NOP

SW T2 16(SP) ; A4, P3 name
SW T3 20(SP) ; A5, P4 name
SW R0 24(SP) ; A6
LI A0 -1 ; Character image (-1 for none)
; 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
LUI A1 hi(PromptHolder)
ADDIU A1 A1 lo(PromptHolder) ; Display Prompt with strings
MOVE A2 V0 ; String #1 (P1 name)
JAL ShowMessage
MOVE A3 V1 ; String #2 (P2 name)

JAL DisablePlayerOption
MOVE A0 S2 ; Pass hitlist address 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

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

J GetSelection
NOP

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 4
BEQ S1 T0 PrePickRival ; If S1 = 4, go to PrePickRival
NOP
SLT T1 S1 T0 ; If S1 < T0, T1 = 1
BNEZ T1 PickRival ; If T1 = 1, pick rival
NOP
; else pick "View map"
JAL 0x80103A64 ; ViewBoardMap
NOP
J StartPrompt
NOP

;===Pick Rival===
PrePickRival:
JAL AILogic
LBU A0 0x1C(S0) ; Pass current player index on A0
MOVE S1 V0 ; Copy V0 to S1

PickRival:
JAL GetPlayerStruct
MOVE A0 S1 ; Get opponent player struct at V0
MOVE S1 V0 ; Copy V0 to S1

;===Fade-out and Sounds===
LI A0 6 ; Assigns square 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 0x32E ; Warp Block sound

JAL SleepProcess
LI A0 20 ; Wait 20 frames for sound

;===Warp to Opponent===
LBU A0 0x1C(S0) ; Pass current player index on A0
LHU A1 0x10(S1) ; Pass opponent player chain index on A1
JAL SetPlayerOntoChain
LHU A2 0x12(S1) ; Pass opponent player chain space index on A2

LBU A0 0x1C(S0) ; Pass current player index on A0
LHU A1 0x14(S1) ; Pass opponent player next chain index on A1
JAL SetNextChainAndSpace
LHU A2 0x16(S1) ; Pass opponent player next chain space index on A2

LW T0 0x24(S1) ; Load opponent player coords pointer into T0
LW T1 12(T0) ; Load opponent player x coords into T1
LW T0 20(T0) ; Load opponent player y coords into T0

LI T2 0x41200000 ; Float value for 10
MTC1 T2 F2 ; Move float value to F2
MTC1 T0 F4 ; Move player y coords float to F4
ADD.S F6 F2 F4 ; Add the floats for maximum floatiness (TM of Airsola)
MFC1 T0 F6 ; Move total float to T0

LW T2 0x24(S0) ; Load current player coords pointer into T2
SW T1 12(T2) ; Store opponent player x coords into pointer
SW T0 20(T2) ; Store opponent y coords into pointer

;===Finish Warp===
JAL 0x800558F4 ; GetCurrentSpaceIndex
NOP ; Get current space index at V0
LI A0 -1 ; Set current player
LI A1 1 ; Rotate in 1 frame
JAL RotateCharacterModel
MOVE A2 V0 ; Face current space (south)

LI A0 6 ; Assigns square 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

;===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

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

;===Hitlist===
.align 16
Hitlist:
.fill 4,1

;===Font Colour Pointers===
.align 16
BlackColour:
.byte 0x01,0 ; Black font

.align 16
WhiteColour:
.byte 0x08,0 ; White font

;===Mini Func to Get Player Names===
.align 4
GetPlayerNames:
ADDIU SP SP -32
SW RA 28(SP)

; V0 = P1 Name
; V1 = P2 Name
; T2 = P3 Name
; T3 = P4 Name

LUI T0 hi(CharacterStrings)
ADDIU T0 T0 lo(CharacterStrings)

LUI V0 hi(p1_char)
ADDIU V0 V0 lo(p1_char)
LBU V0 0(V0) ; Load P1 character value into V0
SLL V0 V0 5 ; Shift left by 5 (multiply by 32)
ADDU V0 V0 T0 ; Add distance between character strings

LUI V1 hi(p2_char)
ADDIU V1 V1 lo(p2_char)
LBU V1 0(V1) ; Load P2 character value into V1
SLL V1 V1 5 ; Shift left by 5 (multiply by 32)
ADDU V1 V1 T0 ; Add distance between character strings

LUI T2 hi(p3_char)
ADDIU T2 T2 lo(p3_char)
LBU T2 0(T2) ; Load P3 character value into T2
SLL T2 T2 5 ; Shift left by 5 (multiply by 32)
ADDU T2 T2 T0 ; Add distance between character strings

LUI T3 hi(p4_char)
ADDIU T3 T3 lo(p4_char)
LBU T3 0(T3) ; Load P4 character value into T3
SLL T3 T3 5 ; Shift left by 5 (multiply by 32)
ADDU T3 T3 T0 ; Add distance between character strings

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

;===Mini Func to Disable Player Option===
.align 4
DisablePlayerOption:
ADDIU SP SP -40
SW RA 36(SP)
SW S0 32(SP)

; A0 = Hitlist Address
; S0 = Loop Counter

LI S0 0 ; Start at 0
DisablePlayerOptionLoop:
LBU T0 0(A0) ; Load player flag from hitlist
BEQZ T0 DisablePlayerOptionLoopExit ; If player flag is OFF, exit
NOP
ADDIU A0 A0 1 ; Add 1 to get next player flag
J DisablePlayerOptionLoop
ADDIU S0 S0 1 ; Add 1 to get next player

DisablePlayerOptionLoopExit:
LI A0 2 ; Window ID
JAL 0x8008D854 ; DisablePromptOption
MOVE A1 S0 ; Disable current player option

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

;===Mini Func to Determine AI Logic===
.align 4
AILogic:
ADDIU SP SP -40
SW RA 36(SP)
SW S0 32(SP)

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

JAL GetRandomByte ; Get randombyte (0-255) at V0
MOVE S0 A0 ; Copy A0 to S0
LI T0 3
DIVU V0 T0 ; Divide V0 by T0
MFHI V0 ; Move the remainder into V0
BEQL S0 R0 AILogicExit ; If current player is P1, exit
ADDIU V0 V0 1 ; Add 1 to get opponent index (1-3) (on likely)
LI T0 3 ; P4 index
BEQ S0 T0 AILogicExit ; If current player is P4, exit
NOP
; else, current player is P2 or P3 (might need correcting)
BEQL V0 S0 AILogicExit ; If selecting current player, exit
LI V0 3 ; Select P4 instead (on likely)
; else, didn't select current player, no correcting needed

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

;===Message Text===
.align 16
Prompt:
.ascii "Who do you want to"
.byte 0x04 ; Purple font
.ascii " warp"
.byte 0x08 ; White font
.ascii " to"
.byte 0xC3 ; Question mark (?)
.byte 0x0A,0x1A,0x1A ; New line + option indent
.byte 0x0C ; Start option
.ascii "%s" ; P1 font colour
.byte 0x11 ; String #1 (P1 name)
.byte 0x0D ; End option
.byte 0x0A,0x1A,0x1A ; New line + option indent
.byte 0x0C ; Start option
.ascii "%s" ; P2 font colour
.byte 0x12 ; String #2 (P2 name)
.byte 0x0D ; End option
.byte 0x0A,0x1A,0x1A ; New line + option indent
.byte 0x0C ; Start option
.ascii "%s" ; P3 font colour
.byte 0x13 ; String #3 (P3 name)
.byte 0x0D ; End option
.byte 0x0A,0x1A,0x1A ; New line + option indent
.byte 0x0C ; Start option
.ascii "%s" ; P4 font colour
.byte 0x14 ; String #4 (P4 name)
.byte 0x0D ; End option
.byte 0x0A,0x1A,0x1A ; New line + option indent
.byte 0x0C ; Start option
.byte 0x08 ; White font
.ascii "Your choice"
.byte 0x0D ; End option
.byte 0x0A,0x1A,0x1A ; New line + option indent
.byte 0x0C ; Start option
.ascii "View map"
.byte 0x0D ; End option
.byte 0 ; End prompt

; 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

;===Prompt Placeholder===
.align 16
PromptHolder:
.fill 0x1024,0

;===Character Strings===
.align 32
CharacterStrings:
.asciiz "MARIO"
.align 32
.asciiz "LUIGI"
.align 32
.asciiz "PEACH"
.align 32
.asciiz "YOSHI"
.align 32
.asciiz "WARIO"
.align 32
.asciiz "DK"