; NAME: Snifit Patrol (Parameters)
; GAMES: MP3_USA
; EXECUTION: Direct
; PARAM: Number|Mushroom
; PARAM: Number|SkeletonKey
; PARAM: Number|PoisonMushroom
; PARAM: Number|ReverseMushroom
; PARAM: Number|CellularShopper
; PARAM: Number|WarpBlock
; PARAM: Number|PlunderChest
; PARAM: Number|BowserPhone
; PARAM: Number|DuelingGlove
; PARAM: Number|LuckyLamp
; PARAM: Number|GoldenMushroom
; PARAM: Number|BooBell
; PARAM: Number|BooRepellant
; PARAM: Number|BowserSuit
; PARAM: Number|MagicLamp
; PARAM: Number|KoopaKard
; PARAM: Number|BarterBox
; PARAM: Number|LuckyCharm
; PARAM: Number|WackyWatch

ADDIU SP SP -64
SW RA 60(SP)
SW S0 56(SP)
SW S1 52(SP)
SW S2 48(SP)
SW S3 44(SP)
SW S4 40(SP)
SW S5 36(SP)
SW S6 32(SP)

; This code is designed to remove specific items from a player's
; inventory at the start of their turn and exchange them for coins.
; The items removed are determined by the Item Array and the coins
; received are determined by the corresponding byte in the Price
; Array.

; When using this version of the event, be sure to set all 19
; parameters. To remove an item, set its parameter to whatever price
; it will be traded for (0-999 coins is supported). Setting the
; parameter to -1 will make it so the event will not check for that
; item (i.e. that item will not be removed). Consequently, negative
; prices (i.e. losing coins) are not supported.

; S0 = Current Player Struct
; S1 = Current Player Struct + Item Offset
; S2 = Coin Tally
; S3 = Item Array
; S4 = Price Array
; S5 = Item Slot Loop Counter
; S6 = Hit Flag (0 or 1)

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

;===Inventory Check===
JAL PlayerHasEmptyItemSlot
LBU A0 0x1D(S0) ; Load player index from offset of player struct
BEQZ V0 exit ; If player has no items, exit
NOP
; else, check for items

;===Get Arrays===
LUI S3 hi(ItemArray)
ADDIU S3 S3 lo(ItemArray) ; Load ItemArray into S3

LUI S4 hi(PriceArray)
ADDIU S4 S4 lo(PriceArray) ; Load PriceArray into S4

MOVE A0 S3 ; Pass ItemArray on A0
JAL BuildArrays
MOVE A1 S4 ; Pass PriceArray on A1

;===Prepare Arrays===
LBU T3 0(S3) ; Load illegal item into T3
LHU T4 0(S4) ; Load item price into T4
LI T0 0xFF ; No item index
LI S6 0 ; Start with no hits

;===Check Items===
RestartItemSlots:
MOVE S1 S0 ; Copy S0 to S1
LI S5 0 ; Start with item slot #1

CheckItems:
LBU T1 0x18(S1) ; Load item #1 from offset of player struct
BNE T1 T3 NextItemSlot ; If not illegal item, go to NextItemSlot
NOP
; else, remove illegal item from inventory and tally coins received

SB T0 0x18(S1) ; Store no item index into offset of player struct
ADDU S2 S2 T4 ; Add item price to coin tally
LI S6 1 ; There is at least one hit

NextItemSlot:
LI T5 2
BEQ S5 T5 CheckNextItem ; If all item slots checked, check next item
NOP
ADDIU S5 S5 1 ; Add 1 to item slot loop counter
J CheckItems
ADDIU S1 S1 1 ; Add 1 to check next item slot

CheckNextItem:
ADDIU S3 S3 1 ; Add 1 to get next illegal item
LBU T3 0(S3) ; Load illegal item into T3
LI T2 0x13 ; Terminator byte
BEQ T2 T3 CheckResults ; If finished checking ItemArray, check results
NOP
ADDIU S4 S4 2 ; Add 2 to get next price
J RestartItemSlots
LHU T4 0(S4) ; Load item price into T4

;===Check Results===
CheckResults:
BEQZ S6 exit ; If no hits, exit
NOP
; else, Snifit Patrol removed at least 1 item

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

;===Refresh Player Items HUD===
JAL FixUpPlayerItemSlots
LBU A0 0x1D(S0) ; Load player index from offset of player struct
JAL FixUpPlayerItemSlots
LBU A0 0x1D(S0) ; Load player index from offset of player struct
JAL RefreshHUD
LBU A0 0x1D(S0) ; Load player index from offset of player struct

;===Check for Coins===
BEQZ S2 exit2 ; If no coins received, exit
NOP
; else, player receives coins

;===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 gained to text string

;===Coins Message===
LUI A0 hi(CoinString)
ADDIU A0 A0 lo(CoinString) ; String #1 (CoinString)
LUI A1 hi(CoinsMessage)
JAL CallMessage
ADDIU A1 A1 lo(CoinsMessage) ; Display CoinsMessage

;===Receive Coins===
LBU A0 0x1D(S0) ; Load player index from offset of player struct
JAL AdjustPlayerCoinsGradual
MOVE A1 S2 ; Gain coins

LBU A0 0x1D(S0) ; Load player index from offset of player struct
JAL ShowPlayerCoinChange
MOVE A1 S2 ; Gain coins

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

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

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

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

exit:
LW RA 60(SP)
LW S0 56(SP)
LW S1 52(SP)
LW S2 48(SP)
LW S3 44(SP)
LW S4 40(SP)
LW S5 36(SP)
LW S6 32(SP)
JR RA
ADDIU SP SP 64

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

.align 16
CoinString:
.fill 8

;===Mini Func to Build Arrays===
.align 4
BuildArrays:
ADDIU SP SP -40
SW RA 36(SP)

; A0 = Item Array
; A1 = Price Array

LUI T2 hi(ParameterArray)
ADDIU T2 T2 lo(ParameterArray)
LI T0 0 ; Start with Mushroom index
LI T4 0xFFFF ; -1 value
BuildArraysLoop:
LHU T1 0(T2) ; Load item price from parameter array
BEQ T1 T4 BuildNextItem ; If item price = -1, build next item
NOP
; else, add to item and price arrays
SB T0 0(A0) ; Add item to item array
SH T1 0(A1) ; Add price to price array
ADDIU A0 A0 1 ; Add 1 to store next item in item array
ADDIU A1 A1 2 ; Add 2 to store next price in price array

BuildNextItem:
LI T3 0x12 ; Final item, Wacky Watch index
BEQ T0 T3 FinishBuilding ; If at final item, finish building
NOP
ADDIU T0 T0 1 ; Add 1 to get next item
J BuildArraysLoop
ADDIU T2 T2 2 ; Add 2 to check next parameter 

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

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

; A0 / S1 = String #1
; A1 / S0 = Message Address

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

JAL PlaySound
LI A0 0x2A1 ; Shy Guy voice

SW R0 16(SP) ; A4
SW R0 20(SP) ; A5
SW R0 24(SP) ; A6
LI A0 0x9 ; Character image (-1 for none, 0x9 for Snifit Patrol)
; 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 ; Pass message address on A1
MOVE A2 S1 ; Pass String #1 on A2
JAL ShowMessage
LI A3 0

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

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

;===Item Array===
.align 16
ItemArray:
.fill 20,0x13

;===Price Array===
.align 16
PriceArray:
.fill 38

;===Parameter Array===
.align 16
ParameterArray:
.halfword Mushroom,SkeletonKey,PoisonMushroom,ReverseMushroom
.halfword CellularShopper,WarpBlock,PlunderChest,BowserPhone
.halfword DuelingGlove,LuckyLamp,GoldenMushroom,BooBell
.halfword BooRepellant,BowserSuit,MagicLamp,KoopaKard
.halfword BarterBox,LuckyCharm,WackyWatch

;===Message Text===
.align 16
GreetingMessage:
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "I"
.byte 0x5C ; Apostrophe (')
.ascii "m the Snifit Patrol"
.byte 0x85 ; Period (.)
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "I see you are in possession"
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "of an"
.byte 0x03 ; Red font
.ascii " illegal item"
.byte 0x08,0x85 ; White font, Period (.)
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "Let me just confiscate that"
.byte 0x85 ; Period (.)
.byte 0xFF,0 ; Wait, press A to confirm

.align 16
CoinsMessage:
.byte 0x1A,0x1A,0x1A,0x1A ; Padding for character image
.ascii "Thanks for cooperating with"
.byte 0x0A,0x1A,0x1A,0x1A,0x1A ; New line + character image padding
.ascii "the law"
.byte 0x85 ; Period (.)
.ascii " Take "
.byte 0x06,0x11 ; Blue font, String #1 stored on A2 (CoinString)
.ascii " coins"
.byte 0x08 ; White font
.ascii " as thanks"
.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

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