; NAME: Magic Window (MP2)
; 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)
SW S3 28(SP)
SW S4 24(SP)
SW S5 20(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

;===Show Opening Message===
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(OpeningMessage)
ADDIU A1 A1 lo(OpeningMessage) ; 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 AILogic
LBU A0 0x1C(S0) ; Pass current player index on A0

J GetSelection
NOP

GetSelection:
LI S1 4 ; 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

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

JAL PlaySound
LI A0 0x32E ; Warp Block sound

JAL SleepProcess
LI A0 20 ; Wait 20 frames for sound

;===Swap Current Player with Opponent===
LHU S2 0x10(S0) ; Load original player chain index on S2
LHU S3 0x12(S0) ; Load original player chain space index on S3
LHU S4 0x14(S0) ; Load original player next chain index on S4
LHU S5 0x16(S0) ; Load original player next chain space index on S5

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

LBU A0 0x1C(S1) ; Pass opponent player index on A0
MOVE A1 S2 ; Pass original player chain index on A1
JAL SetPlayerOntoChain
MOVE A2 S3 ; Pass original player chain space index on A2

LBU A0 0x1C(S1) ; Pass opponent player index on A0
MOVE A1 S4 ; Pass original player next chain index on A1
JAL SetNextChainAndSpace
MOVE A2 S5 ; Pass original player next chain space index on A2

LW T2 0x24(S0) ; Load original player coords pointer into T2
LW S2 12(T2) ; Store original player x coords on S2
LW S3 20(T2) ; Store original player y coords on S3

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

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

LW T2 0x24(S1) ; Load opponent player coords pointer into T2
SW S2 12(T2) ; Store original player x coords into pointer
SW S3 20(T2) ; Store original player 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

;===Show Closing Message===
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(ClosingMessage)
ADDIU A1 A1 lo(ClosingMessage) ; Display Prompt with strings
LUI T0 hi(CharacterStrings)
ADDIU T0 T0 lo(CharacterStrings) ; Load CharacterStrings address into T0
LBU A2 4(S0) ; Load character value from offset of player struct
SLL A2 A2 5 ; Shift left by 5 (multiply by 32)
ADDU A2 A2 T0 ; Add distance between character strings
LBU A3 4(S1) ; Load character value from offset of opponent struct
SLL A3 A3 5 ; Shift left by 5 (multiply by 32)
ADDU A3 A3 T0 ; Add distance between character strings
JAL ShowMessage
NOP

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

;===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)
LW S3 28(SP)
LW S4 24(SP)
LW S5 20(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 0x05,0 ; Green font

;===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
OpeningMessage:
.ascii "You peer through the"
.byte 0x04 ; Purple font
.ascii " magic window"
.byte 0x08 ; White font
.byte 0x82 ; Comma (.)
.byte 0x82 ; Comma (.)
.byte 0x82 ; Comma (.)
.byte 0x0A ; New line (writes below)
.ascii "Someone is looking back at you"
.byte 0xC2 ; Exclamation mark (!)
.byte 0xFF,0 ; Wait, press A to confirm

;===Second Message Text===
.align 16
ClosingMessage:
.byte 0x08 ; White font
.ascii "Why"
.byte 0x82 ; Comma (,)
.byte 0x0A ; New line (writes below)
.byte 0x05 ; Green font
.byte 0x11 ; String #1 (Current player name)
.byte 0x08 ; White fonts
.ascii " and "
.byte 0x05 ; Green font
.byte 0x12 ; String #2 (Selected opponent name)
.byte 0x0A ; New line (writes below)
.byte 0x08 ; White font
.ascii "have switched places"
.byte 0xC2 ; 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

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