2018-12-31 23:09:45 +01:00
# include "global.h"
2019-09-09 03:07:54 +02:00
# include "malloc.h"
2018-12-31 23:09:45 +01:00
# include "bg.h"
# include "coins.h"
2019-01-01 01:07:29 +01:00
# include "decompress.h"
2018-12-31 23:09:45 +01:00
# include "event_data.h"
2019-01-01 01:07:29 +01:00
# include "field_screen_effect.h"
2018-12-31 23:09:45 +01:00
# include "gpu_regs.h"
2019-01-02 23:55:50 +01:00
# include "graphics.h"
2018-12-31 23:09:45 +01:00
# include "m4a.h"
# include "main.h"
# include "menu.h"
# include "menu_helpers.h"
2019-01-01 01:07:29 +01:00
# include "overworld.h"
2018-12-31 23:09:45 +01:00
# include "palette.h"
2020-08-05 01:24:36 +02:00
# include "palette_util.h"
2018-12-31 23:09:45 +01:00
# include "random.h"
# include "roulette.h"
# include "rtc.h"
# include "scanline_effect.h"
2019-01-01 01:07:29 +01:00
# include "script.h"
2018-12-31 23:09:45 +01:00
# include "sound.h"
# include "sprite.h"
2019-01-01 01:07:29 +01:00
# include "string_util.h"
2020-07-31 20:55:42 +02:00
# include "strings.h"
2018-12-31 23:09:45 +01:00
# include "task.h"
# include "trig.h"
# include "tv.h"
# include "window.h"
2020-07-29 10:46:58 +02:00
# include "constants/coins.h"
2019-01-01 01:07:29 +01:00
# include "constants/rgb.h"
2020-07-29 10:46:58 +02:00
# include "constants/roulette.h"
2018-12-31 23:09:45 +01:00
# include "constants/songs.h"
2020-07-29 10:46:58 +02:00
# define BALLS_PER_ROUND 6
2020-08-03 23:31:34 +02:00
// "Board" is used in this file to refer to both the wheel and the bet selection grid
# define NUM_BOARD_COLORS 3 // Rows on grid
# define NUM_BOARD_POKES 4 // Columns on grid
2020-07-29 10:46:58 +02:00
# define NUM_ROULETTE_SLOTS (NUM_BOARD_COLORS * NUM_BOARD_POKES)
2020-08-03 23:31:34 +02:00
// The degree change between each slot on the roulette wheel
# define DEGREES_PER_SLOT (360 / NUM_ROULETTE_SLOTS)
// Where in the slot the ball will drop when landing
# define SLOT_MIDPOINT (DEGREES_PER_SLOT / 2 - 1)
2020-07-29 10:46:58 +02:00
// IDs for grid selections when betting
# define SELECTION_NONE 0
# define COL_WYNAUT 1
# define COL_AZURILL 2
# define COL_SKITTY 3
# define COL_MAKUHITA 4
# define ROW_ORANGE (COL_MAKUHITA + 1)
# define SQU_ORANGE_WYNAUT (ROW_ORANGE + COL_WYNAUT)
# define SQU_ORANGE_AZURILL (ROW_ORANGE + COL_AZURILL)
# define SQU_ORANGE_SKITTY (ROW_ORANGE + COL_SKITTY)
# define SQU_ORANGE_MAKUHITA (ROW_ORANGE + COL_MAKUHITA)
# define ROW_GREEN (SQU_ORANGE_MAKUHITA + 1)
# define SQU_GREEN_WYNAUT (ROW_GREEN + COL_WYNAUT)
# define SQU_GREEN_AZURILL (ROW_GREEN + COL_AZURILL)
# define SQU_GREEN_SKITTY (ROW_GREEN + COL_SKITTY)
# define SQU_GREEN_MAKUHITA (ROW_GREEN + COL_MAKUHITA)
# define ROW_PURPLE (SQU_GREEN_MAKUHITA + 1)
# define SQU_PURPLE_WYNAUT (ROW_PURPLE + COL_WYNAUT)
# define SQU_PURPLE_AZURILL (ROW_PURPLE + COL_AZURILL)
# define SQU_PURPLE_SKITTY (ROW_PURPLE + COL_SKITTY)
# define SQU_PURPLE_MAKUHITA (ROW_PURPLE + COL_MAKUHITA)
# define NUM_GRID_SELECTIONS SQU_PURPLE_MAKUHITA
2020-07-31 20:55:42 +02:00
// Get the id of the col/row from the selection ID
// e.g. GET_ROW(SQU_PURPLE_SKITTY) is ROW_PURPLE
2020-07-29 10:46:58 +02:00
# define GET_COL(selectionId)((selectionId) % (NUM_BOARD_POKES + 1))
# define GET_ROW(selectionId)((selectionId) / (NUM_BOARD_POKES + 1) * (NUM_BOARD_POKES + 1))
2020-07-31 20:55:42 +02:00
// Get the col/row index from the selection ID
2020-08-03 23:31:34 +02:00
// e.g. GET_ROW_IDX(SQU_PURPLE_SKITTY) is 2 (purple being the 3rd row)
2020-07-31 20:55:42 +02:00
# define GET_COL_IDX(selectionId)(selectionId - 1)
# define GET_ROW_IDX(selectionId)(selectionId / 5 - 1)
2020-07-29 10:46:58 +02:00
// Flags for the above selections, used to set which spaces have been hit or bet on
# define F_WYNAUT_COL (1 << COL_WYNAUT)
# define F_AZURILL_COL (1 << COL_AZURILL)
# define F_SKITTY_COL (1 << COL_SKITTY)
# define F_MAKUHITA_COL (1 << COL_MAKUHITA)
# define F_ORANGE_ROW (1 << ROW_ORANGE)
# define F_ORANGE_WYNAUT (1 << SQU_ORANGE_WYNAUT)
# define F_ORANGE_AZURILL (1 << SQU_ORANGE_AZURILL)
# define F_ORANGE_SKITTY (1 << SQU_ORANGE_SKITTY)
# define F_ORANGE_MAKUHITA (1 << SQU_ORANGE_MAKUHITA)
# define F_GREEN_ROW (1 << ROW_GREEN)
# define F_GREEN_WYNAUT (1 << SQU_GREEN_WYNAUT)
# define F_GREEN_AZURILL (1 << SQU_GREEN_AZURILL)
# define F_GREEN_SKITTY (1 << SQU_GREEN_SKITTY)
# define F_GREEN_MAKUHITA (1 << SQU_GREEN_MAKUHITA)
# define F_PURPLE_ROW (1 << ROW_PURPLE)
# define F_PURPLE_WYNAUT (1 << SQU_PURPLE_WYNAUT)
# define F_PURPLE_AZURILL (1 << SQU_PURPLE_AZURILL)
# define F_PURPLE_SKITTY (1 << SQU_PURPLE_SKITTY)
# define F_PURPLE_MAKUHITA (1 << SQU_PURPLE_MAKUHITA)
2020-08-05 01:19:36 +02:00
// Flags for flashing selections on the roulette wheel
# define F_FLASH_COLOR_O_WYNAUT (1 << 0)
# define F_FLASH_COLOR_G_AZURILL (1 << 1)
# define F_FLASH_COLOR_P_SKITTY (1 << 2)
# define F_FLASH_COLOR_O_MAKUHITA (1 << 3)
# define F_FLASH_COLOR_G_WYNAUT (1 << 4)
# define F_FLASH_COLOR_P_AZURILL (1 << 5)
# define F_FLASH_COLOR_O_SKITTY (1 << 6)
# define F_FLASH_COLOR_G_MAKUHITA (1 << 7)
# define F_FLASH_COLOR_P_WYNAUT (1 << 8)
# define F_FLASH_COLOR_O_AZURILL (1 << 9)
# define F_FLASH_COLOR_G_SKITTY (1 << 10)
# define F_FLASH_COLOR_P_MAKUHITA (1 << 11)
# define F_FLASH_OUTER_EDGES (1 << 12) // when the player wins
# define FLASH_ICON (NUM_ROULETTE_SLOTS + 1)
# define FLASH_ICON_2 (FLASH_ICON + 1)
# define FLASH_ICON_3 (FLASH_ICON + 2)
# define F_FLASH_ICON (1 << FLASH_ICON)
# define F_FLASH_COLUMN (1 << FLASH_ICON | 1 << FLASH_ICON_2 | 1 << FLASH_ICON_3)
2020-07-29 10:46:58 +02:00
# define MAX_MULTIPLIER 12
# define PALTAG_SHADOW 1
# define PALTAG_BALL 2
# define PALTAG_BALL_COUNTER 3
2020-08-03 23:31:34 +02:00
# define PALTAG_CURSOR 4
2020-07-29 10:46:58 +02:00
# define PALTAG_INTERFACE 5
# define PALTAG_SHROOMISH 6
# define PALTAG_TAILLOW 7
# define PALTAG_GRID_ICONS 8
# define PALTAG_WYNAUT 9
# define PALTAG_AZURILL 10
# define PALTAG_SKITTY 11
# define PALTAG_MAKUHITA 12
2020-08-03 23:31:34 +02:00
# define GFXTAG_WHEEL_ICONS 0
2020-07-29 10:46:58 +02:00
# define GFXTAG_HEADERS 4
# define GFXTAG_GRID_ICONS 5
2020-08-03 23:31:34 +02:00
# define GFXTAG_WHEEL_CENTER 6
2020-07-29 10:46:58 +02:00
# define GFXTAG_CREDIT 7
# define GFXTAG_CREDIT_DIGIT 8
# define GFXTAG_MULTIPLIER 9
# define GFXTAG_BALL_COUNTER 10
# define GFXTAG_CURSOR 11
# define GFXTAG_BALL 12
# define GFXTAG_SHROOMISH_TAILLOW 13
# define GFXTAG_SHADOW 14
// 2 different Roulette tables with 2 different rates (normal vs service day special)
2021-08-25 00:59:32 +02:00
// & 1 gets which table, >> 7 gets if ROULETTE_SPECIAL_RATE is set
2020-08-03 23:31:34 +02:00
# define GET_MIN_BET_ID(var)(((var) & 1) + (((var) >> 7) * 2))
2020-07-29 10:46:58 +02:00
2020-08-03 23:31:34 +02:00
// Having Shroomish or Taillow in the party can make rolls more consistent in length
// It also increases the likelihood that, if they appear to unstick a ball, they'll move it to a slot the player bet on
2020-07-29 10:46:58 +02:00
# define HAS_SHROOMISH (1 << 0)
# define HAS_TAILLOW (1 << 1)
2020-08-03 23:31:34 +02:00
# define NO_DELAY 0xFFFF
2020-07-31 20:55:42 +02:00
enum {
BALL_STATE_ROLLING ,
BALL_STATE_STUCK ,
BALL_STATE_LANDED = 0xFF ,
} ;
enum {
SELECT_STATE_WAIT ,
SELECT_STATE_DRAW ,
SELECT_STATE_UPDATE ,
SELECT_STATE_ERASE = 0xFF ,
} ;
2020-08-03 23:31:34 +02:00
// Roulette uses a large amount of sprites, and stores ids for these in a single array
// Many are looped over rather than referenced directly
2020-07-29 10:46:58 +02:00
enum {
2020-08-03 23:31:34 +02:00
SPR_WHEEL_BALL_1 ,
SPR_WHEEL_BALL_2 ,
SPR_WHEEL_BALL_3 ,
SPR_WHEEL_BALL_4 ,
SPR_WHEEL_BALL_5 ,
SPR_WHEEL_BALL_6 ,
SPR_WHEEL_CENTER ,
SPR_WHEEL_ICON_ORANGE_WYNAUT ,
SPR_WHEEL_ICON_GREEN_AZURILL ,
SPR_WHEEL_ICON_PURPLE_SKITTY ,
SPR_WHEEL_ICON_ORANGE_MAKUHITA ,
SPR_WHEEL_ICON_GREEN_WYNAUT ,
SPR_WHEEL_ICON_PURPLE_AZURILL ,
SPR_WHEEL_ICON_ORANGE_SKITTY ,
SPR_WHEEL_ICON_GREEN_MAKUHITA ,
SPR_WHEEL_ICON_PURPLE_WYNAUT ,
SPR_WHEEL_ICON_ORANGE_AZURILL ,
SPR_WHEEL_ICON_GREEN_SKITTY ,
SPR_WHEEL_ICON_PURPLE_MAKUHITA ,
SPR_19 , // Unused
2020-07-29 10:46:58 +02:00
SPR_CREDIT ,
SPR_CREDIT_DIG_1 ,
SPR_CREDIT_DIG_10 ,
SPR_CREDIT_DIG_100 ,
SPR_CREDIT_DIG_1000 ,
SPR_MULTIPLIER ,
SPR_BALL_COUNTER_1 ,
SPR_BALL_COUNTER_2 ,
SPR_BALL_COUNTER_3 ,
SPR_GRID_ICON_ORANGE_WYNAUT ,
2020-07-31 20:55:42 +02:00
SPR_GRID_ICON_GREEN_AZURILL ,
SPR_GRID_ICON_PURPLE_SKITTY ,
SPR_GRID_ICON_ORANGE_MAKUHITA ,
SPR_GRID_ICON_GREEN_WYNAUT ,
SPR_GRID_ICON_PURPLE_AZURILL ,
SPR_GRID_ICON_ORANGE_SKITTY ,
SPR_GRID_ICON_GREEN_MAKUHITA ,
SPR_GRID_ICON_PURPLE_WYNAUT ,
SPR_GRID_ICON_ORANGE_AZURILL ,
SPR_GRID_ICON_GREEN_SKITTY ,
SPR_GRID_ICON_PURPLE_MAKUHITA ,
2020-07-29 10:46:58 +02:00
SPR_POKE_HEADER_1 ,
SPR_POKE_HEADER_2 ,
SPR_POKE_HEADER_3 ,
SPR_POKE_HEADER_4 ,
SPR_COLOR_HEADER_1 ,
SPR_COLOR_HEADER_2 ,
SPR_COLOR_HEADER_3 ,
SPR_WIN_SLOT_CURSOR ,
SPR_GRID_BALL_1 ,
SPR_GRID_BALL_2 ,
SPR_GRID_BALL_3 ,
SPR_GRID_BALL_4 ,
SPR_GRID_BALL_5 ,
SPR_GRID_BALL_6 ,
SPR_CLEAR_MON , // Shroomish/Taillow
SPR_CLEAR_MON_SHADOW_1 ,
SPR_CLEAR_MON_SHADOW_2 ,
2020-08-03 23:31:34 +02:00
SPR_58 , // Here below unused
2020-07-29 10:46:58 +02:00
SPR_59 ,
SPR_60 ,
SPR_61 ,
SPR_62 ,
SPR_63 ,
} ;
// Start points for sprite IDs that are looped over
2020-08-03 23:31:34 +02:00
# define SPR_WHEEL_BALLS SPR_WHEEL_BALL_1
# define SPR_WHEEL_ICONS SPR_WHEEL_ICON_ORANGE_WYNAUT
2020-07-31 20:55:42 +02:00
# define SPR_BALL_COUNTER SPR_BALL_COUNTER_1
# define SPR_CREDIT_DIGITS SPR_CREDIT_DIG_1
2020-07-29 10:46:58 +02:00
# define SPR_GRID_ICONS SPR_GRID_ICON_ORANGE_WYNAUT
2020-07-31 20:55:42 +02:00
# define SPR_POKE_HEADERS SPR_POKE_HEADER_1
2020-08-03 23:31:34 +02:00
# define SPR_COLOR_HEADERS SPR_COLOR_HEADER_1
# define SPR_GRID_BALLS SPR_GRID_BALL_1
struct Shroomish
{
u16 startAngle ;
u16 dropAngle ;
u16 fallSlowdown ;
} ;
struct Taillow
{
u16 baseDropDelay ;
u16 rightStartAngle ;
u16 leftStartAngle ;
} ;
2020-07-29 10:46:58 +02:00
2020-07-31 20:55:42 +02:00
struct RouletteTable
2018-12-31 23:09:45 +01:00
{
2020-07-31 20:55:42 +02:00
u8 minBet ; // Never read
2020-08-03 23:31:34 +02:00
u8 randDistanceHigh ;
u8 randDistanceLow ;
2020-07-31 20:55:42 +02:00
u8 wheelSpeed ;
u8 wheelDelay ;
2020-08-03 23:31:34 +02:00
struct Shroomish shroomish ;
struct Taillow taillow ;
u16 ballSpeed ;
u16 baseTravelDist ;
2021-05-01 07:41:27 +02:00
f32 var1C ;
2018-12-31 23:09:45 +01:00
} ;
2020-07-29 10:46:58 +02:00
struct GridSelection
2018-12-31 23:09:45 +01:00
{
2020-08-03 23:31:34 +02:00
u8 spriteIdOffset ;
2020-07-29 10:46:58 +02:00
u8 baseMultiplier : 4 ;
u8 column : 4 ; // Never read
u8 row ; // Never read
u8 x ;
u8 y ;
u8 var05 ; // Never read
2020-08-03 23:31:34 +02:00
u8 tilemapOffset ;
2020-07-29 10:46:58 +02:00
u32 flag ;
u32 inSelectionFlags ;
2020-08-05 01:19:36 +02:00
u16 flashFlags ;
2018-12-31 23:09:45 +01:00
} ;
2020-07-29 10:46:58 +02:00
struct RouletteSlot
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
u8 id1 ; // Never read
u8 id2 ; // Never read
u8 gridSquare ;
u32 flag ;
2019-01-01 01:07:29 +01:00
} ;
2020-07-29 10:46:58 +02:00
static EWRAM_DATA struct Roulette
2018-12-31 23:09:45 +01:00
{
2020-07-31 20:55:42 +02:00
u8 unk0 ; // Never read
2020-08-03 23:31:34 +02:00
u8 shroomishShadowTimer ;
2020-07-29 10:46:58 +02:00
u8 partySpeciesFlags ;
bool8 useTaillow : 5 ;
2020-07-31 20:55:42 +02:00
bool8 ballStuck : 1 ;
bool8 ballUnstuck : 1 ;
bool8 ballRolling : 1 ; // Never read
2020-07-29 10:46:58 +02:00
u8 tableId : 2 ;
2020-07-31 20:55:42 +02:00
u8 unused : 5 ;
2020-07-29 10:46:58 +02:00
bool8 isSpecialRate : 1 ;
u32 hitFlags ;
u8 hitSquares [ BALLS_PER_ROUND ] ;
u8 pokeHits [ NUM_BOARD_POKES ] ;
u8 colorHits [ NUM_BOARD_COLORS ] ;
u8 minBet ;
2020-08-03 23:31:34 +02:00
u8 curBallNum : 4 ; // Never actually gets incremented, tracked with tBallNum instead
u8 unk1 : 4 ; // Never read
2020-07-29 10:46:58 +02:00
u8 betSelection [ BALLS_PER_ROUND ] ; // Because curBallNum is used as the only index, only the first element is ever used (prev bet selections are never needed)
2020-07-31 20:55:42 +02:00
u8 wheelDelayTimer ;
u8 wheelSpeed ;
u8 wheelDelay ;
s16 wheelAngle ;
s16 gridX ;
s16 selectionRectDrawState ;
s16 updateGridHighlight ;
struct OamMatrix wheelRotation ;
2020-08-03 23:31:34 +02:00
u16 shroomishShadowAlpha ;
struct Sprite * ball ;
2020-07-31 20:55:42 +02:00
u8 spriteIds [ MAX_SPRITES ] ;
u8 curBallSpriteId ;
u8 ballState ;
u8 hitSlot ;
2020-08-03 23:31:34 +02:00
u8 stuckHitSlot ;
s16 ballTravelDist ; // Never read
s16 ballTravelDistFast ;
u16 ballTravelDistMed ;
u16 ballTravelDistSlow ;
2021-05-01 07:41:27 +02:00
f32 ballAngle ;
f32 ballAngleSpeed ;
f32 ballAngleAccel ;
f32 ballDistToCenter ;
f32 ballFallSpeed ;
f32 ballFallAccel ;
f32 varA0 ;
2020-07-31 20:55:42 +02:00
u8 playTaskId ;
u8 spinTaskId ;
u8 filler_1 [ 2 ] ;
2020-07-29 10:46:58 +02:00
u16 taskWaitDelay ;
u16 taskWaitKey ;
TaskFunc nextTask ;
2020-07-31 20:55:42 +02:00
u8 filler_2 [ 4 ] ;
TaskFunc prevTask ;
2020-08-05 01:19:36 +02:00
struct RouletteFlashUtil flashUtil ;
2018-12-31 23:09:45 +01:00
u16 tilemapBuffers [ 7 ] [ 0x400 ] ;
2020-07-31 20:55:42 +02:00
u16 * gridTilemap ;
2020-07-29 10:46:58 +02:00
} * sRoulette = NULL ;
static EWRAM_DATA u8 sTextWindowId = 0 ;
2020-07-31 20:55:42 +02:00
static void Task_SpinWheel ( u8 ) ;
2020-07-29 10:46:58 +02:00
static void Task_StartPlaying ( u8 ) ;
static void Task_ContinuePlaying ( u8 ) ;
static void Task_StopPlaying ( u8 ) ;
static void Task_SelectFirstEmptySquare ( u8 ) ;
static void Task_HandleBetGridInput ( u8 ) ;
static void Task_SlideGridOffscreen ( u8 ) ;
2020-07-31 20:55:42 +02:00
static void Task_InitBallRoll ( u8 ) ;
2020-07-29 10:46:58 +02:00
static void Task_RollBall ( u8 ) ;
static void Task_RecordBallHit ( u8 ) ;
static void Task_SlideGridOnscreen ( u8 ) ;
2020-07-31 20:55:42 +02:00
static void Task_FlashBallOnWinningSquare ( u8 ) ;
2020-07-29 10:46:58 +02:00
static void Task_PrintSpinResult ( u8 ) ;
static void Task_PrintPayout ( u8 ) ;
static void Task_EndTurn ( u8 ) ;
static void Task_TryPrintEndTurnMsg ( u8 ) ;
static void Task_ClearBoard ( u8 ) ;
static void ExitRoulette ( u8 ) ;
static void Task_ExitRoulette ( u8 ) ;
static void StartTaskAfterDelayOrInput ( u8 , TaskFunc , u16 , u16 ) ;
2020-08-03 23:31:34 +02:00
static void ResetBallDataForNewSpin ( u8 ) ;
2020-07-29 10:46:58 +02:00
static void ResetHits ( void ) ;
static void Task_AcceptMinBet ( u8 ) ;
static void Task_DeclineMinBet ( u8 ) ;
static u8 RecordHit ( u8 , u8 ) ;
static bool8 IsHitInBetSelection ( u8 , u8 ) ;
static void FlashSelectionOnWheel ( u8 ) ;
static void DrawGridBackground ( u8 ) ;
static u8 GetMultiplier ( u8 ) ;
2020-07-31 20:55:42 +02:00
static void UpdateWheelPosition ( void ) ;
2020-07-29 10:46:58 +02:00
static void LoadOrFreeMiscSpritePalettesAndSheets ( u8 ) ;
static void CreateGridSprites ( void ) ;
static void ShowHideGridIcons ( bool8 , u8 ) ;
static void CreateGridBallSprites ( void ) ;
static void ShowHideGridBalls ( bool8 , u8 ) ;
static void ShowHideWinSlotCursor ( u8 ) ;
2020-08-03 23:31:34 +02:00
static void CreateWheelIconSprites ( void ) ;
static void SpriteCB_WheelIcon ( struct Sprite * ) ;
2020-07-29 10:46:58 +02:00
static void CreateInterfaceSprites ( void ) ;
static void SetCreditDigits ( u16 ) ;
static void SetMultiplierSprite ( u8 ) ;
static void SetBallCounterNumLeft ( u8 ) ;
static void SpriteCB_GridSquare ( struct Sprite * ) ;
2020-08-03 23:31:34 +02:00
static void CreateWheelCenterSprite ( void ) ;
static void SpriteCB_WheelCenter ( struct Sprite * ) ;
static void CreateWheelBallSprites ( void ) ;
static void HideWheelBalls ( void ) ;
static void SpriteCB_RollBall_Start ( struct Sprite * ) ;
2020-07-29 10:46:58 +02:00
static void CreateShroomishSprite ( struct Sprite * ) ;
static void CreateTaillowSprite ( struct Sprite * ) ;
2020-08-03 23:31:34 +02:00
static void SetBallStuck ( struct Sprite * ) ;
static void SpriteCB_Shroomish ( struct Sprite * ) ;
2020-07-29 10:46:58 +02:00
static void SpriteCB_Taillow ( struct Sprite * ) ;
2019-01-02 23:55:50 +01:00
2020-07-31 20:55:42 +02:00
static const u16 sWheel_Pal [ ] = INCBIN_U16 ( " graphics/roulette/wheel.gbapal " ) ; // also palette for grid
static const u32 sGrid_Tilemap [ ] = INCBIN_U32 ( " graphics/roulette/grid.bin.lz " ) ;
static const u32 sWheel_Tilemap [ ] = INCBIN_U32 ( " graphics/roulette/wheel.bin.lz " ) ;
2020-07-29 10:46:58 +02:00
static const struct BgTemplate sBgTemplates [ ] =
2019-01-02 23:40:40 +01:00
{
2020-07-31 20:55:42 +02:00
// Text box
2019-01-02 23:40:40 +01:00
{
. bg = 0 ,
. charBaseIndex = 2 ,
. mapBaseIndex = 31 ,
. screenSize = 0 ,
. paletteMode = 0 ,
. priority = 0 ,
. baseTile = 0
} ,
2020-07-31 20:55:42 +02:00
// Selection grid
2019-01-02 23:40:40 +01:00
{
. bg = 1 ,
. charBaseIndex = 0 ,
. mapBaseIndex = 4 ,
. screenSize = 1 ,
. paletteMode = 0 ,
. priority = 1 ,
. baseTile = 0
} ,
2020-07-31 20:55:42 +02:00
// Wheel
2019-01-02 23:40:40 +01:00
{
. bg = 2 ,
. charBaseIndex = 1 ,
. mapBaseIndex = 6 ,
. screenSize = 1 ,
. paletteMode = 1 ,
. priority = 2 ,
. baseTile = 0
}
} ;
2020-07-29 10:46:58 +02:00
static const struct WindowTemplate sWindowTemplates [ ] =
2019-01-02 23:40:40 +01:00
{
{
. bg = 0 ,
. tilemapLeft = 3 ,
. tilemapTop = 15 ,
. width = 24 ,
. height = 4 ,
. paletteNum = 15 ,
. baseBlock = 0xC5
} ,
2020-12-13 05:28:01 +01:00
# ifdef UBFIX
DUMMY_WIN_TEMPLATE ,
# endif
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const struct GridSelection sGridSelections [ NUM_GRID_SELECTIONS + 1 ] =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
[ SELECTION_NONE ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 0xFF ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = 0 ,
. column = 0 ,
. row = 0 ,
. x = 7 ,
. y = 7 ,
2019-01-02 23:40:40 +01:00
. var05 = 0 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 0 ,
2020-07-29 10:46:58 +02:00
. flag = 0 ,
. inSelectionFlags = 0 ,
2020-08-05 01:19:36 +02:00
. flashFlags = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ COL_WYNAUT ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 12 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_BOARD_POKES ,
. column = 1 ,
. row = 0 ,
. x = 17 ,
. y = 7 ,
2019-01-02 23:40:40 +01:00
. var05 = 0 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 0 ,
2020-07-29 10:46:58 +02:00
. flag = F_WYNAUT_COL ,
. inSelectionFlags = F_WYNAUT_COL | F_ORANGE_WYNAUT | F_GREEN_WYNAUT | F_PURPLE_WYNAUT ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_COLUMN ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ COL_AZURILL ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 13 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_BOARD_POKES ,
. column = 2 ,
. row = 0 ,
. x = 20 ,
. y = 7 ,
2019-01-02 23:40:40 +01:00
. var05 = 0 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 0 ,
2020-07-29 10:46:58 +02:00
. flag = F_AZURILL_COL ,
. inSelectionFlags = F_AZURILL_COL | F_ORANGE_AZURILL | F_GREEN_AZURILL | F_PURPLE_AZURILL ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_COLUMN ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ COL_SKITTY ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 14 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_BOARD_POKES ,
. column = 3 ,
. row = 0 ,
. x = 23 ,
. y = 7 ,
2019-01-02 23:40:40 +01:00
. var05 = 0 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 0 ,
2020-07-29 10:46:58 +02:00
. flag = F_SKITTY_COL ,
. inSelectionFlags = F_SKITTY_COL | F_ORANGE_SKITTY | F_GREEN_SKITTY | F_PURPLE_SKITTY ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_COLUMN ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ COL_MAKUHITA ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 15 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_BOARD_POKES ,
. column = 4 ,
. row = 0 ,
. x = 26 ,
. y = 7 ,
2019-01-02 23:40:40 +01:00
. var05 = 0 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 0 ,
2020-07-29 10:46:58 +02:00
. flag = F_MAKUHITA_COL ,
. inSelectionFlags = F_MAKUHITA_COL | F_ORANGE_MAKUHITA | F_GREEN_MAKUHITA | F_PURPLE_MAKUHITA ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_COLUMN ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ ROW_ORANGE ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 16 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_BOARD_COLORS ,
. column = 0 ,
. row = 1 ,
. x = 14 ,
. y = 10 ,
2019-01-02 23:40:40 +01:00
. var05 = 0 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 12 ,
2020-07-29 10:46:58 +02:00
. flag = F_ORANGE_ROW ,
. inSelectionFlags = F_ORANGE_ROW | F_ORANGE_WYNAUT | F_ORANGE_AZURILL | F_ORANGE_SKITTY | F_ORANGE_MAKUHITA ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_COLOR_O_WYNAUT | F_FLASH_COLOR_O_AZURILL | F_FLASH_COLOR_O_SKITTY | F_FLASH_COLOR_O_MAKUHITA ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_ORANGE_WYNAUT ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 0 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 1 ,
. row = 1 ,
. x = 17 ,
. y = 10 ,
2019-01-02 23:40:40 +01:00
. var05 = 3 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 3 ,
2020-07-29 10:46:58 +02:00
. flag = F_ORANGE_WYNAUT ,
. inSelectionFlags = F_ORANGE_WYNAUT ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_O_WYNAUT ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_ORANGE_AZURILL ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 9 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 2 ,
. row = 1 ,
. x = 20 ,
. y = 10 ,
2019-01-02 23:40:40 +01:00
. var05 = 3 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 3 ,
2020-07-29 10:46:58 +02:00
. flag = F_ORANGE_AZURILL ,
. inSelectionFlags = F_ORANGE_AZURILL ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_O_AZURILL ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_ORANGE_SKITTY ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 6 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 3 ,
. row = 1 ,
. x = 23 ,
. y = 10 ,
2019-01-02 23:40:40 +01:00
. var05 = 3 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 3 ,
2020-07-29 10:46:58 +02:00
. flag = F_ORANGE_SKITTY ,
. inSelectionFlags = F_ORANGE_SKITTY ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_O_SKITTY ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_ORANGE_MAKUHITA ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 3 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 4 ,
. row = 1 ,
. x = 26 ,
. y = 10 ,
2019-01-02 23:40:40 +01:00
. var05 = 3 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 3 ,
2020-07-29 10:46:58 +02:00
. flag = F_ORANGE_MAKUHITA ,
. inSelectionFlags = F_ORANGE_MAKUHITA ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_O_MAKUHITA ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ ROW_GREEN ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 17 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_BOARD_COLORS ,
. column = 0 ,
. row = 2 ,
. x = 14 ,
. y = 13 ,
2019-01-02 23:40:40 +01:00
. var05 = 3 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 15 ,
2020-07-29 10:46:58 +02:00
. flag = F_GREEN_ROW ,
. inSelectionFlags = F_GREEN_ROW | F_GREEN_WYNAUT | F_GREEN_AZURILL | F_GREEN_SKITTY | F_GREEN_MAKUHITA ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_COLOR_G_WYNAUT | F_FLASH_COLOR_G_AZURILL | F_FLASH_COLOR_G_SKITTY | F_FLASH_COLOR_G_MAKUHITA ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_GREEN_WYNAUT ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 4 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 1 ,
. row = 2 ,
. x = 17 ,
. y = 13 ,
2019-01-02 23:40:40 +01:00
. var05 = 6 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 6 ,
2020-07-29 10:46:58 +02:00
. flag = F_GREEN_WYNAUT ,
. inSelectionFlags = F_GREEN_WYNAUT ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_G_WYNAUT ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_GREEN_AZURILL ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 1 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 2 ,
. row = 2 ,
. x = 20 ,
. y = 13 ,
2019-01-02 23:40:40 +01:00
. var05 = 6 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 6 ,
2020-07-29 10:46:58 +02:00
. flag = F_GREEN_AZURILL ,
. inSelectionFlags = F_GREEN_AZURILL ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_G_AZURILL ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_GREEN_SKITTY ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 10 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 3 ,
. row = 2 ,
. x = 23 ,
. y = 13 ,
2019-01-02 23:40:40 +01:00
. var05 = 6 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 6 ,
2020-07-29 10:46:58 +02:00
. flag = F_GREEN_SKITTY ,
. inSelectionFlags = F_GREEN_SKITTY ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_G_SKITTY ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_GREEN_MAKUHITA ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 7 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 4 ,
. row = 2 ,
. x = 26 ,
. y = 13 ,
2019-01-02 23:40:40 +01:00
. var05 = 6 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 6 ,
2020-07-29 10:46:58 +02:00
. flag = F_GREEN_MAKUHITA ,
. inSelectionFlags = F_GREEN_MAKUHITA ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_G_MAKUHITA ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ ROW_PURPLE ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 18 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_BOARD_COLORS ,
. column = 0 ,
. row = 3 ,
. x = 14 ,
. y = 16 ,
2019-01-02 23:40:40 +01:00
. var05 = 6 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 18 ,
2020-07-29 10:46:58 +02:00
. flag = F_PURPLE_ROW ,
. inSelectionFlags = F_PURPLE_ROW | F_PURPLE_WYNAUT | F_PURPLE_AZURILL | F_PURPLE_SKITTY | F_PURPLE_MAKUHITA ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_COLOR_P_WYNAUT | F_FLASH_COLOR_P_AZURILL | F_FLASH_COLOR_P_SKITTY | F_FLASH_COLOR_P_MAKUHITA ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_PURPLE_WYNAUT ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 8 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 1 ,
. row = 3 ,
. x = 17 ,
. y = 16 ,
2019-01-02 23:40:40 +01:00
. var05 = 9 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 9 ,
2020-07-29 10:46:58 +02:00
. flag = F_PURPLE_WYNAUT ,
. inSelectionFlags = F_PURPLE_WYNAUT ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_P_WYNAUT ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_PURPLE_AZURILL ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 5 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 2 ,
. row = 3 ,
. x = 20 ,
. y = 16 ,
2019-01-02 23:40:40 +01:00
. var05 = 9 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 9 ,
2020-07-29 10:46:58 +02:00
. flag = F_PURPLE_AZURILL ,
. inSelectionFlags = F_PURPLE_AZURILL ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_P_AZURILL ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_PURPLE_SKITTY ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 2 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 3 ,
. row = 3 ,
. x = 23 ,
. y = 16 ,
2019-01-02 23:40:40 +01:00
. var05 = 9 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 9 ,
2020-07-29 10:46:58 +02:00
. flag = F_PURPLE_SKITTY ,
. inSelectionFlags = F_PURPLE_SKITTY ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_P_SKITTY ,
2019-01-02 23:40:40 +01:00
} ,
2020-07-29 10:46:58 +02:00
[ SQU_PURPLE_MAKUHITA ] = {
2020-08-03 23:31:34 +02:00
. spriteIdOffset = 11 ,
2020-07-29 10:46:58 +02:00
. baseMultiplier = NUM_ROULETTE_SLOTS ,
. column = 4 ,
. row = 3 ,
. x = 26 ,
. y = 16 ,
2019-01-02 23:40:40 +01:00
. var05 = 9 ,
2020-08-03 23:31:34 +02:00
. tilemapOffset = 9 ,
2020-07-29 10:46:58 +02:00
. flag = F_PURPLE_MAKUHITA ,
. inSelectionFlags = F_PURPLE_MAKUHITA ,
2020-08-05 01:19:36 +02:00
. flashFlags = F_FLASH_ICON | F_FLASH_COLOR_P_MAKUHITA ,
2019-01-02 23:40:40 +01:00
} ,
} ;
2020-07-29 10:46:58 +02:00
static const struct RouletteSlot sRouletteSlots [ ] =
2019-01-02 23:40:40 +01:00
{
{
2020-07-29 10:46:58 +02:00
. id1 = 0 ,
. id2 = 1 ,
. gridSquare = SQU_ORANGE_WYNAUT ,
. flag = F_ORANGE_WYNAUT ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 1 ,
. id2 = 3 ,
. gridSquare = SQU_GREEN_AZURILL ,
. flag = F_GREEN_AZURILL ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 2 ,
. id2 = 5 ,
. gridSquare = SQU_PURPLE_SKITTY ,
. flag = F_PURPLE_SKITTY ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 3 ,
. id2 = 7 ,
. gridSquare = SQU_ORANGE_MAKUHITA ,
. flag = F_ORANGE_MAKUHITA ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 4 ,
. id2 = 9 ,
. gridSquare = SQU_GREEN_WYNAUT ,
. flag = F_GREEN_WYNAUT ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 5 ,
. id2 = 11 ,
. gridSquare = SQU_PURPLE_AZURILL ,
. flag = F_PURPLE_AZURILL ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 6 ,
. id2 = 13 ,
. gridSquare = SQU_ORANGE_SKITTY ,
. flag = F_ORANGE_SKITTY ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 7 ,
. id2 = 15 ,
. gridSquare = SQU_GREEN_MAKUHITA ,
. flag = F_GREEN_MAKUHITA ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 8 ,
. id2 = 17 ,
. gridSquare = SQU_PURPLE_WYNAUT ,
. flag = F_PURPLE_WYNAUT ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 9 ,
. id2 = 19 ,
. gridSquare = SQU_ORANGE_AZURILL ,
. flag = F_ORANGE_AZURILL ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 10 ,
. id2 = 21 ,
. gridSquare = SQU_GREEN_SKITTY ,
. flag = F_GREEN_SKITTY ,
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. id1 = 11 ,
. id2 = 23 ,
. gridSquare = SQU_PURPLE_MAKUHITA ,
. flag = F_PURPLE_MAKUHITA ,
2019-01-02 23:40:40 +01:00
} ,
} ;
2020-07-29 10:46:58 +02:00
static const u8 sTableMinBets [ ] = { 1 , 3 , 1 , 6 } ;
2020-07-31 20:55:42 +02:00
static const struct RouletteTable sRouletteTables [ ] =
2019-01-02 23:40:40 +01:00
{
2020-07-31 20:55:42 +02:00
// Left table
2019-01-02 23:40:40 +01:00
{
2020-07-31 20:55:42 +02:00
. minBet = 1 ,
2020-08-03 23:31:34 +02:00
. randDistanceHigh = DEGREES_PER_SLOT * 2 ,
. randDistanceLow = DEGREES_PER_SLOT ,
2020-07-31 20:55:42 +02:00
. wheelSpeed = 1 ,
. wheelDelay = 1 ,
2020-08-03 23:31:34 +02:00
. shroomish = {
. startAngle = 45 ,
. dropAngle = 30 ,
. fallSlowdown = 1 ,
} ,
. taillow = {
. baseDropDelay = 75 ,
. rightStartAngle = 27 ,
. leftStartAngle = 24 ,
} ,
. ballSpeed = 10 ,
. baseTravelDist = 360 ,
2019-01-02 23:40:40 +01:00
. var1C = - 0.5f
} ,
2020-07-31 20:55:42 +02:00
// Right table
2019-01-02 23:40:40 +01:00
{
2020-07-31 20:55:42 +02:00
. minBet = 3 ,
2020-08-03 23:31:34 +02:00
. randDistanceHigh = DEGREES_PER_SLOT ,
. randDistanceLow = DEGREES_PER_SLOT / 2 ,
2020-07-31 20:55:42 +02:00
. wheelSpeed = 1 ,
. wheelDelay = 0 ,
2020-08-03 23:31:34 +02:00
. shroomish = {
. startAngle = 75 ,
. dropAngle = 60 ,
. fallSlowdown = 2 ,
} ,
. taillow = {
. baseDropDelay = 0 ,
. rightStartAngle = 54 ,
. leftStartAngle = 48 ,
} ,
. ballSpeed = 10 ,
. baseTravelDist = 270 ,
2019-01-02 23:40:40 +01:00
. var1C = - 1.0f
}
} ;
2020-08-05 01:19:36 +02:00
// Data to flash the color indicator for each slot on the roulette wheel
static const struct RouletteFlashSettings sFlashData_Colors [ NUM_ROULETTE_SLOTS + 1 ] =
2019-01-02 23:40:40 +01:00
{
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_O_WYNAUT
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0x5 ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_G_AZURILL
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0xA ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_P_SKITTY
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0x15 ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_O_MAKUHITA
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0x55 ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_G_WYNAUT
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0x5A ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_P_AZURILL
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0x65 ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_O_SKITTY
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0x75 ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_G_MAKUHITA
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0x7A ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_P_WYNAUT
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0x85 ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_O_AZURILL
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0x95 ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_G_SKITTY
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0x9A ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_COLOR_P_MAKUHITA
. color = FLASHUTIL_USE_EXISTING_COLOR ,
. paletteOffset = 0xA5 ,
. numColors = 1 ,
. delay = 1 ,
. unk6 = - 1 ,
. numFadeCycles = 8 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
{ // F_FLASH_OUTER_EDGES
. color = RGB ( 22 , 30 , 29 ) ,
. paletteOffset = 0x28 ,
. numColors = 2 ,
. delay = 10 ,
. unk6 = - 1 ,
. numFadeCycles = 14 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
} ;
2020-08-05 01:19:36 +02:00
// Data to flash any pokemon icon (F_FLASH_ICON) on the roulette wheel. One entry for each color row
// Each poke icon flashes with the tint of the row color it belongs to, so the pokemon itself is irrelevant
static const struct RouletteFlashSettings sFlashData_PokeIcons [ NUM_BOARD_COLORS ] =
2019-01-02 23:40:40 +01:00
{
2020-08-05 01:19:36 +02:00
[ GET_ROW_IDX ( ROW_ORANGE ) ] = {
. color = RGB ( 31 , 31 , 20 ) ,
. paletteOffset = 0x101 ,
. numColors = 5 ,
. delay = 30 ,
. unk6 = - 1 ,
. numFadeCycles = 14 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
[ GET_ROW_IDX ( ROW_GREEN ) ] = {
. color = RGB ( 27 , 31 , 31 ) ,
. paletteOffset = 0x106 ,
. numColors = 5 ,
. delay = 30 ,
. unk6 = - 1 ,
. numFadeCycles = 14 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
} ,
2020-08-05 01:19:36 +02:00
[ GET_ROW_IDX ( ROW_PURPLE ) ] = {
. color = RGB ( 31 , 27 , 31 ) ,
. paletteOffset = 0x10B ,
. numColors = 5 ,
. delay = 30 ,
. unk6 = - 1 ,
. numFadeCycles = 14 ,
. unk7_5 = - 2 ,
. colorDeltaDir = 0 ,
2019-01-02 23:40:40 +01:00
}
} ;
2020-07-29 10:46:58 +02:00
static const struct YesNoFuncTable sYesNoTable_AcceptMinBet =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
Task_AcceptMinBet ,
Task_DeclineMinBet
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const struct YesNoFuncTable sYesNoTable_KeepPlaying =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
Task_ContinuePlaying ,
Task_StopPlaying
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static void CB2_Roulette ( void )
2018-12-31 23:09:45 +01:00
{
RunTasks ( ) ;
AnimateSprites ( ) ;
BuildOamBuffer ( ) ;
2020-08-05 01:19:36 +02:00
if ( sRoulette - > flashUtil . enabled )
RouletteFlash_Run ( & sRoulette - > flashUtil ) ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static void VBlankCB_Roulette ( void )
2018-12-31 23:09:45 +01:00
{
LoadOam ( ) ;
ProcessSpriteCopyRequests ( ) ;
TransferPlttBuffer ( ) ;
2020-07-31 20:55:42 +02:00
UpdateWheelPosition ( ) ;
SetGpuReg ( REG_OFFSET_BG1HOFS , 0x200 - sRoulette - > gridX ) ;
2020-08-03 23:31:34 +02:00
if ( sRoulette - > shroomishShadowTimer )
SetGpuReg ( REG_OFFSET_BLDALPHA , sRoulette - > shroomishShadowAlpha ) ;
2020-07-31 20:55:42 +02:00
if ( sRoulette - > updateGridHighlight )
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
DmaCopy16 ( 3 , & sRoulette - > tilemapBuffers [ 2 ] [ 0xE0 ] , ( void * ) BG_SCREEN_ADDR ( 4 ) + 0x1C0 , 0x340 ) ;
2020-07-31 20:55:42 +02:00
sRoulette - > updateGridHighlight = FALSE ;
2018-12-31 23:09:45 +01:00
}
2020-07-31 20:55:42 +02:00
switch ( sRoulette - > selectionRectDrawState )
2018-12-31 23:09:45 +01:00
{
2020-07-31 20:55:42 +02:00
case SELECT_STATE_DRAW :
2018-12-31 23:09:45 +01:00
SetBgAttribute ( 0 , BG_ATTR_CHARBASEINDEX , 0 ) ;
ShowBg ( 0 ) ;
2020-07-29 10:46:58 +02:00
DmaCopy16 ( 3 , & sRoulette - > tilemapBuffers [ 0 ] [ 0xE0 ] , ( void * ) BG_SCREEN_ADDR ( 31 ) + 0x1C0 , 0x340 ) ;
2020-07-31 20:55:42 +02:00
sRoulette - > selectionRectDrawState = SELECT_STATE_UPDATE ;
2018-12-31 23:09:45 +01:00
break ;
2020-07-31 20:55:42 +02:00
case SELECT_STATE_UPDATE :
2020-07-29 10:46:58 +02:00
DmaCopy16 ( 3 , & sRoulette - > tilemapBuffers [ 0 ] [ 0xE0 ] , ( void * ) BG_SCREEN_ADDR ( 31 ) + 0x1C0 , 0x340 ) ;
2018-12-31 23:09:45 +01:00
break ;
2020-07-31 20:55:42 +02:00
case SELECT_STATE_ERASE :
2018-12-31 23:09:45 +01:00
SetBgAttribute ( 0 , BG_ATTR_CHARBASEINDEX , 2 ) ;
ShowBg ( 0 ) ;
DmaFill16 ( 3 , 0 , ( void * ) BG_SCREEN_ADDR ( 31 ) + 0x1C0 , 0x340 ) ;
2020-07-31 20:55:42 +02:00
sRoulette - > selectionRectDrawState = SELECT_STATE_WAIT ;
case SELECT_STATE_WAIT :
2018-12-31 23:09:45 +01:00
break ;
}
}
2020-07-29 10:46:58 +02:00
static void InitRouletteBgAndWindows ( void )
2018-12-31 23:09:45 +01:00
{
u32 size = 0 ;
2020-07-29 10:46:58 +02:00
sRoulette = AllocZeroed ( sizeof ( * sRoulette ) ) ;
2018-12-31 23:09:45 +01:00
ResetBgsAndClearDma3BusyFlags ( 0 ) ;
2020-07-29 10:46:58 +02:00
InitBgsFromTemplates ( 1 , sBgTemplates , ARRAY_COUNT ( sBgTemplates ) ) ;
SetBgTilemapBuffer ( 0 , sRoulette - > tilemapBuffers [ 0 ] ) ;
SetBgTilemapBuffer ( 1 , sRoulette - > tilemapBuffers [ 2 ] ) ;
SetBgTilemapBuffer ( 2 , sRoulette - > tilemapBuffers [ 6 ] ) ;
InitWindows ( sWindowTemplates ) ;
2020-06-20 01:58:56 +02:00
InitTextBoxGfxAndPrinters ( ) ;
2020-07-29 10:46:58 +02:00
sTextWindowId = 0 ;
2020-07-31 20:55:42 +02:00
sRoulette - > gridTilemap = malloc_and_decompress ( sGrid_Tilemap , & size ) ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static void FreeRoulette ( void )
2018-12-31 23:09:45 +01:00
{
2020-07-31 20:55:42 +02:00
FREE_AND_SET_NULL ( sRoulette - > gridTilemap ) ;
2018-12-31 23:09:45 +01:00
FreeAllWindowBuffers ( ) ;
UnsetBgTilemapBuffer ( 0 ) ;
UnsetBgTilemapBuffer ( 1 ) ;
UnsetBgTilemapBuffer ( 2 ) ;
ResetBgsAndClearDma3BusyFlags ( 0 ) ;
2020-07-29 10:46:58 +02:00
memset ( sRoulette , 0 , sizeof ( * sRoulette ) ) ;
FREE_AND_SET_NULL ( sRoulette ) ;
2018-12-31 23:09:45 +01:00
}
2020-08-03 23:31:34 +02:00
static void InitRouletteTableData ( void )
2018-12-31 23:09:45 +01:00
{
u8 i ;
2020-07-31 20:55:42 +02:00
u16 bgColors [ 3 ] = { RGB ( 24 , 4 , 10 ) , RGB ( 10 , 19 , 6 ) , RGB ( 24 , 4 , 10 ) } ; // 3rd is never used, same as 1st
2018-12-31 23:09:45 +01:00
2020-07-29 10:46:58 +02:00
sRoulette - > tableId = ( gSpecialVar_0x8004 & 1 ) ;
2018-12-31 23:09:45 +01:00
2020-07-29 10:46:58 +02:00
if ( gSpecialVar_0x8004 & ROULETTE_SPECIAL_RATE )
sRoulette - > isSpecialRate = TRUE ;
2018-12-31 23:09:45 +01:00
2020-07-31 20:55:42 +02:00
sRoulette - > wheelSpeed = sRouletteTables [ sRoulette - > tableId ] . wheelSpeed ;
sRoulette - > wheelDelay = sRouletteTables [ sRoulette - > tableId ] . wheelDelay ;
2020-07-29 10:46:58 +02:00
sRoulette - > minBet = sTableMinBets [ sRoulette - > tableId + sRoulette - > isSpecialRate * 2 ] ;
2020-08-03 23:31:34 +02:00
sRoulette - > unk1 = 1 ;
2018-12-31 23:09:45 +01:00
2020-07-31 20:55:42 +02:00
// Left table (with min bet of 1) has red background, other table has green
2020-07-29 10:46:58 +02:00
if ( sRoulette - > minBet = = 1 )
2020-07-31 20:55:42 +02:00
gPlttBufferUnfaded [ 0 ] = gPlttBufferUnfaded [ 0x51 ] = gPlttBufferFaded [ 0 ] = gPlttBufferFaded [ 0x51 ] = bgColors [ 0 ] ;
2018-12-31 23:09:45 +01:00
else
2020-07-31 20:55:42 +02:00
gPlttBufferUnfaded [ 0 ] = gPlttBufferUnfaded [ 0x51 ] = gPlttBufferFaded [ 0 ] = gPlttBufferFaded [ 0x51 ] = bgColors [ 1 ] ;
2018-12-31 23:09:45 +01:00
2020-08-05 01:19:36 +02:00
RouletteFlash_Reset ( & sRoulette - > flashUtil ) ;
2018-12-31 23:09:45 +01:00
2020-07-31 20:55:42 +02:00
// Init flash util for flashing the selected colors on the wheel
2020-08-05 01:19:36 +02:00
// + 1 for the additional entry to flash the outer edges on a win
2020-07-31 20:55:42 +02:00
for ( i = 0 ; i < NUM_ROULETTE_SLOTS + 1 ; i + + )
2018-12-31 23:09:45 +01:00
{
2020-08-05 01:19:36 +02:00
RouletteFlash_Add ( & sRoulette - > flashUtil , i , & sFlashData_Colors [ i ] ) ;
2018-12-31 23:09:45 +01:00
}
2019-04-11 12:05:56 +02:00
2018-12-31 23:09:45 +01:00
for ( i = 0 ; i < PARTY_SIZE ; i + + )
{
switch ( GetMonData ( & gPlayerParty [ i ] , MON_DATA_SPECIES2 ) )
{
case SPECIES_SHROOMISH :
2020-07-29 10:46:58 +02:00
sRoulette - > partySpeciesFlags | = HAS_SHROOMISH ;
2018-12-31 23:09:45 +01:00
break ;
case SPECIES_TAILLOW :
2020-07-29 10:46:58 +02:00
sRoulette - > partySpeciesFlags | = HAS_TAILLOW ;
2018-12-31 23:09:45 +01:00
break ;
}
}
RtcCalcLocalTime ( ) ;
}
2020-07-29 10:46:58 +02:00
// Task data for the roulette game tasks, starting with Task_StartPlaying
# define tMultiplier data[2]
# define tSelectionId data[4]
# define tWonBet data[5]
# define tBallNum data[6]
2020-08-03 23:31:34 +02:00
# define tTotalBallNum data[8] // Same as tBallNum but isn't cleared every 6 balls
2020-07-29 10:46:58 +02:00
# define tConsecutiveWins data[11]
# define tWinningSquare data[12]
# define tCoins data[13]
static void CB2_LoadRoulette ( void )
2018-12-31 23:09:45 +01:00
{
u8 taskId ;
switch ( gMain . state )
{
case 0 :
SetVBlankCallback ( NULL ) ;
ScanlineEffect_Stop ( ) ;
SetVBlankHBlankCallbacksToNull ( ) ;
ResetVramOamAndBgCntRegs ( ) ;
ResetAllBgsCoordinates ( ) ;
break ;
case 1 :
2020-07-29 10:46:58 +02:00
InitRouletteBgAndWindows ( ) ;
2018-12-31 23:09:45 +01:00
DeactivateAllTextPrinters ( ) ;
SetGpuReg ( REG_OFFSET_BLDCNT , BLDCNT_EFFECT_NONE |
BLDCNT_TGT2_BG2 |
BLDCNT_TGT2_BD ) ;
SetGpuReg ( REG_OFFSET_BLDALPHA , BLDALPHA_BLEND ( 10 , 6 ) ) ;
break ;
case 2 :
ResetPaletteFade ( ) ;
ResetSpriteData ( ) ;
ResetTasks ( ) ;
2020-05-14 10:37:09 +02:00
ResetTempTileDataBuffers ( ) ;
2018-12-31 23:09:45 +01:00
break ;
case 3 :
2020-07-31 20:55:42 +02:00
LoadPalette ( & sWheel_Pal , 0 , 0x1C0 ) ;
2020-07-29 10:46:58 +02:00
DecompressAndCopyTileDataToVram ( 1 , gRouletteMenu_Gfx , 0 , 0 , 0 ) ;
DecompressAndCopyTileDataToVram ( 2 , gRouletteWheel_Gfx , 0 , 0 , 0 ) ;
2018-12-31 23:09:45 +01:00
break ;
case 4 :
2020-05-14 10:37:09 +02:00
if ( FreeTempTileDataBuffersIfPossible ( ) )
2018-12-31 23:09:45 +01:00
return ;
2019-04-11 12:05:56 +02:00
2020-08-03 23:31:34 +02:00
InitRouletteTableData ( ) ;
2020-07-29 10:46:58 +02:00
CopyToBgTilemapBuffer ( 2 , sWheel_Tilemap , 0 , 0 ) ;
2018-12-31 23:09:45 +01:00
break ;
case 5 :
2020-07-29 10:46:58 +02:00
LoadOrFreeMiscSpritePalettesAndSheets ( FALSE ) ;
2020-08-03 23:31:34 +02:00
CreateWheelBallSprites ( ) ;
CreateWheelCenterSprite ( ) ;
2020-07-29 10:46:58 +02:00
CreateInterfaceSprites ( ) ;
CreateGridSprites ( ) ;
CreateGridBallSprites ( ) ;
2020-08-03 23:31:34 +02:00
CreateWheelIconSprites ( ) ;
2018-12-31 23:09:45 +01:00
break ;
case 6 :
AnimateSprites ( ) ;
BuildOamBuffer ( ) ;
2020-07-29 10:46:58 +02:00
SetCreditDigits ( GetCoins ( ) ) ;
SetBallCounterNumLeft ( BALLS_PER_ROUND ) ;
SetMultiplierSprite ( SELECTION_NONE ) ;
DrawGridBackground ( SELECTION_NONE ) ;
DrawStdWindowFrame ( sTextWindowId , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( sTextWindowId , FONT_NORMAL , Roulette_Text_ControlsInstruction , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2020-07-29 10:46:58 +02:00
CopyWindowToVram ( sTextWindowId , 3 ) ;
2019-01-01 02:39:41 +01:00
gSpriteCoordOffsetX = - 60 ;
gSpriteCoordOffsetY = 0 ;
2018-12-31 23:09:45 +01:00
break ;
case 7 :
SetGpuReg ( REG_OFFSET_DISPCNT , DISPCNT_MODE_0 |
DISPCNT_OBJ_1D_MAP |
DISPCNT_OBJ_ON ) ;
CopyBgTilemapBufferToVram ( 1 ) ;
CopyBgTilemapBufferToVram ( 2 ) ;
ShowBg ( 0 ) ;
ShowBg ( 1 ) ;
ShowBg ( 2 ) ;
break ;
case 8 :
EnableInterrupts ( INTR_FLAG_VBLANK ) ;
2020-07-29 10:46:58 +02:00
SetVBlankCallback ( VBlankCB_Roulette ) ;
2018-12-31 23:09:45 +01:00
BeginHardwarePaletteFade ( 0xFF , 0 , 16 , 0 , 1 ) ;
2020-07-31 20:55:42 +02:00
taskId = sRoulette - > playTaskId = CreateTask ( Task_StartPlaying , 0 ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . tBallNum = BALLS_PER_ROUND ;
gTasks [ taskId ] . tCoins = GetCoins ( ) ;
2019-02-22 22:03:35 +01:00
AlertTVThatPlayerPlayedRoulette ( GetCoins ( ) ) ;
2020-07-31 20:55:42 +02:00
sRoulette - > spinTaskId = CreateTask ( Task_SpinWheel , 1 ) ;
2020-07-29 10:46:58 +02:00
SetMainCallback2 ( CB2_Roulette ) ;
2018-12-31 23:09:45 +01:00
return ;
}
gMain . state + + ;
}
2020-07-31 20:55:42 +02:00
static void Task_SpinWheel ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
s16 sin ;
s16 cos ;
2020-07-31 20:55:42 +02:00
if ( sRoulette - > wheelDelayTimer + + = = sRoulette - > wheelDelay )
2018-12-31 23:09:45 +01:00
{
2020-07-31 20:55:42 +02:00
sRoulette - > wheelDelayTimer = 0 ;
if ( ( sRoulette - > wheelAngle - = sRoulette - > wheelSpeed ) < 0 )
sRoulette - > wheelAngle = 360 - sRoulette - > wheelSpeed ;
2018-12-31 23:09:45 +01:00
}
2020-07-31 20:55:42 +02:00
sin = Sin2 ( sRoulette - > wheelAngle ) ;
cos = Cos2 ( sRoulette - > wheelAngle ) ;
2018-12-31 23:09:45 +01:00
sin = sin / 16 ;
2020-07-31 20:55:42 +02:00
sRoulette - > wheelRotation . a = sRoulette - > wheelRotation . d = cos / 16 ;
sRoulette - > wheelRotation . b = sin ;
sRoulette - > wheelRotation . c = - sin ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_StartPlaying ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
if ( UpdatePaletteFade ( ) = = 0 )
{
SetGpuReg ( REG_OFFSET_BLDCNT , BLDCNT_EFFECT_NONE |
BLDCNT_TGT2_BG2 |
BLDCNT_TGT2_BD ) ;
SetGpuReg ( REG_OFFSET_BLDALPHA , BLDALPHA_BLEND ( 8 , 8 ) ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . tBallNum = 0 ;
2020-08-03 23:31:34 +02:00
ResetBallDataForNewSpin ( taskId ) ;
2020-07-29 10:46:58 +02:00
ResetHits ( ) ;
2020-08-03 23:31:34 +02:00
HideWheelBalls ( ) ;
2020-07-29 10:46:58 +02:00
DrawGridBackground ( SELECTION_NONE ) ;
SetBallCounterNumLeft ( BALLS_PER_ROUND ) ;
2020-08-03 23:31:34 +02:00
StartTaskAfterDelayOrInput ( taskId , Task_ContinuePlaying , NO_DELAY , A_BUTTON | B_BUTTON ) ;
2018-12-31 23:09:45 +01:00
}
}
2020-07-29 10:46:58 +02:00
static void Task_AskKeepPlaying ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2019-02-27 04:30:40 +01:00
DisplayYesNoMenuDefaultYes ( ) ;
2020-07-29 10:46:58 +02:00
DrawStdWindowFrame ( sTextWindowId , 0 ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( sTextWindowId , FONT_NORMAL , Roulette_Text_KeepPlaying , 0 , 1 , TEXT_SPEED_FF , 0 ) ;
2020-07-29 10:46:58 +02:00
CopyWindowToVram ( sTextWindowId , 3 ) ;
DoYesNoFuncWithChoice ( taskId , & sYesNoTable_KeepPlaying ) ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_ContinuePlaying ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2019-02-22 07:40:11 +01:00
ClearStdWindowAndFrame ( 0 , TRUE ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_SelectFirstEmptySquare ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_StopPlaying ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2020-07-31 20:55:42 +02:00
DestroyTask ( sRoulette - > spinTaskId ) ;
2020-07-29 10:46:58 +02:00
ExitRoulette ( taskId ) ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static void UpdateGridSelectionRect ( u8 selectionId )
2018-12-31 23:09:45 +01:00
{
u8 temp0 , temp1 ;
2020-07-29 10:46:58 +02:00
switch ( selectionId )
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
case SELECTION_NONE :
2021-11-01 23:06:15 +01:00
FillTilemapRect ( & sRoulette - > tilemapBuffers [ 0 ] [ 0 ] , 0 , 14 , 7 , 16 , 13 ) ;
2018-12-31 23:09:45 +01:00
break ;
2020-07-29 10:46:58 +02:00
case COL_WYNAUT :
case COL_AZURILL :
case COL_SKITTY :
case COL_MAKUHITA :
temp0 = ( selectionId * 3 + 14 ) ;
2021-11-01 23:06:15 +01:00
FillTilemapRect ( & sRoulette - > tilemapBuffers [ 0 ] [ 0 ] , 0 , 14 , 7 , 16 , 13 ) ;
2020-07-31 20:55:42 +02:00
SetTilemapRect ( & sRoulette - > tilemapBuffers [ 0 ] [ 0 ] , & sRoulette - > gridTilemap [ 281 ] , temp0 , 7 , 3 , 13 ) ;
2018-12-31 23:09:45 +01:00
break ;
2020-07-29 10:46:58 +02:00
case ROW_ORANGE :
case ROW_GREEN :
case ROW_PURPLE :
temp1 = ( ( selectionId - 1 ) / 5 * 3 + 10 ) ;
2021-11-01 23:06:15 +01:00
FillTilemapRect ( & sRoulette - > tilemapBuffers [ 0 ] [ 0 ] , 0 , 14 , 7 , 16 , 13 ) ;
2020-07-31 20:55:42 +02:00
SetTilemapRect ( & sRoulette - > tilemapBuffers [ 0 ] [ 0 ] , & sRoulette - > gridTilemap [ 320 ] , 14 , temp1 , 16 , 3 ) ;
2018-12-31 23:09:45 +01:00
break ;
2020-07-29 10:46:58 +02:00
// Individual square
2018-12-31 23:09:45 +01:00
default :
2020-07-29 10:46:58 +02:00
temp0 = GET_COL ( selectionId ) * 3 + 14 ;
temp1 = ( ( selectionId - 1 ) / 5 * 3 + 7 ) ;
2021-11-01 23:06:15 +01:00
FillTilemapRect ( & sRoulette - > tilemapBuffers [ 0 ] [ 0 ] , 0 , 14 , 7 , 16 , 13 ) ;
2020-07-31 20:55:42 +02:00
SetTilemapRect ( & sRoulette - > tilemapBuffers [ 0 ] [ 0 ] , & sRoulette - > gridTilemap [ 272 ] , temp0 , temp1 , 3 , 3 ) ;
2018-12-31 23:09:45 +01:00
break ;
}
}
2020-07-29 10:46:58 +02:00
static void UpdateGridSelection ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
SetMultiplierSprite ( gTasks [ taskId ] . tSelectionId ) ;
UpdateGridSelectionRect ( gTasks [ taskId ] . tSelectionId ) ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_StartHandleBetGridInput ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2020-07-31 20:55:42 +02:00
sRoulette - > selectionRectDrawState = SELECT_STATE_DRAW ;
2020-07-29 10:46:58 +02:00
UpdateGridSelectionRect ( gTasks [ taskId ] . tSelectionId ) ;
2020-07-31 20:55:42 +02:00
sRoulette - > wheelDelay = 2 ;
sRoulette - > wheelDelayTimer = 0 ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_HandleBetGridInput ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_SelectFirstEmptySquare ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
s16 i ;
2020-07-29 10:46:58 +02:00
if ( sRoulette - > hitFlags & F_ORANGE_ROW )
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
// If the whole orange row is filled, get first in green row
for ( i = SQU_GREEN_WYNAUT ; i < SQU_GREEN_MAKUHITA ; i + + )
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
if ( ! ( sRoulette - > hitFlags & sGridSelections [ i ] . flag ) )
2018-12-31 23:09:45 +01:00
break ;
}
}
else
{
2020-07-29 10:46:58 +02:00
// Otherwise get first in orange row
// With only 6 balls both rows can't be filled, no need to check purple row
for ( i = SQU_ORANGE_WYNAUT ; i < = SQU_ORANGE_MAKUHITA ; i + + ) // <= is accidental, but it will never get that far
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
if ( ! ( sRoulette - > hitFlags & sGridSelections [ i ] . flag ) )
2018-12-31 23:09:45 +01:00
break ;
}
}
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . tSelectionId = i ;
2020-08-03 23:31:34 +02:00
ResetBallDataForNewSpin ( taskId ) ;
2020-07-29 10:46:58 +02:00
DrawGridBackground ( gTasks [ taskId ] . tSelectionId ) ;
SetMultiplierSprite ( gTasks [ taskId ] . tSelectionId ) ;
FlashSelectionOnWheel ( gTasks [ taskId ] . tSelectionId ) ;
2018-12-31 23:09:45 +01:00
gTasks [ taskId ] . data [ 1 ] = 0 ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_StartHandleBetGridInput ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static bool8 CanMoveSelectionInDir ( s16 * selectionId , u8 dir )
2018-12-31 23:09:45 +01:00
{
s8 temp1 = 0 ;
s8 temp = 0 ;
2020-07-29 10:46:58 +02:00
s8 moveOffsets [ 4 ] = { - 5 , 5 , - 1 , 1 } ;
s8 originalSelection = * selectionId ;
2018-12-31 23:09:45 +01:00
2020-07-29 10:46:58 +02:00
switch ( dir )
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
case 0 : // UP
case 1 : // DOWN
temp1 = GET_COL ( * selectionId ) ;
temp = temp1 + ROW_PURPLE ;
if ( temp1 = = SELECTION_NONE )
2018-12-31 23:09:45 +01:00
temp1 = 5 ;
break ;
2020-07-29 10:46:58 +02:00
case 2 : // LEFT
case 3 : // RIGHT
temp1 = GET_ROW ( * selectionId ) ;
temp = temp1 + COL_MAKUHITA ;
if ( temp1 = = SELECTION_NONE )
2018-12-31 23:09:45 +01:00
temp1 = 1 ;
break ;
}
2020-07-29 10:46:58 +02:00
* selectionId + = moveOffsets [ dir ] ;
2018-12-31 23:09:45 +01:00
2020-07-29 10:46:58 +02:00
if ( * selectionId < temp1 )
* selectionId = temp ;
2018-12-31 23:09:45 +01:00
2020-07-29 10:46:58 +02:00
if ( * selectionId > temp )
* selectionId = temp1 ;
2018-12-31 23:09:45 +01:00
2020-07-29 10:46:58 +02:00
if ( * selectionId ! = originalSelection )
2018-12-31 23:09:45 +01:00
return TRUE ;
return FALSE ;
}
2020-07-29 10:46:58 +02:00
static void ProcessBetGridInput ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2020-07-31 20:55:42 +02:00
u8 headerOffset = 0 ;
2020-07-29 10:46:58 +02:00
bool8 dirPressed = FALSE ;
2020-07-31 20:55:42 +02:00
if ( ( ! ( JOY_NEW ( DPAD_UP ) ) | | ( ( dirPressed = TRUE ) & & CanMoveSelectionInDir ( & gTasks [ taskId ] . tSelectionId , 0 ) ) )
& & ( ! ( JOY_NEW ( DPAD_DOWN ) ) | | ( ( dirPressed = TRUE ) & & CanMoveSelectionInDir ( & gTasks [ taskId ] . tSelectionId , 1 ) ) )
& & ( ! ( JOY_NEW ( DPAD_LEFT ) ) | | ( ( dirPressed = TRUE ) & & CanMoveSelectionInDir ( & gTasks [ taskId ] . tSelectionId , 2 ) ) )
& & ( ! ( JOY_NEW ( DPAD_RIGHT ) ) | | ( ( dirPressed = TRUE ) & & CanMoveSelectionInDir ( & gTasks [ taskId ] . tSelectionId , 3 ) ) )
2020-07-29 10:46:58 +02:00
& & ( dirPressed ) )
{
u8 i ;
DrawGridBackground ( gTasks [ taskId ] . tSelectionId ) ;
UpdateGridSelection ( taskId ) ;
2020-07-31 20:55:42 +02:00
gTasks [ taskId ] . data [ 1 ] = 0 ;
2020-07-29 10:46:58 +02:00
PlaySE ( SE_SELECT ) ;
2020-08-05 01:19:36 +02:00
RouletteFlash_Stop ( & sRoulette - > flashUtil , 0xFFFF ) ;
sRoulette - > flashUtil . palettes [ FLASH_ICON ] . available = sRoulette - > flashUtil . palettes [ FLASH_ICON_2 ] . available = sRoulette - > flashUtil . palettes [ FLASH_ICON_3 ] . available = FALSE ;
2020-07-29 10:46:58 +02:00
FlashSelectionOnWheel ( gTasks [ taskId ] . tSelectionId ) ;
2021-08-25 00:59:32 +02:00
2020-07-31 20:55:42 +02:00
// Switch all the poke (column) headers to gray outlines
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < NUM_BOARD_POKES ; i + + )
{
2020-07-31 20:55:42 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_POKE_HEADERS ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ i + SPR_POKE_HEADERS ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ i + SPR_POKE_HEADERS ] ] . anims ) - > type ;
2020-07-29 10:46:58 +02:00
}
2020-07-31 20:55:42 +02:00
// If the current selection is a column with at least 1 unhit space, fill in the header
2020-08-03 23:31:34 +02:00
if ( ( u16 ) ( gTasks [ taskId ] . tSelectionId - 1 ) < COL_MAKUHITA & & ! ( sRoulette - > hitFlags & sGridSelections [ gTasks [ taskId ] . tSelectionId ] . flag ) )
2020-07-29 10:46:58 +02:00
{
2020-07-31 20:55:42 +02:00
headerOffset = gTasks [ taskId ] . tSelectionId - 1 ;
gSprites [ sRoulette - > spriteIds [ headerOffset + SPR_POKE_HEADERS ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ headerOffset + SPR_POKE_HEADERS ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ headerOffset + SPR_POKE_HEADERS ] ] . anims + 1 ) - > type ;
2020-07-29 10:46:58 +02:00
}
}
2018-12-31 23:09:45 +01:00
}
2020-08-03 23:31:34 +02:00
static void Task_StartSpin ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2019-10-20 08:31:51 +02:00
IncrementDailyRouletteUses ( ) ;
2020-07-31 20:55:42 +02:00
sRoulette - > selectionRectDrawState = SELECT_STATE_ERASE ;
2020-07-29 10:46:58 +02:00
if ( sRoulette - > minBet = = 1 )
2020-07-31 20:55:42 +02:00
sRoulette - > wheelDelay = 1 ;
2018-12-31 23:09:45 +01:00
else
2020-07-31 20:55:42 +02:00
sRoulette - > wheelDelay = 0 ;
sRoulette - > wheelDelayTimer = 0 ;
gTasks [ taskId ] . data [ 1 ] = 32 ;
gTasks [ taskId ] . func = Task_SlideGridOffscreen ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_PlaceBet ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
sRoulette - > betSelection [ sRoulette - > curBallNum ] = gTasks [ taskId ] . tSelectionId ;
gTasks [ taskId ] . tMultiplier = GetMultiplier ( sRoulette - > betSelection [ sRoulette - > curBallNum ] ) ;
SetMultiplierSprite ( sRoulette - > betSelection [ sRoulette - > curBallNum ] ) ;
if ( ( gTasks [ taskId ] . tCoins - = sRoulette - > minBet ) < 0 )
gTasks [ taskId ] . tCoins = 0 ;
SetCreditDigits ( gTasks [ taskId ] . tCoins ) ;
2020-08-03 23:31:34 +02:00
gTasks [ taskId ] . func = Task_StartSpin ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_HandleBetGridInput ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
ProcessBetGridInput ( taskId ) ;
2018-12-31 23:09:45 +01:00
2020-07-29 10:46:58 +02:00
// Flash selection rect
2019-01-01 01:07:29 +01:00
switch ( gTasks [ taskId ] . data [ 1 ] )
2018-12-31 23:09:45 +01:00
{
case 0 :
2020-07-29 10:46:58 +02:00
UpdateGridSelectionRect ( gTasks [ taskId ] . tSelectionId ) ;
2019-01-02 23:55:50 +01:00
gTasks [ taskId ] . data [ 1 ] + + ;
2018-12-31 23:09:45 +01:00
break ;
case 30 :
2020-07-29 10:46:58 +02:00
UpdateGridSelectionRect ( SELECTION_NONE ) ;
2019-01-02 23:55:50 +01:00
gTasks [ taskId ] . data [ 1 ] + + ;
2018-12-31 23:09:45 +01:00
break ;
case 59 :
2019-01-01 01:07:29 +01:00
gTasks [ taskId ] . data [ 1 ] = 0 ;
2018-12-31 23:09:45 +01:00
break ;
default :
2019-01-01 01:07:29 +01:00
gTasks [ taskId ] . data [ 1 ] + + ;
2018-12-31 23:09:45 +01:00
}
2020-07-29 10:46:58 +02:00
if ( JOY_NEW ( A_BUTTON ) )
2018-12-31 23:09:45 +01:00
{
2020-08-10 23:09:17 +02:00
if ( sRoulette - > hitFlags & sGridSelections [ gTasks [ taskId ] . tSelectionId ] . flag )
2020-07-29 10:46:58 +02:00
{
// Ball has already landed on this space
2018-12-31 23:09:45 +01:00
PlaySE ( SE_BOO ) ;
2020-07-29 10:46:58 +02:00
}
2018-12-31 23:09:45 +01:00
else
{
2020-08-21 00:02:00 +02:00
m4aSongNumStart ( SE_SHOP ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_PlaceBet ;
2018-12-31 23:09:45 +01:00
}
}
}
2020-07-29 10:46:58 +02:00
static void Task_SlideGridOffscreen ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2019-01-01 01:07:29 +01:00
if ( gTasks [ taskId ] . data [ 1 ] - - > 0 )
2018-12-31 23:09:45 +01:00
{
2020-08-03 23:31:34 +02:00
// Slide wheel over
2019-01-01 01:07:29 +01:00
if ( gTasks [ taskId ] . data [ 1 ] > 2 )
gSpriteCoordOffsetX + = 2 ;
2020-08-03 23:31:34 +02:00
// Slide grid over
2020-07-31 20:55:42 +02:00
if ( ( sRoulette - > gridX + = 4 ) = = 104 )
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_MULTIPLIER ] ] . callback = & SpriteCallbackDummy ;
2018-12-31 23:09:45 +01:00
}
else
{
2020-07-29 10:46:58 +02:00
ShowHideGridIcons ( TRUE , - 1 ) ;
ShowHideGridBalls ( TRUE , - 1 ) ;
2020-07-31 20:55:42 +02:00
gTasks [ taskId ] . func = Task_InitBallRoll ;
2019-01-01 01:07:29 +01:00
gTasks [ taskId ] . data [ 1 ] = 0 ;
2018-12-31 23:09:45 +01:00
}
}
2020-08-03 23:31:34 +02:00
// Each table has a set base distance used to determine how far the ball will travel
// Each roll a random value is generated to add onto this distance
// Half the value returned by this function is the max distance that can be added on per roll
// i.e. the lower this value is, the closer the roll will be to a consistent distance
// Odds of a lower value increase as play continues, if the player has Shroomish and/or Taillow in the party, and dependent on the time
static u8 GetRandomForBallTravelDistance ( u16 ballNum , u16 rand )
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
switch ( sRoulette - > partySpeciesFlags )
2018-12-31 23:09:45 +01:00
{
2020-07-29 10:46:58 +02:00
case HAS_SHROOMISH :
case HAS_TAILLOW :
2018-12-31 23:09:45 +01:00
// one of the two is in party
if ( gLocalTime . hours > 3 & & gLocalTime . hours < 10 )
{
2020-08-03 23:31:34 +02:00
if ( ballNum < BALLS_PER_ROUND * 2 | | ( rand & 1 ) )
return sRouletteTables [ sRoulette - > tableId ] . randDistanceLow / 2 ;
2018-12-31 23:09:45 +01:00
else
2019-01-02 23:55:50 +01:00
return 1 ;
2018-12-31 23:09:45 +01:00
}
2021-08-25 00:59:32 +02:00
else if ( ! ( rand & 3 ) )
2018-12-31 23:09:45 +01:00
{
2020-08-03 23:31:34 +02:00
return sRouletteTables [ sRoulette - > tableId ] . randDistanceLow / 2 ;
2018-12-31 23:09:45 +01:00
}
2021-08-25 00:59:32 +02:00
else
2018-12-31 23:09:45 +01:00
{
2020-08-03 23:31:34 +02:00
return sRouletteTables [ sRoulette - > tableId ] . randDistanceLow ;
2018-12-31 23:09:45 +01:00
}
break ;
2020-07-29 10:46:58 +02:00
case HAS_SHROOMISH | HAS_TAILLOW :
2018-12-31 23:09:45 +01:00
// both are in party
if ( gLocalTime . hours > 3 & & gLocalTime . hours < 11 )
{
2020-08-03 23:31:34 +02:00
if ( ballNum < BALLS_PER_ROUND | | ( rand & 1 ) )
return sRouletteTables [ sRoulette - > tableId ] . randDistanceLow / 2 ;
2018-12-31 23:09:45 +01:00
else
2019-01-02 23:55:50 +01:00
return 1 ;
2018-12-31 23:09:45 +01:00
}
2021-08-25 00:59:32 +02:00
else if ( ( rand & 1 ) & & ballNum > BALLS_PER_ROUND )
2018-12-31 23:09:45 +01:00
{
2020-08-03 23:31:34 +02:00
return sRouletteTables [ sRoulette - > tableId ] . randDistanceLow / 4 ;
2018-12-31 23:09:45 +01:00
}
2021-08-25 00:59:32 +02:00
else
2018-12-31 23:09:45 +01:00
{
2020-08-03 23:31:34 +02:00
return sRouletteTables [ sRoulette - > tableId ] . randDistanceLow / 2 ;
2018-12-31 23:09:45 +01:00
}
break ;
case 0 :
default :
// neither is in party
if ( gLocalTime . hours > 3 & & gLocalTime . hours < 10 )
{
2020-08-03 23:31:34 +02:00
if ( ! ( rand & 3 ) )
2019-01-02 23:55:50 +01:00
return 1 ;
2018-12-31 23:09:45 +01:00
else
2020-08-03 23:31:34 +02:00
return sRouletteTables [ sRoulette - > tableId ] . randDistanceLow / 2 ;
2018-12-31 23:09:45 +01:00
}
2020-08-03 23:31:34 +02:00
else if ( ! ( rand & 3 ) )
2018-12-31 23:09:45 +01:00
{
2020-08-03 23:31:34 +02:00
if ( ballNum > BALLS_PER_ROUND * 2 )
return sRouletteTables [ sRoulette - > tableId ] . randDistanceLow / 2 ;
2018-12-31 23:09:45 +01:00
else
2020-08-03 23:31:34 +02:00
return sRouletteTables [ sRoulette - > tableId ] . randDistanceLow ;
2018-12-31 23:09:45 +01:00
}
2020-08-03 23:31:34 +02:00
else if ( rand & ( 1 < < 15 ) )
2018-12-31 23:09:45 +01:00
{
2020-08-03 23:31:34 +02:00
if ( ballNum > BALLS_PER_ROUND * 2 )
return sRouletteTables [ sRoulette - > tableId ] . randDistanceLow ;
2018-12-31 23:09:45 +01:00
else
2020-08-03 23:31:34 +02:00
return sRouletteTables [ sRoulette - > tableId ] . randDistanceHigh ;
2018-12-31 23:09:45 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
return sRouletteTables [ sRoulette - > tableId ] . randDistanceHigh * 2 ;
2018-12-31 23:09:45 +01:00
}
break ;
}
}
2020-07-31 20:55:42 +02:00
static void Task_InitBallRoll ( u8 taskId )
2018-12-31 23:09:45 +01:00
{
2020-08-03 23:31:34 +02:00
u8 randTravelMod ;
s8 randTravelDist ;
s8 startAngleId ;
u16 travelDist = 0 ;
2018-12-31 23:09:45 +01:00
u16 rand ;
u16 randmod ;
2020-08-03 23:31:34 +02:00
u16 startAngles [ 4 ] = { 0 , 180 , 90 , 270 } ; // possible angles to start ball from
2018-12-31 23:09:45 +01:00
rand = Random ( ) ;
randmod = rand % 100 ;
2020-07-31 20:55:42 +02:00
sRoulette - > curBallSpriteId = gTasks [ taskId ] . tBallNum ;
2020-08-03 23:31:34 +02:00
// BALL_STATE_ROLLING set below
sRoulette - > ballState = sRoulette - > hitSlot = sRoulette - > stuckHitSlot = 0 ;
randTravelMod = GetRandomForBallTravelDistance ( gTasks [ taskId ] . tTotalBallNum , rand ) ;
randTravelDist = ( rand % randTravelMod ) - ( randTravelMod / 2 ) ;
2018-12-31 23:09:45 +01:00
if ( gLocalTime . hours < 13 )
2020-08-03 23:31:34 +02:00
startAngleId = 0 ;
2018-12-31 23:09:45 +01:00
else
2020-08-03 23:31:34 +02:00
startAngleId = 1 ;
2018-12-31 23:09:45 +01:00
if ( randmod < 80 )
2020-08-03 23:31:34 +02:00
startAngleId * = 2 ;
2018-12-31 23:09:45 +01:00
else
2020-08-03 23:31:34 +02:00
startAngleId = ( 1 - startAngleId ) * 2 ;
2018-12-31 23:09:45 +01:00
2020-08-03 23:31:34 +02:00
sRoulette - > ballTravelDist = travelDist = sRouletteTables [ sRoulette - > tableId ] . baseTravelDist + randTravelDist ;
2018-12-31 23:09:45 +01:00
2020-08-03 23:31:34 +02:00
travelDist = S16TOPOSFLOAT ( travelDist ) / 5.0f ;
sRoulette - > ballTravelDistFast = travelDist * 3 ;
sRoulette - > ballTravelDistSlow = sRoulette - > ballTravelDistMed = travelDist ;
2020-07-29 10:46:58 +02:00
2020-08-03 23:31:34 +02:00
sRoulette - > ballAngle = S16TOPOSFLOAT ( startAngles [ ( rand & 1 ) + startAngleId ] ) ;
sRoulette - > ballAngleSpeed = S16TOPOSFLOAT ( sRouletteTables [ sRoulette - > tableId ] . ballSpeed ) ;
sRoulette - > ballAngleAccel = ( ( sRoulette - > ballAngleSpeed * 0.5f ) - sRoulette - > ballAngleSpeed ) / S16TOPOSFLOAT ( sRoulette - > ballTravelDistFast ) ;
sRoulette - > ballDistToCenter = 68.0f ;
sRoulette - > ballFallAccel = 0.0f ;
sRoulette - > ballFallSpeed = - ( 8.0f / S16TOPOSFLOAT ( sRoulette - > ballTravelDistFast ) ) ;
2020-07-29 10:46:58 +02:00
sRoulette - > varA0 = 36.0f ;
2020-07-31 20:55:42 +02:00
gTasks [ taskId ] . func = Task_RollBall ;
2018-12-31 23:09:45 +01:00
}
2019-01-01 01:07:29 +01:00
2020-07-31 20:55:42 +02:00
static void Task_RollBall ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
sRoulette - > ballRolling = TRUE ;
2020-08-03 23:31:34 +02:00
sRoulette - > ball = & gSprites [ sRoulette - > spriteIds [ sRoulette - > curBallSpriteId ] ] ;
sRoulette - > ball - > callback = SpriteCB_RollBall_Start ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . tBallNum + + ;
2020-08-03 23:31:34 +02:00
gTasks [ taskId ] . tTotalBallNum + + ;
2020-07-29 10:46:58 +02:00
SetBallCounterNumLeft ( BALLS_PER_ROUND - gTasks [ taskId ] . tBallNum ) ;
2020-08-21 00:02:00 +02:00
m4aSongNumStart ( SE_ROULETTE_BALL ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_RecordBallHit ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_RecordBallHit ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
// Wait for ball to finish rolling
if ( sRoulette - > ballState ! = BALL_STATE_ROLLING )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
// If the ball got stuck, wait for it to be unstuck
if ( sRoulette - > ballStuck )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
if ( sRoulette - > ballUnstuck )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
sRoulette - > ballUnstuck = FALSE ;
sRoulette - > ballStuck = FALSE ;
2019-01-01 01:07:29 +01:00
}
}
else
{
2020-07-31 20:55:42 +02:00
if ( gTasks [ taskId ] . data [ 1 ] = = 0 )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
bool8 won = IsHitInBetSelection ( RecordHit ( taskId , sRoulette - > hitSlot ) , sRoulette - > betSelection [ sRoulette - > curBallNum ] ) ;
gTasks [ taskId ] . tWonBet = won ;
if ( won = = TRUE )
2020-08-05 01:19:36 +02:00
RouletteFlash_Enable ( & sRoulette - > flashUtil , F_FLASH_OUTER_EDGES ) ;
2019-01-01 01:07:29 +01:00
}
if ( gTasks [ taskId ] . data [ 1 ] < = 60 )
{
2020-07-29 10:46:58 +02:00
if ( JOY_NEW ( A_BUTTON ) )
2019-01-01 01:07:29 +01:00
gTasks [ taskId ] . data [ 1 ] = 60 ;
gTasks [ taskId ] . data [ 1 ] + + ;
}
else
{
2020-07-29 10:46:58 +02:00
DrawGridBackground ( sRoulette - > betSelection [ sRoulette - > curBallNum ] ) ;
ShowHideGridIcons ( FALSE , gTasks [ taskId ] . tWinningSquare ) ;
ShowHideGridBalls ( FALSE , gTasks [ taskId ] . tBallNum - 1 ) ;
2019-01-01 01:07:29 +01:00
gTasks [ taskId ] . data [ 1 ] = 32 ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_SlideGridOnscreen ;
2019-01-01 01:07:29 +01:00
}
}
}
}
2020-07-29 10:46:58 +02:00
static void Task_SlideGridOnscreen ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
if ( gTasks [ taskId ] . data [ 1 ] - - > 0 )
{
2020-08-03 23:31:34 +02:00
// Slide wheel over
2019-01-01 01:07:29 +01:00
if ( gTasks [ taskId ] . data [ 1 ] > 2 )
gSpriteCoordOffsetX - = 2 ;
2020-08-03 23:31:34 +02:00
// Slide grid over
2020-07-31 20:55:42 +02:00
if ( ( sRoulette - > gridX - = 4 ) = = 104 )
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_MULTIPLIER ] ] . callback = SpriteCB_GridSquare ;
2019-01-01 01:07:29 +01:00
}
else
{
2020-07-29 10:46:58 +02:00
ShowHideWinSlotCursor ( gTasks [ taskId ] . tWinningSquare ) ;
if ( gTasks [ taskId ] . tWonBet = = TRUE )
2019-01-01 01:07:29 +01:00
gTasks [ taskId ] . data [ 1 ] = 121 ;
else
gTasks [ taskId ] . data [ 1 ] = 61 ;
2020-07-31 20:55:42 +02:00
gTasks [ taskId ] . func = Task_FlashBallOnWinningSquare ;
2019-01-01 01:07:29 +01:00
}
}
2020-07-31 20:55:42 +02:00
static void Task_FlashBallOnWinningSquare ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
if ( gTasks [ taskId ] . data [ 1 ] - - > 1 )
{
switch ( gTasks [ taskId ] . data [ 1 ] % 16 )
{
case 8 :
2020-07-31 20:55:42 +02:00
// Winning square uncovered
2020-07-29 10:46:58 +02:00
ShowHideGridIcons ( FALSE , - 1 ) ;
ShowHideGridBalls ( FALSE , - 1 ) ;
2019-01-01 01:07:29 +01:00
break ;
case 0 :
2020-07-31 20:55:42 +02:00
// Winning square occluded by ball
2020-07-29 10:46:58 +02:00
ShowHideGridIcons ( FALSE , gTasks [ taskId ] . tWinningSquare ) ;
ShowHideGridBalls ( FALSE , gTasks [ taskId ] . tBallNum - 1 ) ;
2019-01-01 01:07:29 +01:00
break ;
}
}
else
{
2020-07-29 10:46:58 +02:00
StartTaskAfterDelayOrInput ( taskId , Task_PrintSpinResult , 30 , 0 ) ;
2019-01-01 01:07:29 +01:00
}
}
2020-07-29 10:46:58 +02:00
static void Task_TryIncrementWins ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
switch ( gTasks [ taskId ] . tWonBet )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
case TRUE :
case 2 : // never happens
2019-01-01 01:07:29 +01:00
if ( IsFanfareTaskInactive ( ) )
{
u32 wins = GetGameStat ( GAME_STAT_CONSECUTIVE_ROULETTE_WINS ) ;
2020-07-29 10:46:58 +02:00
if ( wins < + + gTasks [ taskId ] . tConsecutiveWins )
SetGameStat ( GAME_STAT_CONSECUTIVE_ROULETTE_WINS , gTasks [ taskId ] . tConsecutiveWins ) ;
2020-08-03 23:31:34 +02:00
StartTaskAfterDelayOrInput ( taskId , Task_PrintPayout , NO_DELAY , A_BUTTON | B_BUTTON ) ;
2019-01-01 01:07:29 +01:00
}
break ;
2020-07-29 10:46:58 +02:00
case FALSE :
2019-01-01 01:07:29 +01:00
default :
if ( ! IsSEPlaying ( ) )
{
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . tConsecutiveWins = 0 ;
2020-08-03 23:31:34 +02:00
StartTaskAfterDelayOrInput ( taskId , Task_EndTurn , NO_DELAY , A_BUTTON | B_BUTTON ) ;
2019-01-01 01:07:29 +01:00
}
break ;
}
}
2020-07-29 10:46:58 +02:00
static void Task_PrintSpinResult ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
switch ( gTasks [ taskId ] . tWonBet )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
case TRUE :
case 2 : // never happens
if ( gTasks [ taskId ] . tMultiplier = = MAX_MULTIPLIER )
2019-01-01 01:07:29 +01:00
{
2020-08-21 00:02:00 +02:00
PlayFanfare ( MUS_SLOTS_JACKPOT ) ;
2020-07-29 10:46:58 +02:00
DrawStdWindowFrame ( sTextWindowId , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( sTextWindowId , FONT_NORMAL , Roulette_Text_Jackpot , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2020-07-29 10:46:58 +02:00
CopyWindowToVram ( sTextWindowId , 3 ) ;
2019-01-01 01:07:29 +01:00
}
else
{
2020-08-21 00:02:00 +02:00
PlayFanfare ( MUS_SLOTS_WIN ) ;
2020-07-29 10:46:58 +02:00
DrawStdWindowFrame ( sTextWindowId , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( sTextWindowId , FONT_NORMAL , Roulette_Text_ItsAHit , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2020-07-29 10:46:58 +02:00
CopyWindowToVram ( sTextWindowId , 3 ) ;
2019-01-01 01:07:29 +01:00
}
break ;
2020-07-29 10:46:58 +02:00
case FALSE :
2019-01-01 01:07:29 +01:00
default :
2020-08-21 00:02:00 +02:00
m4aSongNumStart ( SE_FAILURE ) ;
2020-07-29 10:46:58 +02:00
DrawStdWindowFrame ( sTextWindowId , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( sTextWindowId , FONT_NORMAL , Roulette_Text_NothingDoing , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2020-07-29 10:46:58 +02:00
CopyWindowToVram ( sTextWindowId , 3 ) ;
2019-01-01 01:07:29 +01:00
break ;
}
gTasks [ taskId ] . data [ 1 ] = 0 ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_TryIncrementWins ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
# define tPayout data[1]
static void Task_GivePayout ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
switch ( gTasks [ taskId ] . data [ 7 ] )
2019-01-01 01:07:29 +01:00
{
case 0 :
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . tCoins + + ;
2019-01-01 01:07:29 +01:00
m4aSongNumStart ( SE_PIN ) ;
2020-07-29 10:46:58 +02:00
SetCreditDigits ( gTasks [ taskId ] . tCoins ) ;
if ( gTasks [ taskId ] . tCoins > = MAX_COINS )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . tPayout = 0 ;
2019-01-01 01:07:29 +01:00
}
else
{
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . tPayout - - ;
2019-01-01 01:07:29 +01:00
gTasks [ taskId ] . data [ 7 ] + + ;
}
break ;
case 3 :
m4aSongNumStop ( SE_PIN ) ;
gTasks [ taskId ] . data [ 7 ] = 0 ;
break ;
default :
gTasks [ taskId ] . data [ 7 ] + + ;
break ;
}
2020-07-29 10:46:58 +02:00
if ( gTasks [ taskId ] . tPayout = = 0 )
2020-08-03 23:31:34 +02:00
StartTaskAfterDelayOrInput ( taskId , Task_EndTurn , NO_DELAY , A_BUTTON | B_BUTTON ) ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_PrintPayout ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
ConvertIntToDecimalStringN ( gStringVar1 , ( sRoulette - > minBet * gTasks [ taskId ] . tMultiplier ) , STR_CONV_MODE_LEFT_ALIGN , 2 ) ;
2019-10-07 08:00:16 +02:00
StringExpandPlaceholders ( gStringVar4 , Roulette_Text_YouveWonXCoins ) ;
2020-07-29 10:46:58 +02:00
DrawStdWindowFrame ( sTextWindowId , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( sTextWindowId , FONT_NORMAL , gStringVar4 , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2020-07-29 10:46:58 +02:00
CopyWindowToVram ( sTextWindowId , 3 ) ;
gTasks [ taskId ] . tPayout = ( sRoulette - > minBet * gTasks [ taskId ] . tMultiplier ) ;
2019-01-01 01:07:29 +01:00
gTasks [ taskId ] . data [ 7 ] = 0 ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_GivePayout ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
# undef tPayout
static void Task_EndTurn ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
2020-08-05 01:19:36 +02:00
RouletteFlash_Stop ( & sRoulette - > flashUtil , 0xFFFF ) ;
sRoulette - > flashUtil . palettes [ FLASH_ICON ] . available = sRoulette - > flashUtil . palettes [ FLASH_ICON_2 ] . available = sRoulette - > flashUtil . palettes [ FLASH_ICON_3 ] . available = FALSE ;
2020-08-03 23:31:34 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_WHEEL_ICONS + sGridSelections [ gTasks [ taskId ] . tWinningSquare ] . spriteIdOffset ] ] . invisible = TRUE ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_TryPrintEndTurnMsg ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_TryPrintEndTurnMsg ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
u8 i = 0 ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . tSelectionId = i ;
sRoulette - > betSelection [ sRoulette - > curBallNum ] = SELECTION_NONE ;
DrawGridBackground ( SELECTION_NONE ) ;
gSprites [ sRoulette - > spriteIds [ SPR_WIN_SLOT_CURSOR ] ] . invisible = TRUE ;
for ( i = 0 ; i < NUM_BOARD_POKES ; i + + )
{
2020-07-31 20:55:42 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_POKE_HEADERS ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ i + SPR_POKE_HEADERS ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ i + SPR_POKE_HEADERS ] ] . anims ) - > type ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
if ( gTasks [ taskId ] . tCoins > = sRoulette - > minBet )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
if ( gTasks [ taskId ] . tBallNum = = BALLS_PER_ROUND )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
// Reached Ball 6, clear board
DrawStdWindowFrame ( sTextWindowId , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( sTextWindowId , FONT_NORMAL , Roulette_Text_BoardWillBeCleared , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2020-07-29 10:46:58 +02:00
CopyWindowToVram ( sTextWindowId , 3 ) ;
2020-08-03 23:31:34 +02:00
StartTaskAfterDelayOrInput ( taskId , Task_ClearBoard , NO_DELAY , A_BUTTON | B_BUTTON ) ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
else if ( gTasks [ taskId ] . tCoins = = MAX_COINS )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
// Player maxed out coins
DrawStdWindowFrame ( sTextWindowId , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( sTextWindowId , FONT_NORMAL , Roulette_Text_CoinCaseIsFull , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2020-07-29 10:46:58 +02:00
CopyWindowToVram ( sTextWindowId , 3 ) ;
2020-08-03 23:31:34 +02:00
StartTaskAfterDelayOrInput ( taskId , Task_AskKeepPlaying , NO_DELAY , A_BUTTON | B_BUTTON ) ;
2019-01-01 01:07:29 +01:00
}
else
{
2020-07-29 10:46:58 +02:00
// No special msg, ask to continue
gTasks [ taskId ] . func = Task_AskKeepPlaying ;
2019-01-01 01:07:29 +01:00
}
}
else
{
2020-07-29 10:46:58 +02:00
// Player out of coins
DrawStdWindowFrame ( sTextWindowId , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( sTextWindowId , FONT_NORMAL , Roulette_Text_NoCoinsLeft , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2020-07-29 10:46:58 +02:00
CopyWindowToVram ( sTextWindowId , 3 ) ;
StartTaskAfterDelayOrInput ( taskId , Task_StopPlaying , 60 , A_BUTTON | B_BUTTON ) ;
2019-01-01 01:07:29 +01:00
}
}
2020-07-29 10:46:58 +02:00
static void Task_ClearBoard ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
u8 i = 0 ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . tBallNum = 0 ;
2020-08-03 23:31:34 +02:00
ResetBallDataForNewSpin ( taskId ) ;
2020-07-29 10:46:58 +02:00
ResetHits ( ) ;
2020-08-03 23:31:34 +02:00
HideWheelBalls ( ) ;
2020-07-29 10:46:58 +02:00
DrawGridBackground ( SELECTION_NONE ) ;
SetBallCounterNumLeft ( BALLS_PER_ROUND ) ;
2019-01-01 01:07:29 +01:00
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < NUM_ROULETTE_SLOTS ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-08-03 23:31:34 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_WHEEL_ICONS ] ] . invisible = FALSE ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
if ( gTasks [ taskId ] . tCoins = = MAX_COINS )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
DrawStdWindowFrame ( sTextWindowId , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( sTextWindowId , FONT_NORMAL , Roulette_Text_CoinCaseIsFull , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2020-07-29 10:46:58 +02:00
CopyWindowToVram ( sTextWindowId , 3 ) ;
2020-08-03 23:31:34 +02:00
StartTaskAfterDelayOrInput ( taskId , Task_AskKeepPlaying , NO_DELAY , A_BUTTON | B_BUTTON ) ;
2019-01-01 01:07:29 +01:00
}
else
{
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_AskKeepPlaying ;
2019-01-01 01:07:29 +01:00
}
}
2020-07-29 10:46:58 +02:00
static void ExitRoulette ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
2020-08-05 01:19:36 +02:00
RouletteFlash_Stop ( & sRoulette - > flashUtil , 0xFFFF ) ;
RouletteFlash_Reset ( & sRoulette - > flashUtil ) ;
2020-07-29 10:46:58 +02:00
SetCoins ( gTasks [ taskId ] . tCoins ) ;
if ( GetCoins ( ) < sRoulette - > minBet )
2019-01-01 01:07:29 +01:00
gSpecialVar_0x8004 = TRUE ;
else
gSpecialVar_0x8004 = FALSE ;
2021-04-25 23:22:45 +02:00
TryPutFindThatGamerOnAir ( GetCoins ( ) ) ;
2019-01-01 01:07:29 +01:00
BeginHardwarePaletteFade ( 0xFF , 0 , 0 , 16 , 0 ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_ExitRoulette ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_ExitRoulette ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
if ( UpdatePaletteFade ( ) = = 0 )
{
SetVBlankCallback ( NULL ) ;
gSpriteCoordOffsetX = gSpriteCoordOffsetY = 0 ;
ResetVramOamAndBgCntRegs ( ) ;
ResetAllBgsCoordinates ( ) ;
SetGpuReg ( REG_OFFSET_BLDCNT , 0 ) ;
SetGpuReg ( REG_OFFSET_BLDALPHA , 0 ) ;
SetGpuReg ( REG_OFFSET_BLDY , 0 ) ;
FreeAllSpritePalettes ( ) ;
ResetPaletteFade ( ) ;
ResetSpriteData ( ) ;
2020-07-29 10:46:58 +02:00
FreeRoulette ( ) ;
2019-12-17 09:24:44 +01:00
gFieldCallback = FieldCB_ContinueScriptHandleMusic ;
2019-01-01 01:07:29 +01:00
SetMainCallback2 ( CB2_ReturnToField ) ;
DestroyTask ( taskId ) ;
}
}
2020-07-29 10:46:58 +02:00
static void Task_WaitForNextTask ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
if ( sRoulette - > taskWaitDelay = = 0 | | JOY_NEW ( sRoulette - > taskWaitKey ) )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = sRoulette - > nextTask ;
if ( sRoulette - > taskWaitKey > 0 )
2019-01-01 01:07:29 +01:00
PlaySE ( SE_SELECT ) ;
2020-07-29 10:46:58 +02:00
sRoulette - > nextTask = NULL ;
sRoulette - > taskWaitKey = 0 ;
sRoulette - > taskWaitDelay = 0 ;
2019-01-01 01:07:29 +01:00
}
2020-08-03 23:31:34 +02:00
if ( sRoulette - > taskWaitDelay ! = NO_DELAY )
2020-07-29 10:46:58 +02:00
sRoulette - > taskWaitDelay - - ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
static void StartTaskAfterDelayOrInput ( u8 taskId , TaskFunc task , u16 delay , u16 key )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
sRoulette - > prevTask = gTasks [ taskId ] . func ;
2020-07-29 10:46:58 +02:00
if ( task = = NULL )
2020-07-31 20:55:42 +02:00
task = sRoulette - > prevTask ;
2020-07-29 10:46:58 +02:00
sRoulette - > nextTask = task ;
sRoulette - > taskWaitDelay = delay ;
2020-08-03 23:31:34 +02:00
if ( delay = = NO_DELAY & & key = = 0 )
2020-07-29 10:46:58 +02:00
sRoulette - > taskWaitKey = 0xFFFF ;
2019-01-01 01:07:29 +01:00
else
2020-07-29 10:46:58 +02:00
sRoulette - > taskWaitKey = key ;
gTasks [ taskId ] . func = Task_WaitForNextTask ;
2019-01-01 01:07:29 +01:00
}
2020-08-03 23:31:34 +02:00
static void ResetBallDataForNewSpin ( u8 taskId )
2019-01-01 01:07:29 +01:00
{
u8 i = 0 ;
2020-07-31 20:55:42 +02:00
sRoulette - > unk0 = FALSE ;
sRoulette - > ballRolling = FALSE ;
sRoulette - > ballStuck = FALSE ;
sRoulette - > ballUnstuck = FALSE ;
2020-07-29 10:46:58 +02:00
sRoulette - > useTaillow = FALSE ;
for ( i = 0 ; i < BALLS_PER_ROUND ; i + + )
sRoulette - > betSelection [ i ] = SELECTION_NONE ;
sRoulette - > curBallNum = 0 ;
2019-01-01 01:07:29 +01:00
gTasks [ taskId ] . data [ 1 ] = 0 ;
}
2020-07-29 10:46:58 +02:00
static void ResetHits ( void )
2019-01-01 01:07:29 +01:00
{
u8 i ;
2020-07-29 10:46:58 +02:00
sRoulette - > hitFlags = 0 ;
for ( i = 0 ; i < BALLS_PER_ROUND ; i + + )
sRoulette - > hitSquares [ i ] = 0 ;
for ( i = 0 ; i < NUM_BOARD_POKES ; i + + )
sRoulette - > pokeHits [ i ] = 0 ;
for ( i = 0 ; i < NUM_BOARD_COLORS ; i + + )
sRoulette - > colorHits [ i ] = 0 ;
ShowHideGridBalls ( TRUE , - 1 ) ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
static u8 RecordHit ( u8 taskId , u8 slotId )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
u8 i , j ;
u32 columnFlags [ NUM_BOARD_POKES ] = {
2021-08-25 00:59:32 +02:00
F_WYNAUT_COL | F_ORANGE_WYNAUT | F_GREEN_WYNAUT | F_PURPLE_WYNAUT ,
F_AZURILL_COL | F_ORANGE_AZURILL | F_GREEN_AZURILL | F_PURPLE_AZURILL ,
F_SKITTY_COL | F_ORANGE_SKITTY | F_GREEN_SKITTY | F_PURPLE_SKITTY ,
2020-07-29 10:46:58 +02:00
F_MAKUHITA_COL | F_ORANGE_MAKUHITA | F_GREEN_MAKUHITA | F_PURPLE_MAKUHITA
} ;
u32 rowFlags [ NUM_BOARD_COLORS ] = {
2021-08-25 00:59:32 +02:00
F_ORANGE_ROW | F_ORANGE_WYNAUT | F_ORANGE_AZURILL | F_ORANGE_SKITTY | F_ORANGE_MAKUHITA ,
F_GREEN_ROW | F_GREEN_WYNAUT | F_GREEN_AZURILL | F_GREEN_SKITTY | F_GREEN_MAKUHITA ,
2020-07-29 10:46:58 +02:00
F_PURPLE_ROW | F_PURPLE_WYNAUT | F_PURPLE_AZURILL | F_PURPLE_SKITTY | F_PURPLE_MAKUHITA
} ;
2019-01-01 01:07:29 +01:00
2020-07-29 10:46:58 +02:00
if ( slotId > = NUM_ROULETTE_SLOTS )
2019-01-01 01:07:29 +01:00
return 0 ;
2020-07-29 10:46:58 +02:00
sRoulette - > hitSquares [ gTasks [ taskId ] . tBallNum - 1 ] = sRouletteSlots [ slotId ] . gridSquare ;
gTasks [ taskId ] . tWinningSquare = sRouletteSlots [ slotId ] . gridSquare ;
sRoulette - > hitFlags | = sRouletteSlots [ slotId ] . flag ;
for ( i = 0 ; i < NUM_BOARD_POKES ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
if ( sRouletteSlots [ slotId ] . flag & columnFlags [ i ] )
sRoulette - > pokeHits [ i ] + + ;
// If hit every color of a poke, set column completed
if ( sRoulette - > pokeHits [ i ] > = NUM_BOARD_COLORS )
sRoulette - > hitFlags | = columnFlags [ i ] ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
for ( j = 0 ; j < NUM_BOARD_COLORS ; j + + )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
if ( sRouletteSlots [ slotId ] . flag & rowFlags [ j ] )
sRoulette - > colorHits [ j ] + + ;
// If hit every poke of a color, set row completed
if ( sRoulette - > colorHits [ j ] > = NUM_BOARD_POKES )
sRoulette - > hitFlags | = rowFlags [ j ] ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
return sRouletteSlots [ slotId ] . gridSquare ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
static bool8 IsHitInBetSelection ( u8 gridSquare , u8 betSelection )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
u8 hit = gridSquare ;
if ( - - gridSquare < NUM_GRID_SELECTIONS )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
switch ( betSelection )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
case SELECTION_NONE :
return 3 ; // should never happen, player must place bet
case COL_WYNAUT :
case COL_AZURILL :
case COL_SKITTY :
case COL_MAKUHITA :
2021-08-25 00:59:32 +02:00
if ( hit = = betSelection + ROW_ORANGE
| | hit = = betSelection + ROW_GREEN
2020-07-29 10:46:58 +02:00
| | hit = = betSelection + ROW_PURPLE )
2019-01-01 01:07:29 +01:00
return TRUE ;
break ;
2020-07-29 10:46:58 +02:00
case ROW_ORANGE :
case ROW_GREEN :
case ROW_PURPLE :
2021-08-25 00:59:32 +02:00
if ( hit > = ( betSelection + COL_WYNAUT )
2020-07-29 10:46:58 +02:00
& & hit < = ( betSelection + COL_MAKUHITA ) )
2019-01-01 01:07:29 +01:00
return TRUE ;
break ;
2020-07-29 10:46:58 +02:00
// Individual square
2019-01-01 01:07:29 +01:00
default :
2020-07-29 10:46:58 +02:00
if ( hit = = betSelection )
2019-01-01 01:07:29 +01:00
return TRUE ;
}
}
return FALSE ;
}
2020-07-29 10:46:58 +02:00
static void FlashSelectionOnWheel ( u8 selectionId )
2019-01-01 01:07:29 +01:00
{
2020-08-05 01:19:36 +02:00
u16 flashFlags = 0 ;
2020-07-31 20:55:42 +02:00
u8 numSelected ;
2020-08-05 01:19:36 +02:00
u16 palOffset ;
2019-01-01 01:07:29 +01:00
u8 i ;
2020-07-29 10:46:58 +02:00
switch ( selectionId )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
case ROW_ORANGE :
case ROW_GREEN :
case ROW_PURPLE :
2020-07-31 20:55:42 +02:00
// Flash colors of row selection
2020-07-29 10:46:58 +02:00
for ( i = ( selectionId + 1 ) ; i < ( selectionId + 5 ) ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
if ( ! ( sRoulette - > hitFlags & sGridSelections [ i ] . flag ) )
2020-08-05 01:19:36 +02:00
flashFlags | = sGridSelections [ i ] . flashFlags ;
2019-01-01 01:07:29 +01:00
}
2020-08-05 01:19:36 +02:00
RouletteFlash_Enable ( & sRoulette - > flashUtil , flashFlags & = ~ ( F_FLASH_ICON ) ) ;
2019-01-01 01:07:29 +01:00
break ;
default :
{
2020-07-31 20:55:42 +02:00
// Selection is either a column or individual square
2020-08-05 01:19:36 +02:00
struct RouletteFlashSettings iconFlash [ NUM_BOARD_COLORS ] ;
memcpy ( iconFlash , sFlashData_PokeIcons , sizeof ( iconFlash ) ) ;
2020-07-31 20:55:42 +02:00
2020-07-29 10:46:58 +02:00
if ( selectionId > = COL_WYNAUT & & selectionId < = COL_MAKUHITA )
2020-07-31 20:55:42 +02:00
numSelected = NUM_BOARD_COLORS ; // Selection is full column
2019-01-01 01:07:29 +01:00
else
2020-07-31 20:55:42 +02:00
numSelected = 1 ;
2020-07-29 10:46:58 +02:00
2020-08-05 01:19:36 +02:00
palOffset = GET_ROW_IDX ( selectionId ) ;
2020-07-29 10:46:58 +02:00
switch ( GET_COL ( selectionId ) )
2019-01-01 01:07:29 +01:00
{
2020-08-05 01:19:36 +02:00
// The specific color of the poke it references doesn't matter, because the icons of a poke share a palette
2020-07-29 10:46:58 +02:00
// So it just uses the first sprite ID of each
case COL_WYNAUT :
2020-08-05 01:19:36 +02:00
palOffset = gSprites [ sRoulette - > spriteIds [ SPR_WHEEL_ICON_ORANGE_WYNAUT ] ] . oam . paletteNum * 16 ;
2020-07-29 10:46:58 +02:00
break ;
case COL_AZURILL :
2020-08-05 01:19:36 +02:00
palOffset = gSprites [ sRoulette - > spriteIds [ SPR_WHEEL_ICON_GREEN_AZURILL ] ] . oam . paletteNum * 16 ;
2020-07-29 10:46:58 +02:00
break ;
case COL_SKITTY :
2020-08-05 01:19:36 +02:00
palOffset = gSprites [ sRoulette - > spriteIds [ SPR_WHEEL_ICON_PURPLE_SKITTY ] ] . oam . paletteNum * 16 ;
2020-07-29 10:46:58 +02:00
break ;
case COL_MAKUHITA :
2020-08-05 01:19:36 +02:00
palOffset = gSprites [ sRoulette - > spriteIds [ SPR_WHEEL_ICON_ORANGE_MAKUHITA ] ] . oam . paletteNum * 16 ;
2020-07-29 10:46:58 +02:00
break ;
2019-01-01 01:07:29 +01:00
}
2020-07-31 20:55:42 +02:00
if ( numSelected = = 1 )
2019-01-01 01:07:29 +01:00
{
2020-08-05 01:19:36 +02:00
// Selection is individual square, add entry in flash util for its icon
2020-07-29 10:46:58 +02:00
if ( ! ( sRoulette - > hitFlags & sGridSelections [ selectionId ] . flag ) )
2019-01-01 01:07:29 +01:00
{
2020-08-05 01:19:36 +02:00
iconFlash [ GET_ROW_IDX ( selectionId ) ] . paletteOffset + = palOffset ;
RouletteFlash_Add ( & sRoulette - > flashUtil , NUM_ROULETTE_SLOTS + 1 , & iconFlash [ GET_ROW_IDX ( selectionId ) ] ) ;
2019-01-01 01:07:29 +01:00
}
else
{
2020-07-31 20:55:42 +02:00
// Square was already hit, don't flash it
2019-01-01 01:07:29 +01:00
break ;
}
}
else
{
2020-08-05 01:19:36 +02:00
// Selection is full column, add entry in flash util for each unhit space's icon
// If there is only 1 unhit space, also add its flags so its color will flash as well
2020-07-31 20:55:42 +02:00
for ( i = 0 ; i < NUM_BOARD_COLORS ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-08-05 01:19:36 +02:00
u8 columnSlotId = i * 5 + selectionId + 5 ;
if ( ! ( sRoulette - > hitFlags & sGridSelections [ columnSlotId ] . flag ) )
2019-01-01 01:07:29 +01:00
{
2020-08-05 01:19:36 +02:00
iconFlash [ GET_ROW_IDX ( columnSlotId ) ] . paletteOffset + = palOffset ;
RouletteFlash_Add ( & sRoulette - > flashUtil , i + NUM_ROULETTE_SLOTS + 1 , & iconFlash [ GET_ROW_IDX ( columnSlotId ) ] ) ;
2020-07-31 20:55:42 +02:00
if ( numSelected = = 3 )
2020-08-05 01:19:36 +02:00
flashFlags = sGridSelections [ columnSlotId ] . flashFlags ;
2020-07-31 20:55:42 +02:00
numSelected - - ;
2019-01-01 01:07:29 +01:00
}
}
2020-08-05 01:19:36 +02:00
// If there was more than 1 space in the column, reset flags; only icons will flash
2020-07-31 20:55:42 +02:00
if ( numSelected ! = 2 )
2020-08-05 01:19:36 +02:00
flashFlags = 0 ;
2019-01-01 01:07:29 +01:00
}
2020-07-31 20:55:42 +02:00
// Do flash
2020-08-05 01:19:36 +02:00
RouletteFlash_Enable ( & sRoulette - > flashUtil , flashFlags | = sGridSelections [ selectionId ] . flashFlags ) ;
2019-01-01 01:07:29 +01:00
break ;
}
}
}
2020-07-29 10:46:58 +02:00
static void DrawGridBackground ( u8 selectionId )
2019-01-01 01:07:29 +01:00
{
2020-08-03 23:31:34 +02:00
vu8 i , j ;
vu16 x , y ;
vu8 tilemapOffset ;
u8 selectionIds [ NUM_BOARD_POKES > = NUM_BOARD_COLORS ? NUM_BOARD_POKES + 1 : NUM_BOARD_COLORS + 1 ] ;
u8 numSquares ;
2020-07-31 20:55:42 +02:00
sRoulette - > updateGridHighlight = TRUE ;
2020-07-29 10:46:58 +02:00
ShowHideGridIcons ( FALSE , 0 ) ;
2020-07-31 20:55:42 +02:00
SetTilemapRect ( sRoulette - > tilemapBuffers [ 2 ] , sRoulette - > gridTilemap , 14 , 7 , 16 , 13 ) ;
2020-08-03 23:31:34 +02:00
// Highlight selected square
// (just buffers the highlight, it's actually drawn in VBlankCB_Roulette)
2020-07-29 10:46:58 +02:00
switch ( selectionId )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
case SELECTION_NONE :
2019-01-01 01:07:29 +01:00
return ;
2020-07-29 10:46:58 +02:00
case COL_WYNAUT :
case COL_AZURILL :
case COL_SKITTY :
case COL_MAKUHITA :
2020-08-03 23:31:34 +02:00
numSquares = NUM_BOARD_COLORS + 1 ; // For each poke column, 3 colors and a header
for ( i = 0 ; i < numSquares ; i + + )
selectionIds [ i ] = i * ROW_ORANGE + selectionId ;
2019-01-01 01:07:29 +01:00
break ;
2020-07-29 10:46:58 +02:00
case ROW_ORANGE :
case ROW_GREEN :
case ROW_PURPLE :
2020-08-03 23:31:34 +02:00
numSquares = NUM_BOARD_POKES + 1 ; // For each color row, 4 pokes and a header
for ( i = 0 ; i < numSquares ; i + + )
selectionIds [ i ] = i + selectionId ;
2019-01-01 01:07:29 +01:00
break ;
2020-07-29 10:46:58 +02:00
// Individual square
2019-01-01 01:07:29 +01:00
default :
2020-08-03 23:31:34 +02:00
numSquares = 1 ;
selectionIds [ 0 ] = selectionId ;
2019-01-01 01:07:29 +01:00
}
2020-08-03 23:31:34 +02:00
for ( i = 0 ; i < numSquares ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-08-03 23:31:34 +02:00
tilemapOffset = sGridSelections [ selectionIds [ i ] ] . tilemapOffset ;
x = sGridSelections [ selectionIds [ i ] ] . x ;
// Grid square highlight is drawn in 9 segments, starting from the top left of the square
// Each iteration of this loop draws 3 segments to form a single horizontal segment
for ( j = 0 ; j < 3 ; j + + )
2019-01-01 01:07:29 +01:00
{
2020-08-03 23:31:34 +02:00
y = ( sGridSelections [ selectionIds [ i ] ] . y + j ) * 32 ;
sRoulette - > tilemapBuffers [ 2 ] [ x + y + 0 ] = sRoulette - > gridTilemap [ ( tilemapOffset + j ) * 3 + 208 + 0 ] ;
sRoulette - > tilemapBuffers [ 2 ] [ x + y + 1 ] = sRoulette - > gridTilemap [ ( tilemapOffset + j ) * 3 + 208 + 1 ] ;
sRoulette - > tilemapBuffers [ 2 ] [ x + y + 2 ] = sRoulette - > gridTilemap [ ( tilemapOffset + j ) * 3 + 208 + 2 ] ;
2019-01-01 01:07:29 +01:00
}
}
}
2020-07-29 10:46:58 +02:00
static u8 GetMultiplier ( u8 selectionId )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
u8 multipliers [ 5 ] = { 0 , 3 , 4 , 6 , MAX_MULTIPLIER } ;
2020-07-29 10:46:58 +02:00
if ( selectionId > NUM_GRID_SELECTIONS )
selectionId = 0 ;
2019-01-01 01:07:29 +01:00
2020-07-29 10:46:58 +02:00
switch ( sGridSelections [ selectionId ] . baseMultiplier )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
case NUM_BOARD_COLORS :
2020-07-31 20:55:42 +02:00
selectionId = GET_ROW_IDX ( selectionId ) ;
2020-07-29 10:46:58 +02:00
// If already hit all pokes of this color, multiplier is 0
if ( sRoulette - > colorHits [ selectionId ] > = NUM_BOARD_POKES )
2019-01-01 01:07:29 +01:00
return 0 ;
2020-07-29 10:46:58 +02:00
return multipliers [ sRoulette - > colorHits [ selectionId ] + 1 ] ;
case NUM_BOARD_POKES :
2020-07-31 20:55:42 +02:00
selectionId = GET_COL_IDX ( selectionId ) ;
2020-07-29 10:46:58 +02:00
// If already hit all colors of this poke, multiplier is 0
if ( sRoulette - > pokeHits [ selectionId ] > = NUM_BOARD_COLORS )
2019-01-01 01:07:29 +01:00
return 0 ;
2020-07-29 10:46:58 +02:00
return multipliers [ sRoulette - > pokeHits [ selectionId ] + 2 ] ;
case NUM_ROULETTE_SLOTS :
// If square has been hit already, multiplier is 0
if ( sRoulette - > hitFlags & sGridSelections [ selectionId ] . flag )
2019-01-01 01:07:29 +01:00
return 0 ;
2020-07-31 20:55:42 +02:00
return multipliers [ ARRAY_COUNT ( multipliers ) - 1 ] ;
2019-01-01 01:07:29 +01:00
}
return 0 ;
}
2020-07-31 20:55:42 +02:00
static void UpdateWheelPosition ( void )
{
s32 bg2x ;
s32 bg2y ;
SetGpuReg ( REG_OFFSET_BG2PA , sRoulette - > wheelRotation . a ) ;
SetGpuReg ( REG_OFFSET_BG2PB , sRoulette - > wheelRotation . b ) ;
SetGpuReg ( REG_OFFSET_BG2PC , sRoulette - > wheelRotation . c ) ;
SetGpuReg ( REG_OFFSET_BG2PD , sRoulette - > wheelRotation . d ) ;
bg2x = 0x7400 - sRoulette - > wheelRotation . a * ( gSpriteCoordOffsetX + 116 )
- sRoulette - > wheelRotation . b * ( gSpriteCoordOffsetY + 80 ) ;
bg2y = 0x5400 - sRoulette - > wheelRotation . c * ( gSpriteCoordOffsetX + 116 )
- sRoulette - > wheelRotation . d * ( gSpriteCoordOffsetY + 80 ) ;
SetGpuReg ( REG_OFFSET_BG2X_L , bg2x ) ;
SetGpuReg ( REG_OFFSET_BG2X_H , ( bg2x & 0x0fff0000 ) > > 16 ) ;
SetGpuReg ( REG_OFFSET_BG2Y_L , bg2y ) ;
SetGpuReg ( REG_OFFSET_BG2Y_H , ( bg2y & 0x0fff0000 ) > > 16 ) ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
static const u8 sFiller [ 3 ] = { } ;
static const u16 sShadow_Pal [ ] = INCBIN_U16 ( " graphics/roulette/shadow.gbapal " ) ;
static const u16 sBall_Pal [ ] = INCBIN_U16 ( " graphics/roulette/ball.gbapal " ) ;
static const u16 sBallCounter_Pal [ ] = INCBIN_U16 ( " graphics/roulette/ball_counter.gbapal " ) ;
static const u16 sCursor_Pal [ ] = INCBIN_U16 ( " graphics/roulette/cursor.gbapal " ) ;
static const u16 sCredit_Pal [ ] = INCBIN_U16 ( " graphics/roulette/credit.gbapal " ) ;
static const u16 sShroomish_Pal [ ] = INCBIN_U16 ( " graphics/roulette/shroomish.gbapal " ) ;
static const u16 sTaillow_Pal [ ] = INCBIN_U16 ( " graphics/roulette/tailow.gbapal " ) ;
static const u16 sGridIcons_Pal [ ] = INCBIN_U16 ( " graphics/roulette/grid_icons.gbapal " ) ;
static const u16 sWynaut_Pal [ ] = INCBIN_U16 ( " graphics/roulette/wynaut.gbapal " ) ;
static const u16 sAzurill_Pal [ ] = INCBIN_U16 ( " graphics/roulette/azurill.gbapal " ) ;
static const u16 sSkitty_Pal [ ] = INCBIN_U16 ( " graphics/roulette/skitty.gbapal " ) ;
static const u16 sMakuhita_Pal [ ] = INCBIN_U16 ( " graphics/roulette/makuhita.gbapal " ) ;
static const u16 sUnused1_Pal [ ] = INCBIN_U16 ( " graphics/roulette/unused_1.gbapal " ) ;
static const u16 sUnused2_Pal [ ] = INCBIN_U16 ( " graphics/roulette/unused_2.gbapal " ) ;
static const u16 sUnused3_Pal [ ] = INCBIN_U16 ( " graphics/roulette/unused_3.gbapal " ) ;
static const u16 sUnused4_Pal [ ] = INCBIN_U16 ( " graphics/roulette/unused_4.gbapal " ) ;
static const u32 sBall_Gfx [ ] = INCBIN_U32 ( " graphics/roulette/ball.4bpp.lz " ) ;
static const u32 sBallCounter_Gfx [ ] = INCBIN_U32 ( " graphics/roulette/ball_counter.4bpp.lz " ) ;
static const u32 sShroomishTaillow_Gfx [ ] = INCBIN_U32 ( " graphics/roulette/roulette_tilt.4bpp.lz " ) ;
static const u32 sGridIcons_Gfx [ ] = INCBIN_U32 ( " graphics/roulette/grid_icons.4bpp.lz " ) ;
2020-08-03 23:31:34 +02:00
static const u32 sWheelIcons_Gfx [ ] = INCBIN_U32 ( " graphics/roulette/wheel_icons.4bpp.lz " ) ;
2020-07-29 10:46:58 +02:00
static const u32 sShadow_Gfx [ ] = INCBIN_U32 ( " graphics/roulette/shadow.4bpp.lz " ) ;
static const u32 sCursor_Gfx [ ] = INCBIN_U32 ( " graphics/roulette/cursor.4bpp.lz " ) ;
static const struct SpritePalette sSpritePalettes [ ] =
{
{ . data = sShadow_Pal , . tag = PALTAG_SHADOW } ,
{ . data = sBall_Pal , . tag = PALTAG_BALL } ,
{ . data = sBallCounter_Pal , . tag = PALTAG_BALL_COUNTER } ,
2020-08-03 23:31:34 +02:00
{ . data = sCursor_Pal , . tag = PALTAG_CURSOR } ,
2020-07-29 10:46:58 +02:00
{ . data = sCredit_Pal , . tag = PALTAG_INTERFACE } ,
{ . data = sShroomish_Pal , . tag = PALTAG_SHROOMISH } ,
{ . data = sTaillow_Pal , . tag = PALTAG_TAILLOW } ,
{ . data = sGridIcons_Pal , . tag = PALTAG_GRID_ICONS } ,
{ . data = sWynaut_Pal , . tag = PALTAG_WYNAUT } ,
{ . data = sAzurill_Pal , . tag = PALTAG_AZURILL } ,
{ . data = sSkitty_Pal , . tag = PALTAG_SKITTY } ,
{ . data = sMakuhita_Pal , . tag = PALTAG_MAKUHITA } ,
2019-01-02 23:40:40 +01:00
{ }
} ;
2020-07-31 20:55:42 +02:00
static const struct OamData sOam_GridHeader =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 32 x32 ) ,
. size = SPRITE_SIZE ( 32 x32 ) ,
2019-01-02 23:40:40 +01:00
. priority = 1 ,
} ;
2020-07-29 10:46:58 +02:00
static const struct OamData sOam_GridIcon =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 16 x16 ) ,
. size = SPRITE_SIZE ( 16 x16 ) ,
2019-01-02 23:40:40 +01:00
. priority = 1 ,
} ;
2020-08-03 23:31:34 +02:00
static const struct OamData sOam_WheelIcon =
2019-01-02 23:40:40 +01:00
{
. y = 60 ,
. affineMode = ST_OAM_AFFINE_DOUBLE ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 16 x32 ) ,
. size = SPRITE_SIZE ( 16 x32 ) ,
2019-01-02 23:40:40 +01:00
. priority = 2 ,
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd sAffineAnim_Unused1 [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 0 ) ,
ANIMCMD_END
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAffineAnims_Unused1 [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
sAffineAnim_Unused1
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AffineAnimCmd sAffineAnim_Unused2 [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
AFFINEANIMCMD_END
} ;
2020-07-29 10:46:58 +02:00
static const union AffineAnimCmd * const sAffineAnims_Unused2 [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
sAffineAnim_Unused2
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const struct CompressedSpriteSheet sSpriteSheet_WheelIcons =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
. data = sWheelIcons_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0xC00 ,
2020-08-03 23:31:34 +02:00
. tag = GFXTAG_WHEEL_ICONS
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_WheelIcons [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 0 ) ,
ANIMCMD_FRAME ( 32 , 0 ) ,
ANIMCMD_FRAME ( 64 , 0 ) ,
ANIMCMD_FRAME ( 72 , 0 ) ,
ANIMCMD_FRAME ( 8 , 0 ) ,
ANIMCMD_FRAME ( 40 , 0 ) ,
ANIMCMD_FRAME ( 48 , 0 ) ,
ANIMCMD_FRAME ( 80 , 0 ) ,
ANIMCMD_FRAME ( 16 , 0 ) ,
ANIMCMD_FRAME ( 24 , 0 ) ,
ANIMCMD_FRAME ( 56 , 0 ) ,
ANIMCMD_FRAME ( 88 , 0 ) ,
ANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_OrangeWynaut [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 0 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_GreenAzurill [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 1 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_PurpleSkitty [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 2 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_OrangeMakuhita [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 3 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_GreenWynaut [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 4 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_PurpleAzurill [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 5 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_OrangeSkitty [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 6 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_GreenMakuhita [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 7 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_PurpleWynaut [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 8 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_OrangeAzurill [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 9 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_GreenSkitty [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 10 ]
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnim_WheelIcon_PurpleMakuhita [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
& sAnim_WheelIcons [ 11 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const struct CompressedSpriteSheet sSpriteSheet_Headers =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
. data = gRouletteHeaders_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0x1600 ,
2020-07-29 10:46:58 +02:00
. tag = GFXTAG_HEADERS
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const struct CompressedSpriteSheet sSpriteSheet_GridIcons =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
. data = sGridIcons_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0x400 ,
2020-07-29 10:46:58 +02:00
. tag = GFXTAG_GRID_ICONS
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd sAnim_Headers [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 0 ) ,
ANIMCMD_FRAME ( 16 , 0 ) ,
ANIMCMD_FRAME ( 32 , 0 ) ,
ANIMCMD_FRAME ( 48 , 0 ) ,
ANIMCMD_FRAME ( 64 , 0 ) ,
ANIMCMD_FRAME ( 80 , 0 ) ,
ANIMCMD_FRAME ( 96 , 0 ) ,
ANIMCMD_FRAME ( 112 , 0 ) ,
ANIMCMD_FRAME ( 128 , 0 ) ,
ANIMCMD_FRAME ( 144 , 0 ) ,
ANIMCMD_FRAME ( 160 , 0 ) ,
ANIMCMD_END
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd sAnim_GridIcons [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 0 ) ,
ANIMCMD_FRAME ( 4 , 0 ) ,
ANIMCMD_FRAME ( 8 , 0 ) ,
ANIMCMD_FRAME ( 12 , 0 ) ,
ANIMCMD_END
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_WynautHeader [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_Headers [ 0 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_AzurillHeader [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_Headers [ 2 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_SkittyHeader [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_Headers [ 4 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_MakuhitaHeader [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_Headers [ 6 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_OrangeHeader [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_Headers [ 8 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_GreenHeader [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_Headers [ 9 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_PurpleHeader [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_Headers [ 10 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_GridIcon_Wynaut [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_GridIcons [ 0 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_GridIcon_Azurill [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_GridIcons [ 1 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_GridIcon_Skitty [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_GridIcons [ 2 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnim_GridIcon_Makuhita [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
& sAnim_GridIcons [ 3 ]
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplates_PokeHeaders [ NUM_BOARD_POKES ] =
2019-01-02 23:40:40 +01:00
{
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_HEADERS ,
. paletteTag = PALTAG_GRID_ICONS ,
2020-07-31 20:55:42 +02:00
. oam = & sOam_GridHeader ,
2020-07-29 10:46:58 +02:00
. anims = sAnim_WynautHeader ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_HEADERS ,
. paletteTag = PALTAG_GRID_ICONS ,
2020-07-31 20:55:42 +02:00
. oam = & sOam_GridHeader ,
2020-07-29 10:46:58 +02:00
. anims = sAnim_AzurillHeader ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_HEADERS ,
. paletteTag = PALTAG_GRID_ICONS ,
2020-07-31 20:55:42 +02:00
. oam = & sOam_GridHeader ,
2020-07-29 10:46:58 +02:00
. anims = sAnim_SkittyHeader ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_HEADERS ,
. paletteTag = PALTAG_GRID_ICONS ,
2020-07-31 20:55:42 +02:00
. oam = & sOam_GridHeader ,
2020-07-29 10:46:58 +02:00
. anims = sAnim_MakuhitaHeader ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
}
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplates_ColorHeaders [ NUM_BOARD_COLORS ] =
2019-01-02 23:40:40 +01:00
{
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_HEADERS ,
. paletteTag = PALTAG_GRID_ICONS ,
2020-07-31 20:55:42 +02:00
. oam = & sOam_GridHeader ,
2020-07-29 10:46:58 +02:00
. anims = sAnim_OrangeHeader ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_HEADERS ,
. paletteTag = PALTAG_GRID_ICONS ,
2020-07-31 20:55:42 +02:00
. oam = & sOam_GridHeader ,
2020-07-29 10:46:58 +02:00
. anims = sAnim_GreenHeader ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_HEADERS ,
. paletteTag = PALTAG_GRID_ICONS ,
2020-07-31 20:55:42 +02:00
. oam = & sOam_GridHeader ,
2020-07-29 10:46:58 +02:00
. anims = sAnim_PurpleHeader ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
}
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplate_GridIcons [ NUM_BOARD_POKES ] =
2019-01-02 23:40:40 +01:00
{
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_GRID_ICONS ,
. paletteTag = PALTAG_GRID_ICONS ,
. oam = & sOam_GridIcon ,
. anims = sAnim_GridIcon_Wynaut ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_GRID_ICONS ,
. paletteTag = PALTAG_GRID_ICONS ,
. oam = & sOam_GridIcon ,
. anims = sAnim_GridIcon_Azurill ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_GRID_ICONS ,
. paletteTag = PALTAG_GRID_ICONS ,
. oam = & sOam_GridIcon ,
. anims = sAnim_GridIcon_Skitty ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_GRID_ICONS ,
. paletteTag = PALTAG_GRID_ICONS ,
. oam = & sOam_GridIcon ,
. anims = sAnim_GridIcon_Makuhita ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
}
} ;
2020-08-03 23:31:34 +02:00
// Wheel icons are listed clockwise starting from 1 oclock on the roulette wheel (with pokeball upside right)
2020-07-29 10:46:58 +02:00
// They go Wynaut -> Azurill -> Skitty -> Makuhita, and Orange -> Green -> Purple
2020-08-03 23:31:34 +02:00
static const struct SpriteTemplate sSpriteTemplates_WheelIcons [ NUM_ROULETTE_SLOTS ] =
2019-01-02 23:40:40 +01:00
{
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_WYNAUT ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_OrangeWynaut ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_AZURILL ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_GreenAzurill ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_SKITTY ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_PurpleSkitty ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_MAKUHITA ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_OrangeMakuhita ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_WYNAUT ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_GreenWynaut ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_AZURILL ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_PurpleAzurill ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_SKITTY ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_OrangeSkitty ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_MAKUHITA ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_GreenMakuhita ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_WYNAUT ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_PurpleWynaut ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_AZURILL ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_OrangeAzurill ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_SKITTY ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_GreenSkitty ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
} ,
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_ICONS ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_MAKUHITA ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelIcon ,
. anims = sAnim_WheelIcon_PurpleMakuhita ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelIcon
2019-01-02 23:40:40 +01:00
}
} ;
2020-07-29 10:46:58 +02:00
static const struct OamData sOam_Credit =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 64 x32 ) ,
. size = SPRITE_SIZE ( 64 x32 ) ,
2019-01-02 23:40:40 +01:00
. priority = 1 ,
} ;
2020-07-29 10:46:58 +02:00
static const struct OamData sOam_CreditDigit =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 8 x16 ) ,
. size = SPRITE_SIZE ( 8 x16 ) ,
2019-01-02 23:40:40 +01:00
. priority = 1 ,
} ;
2020-07-29 10:46:58 +02:00
static const struct OamData sOam_Multiplier =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 32 x16 ) ,
. size = SPRITE_SIZE ( 32 x16 ) ,
2019-01-02 23:40:40 +01:00
. priority = 1 ,
} ;
2020-07-29 10:46:58 +02:00
static const struct OamData sOam_BallCounter =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 16 x8 ) ,
. size = SPRITE_SIZE ( 16 x8 ) ,
2019-01-02 23:40:40 +01:00
. priority = 1 ,
} ;
2020-07-29 10:46:58 +02:00
static const struct CompressedSpriteSheet sSpriteSheets_Interface [ ] =
2019-01-02 23:40:40 +01:00
{
{
2020-07-29 10:46:58 +02:00
. data = gRouletteCredit_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0x400 ,
2020-07-29 10:46:58 +02:00
. tag = GFXTAG_CREDIT
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. data = gRouletteNumbers_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0x280 ,
2020-07-29 10:46:58 +02:00
. tag = GFXTAG_CREDIT_DIGIT
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. data = gRouletteMultiplier_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0x500 ,
2020-07-29 10:46:58 +02:00
. tag = GFXTAG_MULTIPLIER
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. data = sBallCounter_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0x140 ,
2020-07-29 10:46:58 +02:00
. tag = GFXTAG_BALL_COUNTER
2019-01-02 23:40:40 +01:00
} ,
{
2020-07-29 10:46:58 +02:00
. data = sCursor_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0x200 ,
2020-07-29 10:46:58 +02:00
. tag = GFXTAG_CURSOR
2019-01-02 23:40:40 +01:00
} ,
{ }
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_CreditDigit [ ] =
{
ANIMCMD_FRAME ( 0 , 0 ) , // 0
ANIMCMD_FRAME ( 2 , 0 ) , // 1
ANIMCMD_FRAME ( 4 , 0 ) , // 2
ANIMCMD_FRAME ( 6 , 0 ) , // 3
ANIMCMD_FRAME ( 8 , 0 ) , // 4
ANIMCMD_FRAME ( 10 , 0 ) , // 5
ANIMCMD_FRAME ( 12 , 0 ) , // 6
ANIMCMD_FRAME ( 14 , 0 ) , // 7
ANIMCMD_FRAME ( 16 , 0 ) , // 8
ANIMCMD_FRAME ( 18 , 0 ) , // 9
2019-01-02 23:40:40 +01:00
// BUG: Animation not terminated properly
2020-08-03 23:31:34 +02:00
// Doesn't matter in practice, the frames are set directly and not looped
2021-05-15 22:56:17 +02:00
# ifdef BUGFIX
ANIMCMD_END
# endif
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnims_CreditDigit [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
sAnim_CreditDigit
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd sAnim_Multiplier [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 0 ) ,
ANIMCMD_FRAME ( 8 , 0 ) ,
ANIMCMD_FRAME ( 16 , 0 ) ,
ANIMCMD_FRAME ( 24 , 0 ) ,
ANIMCMD_FRAME ( 32 , 0 ) ,
ANIMCMD_END
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnims_Multiplier [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
sAnim_Multiplier
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd sAnim_BallCounter [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 0 ) ,
ANIMCMD_FRAME ( 2 , 0 ) ,
ANIMCMD_FRAME ( 4 , 0 ) ,
ANIMCMD_FRAME ( 6 , 0 ) ,
ANIMCMD_FRAME ( 8 , 0 ) ,
ANIMCMD_END
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnims_BallCounter [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
sAnim_BallCounter
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplate_Credit =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_CREDIT ,
. paletteTag = PALTAG_INTERFACE ,
. oam = & sOam_Credit ,
2019-01-02 23:40:40 +01:00
. anims = gDummySpriteAnimTable ,
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
. callback = SpriteCallbackDummy
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplate_CreditDigit =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_CREDIT_DIGIT ,
. paletteTag = PALTAG_INTERFACE ,
. oam = & sOam_CreditDigit ,
2020-08-03 23:31:34 +02:00
. anims = sAnims_CreditDigit ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
. callback = SpriteCallbackDummy
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplate_Multiplier =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_MULTIPLIER ,
. paletteTag = PALTAG_INTERFACE ,
. oam = & sOam_Multiplier ,
. anims = sAnims_Multiplier ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_GridSquare
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplate_BallCounter =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_BALL_COUNTER ,
. paletteTag = PALTAG_BALL_COUNTER ,
. oam = & sOam_BallCounter ,
. anims = sAnims_BallCounter ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
. callback = SpriteCallbackDummy
} ;
2020-07-29 10:46:58 +02:00
// NOTE: This cursor is only used to identify the winning square on the grid
static const struct SpriteTemplate sSpriteTemplate_Cursor =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_CURSOR ,
. paletteTag = PALTAG_INTERFACE ,
2020-07-31 20:55:42 +02:00
. oam = & sOam_GridHeader ,
2019-01-02 23:40:40 +01:00
. anims = gDummySpriteAnimTable ,
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
. callback = SpriteCallbackDummy
} ;
2020-07-29 10:46:58 +02:00
static const struct OamData sOam_Ball =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 16 x16 ) ,
. size = SPRITE_SIZE ( 16 x16 ) ,
2019-01-02 23:40:40 +01:00
. priority = 2 ,
} ;
2020-07-29 10:46:58 +02:00
static const struct CompressedSpriteSheet sSpriteSheet_Ball = {
. data = sBall_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0x200 ,
2020-07-29 10:46:58 +02:00
. tag = GFXTAG_BALL
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Ball_RollFast [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 5 ) ,
ANIMCMD_FRAME ( 4 , 5 ) ,
ANIMCMD_FRAME ( 8 , 5 ) ,
ANIMCMD_FRAME ( 4 , 5 ) ,
ANIMCMD_JUMP ( 0 )
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Ball_RollMedium [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 10 ) ,
ANIMCMD_FRAME ( 4 , 10 ) ,
ANIMCMD_FRAME ( 8 , 10 ) ,
ANIMCMD_FRAME ( 4 , 10 ) ,
ANIMCMD_JUMP ( 0 )
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Ball_RollSlow [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 15 ) ,
ANIMCMD_FRAME ( 4 , 15 ) ,
ANIMCMD_FRAME ( 8 , 15 ) ,
ANIMCMD_FRAME ( 4 , 15 ) ,
ANIMCMD_JUMP ( 0 )
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Ball_StopOnFrame1 [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 4 , 2 ) ,
ANIMCMD_FRAME ( 8 , 5 ) ,
ANIMCMD_FRAME ( 4 , 5 ) ,
ANIMCMD_FRAME ( 12 , 5 ) ,
ANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Ball_StopOnFrame3 [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 4 , 2 ) ,
ANIMCMD_FRAME ( 0 , 4 ) ,
ANIMCMD_FRAME ( 4 , 4 ) ,
ANIMCMD_FRAME ( 8 , 4 ) ,
ANIMCMD_FRAME ( 12 , 4 ) ,
ANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Ball_StopOnFrame4 [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 2 ) ,
ANIMCMD_FRAME ( 4 , 5 ) ,
ANIMCMD_FRAME ( 8 , 5 ) ,
ANIMCMD_FRAME ( 12 , 5 ) ,
ANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Ball_Still [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 12 , 0 ) ,
ANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Ball_StopOnFrame2 [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 8 , 2 ) ,
ANIMCMD_FRAME ( 4 , 5 ) ,
ANIMCMD_FRAME ( 0 , 5 ) ,
ANIMCMD_FRAME ( 12 , 5 ) ,
ANIMCMD_END
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnims_Ball [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
sAnim_Ball_RollFast ,
sAnim_Ball_RollMedium ,
sAnim_Ball_RollSlow ,
sAnim_Ball_StopOnFrame1 ,
sAnim_Ball_StopOnFrame2 ,
sAnim_Ball_StopOnFrame3 ,
sAnim_Ball_StopOnFrame4 ,
sAnim_Ball_StopOnFrame4 ,
sAnim_Ball_Still
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplate_Ball =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_BALL ,
. paletteTag = PALTAG_BALL ,
. oam = & sOam_Ball ,
. anims = sAnims_Ball ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
. callback = SpriteCallbackDummy
} ;
2020-08-03 23:31:34 +02:00
static const struct OamData sOam_WheelCenter =
2019-01-02 23:40:40 +01:00
{
. y = 81 ,
. affineMode = ST_OAM_AFFINE_DOUBLE ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 64 x64 ) ,
. size = SPRITE_SIZE ( 64 x64 ) ,
2019-01-02 23:40:40 +01:00
. priority = 2 ,
} ;
2020-08-03 23:31:34 +02:00
static const struct CompressedSpriteSheet sSpriteSheet_WheelCenter =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
. data = gRouletteCenter_Gfx ,
. size = 0x800 ,
2020-08-03 23:31:34 +02:00
. tag = GFXTAG_WHEEL_CENTER
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const struct SpriteTemplate sSpriteTemplate_WheelCenter =
2019-01-02 23:40:40 +01:00
{
2020-08-03 23:31:34 +02:00
. tileTag = GFXTAG_WHEEL_CENTER ,
2020-07-29 10:46:58 +02:00
. paletteTag = PALTAG_BALL ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_WheelCenter ,
2019-01-02 23:40:40 +01:00
. anims = gDummySpriteAnimTable ,
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_WheelCenter
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const struct OamData sOam_Shroomish =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 32 x32 ) ,
. size = SPRITE_SIZE ( 32 x32 ) ,
2019-01-02 23:40:40 +01:00
. priority = 2 ,
} ;
2020-07-29 10:46:58 +02:00
static const struct OamData sOam_Taillow =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 32 x32 ) ,
. size = SPRITE_SIZE ( 32 x32 ) ,
2019-01-02 23:40:40 +01:00
. priority = 2 ,
} ;
2020-07-29 10:46:58 +02:00
static const struct CompressedSpriteSheet sSpriteSheet_ShroomishTaillow =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
. data = sShroomishTaillow_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0xE00 ,
2020-07-29 10:46:58 +02:00
. tag = GFXTAG_SHROOMISH_TAILLOW
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd sAnim_Shroomish [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 6 ) ,
ANIMCMD_FRAME ( 16 , 6 ) ,
ANIMCMD_FRAME ( 32 , 6 ) ,
ANIMCMD_FRAME ( 48 , 6 ) ,
ANIMCMD_FRAME ( 32 , 6 ) ,
ANIMCMD_FRAME ( 64 , 6 ) ,
ANIMCMD_JUMP ( 2 )
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Taillow_WingDown_Left [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 80 , 10 ) ,
ANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Taillow_WingDown_Right [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 80 , 10 , . hFlip = TRUE ) ,
ANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Taillow_FlapSlow_Left [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 80 , 20 ) ,
ANIMCMD_FRAME ( 96 , 20 ) ,
ANIMCMD_JUMP ( 0 )
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Taillow_FlapSlow_Right [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 80 , 20 , . hFlip = TRUE ) ,
ANIMCMD_FRAME ( 96 , 20 , . hFlip = TRUE ) ,
ANIMCMD_JUMP ( 0 )
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Taillow_FlapFast_Left [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 80 , 10 ) ,
ANIMCMD_FRAME ( 96 , 10 ) ,
ANIMCMD_JUMP ( 0 )
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_Taillow_FlapFast_Right [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 80 , 10 , . hFlip = TRUE ) ,
ANIMCMD_FRAME ( 96 , 10 , . hFlip = TRUE ) ,
ANIMCMD_JUMP ( 0 )
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnims_Shroomish [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
sAnim_Shroomish
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AnimCmd * const sAnims_Taillow [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
sAnim_Taillow_WingDown_Left , // While gliding in
sAnim_Taillow_WingDown_Right ,
sAnim_Taillow_FlapSlow_Left , // While carrying ball
sAnim_Taillow_FlapSlow_Right ,
sAnim_Taillow_FlapFast_Left , // While flying off
sAnim_Taillow_FlapFast_Right
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplate_Shroomish =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_SHROOMISH_TAILLOW ,
. paletteTag = PALTAG_SHROOMISH ,
. oam = & sOam_Shroomish ,
. anims = sAnims_Shroomish ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
. callback = SpriteCallbackDummy
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplate_Taillow =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_SHROOMISH_TAILLOW ,
. paletteTag = PALTAG_TAILLOW ,
. oam = & sOam_Taillow ,
. anims = sAnims_Taillow ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-07-29 10:46:58 +02:00
. callback = SpriteCB_Taillow
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const struct OamData sOam_ShroomishBallShadow =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 16 x16 ) ,
. size = SPRITE_SIZE ( 16 x16 ) ,
2019-01-02 23:40:40 +01:00
. priority = 2 ,
} ;
2020-08-03 23:31:34 +02:00
static const struct OamData sOam_ShroomishShadow =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_OFF ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 32 x16 ) ,
. size = SPRITE_SIZE ( 32 x16 ) ,
2019-01-02 23:40:40 +01:00
. priority = 2 ,
} ;
2020-07-29 10:46:58 +02:00
static const struct OamData sOam_TaillowShadow =
2019-01-02 23:40:40 +01:00
{
. affineMode = ST_OAM_AFFINE_NORMAL ,
. objMode = ST_OAM_OBJ_NORMAL ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 32 x16 ) ,
. size = SPRITE_SIZE ( 32 x16 ) ,
2019-01-02 23:40:40 +01:00
. priority = 2 ,
} ;
2019-01-02 23:55:50 +01:00
2020-07-29 10:46:58 +02:00
static const struct CompressedSpriteSheet sSpriteSheet_Shadow =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
. data = sShadow_Gfx ,
2019-01-02 23:40:40 +01:00
. size = 0x180 ,
2020-07-29 10:46:58 +02:00
. tag = GFXTAG_SHADOW
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AffineAnimCmd sAffineAnim_Unused3 [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
AFFINEANIMCMD_FRAME ( 0x80 , 0x80 , 0 , 0 ) ,
AFFINEANIMCMD_FRAME ( 2 , 2 , 0 , 60 ) ,
AFFINEANIMCMD_END
} ;
2020-07-29 10:46:58 +02:00
static const union AffineAnimCmd sAffineAnim_TaillowShadow [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
AFFINEANIMCMD_FRAME ( 0x100 , 0x100 , 0 , 0 ) ,
AFFINEANIMCMD_FRAME ( - 2 , 0x0 , 0 , 15 ) ,
AFFINEANIMCMD_FRAME ( - 1 , - 2 , 0 , 15 ) ,
AFFINEANIMCMD_FRAME ( - 1 , - 5 , 0 , 24 ) ,
AFFINEANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AffineAnimCmd * const sAffineAnims_Unused3 [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
sAffineAnim_Unused3
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const union AffineAnimCmd * const sAffineAnims_TaillowShadow [ ] =
2019-03-11 08:12:15 +01:00
{
2020-07-29 10:46:58 +02:00
sAffineAnim_TaillowShadow
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AffineAnimCmd sAffineAnim_Unused4 [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
AFFINEANIMCMD_FRAME ( 0x100 , 0x100 , 0 , 0 ) ,
AFFINEANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AffineAnimCmd * const sAffineAnims_Unused4 [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
sAffineAnim_Unused4
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_ShroomishBallShadow [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 0 , 0 ) ,
ANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd sAnim_UnstickMonShadow [ ] =
2019-03-11 08:12:15 +01:00
{
2019-01-02 23:40:40 +01:00
ANIMCMD_FRAME ( 4 , 0 ) ,
ANIMCMD_END
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnims_ShroomishBallShadow [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
sAnim_ShroomishBallShadow
2019-01-02 23:40:40 +01:00
} ;
2020-08-03 23:31:34 +02:00
static const union AnimCmd * const sAnims_UnstickMonShadow [ ] =
2019-03-11 08:12:15 +01:00
{
2020-08-03 23:31:34 +02:00
sAnim_UnstickMonShadow
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplate_ShroomishShadow [ ] =
2019-01-02 23:40:40 +01:00
{
2020-08-03 23:31:34 +02:00
// Ball's shadow as it flies up
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_SHADOW ,
. paletteTag = PALTAG_SHADOW ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_ShroomishBallShadow ,
. anims = sAnims_ShroomishBallShadow ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
. callback = SpriteCallbackDummy
} ,
2020-08-03 23:31:34 +02:00
// Shroomish's Shadow
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_SHADOW ,
. paletteTag = PALTAG_SHADOW ,
2020-08-03 23:31:34 +02:00
. oam = & sOam_ShroomishShadow ,
. anims = sAnims_UnstickMonShadow ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
2020-08-03 23:31:34 +02:00
. callback = SpriteCB_Shroomish
2019-01-02 23:40:40 +01:00
}
} ;
2020-07-29 10:46:58 +02:00
static const struct SpriteTemplate sSpriteTemplate_TaillowShadow =
2019-01-02 23:40:40 +01:00
{
2020-07-29 10:46:58 +02:00
. tileTag = GFXTAG_SHADOW ,
. paletteTag = PALTAG_SHADOW ,
. oam = & sOam_TaillowShadow ,
2020-08-03 23:31:34 +02:00
. anims = sAnims_UnstickMonShadow ,
2019-01-02 23:40:40 +01:00
. images = NULL ,
2020-07-29 10:46:58 +02:00
. affineAnims = sAffineAnims_TaillowShadow ,
. callback = SpriteCB_Taillow
2019-01-02 23:40:40 +01:00
} ;
2020-07-29 10:46:58 +02:00
static void Task_ShowMinBetYesNo ( u8 taskId )
2019-01-02 23:55:50 +01:00
{
2019-02-27 04:30:40 +01:00
DisplayYesNoMenuDefaultYes ( ) ;
2020-07-29 10:46:58 +02:00
DoYesNoFuncWithChoice ( taskId , & sYesNoTable_AcceptMinBet ) ;
2019-01-02 23:55:50 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_FadeToRouletteGame ( u8 taskId )
2019-01-02 23:55:50 +01:00
{
if ( ! gPaletteFade . active )
{
SetVBlankCallback ( NULL ) ;
2020-07-29 10:46:58 +02:00
SetMainCallback2 ( CB2_LoadRoulette ) ;
2019-01-02 23:55:50 +01:00
DestroyTask ( taskId ) ;
}
}
2020-07-29 10:46:58 +02:00
static void Task_AcceptMinBet ( u8 taskId )
2019-01-02 23:55:50 +01:00
{
2019-02-22 07:40:11 +01:00
ClearStdWindowAndFrame ( 0 , TRUE ) ;
2019-01-02 23:55:50 +01:00
HideCoinsWindow ( ) ;
FreeAllWindowBuffers ( ) ;
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade ( PALETTES_ALL , 0 , 0 , 16 , RGB_BLACK ) ;
2019-01-02 23:55:50 +01:00
gPaletteFade . delayCounter = gPaletteFade . multipurpose2 ;
UpdatePaletteFade ( ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_FadeToRouletteGame ;
2019-01-02 23:55:50 +01:00
}
2020-07-29 10:46:58 +02:00
static void Task_DeclineMinBet ( u8 taskId )
2019-01-02 23:55:50 +01:00
{
2019-02-22 07:40:11 +01:00
ClearStdWindowAndFrame ( 0 , FALSE ) ;
2019-01-02 23:55:50 +01:00
HideCoinsWindow ( ) ;
ScriptContext2_Disable ( ) ;
DestroyTask ( taskId ) ;
}
2020-07-29 10:46:58 +02:00
static void Task_NotEnoughForMinBet ( u8 taskId )
2019-01-02 23:55:50 +01:00
{
gTasks [ taskId ] . data [ 0 ] + + ;
2020-07-29 10:46:58 +02:00
if ( JOY_NEW ( A_BUTTON | B_BUTTON ) )
2019-01-02 23:55:50 +01:00
{
gSpecialVar_0x8004 = 1 ;
HideCoinsWindow ( ) ;
2019-02-22 07:40:11 +01:00
ClearStdWindowAndFrame ( 0 , TRUE ) ;
2019-01-02 23:55:50 +01:00
ScriptContext2_Disable ( ) ;
DestroyTask ( taskId ) ;
}
}
2020-07-29 10:46:58 +02:00
static void Task_PrintMinBet ( u8 taskId )
2019-01-02 23:55:50 +01:00
{
2020-07-29 10:46:58 +02:00
if ( JOY_NEW ( A_BUTTON | B_BUTTON ) )
2019-01-02 23:55:50 +01:00
{
2020-08-03 23:31:34 +02:00
u32 minBet = sTableMinBets [ GET_MIN_BET_ID ( gSpecialVar_0x8004 ) ] ;
2020-07-29 10:46:58 +02:00
ConvertIntToDecimalStringN ( gStringVar1 , minBet , STR_CONV_MODE_LEADING_ZEROS , 1 ) ;
2019-10-07 08:00:16 +02:00
StringExpandPlaceholders ( gStringVar4 , Roulette_Text_PlayMinimumWagerIsX ) ;
2019-02-22 07:40:11 +01:00
DrawStdWindowFrame ( 0 , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( 0 , FONT_NORMAL , gStringVar4 , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2019-01-02 23:55:50 +01:00
CopyWindowToVram ( 0 , 3 ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_ShowMinBetYesNo ;
2019-01-02 23:55:50 +01:00
}
}
2020-07-29 10:46:58 +02:00
static void Task_PrintRouletteEntryMsg ( u8 taskId )
2019-01-02 23:55:50 +01:00
{
2020-07-29 10:46:58 +02:00
s32 minBet ;
PrintCoinsString ( gTasks [ taskId ] . tCoins ) ;
2020-08-03 23:31:34 +02:00
minBet = sTableMinBets [ GET_MIN_BET_ID ( gSpecialVar_0x8004 ) ] ;
2020-07-29 10:46:58 +02:00
ConvertIntToDecimalStringN ( gStringVar1 , minBet , STR_CONV_MODE_LEADING_ZEROS , 1 ) ;
2021-08-25 00:59:32 +02:00
2020-07-29 10:46:58 +02:00
if ( gTasks [ taskId ] . tCoins > = minBet )
2019-01-02 23:55:50 +01:00
{
2020-07-29 10:46:58 +02:00
if ( ( gSpecialVar_0x8004 & ROULETTE_SPECIAL_RATE ) & & ( gSpecialVar_0x8004 & 1 ) )
2019-01-02 23:55:50 +01:00
{
2020-07-29 10:46:58 +02:00
// Special rate for Game Corner service day (only at second table)
2019-02-22 07:40:11 +01:00
DrawStdWindowFrame ( 0 , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( 0 , FONT_NORMAL , Roulette_Text_SpecialRateTable , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2019-01-02 23:55:50 +01:00
CopyWindowToVram ( 0 , 3 ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_PrintMinBet ;
2019-01-02 23:55:50 +01:00
}
else
{
2020-07-29 10:46:58 +02:00
// Print minimum bet
2019-10-07 08:00:16 +02:00
StringExpandPlaceholders ( gStringVar4 , Roulette_Text_PlayMinimumWagerIsX ) ;
2019-02-22 07:40:11 +01:00
DrawStdWindowFrame ( 0 , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( 0 , FONT_NORMAL , gStringVar4 , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2019-01-02 23:55:50 +01:00
CopyWindowToVram ( 0 , 3 ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_ShowMinBetYesNo ;
2019-01-02 23:55:50 +01:00
}
}
else
{
2020-07-29 10:46:58 +02:00
// Not enough for minimum bet
2019-10-07 08:00:16 +02:00
StringExpandPlaceholders ( gStringVar4 , Roulette_Text_NotEnoughCoins ) ;
2019-02-22 07:40:11 +01:00
DrawStdWindowFrame ( 0 , FALSE ) ;
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized ( 0 , FONT_NORMAL , gStringVar4 , 0 , 1 , TEXT_SPEED_FF , NULL ) ;
2019-01-02 23:55:50 +01:00
CopyWindowToVram ( 0 , 3 ) ;
2020-07-29 10:46:58 +02:00
gTasks [ taskId ] . func = Task_NotEnoughForMinBet ;
gTasks [ taskId ] . tCoins = 0 ;
2019-01-02 23:55:50 +01:00
gTasks [ taskId ] . data [ 0 ] = 0 ;
}
}
void PlayRoulette ( void )
{
u8 taskId ;
ScriptContext2_Enable ( ) ;
ShowCoinsWindow ( GetCoins ( ) , 1 , 1 ) ;
2020-07-29 10:46:58 +02:00
taskId = CreateTask ( Task_PrintRouletteEntryMsg , 0 ) ;
gTasks [ taskId ] . tCoins = GetCoins ( ) ;
2019-01-02 23:55:50 +01:00
}
2020-07-29 10:46:58 +02:00
static void LoadOrFreeMiscSpritePalettesAndSheets ( bool8 free )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
if ( ! free )
2019-01-01 01:07:29 +01:00
{
FreeAllSpritePalettes ( ) ;
2020-07-29 10:46:58 +02:00
LoadSpritePalettes ( sSpritePalettes ) ;
LoadCompressedSpriteSheet ( & sSpriteSheet_Ball ) ;
LoadCompressedSpriteSheet ( & sSpriteSheet_ShroomishTaillow ) ;
LoadCompressedSpriteSheet ( & sSpriteSheet_Shadow ) ;
2019-01-01 01:07:29 +01:00
}
else
{
2020-07-29 10:46:58 +02:00
// Unused
FreeSpriteTilesByTag ( GFXTAG_SHADOW ) ;
FreeSpriteTilesByTag ( GFXTAG_SHROOMISH_TAILLOW ) ;
FreeSpriteTilesByTag ( GFXTAG_BALL ) ;
2019-01-01 01:07:29 +01:00
FreeAllSpritePalettes ( ) ;
}
}
2020-08-03 23:31:34 +02:00
static u8 CreateWheelIconSprite ( const struct SpriteTemplate * template , u8 r1 , u16 * angle )
2019-01-01 01:07:29 +01:00
{
u16 temp ;
2020-08-03 23:31:34 +02:00
u8 spriteId = CreateSprite ( template , 116 , 80 , template - > oam - > y ) ;
gSprites [ spriteId ] . data [ 0 ] = * angle ;
2020-07-29 10:46:58 +02:00
gSprites [ spriteId ] . data [ 1 ] = r1 ;
2019-01-01 01:07:29 +01:00
gSprites [ spriteId ] . coordOffsetEnabled = TRUE ;
2020-07-29 10:46:58 +02:00
gSprites [ spriteId ] . animPaused = TRUE ;
gSprites [ spriteId ] . affineAnimPaused = TRUE ;
2020-08-03 23:31:34 +02:00
temp = * angle ;
* angle + = DEGREES_PER_SLOT ;
if ( * angle > = 360 )
* angle = temp - ( 360 - DEGREES_PER_SLOT ) ;
2019-01-01 01:07:29 +01:00
return spriteId ;
}
2020-07-29 10:46:58 +02:00
static void CreateGridSprites ( void )
2019-01-01 01:07:29 +01:00
{
u8 i , j ;
u8 spriteId ;
struct SpriteSheet s ;
2020-07-29 10:46:58 +02:00
LZ77UnCompWram ( sSpriteSheet_Headers . data , gDecompressionBuffer ) ;
2019-01-01 01:07:29 +01:00
s . data = gDecompressionBuffer ;
2020-07-29 10:46:58 +02:00
s . size = sSpriteSheet_Headers . size ;
s . tag = sSpriteSheet_Headers . tag ;
2019-01-01 01:07:29 +01:00
LoadSpriteSheet ( & s ) ;
2020-08-03 23:31:34 +02:00
LZ77UnCompWram ( sSpriteSheet_GridIcons . data , gDecompressionBuffer ) ;
2019-01-01 01:07:29 +01:00
s . data = gDecompressionBuffer ;
2020-08-03 23:31:34 +02:00
s . size = sSpriteSheet_GridIcons . size ;
s . tag = sSpriteSheet_GridIcons . tag ;
2019-01-01 01:07:29 +01:00
LoadSpriteSheet ( & s ) ;
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < NUM_BOARD_COLORS ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-08-03 23:31:34 +02:00
u8 y = i * 24 ;
2020-07-29 10:46:58 +02:00
for ( j = 0 ; j < NUM_BOARD_POKES ; j + + )
2019-01-01 01:07:29 +01:00
{
2020-08-03 23:31:34 +02:00
spriteId = sRoulette - > spriteIds [ ( i * NUM_BOARD_POKES ) + SPR_GRID_ICONS + j ] = CreateSprite ( & sSpriteTemplate_GridIcons [ j ] , ( j * 24 ) + 148 , y + 92 , 30 ) ;
2019-01-01 01:07:29 +01:00
gSprites [ spriteId ] . animPaused = TRUE ;
2020-08-03 23:31:34 +02:00
y + = 24 ;
if ( y > = 72 )
y = 0 ;
2019-01-01 01:07:29 +01:00
}
}
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < ARRAY_COUNT ( sSpriteTemplates_PokeHeaders ) ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
spriteId = sRoulette - > spriteIds [ i + SPR_POKE_HEADERS ] = CreateSprite ( & sSpriteTemplates_PokeHeaders [ i ] , ( i * 24 ) + 148 , 70 , 30 ) ;
2019-01-01 01:07:29 +01:00
gSprites [ spriteId ] . animPaused = TRUE ;
}
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < ARRAY_COUNT ( sSpriteTemplates_ColorHeaders ) ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-08-03 23:31:34 +02:00
spriteId = sRoulette - > spriteIds [ i + SPR_COLOR_HEADERS ] = CreateSprite ( & sSpriteTemplates_ColorHeaders [ i ] , 126 , ( i * 24 ) + 92 , 30 ) ;
2019-01-01 01:07:29 +01:00
gSprites [ spriteId ] . animPaused = TRUE ;
}
}
2020-07-29 10:46:58 +02:00
// Unused
static void DestroyGridSprites ( void )
2019-01-01 01:07:29 +01:00
{
u8 i ;
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < NUM_ROULETTE_SLOTS ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
DestroySprite ( & gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_ICONS ] ] ) ;
2019-01-01 01:07:29 +01:00
}
}
2020-07-29 10:46:58 +02:00
static void ShowHideGridIcons ( bool8 hideAll , u8 hideSquare )
2019-01-01 01:07:29 +01:00
{
u8 i ;
2020-07-29 10:46:58 +02:00
switch ( hideAll )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
case TRUE :
// Hide grid icons and headers
for ( i = 0 ; i < NUM_GRID_SELECTIONS ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_ICONS ] ] . invisible = TRUE ;
2019-01-01 01:07:29 +01:00
}
break ;
2020-07-29 10:46:58 +02:00
case FALSE :
for ( i = 0 ; i < NUM_ROULETTE_SLOTS ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
if ( ! ( sRoulette - > hitFlags & sRouletteSlots [ i ] . flag ) )
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_ICONS ] ] . invisible = FALSE ;
else if ( sRouletteSlots [ i ] . gridSquare ! = hideSquare )
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_ICONS ] ] . invisible = TRUE ;
2019-01-01 01:07:29 +01:00
else
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_ICONS ] ] . invisible = FALSE ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
// Always show grid headers
for ( ; i < NUM_GRID_SELECTIONS ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_ICONS ] ] . invisible = FALSE ;
2019-01-01 01:07:29 +01:00
}
break ;
}
}
2020-07-29 10:46:58 +02:00
static void CreateGridBallSprites ( void )
2019-01-01 01:07:29 +01:00
{
u8 i ;
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < BALLS_PER_ROUND ; i + + )
{
2020-08-03 23:31:34 +02:00
sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] = CreateSprite ( & sSpriteTemplate_Ball , 116 , 20 , 10 ) ;
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] ] . invisible = TRUE ;
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] ] . data [ 0 ] = 1 ;
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] ] . callback = SpriteCB_GridSquare ;
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] ] . oam . priority = 1 ;
StartSpriteAnim ( & gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] ] , 8 ) ;
2019-01-01 01:07:29 +01:00
}
}
2020-07-29 10:46:58 +02:00
static void ShowHideGridBalls ( bool8 hideAll , u8 hideBallId )
2019-01-01 01:07:29 +01:00
{
u8 i = 0 ;
2020-07-29 10:46:58 +02:00
if ( hideAll )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
for ( ; i < BALLS_PER_ROUND ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-08-03 23:31:34 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] ] . invisible = TRUE ;
2019-01-01 01:07:29 +01:00
}
}
else
{
2020-07-29 10:46:58 +02:00
for ( ; i < BALLS_PER_ROUND ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
if ( ! sRoulette - > hitSquares [ i ] | | i = = hideBallId )
2019-01-01 01:07:29 +01:00
{
2020-08-03 23:31:34 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] ] . invisible = TRUE ;
2019-01-01 01:07:29 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] ] . invisible = FALSE ;
2021-07-07 15:11:52 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] ] . x = ( sGridSelections [ sRoulette - > hitSquares [ i ] ] . x + 1 ) * 8 + 4 ;
gSprites [ sRoulette - > spriteIds [ i + SPR_GRID_BALLS ] ] . y = ( sGridSelections [ sRoulette - > hitSquares [ i ] ] . y + 1 ) * 8 + 3 ;
2019-01-01 01:07:29 +01:00
}
}
}
}
2020-07-29 10:46:58 +02:00
static void ShowHideWinSlotCursor ( u8 selectionId )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
if ( selectionId = = 0 )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_WIN_SLOT_CURSOR ] ] . invisible = TRUE ;
2019-01-01 01:07:29 +01:00
}
else
{
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_WIN_SLOT_CURSOR ] ] . invisible = FALSE ;
2021-07-07 15:11:52 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_WIN_SLOT_CURSOR ] ] . x = ( sGridSelections [ selectionId ] . x + 2 ) * 8 ;
gSprites [ sRoulette - > spriteIds [ SPR_WIN_SLOT_CURSOR ] ] . y = ( sGridSelections [ selectionId ] . y + 2 ) * 8 ;
2019-01-01 01:07:29 +01:00
}
}
2020-08-03 23:31:34 +02:00
static void CreateWheelIconSprites ( void )
2019-01-01 01:07:29 +01:00
{
u8 i , j ;
2020-08-03 23:31:34 +02:00
u16 angle ;
2019-01-01 01:07:29 +01:00
struct SpriteSheet s ;
2020-08-03 23:31:34 +02:00
LZ77UnCompWram ( sSpriteSheet_WheelIcons . data , gDecompressionBuffer ) ;
2019-01-01 01:07:29 +01:00
s . data = gDecompressionBuffer ;
2020-08-03 23:31:34 +02:00
s . size = sSpriteSheet_WheelIcons . size ;
s . tag = sSpriteSheet_WheelIcons . tag ;
2019-01-01 01:07:29 +01:00
LoadSpriteSheet ( & s ) ;
2020-08-03 23:31:34 +02:00
angle = 15 ;
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < NUM_BOARD_COLORS ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
for ( j = 0 ; j < NUM_BOARD_POKES ; j + + )
2019-01-01 01:07:29 +01:00
{
u8 spriteId ;
2020-08-03 23:31:34 +02:00
spriteId = sRoulette - > spriteIds [ ( i * NUM_BOARD_POKES ) + SPR_WHEEL_ICONS + j ] = CreateWheelIconSprite ( & sSpriteTemplates_WheelIcons [ i * NUM_BOARD_POKES + j ] , 40 , & angle ) ;
2019-01-01 01:07:29 +01:00
gSprites [ spriteId ] . animPaused = TRUE ;
gSprites [ spriteId ] . affineAnimPaused = TRUE ;
}
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_WheelIcon ( struct Sprite * sprite )
2019-01-01 01:07:29 +01:00
{
s16 cos ;
s16 sin ;
u32 matrixNum ;
2020-07-31 20:55:42 +02:00
s16 angle = sRoulette - > wheelAngle + sprite - > data [ 0 ] ;
2019-01-01 01:07:29 +01:00
if ( angle > = 360 )
angle - = 360 ;
sin = Sin2 ( angle ) ;
cos = Cos2 ( angle ) ;
2021-07-07 15:11:52 +02:00
sprite - > x2 = sin * sprite - > data [ 1 ] > > 12 ;
sprite - > y2 = - cos * sprite - > data [ 1 ] > > 12 ;
2019-01-01 01:07:29 +01:00
matrixNum = sprite - > oam . matrixNum ;
sin / = 16 ;
gOamMatrices [ matrixNum ] . d = cos / = 16 ;
gOamMatrices [ matrixNum ] . a = cos ;
gOamMatrices [ matrixNum ] . b = sin ;
gOamMatrices [ matrixNum ] . c = - sin ;
}
2020-07-29 10:46:58 +02:00
static void CreateInterfaceSprites ( void )
2019-01-01 01:07:29 +01:00
{
u8 i ;
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < ARRAY_COUNT ( sSpriteSheets_Interface ) - 1 ; i + + )
2019-01-01 01:07:29 +01:00
{
struct SpriteSheet s ;
2020-07-29 10:46:58 +02:00
LZ77UnCompWram ( sSpriteSheets_Interface [ i ] . data , gDecompressionBuffer ) ;
2019-01-01 01:07:29 +01:00
s . data = gDecompressionBuffer ;
2020-07-29 10:46:58 +02:00
s . size = sSpriteSheets_Interface [ i ] . size ;
s . tag = sSpriteSheets_Interface [ i ] . tag ;
2019-01-01 01:07:29 +01:00
LoadSpriteSheet ( & s ) ;
}
2020-07-29 10:46:58 +02:00
sRoulette - > spriteIds [ SPR_CREDIT ] = CreateSprite ( & sSpriteTemplate_Credit , 208 , 16 , 4 ) ;
gSprites [ sRoulette - > spriteIds [ SPR_CREDIT ] ] . animPaused = TRUE ;
for ( i = 0 ; i < MAX_COIN_DIGITS ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
sRoulette - > spriteIds [ i + SPR_CREDIT_DIGITS ] = CreateSprite ( & sSpriteTemplate_CreditDigit , i * 8 + 196 , 24 , 0 ) ;
gSprites [ sRoulette - > spriteIds [ i + SPR_CREDIT_DIGITS ] ] . invisible = TRUE ;
gSprites [ sRoulette - > spriteIds [ i + SPR_CREDIT_DIGITS ] ] . animPaused = TRUE ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
sRoulette - > spriteIds [ SPR_MULTIPLIER ] = CreateSprite ( & sSpriteTemplate_Multiplier , 120 , 68 , 4 ) ;
gSprites [ sRoulette - > spriteIds [ SPR_MULTIPLIER ] ] . animPaused = TRUE ;
for ( i = 0 ; i < BALLS_PER_ROUND / 2 ; i + + )
{
// Each ball counter sprite has 2 balls
2020-07-31 20:55:42 +02:00
sRoulette - > spriteIds [ i + SPR_BALL_COUNTER ] = CreateSprite ( & sSpriteTemplate_BallCounter , i * 16 + 192 , 36 , 4 ) ;
gSprites [ sRoulette - > spriteIds [ i + SPR_BALL_COUNTER ] ] . invisible = TRUE ;
gSprites [ sRoulette - > spriteIds [ i + SPR_BALL_COUNTER ] ] . animPaused = TRUE ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
sRoulette - > spriteIds [ SPR_WIN_SLOT_CURSOR ] = CreateSprite ( & sSpriteTemplate_Cursor , 152 , 96 , 9 ) ;
gSprites [ sRoulette - > spriteIds [ SPR_WIN_SLOT_CURSOR ] ] . oam . priority = 1 ;
gSprites [ sRoulette - > spriteIds [ SPR_WIN_SLOT_CURSOR ] ] . animPaused = TRUE ;
gSprites [ sRoulette - > spriteIds [ SPR_WIN_SLOT_CURSOR ] ] . invisible = TRUE ;
2019-01-01 01:07:29 +01:00
}
2020-07-31 20:55:42 +02:00
static void SetCreditDigits ( u16 num )
2019-01-01 01:07:29 +01:00
{
u8 i ;
u16 d = 1000 ;
2020-07-31 20:55:42 +02:00
bool8 printZero = FALSE ;
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < MAX_COIN_DIGITS ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
u8 digit = num / d ;
gSprites [ sRoulette - > spriteIds [ i + SPR_CREDIT_DIGITS ] ] . invisible = TRUE ;
if ( digit > 0 | | printZero | | i = = MAX_COIN_DIGITS - 1 )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_CREDIT_DIGITS ] ] . invisible = FALSE ;
gSprites [ sRoulette - > spriteIds [ i + SPR_CREDIT_DIGITS ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ i + SPR_CREDIT_DIGITS ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ i + SPR_CREDIT_DIGITS ] ] . anims + digit ) - > type ;
printZero = TRUE ;
2019-01-01 01:07:29 +01:00
}
2020-07-31 20:55:42 +02:00
num = num % d ;
2019-01-01 01:07:29 +01:00
d = d / 10 ;
}
}
2020-07-29 10:46:58 +02:00
// Identical to GetMultiplier but with different data array
static u8 GetMultiplierAnimId ( u8 selectionId )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
u8 animIds [ 5 ] = { 0 , 1 , 2 , 3 , 4 } ;
2019-01-02 23:40:40 +01:00
2020-07-29 10:46:58 +02:00
if ( selectionId > NUM_GRID_SELECTIONS )
selectionId = 0 ;
switch ( sGridSelections [ selectionId ] . baseMultiplier )
2019-01-01 01:07:29 +01:00
{
2020-07-29 10:46:58 +02:00
case NUM_BOARD_COLORS :
2020-07-31 20:55:42 +02:00
selectionId = GET_ROW_IDX ( selectionId ) ;
2020-07-29 10:46:58 +02:00
if ( sRoulette - > colorHits [ selectionId ] > 3 )
2019-01-01 01:07:29 +01:00
return 0 ;
2020-07-29 10:46:58 +02:00
return animIds [ sRoulette - > colorHits [ selectionId ] + 1 ] ;
case NUM_BOARD_POKES :
2020-07-31 20:55:42 +02:00
selectionId = GET_COL_IDX ( selectionId ) ;
2020-07-29 10:46:58 +02:00
if ( sRoulette - > pokeHits [ selectionId ] > 2 )
2019-01-01 01:07:29 +01:00
return 0 ;
2020-07-29 10:46:58 +02:00
return animIds [ sRoulette - > pokeHits [ selectionId ] + 2 ] ;
case NUM_ROULETTE_SLOTS :
if ( sRoulette - > hitFlags & sGridSelections [ selectionId ] . flag )
2019-01-01 01:07:29 +01:00
return 0 ;
2020-07-29 10:46:58 +02:00
return animIds [ 4 ] ;
2019-01-01 01:07:29 +01:00
}
return 0 ;
}
2020-07-29 10:46:58 +02:00
static void SetMultiplierSprite ( u8 selectionId )
2019-01-01 01:07:29 +01:00
{
2020-08-03 23:31:34 +02:00
struct Sprite * sprite = & gSprites [ sRoulette - > spriteIds [ SPR_MULTIPLIER ] ] ;
sprite - > animCmdIndex = GetMultiplierAnimId ( selectionId ) ;
sprite - > oam . tileNum = sprite - > sheetTileStart + ( * sprite - > anims + sprite - > animCmdIndex ) - > type ;
2019-01-01 01:07:29 +01:00
}
2020-07-29 10:46:58 +02:00
static void SetBallCounterNumLeft ( u8 numBalls )
2019-01-01 01:07:29 +01:00
{
u8 i ;
u8 t = 0 ;
2020-07-29 10:46:58 +02:00
if ( sRoulette - > minBet = = 1 )
2019-01-01 01:07:29 +01:00
t = 2 ;
2020-07-29 10:46:58 +02:00
switch ( numBalls )
2019-01-01 01:07:29 +01:00
{
case 6 :
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < BALLS_PER_ROUND / 2 ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_BALL_COUNTER ] ] . invisible = FALSE ;
gSprites [ sRoulette - > spriteIds [ i + SPR_BALL_COUNTER ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ i + SPR_BALL_COUNTER ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ i + SPR_BALL_COUNTER ] ] . anims ) - > type ;
2019-01-01 01:07:29 +01:00
}
break ;
case 5 :
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_3 ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_3 ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_3 ] ] . anims + t + 1 ) - > type ;
2019-01-01 01:07:29 +01:00
break ;
case 4 :
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_3 ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_3 ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_3 ] ] . anims + t + 2 ) - > type ;
2019-01-01 01:07:29 +01:00
break ;
case 3 :
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_2 ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_2 ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_2 ] ] . anims + t + 1 ) - > type ;
2019-01-01 01:07:29 +01:00
break ;
case 2 :
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_2 ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_2 ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_2 ] ] . anims + t + 2 ) - > type ;
2019-01-01 01:07:29 +01:00
break ;
case 1 :
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_1 ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_1 ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ SPR_BALL_COUNTER_1 ] ] . anims + t + 1 ) - > type ;
2019-01-01 01:07:29 +01:00
break ;
case 0 :
default :
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < BALLS_PER_ROUND / 2 ; i + + )
2019-01-01 01:07:29 +01:00
{
2020-07-31 20:55:42 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_BALL_COUNTER ] ] . oam . tileNum =
gSprites [ sRoulette - > spriteIds [ i + SPR_BALL_COUNTER ] ] . sheetTileStart
+ ( * gSprites [ sRoulette - > spriteIds [ i + SPR_BALL_COUNTER ] ] . anims + t + 2 ) - > type ;
2019-01-01 01:07:29 +01:00
}
}
}
2019-01-01 02:39:41 +01:00
2020-07-29 10:46:58 +02:00
static void SpriteCB_GridSquare ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2021-07-07 15:11:52 +02:00
sprite - > x2 = sRoulette - > gridX ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
static void CreateWheelCenterSprite ( void )
2019-01-01 02:39:41 +01:00
{
u8 spriteId ;
struct SpriteSheet s ;
2020-08-03 23:31:34 +02:00
LZ77UnCompWram ( sSpriteSheet_WheelCenter . data , gDecompressionBuffer ) ;
2019-01-01 02:39:41 +01:00
s . data = gDecompressionBuffer ;
2020-08-03 23:31:34 +02:00
s . size = sSpriteSheet_WheelCenter . size ;
s . tag = sSpriteSheet_WheelCenter . tag ;
2019-01-01 02:39:41 +01:00
LoadSpriteSheet ( & s ) ;
2020-08-03 23:31:34 +02:00
// This sprite id isn't saved because it doesn't need to be referenced again
// but by virtue of creation order it's SPR_WHEEL_CENTER
spriteId = CreateSprite ( & sSpriteTemplate_WheelCenter , 116 , 80 , 81 ) ;
2020-07-31 20:55:42 +02:00
gSprites [ spriteId ] . data [ 0 ] = sRoulette - > wheelAngle ;
2019-01-01 02:39:41 +01:00
gSprites [ spriteId ] . data [ 1 ] = 0 ;
gSprites [ spriteId ] . animPaused = TRUE ;
gSprites [ spriteId ] . affineAnimPaused = TRUE ;
gSprites [ spriteId ] . coordOffsetEnabled = TRUE ;
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_WheelCenter ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
u32 matrixNum = sprite - > oam . matrixNum ;
struct OamMatrix * matrix = & gOamMatrices [ 0 ] ;
matrix [ matrixNum ] . d = sRoulette - > wheelRotation . a ;
matrix [ matrixNum ] . a = sRoulette - > wheelRotation . a ;
matrix [ matrixNum ] . b = sRoulette - > wheelRotation . b ;
matrix [ matrixNum ] . c = sRoulette - > wheelRotation . c ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
static void CreateWheelBallSprites ( void )
2019-01-01 02:39:41 +01:00
{
u8 i ;
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < BALLS_PER_ROUND ; i + + )
2019-01-01 02:39:41 +01:00
{
2020-07-29 10:46:58 +02:00
sRoulette - > spriteIds [ i ] = CreateSprite ( & sSpriteTemplate_Ball , 116 , 80 , 57 - i ) ;
if ( sRoulette - > spriteIds [ i ] ! = MAX_SPRITES )
2019-01-01 02:39:41 +01:00
{
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ i ] ] . invisible = TRUE ;
gSprites [ sRoulette - > spriteIds [ i ] ] . coordOffsetEnabled = TRUE ;
2019-01-01 02:39:41 +01:00
}
}
}
2020-08-03 23:31:34 +02:00
static void HideWheelBalls ( void )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
u8 spriteId = sRoulette - > spriteIds [ SPR_WHEEL_BALLS ] ;
2019-01-01 02:39:41 +01:00
u8 i ;
2020-07-29 10:46:58 +02:00
for ( i = 0 ; i < BALLS_PER_ROUND ; i + + )
2019-01-01 02:39:41 +01:00
{
u8 j ;
2020-07-31 20:55:42 +02:00
gSprites [ spriteId ] . invisible = TRUE ;
gSprites [ spriteId ] . callback = & SpriteCallbackDummy ;
StartSpriteAnim ( & gSprites [ spriteId ] , 0 ) ;
2019-01-01 02:39:41 +01:00
for ( j = 0 ; j < 8 ; j + + )
2020-07-31 20:55:42 +02:00
gSprites [ spriteId ] . data [ j ] = 0 ;
spriteId + + ;
2019-01-01 02:39:41 +01:00
}
}
2020-08-03 23:31:34 +02:00
// Sprite data for the roulette ball
# define sStuckOnWheelLeft data[0] // if true, ball got stuck in left half of wheel, else got stuck in right half
# define sState data[1]
# define sSlotMidpointDist data[2]
# define sBallAngle data[3]
# define sBallDistToCenter data[4]
# define sBallWheelAngle data[6]
# define LandBall() \
{ \
sRoulette - > ballState = BALL_STATE_LANDED ; \
sRoulette - > ballRolling = FALSE ; \
StartSpriteAnim ( sprite , sprite - > animCmdIndex + 3 ) ; \
UpdateSlotBelowBall ( sprite ) ; \
sprite - > sBallDistToCenter = 30 ; \
UpdateBallRelativeWheelAngle ( sprite ) ; \
sprite - > sBallWheelAngle = ( sprite - > sBallWheelAngle / DEGREES_PER_SLOT ) * DEGREES_PER_SLOT + 15 ; \
sprite - > callback = SpriteCB_BallLandInSlot ; \
2020-08-21 00:02:00 +02:00
m4aSongNumStartOrChange ( SE_BRIDGE_WALK ) ; \
2020-08-03 23:31:34 +02:00
}
// "wheelAngle" and "sBallAngle" are relative to the screen (e.g. 180 degrees for either is always screen bottom)
// "sBallWheelAngle" is the ball's angle relative to the wheel
// e.g. if the ball is screen right (90), but wheel is upside down (180), sBallWheelAngle is 270 (because the ball is wheel left)
static s16 UpdateBallRelativeWheelAngle ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > wheelAngle > sprite - > sBallAngle )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
sprite - > sBallWheelAngle = 360 - sRoulette - > wheelAngle + sprite - > sBallAngle ;
if ( sprite - > sBallWheelAngle > = 360 )
sprite - > sBallWheelAngle - = 360 ;
2019-01-01 02:39:41 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
sprite - > sBallWheelAngle = sprite - > sBallAngle - sRoulette - > wheelAngle ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
return sprite - > sBallWheelAngle ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
static u8 UpdateSlotBelowBall ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2021-05-01 07:41:27 +02:00
sRoulette - > hitSlot = UpdateBallRelativeWheelAngle ( sprite ) / ( f32 ) DEGREES_PER_SLOT ;
2020-07-31 20:55:42 +02:00
return sRoulette - > hitSlot ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
static s16 GetBallDistanceToSlotMidpoint ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
s16 angleIntoSlot = UpdateBallRelativeWheelAngle ( sprite ) % DEGREES_PER_SLOT ;
u16 distanceToMidpoint ;
if ( angleIntoSlot = = SLOT_MIDPOINT )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
// Ball is at midpoint, ok to drop into slot
distanceToMidpoint = 0 ;
return sprite - > sSlotMidpointDist = distanceToMidpoint ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
else if ( angleIntoSlot > = SLOT_MIDPOINT )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
// Ball has passed midpoint, travel to midpoint of next slot
distanceToMidpoint = ( DEGREES_PER_SLOT - 1 ) + SLOT_MIDPOINT - angleIntoSlot ;
return sprite - > sSlotMidpointDist = distanceToMidpoint ;
2019-01-01 02:39:41 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
// Ball hasn't reached midpoint of this slot yet
distanceToMidpoint = SLOT_MIDPOINT - angleIntoSlot ;
return sprite - > sSlotMidpointDist = distanceToMidpoint ;
2019-01-01 02:39:41 +01:00
}
}
2020-08-03 23:31:34 +02:00
static void UpdateBallPos ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
s16 sin , cos ;
2020-08-03 23:31:34 +02:00
sRoulette - > ballAngleSpeed + = sRoulette - > ballAngleAccel ;
sRoulette - > ballAngle + = sRoulette - > ballAngleSpeed ;
if ( sRoulette - > ballAngle > = 360 )
sRoulette - > ballAngle - = 360.0f ;
else if ( sRoulette - > ballAngle < 0.0f )
sRoulette - > ballAngle + = 360.0f ;
sprite - > sBallAngle = sRoulette - > ballAngle ;
sRoulette - > ballFallSpeed + = sRoulette - > ballFallAccel ;
sRoulette - > ballDistToCenter + = sRoulette - > ballFallSpeed ;
sprite - > sBallDistToCenter = sRoulette - > ballDistToCenter ;
sin = Sin2 ( sprite - > sBallAngle ) ;
cos = Cos2 ( sprite - > sBallAngle ) ;
2021-07-07 15:11:52 +02:00
sprite - > x2 = sin * sprite - > sBallDistToCenter > > 12 ;
sprite - > y2 = - cos * sprite - > sBallDistToCenter > > 12 ;
2019-01-01 02:39:41 +01:00
if ( IsSEPlaying ( ) )
{
2021-10-09 17:33:37 +02:00
m4aMPlayPanpotControl ( & gMPlayInfo_SE1 , TRACKS_ALL , sprite - > x2 ) ;
m4aMPlayPanpotControl ( & gMPlayInfo_SE2 , TRACKS_ALL , sprite - > x2 ) ;
2019-01-01 02:39:41 +01:00
}
}
2020-08-03 23:31:34 +02:00
// Snap to the bottom of the slot and continue to spin with the wheel
static void SpriteCB_BallLandInSlot ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
s16 sin , cos ;
2020-08-03 23:31:34 +02:00
sprite - > sBallAngle = sRoulette - > wheelAngle + sprite - > sBallWheelAngle ;
if ( sprite - > sBallAngle > = 360 )
sprite - > sBallAngle - = 360 ;
sin = Sin2 ( sprite - > sBallAngle ) ;
cos = Cos2 ( sprite - > sBallAngle ) ;
2021-07-07 15:11:52 +02:00
sprite - > x2 = sin * sprite - > sBallDistToCenter > > 12 ;
sprite - > y2 = - cos * sprite - > sBallDistToCenter > > 12 ;
sprite - > y2 + = gSpriteCoordOffsetY ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_UnstickBall_ShroomishBallFall ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
UpdateBallPos ( sprite ) ;
2019-01-01 02:39:41 +01:00
sprite - > data [ 2 ] + + ;
2020-08-03 23:31:34 +02:00
if ( sprite - > sBallDistToCenter < - 132 | | sprite - > sBallDistToCenter > 80 )
2019-01-01 02:39:41 +01:00
sprite - > invisible = TRUE ;
else
sprite - > invisible = FALSE ;
2020-08-03 23:31:34 +02:00
if ( sprite - > data [ 2 ] > = DEGREES_PER_SLOT )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
if ( ! sprite - > sStuckOnWheelLeft )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ballDistToCenter < = sRoulette - > varA0 - 2.0f )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
LandBall ( )
sRoulette - > ballFallAccel = sRoulette - > ballFallSpeed = 0.0f ;
sRoulette - > ballAngleSpeed = - 1.0f ;
2019-01-01 02:39:41 +01:00
}
}
else
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ballDistToCenter > = sRoulette - > varA0 - 2.0f )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
LandBall ( )
sRoulette - > ballFallAccel = sRoulette - > ballFallSpeed = 0.0f ;
sRoulette - > ballAngleSpeed = - 1.0f ;
2019-01-01 02:39:41 +01:00
}
}
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_UnstickBall_Shroomish ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2021-05-01 07:41:27 +02:00
f32 slotOffset , ballFallDist , ballFallSpeed ;
2020-08-03 23:31:34 +02:00
UpdateBallPos ( sprite ) ;
2019-01-01 02:39:41 +01:00
2020-08-03 23:31:34 +02:00
switch ( sprite - > sBallAngle )
2019-01-01 02:39:41 +01:00
{
case 0 :
2020-08-03 23:31:34 +02:00
if ( sprite - > sStuckOnWheelLeft ! = TRUE )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
slotOffset = sprite - > data [ 7 ] ;
ballFallDist = ( slotOffset * sRouletteTables [ sRoulette - > tableId ] . randDistanceHigh + ( sRouletteTables [ sRoulette - > tableId ] . randDistanceLow - 1 ) ) ;
ballFallSpeed = ( slotOffset / sRouletteTables [ sRoulette - > tableId ] . shroomish . fallSlowdown ) ;
2019-01-01 02:39:41 +01:00
}
else
{
return ;
}
break ;
case 180 :
2020-08-03 23:31:34 +02:00
if ( sprite - > sStuckOnWheelLeft )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
slotOffset = sprite - > data [ 7 ] ;
ballFallDist = ( slotOffset * sRouletteTables [ sRoulette - > tableId ] . randDistanceHigh + ( sRouletteTables [ sRoulette - > tableId ] . randDistanceLow - 1 ) ) ;
ballFallSpeed = - ( slotOffset / sRouletteTables [ sRoulette - > tableId ] . shroomish . fallSlowdown ) ;
2019-01-01 02:39:41 +01:00
}
else
{
return ;
}
break ;
default :
return ;
}
2020-08-03 23:31:34 +02:00
sRoulette - > varA0 = sRoulette - > ballDistToCenter ;
sRoulette - > ballFallSpeed = ballFallSpeed ;
sRoulette - > ballFallAccel = - ( ( ballFallSpeed * 2.0f ) / ballFallDist + ( 2.0f / ( ballFallDist * ballFallDist ) ) ) ;
sRoulette - > ballAngleSpeed = 0.0f ;
2019-01-01 02:39:41 +01:00
sprite - > animPaused = FALSE ;
sprite - > animNum = 0 ;
sprite - > animBeginning = TRUE ;
sprite - > animEnded = FALSE ;
2020-08-03 23:31:34 +02:00
sprite - > callback = SpriteCB_UnstickBall_ShroomishBallFall ;
2019-01-01 02:39:41 +01:00
sprite - > data [ 2 ] = 0 ;
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_UnstickBall_TaillowDrop ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2021-07-07 15:11:52 +02:00
sprite - > y2 = ( s16 ) ( sprite - > data [ 2 ] * 0.05f * sprite - > data [ 2 ] ) - 45 ;
2019-01-01 02:39:41 +01:00
sprite - > data [ 2 ] + + ;
2021-07-07 15:11:52 +02:00
if ( sprite - > data [ 2 ] > = DEGREES_PER_SLOT & & sprite - > y2 > = 0 )
2020-08-03 23:31:34 +02:00
{
LandBall ( )
2020-07-31 20:55:42 +02:00
sRoulette - > ballUnstuck = TRUE ;
2019-01-01 02:39:41 +01:00
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_UnstickBall_TaillowPickUp ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
if ( sprite - > data [ 2 ] + + < 45 )
{
2021-07-07 15:11:52 +02:00
sprite - > y2 - - ;
2019-01-01 02:39:41 +01:00
if ( sprite - > data [ 2 ] = = 45 )
{
2020-07-29 10:46:58 +02:00
if ( gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON ] ] . animCmdIndex = = 1 )
2021-07-07 15:11:52 +02:00
sprite - > y2 + + ;
2019-01-01 02:39:41 +01:00
}
}
else
{
if ( sprite - > data [ 2 ] < sprite - > data [ 7 ] )
{
2020-07-29 10:46:58 +02:00
if ( gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON ] ] . animDelayCounter = = 0 )
2019-01-01 02:39:41 +01:00
{
2020-07-29 10:46:58 +02:00
if ( gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON ] ] . animCmdIndex = = 1 )
2021-07-07 15:11:52 +02:00
sprite - > y2 + + ;
2019-01-01 02:39:41 +01:00
else
2021-07-07 15:11:52 +02:00
sprite - > y2 - - ;
2019-01-01 02:39:41 +01:00
}
}
else
{
sprite - > animPaused = FALSE ;
sprite - > animNum = 1 ;
sprite - > animBeginning = TRUE ;
sprite - > animEnded = FALSE ;
sprite - > data [ 2 ] = 0 ;
2020-08-03 23:31:34 +02:00
sprite - > callback = SpriteCB_UnstickBall_TaillowDrop ;
2020-08-21 00:02:00 +02:00
m4aSongNumStart ( SE_BALL_THROW ) ;
2019-01-01 02:39:41 +01:00
}
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_UnstickBall_Taillow ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
UpdateBallPos ( sprite ) ;
switch ( sprite - > sBallAngle )
2019-01-01 02:39:41 +01:00
{
case 90 :
2020-08-03 23:31:34 +02:00
if ( sprite - > sStuckOnWheelLeft ! = TRUE )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
sprite - > callback = & SpriteCB_UnstickBall_TaillowPickUp ;
2019-01-01 02:39:41 +01:00
sprite - > data [ 2 ] = 0 ;
}
break ;
case 270 :
2020-08-03 23:31:34 +02:00
if ( sprite - > sStuckOnWheelLeft )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
sprite - > callback = & SpriteCB_UnstickBall_TaillowPickUp ;
2019-01-01 02:39:41 +01:00
sprite - > data [ 2 ] = 0 ;
}
break ;
}
}
2020-08-03 23:31:34 +02:00
// The below SpriteCB_UnstickBall_* callbacks handle the ball while its being cleared by Shroomish/Taillow
// For what Shroomish/Taillow do during this sequence, see SpriteCB_Shroomish / SpriteCB_Taillow
static void SpriteCB_UnstickBall ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
UpdateBallPos ( sprite ) ;
2020-07-29 10:46:58 +02:00
switch ( sRoulette - > useTaillow )
2019-01-01 02:39:41 +01:00
{
default :
2020-07-29 10:46:58 +02:00
case FALSE :
CreateShroomishSprite ( sprite ) ;
2020-08-03 23:31:34 +02:00
sprite - > callback = SpriteCB_UnstickBall_Shroomish ;
2019-01-01 02:39:41 +01:00
break ;
2020-07-29 10:46:58 +02:00
case TRUE :
CreateTaillowSprite ( sprite ) ;
2020-08-03 23:31:34 +02:00
sprite - > callback = SpriteCB_UnstickBall_Taillow ;
2019-01-01 02:39:41 +01:00
break ;
}
}
2020-08-03 23:31:34 +02:00
# define sStillStuck data[0]
static void SpriteCB_RollBall_TryLandAdjacent ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
UpdateBallPos ( sprite ) ;
2019-01-01 02:39:41 +01:00
if ( sprite - > data [ 2 ] - - = = 16 )
2020-08-03 23:31:34 +02:00
sRoulette - > ballFallSpeed * = - 1.0f ;
2019-01-01 02:39:41 +01:00
if ( sprite - > data [ 2 ] = = 0 )
{
2020-08-03 23:31:34 +02:00
if ( ! sprite - > sStillStuck )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
// Ball can successfully fall into adjacent space
LandBall ( )
2019-01-01 02:39:41 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
// Ball is stuck, need Shroomish/Taillow to clear ball
2019-01-01 02:39:41 +01:00
sprite - > animPaused = TRUE ;
2020-08-21 00:02:00 +02:00
m4aSongNumStart ( SE_BALL_BOUNCE_1 ) ;
2020-08-03 23:31:34 +02:00
SetBallStuck ( sprite ) ;
2019-01-01 02:39:41 +01:00
}
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_RollBall_TryLand ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
UpdateBallPos ( sprite ) ;
2019-01-01 02:39:41 +01:00
sprite - > data [ 2 ] = 0 ;
2020-08-03 23:31:34 +02:00
UpdateSlotBelowBall ( sprite ) ;
2020-07-31 20:55:42 +02:00
if ( ! ( sRouletteSlots [ sRoulette - > hitSlot ] . flag & sRoulette - > hitFlags ) )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
// Space is empty, land successfully
LandBall ( )
2019-01-01 02:39:41 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
// Space has already been landed on, try to fall into adjacent space
2020-07-29 10:46:58 +02:00
u8 slotId ;
2020-08-03 23:31:34 +02:00
u32 fallRight ;
2020-08-21 00:02:00 +02:00
m4aSongNumStart ( SE_BALL_BOUNCE_1 ) ;
2020-08-03 23:31:34 +02:00
fallRight = Random ( ) & 1 ;
if ( fallRight )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
sRoulette - > ballAngleSpeed = 0.0f ;
sRoulette - > stuckHitSlot = slotId = ( sRoulette - > hitSlot + 1 ) % NUM_ROULETTE_SLOTS ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
else // fall left
2019-01-01 02:39:41 +01:00
{
2021-05-01 07:41:27 +02:00
f32 temp ;
2020-08-03 23:31:34 +02:00
sRoulette - > ballAngleSpeed = ( temp = sRouletteTables [ sRoulette - > tableId ] . var1C ) * 2.0f ;
2020-07-31 20:55:42 +02:00
slotId = ( sRoulette - > hitSlot + NUM_ROULETTE_SLOTS - 1 ) % NUM_ROULETTE_SLOTS ;
2020-08-03 23:31:34 +02:00
sRoulette - > stuckHitSlot = sRoulette - > hitSlot ;
2019-01-01 02:39:41 +01:00
}
2020-07-29 10:46:58 +02:00
if ( sRouletteSlots [ slotId ] . flag & sRoulette - > hitFlags )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
// Attempted adjacent space has also been landed on
sprite - > sStillStuck = TRUE ;
sprite - > data [ 2 ] = sRouletteTables [ sRoulette - > tableId ] . randDistanceLow ;
2019-01-01 02:39:41 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
sprite - > sStillStuck = FALSE ;
2020-07-29 10:46:58 +02:00
if ( sRoulette - > tableId )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
sprite - > data [ 2 ] = sRouletteTables [ sRoulette - > tableId ] . randDistanceHigh ;
2019-01-01 02:39:41 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
sprite - > data [ 2 ] = sRouletteTables [ sRoulette - > tableId ] . randDistanceLow ;
if ( fallRight )
sRoulette - > ballAngleSpeed = 0.5f ;
2019-01-01 02:39:41 +01:00
else
2020-08-03 23:31:34 +02:00
sRoulette - > ballAngleSpeed = - 1.5f ;
2019-01-01 02:39:41 +01:00
}
}
2020-08-03 23:31:34 +02:00
sRoulette - > ballFallSpeed = 0.085f ;
sprite - > callback = SpriteCB_RollBall_TryLandAdjacent ;
sprite - > sState = 5 ;
2019-01-01 02:39:41 +01:00
}
}
2020-08-03 23:31:34 +02:00
# undef sStillStuck
static void SpriteCB_RollBall_Slow ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
UpdateBallPos ( sprite ) ;
if ( sRoulette - > ballAngleSpeed > 0.5f )
2019-01-01 02:39:41 +01:00
return ;
2020-08-03 23:31:34 +02:00
UpdateSlotBelowBall ( sprite ) ;
if ( GetBallDistanceToSlotMidpoint ( sprite ) = = 0 )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
// Reached slot to land in
sRoulette - > ballAngleAccel = 0.0f ;
2021-05-01 07:41:27 +02:00
sRoulette - > ballAngleSpeed - = ( f32 ) ( sRouletteTables [ sRoulette - > tableId ] . wheelSpeed )
2020-07-31 20:55:42 +02:00
/ ( sRouletteTables [ sRoulette - > tableId ] . wheelDelay + 1 ) ;
2020-08-03 23:31:34 +02:00
sprite - > sState = 4 ;
sprite - > callback = SpriteCB_RollBall_TryLand ;
2019-01-01 02:39:41 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ballAngleAccel ! = 0.0f )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ballAngleSpeed < 0.0f )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
sRoulette - > ballAngleAccel = 0.0f ;
sRoulette - > ballAngleSpeed = 0.0f ;
sRoulette - > ballFallSpeed / = 1.2 ;
2019-01-01 02:39:41 +01:00
}
}
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_RollBall_Medium ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
UpdateBallPos ( sprite ) ;
if ( sRoulette - > ballDistToCenter > 40.0f )
2019-01-01 02:39:41 +01:00
return ;
2021-05-01 07:41:27 +02:00
sRoulette - > ballFallSpeed = - ( 4.0f / ( f32 ) ( sRoulette - > ballTravelDistSlow ) ) ;
sRoulette - > ballAngleAccel = - ( sRoulette - > ballAngleSpeed / ( f32 ) ( sRoulette - > ballTravelDistSlow ) ) ;
2019-01-01 02:39:41 +01:00
sprite - > animNum = 2 ;
sprite - > animBeginning = TRUE ;
sprite - > animEnded = FALSE ;
2020-08-03 23:31:34 +02:00
sprite - > sState = 3 ;
sprite - > callback = SpriteCB_RollBall_Slow ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_RollBall_Fast ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
UpdateBallPos ( sprite ) ;
if ( sRoulette - > ballDistToCenter > 60.0f )
2019-01-01 02:39:41 +01:00
return ;
2020-08-21 00:02:00 +02:00
m4aSongNumStartOrChange ( SE_ROULETTE_BALL2 ) ;
2021-05-01 07:41:27 +02:00
sRoulette - > ballFallSpeed = - ( 20.0f / ( f32 ) ( sRoulette - > ballTravelDistMed ) ) ;
sRoulette - > ballAngleAccel = ( ( 1.0f - sRoulette - > ballAngleSpeed ) / ( f32 ) ( sRoulette - > ballTravelDistMed ) ) ;
2019-01-01 02:39:41 +01:00
sprite - > animNum = 1 ;
sprite - > animBeginning = TRUE ;
sprite - > animEnded = FALSE ;
2020-08-03 23:31:34 +02:00
sprite - > sState = 2 ;
sprite - > callback = SpriteCB_RollBall_Medium ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_RollBall_Start ( struct Sprite * sprite )
2019-01-01 02:39:41 +01:00
{
2020-08-03 23:31:34 +02:00
sprite - > sState = 1 ;
2019-01-01 02:39:41 +01:00
sprite - > data [ 2 ] = 0 ;
2020-08-03 23:31:34 +02:00
UpdateBallPos ( sprite ) ;
2019-01-01 02:39:41 +01:00
sprite - > invisible = FALSE ;
2020-08-03 23:31:34 +02:00
sprite - > callback = SpriteCB_RollBall_Fast ;
2019-01-01 02:39:41 +01:00
}
2020-08-03 23:31:34 +02:00
// Sprite data for Shroomish / its shadows
# define sMonSpriteId data[4]
# define sBallShadowSpriteId data[5]
# define sMonShadowSpriteId data[6]
static void CreateShroomishSprite ( struct Sprite * ball )
2019-01-01 02:39:41 +01:00
{
u16 t ;
u8 i ;
2020-08-03 23:31:34 +02:00
s16 coords [ 2 ] [ 2 ] = {
2019-01-02 23:40:40 +01:00
{ 116 , 44 } ,
{ 116 , 112 }
} ;
2020-08-03 23:31:34 +02:00
struct Roulette * roulette ;
2019-01-01 02:39:41 +01:00
2020-08-03 23:31:34 +02:00
t = ball - > data [ 7 ] - 2 ;
roulette = sRoulette ; // Unnecessary, needed to match
2020-07-29 10:46:58 +02:00
sRoulette - > spriteIds [ SPR_CLEAR_MON ] = CreateSprite ( & sSpriteTemplate_Shroomish , 36 , - 12 , 50 ) ;
2020-08-03 23:31:34 +02:00
sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_1 ] = CreateSprite ( & sSpriteTemplate_ShroomishShadow [ 0 ] , coords [ ball - > sStuckOnWheelLeft ] [ 0 ] , coords [ ball - > sStuckOnWheelLeft ] [ 1 ] , 59 ) ;
2020-07-29 10:46:58 +02:00
sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_2 ] = CreateSprite ( & sSpriteTemplate_ShroomishShadow [ 1 ] , 36 , 140 , 51 ) ;
gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_2 ] ] . oam . objMode = ST_OAM_OBJ_BLEND ;
2019-01-01 02:39:41 +01:00
for ( i = 0 ; i < 3 ; i + + )
{
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_CLEAR_MON ] ] . coordOffsetEnabled = FALSE ;
gSprites [ sRoulette - > spriteIds [ i + SPR_CLEAR_MON ] ] . invisible = TRUE ;
gSprites [ sRoulette - > spriteIds [ i + SPR_CLEAR_MON ] ] . animPaused = TRUE ;
gSprites [ sRoulette - > spriteIds [ i + SPR_CLEAR_MON ] ] . affineAnimPaused = TRUE ;
2020-08-03 23:31:34 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_CLEAR_MON ] ] . sMonSpriteId = sRoulette - > spriteIds [ SPR_CLEAR_MON ] ;
gSprites [ sRoulette - > spriteIds [ i + SPR_CLEAR_MON ] ] . sBallShadowSpriteId = sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_1 ] ;
gSprites [ sRoulette - > spriteIds [ i + SPR_CLEAR_MON ] ] . sMonShadowSpriteId = sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_2 ] ;
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_CLEAR_MON ] ] . data [ 2 ] = t ;
2020-08-03 23:31:34 +02:00
gSprites [ sRoulette - > spriteIds [ i + SPR_CLEAR_MON ] ] . data [ 3 ] = ( ball - > data [ 7 ] * sRouletteTables [ sRoulette - > tableId ] . randDistanceHigh ) +
( sRouletteTables [ sRoulette - > tableId ] . randDistanceLow + 0xFFFF ) ;
2019-01-01 02:39:41 +01:00
}
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_1 ] ] . coordOffsetEnabled = TRUE ;
2020-08-03 23:31:34 +02:00
sRoulette - > ball = ball ;
2019-01-01 02:39:41 +01:00
}
2019-01-01 22:25:52 +01:00
2020-08-03 23:31:34 +02:00
static void CreateTaillowSprite ( struct Sprite * ball )
2019-01-01 22:25:52 +01:00
{
u8 i = 0 ;
s16 t ;
2020-08-03 23:31:34 +02:00
s16 coords [ 2 ] [ 2 ] = {
{ 256 , 84 } , // Right approach
{ - 16 , 84 } // Left approach
2019-01-02 23:40:40 +01:00
} ;
2019-01-01 22:25:52 +01:00
2020-08-03 23:31:34 +02:00
t = ball - > data [ 7 ] - 2 ;
sRoulette - > spriteIds [ SPR_CLEAR_MON ] = CreateSprite ( & sSpriteTemplate_Taillow , coords [ ball - > sStuckOnWheelLeft ] [ 0 ] , coords [ ball - > sStuckOnWheelLeft ] [ 1 ] , 50 ) ;
StartSpriteAnim ( & gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON ] ] , ball - > sStuckOnWheelLeft ) ;
sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_1 ] = CreateSprite ( & sSpriteTemplate_TaillowShadow , coords [ ball - > sStuckOnWheelLeft ] [ 0 ] , coords [ ball - > sStuckOnWheelLeft ] [ 1 ] , 51 ) ;
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_1 ] ] . affineAnimPaused = TRUE ;
gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_1 ] ] . animPaused = TRUE ;
2020-08-03 23:31:34 +02:00
ball - > data [ 7 ] = ( t * sRouletteTables [ sRoulette - > tableId ] . randDistanceHigh ) + ( sRouletteTables [ sRoulette - > tableId ] . taillow . baseDropDelay + 45 ) ;
2019-01-01 22:25:52 +01:00
for ( ; i < 2 ; i + + )
{
2020-08-03 23:31:34 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON + i ] ] . sMonSpriteId = sRoulette - > spriteIds [ SPR_CLEAR_MON ] ;
gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON + i ] ] . sBallShadowSpriteId = sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_1 ] ;
gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON + i ] ] . sMonShadowSpriteId = sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_1 ] ;
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON + i ] ] . data [ 2 ] = t ;
2020-08-03 23:31:34 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON + i ] ] . data [ 3 ] = ball - > data [ 7 ] - 45 ;
2019-01-01 22:25:52 +01:00
}
2020-08-03 23:31:34 +02:00
sRoulette - > ball = ball ;
2019-01-01 22:25:52 +01:00
}
2020-08-03 23:31:34 +02:00
static void SetBallStuck ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
u8 slotId ;
u16 angle ;
u8 numCandidates = 0 ;
u8 maxSlotToCheck = 5 ;
u8 betSlotId = 0 ;
2019-04-11 12:05:56 +02:00
u8 i = 0 ;
2020-08-03 23:31:34 +02:00
u8 slotsToSkip ;
u8 slotCandidates [ NUM_ROULETTE_SLOTS - 2 ] = { } ; // - 2 because we know at least 2 are already occupied
2019-04-11 12:05:56 +02:00
u16 rand = Random ( ) ;
2019-01-01 22:25:52 +01:00
2020-07-31 20:55:42 +02:00
sRoulette - > ballState = BALL_STATE_STUCK ;
sRoulette - > ballStuck = TRUE ;
sRoulette - > ballUnstuck = FALSE ;
sRoulette - > hitSlot = 0xFF ;
2020-08-03 23:31:34 +02:00
sRoulette - > ballAngle = sprite - > sBallAngle ;
sRoulette - > ballFallSpeed = 0.0f ;
sRoulette - > ballAngleSpeed = sRouletteTables [ sRoulette - > tableId ] . var1C ;
2019-04-11 12:05:56 +02:00
2020-08-03 23:31:34 +02:00
angle = ( sRoulette - > tableId * DEGREES_PER_SLOT + 33 ) + ( 1 - sRoulette - > useTaillow ) * 15 ;
// Determine which quadrant the ball got stuck in
// Use either Shroomish or Taillow to clear the ball depending on where it's stuck
2019-01-01 22:25:52 +01:00
for ( i = 0 ; i < 4 ; i + + )
{
2020-08-03 23:31:34 +02:00
if ( angle < sprite - > sBallAngle & & sprite - > sBallAngle < = angle + 90 )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
sprite - > sStuckOnWheelLeft = i / 2 ;
2020-07-29 10:46:58 +02:00
sRoulette - > useTaillow = i % 2 ;
2019-01-01 22:25:52 +01:00
break ;
}
if ( i = = 3 )
{
2020-08-03 23:31:34 +02:00
sprite - > sStuckOnWheelLeft = TRUE ;
2020-07-29 10:46:58 +02:00
sRoulette - > useTaillow = TRUE ;
2019-01-01 22:25:52 +01:00
break ;
}
2020-08-03 23:31:34 +02:00
angle + = 90 ;
2019-01-01 22:25:52 +01:00
}
2019-04-11 12:05:56 +02:00
2020-07-29 10:46:58 +02:00
if ( sRoulette - > useTaillow )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
if ( sprite - > sStuckOnWheelLeft )
2021-11-07 19:54:44 +01:00
PlayCry_Normal ( SPECIES_TAILLOW , - 63 ) ;
2019-01-01 22:25:52 +01:00
else
2021-11-07 19:54:44 +01:00
PlayCry_Normal ( SPECIES_TAILLOW , 63 ) ;
2019-01-01 22:25:52 +01:00
}
else
{
2021-11-07 19:54:44 +01:00
PlayCry_Normal ( SPECIES_SHROOMISH , - 63 ) ;
2019-01-01 22:25:52 +01:00
}
2019-04-11 12:05:56 +02:00
2020-08-03 23:31:34 +02:00
slotsToSkip = 2 ;
slotId = ( sRoulette - > stuckHitSlot + 2 ) % NUM_ROULETTE_SLOTS ;
2019-04-11 12:05:56 +02:00
2020-07-29 10:46:58 +02:00
if ( sRoulette - > useTaillow = = TRUE & & sRoulette - > tableId = = 1 )
2020-08-03 23:31:34 +02:00
maxSlotToCheck + = 6 ; // Check all remaining slots
2019-01-01 22:25:52 +01:00
else
2020-08-03 23:31:34 +02:00
maxSlotToCheck + = slotsToSkip ; // Check enough slots to guarantee an empty will be found
2019-04-11 12:05:56 +02:00
2020-08-03 23:31:34 +02:00
// Identify open slots on the wheel that the stuck ball could be moved to
for ( i = slotsToSkip ; i < maxSlotToCheck ; i + + )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
if ( ! ( sRoulette - > hitFlags & sRouletteSlots [ slotId ] . flag ) )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
slotCandidates [ numCandidates + + ] = i ;
if ( betSlotId = = 0 & & ( sRouletteSlots [ slotId ] . flag & sGridSelections [ sRoulette - > betSelection [ sRoulette - > curBallNum ] ] . inSelectionFlags ) )
betSlotId = i ;
2019-01-01 22:25:52 +01:00
}
2020-08-03 23:31:34 +02:00
slotId = ( slotId + 1 ) % NUM_ROULETTE_SLOTS ;
2019-01-01 22:25:52 +01:00
}
2019-04-11 12:05:56 +02:00
2020-08-03 23:31:34 +02:00
// Determine which identified slot the ball should be moved to
// The below slot ids are relative to the slot the ball got stuck on
2020-07-29 10:46:58 +02:00
if ( ( sRoulette - > useTaillow + 1 ) & sRoulette - > partySpeciesFlags )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
// If the player has the corresponding pokemon in their party (HAS_SHROOMISH or HAS_TAILLOW),
// there's a 75% chance that the ball will be moved to a spot they bet on
// assuming it was one of the slots identified as a candidate
if ( betSlotId & & ( rand % 256 ) < 192 )
sprite - > data [ 7 ] = betSlotId ;
2019-01-01 22:25:52 +01:00
else
2020-08-03 23:31:34 +02:00
sprite - > data [ 7 ] = slotCandidates [ rand % numCandidates ] ;
2019-01-01 22:25:52 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
sprite - > data [ 7 ] = slotCandidates [ rand % numCandidates ] ;
2019-01-01 22:25:52 +01:00
}
2019-04-11 12:05:56 +02:00
2020-08-03 23:31:34 +02:00
sprite - > callback = SpriteCB_UnstickBall ;
2019-01-01 22:25:52 +01:00
}
2020-08-03 23:31:34 +02:00
static const u16 sShroomishShadowAlphas [ ] = {
2019-01-02 23:40:40 +01:00
0x907 ,
0x808 ,
0x709 ,
0x60A ,
0x50B ,
0x40C ,
0x30D ,
0x20E ,
0x10F ,
0x010 ,
} ;
2020-08-03 23:31:34 +02:00
static void SpriteCB_ShroomishExit ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
// Delay for screen shaking, then exit left
2019-01-01 22:25:52 +01:00
if ( sprite - > data [ 1 ] + + > = sprite - > data [ 3 ] )
{
2021-07-07 15:11:52 +02:00
sprite - > x - = 2 ;
if ( sprite - > x < - 16 )
2019-01-01 22:25:52 +01:00
{
2020-07-31 20:55:42 +02:00
if ( ! sRoulette - > ballUnstuck )
sRoulette - > ballUnstuck = TRUE ;
2019-01-01 22:25:52 +01:00
DestroySprite ( sprite ) ;
2020-08-03 23:31:34 +02:00
sRoulette - > shroomishShadowTimer = 0 ;
sRoulette - > shroomishShadowAlpha = sShroomishShadowAlphas [ 0 ] ;
2019-01-01 22:25:52 +01:00
}
}
}
2020-08-03 23:31:34 +02:00
// Handles both the screen shake and ball shadow effect for when Shroomish unsticks the ball
static void SpriteCB_ShroomishShakeScreen ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
int screenShakeIdx ;
u16 screenShakeOffsets [ ] [ 4 ] = {
2019-01-02 23:40:40 +01:00
{ - 1 , 0 , 1 , 0 } ,
{ - 2 , 0 , 2 , 0 } ,
{ - 3 , 0 , 3 , 0 } ,
} ;
2019-01-01 22:25:52 +01:00
if ( sprite - > data [ 1 ] + + < sprite - > data [ 3 ] )
{
if ( sprite - > data [ 1 ] & 1 )
{
2020-08-03 23:31:34 +02:00
// Shake screen
gSpriteCoordOffsetY = screenShakeOffsets [ sprite - > data [ 2 ] / 2 ] [ sprite - > data [ 7 ] ] ;
screenShakeIdx = sprite - > data [ 7 ] + 1 ;
sprite - > data [ 7 ] = screenShakeIdx - ( ( screenShakeIdx / 4 ) * 4 ) ;
2019-01-01 22:25:52 +01:00
}
2020-08-03 23:31:34 +02:00
// Flicker shadow
2019-01-01 22:25:52 +01:00
sprite - > invisible ^ = 1 ;
}
else
{
gSpriteCoordOffsetY = 0 ;
2020-07-29 10:46:58 +02:00
gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON ] ] . animPaused = FALSE ;
2019-01-01 22:25:52 +01:00
DestroySprite ( sprite ) ;
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_ShroomishFall ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
2021-05-01 07:41:27 +02:00
f32 timer ;
2019-01-01 22:25:52 +01:00
sprite - > data [ 1 ] + + ;
2020-08-03 23:31:34 +02:00
timer = sprite - > data [ 1 ] ;
2021-07-07 15:11:52 +02:00
sprite - > y2 = timer * 0.039f * timer ;
2020-08-03 23:31:34 +02:00
sRoulette - > shroomishShadowAlpha = sShroomishShadowAlphas [ ( sRoulette - > shroomishShadowTimer - 1 ) / 2 ] ;
if ( sRoulette - > shroomishShadowTimer < ARRAY_COUNT ( sShroomishShadowAlphas ) * 2 - 1 )
sRoulette - > shroomishShadowTimer + + ;
2019-01-01 22:25:52 +01:00
if ( sprite - > data [ 1 ] > 60 )
{
sprite - > data [ 1 ] = 0 ;
2020-08-03 23:31:34 +02:00
sprite - > callback = SpriteCB_ShroomishExit ;
gSprites [ sprite - > sMonShadowSpriteId ] . callback = SpriteCB_ShroomishExit ;
gSprites [ sprite - > sMonShadowSpriteId ] . data [ 1 ] = - 2 ;
gSprites [ sprite - > sBallShadowSpriteId ] . invisible = FALSE ;
gSprites [ sprite - > sBallShadowSpriteId ] . callback = SpriteCB_ShroomishShakeScreen ;
2020-08-21 00:02:00 +02:00
m4aSongNumStart ( SE_M_STRENGTH ) ;
2019-01-01 22:25:52 +01:00
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_Shroomish ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
if ( sprite - > data [ 7 ] = = 0 )
{
2020-08-03 23:31:34 +02:00
// Wait for the ball to be a specific angle (or its 180 degree opposite) specified by the table
// Once it is, reveal the shadow for Shroomish falling in
if ( ! sRoulette - > ball - > sStuckOnWheelLeft )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ball - > sBallAngle ! = sRouletteTables [ sRoulette - > tableId ] . shroomish . startAngle )
2019-01-01 22:25:52 +01:00
return ;
}
else
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ball - > sBallAngle ! = sRouletteTables [ sRoulette - > tableId ] . shroomish . startAngle + 180 )
2019-01-01 22:25:52 +01:00
return ;
}
sprite - > invisible = FALSE ;
sprite - > data [ 7 ] + + ;
2020-08-21 00:02:00 +02:00
m4aSongNumStart ( SE_FALL ) ;
2020-08-03 23:31:34 +02:00
sRoulette - > shroomishShadowTimer = 1 ;
sRoulette - > shroomishShadowAlpha = sShroomishShadowAlphas [ 0 ] ;
2019-01-01 22:25:52 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
sRoulette - > shroomishShadowAlpha = sShroomishShadowAlphas [ ( sRoulette - > shroomishShadowTimer - 1 ) / 2 ] ;
if ( sRoulette - > shroomishShadowTimer < 19 )
sRoulette - > shroomishShadowTimer + + ;
2019-01-01 22:25:52 +01:00
2020-08-03 23:31:34 +02:00
// Wait for the ball to be a specific angle (or its 180 degree opposite) specified by the table
// Once it is, have Shroomish begin to fall in
// On both tables this angle is 15 degrees off the "start" angle
if ( ! sRoulette - > ball - > sStuckOnWheelLeft )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ball - > sBallAngle ! = sRouletteTables [ sRoulette - > tableId ] . shroomish . dropAngle )
2019-01-01 22:25:52 +01:00
return ;
}
else
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ball - > sBallAngle ! = sRouletteTables [ sRoulette - > tableId ] . shroomish . dropAngle + 180 )
2019-01-01 22:25:52 +01:00
return ;
}
2020-08-03 23:31:34 +02:00
gSprites [ sprite - > sMonSpriteId ] . callback = SpriteCB_ShroomishFall ;
gSprites [ sprite - > sMonSpriteId ] . invisible = FALSE ;
2019-01-01 22:25:52 +01:00
sprite - > callback = & SpriteCallbackDummy ;
sprite - > data [ 7 ] = 0 ;
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_TaillowShadow_Flash ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
sprite - > invisible ^ = 1 ;
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_Taillow_FlyAway ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
2021-07-07 15:11:52 +02:00
if ( sprite - > y > - 16 )
2019-01-01 22:25:52 +01:00
{
2021-07-07 15:11:52 +02:00
sprite - > y - - ;
2019-01-01 22:25:52 +01:00
}
else
{
sprite - > callback = SpriteCallbackDummy ;
sprite - > invisible = TRUE ;
sprite - > animPaused = TRUE ;
2020-08-21 00:02:00 +02:00
m4aSongNumStop ( SE_TAILLOW_WING_FLAP ) ;
2019-01-01 22:25:52 +01:00
DestroySprite ( sprite ) ;
2020-07-29 10:46:58 +02:00
FreeOamMatrix ( gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_1 ] ] . oam . matrixNum ) ;
DestroySprite ( & gSprites [ sRoulette - > spriteIds [ SPR_CLEAR_MON_SHADOW_1 ] ] ) ;
2019-01-01 22:25:52 +01:00
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_Taillow_PickUpBall ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
if ( sprite - > data [ 1 ] > = 0 )
{
sprite - > data [ 1 ] - - ;
2021-07-07 15:11:52 +02:00
sprite - > y - - ;
2019-01-01 22:25:52 +01:00
if ( sprite - > data [ 1 ] = = 0 & & sprite - > animCmdIndex = = 1 )
2021-07-07 15:11:52 +02:00
sprite - > y2 + + ;
2019-01-01 22:25:52 +01:00
}
else
{
if ( sprite - > data [ 3 ] > = 0 )
{
sprite - > data [ 3 ] - - ;
if ( sprite - > animDelayCounter = = 0 )
{
if ( sprite - > animCmdIndex = = 1 )
2021-07-07 15:11:52 +02:00
sprite - > y2 + + ;
2019-01-01 22:25:52 +01:00
else
2021-07-07 15:11:52 +02:00
sprite - > y2 - - ;
2019-01-01 22:25:52 +01:00
}
}
else
{
2020-08-21 00:02:00 +02:00
m4aSongNumStart ( SE_FALL ) ;
2020-08-03 23:31:34 +02:00
StartSpriteAnim ( sprite , sRoulette - > ball - > sStuckOnWheelLeft + 4 ) ;
sprite - > callback = SpriteCB_Taillow_FlyAway ;
gSprites [ sprite - > sMonShadowSpriteId ] . affineAnimPaused = FALSE ;
2019-01-01 22:25:52 +01:00
}
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_Taillow_FlyIn ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
s8 xMoveOffsets [ 2 ] = { - 1 , 1 } ;
s8 yMoveOffsets [ ] [ 2 ] = {
2019-01-02 23:40:40 +01:00
{ 2 , 0 } ,
{ 2 , 0 } ,
{ 2 , - 1 } ,
{ 2 , - 1 } ,
{ 2 , - 1 } ,
{ 2 , - 1 } ,
{ 2 , - 2 } ,
{ 2 , - 2 } ,
} ;
2019-01-01 22:25:52 +01:00
if ( sprite - > data [ 1 ] - - > 7 )
{
2021-07-07 15:11:52 +02:00
sprite - > x + = xMoveOffsets [ sRoulette - > ball - > sStuckOnWheelLeft ] * 2 ;
2019-01-01 22:25:52 +01:00
if ( IsSEPlaying ( ) )
{
2021-07-07 15:11:52 +02:00
s8 pan = - ( ( 116 - sprite - > x ) / 2 ) ;
2021-10-09 17:33:37 +02:00
m4aMPlayPanpotControl ( & gMPlayInfo_SE1 , TRACKS_ALL , pan ) ;
m4aMPlayPanpotControl ( & gMPlayInfo_SE2 , TRACKS_ALL , pan ) ;
2019-01-01 22:25:52 +01:00
}
}
else
{
if ( sprite - > data [ 1 ] > = 0 )
{
2021-07-07 15:11:52 +02:00
sprite - > x + = xMoveOffsets [ sRoulette - > ball - > sStuckOnWheelLeft ] * yMoveOffsets [ 7 - sprite - > data [ 1 ] ] [ 0 ] ;
sprite - > y + = yMoveOffsets [ 7 - sprite - > data [ 1 ] ] [ 1 ] ;
2019-01-01 22:25:52 +01:00
}
else
{
2020-08-21 00:02:00 +02:00
m4aSongNumStartOrChange ( SE_TAILLOW_WING_FLAP ) ;
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ball - > sStuckOnWheelLeft = = 0 )
2021-11-07 19:54:44 +01:00
PlayCry_Normal ( SPECIES_TAILLOW , 63 ) ;
2019-01-01 22:25:52 +01:00
else
2021-11-07 19:54:44 +01:00
PlayCry_Normal ( SPECIES_TAILLOW , - 63 ) ;
2020-08-03 23:31:34 +02:00
StartSpriteAnim ( sprite , sRoulette - > ball - > sStuckOnWheelLeft + 2 ) ;
2019-01-01 22:25:52 +01:00
sprite - > data [ 1 ] = 45 ;
2020-08-03 23:31:34 +02:00
sprite - > callback = SpriteCB_Taillow_PickUpBall ;
2019-01-01 22:25:52 +01:00
}
}
}
2020-08-03 23:31:34 +02:00
static void SpriteCB_TaillowShadow_FlyIn ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
s8 moveDir [ 2 ] = { - 1 , 1 } ;
2019-04-11 12:05:56 +02:00
2019-01-01 22:25:52 +01:00
if ( sprite - > data [ 1 ] - - > = 0 )
{
2021-07-07 15:11:52 +02:00
sprite - > x + = moveDir [ sRoulette - > ball - > sStuckOnWheelLeft ] * 2 ;
2020-08-03 23:31:34 +02:00
gSprites [ sprite - > sMonShadowSpriteId ] . invisible ^ = 1 ;
2019-01-01 22:25:52 +01:00
}
else
{
2020-08-03 23:31:34 +02:00
sprite - > callback = SpriteCB_TaillowShadow_Flash ;
2019-01-01 22:25:52 +01:00
}
}
2020-07-29 10:46:58 +02:00
static void SpriteCB_Taillow ( struct Sprite * sprite )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ball - > sStuckOnWheelLeft = = FALSE )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ball - > sBallAngle = = sRouletteTables [ sRoulette - > tableId ] . taillow . rightStartAngle + 90 )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
gSprites [ sprite - > sMonShadowSpriteId ] . data [ 1 ] = 52 ;
gSprites [ sprite - > sMonSpriteId ] . data [ 1 ] = 52 ;
2019-01-01 22:25:52 +01:00
}
else
{
return ;
}
}
else
{
2020-08-03 23:31:34 +02:00
if ( sRoulette - > ball - > sBallAngle = = sRouletteTables [ sRoulette - > tableId ] . taillow . leftStartAngle + 270 )
2019-01-01 22:25:52 +01:00
{
2020-08-03 23:31:34 +02:00
gSprites [ sprite - > sMonShadowSpriteId ] . data [ 1 ] = 46 ;
gSprites [ sprite - > sMonSpriteId ] . data [ 1 ] = 46 ;
2019-01-01 22:25:52 +01:00
}
else
{
return ;
}
}
2020-08-03 23:31:34 +02:00
gSprites [ sprite - > sMonShadowSpriteId ] . callback = SpriteCB_TaillowShadow_FlyIn ;
gSprites [ sprite - > sMonSpriteId ] . callback = SpriteCB_Taillow_FlyIn ;
2020-08-21 00:02:00 +02:00
m4aSongNumStart ( SE_FALL ) ;
2019-01-01 22:25:52 +01:00
}