; NAME: Sell Star(s) for Coins
; GAMES: MP3_USA
; EXECUTION: Direct
; PARAM: Number|SellPrice
; PARAM: Boolean|SellMultiple
; PARAM: Space|SpaceToFace

; This code is designed to allow you to sell Stars to receive coins.
; The coins received per Star is set by the parameter "SellPrice".
; This event supports selling either one Star at a time or multiple
; at once; just set the parameter "SellMultiple" to "true" to allow
; for selling multiple Stars at once.

ADDIU SP SP -80
SW RA 76(SP)
SW S0 72(SP)
SW S1 68(SP)
SW S2 64(SP)
SW S3 60(SP)
SW S4 56(SP)
SW S5 52(SP)

; S0 = Current Player Struct
; S1 = Prompt Choice
; S2 = Coin Profit
; S3 = Stars to Sell
; S4 = Player's Stars
; S5 = SellPrice

;===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 over 8 frames
JAL 0x800ED20C ; Rotate Player Model
LI A2 SpaceToFace

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

LBU S4 0x0E(S0) ; Load stars into S1 from offset of player struct
BEQZ S4 NoStars ; If S1 = 0, player has no stars
NOP

;===Prepare Coin String to Display in Message===
LI S5 SellPrice

LUI A0 hi(CoinString)
ADDIU A0 A0 lo(CoinString) ; Saves # of coins to CoinString
LUI A1 hi(percent_d)
ADDIU A1 A1 lo(percent_d)
JAL sprintf ; Converts a number to a text string
MOVE A2 S5 ; Converts the number of coins to a string

;===Prepare Star String to Display in Message===
LUI A0 hi(StarString)
ADDIU A0 A0 lo(StarString) ; Location of converted string
LUI A1 hi(percent_d)
ADDIU A1 A1 lo(percent_d)
JAL sprintf
LI A2 1 ; Convert # of stars for sale into string (default 1)

;===Check to Sell Multiple Stars===
LI S3 1 ; Default sell 1 star at a time
LI T0 1
BEQ T0 S4 SellSingleStar ; If S1 = 1, player can sell 1 star
NOP
LI T0 SellMultiple ; 0 = only sell single star
BEQZ T0 SellSingleStar
NOP

;===Sell Multiple Stars===
JAL PlaySound
LI A0 0x256 ; Bob-omb voice

SW R0 16(SP) ; A4
SW R0 20(SP) ; A5
SW R0 24(SP) ; A6
LI A0 0xB ; Character image (-1 for none, 0xB for Red Bob-omb)
; 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(SellMultiStarsMessage)
ADDIU A1 A1 lo(SellMultiStarsMessage)
LUI A2 hi(StarString)
ADDIU A2 A2 lo(StarString) ; Load StarString into A2 (string #1)
LUI A3 hi(CoinString)
JAL 0x800EC92C  ; ShowMessage2
ADDIU A3 A3 lo(CoinString) ; Load CoinString into A3 (string #2)

JAL PlayerIsCPU
LBU A0 0x1D(S0) ; V0 = 1 if current player is CPU

BNEZ V0 exitloop
NOP

LoopReturn:
JAL DetectCStickInput ; V0 = 1 if Stick is Up, -1 if Down, ELSE 0
LBU A0 0x1D(S0)

BEQZ V0 Loop
NOP

LI T0 1
BEQ V0 T0 CheckMax
NOP ; else CheckMin
CheckMin:
BNE S3 T0 ContinueNormal ; S3 =/= 1
NOP
J ContinueRefresh
MOVE S3 S4 ; Copy Player's Stars to Stars to Sell

CheckMax:
BNE S3 S4 ContinueNormal ; Player's Stars =/= Stars to Sell
NOP
J ContinueRefresh
MOVE S3 T0 ; S3 = 1

ContinueNormal:
ADDU S3 S3 V0 ; Add 1 to Stars to Sell

ContinueRefresh:
LUI A0 hi(StarString)
ADDIU A0 A0 lo(StarString)
LUI A1 hi(percent_d)
ADDIU A1 A1 lo(percent_d)
JAL sprintf
MOVE A2 S3 ; Move Stars to Sell into A2

MULT S3 S5 ; Multiply Stars to Sell by Sell Price
MFLO A2 ; Move result to A2

LUI A0 hi(CoinString)
ADDIU A0 A0 lo(CoinString) ; Saves # of coins to CoinString
LUI A1 hi(percent_d)
JAL sprintf ; Converts a number to a text string
ADDIU A1 A1 lo(percent_d)

JAL PlaySound
LI A0 582 ; Coin Sound

JAL SleepProcess
LI A0 2 ; Sleep for 2 frames so choosing amount is easier

Loop:
JAL DetectABInput ; V0 = 1 if A press, 2 if B press, ELSE 0
LBU A0 0x1D(S0)

LI T0 1
BEQ V0 T0 exitloop
NOP
BEQZ V0 ContinueInLoop
NOP

JAL PlaySound
LI A0 4 ; Back Sound Index

JAL 0x800EC6C8
NOP
JAL 0x800EC6EC
NOP
J SayingNo
NOP

ContinueInLoop:
LI A0 2
LUI A1 hi(StarString)
ADDIU A1 A1 lo(StarString) ; String value
JAL 0x8005B6BC
LI A2 0 ; Start with String #1

LI A0 2
LUI A1 hi(SellMultiStarsMessage)
ADDIU A1 A1 lo(SellMultiStarsMessage)
LI A2 -1
JAL 0x8005B43C
LI A3 -1

JAL SleepProcess
LI A0 3

J LoopReturn
NOP

exitloop:
JAL CloseMessage
NOP
JAL 0x800EC6EC
NOP

JAL PlaySound
LI A0 583 ; Cash Register Sound

JAL SleepProcess
LI A0 10 ; Sleep 10 frames

J SellStar
NOP

;===Display Prompt to Sell a Star===
SellSingleStar:
LUI A0 hi(SellStarPrompt)
ADDIU A0 A0 lo(SellStarPrompt)
LI A1 1 ; Display prompt
LUI A2 hi(CoinString)
JAL CallMessage
ADDIU A2 A2 lo(CoinString) ; Load CoinString into A2 (string #1)

; Get the selection, either from the player or CPU.
; If A0 is a pointer to AI data, AI logic is ran to pick for CPUs.
; If A0 is 0 or 1, the 0th or 1st option is chosen by CPUs.
; If A0 is 2, then the value of A1 is the CPUs option index choice.
JAL AILogic
LBU A0 0x1D(S0) ; Current player index from offset of player struct
LI A0 2
JAL GetBasicPromptSelection
MOVE A1 V0 ; A1 now has the AI's decision
MOVE S1 V0 ; S1 now has the chosen option index

; Obligatory message box closing/cleanup calls.
JAL 0x800EC6C8
NOP
JAL 0x800EC6EC
NOP

; Change the player's destination based on the choice.
LI T0 0
BEQ S1 T0 SellStar
NOP
LI T0 1
BEQ S1 T0 SayNo
NOP
JAL ViewBoardMap
NOP
J SellSingleStar
NOP

;===Sell Star(s)===
SellStar:
LBU T0 0x0E(S0) ; Load stars into T0 from offset of player struct
SUBU T0 T0 S3 ; T0 minus S3
SB T0 0x0E(S0) ; Store new star value into offset of player struct

;===Gain Coins===
MULT S3 S5 ; Multiply stars sold by price per star
MFLO S2 ; Store result in S2
SLTI T0 S2 1000 ; T0 = 1 if S2 < 1000
BNEZ T0 GainCoins
NOP ; else S2 = 1000+
LI S2 999

GainCoins:
LBU A0 0x1D(S0) ; Give coins to current player
JAL AdjustPlayerCoinsGradual
MOVE A1 S2 ; Give coins

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

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

;===Play Happy Voice===
LBU T0 3(S0) ; ; Load character value from offset of player struct
JAL PlaySound
ADDIU A0 T0 0x2BE ; Add character value to Mario's sad 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.
; 0x2BE = Happy Voice, 0x287 = Sad Voice

; Visit the following link to get SFX Indexes:
; https://pastebin.com/H1jxNFqr

;===Play Happy Animation===
LI A0 -1 ; Set current player
LI A1 5 ; Joy animation
JAL SetBoardPlayerAnimation
LI A2 0 ; Do not loop animation

JAL SleepProcess
LI A0 40 ; Wait 40 frames for animation

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

J exit
NOP

;===Prepare Say No Message===
SayingNo:
LUI A0 hi(CoinString)
ADDIU A0 A0 lo(CoinString) ; Saves # of coins to CoinString
LUI A1 hi(percent_d)
ADDIU A1 A1 lo(percent_d)
JAL sprintf ; Converts a number to a text string
MOVE A2 S5 ; Converts the number of coins to a string

;===Say No Message===
SayNo:
LUI A0 hi(DeclineMessage)
ADDIU A0 A0 lo(DeclineMessage)
LI A1 0 ; Display message
LUI A2 hi(CoinString)
JAL CallMessage
ADDIU A2 A2 lo(CoinString) ; Load CoinString into A2 (string #1)

J exit
NOP

;===No Stars Message===
NoStars:
LUI A0 hi(NoStarsMessage)
ADDIU A0 A0 lo(NoStarsMessage)
LI A1 0 ; Display message
JAL CallMessage
LI A2 0 ; No string

exit:
LW RA 76(SP)
LW S0 72(SP)
LW S1 68(SP)
LW S2 64(SP)
LW S3 60(SP)
LW S4 56(SP)
LW S5 52(SP)
JR RA
ADDIU SP SP 80

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

.align 16
CoinString:
.fill 8

.align 16
StarString:
.fill 8

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

; A0 = Message Address
; A1 = Message or Prompt (0 or 1)
; A2 = String #1 (byte 0x11)

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

JAL PlaySound
LI A0 0x256 ; Bob-omb voice

SW R0 16(SP) ; A4
SW R0 20(SP) ; A5
SW R0 24(SP) ; A6
LI A0 0xB ; Character image (-1 for none, 0xB for Red Bob-omb)
; 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
MOVE A1 S0 ; Copy S0 to A0
MOVE A2 S2 ; Copy S2 to A2
JAL ShowMessage
LI A3 0

BNEZ S1 CallMessageExit ; If S0 = 1, exit to close prompt
NOP

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

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

;===Mini Func to Decide AI Choice for Prompt===
.align 4
AILogic:
ADDIU SP SP -32
SW RA 28(SP)

; A0 = Current Player Index

JAL GetPlayerPlacement ; Returns 0-3 for 1st to 4th
NOP
LI T0 20 ; Chances in increments of 20
MULT T0 V0 ; Multiply V0 by T0
MFLO T0 ; Move result from LO to T0 (0,20,40,60)
JAL RNGPercentChance ; A0 % chance of V0 = 1
ADDIU A0 T0 20 ; Add base 20% chance

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

;===Message Text===
.align 16
SellMultiStarsMessage:
.byte 0x0B ; Begin prompt
.byte 0x1A,0x1A,0x1A,0x1A ; Standard padding for picture
.ascii "Choose the number of"
.byte 0x0A ; New Line (Writes Below)
.byte 0x1A,0x1A,0x1A,0x1A ; Standard padding for picture
.byte 0x07 ; Yellow font
.ascii "stars"
.byte 0x08 ; White font
.ascii " you"
.byte 0x5C ; Apostrophe (')
.ascii "ll sell"
.byte 0x85 ; Period (.)
.byte 0x0A ; New Line (Writes Below)
.byte 0x0A ; New Line (Writes Below)
.byte 0x1A,0x1A,0x1A,0x1A,0x1A ; Picture + Option Indent
.ascii "Sell"
.byte 0x10,0x10 ; Space 2x (  )
.byte 0x2A ; Star icon
.byte 0x20 ; ???
.byte 0x3E ; x (multiply)
.byte 0x20 ; ???
.byte 0x05 ; Green Font
.byte 0x0F ; ???
.byte 0x11 ; String #1 (Price)
.byte 0x19 ; ???
.byte 0x0A ; New Line (Writes Below)
.byte 0x08 ; White font
.byte 0x1A,0x1A,0x1A,0x1A,0x1A ; Picture + Option Indent
.ascii "Gain"
.byte 0x10,0x10 ; Space 2x (  )
.byte 0x29 ; Coin icon
.byte 0x20 ; ???
.byte 0x3E ; x (multiply)
.byte 0x20 ; ???
.byte 0x05 ; Green Font
.byte 0x0F ; ???
.byte 0x12 ; String #2 (Price)
.byte 0x19 ; ???
.byte 0x0A ; New Line (Writes Below)
.byte 0x0A ; New Line (Writes Below)
.byte 0x1A,0x1A,0x1A,0x1A,0x1A,0x1A;Picture + Option Indent
.byte 0x28 ; Control Stick Icon
.byte 0x85,0x85,0x85 ; Period (...)
.ascii "Choose"
.byte 0x0A ; New Line (Writes Below)
.byte 0x1A,0x1A,0x1A,0x1A,0x1A,0x1A;Picture + Option Indent
.byte 0x21 ; (A) Button Icon
.byte 0x85,0x85,0x85 ; Period (...)
.ascii "Confirm"
.byte 0x0A ; New Line (Writes Below)
.byte 0x1A,0x1A,0x1A,0x1A,0x1A,0x1A;Picture + Option Indent
.byte 0x22 ; (B) Button Icon
.byte 0x85,0x85,0x85 ; Period (...)
.ascii "Quit"
.byte 0
.byte 0

.align 16
SellStarPrompt:
.byte 0x0B ; Begin prompt
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Ten"
.byte 0x3D ; Dash (-)
.ascii "hut"
.byte 0x82 ; Comma (,)
.ascii " soldier"
.byte 0xC2 ; Exclamation mark (!)
.ascii " It looks like"
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "you can sell a"
.byte 0x07 ; Yellow font
.ascii " Star"
.byte 0x08 ; White font
.ascii " for"
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.byte 0x06 ; Blue font
.byte 0x11 ; String #1 stored in A2 (CoinString)
.ascii " coins"
.byte 0x08,0xC2 ; White font, Exclamation mark (!)
.ascii " Deal or no deal"
.byte 0xC3 ; Question mark (?)
.byte 0x0A,0x0A ; Two new lines
.byte 0x1A,0x1A,0x1A,0x1A,0x1A,0x1A ; Little more for option indent
.byte 0x0C ; Start option
.ascii "Sell"
.byte 0x07 ; Yellow font
.ascii " a Star"
.byte 0x08 ; White font
.ascii " for "
.byte 0x06 ; Blue font
.byte 0x11 ; String #1 stored in A2 (CoinString)
.ascii " coins"
.byte 0x08,0x0D ; White font, End option
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A,0x1A,0x1A ; Little more for option indent
.byte 0x0C ; Start option
.ascii "No deal"
.byte 0x0D ; End option
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A,0x1A,0x1A ; Little more for option indent
.byte 0x0C ; Start option
.ascii "View map"
.byte 0x0D ; End option
.byte 0

.align 16
SoldMessage:
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Many thanks"
.byte 0x82 ; Comma (,)
.ascii " soldier"
.byte 0xC2 ; Exclamation mark (!)
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Ten"
.byte 0x3D ; Dash (-)
.ascii "hut"
.byte 0xC2,0xC2 ; Two exclamation marks (!!)
.byte 0xFF,0 ; Wait, press A to confirm

.align 16
DeclineMessage:
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Ten"
.byte 0x3D ; Dash (-)
.ascii "hut"
.byte 0x82 ; Comma (,)
.ascii " soldier"
.byte 0xC2 ; Exclamation mark (!)
.ascii " The choice"
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "is yours"
.byte 0x85 ; Period (.)
.ascii " Just remember that"
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.byte 0x07 ; Yellow font
.ascii "one Star"
.byte 0x08 ; White font
.ascii " sells for "
.byte 0x06 ; Blue font
.byte 0x11 ; String #1 stored in A2 (CoinString)
.ascii " coins"
.byte 0x08,0xC2 ; White font, Exclamation mark (!)
.byte 0xFF,0 ; Wait, press A to confirm

.align 16
NoStarsMessage:
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Ten"
.byte 0x3D ; Dash (-)
.ascii "hut"
.byte 0x82 ; Comma (,)
.ascii " soldier"
.byte 0xC2 ; Exclamation mark (!)
.ascii " It looks like"
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "you have"
.byte 0x03 ; Red font
.ascii " 0 Stars"
.byte 0x08 ; White font
.ascii " to sell"
.byte 0xC2 ; Exclamation mark (!)
.byte 0x0A ; New line (writes below)
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Come back when you"
.byte 0x5C ; Apostrophe (')
.ascii "ve collected some"
.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 ; x (multiply)
; .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

;===Funcs to Read Controller Inputs===
.align 4
DetectCStickInput:
ADDIU SP SP -40
SW RA 36(SP)
SW S5 32(SP)

; A0 Current Player index

LUI T1 hi(p1_controller)
ADDIU T1 T1 lo(p1_controller) ; Load P1's Controller
LI T0 0x38 ; This is the distance between each player's Controller
MULT A0 T0 ;  Multiply Current Player Index by S3
MFLO T0 ; Move the result to S3

ADDU T1 T1 T0 ; Add result to get Current Player's Controller Addr
LBU T0 0(T1) ; Load address value into A1

LUI T1 hi(0x800CC3F7)
ADDIU T1 T1 lo(0x800CC3F7) ; Load P1's Y Axis
LI A2 0x8 ; This is the distance between each player's Controller
MULT A2 T0 ;  Multiply Controller value by 8
MFLO T0 ; Move the result to S3

ADDU T1 T1 T0 ; Add result to get Current Player's Y Axis
LBU T0 0(T1) ; Load address value into A1

SLTI S5 T0 0x1E ; S5 = 1 if less than 1E
BNE S5 R0 return_zero 
NOP
SLTI S5 T0 0x7C ; Set if Stick is tilted up
BNE S5 R0 return_one
NOP
SLTI S5 T0 0xE2
BNE S5 R0 return_neg_one
NOP

return_zero:
J DetectCStickInputexit
LI V0 0

return_one:
J DetectCStickInputexit
LI V0 1

return_neg_one:
LI V0 -1

DetectCStickInputexit:
LW RA 36(SP)
LW S5 32(SP)
JR RA
ADDIU SP SP 40

.align 4
DetectABInput:
ADDIU SP SP -40
SW RA 36(SP)

; A0 Current Player's Control Stick Y axis

LUI T1 hi(p1_controller)
ADDIU T1 T1 lo(p1_controller) ; Load P1's Controller
LI T0 0x38 ; This is the distance between each player's Controller
MULT A0 T0 ;  Multiply Current Player Index by S3
MFLO T0 ; Move the result to S3

ADDU T1 T1 T0 ; Add result to get Current Player's Controller Addr
LBU T0 0(T1) ; Load address value into A1

LUI T1 hi(0x800CC3F4)
ADDIU T1 T1 lo(0x800CC3F4) ; Load P1's Button Press Address
LI A2 0x2 ; This is the distance between each player's Button Address
MULT A2 T0 ;  Multiply Controller value by 2
MFLO T0 ; Move the result to S3

ADDU T1 T1 T0 ; Add result to get Current Player's Y Axis
LBU T0 0(T1) ; Load address value into A1

LI T1 0x80
BEQ T0 T1 APress
NOP
LI T1 0x40
BEQ T0 T1 BPress
NOP

NoPress:
J DetectABInputexit
LI V0 0

APress:
J DetectABInputexit
LI V0 1

BPress:
LI V0 2

DetectABInputexit:
LW RA 36(SP)
JR RA
ADDIU SP SP 40