pokeemerald/src/berry_blender.c

3774 lines
107 KiB
C
Raw Normal View History

2017-09-30 16:12:35 +02:00
#include "global.h"
2017-12-05 18:55:48 +01:00
#include "constants/game_stat.h"
#include "overworld.h"
2017-11-19 22:48:46 +01:00
#include "berry_blender.h"
2017-11-04 22:40:36 +01:00
#include "bg.h"
#include "window.h"
#include "task.h"
#include "sprite.h"
2017-11-18 16:11:34 +01:00
#include "sound.h"
2017-12-11 19:27:51 +01:00
#include "constants/songs.h"
2017-11-18 16:11:34 +01:00
#include "m4a.h"
#include "bg.h"
#include "palette.h"
#include "decompress.h"
#include "malloc.h"
2017-11-18 16:11:34 +01:00
#include "gpu_regs.h"
#include "text.h"
2018-07-16 20:23:05 +02:00
#include "text_window.h"
2017-11-18 16:11:34 +01:00
#include "event_data.h"
#include "main.h"
#include "link.h"
#include "item_menu_icons.h"
#include "berry.h"
2017-11-19 22:48:46 +01:00
#include "item.h"
2017-12-05 18:55:48 +01:00
#include "constants/items.h"
2017-11-18 16:11:34 +01:00
#include "string_util.h"
2017-11-18 21:38:57 +01:00
#include "international_string_util.h"
#include "random.h"
2017-11-19 22:48:46 +01:00
#include "menu.h"
#include "pokeblock.h"
#include "trig.h"
#include "tv.h"
2018-03-02 10:21:12 +01:00
#include "item_menu.h"
#include "battle_records.h"
2018-11-07 19:35:31 +01:00
#include "graphics.h"
2018-11-19 01:03:14 +01:00
#include "new_game.h"
2019-02-27 04:04:44 +01:00
#include "save.h"
#include "link.h"
2019-09-16 05:47:07 +02:00
#include "constants/berry.h"
2019-04-04 23:05:46 +02:00
#include "constants/rgb.h"
2017-09-30 16:12:35 +02:00
2020-08-23 00:20:22 +02:00
enum {
SCORE_BEST,
SCORE_GOOD,
SCORE_MISS,
NUM_SCORE_TYPES,
};
// Redundant with the above. Reversed
enum {
PROXIMITY_MISS,
PROXIMITY_GOOD,
PROXIMITY_BEST,
};
enum {
SCOREANIM_GOOD,
SCOREANIM_MISS,
SCOREANIM_BEST_FLASH,
SCOREANIM_BEST_STATIC,
};
#define MAX_PROGRESS_BAR 1000
#define GFXTAG_COUNTDOWN_NUMBERS 12345
#define GFXTAG_START 12346
#define GFXTAG_PARTICLES 23456
#define GFXTAG_PLAYER_ARROW 46545
#define GFXTAG_SCORE_SYMBOLS 48888
#define PALTAG_PLAYER_ARROW 12312
#define PALTAG_MISC 46546
2017-09-30 16:12:35 +02:00
2020-08-23 00:20:22 +02:00
#define BLENDER_MAX_PLAYERS MAX_LINK_PLAYERS
2017-11-18 16:11:34 +01:00
2017-11-19 22:48:46 +01:00
enum
{
PLAY_AGAIN_OK,
DONT_PLAY_AGAIN,
CANT_PLAY_NO_BERRIES,
CANT_PLAY_NO_PKBLCK_SPACE
};
2017-09-30 16:12:35 +02:00
2017-11-18 16:11:34 +01:00
struct BlenderBerry
{
u16 itemId;
2018-09-01 22:03:21 +02:00
u8 name[BERRY_NAME_LENGTH + 1];
2017-11-27 20:03:41 +01:00
u8 flavors[FLAVOR_COUNT];
2017-11-18 16:11:34 +01:00
u8 smoothness;
};
2017-09-30 16:12:35 +02:00
2017-11-19 22:48:46 +01:00
struct TimeAndRPM
{
u32 time;
2020-08-23 00:20:22 +02:00
u16 maxRPM;
2017-11-19 22:48:46 +01:00
};
struct BlenderGameBlock
{
struct TimeAndRPM timeRPM;
2020-08-23 00:20:22 +02:00
u16 scores[BLENDER_MAX_PLAYERS][NUM_SCORE_TYPES];
2017-11-19 22:48:46 +01:00
};
struct TvBlenderStruct
{
u8 name[11];
2017-11-27 20:03:41 +01:00
u8 pokeblockFlavor;
2017-11-19 22:48:46 +01:00
u8 pokeblockColor;
u8 pokeblockSheen;
};
2020-08-23 00:20:22 +02:00
struct BerryBlender
2017-11-18 16:11:34 +01:00
{
u8 mainState;
u8 loadGfxState;
2017-11-19 22:48:46 +01:00
u8 unused_02[0x42];
2017-11-18 21:38:57 +01:00
u16 field_44;
2020-08-23 00:20:22 +02:00
u8 scoreIconIds[NUM_SCORE_TYPES];
2017-11-18 16:11:34 +01:00
u16 arrowPos;
2020-08-23 00:20:22 +02:00
s16 speed;
u16 maxRPM;
u8 playerArrowSpriteIds[BLENDER_MAX_PLAYERS];
u8 playerArrowSpriteIds2[BLENDER_MAX_PLAYERS];
2017-11-19 22:48:46 +01:00
u8 unused_57[0xB];
u8 gameEndState;
2017-11-18 16:11:34 +01:00
u16 field_64[BLENDER_MAX_PLAYERS];
2017-11-19 22:48:46 +01:00
u16 field_6C;
u16 field_6E;
u16 playAgainState;
2017-11-18 16:11:34 +01:00
u8 field_72;
u16 chosenItemId[BLENDER_MAX_PLAYERS];
2020-08-23 00:20:22 +02:00
u8 numPlayers;
2017-11-19 22:48:46 +01:00
u8 unused_7D[0x10];
2017-11-18 21:38:57 +01:00
u16 field_8E[BLENDER_MAX_PLAYERS];
u16 field_96[BLENDER_MAX_PLAYERS];
2017-11-19 22:48:46 +01:00
u8 yesNoAnswer;
u8 stringVar[100];
2017-11-18 16:11:34 +01:00
u32 gameFrameTime;
s32 framesToWait;
u32 field_10C;
2017-11-19 22:48:46 +01:00
u8 unused_110[4];
2020-08-23 00:20:22 +02:00
u8 playerToThrowBerry;
u16 progressBarValue;
u16 maxProgressBarValue;
2017-11-18 16:11:34 +01:00
u16 field_11A;
s16 bg_X;
s16 bg_Y;
2020-08-23 00:20:22 +02:00
u8 opponentTaskIds[BLENDER_MAX_PLAYERS - 1];
2017-11-18 16:11:34 +01:00
u8 field_123;
2020-08-23 00:20:22 +02:00
u16 scores[BLENDER_MAX_PLAYERS][NUM_SCORE_TYPES];
2017-11-19 22:48:46 +01:00
u8 playerPlaces[BLENDER_MAX_PLAYERS];
2017-11-18 16:11:34 +01:00
struct BgAffineSrcData bgAffineSrc;
2020-08-23 00:20:22 +02:00
u16 savedMusic;
2017-11-18 16:11:34 +01:00
struct BlenderBerry blendedBerries[BLENDER_MAX_PLAYERS];
2017-11-19 22:48:46 +01:00
struct TimeAndRPM smallBlock;
u32 field_1A0;
2017-11-18 16:11:34 +01:00
u8 field_1A4;
2017-11-19 22:48:46 +01:00
struct TvBlenderStruct tvBlender;
2017-11-18 16:11:34 +01:00
u8 tilemapBuffers[2][0x800];
s16 textState;
void *tilesBuffer;
2017-11-19 22:48:46 +01:00
struct BlenderGameBlock gameBlock;
2017-11-18 16:11:34 +01:00
};
extern struct MusicPlayerInfo gMPlayInfo_SE2;
extern struct MusicPlayerInfo gMPlayInfo_BGM;
2017-11-19 22:48:46 +01:00
2017-11-18 16:11:34 +01:00
// text
2017-11-19 22:48:46 +01:00
extern const u8 gText_SavingDontTurnOff2[];
extern const u8 gText_Space[];
extern const u8 gText_BlenderMaxSpeedRecord[];
extern const u8 gText_234Players[];
2017-11-18 16:11:34 +01:00
// this file's functions
2017-11-19 22:48:46 +01:00
static void BerryBlender_SetBackgroundsPos(void);
2020-08-23 00:20:22 +02:00
static void Task_HandleOpponent1(u8);
static void Task_HandleOpponent2(u8);
static void Task_HandleOpponent3(u8);
static void Task_HandleBerryMaster(u8);
static void sub_8083F3C(u8);
static void SpriteCB_PlayerArrow(struct Sprite *);
static void SpriteCB_ScoreSymbol(struct Sprite *);
static void SpriteCB_CountdownNumber(struct Sprite *);
static void SpriteCB_Start(struct Sprite *);
static void SpriteCB_ScoreSymbolBest(struct Sprite *);
static void Blender_SetPlayerNamesLocal(u8);
2017-11-19 22:48:46 +01:00
static void sub_807FAC8(void);
static void sub_8082D28(void);
2020-08-23 00:20:22 +02:00
static bool32 Blender_PrintText(s16 *, const u8 *, s32 );
static void StartBlender(void);
static void CB2_StartBlenderLink(void);
static void CB2_StartBlenderLocal(void);
static void Blender_DummiedOutFunc(s16, s16);
static void CB2_PlayBlender(void);
static void DrawBlenderCenter(struct BgAffineSrcData *);
2017-11-19 22:48:46 +01:00
static bool8 sub_8083380(void);
static void sub_808074C(void);
static void Blender_PrintPlayerNames(void);
2020-08-23 00:20:22 +02:00
static void InitBlenderBgs(void);
static void Blender_SetParticipantBerryData(u8, u16);
static void Blender_AddTextPrinter(u8, const u8 *, u8, u8, s32, s32);
2017-11-19 22:48:46 +01:00
static void sub_8080DF8(void);
2020-08-23 00:20:22 +02:00
static void CreateParticleSprites(void);
static void sub_80832BC(s16*, u16);
static void TryUpdateProgressBar(u16, u16);
static void UpdateRPM(u16);
2017-11-19 22:48:46 +01:00
static void sub_808330C(void);
static void sub_8082AD4(void);
static void CB2_HandleBlenderEndGame(void);
2020-08-23 00:20:22 +02:00
static bool8 PrintBlendingRanking(void);
static bool8 PrintBlendingResults(void);
2017-11-19 22:48:46 +01:00
static void CB2_HandlePlayerPlayAgainChoice(void);
static void CB2_HandlePlayerLinkPlayAgainChoice(void);
2020-08-23 00:20:22 +02:00
static void UpdateProgressBar(u16, u16);
static void Blender_PrintMadePokeblockString(struct Pokeblock *, u8 *);
static bool32 TryAddContestLinkTvShow(struct Pokeblock *, struct TvBlenderStruct *);
2017-11-19 22:48:46 +01:00
2018-11-19 01:03:14 +01:00
// EWRAM
2020-08-23 00:20:22 +02:00
EWRAM_DATA static struct BerryBlender *sBerryBlender = NULL;
2017-11-19 22:48:46 +01:00
EWRAM_DATA static s32 sUnknown_020322A8[5] = {0};
EWRAM_DATA static s32 sUnknown_020322BC[5] = {0};
EWRAM_DATA static u32 sUnknown_020322D0 = 0;
2018-11-19 01:03:14 +01:00
// IWRAM bss
static s16 sUnknown_03000DE8[8];
static s16 sUnknown_03000DF8[6];
static s16 sUnknown_03000E04;
static s16 sUnknown_03000E06;
2017-11-19 22:48:46 +01:00
2018-11-19 01:03:14 +01:00
// IWRAM common
u8 gInGameOpponentsNo;
2017-11-19 22:48:46 +01:00
// rom
2020-08-23 00:20:22 +02:00
static const u16 sBlenderCenter_Pal[] = INCBIN_U16("graphics/berry_blender/center.gbapal");
static const u8 sBlenderCenter_Tilemap[] = INCBIN_U8("graphics/berry_blender/center_map.bin");
static const u16 sBlenderOuter_Pal[] = INCBIN_U16("graphics/berry_blender/outer.gbapal");
2017-11-04 22:40:36 +01:00
// unreferenced pals?
2017-11-13 18:18:12 +01:00
static const u16 sUnknownPal_0[] = INCBIN_U16("graphics/unknown/unknown_339514.gbapal");
2017-11-04 22:40:36 +01:00
static const u16 sUnknownArray_1[224] = {0};
// unused text?
static const u8 sUnusedText_YesNo[] = _("YES\nNO");
static const u8 sUnusedText_2[] = _("");
static const u8 sUnusedText_Space[] = _(" ");
static const u8 sUnusedText_Terminating[] = _("Terminating.");
static const u8 sUnusedText_LinkPartnerNotFound[] = _("Link partner(s) not found.\nPlease try again.\p");
2017-11-19 22:48:46 +01:00
static const u8 sText_BerryBlenderStart[] = _("Starting up the BERRY BLENDER.\pPlease select a BERRY from your BAG\nto put in the BERRY BLENDER.\p");
static const u8 sText_NewParagraph[] = _("\p");
static const u8 sText_WasMade[] = _(" was made!");
2017-11-04 22:40:36 +01:00
static const u8 sText_Mister[] = _("MISTER");
static const u8 sText_Laddie[] = _("LADDIE");
static const u8 sText_Lassie[] = _("LASSIE");
static const u8 sText_Master[] = _("MASTER");
static const u8 sText_Dude[] = _("DUDE");
static const u8 sText_Miss[] = _("MISS");
2017-11-19 22:48:46 +01:00
static const u8* const sBlenderOpponentsNames[] =
2017-11-04 22:40:36 +01:00
{
sText_Mister,
sText_Laddie,
sText_Lassie,
sText_Master,
sText_Dude,
sText_Miss
};
2017-11-18 16:11:34 +01:00
enum
{
BLENDER_MISTER,
BLENDER_LADDIE,
BLENDER_LASSIE,
BLENDER_MASTER,
BLENDER_DUDE,
BLENDER_MISS
};
2017-11-12 18:41:04 +01:00
static const u8 sText_PressAToStart[] = _("Press the A Button to start.");
2017-11-04 22:40:36 +01:00
static const u8 sText_PleaseWaitAWhile[] = _("Please wait a while.");
2017-11-19 22:48:46 +01:00
static const u8 sText_CommunicationStandby[] = _("Communication standby…");
static const u8 sText_WouldLikeToBlendAnotherBerry[] = _("Would you like to blend another BERRY?");
2018-12-07 16:41:08 +01:00
static const u8 sText_RunOutOfBerriesForBlending[] = _("You've run out of BERRIES for\nblending in the BERRY BLENDER.\p");
2017-11-19 22:48:46 +01:00
static const u8 sText_YourPokeblockCaseIsFull[] = _("Your {POKEBLOCK} CASE is full.\p");
static const u8 sText_HasNoBerriesToPut[] = _(" has no BERRIES to put in\nthe BERRY BLENDER.");
2018-12-07 16:41:08 +01:00
static const u8 sText_ApostropheSPokeblockCaseIsFull[] = _("'s {POKEBLOCK} CASE is full.\p");
2017-11-19 22:48:46 +01:00
static const u8 sText_BlendingResults[] = _("RESULTS OF BLENDING");
2017-11-04 22:40:36 +01:00
static const u8 sText_BerryUsed[] = _("BERRY USED");
2017-11-19 22:48:46 +01:00
static const u8 sText_SpaceBerry[] = _(" BERRY");
static const u8 sText_Time[] = _("Time:");
static const u8 sText_Min[] = _(" min. ");
static const u8 sText_Sec[] = _(" sec.");
static const u8 sText_MaximumSpeed[] = _("MAXIMUM SPEED");
static const u8 sText_RPM[] = _(" RPM");
static const u8 sText_Dot[] = _(".");
static const u8 sText_NewLine[] = _("\n");
2017-11-04 22:40:36 +01:00
static const u8 sText_Space[] = _(" ");
2017-11-19 22:48:46 +01:00
static const u8 sText_Ranking[] = _("RANKING");
static const u8 sText_TheLevelIs[] = _("The level is ");
static const u8 sText_TheFeelIs[] = _(", and the feel is ");
static const u8 sText_Dot2[] = _(".");
2017-11-04 22:40:36 +01:00
2020-08-23 00:20:22 +02:00
static const struct BgTemplate sBgTemplates[3] =
2017-11-04 22:40:36 +01:00
{
{
.bg = 0,
.charBaseIndex = 3,
.mapBaseIndex = 31,
.screenSize = 0,
.paletteMode = 0,
.priority = 0,
.baseTile = 0,
},
{
.bg = 1,
.charBaseIndex = 2,
.mapBaseIndex = 12,
.screenSize = 0,
.paletteMode = 0,
.priority = 1,
.baseTile = 0,
},
{
.bg = 2,
.charBaseIndex = 0,
.mapBaseIndex = 8,
.screenSize = 1,
.paletteMode = 1,
.priority = 0,
.baseTile = 0,
}
};
2020-08-23 00:20:22 +02:00
static const struct WindowTemplate sWindowTemplates[] =
2017-11-04 22:40:36 +01:00
{
{
2018-10-27 00:53:07 +02:00
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 6,
.width = 7,
.height = 2,
.paletteNum = 14,
.baseBlock = 0x28,
},
{
2018-10-27 00:53:07 +02:00
.bg = 0,
.tilemapLeft = 22,
.tilemapTop = 6,
.width = 7,
.height = 2,
.paletteNum = 14,
.baseBlock = 0x36,
},
{
2018-10-27 00:53:07 +02:00
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 12,
.width = 7,
.height = 2,
.paletteNum = 14,
.baseBlock = 0x44,
},
{
2018-10-27 00:53:07 +02:00
.bg = 0,
.tilemapLeft = 22,
.tilemapTop = 12,
.width = 7,
.height = 2,
.paletteNum = 14,
.baseBlock = 0x52,
},
{
2018-10-27 00:53:07 +02:00
.bg = 0,
.tilemapLeft = 2,
.tilemapTop = 15,
.width = 27,
.height = 4,
.paletteNum = 14,
.baseBlock = 0x60,
},
{
2018-10-27 00:53:07 +02:00
.bg = 0,
.tilemapLeft = 5,
.tilemapTop = 3,
.width = 21,
.height = 14,
.paletteNum = 14,
.baseBlock = 0x60,
},
2017-11-04 22:40:36 +01:00
DUMMY_WIN_TEMPLATE
};
2017-11-19 22:48:46 +01:00
static const struct WindowTemplate sBlender_YesNoWindowTemplate =
2017-11-04 22:40:36 +01:00
{
2018-10-27 00:53:07 +02:00
.bg = 0,
.tilemapLeft = 21,
.tilemapTop = 9,
.width = 5,
.height = 4,
.paletteNum = 14,
.baseBlock = 0xCC
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const s8 sPlayerArrowQuadrant[BLENDER_MAX_PLAYERS][2] =
2017-11-04 22:40:36 +01:00
{
{-1, -1}, {1, -1}, {-1, 1}, {1, 1}
};
2020-08-23 00:20:22 +02:00
static const u8 sPlayerArrowPos[BLENDER_MAX_PLAYERS][2] =
2017-11-04 22:40:36 +01:00
{
{72, 32}, {168, 32}, {72, 128}, {168, 128}
};
2020-08-23 00:20:22 +02:00
// -1 indicates no player at this position
static const u8 sPlayerIdMap[BLENDER_MAX_PLAYERS - 1][BLENDER_MAX_PLAYERS] =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
{-1, 0, 1, -1}, // 2 Players
{-1, 0, 1, 2}, // 3 Players
{0, 1, 2, 3} // 4 Players
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const u16 sArrowStartPos[] = {0, 0xC000, 0x4000, 0x8000};
static const u8 sArrowStartPosIds[BLENDER_MAX_PLAYERS - 1] = {1, 1, 0};
2017-11-19 22:48:46 +01:00
static const u8 sUnknown_083399E7[] = {32, 224, 96, 160, 0};
2017-11-04 22:40:36 +01:00
2020-08-23 00:20:22 +02:00
static const TaskFunc sLocalOpponentTasks[] =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
Task_HandleOpponent1,
Task_HandleOpponent2,
Task_HandleOpponent3
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct OamData sOam_PlayerArrow =
2017-11-04 22:40:36 +01:00
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
2017-11-04 22:40:36 +01:00
.mosaic = 0,
.bpp = ST_OAM_4BPP,
.shape = SPRITE_SHAPE(32x32),
2017-11-04 22:40:36 +01:00
.x = 0,
.matrixNum = 0,
.size = SPRITE_SIZE(32x32),
2017-11-04 22:40:36 +01:00
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
.affineParam = 0,
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_TopLeft[] =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
ANIMCMD_FRAME(16, 5, .vFlip = TRUE, .hFlip = TRUE),
2017-11-04 22:40:36 +01:00
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_TopRight[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(16, 5, .vFlip = TRUE),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_BottomLeft[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(16, 5, .hFlip = TRUE),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_BottomRight[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(16, 5, 0, 0),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_TopLeft_Flash[] =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
ANIMCMD_FRAME(48, 2, .vFlip = TRUE, .hFlip = TRUE),
ANIMCMD_FRAME(32, 5, .vFlip = TRUE, .hFlip = TRUE),
ANIMCMD_FRAME(48, 3, .vFlip = TRUE, .hFlip = TRUE),
ANIMCMD_FRAME(16, 5, .vFlip = TRUE, .hFlip = TRUE),
2017-11-04 22:40:36 +01:00
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_TopRight_Flash[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(48, 2, .vFlip = TRUE),
ANIMCMD_FRAME(32, 5, .vFlip = TRUE),
ANIMCMD_FRAME(48, 3, .vFlip = TRUE),
ANIMCMD_FRAME(16, 5, .vFlip = TRUE),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_BottomLeft_Flash[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(48, 2, .hFlip = TRUE),
ANIMCMD_FRAME(32, 5, .hFlip = TRUE),
ANIMCMD_FRAME(48, 3, .hFlip = TRUE),
ANIMCMD_FRAME(16, 5, .hFlip = TRUE),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_BottomRight_Flash[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(48, 2, 0, 0),
ANIMCMD_FRAME(32, 5, 0, 0),
ANIMCMD_FRAME(48, 3, 0, 0),
ANIMCMD_FRAME(16, 5, 0, 0),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_TopLeft_Off[] =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
ANIMCMD_FRAME(0, 5, .vFlip = TRUE, .hFlip = TRUE),
2017-11-04 22:40:36 +01:00
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_TopRight_Off[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(0, 5, .vFlip = TRUE),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_BottomLeft_Off[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(0, 5, .hFlip = TRUE),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_PlayerArrow_BottomRight_Off[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(0, 5, 0, 0),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd *const sAnims_PlayerArrow[] =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
sAnim_PlayerArrow_TopLeft,
sAnim_PlayerArrow_TopRight,
sAnim_PlayerArrow_BottomLeft,
sAnim_PlayerArrow_BottomRight,
sAnim_PlayerArrow_TopLeft_Flash,
sAnim_PlayerArrow_TopRight_Flash,
sAnim_PlayerArrow_BottomLeft_Flash,
sAnim_PlayerArrow_BottomRight_Flash,
sAnim_PlayerArrow_TopLeft_Off,
sAnim_PlayerArrow_TopRight_Off,
sAnim_PlayerArrow_BottomLeft_Off,
sAnim_PlayerArrow_BottomRight_Off
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct SpriteSheet sSpriteSheet_PlayerArrow =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
gBerryBlenderPlayerArrow_Gfx, 0x800, GFXTAG_PLAYER_ARROW
2017-11-04 22:40:36 +01:00
};
2017-11-19 22:48:46 +01:00
static const struct SpritePalette sSpritePal_BlenderMisc =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
gBerryBlenderMiscPalette, PALTAG_MISC
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct SpritePalette sSpritePal_PlayerArrow =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
gBerryBlenderArrowPalette, PALTAG_PLAYER_ARROW
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct SpriteTemplate sSpriteTemplate_PlayerArrow =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
.tileTag = GFXTAG_PLAYER_ARROW,
.paletteTag = PALTAG_PLAYER_ARROW,
.oam = &sOam_PlayerArrow,
.anims = sAnims_PlayerArrow,
2017-11-04 22:40:36 +01:00
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2020-08-23 00:20:22 +02:00
.callback = SpriteCB_PlayerArrow
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct OamData sOam_ScoreSymbols =
2017-11-04 22:40:36 +01:00
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
2017-11-04 22:40:36 +01:00
.mosaic = 0,
.bpp = ST_OAM_4BPP,
.shape = SPRITE_SHAPE(16x16),
2017-11-04 22:40:36 +01:00
.x = 0,
.matrixNum = 0,
.size = SPRITE_SIZE(16x16),
2017-11-04 22:40:36 +01:00
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_ScoreSymbols_Good[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(0, 20),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_ScoreSymbols_Miss[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(4, 20, 1, 0),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_ScoreSymbols_BestFlash[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(8, 4),
ANIMCMD_FRAME(12, 4),
ANIMCMD_FRAME(8, 4),
ANIMCMD_FRAME(12, 4),
ANIMCMD_FRAME(8, 4),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_ScoreSymbols_BestStatic[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(8, 4),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd *const sAnims_ScoreSymbols[] =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
[SCOREANIM_GOOD] = sAnim_ScoreSymbols_Good,
[SCOREANIM_MISS] = sAnim_ScoreSymbols_Miss,
[SCOREANIM_BEST_FLASH] = sAnim_ScoreSymbols_BestFlash,
[SCOREANIM_BEST_STATIC] = sAnim_ScoreSymbols_BestStatic,
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct SpriteSheet sSpriteSheet_ScoreSymbols =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
gBerryBlenderScoreSymbols_Gfx, 0x200, GFXTAG_SCORE_SYMBOLS
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct SpriteTemplate sSpriteTemplate_ScoreSymbols =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
.tileTag = GFXTAG_SCORE_SYMBOLS,
.paletteTag = PALTAG_MISC,
.oam = &sOam_ScoreSymbols,
.anims = sAnims_ScoreSymbols,
2017-11-04 22:40:36 +01:00
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2020-08-23 00:20:22 +02:00
.callback = SpriteCB_ScoreSymbol
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct OamData sOam_Particles =
2017-11-04 22:40:36 +01:00
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
2017-11-04 22:40:36 +01:00
.mosaic = 0,
.bpp = ST_OAM_4BPP,
.shape = SPRITE_SHAPE(8x8),
2017-11-04 22:40:36 +01:00
.x = 0,
.matrixNum = 0,
.size = SPRITE_SIZE(8x8),
2017-11-04 22:40:36 +01:00
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
.affineParam = 0,
};
static const union AnimCmd sSpriteAnim_821647C[] =
{
ANIMCMD_FRAME(0, 3),
ANIMCMD_FRAME(1, 4),
ANIMCMD_FRAME(3, 5),
ANIMCMD_FRAME(1, 4),
ANIMCMD_FRAME(0, 3),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_8216494[] =
{
ANIMCMD_FRAME(0, 3),
ANIMCMD_FRAME(2, 4),
ANIMCMD_FRAME(4, 5),
ANIMCMD_FRAME(2, 4),
ANIMCMD_FRAME(0, 3),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_82164AC[] =
{
ANIMCMD_FRAME(0, 2),
ANIMCMD_FRAME(1, 2),
ANIMCMD_FRAME(2, 2),
ANIMCMD_FRAME(4, 4),
ANIMCMD_FRAME(3, 3),
ANIMCMD_FRAME(2, 2),
ANIMCMD_FRAME(1, 2),
ANIMCMD_FRAME(0, 2),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_82164D0[] =
{
ANIMCMD_FRAME(5, 5, 1, 1),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_82164D8[] =
{
ANIMCMD_FRAME(6, 5, 1, 1),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd *const sAnims_Particles[] =
2017-11-04 22:40:36 +01:00
{
sSpriteAnim_821647C,
sSpriteAnim_8216494,
sSpriteAnim_82164AC,
sSpriteAnim_82164D0,
sSpriteAnim_82164D8,
};
2020-08-23 00:20:22 +02:00
static const struct SpriteSheet sSpriteSheet_Particles =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
gBerryBlenderParticles_Gfx, 0xE0, GFXTAG_PARTICLES
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct SpriteTemplate sSpriteTemplate_Particles =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
.tileTag = GFXTAG_PARTICLES,
.paletteTag = PALTAG_MISC,
.oam = &sOam_Particles,
.anims = sAnims_Particles,
2017-11-04 22:40:36 +01:00
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
};
2020-08-23 00:20:22 +02:00
static const struct OamData sOam_CountdownNumbers =
2017-11-04 22:40:36 +01:00
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
2017-11-04 22:40:36 +01:00
.mosaic = 0,
.bpp = ST_OAM_4BPP,
.shape = SPRITE_SHAPE(32x32),
2017-11-04 22:40:36 +01:00
.x = 0,
.matrixNum = 0,
.size = SPRITE_SIZE(32x32),
2017-11-04 22:40:36 +01:00
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
.affineParam = 0,
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_CountdownNumbers_3[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(32, 30),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_CountdownNumbers_2[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(16, 30),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_CountdownNumbers_1[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(0, 30),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd *const sAnims_CountdownNumbers[] =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
sAnim_CountdownNumbers_3,
sAnim_CountdownNumbers_2,
sAnim_CountdownNumbers_1,
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct SpriteSheet sSpriteSheet_CountdownNumbers =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
gBerryBlenderCountdownNumbers_Gfx, 0x600, GFXTAG_COUNTDOWN_NUMBERS
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct SpriteTemplate sSpriteTemplate_CountdownNumbers =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
.tileTag = GFXTAG_COUNTDOWN_NUMBERS,
.paletteTag = PALTAG_MISC,
.oam = &sOam_CountdownNumbers,
.anims = sAnims_CountdownNumbers,
2017-11-04 22:40:36 +01:00
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2020-08-23 00:20:22 +02:00
.callback = SpriteCB_CountdownNumber
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct OamData sOam_Start =
2017-11-04 22:40:36 +01:00
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
2017-11-04 22:40:36 +01:00
.mosaic = 0,
.bpp = ST_OAM_4BPP,
.shape = SPRITE_SHAPE(64x32),
2017-11-04 22:40:36 +01:00
.x = 0,
.matrixNum = 0,
.size = SPRITE_SIZE(64x32),
2017-11-04 22:40:36 +01:00
.tileNum = 0,
.priority = 1,
.paletteNum = 0,
.affineParam = 0,
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd sAnim_Start[] =
2017-11-04 22:40:36 +01:00
{
ANIMCMD_FRAME(0, 30),
ANIMCMD_END
};
2020-08-23 00:20:22 +02:00
static const union AnimCmd *const sAnims_Start[] =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
sAnim_Start,
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct SpriteSheet sSpriteSheet_Start =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
gBerryBlenderStart_Gfx, 0x400, GFXTAG_START
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
static const struct SpriteTemplate sSpriteTemplate_Start =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
.tileTag = GFXTAG_START,
.paletteTag = PALTAG_MISC,
.oam = &sOam_Start,
.anims = sAnims_Start,
2017-11-04 22:40:36 +01:00
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
2020-08-23 00:20:22 +02:00
.callback = SpriteCB_Start
2017-11-04 22:40:36 +01:00
};
2020-08-23 00:20:22 +02:00
// Data for throwing the berries in at the start
// x, y, bounce speed, x speed, y speed
static const s16 sBerrySpriteData[][5] =
2017-11-04 22:40:36 +01:00
{
{-10, 20, 10, 2, 1},
{250, 20, 10, -2, 1},
{-10, 140, 10, 2, -1},
{250, 140, 10, -2, -1},
};
2017-11-18 21:38:57 +01:00
static const u8 sOpponentBerrySets[][3] =
2017-11-04 22:40:36 +01:00
{
2020-08-23 00:20:22 +02:00
{4, 3, 2},
{0, 4, 3},
{1, 0, 4},
{2, 1, 0},
{3, 2, 1},
{0, 2, 3},
{1, 3, 4},
{2, 4, 0},
{3, 0, 1},
{4, 1, 2},
2017-11-04 22:40:36 +01:00
};
2017-11-18 21:38:57 +01:00
static const u8 sSpecialOpponentBerrySets[] = {30, 31, 32, 33, 34};
2017-11-04 22:40:36 +01:00
2020-08-23 00:20:22 +02:00
// "0 players" is link
static const u8 sNumPlayersToSpeedDivisor[] = {1, 1, 2, 3, 4};
2017-11-04 22:40:36 +01:00
2017-11-19 22:48:46 +01:00
static const u8 sUnknown_08339CC8[] = {0x1C, 0x16, 0x13, 0x1A, 0x19, 0x0E, 0x0D, 0x0B, 0x07, 0x15};
2017-11-04 22:40:36 +01:00
2017-11-19 22:48:46 +01:00
static const u8 sUnknown_08339CD2[] =
2017-11-04 22:40:36 +01:00
{
0xfe, 0x02, 0x02, 0xce, 0xd0, 0x37, 0x44, 0x07, 0x1f, 0x0c, 0x10,
0x00, 0xff, 0xfe, 0x91, 0x72, 0xce, 0xd0, 0x37, 0x44, 0x07, 0x1f,
0x0c, 0x10, 0x00, 0xff, 0x06, 0x27, 0x02, 0xff, 0x00, 0x0c, 0x48,
0x02, 0xff, 0x00, 0x01, 0x1f, 0x02, 0xff, 0x00, 0x16, 0x37, 0x02,
0xff, 0x00, 0x0d, 0x50, 0x4b, 0x02, 0xff, 0x06, 0x06, 0x06, 0x06,
0x05, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02
};
2018-09-02 17:10:06 +02:00
static const struct WindowTemplate sBlenderRecordWindowTemplate =
{
2018-10-27 00:53:07 +02:00
.bg = 0,
2018-09-02 17:10:06 +02:00
.tilemapLeft = 6,
.tilemapTop = 4,
.width = 18,
.height = 11,
.paletteNum = 15,
.baseBlock = 8
};
2017-09-30 16:12:35 +02:00
2017-11-18 16:11:34 +01:00
// code
2017-11-19 22:48:46 +01:00
static void Blender_ControlHitPitch(void)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
m4aMPlayPitchControl(&gMPlayInfo_SE2, 0xFFFF, 2 * (sBerryBlender->speed - 128));
2017-11-18 16:11:34 +01:00
}
2020-08-23 00:20:22 +02:00
static void VBlankCB_BerryBlender(void)
2017-11-18 16:11:34 +01:00
{
2017-11-19 22:48:46 +01:00
BerryBlender_SetBackgroundsPos();
2020-08-23 00:20:22 +02:00
SetBgAffine(2, sBerryBlender->bgAffineSrc.texX, sBerryBlender->bgAffineSrc.texY,
sBerryBlender->bgAffineSrc.scrX, sBerryBlender->bgAffineSrc.scrY,
sBerryBlender->bgAffineSrc.sx, sBerryBlender->bgAffineSrc.sy,
sBerryBlender->bgAffineSrc.alpha);
2017-11-18 16:11:34 +01:00
LoadOam();
ProcessSpriteCopyRequests();
TransferPlttBuffer();
}
2017-11-19 22:48:46 +01:00
static bool8 LoadBerryBlenderGfx(void)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
switch (sBerryBlender->loadGfxState)
2017-11-18 16:11:34 +01:00
{
case 0:
2020-08-23 00:20:22 +02:00
sBerryBlender->tilesBuffer = AllocZeroed(GetDecompressedDataSize(gBerryBlenderCenter_Gfx) + 100);
LZDecompressWram(gBerryBlenderCenter_Gfx, sBerryBlender->tilesBuffer);
sBerryBlender->loadGfxState++;
2017-11-18 16:11:34 +01:00
break;
case 1:
2020-08-23 00:20:22 +02:00
CopyToBgTilemapBuffer(2, sBlenderCenter_Tilemap, 0x400, 0);
2017-11-18 16:11:34 +01:00
CopyBgTilemapBufferToVram(2);
2020-08-23 00:20:22 +02:00
LoadPalette(sBlenderCenter_Pal, 0, 0x100);
sBerryBlender->loadGfxState++;
2017-11-18 16:11:34 +01:00
break;
case 2:
2020-08-23 00:20:22 +02:00
LoadBgTiles(2, sBerryBlender->tilesBuffer, GetDecompressedDataSize(gBerryBlenderCenter_Gfx), 0);
sBerryBlender->loadGfxState++;
2017-11-18 16:11:34 +01:00
break;
case 3:
2020-08-23 00:20:22 +02:00
LZDecompressWram(gBerryBlenderOuter_Gfx, sBerryBlender->tilesBuffer);
sBerryBlender->loadGfxState++;
2017-11-18 16:11:34 +01:00
break;
case 4:
2020-08-23 00:20:22 +02:00
LoadBgTiles(1, sBerryBlender->tilesBuffer, GetDecompressedDataSize(gBerryBlenderOuter_Gfx), 0);
sBerryBlender->loadGfxState++;
2017-11-18 16:11:34 +01:00
break;
case 5:
2020-08-23 00:20:22 +02:00
LZDecompressWram(gBerryBlenderOuter_Tilemap, sBerryBlender->tilesBuffer);
sBerryBlender->loadGfxState++;
2017-11-18 16:11:34 +01:00
break;
case 6:
2020-08-23 00:20:22 +02:00
CopyToBgTilemapBuffer(1, sBerryBlender->tilesBuffer, GetDecompressedDataSize(gBerryBlenderOuter_Tilemap), 0);
2017-11-18 16:11:34 +01:00
CopyBgTilemapBufferToVram(1);
2020-08-23 00:20:22 +02:00
sBerryBlender->loadGfxState++;
2017-11-18 16:11:34 +01:00
break;
case 7:
2020-08-23 00:20:22 +02:00
LoadPalette(sBlenderOuter_Pal, 0x80, 0x20);
sBerryBlender->loadGfxState++;
2017-11-18 16:11:34 +01:00
break;
case 8:
2020-08-23 00:20:22 +02:00
LoadSpriteSheet(&sSpriteSheet_PlayerArrow);
LoadSpriteSheet(&sSpriteSheet_Particles);
LoadSpriteSheet(&sSpriteSheet_ScoreSymbols);
sBerryBlender->loadGfxState++;
2017-11-18 16:11:34 +01:00
break;
case 9:
2020-08-23 00:20:22 +02:00
LoadSpriteSheet(&sSpriteSheet_CountdownNumbers);
LoadSpriteSheet(&sSpriteSheet_Start);
LoadSpritePalette(&sSpritePal_PlayerArrow);
2017-11-18 16:11:34 +01:00
LoadSpritePalette(&sSpritePal_BlenderMisc);
2020-08-23 00:20:22 +02:00
Free(sBerryBlender->tilesBuffer);
sBerryBlender->loadGfxState = 0;
2017-11-18 16:11:34 +01:00
return TRUE;
}
return FALSE;
}
2017-11-19 22:48:46 +01:00
static void sub_807F9D0(void)
2017-11-18 16:11:34 +01:00
{
FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 0x1E, 0x14);
CopyBgTilemapBufferToVram(0);
ShowBg(0);
ShowBg(1);
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
ChangeBgX(0, 0, 0);
ChangeBgY(0, 0, 0);
ChangeBgX(1, 0, 0);
ChangeBgY(1, 0, 0);
}
2017-11-19 22:48:46 +01:00
static void InitBerryBlenderWindows(void)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
if (InitWindows(sWindowTemplates))
2017-11-18 16:11:34 +01:00
{
s32 i;
DeactivateAllTextPrinters();
for (i = 0; i < 5; i++)
FillWindowPixelBuffer(i, PIXEL_FILL(0));
2017-11-18 16:11:34 +01:00
FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 0x1E, 0x14);
2019-04-01 00:59:52 +02:00
Menu_LoadStdPalAt(0xE0);
2017-11-18 16:11:34 +01:00
}
}
void DoBerryBlending(void)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender == NULL)
sBerryBlender = AllocZeroed(sizeof(*sBerryBlender));
2017-11-18 16:11:34 +01:00
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState = 0;
sBerryBlender->mainState = 0;
sBerryBlender->gameEndState = 0;
2017-11-18 16:11:34 +01:00
Blender_SetPlayerNamesLocal(gSpecialVar_0x8004);
SetMainCallback2(sub_807FAC8);
}
2017-11-19 22:48:46 +01:00
static void sub_807FAC8(void)
2017-11-18 16:11:34 +01:00
{
s32 i;
2020-08-23 00:20:22 +02:00
switch (sBerryBlender->mainState)
2017-11-18 16:11:34 +01:00
{
case 0:
SetGpuReg(REG_OFFSET_DISPCNT, 0);
ResetSpriteData();
FreeAllSpritePalettes();
SetVBlankCallback(NULL);
ResetBgsAndClearDma3BusyFlags(0);
2020-08-23 00:20:22 +02:00
InitBgsFromTemplates(1, sBgTemplates, ARRAY_COUNT(sBgTemplates));
SetBgTilemapBuffer(1, sBerryBlender->tilemapBuffers[0]);
SetBgTilemapBuffer(2, sBerryBlender->tilemapBuffers[1]);
2018-07-15 13:23:38 +02:00
LoadUserWindowBorderGfx(0, 1, 0xD0);
2018-06-17 16:48:58 +02:00
LoadMessageBoxGfx(0, 0x14, 0xF0);
2017-11-18 16:11:34 +01:00
InitBerryBlenderWindows();
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
sBerryBlender->maxProgressBarValue = 0;
sBerryBlender->progressBarValue = 0;
sBerryBlender->field_11A = 80;
sBerryBlender->bg_X = 0;
sBerryBlender->bg_Y = 0;
sBerryBlender->loadGfxState = 0;
2017-11-18 16:11:34 +01:00
sub_8082D28();
break;
case 1:
if (LoadBerryBlenderGfx())
{
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
sBerryBlender->playerArrowSpriteIds[i] = CreateSprite(&sSpriteTemplate_PlayerArrow, sPlayerArrowPos[i][0], sPlayerArrowPos[i][1], 1);
StartSpriteAnim(&gSprites[sBerryBlender->playerArrowSpriteIds[i]], i + 8);
2017-11-18 16:11:34 +01:00
}
2017-11-28 02:05:51 +01:00
if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
2017-11-18 16:11:34 +01:00
{
2019-04-04 23:05:46 +02:00
LoadWirelessStatusIndicatorSpriteGfx();
2017-12-04 04:01:06 +01:00
CreateWirelessStatusIndicatorSprite(0, 0);
2017-11-18 16:11:34 +01:00
}
2020-08-23 00:20:22 +02:00
SetVBlankCallback(VBlankCB_BerryBlender);
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
}
break;
case 2:
2019-04-04 23:05:46 +02:00
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, RGB_BLACK);
2017-11-18 16:11:34 +01:00
sub_8082D28();
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
break;
case 3:
sub_807F9D0();
if (!gPaletteFade.active)
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
break;
case 4:
2020-08-23 00:20:22 +02:00
if (Blender_PrintText(&sBerryBlender->textState, sText_BerryBlenderStart, GetPlayerTextSpeedDelay()))
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
break;
case 5:
2019-04-04 23:05:46 +02:00
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
break;
case 6:
if (!gPaletteFade.active)
{
FreeAllWindowBuffers();
UnsetBgTilemapBuffer(2);
UnsetBgTilemapBuffer(1);
SetVBlankCallback(NULL);
2020-08-23 00:20:22 +02:00
ChooseBerryForMachine(StartBlender);
2017-11-18 16:11:34 +01:00
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState = 0;
2017-11-18 16:11:34 +01:00
}
break;
}
AnimateSprites();
BuildOamBuffer();
RunTextPrinters();
UpdatePaletteFade();
}
2020-08-23 00:20:22 +02:00
#define sTargetY data[0]
#define sX data[1]
#define sY data[2]
#define sBounceSpeed data[3]
#define sYUpSpeed data[4]
#define sBounces data[5]
#define sXSpeed data[6]
#define sYDownSpeed data[7]
// For throwing berries into the machine
static void SpriteCB_Berry(struct Sprite* sprite)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
sprite->sX += sprite->sXSpeed;
sprite->sY -= sprite->sYUpSpeed;
sprite->sY += sprite->sYDownSpeed;
sprite->sTargetY += sprite->sYDownSpeed;
sprite->sYUpSpeed--;
2017-11-18 16:11:34 +01:00
2020-08-23 00:20:22 +02:00
if (sprite->sTargetY < sprite->sY)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
sprite->sBounceSpeed = sprite->sYUpSpeed = sprite->sBounceSpeed - 1;
2017-11-18 16:11:34 +01:00
2020-08-23 00:20:22 +02:00
if (++sprite->sBounces > 3)
2017-11-18 16:11:34 +01:00
DestroySprite(sprite);
else
PlaySE(SE_TB_KARA);
}
2020-08-23 00:20:22 +02:00
sprite->pos1.x = sprite->sX;
sprite->pos1.y = sprite->sY;
2017-11-18 16:11:34 +01:00
}
2020-08-23 00:20:22 +02:00
static void SetBerrySpriteData(struct Sprite* sprite, s16 x, s16 y, s16 bounceSpeed, s16 xSpeed, s16 ySpeed)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
sprite->sTargetY = y;
sprite->sX = x;
sprite->sY = y;
sprite->sBounceSpeed = bounceSpeed;
sprite->sYUpSpeed = 10;
sprite->sBounces = 0;
sprite->sXSpeed = xSpeed;
sprite->sYDownSpeed = ySpeed;
sprite->callback = SpriteCB_Berry;
2017-11-18 16:11:34 +01:00
}
2020-08-23 00:20:22 +02:00
#undef sTargetY
#undef sX
#undef sY
#undef sBounceSpeed
#undef sYUpSpeed
#undef sBounces
#undef sXSpeed
#undef sYDownSpeed
static void CreateBerrySprite(u16 a0, u8 playerId)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
u8 spriteId = CreateSpinningBerrySprite(a0 + FIRST_BERRY_INDEX - 10, 0, 80, playerId & 1);
SetBerrySpriteData(&gSprites[spriteId],
sBerrySpriteData[playerId][0],
sBerrySpriteData[playerId][1],
sBerrySpriteData[playerId][2],
sBerrySpriteData[playerId][3],
sBerrySpriteData[playerId][4]);
2017-11-18 16:11:34 +01:00
}
2020-08-23 00:20:22 +02:00
static void ConvertItemToBlenderBerry(struct BlenderBerry* berry, u16 itemId)
2017-11-18 16:11:34 +01:00
{
const struct Berry *berryInfo = GetBerryInfo(ITEM_TO_BERRY(itemId));
berry->itemId = itemId;
StringCopy(berry->name, berryInfo->name);
2017-11-27 20:03:41 +01:00
berry->flavors[FLAVOR_SPICY] = berryInfo->spicy;
berry->flavors[FLAVOR_DRY] = berryInfo->dry;
berry->flavors[FLAVOR_SWEET] = berryInfo->sweet;
berry->flavors[FLAVOR_BITTER] = berryInfo->bitter;
berry->flavors[FLAVOR_SOUR] = berryInfo->sour;
2017-11-18 16:11:34 +01:00
berry->smoothness = berryInfo->smoothness;
}
2017-11-19 22:48:46 +01:00
static void Blender_SetPlayerNamesLocal(u8 opponentsNum)
2017-11-18 16:11:34 +01:00
{
switch (opponentsNum)
{
2020-08-23 00:20:22 +02:00
case 0: // Link games have 0 in-game opponents
2017-11-18 16:11:34 +01:00
gInGameOpponentsNo = 0;
break;
case 1:
gInGameOpponentsNo = 1;
2020-08-23 00:20:22 +02:00
sBerryBlender->numPlayers = 2;
2017-11-18 16:11:34 +01:00
StringCopy(gLinkPlayers[0].name, gSaveBlock2Ptr->playerName);
if (!FlagGet(FLAG_HIDE_LILYCOVE_CONTEST_HALL_BLEND_MASTER))
2017-11-18 16:11:34 +01:00
StringCopy(gLinkPlayers[1].name, sBlenderOpponentsNames[BLENDER_MASTER]);
else
StringCopy(gLinkPlayers[1].name, sBlenderOpponentsNames[BLENDER_MISTER]);
gLinkPlayers[0].language = GAME_LANGUAGE;
gLinkPlayers[1].language = GAME_LANGUAGE;
break;
case 2:
gInGameOpponentsNo = 2;
2020-08-23 00:20:22 +02:00
sBerryBlender->numPlayers = 3;
2017-11-18 16:11:34 +01:00
StringCopy(gLinkPlayers[0].name, gSaveBlock2Ptr->playerName);
StringCopy(gLinkPlayers[1].name, sBlenderOpponentsNames[BLENDER_DUDE]);
StringCopy(gLinkPlayers[2].name, sBlenderOpponentsNames[BLENDER_LASSIE]);
gLinkPlayers[0].language = GAME_LANGUAGE;
gLinkPlayers[1].language = GAME_LANGUAGE;
gLinkPlayers[2].language = GAME_LANGUAGE;
break;
case 3:
gInGameOpponentsNo = 3;
2020-08-23 00:20:22 +02:00
sBerryBlender->numPlayers = 4;
2017-11-18 16:11:34 +01:00
StringCopy(gLinkPlayers[0].name, gSaveBlock2Ptr->playerName);
StringCopy(gLinkPlayers[1].name, sBlenderOpponentsNames[BLENDER_MISS]);
StringCopy(gLinkPlayers[2].name, sBlenderOpponentsNames[BLENDER_LADDIE]);
StringCopy(gLinkPlayers[3].name, sBlenderOpponentsNames[BLENDER_LASSIE]);
gLinkPlayers[0].language = GAME_LANGUAGE;
gLinkPlayers[1].language = GAME_LANGUAGE;
gLinkPlayers[2].language = GAME_LANGUAGE;
gLinkPlayers[3].language = GAME_LANGUAGE;
break;
}
}
2020-08-23 00:20:22 +02:00
static void StartBlender(void)
2017-11-18 16:11:34 +01:00
{
s32 i;
SetGpuReg(REG_OFFSET_DISPCNT, 0);
2020-08-23 00:20:22 +02:00
if (sBerryBlender == NULL)
sBerryBlender = AllocZeroed(sizeof(*sBerryBlender));
2017-11-18 16:11:34 +01:00
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState = 0;
sBerryBlender->field_10C = 0;
2017-11-18 16:11:34 +01:00
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
2020-08-23 00:20:22 +02:00
sBerryBlender->chosenItemId[i] = ITEM_NONE;
2017-11-18 16:11:34 +01:00
Blender_SetPlayerNamesLocal(gSpecialVar_0x8004);
if (gSpecialVar_0x8004 == 0)
2020-08-23 00:20:22 +02:00
SetMainCallback2(CB2_StartBlenderLink);
2017-11-18 16:11:34 +01:00
else
2020-08-23 00:20:22 +02:00
SetMainCallback2(CB2_StartBlenderLocal);
2017-11-18 16:11:34 +01:00
}
2020-08-23 00:20:22 +02:00
static void CB2_StartBlenderLink(void)
2017-11-18 16:11:34 +01:00
{
s32 i, j;
2020-08-23 00:20:22 +02:00
switch (sBerryBlender->mainState)
2017-11-18 16:11:34 +01:00
{
case 0:
2020-08-23 00:20:22 +02:00
InitBlenderBgs();
2019-10-11 10:14:09 +02:00
gLinkType = LINKTYPE_BERRY_BLENDER;
2020-08-23 00:20:22 +02:00
sBerryBlender->field_72 = 0;
2017-11-18 16:11:34 +01:00
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
sBerryBlender->field_64[i] = 0;
for (j = 0; j < NUM_SCORE_TYPES; j++)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->scores[i][j] = 0;
2017-11-18 16:11:34 +01:00
}
}
2020-08-23 00:20:22 +02:00
sBerryBlender->playAgainState = 0;
sBerryBlender->maxRPM = 0;
sBerryBlender->loadGfxState = 0;
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
break;
case 1:
if (LoadBerryBlenderGfx())
{
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
sub_8082D28();
}
break;
case 2:
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
sBerryBlender->playerArrowSpriteIds2[i] = CreateSprite(&sSpriteTemplate_PlayerArrow, sPlayerArrowPos[i][0], sPlayerArrowPos[i][1], 1);
StartSpriteAnim(&gSprites[sBerryBlender->playerArrowSpriteIds2[i]], i + 8);
2017-11-18 16:11:34 +01:00
}
2017-11-28 02:05:51 +01:00
if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
2017-11-18 16:11:34 +01:00
{
2019-04-04 23:05:46 +02:00
LoadWirelessStatusIndicatorSpriteGfx();
2017-12-04 04:01:06 +01:00
CreateWirelessStatusIndicatorSprite(0, 0);
2017-11-18 16:11:34 +01:00
}
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
break;
case 3:
2019-04-04 23:05:46 +02:00
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, RGB_BLACK);
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
break;
case 4:
sub_807F9D0();
if (!gPaletteFade.active)
{
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
}
break;
case 5:
2020-08-23 00:20:22 +02:00
Blender_PrintText(&sBerryBlender->textState, sText_CommunicationStandby, 0);
sBerryBlender->mainState = 8;
sBerryBlender->framesToWait = 0;
2017-11-18 16:11:34 +01:00
break;
case 8:
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
sBerryBlender->playerToThrowBerry = 0;
ConvertItemToBlenderBerry(&sBerryBlender->blendedBerries[0], gSpecialVar_ItemId);
memcpy(gBlockSendBuffer, &sBerryBlender->blendedBerries[0], sizeof(struct BlenderBerry));
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback();
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
2017-11-18 16:11:34 +01:00
break;
case 9:
2018-12-31 09:22:21 +01:00
if (IsLinkTaskFinished())
2017-11-18 16:11:34 +01:00
{
ResetBlockReceivedFlags();
if (GetMultiplayerId() == 0)
2020-08-13 09:09:47 +02:00
SendBlockRequest(4);
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
}
break;
case 10:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait > 20)
2017-11-18 16:11:34 +01:00
{
ClearDialogWindowAndFrameToTransparent(4, TRUE);
if (GetBlockReceivedStatus() == GetLinkPlayerCountAsBitFlags())
2017-11-18 16:11:34 +01:00
{
for (i = 0; i < GetLinkPlayerCount(); i++)
{
2020-08-23 00:20:22 +02:00
memcpy(&sBerryBlender->blendedBerries[i], &gBlockRecvBuffer[i][0], sizeof(struct BlenderBerry));
sBerryBlender->chosenItemId[i] = sBerryBlender->blendedBerries[i].itemId;
2017-11-18 16:11:34 +01:00
}
ResetBlockReceivedFlags();
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
}
}
break;
case 11:
2020-08-23 00:20:22 +02:00
sBerryBlender->numPlayers = GetLinkPlayerCount();
2017-11-18 16:11:34 +01:00
2020-08-23 00:20:22 +02:00
// Check each player, throw 1 berry in
2017-11-18 16:11:34 +01:00
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->playerToThrowBerry == sPlayerIdMap[sBerryBlender->numPlayers - 2][i])
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
CreateBerrySprite(sBerryBlender->chosenItemId[sBerryBlender->playerToThrowBerry], i);
2017-11-18 16:11:34 +01:00
break;
}
}
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->mainState++;
sBerryBlender->playerToThrowBerry++;
2017-11-18 16:11:34 +01:00
break;
case 12:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait > 60)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->playerToThrowBerry >= sBerryBlender->numPlayers)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
// Finished throwing berries in
sBerryBlender->mainState++;
sBerryBlender->arrowPos = sArrowStartPos[sArrowStartPosIds[sBerryBlender->numPlayers - 2]] - 0x5800;
2017-11-18 16:11:34 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
// Haven't finished throwing berries in, go back to prev step
sBerryBlender->mainState--;
2017-11-18 16:11:34 +01:00
}
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
2017-11-18 16:11:34 +01:00
}
break;
case 13:
2018-12-31 09:22:21 +01:00
if (IsLinkTaskFinished())
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
DrawBlenderCenter(&sBerryBlender->bgAffineSrc);
2017-11-18 16:11:34 +01:00
PlaySE(SE_RU_HYUU);
ShowBg(2);
}
break;
case 14:
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON);
2020-08-23 00:20:22 +02:00
sBerryBlender->arrowPos += 0x200;
sBerryBlender->field_11A += 4;
if (sBerryBlender->field_11A > 255)
2017-11-18 16:11:34 +01:00
{
SetGpuRegBits(REG_OFFSET_BG2CNT, 2);
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
sBerryBlender->field_11A = 256;
sBerryBlender->arrowPos = sArrowStartPos[sArrowStartPosIds[sBerryBlender->numPlayers - 2]];
sBerryBlender->framesToWait = 0;
2017-11-18 16:11:34 +01:00
PlaySE(SE_TRACK_DOOR);
sub_808074C();
2017-11-18 21:38:57 +01:00
Blender_PrintPlayerNames();
2017-11-18 16:11:34 +01:00
}
2020-08-23 00:20:22 +02:00
DrawBlenderCenter(&sBerryBlender->bgAffineSrc);
2017-11-18 16:11:34 +01:00
break;
case 15:
if (sub_8083380())
{
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
}
2020-08-23 00:20:22 +02:00
DrawBlenderCenter(&sBerryBlender->bgAffineSrc);
2017-11-18 16:11:34 +01:00
break;
case 16:
2020-08-23 00:20:22 +02:00
CreateSprite(&sSpriteTemplate_CountdownNumbers, 120, -16, 3);
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
break;
case 18:
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
break;
case 19:
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback();
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
break;
case 20:
2018-12-31 09:22:21 +01:00
if (IsLinkTaskFinished())
2017-11-18 16:11:34 +01:00
{
sub_800A418();
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 16:11:34 +01:00
}
break;
case 21:
2020-08-23 00:20:22 +02:00
sBerryBlender->speed = 128;
sBerryBlender->gameFrameTime = 0;
SetMainCallback2(CB2_PlayBlender);
2017-12-22 08:46:19 +01:00
if (GetCurrentMapMusic() != MUS_CYCLING)
2017-11-18 16:11:34 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->savedMusic = GetCurrentMapMusic();
2017-11-18 16:11:34 +01:00
}
2017-12-22 08:46:19 +01:00
PlayBGM(MUS_CYCLING);
2017-11-18 16:11:34 +01:00
break;
}
2020-08-23 00:20:22 +02:00
Blender_DummiedOutFunc(sBerryBlender->bg_X, sBerryBlender->bg_Y);
2017-11-18 16:11:34 +01:00
RunTasks();
AnimateSprites();
BuildOamBuffer();
RunTextPrinters();
UpdatePaletteFade();
}
2017-11-18 21:38:57 +01:00
2020-08-23 00:20:22 +02:00
static void InitBlenderBgs(void)
2017-11-18 21:38:57 +01:00
{
SetGpuReg(REG_OFFSET_DISPCNT, 0);
ResetSpriteData();
FreeAllSpritePalettes();
ResetTasks();
2020-08-23 00:20:22 +02:00
SetVBlankCallback(VBlankCB_BerryBlender);
2017-11-18 21:38:57 +01:00
ResetBgsAndClearDma3BusyFlags(0);
2020-08-23 00:20:22 +02:00
InitBgsFromTemplates(1, sBgTemplates, ARRAY_COUNT(sBgTemplates));
2017-11-18 21:38:57 +01:00
2020-08-23 00:20:22 +02:00
SetBgTilemapBuffer(1, sBerryBlender->tilemapBuffers[0]);
SetBgTilemapBuffer(2, sBerryBlender->tilemapBuffers[1]);
2018-07-15 13:23:38 +02:00
LoadUserWindowBorderGfx(0, 1, 0xD0);
2018-06-17 16:48:58 +02:00
LoadMessageBoxGfx(0, 0x14, 0xF0);
2017-11-18 21:38:57 +01:00
InitBerryBlenderWindows();
2020-08-23 00:20:22 +02:00
sBerryBlender->field_44 = 0;
sBerryBlender->speed = 0;
sBerryBlender->arrowPos = 0;
sBerryBlender->maxRPM = 0;
sBerryBlender->bg_X = 0;
sBerryBlender->bg_Y = 0;
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
static u8 GetArrowProximity(u16 arrowPos, u8 playerId)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
u32 pos = (arrowPos / 256) + 24;
u8 arrID = sBerryBlender->field_96[playerId];
2017-11-19 22:48:46 +01:00
u32 var2 = sUnknown_083399E7[arrID];
2017-11-18 21:38:57 +01:00
2020-08-23 00:20:22 +02:00
if (pos >= var2 && pos < var2 + 48)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
if (pos >= var2 + 20 && pos < var2 + 28)
return PROXIMITY_BEST;
2017-11-18 21:38:57 +01:00
else
2020-08-23 00:20:22 +02:00
return PROXIMITY_GOOD;
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
return PROXIMITY_MISS;
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
static void SetOpponentsBerryData(u16 playerBerryItemId, u8 playersNum, struct BlenderBerry* playerBerry)
2017-11-18 21:38:57 +01:00
{
u16 opponentSetId = 0;
u16 opponentBerryId;
u16 var;
u16 i;
if (playerBerryItemId == ITEM_ENIGMA_BERRY)
{
2017-11-27 20:03:41 +01:00
for (i = 0; i < FLAVOR_COUNT; i++)
2017-11-18 21:38:57 +01:00
{
2017-11-27 20:03:41 +01:00
if (playerBerry->flavors[opponentSetId] > playerBerry->flavors[i])
2017-11-18 21:38:57 +01:00
opponentSetId = i;
}
opponentSetId += 5;
}
else
{
2020-08-23 00:20:22 +02:00
opponentSetId = ITEM_TO_BERRY(playerBerryItemId) - 1;
2017-11-18 21:38:57 +01:00
if (opponentSetId >= 5)
opponentSetId = (opponentSetId % 5) + 5;
}
for (i = 0; i < playersNum - 1; i++)
{
opponentBerryId = sOpponentBerrySets[opponentSetId][i];
2020-08-23 00:20:22 +02:00
var = ITEM_TO_BERRY(playerBerryItemId) - 31;
if (!FlagGet(FLAG_HIDE_LILYCOVE_CONTEST_HALL_BLEND_MASTER) && gSpecialVar_0x8004 == 1)
2017-11-18 21:38:57 +01:00
{
opponentSetId %= 5;
opponentBerryId = sSpecialOpponentBerrySets[opponentSetId];
if (var <= 4)
opponentBerryId -= 5;
}
2018-09-01 18:36:08 +02:00
Blender_SetParticipantBerryData(i + 1, opponentBerryId + FIRST_BERRY_INDEX);
2017-11-18 21:38:57 +01:00
}
}
2017-11-19 22:48:46 +01:00
static void sub_808074C(void)
2017-11-18 21:38:57 +01:00
{
s32 i, j;
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
sBerryBlender->field_96[i] = 0xFF;
sBerryBlender->field_8E[i] = sPlayerIdMap[sBerryBlender->numPlayers - 2][i];
2017-11-18 21:38:57 +01:00
}
for (j = 0; j < BLENDER_MAX_PLAYERS; j++)
{
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_8E[i] == j)
sBerryBlender->field_96[j] = i;
2017-11-18 21:38:57 +01:00
}
}
}
2017-11-19 22:48:46 +01:00
static void Blender_PrintPlayerNames(void)
2017-11-18 21:38:57 +01:00
{
2017-11-19 22:48:46 +01:00
s32 i, xPos;
2017-11-18 21:38:57 +01:00
u32 multiplayerId = 0;
u8 text[20];
if (gReceivedRemoteLinkPlayers)
multiplayerId = GetMultiplayerId();
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_8E[i] != 0xFF)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->playerArrowSpriteIds[sBerryBlender->field_8E[i]] = sBerryBlender->playerArrowSpriteIds2[i];
StartSpriteAnim(&gSprites[sBerryBlender->playerArrowSpriteIds[sBerryBlender->field_8E[i]]], i);
2017-11-18 21:38:57 +01:00
text[0] = EOS;
2020-08-23 00:20:22 +02:00
StringCopy(text, gLinkPlayers[sBerryBlender->field_8E[i]].name);
2017-11-19 22:48:46 +01:00
xPos = GetStringCenterAlignXOffset(1, text, 0x38);
2017-11-18 21:38:57 +01:00
2020-08-23 00:20:22 +02:00
if (multiplayerId == sBerryBlender->field_8E[i])
2017-11-19 22:48:46 +01:00
Blender_AddTextPrinter(i, text, xPos, 1, 0, 2);
2017-11-18 21:38:57 +01:00
else
2017-11-19 22:48:46 +01:00
Blender_AddTextPrinter(i, text, xPos, 1, 0, 1);
2017-11-18 21:38:57 +01:00
PutWindowTilemap(i);
CopyWindowToVram(i, 3);
}
}
}
2020-08-23 00:20:22 +02:00
static void CB2_StartBlenderLocal(void)
2017-11-18 21:38:57 +01:00
{
s32 i, j;
2020-08-23 00:20:22 +02:00
switch (sBerryBlender->mainState)
2017-11-18 21:38:57 +01:00
{
case 0:
2020-06-06 22:46:19 +02:00
SetWirelessCommType0();
2020-08-23 00:20:22 +02:00
InitBlenderBgs();
2018-09-01 18:36:08 +02:00
Blender_SetParticipantBerryData(0, gSpecialVar_ItemId);
2020-08-23 00:20:22 +02:00
ConvertItemToBlenderBerry(&sBerryBlender->blendedBerries[0], gSpecialVar_ItemId);
SetOpponentsBerryData(gSpecialVar_ItemId, sBerryBlender->numPlayers, &sBerryBlender->blendedBerries[0]);
2017-11-18 21:38:57 +01:00
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
sBerryBlender->field_64[i] = 0;
for (j = 0; j < NUM_SCORE_TYPES; j++)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->scores[i][j] = 0;
2017-11-18 21:38:57 +01:00
}
}
2020-08-23 00:20:22 +02:00
sBerryBlender->playAgainState = 0;
sBerryBlender->loadGfxState = 0;
2019-10-11 10:14:09 +02:00
gLinkType = LINKTYPE_BERRY_BLENDER;
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 21:38:57 +01:00
break;
case 1:
if (LoadBerryBlenderGfx())
{
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 21:38:57 +01:00
sub_8082D28();
}
break;
case 2:
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
sBerryBlender->playerArrowSpriteIds2[i] = CreateSprite(&sSpriteTemplate_PlayerArrow, sPlayerArrowPos[i][0], sPlayerArrowPos[i][1], 1);
StartSpriteAnim(&gSprites[sBerryBlender->playerArrowSpriteIds2[i]], i + 8);
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 21:38:57 +01:00
break;
case 3:
2019-04-04 23:05:46 +02:00
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, RGB_BLACK);
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
sBerryBlender->framesToWait = 0;
2017-11-18 21:38:57 +01:00
break;
case 4:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait == 2)
2017-11-18 21:38:57 +01:00
sub_807F9D0();
if (!gPaletteFade.active)
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState = 8;
2017-11-18 21:38:57 +01:00
break;
case 8:
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState = 11;
sBerryBlender->playerToThrowBerry = 0;
2017-11-18 21:38:57 +01:00
break;
case 11:
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
u32 posId = sPlayerIdMap[sBerryBlender->numPlayers - 2][i];
if (sBerryBlender->playerToThrowBerry == posId)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
CreateBerrySprite(sBerryBlender->chosenItemId[sBerryBlender->playerToThrowBerry], i);
2017-11-18 21:38:57 +01:00
break;
}
}
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->mainState++;
sBerryBlender->playerToThrowBerry++;
2017-11-18 21:38:57 +01:00
break;
case 12:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait > 60)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->playerToThrowBerry >= sBerryBlender->numPlayers)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->arrowPos = sArrowStartPos[sArrowStartPosIds[sBerryBlender->numPlayers - 2]] - 0x5800;
sBerryBlender->mainState++;
2017-11-18 21:38:57 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState--;
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
2017-11-18 21:38:57 +01:00
}
break;
case 13:
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 21:38:57 +01:00
sub_808074C();
PlaySE(SE_RU_HYUU);
2020-08-23 00:20:22 +02:00
DrawBlenderCenter(&sBerryBlender->bgAffineSrc);
2017-11-18 21:38:57 +01:00
ShowBg(2);
break;
case 14:
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON);
2020-08-23 00:20:22 +02:00
sBerryBlender->arrowPos += 0x200;
sBerryBlender->field_11A += 4;
if (sBerryBlender->field_11A > 255)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
sBerryBlender->field_11A = 256;
sBerryBlender->arrowPos = sArrowStartPos[sArrowStartPosIds[sBerryBlender->numPlayers - 2]];
2017-11-18 21:38:57 +01:00
SetGpuRegBits(REG_OFFSET_BG2CNT, 2);
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
2017-11-18 21:38:57 +01:00
PlaySE(SE_TRACK_DOOR);
Blender_PrintPlayerNames();
}
2020-08-23 00:20:22 +02:00
DrawBlenderCenter(&sBerryBlender->bgAffineSrc);
2017-11-18 21:38:57 +01:00
break;
case 15:
if (sub_8083380())
{
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
DrawBlenderCenter(&sBerryBlender->bgAffineSrc);
2017-11-18 21:38:57 +01:00
break;
case 16:
2020-08-23 00:20:22 +02:00
CreateSprite(&sSpriteTemplate_CountdownNumbers, 120, -16, 3);
sBerryBlender->mainState++;
2017-11-18 21:38:57 +01:00
break;
case 18:
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 21:38:57 +01:00
break;
case 19:
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 21:38:57 +01:00
break;
case 20:
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-18 21:38:57 +01:00
break;
case 21:
sub_8080DF8();
2020-08-23 00:20:22 +02:00
sBerryBlender->speed = 128;
sBerryBlender->gameFrameTime = 0;
sBerryBlender->field_123 = 0;
sBerryBlender->field_72 = 0;
SetMainCallback2(CB2_PlayBlender);
2017-11-18 21:38:57 +01:00
if (gSpecialVar_0x8004 == 1)
{
if (!FlagGet(FLAG_HIDE_LILYCOVE_CONTEST_HALL_BLEND_MASTER))
2020-08-23 00:20:22 +02:00
sBerryBlender->opponentTaskIds[0] = CreateTask(Task_HandleBerryMaster, 10);
2017-11-18 21:38:57 +01:00
else
2020-08-23 00:20:22 +02:00
sBerryBlender->opponentTaskIds[0] = CreateTask(sLocalOpponentTasks[0], 10);
2017-11-18 21:38:57 +01:00
}
if (gSpecialVar_0x8004 > 1)
{
for (i = 0; i < gSpecialVar_0x8004; i++)
2020-08-23 00:20:22 +02:00
sBerryBlender->opponentTaskIds[i] = CreateTask(sLocalOpponentTasks[i], 10 + i);
2017-11-18 21:38:57 +01:00
}
2017-12-22 08:46:19 +01:00
if (GetCurrentMapMusic() != MUS_CYCLING)
2020-08-23 00:20:22 +02:00
sBerryBlender->savedMusic = GetCurrentMapMusic();
2017-11-18 21:38:57 +01:00
2017-12-22 08:46:19 +01:00
PlayBGM(MUS_CYCLING);
2017-11-18 21:38:57 +01:00
PlaySE(SE_MOTER);
Blender_ControlHitPitch();
break;
}
2020-08-23 00:20:22 +02:00
Blender_DummiedOutFunc(sBerryBlender->bg_X, sBerryBlender->bg_Y);
2017-11-18 21:38:57 +01:00
RunTasks();
AnimateSprites();
BuildOamBuffer();
RunTextPrinters();
UpdatePaletteFade();
}
2017-11-19 22:48:46 +01:00
static void sub_8080DF8(void)
2017-11-18 21:38:57 +01:00
{
s32 i;
for (i = 0; i < CMD_LENGTH / 2; i++)
2017-11-18 21:38:57 +01:00
{
gSendCmd[0] = 0;
gSendCmd[2] = 0;
gRecvCmds[i][0] = 0;
gRecvCmds[i][2] = 0;
}
}
2020-08-23 00:20:22 +02:00
#define tTimer data[0]
#define tDelay data[1]
#define tPlayerId data[2]
static void Task_OpponentMiss(u8 taskId)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
if(++gTasks[taskId].tTimer > gTasks[taskId].tDelay)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
gRecvCmds[gTasks[taskId].tPlayerId][2] = LINKCMD_BLENDER_SCORE_MISS;
2017-11-18 21:38:57 +01:00
DestroyTask(taskId);
}
}
2020-08-23 00:20:22 +02:00
static void CreateOpponentMissTask(u8 playerId, u8 delay)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
u8 taskId = CreateTask(Task_OpponentMiss, 80);
gTasks[taskId].tDelay = delay;
gTasks[taskId].tPlayerId = playerId;
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
#undef tTimer
#undef tDelay
#undef tPlayerId
static void Task_HandleOpponent1(u8 taskId)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
if (GetArrowProximity(sBerryBlender->arrowPos, 1) == PROXIMITY_BEST)
2017-11-18 21:38:57 +01:00
{
if (gTasks[taskId].data[0] == 0)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_123 == 0)
2017-11-18 21:38:57 +01:00
{
u8 rand = Random() / 655;
2020-08-23 00:20:22 +02:00
if (sBerryBlender->speed < 500)
2017-11-18 21:38:57 +01:00
{
if (rand > 75)
2020-08-23 00:20:22 +02:00
gRecvCmds[1][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
else
2020-08-23 00:20:22 +02:00
gRecvCmds[1][2] = LINKCMD_BLENDER_SCORE_GOOD;
2017-11-18 21:38:57 +01:00
2020-08-23 00:20:22 +02:00
gRecvCmds[1][2] = LINKCMD_BLENDER_SCORE_GOOD;
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
else if (sBerryBlender->speed < 1500)
2017-11-18 21:38:57 +01:00
{
if (rand > 80)
{
2020-08-23 00:20:22 +02:00
gRecvCmds[1][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
}
else
{
u8 value = rand - 21;
if (value < 60)
2020-08-23 00:20:22 +02:00
gRecvCmds[1][2] = LINKCMD_BLENDER_SCORE_GOOD;
2017-11-18 21:38:57 +01:00
else if (rand < 10)
2020-08-23 00:20:22 +02:00
CreateOpponentMissTask(1, 5);
2017-11-18 21:38:57 +01:00
}
}
else if (rand <= 90)
{
u8 value = rand - 71;
if (value < 20)
2020-08-23 00:20:22 +02:00
gRecvCmds[1][2] = LINKCMD_BLENDER_SCORE_GOOD;
2017-11-18 21:38:57 +01:00
else if (rand < 30)
2020-08-23 00:20:22 +02:00
CreateOpponentMissTask(1, 5);
2017-11-18 21:38:57 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
gRecvCmds[1][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
}
}
else
{
2020-08-23 00:20:22 +02:00
gRecvCmds[1][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
}
gTasks[taskId].data[0] = 1;
}
}
else
{
gTasks[taskId].data[0] = 0;
}
}
2020-08-23 00:20:22 +02:00
static void Task_HandleOpponent2(u8 taskId)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
u32 var1 = (sBerryBlender->arrowPos + 0x1800) & 0xFFFF;
u32 var2 = sBerryBlender->field_96[2] & 0xFF;
2017-11-19 22:48:46 +01:00
if ((var1 >> 8) > sUnknown_083399E7[var2] + 20 && (var1 >> 8) < sUnknown_083399E7[var2] + 40)
2017-11-18 21:38:57 +01:00
{
if (gTasks[taskId].data[0] == 0)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_123 == 0)
2017-11-18 21:38:57 +01:00
{
u8 rand = Random() / 655;
2020-08-23 00:20:22 +02:00
if (sBerryBlender->speed < 500)
2017-11-18 21:38:57 +01:00
{
if (rand > 66)
2020-08-23 00:20:22 +02:00
gRecvCmds[2][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
else
2020-08-23 00:20:22 +02:00
gRecvCmds[2][2] = LINKCMD_BLENDER_SCORE_GOOD;
2017-11-18 21:38:57 +01:00
}
else
{
u8 value;
if (rand > 65)
2020-08-23 00:20:22 +02:00
gRecvCmds[2][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
value = rand - 41;
if (value < 25)
2020-08-23 00:20:22 +02:00
gRecvCmds[2][2] = LINKCMD_BLENDER_SCORE_GOOD;
2017-11-18 21:38:57 +01:00
if (rand < 10)
2020-08-23 00:20:22 +02:00
CreateOpponentMissTask(2, 5);
2017-11-18 21:38:57 +01:00
}
gTasks[taskId].data[0] = 1;
}
else
{
2020-08-23 00:20:22 +02:00
gRecvCmds[2][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
gTasks[taskId].data[0] = 1;
}
}
}
else
{
gTasks[taskId].data[0] = 0;
}
}
2020-08-23 00:20:22 +02:00
static void Task_HandleOpponent3(u8 taskId)
2017-11-18 21:38:57 +01:00
{
u32 var1, var2;
2020-08-23 00:20:22 +02:00
var1 = (sBerryBlender->arrowPos + 0x1800) & 0xFFFF;
var2 = sBerryBlender->field_96[3] & 0xFF;
2017-11-19 22:48:46 +01:00
if ((var1 >> 8) > sUnknown_083399E7[var2] + 20 && (var1 >> 8) < sUnknown_083399E7[var2] + 40)
2017-11-18 21:38:57 +01:00
{
if (gTasks[taskId].data[0] == 0)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_123 == 0)
2017-11-18 21:38:57 +01:00
{
u8 rand = (Random() / 655);
2020-08-23 00:20:22 +02:00
if (sBerryBlender->speed < 500)
2017-11-18 21:38:57 +01:00
{
if (rand > 88)
2020-08-23 00:20:22 +02:00
gRecvCmds[3][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
else
2020-08-23 00:20:22 +02:00
gRecvCmds[3][2] = LINKCMD_BLENDER_SCORE_GOOD;
2017-11-18 21:38:57 +01:00
}
else
{
if (rand > 60)
{
2020-08-23 00:20:22 +02:00
gRecvCmds[3][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
}
else
{
s8 value = rand - 56; // makes me wonder what the original code was
u8 value2 = value;
if (value2 < 5)
2020-08-23 00:20:22 +02:00
gRecvCmds[3][2] = LINKCMD_BLENDER_SCORE_GOOD;
2017-11-18 21:38:57 +01:00
}
if (rand < 5)
2020-08-23 00:20:22 +02:00
CreateOpponentMissTask(3, 5);
2017-11-18 21:38:57 +01:00
}
gTasks[taskId].data[0] = 1;
}
else
{
2020-08-23 00:20:22 +02:00
gRecvCmds[3][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
gTasks[taskId].data[0] = 1;
}
}
}
else
{
gTasks[taskId].data[0] = 0;
}
}
2020-08-23 00:20:22 +02:00
static void Task_HandleBerryMaster(u8 taskId)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
if (GetArrowProximity(sBerryBlender->arrowPos, 1) == PROXIMITY_BEST)
2017-11-18 21:38:57 +01:00
{
if (gTasks[taskId].data[0] == 0)
{
2020-08-23 00:20:22 +02:00
gRecvCmds[1][2] = LINKCMD_BLENDER_SCORE_BEST;
2017-11-18 21:38:57 +01:00
gTasks[taskId].data[0] = 1;
}
}
else
{
gTasks[taskId].data[0] = 0;
}
}
2020-08-23 00:20:22 +02:00
static void CreateScoreSymbolSprite(u16 cmd, u8 arrowId)
2017-11-18 21:38:57 +01:00
{
u8 spriteId;
2020-08-23 00:20:22 +02:00
spriteId = CreateSprite(&sSpriteTemplate_ScoreSymbols,
sPlayerArrowPos[arrowId][0] - (10 * sPlayerArrowQuadrant[arrowId][0]),
sPlayerArrowPos[arrowId][1] - (10 * sPlayerArrowQuadrant[arrowId][1]),
2017-11-18 21:38:57 +01:00
1);
2020-08-23 00:20:22 +02:00
if (cmd == LINKCMD_BLENDER_SCORE_BEST)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
StartSpriteAnim(&gSprites[spriteId], SCOREANIM_BEST_FLASH);
gSprites[spriteId].callback = SpriteCB_ScoreSymbolBest;
2017-11-18 21:38:57 +01:00
PlaySE(SE_RU_GASHIN);
}
2020-08-23 00:20:22 +02:00
else if (cmd == LINKCMD_BLENDER_SCORE_GOOD)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
StartSpriteAnim(&gSprites[spriteId], SCOREANIM_GOOD);
2017-11-18 21:38:57 +01:00
PlaySE(SE_SEIKAI);
}
2020-08-23 00:20:22 +02:00
else if (cmd == LINKCMD_BLENDER_SCORE_MISS)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
StartSpriteAnim(&gSprites[spriteId], SCOREANIM_MISS);
2017-11-18 21:38:57 +01:00
PlaySE(SE_HAZURE);
}
2020-08-23 00:20:22 +02:00
CreateParticleSprites();
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
static void sub_8081370(u16 cmd)
2017-11-18 21:38:57 +01:00
{
Blender_ControlHitPitch();
2020-08-23 00:20:22 +02:00
switch (cmd)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
case LINKCMD_BLENDER_SCORE_BEST:
if (sBerryBlender->speed < 1500) {
sBerryBlender->speed += (384 / sNumPlayersToSpeedDivisor[sBerryBlender->numPlayers]);
}
2017-11-18 21:38:57 +01:00
else
{
2020-08-23 00:20:22 +02:00
sBerryBlender->speed += (128 / sNumPlayersToSpeedDivisor[sBerryBlender->numPlayers]);
sub_80832BC(&sBerryBlender->bg_X, (sBerryBlender->speed / 100) - 10);
sub_80832BC(&sBerryBlender->bg_Y, (sBerryBlender->speed / 100) - 10);
2017-11-18 21:38:57 +01:00
}
break;
2020-08-23 00:20:22 +02:00
case LINKCMD_BLENDER_SCORE_GOOD:
if (sBerryBlender->speed < 1500)
sBerryBlender->speed += (256 / sNumPlayersToSpeedDivisor[sBerryBlender->numPlayers]);
2017-11-18 21:38:57 +01:00
break;
2020-08-23 00:20:22 +02:00
case LINKCMD_BLENDER_SCORE_MISS:
sBerryBlender->speed -= (256 / sNumPlayersToSpeedDivisor[sBerryBlender->numPlayers]);
if (sBerryBlender->speed < 128)
sBerryBlender->speed = 128;
2017-11-18 21:38:57 +01:00
break;
}
}
2017-11-19 22:48:46 +01:00
static bool32 sub_80814B0(u16 arg0, u16 arg1, u16 arg2)
2017-11-18 21:38:57 +01:00
{
2017-11-28 02:05:51 +01:00
if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
2017-11-18 21:38:57 +01:00
{
if ((arg0 & 0xFF00) == arg2)
return TRUE;
}
else
{
if (arg0 == arg1)
return TRUE;
}
return FALSE;
}
2020-08-23 00:20:22 +02:00
static void UpdateOpponentScores(void)
2017-11-18 21:38:57 +01:00
{
s32 i;
if (gSpecialVar_0x8004 != 0)
{
2020-08-23 00:20:22 +02:00
// Local game, simulate NPCs sending link commands
2017-11-18 21:38:57 +01:00
if (gSendCmd[2] != 0)
{
2017-11-19 22:48:46 +01:00
gRecvCmds[0][2] = gSendCmd[2];
2020-08-23 00:20:22 +02:00
gRecvCmds[0][0] = LINKCMD_SEND_HELD_KEYS;
2017-11-18 21:38:57 +01:00
gSendCmd[2] = 0;
}
2020-08-23 00:20:22 +02:00
for (i = 1; i < BLENDER_MAX_PLAYERS; i++)
2017-11-18 21:38:57 +01:00
{
2017-11-19 22:48:46 +01:00
if (gRecvCmds[i][2] != 0)
2020-08-23 00:20:22 +02:00
gRecvCmds[i][0] = LINKCMD_SEND_HELD_KEYS;
2017-11-18 21:38:57 +01:00
}
}
2020-08-23 00:20:22 +02:00
for (i = 0; i < sBerryBlender->numPlayers; i++)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
if (sub_80814B0(gRecvCmds[i][0], LINKCMD_SEND_HELD_KEYS, LINKCMD_0x4400))
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
u32 arrowId = sBerryBlender->field_96[i];
if (gRecvCmds[i][2] == LINKCMD_BLENDER_SCORE_BEST)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
sub_8081370(LINKCMD_BLENDER_SCORE_BEST);
sBerryBlender->progressBarValue += (sBerryBlender->speed / 55);
if (sBerryBlender->progressBarValue >= MAX_PROGRESS_BAR)
sBerryBlender->progressBarValue = MAX_PROGRESS_BAR;
CreateScoreSymbolSprite(LINKCMD_BLENDER_SCORE_BEST, arrowId);
sBerryBlender->scores[i][SCORE_BEST]++;
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
else if (gRecvCmds[i][2] == LINKCMD_BLENDER_SCORE_GOOD)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
sub_8081370(LINKCMD_BLENDER_SCORE_GOOD);
sBerryBlender->progressBarValue += (sBerryBlender->speed / 70);
CreateScoreSymbolSprite(LINKCMD_BLENDER_SCORE_GOOD, arrowId);
sBerryBlender->scores[i][SCORE_GOOD]++;
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
else if (gRecvCmds[i][2] == LINKCMD_BLENDER_SCORE_MISS)
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
CreateScoreSymbolSprite(LINKCMD_BLENDER_SCORE_MISS, arrowId);
sub_8081370(LINKCMD_BLENDER_SCORE_MISS);
if (sBerryBlender->scores[i][SCORE_MISS] < 999)
sBerryBlender->scores[i][SCORE_MISS]++;
2017-11-18 21:38:57 +01:00
}
2020-08-23 00:20:22 +02:00
if (gRecvCmds[i][2] == LINKCMD_BLENDER_SCORE_MISS
|| gRecvCmds[2][i] == LINKCMD_BLENDER_SCORE_BEST
|| gRecvCmds[2][i] == LINKCMD_BLENDER_SCORE_GOOD) // could be a bug, 2 and i are reversed
2017-11-18 21:38:57 +01:00
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->speed > 1500)
m4aMPlayTempoControl(&gMPlayInfo_BGM, ((sBerryBlender->speed - 750) / 20) + 256);
2017-11-18 21:38:57 +01:00
else
m4aMPlayTempoControl(&gMPlayInfo_BGM, 0x100);
2017-11-18 21:38:57 +01:00
}
}
}
if (gSpecialVar_0x8004 != 0)
{
2020-08-23 00:20:22 +02:00
for (i = 0; i < sBerryBlender->numPlayers; i++)
2017-11-19 22:48:46 +01:00
{
gRecvCmds[i][0] = 0;
gRecvCmds[i][2] = 0;
}
}
}
2020-08-23 00:20:22 +02:00
static void HandlePlayerInput(void)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
u8 arrowId;
bool8 pressedA = FALSE;
2017-11-19 22:48:46 +01:00
u8 playerId = 0;
2020-08-23 00:20:22 +02:00
if (gReceivedRemoteLinkPlayers)
2017-11-19 22:48:46 +01:00
playerId = GetMultiplayerId();
2020-08-23 00:20:22 +02:00
arrowId = sBerryBlender->field_96[playerId];
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
if (sBerryBlender->gameEndState == 0)
2017-11-19 22:48:46 +01:00
{
if (gSaveBlock2Ptr->optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A && gMain.newKeys & A_BUTTON)
{
if ((gMain.heldKeysRaw & (A_BUTTON | L_BUTTON)) != (A_BUTTON | L_BUTTON))
2020-08-23 00:20:22 +02:00
pressedA = TRUE;
2017-11-19 22:48:46 +01:00
}
else if (gMain.newKeys & A_BUTTON)
{
2020-08-23 00:20:22 +02:00
pressedA = TRUE;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
if (pressedA)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
u8 proximity;
StartSpriteAnim(&gSprites[sBerryBlender->playerArrowSpriteIds[sBerryBlender->field_8E[arrowId]]], arrowId + 4);
proximity = GetArrowProximity(sBerryBlender->arrowPos, playerId);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
if (proximity == PROXIMITY_BEST)
gSendCmd[2] = LINKCMD_BLENDER_SCORE_BEST;
else if (proximity == PROXIMITY_GOOD)
gSendCmd[2] = LINKCMD_BLENDER_SCORE_GOOD;
2017-11-19 22:48:46 +01:00
else
2020-08-23 00:20:22 +02:00
gSendCmd[2] = LINKCMD_BLENDER_SCORE_MISS;
2017-11-19 22:48:46 +01:00
}
}
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->field_72 > 5)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->speed > 128)
sBerryBlender->speed--;
sBerryBlender->field_72 = 0;
2017-11-19 22:48:46 +01:00
}
if (gEnableContestDebugging && gMain.newKeys & L_BUTTON)
2020-08-23 00:20:22 +02:00
sBerryBlender->field_123 ^= 1;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
static void CB2_PlayBlender(void)
2017-11-19 22:48:46 +01:00
{
sub_8082D28();
2020-08-23 00:20:22 +02:00
if (sBerryBlender->gameFrameTime < (99 * 60 * 60) + (59 * 60)) // game time can't be longer than 99 minutes and 59 seconds, can't print 3 digits
sBerryBlender->gameFrameTime++;
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
HandlePlayerInput();
SetLinkDebugValues((u16)(sBerryBlender->speed), sBerryBlender->progressBarValue);
UpdateOpponentScores();
TryUpdateProgressBar(sBerryBlender->progressBarValue, MAX_PROGRESS_BAR);
UpdateRPM(sBerryBlender->speed);
2017-11-19 22:48:46 +01:00
sub_808330C();
sub_8082AD4();
2020-08-23 00:20:22 +02:00
if (sBerryBlender->gameEndState == 0 && sBerryBlender->maxProgressBarValue >= MAX_PROGRESS_BAR)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->progressBarValue = MAX_PROGRESS_BAR;
sBerryBlender->gameEndState = 1;
2017-11-19 22:48:46 +01:00
SetMainCallback2(CB2_HandleBlenderEndGame);
}
2020-08-23 00:20:22 +02:00
Blender_DummiedOutFunc(sBerryBlender->bg_X, sBerryBlender->bg_Y);
2017-11-19 22:48:46 +01:00
RunTasks();
AnimateSprites();
BuildOamBuffer();
RunTextPrinters();
UpdatePaletteFade();
}
static void Blender_DummiedOutFunc(s16 a0, s16 a1)
{
}
static bool8 sub_8081964(struct BlenderBerry* berries, u8 index1, u8 index2)
{
if (berries[index1].itemId != berries[index2].itemId
|| (StringCompare(berries[index1].name, berries[index2].name) == 0
2017-11-27 20:03:41 +01:00
&& (berries[index1].flavors[FLAVOR_SPICY] == berries[index2].flavors[FLAVOR_SPICY]
&& berries[index1].flavors[FLAVOR_DRY] == berries[index2].flavors[FLAVOR_DRY]
&& berries[index1].flavors[FLAVOR_SWEET] == berries[index2].flavors[FLAVOR_SWEET]
&& berries[index1].flavors[FLAVOR_BITTER] == berries[index2].flavors[FLAVOR_BITTER]
&& berries[index1].flavors[FLAVOR_SOUR] == berries[index2].flavors[FLAVOR_SOUR]
2017-11-19 22:48:46 +01:00
&& berries[index1].smoothness == berries[index2].smoothness)))
return TRUE;
else
return FALSE;
}
2020-08-23 00:20:22 +02:00
static u32 Blender_GetPokeblockColor(struct BlenderBerry* berries, s16* a1, u8 numPlayers, u8 a3)
2017-11-19 22:48:46 +01:00
{
s16 vars[6];
s32 i;
s32 r6;
u8 r2;
for (i = 0; i < 6; i++)
vars[i] = a1[i];
r6 = 0;
for (i = 0; i < 5; i++)
{
if (vars[i] == 0)
r6++;
}
if (r6 == 5 || a3 > 3)
return 12;
2020-08-23 00:20:22 +02:00
for (i = 0; i < numPlayers; i++)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
for (r6 = 0; r6 < numPlayers; r6++)
2017-11-19 22:48:46 +01:00
{
if (berries[i].itemId == berries[r6].itemId && i != r6
&& (berries[i].itemId != ITEM_ENIGMA_BERRY || sub_8081964(berries, i, r6)))
return 12;
}
}
r2 = 0;
for (r2 = 0, i = 0; i < 5; i++)
{
if (vars[i] > 0)
r2++;
}
if (r2 > 3)
return 13;
if (r2 == 3)
return 11;
for (i = 0; i < 5; i++)
{
if (vars[i] > 50)
return 14;
}
if (r2 == 1 && vars[0] > 0)
return 1;
if (r2 == 1 && vars[1] > 0)
return 2;
if (r2 == 1 && vars[2] > 0)
return 3;
if (r2 == 1 && vars[3] > 0)
return 4;
if (r2 == 1 && vars[4] > 0)
return 5;
if (r2 == 2)
{
s32 var = 0;
for (i = 0; i < 5; i++)
{
if (vars[i] > 0)
sUnknown_03000DF8[var++] = i;
}
if (vars[sUnknown_03000DF8[0]] >= vars[sUnknown_03000DF8[1]])
{
if (sUnknown_03000DF8[0] == 0)
return (sUnknown_03000DF8[1] << 16) | 6;
if (sUnknown_03000DF8[0] == 1)
return (sUnknown_03000DF8[1] << 16) | 7;
if (sUnknown_03000DF8[0] == 2)
return (sUnknown_03000DF8[1] << 16) | 8;
if (sUnknown_03000DF8[0] == 3)
return (sUnknown_03000DF8[1] << 16) | 9;
if (sUnknown_03000DF8[0] == 4)
return (sUnknown_03000DF8[1] << 16) | 10;
}
else
{
if (sUnknown_03000DF8[1] == 0)
return (sUnknown_03000DF8[0] << 16) | 6;
if (sUnknown_03000DF8[1] == 1)
return (sUnknown_03000DF8[0] << 16) | 7;
if (sUnknown_03000DF8[1] == 2)
return (sUnknown_03000DF8[0] << 16) | 8;
if (sUnknown_03000DF8[1] == 3)
return (sUnknown_03000DF8[0] << 16) | 9;
if (sUnknown_03000DF8[1] == 4)
return (sUnknown_03000DF8[0] << 16) | 10;
}
}
return 0;
}
static void sub_8081BB0(s16 value)
{
sUnknown_03000E04 = value;
}
static s16 sub_8081BBC(void)
{
return sUnknown_03000E04;
}
static void sub_8081BC8(s16 value)
{
sUnknown_03000E06 = value;
}
static s16 sub_8081BD4(void)
{
return sUnknown_03000E06;
}
#if MODERN
// TODO remove this as soon as the code below is understood
// add a UBFIX if required (code buggy?)
__attribute__((optimize("no-aggressive-loop-optimizations")))
#endif
2020-08-23 00:20:22 +02:00
static void Blender_CalculatePokeblock(struct BlenderBerry *berries, struct Pokeblock *pokeblock, u8 numPlayers, u8 *flavors, u16 maxRPM)
2017-11-19 22:48:46 +01:00
{
s32 i, j;
s32 multiuseVar, var2;
u8 var3;
for (i = 0; i < 6; i++)
sUnknown_03000DE8[i] = 0;
2020-08-23 00:20:22 +02:00
for (i = 0; i < numPlayers; i++)
2017-11-19 22:48:46 +01:00
{
for (j = 0; j < 6; j++)
2017-11-27 20:03:41 +01:00
sUnknown_03000DE8[j] += berries[i].flavors[j];
2017-11-19 22:48:46 +01:00
}
multiuseVar = sUnknown_03000DE8[0];
sUnknown_03000DE8[0] -= sUnknown_03000DE8[1];
sUnknown_03000DE8[1] -= sUnknown_03000DE8[2];
sUnknown_03000DE8[2] -= sUnknown_03000DE8[3];
sUnknown_03000DE8[3] -= sUnknown_03000DE8[4];
sUnknown_03000DE8[4] -= multiuseVar;
multiuseVar = 0;
for (i = 0; i < 5; i++)
{
if (sUnknown_03000DE8[i] < 0)
{
sUnknown_03000DE8[i] = 0;
multiuseVar++;
}
}
var3 = multiuseVar;
for (i = 0; i < 5; i++)
{
if (sUnknown_03000DE8[i] > 0)
{
if (sUnknown_03000DE8[i] < multiuseVar)
sUnknown_03000DE8[i] = 0;
else
sUnknown_03000DE8[i] -= multiuseVar;
}
}
for (i = 0; i < 5; i++)
{
sUnknown_020322A8[i] = sUnknown_03000DE8[i];
}
multiuseVar = maxRPM / 333 + 100;
sUnknown_020322D0 = multiuseVar;
for (i = 0; i < 5; i++)
{
s32 r4;
s32 r5 = sUnknown_03000DE8[i];
r5 = (r5 * multiuseVar) / 10;
r4 = r5 % 10;
r5 /= 10;
if (r4 > 4)
r5++;
sUnknown_03000DE8[i] = r5;
}
for (i = 0; i < 5; i++)
{
sUnknown_020322BC[i] = sUnknown_03000DE8[i];
}
2020-08-23 00:20:22 +02:00
pokeblock->color = Blender_GetPokeblockColor(berries, &sUnknown_03000DE8[0], numPlayers, var3);
sUnknown_03000DE8[5] = (sUnknown_03000DE8[5] / numPlayers) - numPlayers;
2017-11-19 22:48:46 +01:00
if (sUnknown_03000DE8[5] < 0)
sUnknown_03000DE8[5] = 0;
if (pokeblock->color == 12)
{
multiuseVar = Random() % 10;
for (i = 0; i < 5; i++)
2017-11-18 21:38:57 +01:00
{
2017-11-19 22:48:46 +01:00
if ((sUnknown_08339CC8[multiuseVar] >> i) & 1)
sUnknown_03000DE8[i] = 2;
else
sUnknown_03000DE8[i] = 0;
2017-11-18 21:38:57 +01:00
}
}
2017-11-19 22:48:46 +01:00
for (i = 0; i < 6; i++)
{
if (sUnknown_03000DE8[i] > 255)
sUnknown_03000DE8[i] = 255;
}
pokeblock->spicy = sUnknown_03000DE8[0];
pokeblock->dry = sUnknown_03000DE8[1];
pokeblock->sweet = sUnknown_03000DE8[2];
pokeblock->bitter = sUnknown_03000DE8[3];
pokeblock->sour = sUnknown_03000DE8[4];
pokeblock->feel = sUnknown_03000DE8[5];
for (i = 0; i < 6; i++)
{
2017-11-27 20:03:41 +01:00
flavors[i] = sUnknown_03000DE8[i];
2017-11-19 22:48:46 +01:00
}
}
2020-08-23 00:20:22 +02:00
static void BlenderDebug_CalculatePokeblock(struct BlenderBerry* berries, struct Pokeblock* pokeblock, u8 numPlayers, u8* flavors, u16 maxRPM)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
Blender_CalculatePokeblock(berries, pokeblock, numPlayers, flavors, maxRPM);
2017-11-19 22:48:46 +01:00
}
static void sub_8081E20(void)
{
2020-08-23 00:20:22 +02:00
u32 frames = (u16)(sBerryBlender->gameFrameTime);
u16 maxRPM = sBerryBlender->maxRPM;
2017-11-19 22:48:46 +01:00
s16 var = 0;
if (frames < 900)
var = 5;
else if ((u16)(frames - 900) < 600)
var = 4;
else if ((u16)(frames - 1500) < 600)
var = 3;
else if ((u16)(frames - 2100) < 900)
var = 2;
else if ((u16)(frames - 3300) < 300)
var = 1;
sub_8081BC8(var);
var = 0;
2020-08-23 00:20:22 +02:00
if (maxRPM <= 64)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
if (maxRPM >= 50 && maxRPM < 100)
2017-11-19 22:48:46 +01:00
var = -1;
2020-08-23 00:20:22 +02:00
else if (maxRPM >= 100 && maxRPM < 150)
2017-11-19 22:48:46 +01:00
var = -2;
2020-08-23 00:20:22 +02:00
else if (maxRPM >= 150 && maxRPM < 200)
2017-11-19 22:48:46 +01:00
var = -3;
2020-08-23 00:20:22 +02:00
else if (maxRPM >= 200 && maxRPM < 250)
2017-11-19 22:48:46 +01:00
var = -4;
2020-08-23 00:20:22 +02:00
else if (maxRPM >= 250 && maxRPM < 300)
2017-11-19 22:48:46 +01:00
var = -5;
2020-08-23 00:20:22 +02:00
else if (maxRPM >= 350 && maxRPM < 400)
2017-11-19 22:48:46 +01:00
var = -6;
2020-08-23 00:20:22 +02:00
else if (maxRPM >= 400 && maxRPM < 450)
2017-11-19 22:48:46 +01:00
var = -7;
2020-08-23 00:20:22 +02:00
else if (maxRPM >= 500 && maxRPM < 550)
2017-11-19 22:48:46 +01:00
var = -8;
2020-08-23 00:20:22 +02:00
else if (maxRPM >= 550 && maxRPM < 600)
2017-11-19 22:48:46 +01:00
var = -9;
2020-08-23 00:20:22 +02:00
else if (maxRPM >= 600)
2017-11-19 22:48:46 +01:00
var = -10;
}
sub_8081BB0(var);
}
static void sub_8081F94(u16 *a0)
{
2017-11-28 02:05:51 +01:00
if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
2020-08-23 00:20:22 +02:00
*a0 = LINKCMD_0x2F00;
2017-11-19 22:48:46 +01:00
else
2020-08-23 00:20:22 +02:00
*a0 = LINKCMD_0x2FFF;
2017-11-19 22:48:46 +01:00
}
static void CB2_HandleBlenderEndGame(void)
{
u8 i, j;
2020-08-23 00:20:22 +02:00
if (sBerryBlender->gameEndState < 3)
2017-11-19 22:48:46 +01:00
sub_8082D28();
GetMultiplayerId(); // unused return value
2020-08-23 00:20:22 +02:00
switch (sBerryBlender->gameEndState)
2017-11-19 22:48:46 +01:00
{
case 1:
m4aMPlayTempoControl(&gMPlayInfo_BGM, 256);
2017-11-19 22:48:46 +01:00
for (i = 0; i < gSpecialVar_0x8004; i++)
{
2020-08-23 00:20:22 +02:00
DestroyTask(sBerryBlender->opponentTaskIds[i]);
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
break;
case 2:
2020-08-23 00:20:22 +02:00
sBerryBlender->speed -= 32;
if (sBerryBlender->speed <= 0)
2017-11-19 22:48:46 +01:00
{
2017-11-28 02:05:51 +01:00
ClearLinkCallback();
2020-08-23 00:20:22 +02:00
sBerryBlender->speed = 0;
2017-11-19 22:48:46 +01:00
if (gReceivedRemoteLinkPlayers != 0)
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
else
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState = 5;
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState = 0;
m4aMPlayStop(&gMPlayInfo_SE2);
2017-11-19 22:48:46 +01:00
}
Blender_ControlHitPitch();
break;
case 3:
if (GetMultiplayerId() != 0)
{
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
2018-12-31 09:22:21 +01:00
else if (IsLinkTaskFinished())
2017-11-19 22:48:46 +01:00
{
2017-11-28 02:05:51 +01:00
if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->gameBlock.timeRPM.time = sBerryBlender->gameFrameTime;
sBerryBlender->gameBlock.timeRPM.maxRPM = sBerryBlender->maxRPM;
2017-11-19 22:48:46 +01:00
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
for (j = 0; j < NUM_SCORE_TYPES; j++)
sBerryBlender->gameBlock.scores[i][j] = sBerryBlender->scores[i][j];
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
if (SendBlock(0, &sBerryBlender->gameBlock, sizeof(sBerryBlender->gameBlock)))
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
sBerryBlender->smallBlock.time = sBerryBlender->gameFrameTime;
sBerryBlender->smallBlock.maxRPM = sBerryBlender->maxRPM;
if (SendBlock(0, &sBerryBlender->smallBlock, sizeof(sBerryBlender->smallBlock) + 32))
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
}
break;
case 4:
if (GetBlockReceivedStatus())
{
ResetBlockReceivedFlags();
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
2017-11-28 02:05:51 +01:00
if (gReceivedRemoteLinkPlayers != 0 && gWirelessCommType)
2017-11-19 22:48:46 +01:00
{
struct BlenderGameBlock *receivedBlock = (struct BlenderGameBlock*)(&gBlockRecvBuffer);
2020-08-23 00:20:22 +02:00
sBerryBlender->maxRPM = receivedBlock->timeRPM.maxRPM;
sBerryBlender->gameFrameTime = receivedBlock->timeRPM.time;
2017-11-19 22:48:46 +01:00
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
for (j = 0; j < NUM_SCORE_TYPES; j++)
sBerryBlender->scores[i][j] = receivedBlock->scores[i][j];
2017-11-19 22:48:46 +01:00
}
}
else
{
struct TimeAndRPM *receivedBlock = (struct TimeAndRPM*)(&gBlockRecvBuffer);
2020-08-23 00:20:22 +02:00
sBerryBlender->maxRPM = receivedBlock->maxRPM;
sBerryBlender->gameFrameTime = receivedBlock->time;
2017-11-19 22:48:46 +01:00
}
}
break;
case 5:
2020-08-23 00:20:22 +02:00
if (PrintBlendingRanking())
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
break;
case 6:
2020-08-23 00:20:22 +02:00
if (PrintBlendingResults())
2017-11-19 22:48:46 +01:00
{
if (gInGameOpponentsNo == 0)
IncrementGameStat(GAME_STAT_POKEBLOCKS_WITH_FRIENDS);
else
IncrementGameStat(GAME_STAT_POKEBLOCKS);
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
break;
case 7:
2020-08-23 00:20:22 +02:00
if (Blender_PrintText(&sBerryBlender->textState, sText_WouldLikeToBlendAnotherBerry, GetPlayerTextSpeedDelay()))
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
break;
case 9:
2020-08-23 00:20:22 +02:00
sBerryBlender->yesNoAnswer = 0;
2017-11-19 22:48:46 +01:00
CreateYesNoMenu(&sBlender_YesNoWindowTemplate, 1, 0xD, 0);
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
break;
case 10:
2018-11-05 21:45:54 +01:00
switch (Menu_ProcessInputNoWrapClearOnChoose())
2017-11-19 22:48:46 +01:00
{
case 1:
case -1:
2020-08-23 00:20:22 +02:00
sBerryBlender->yesNoAnswer = 1;
sBerryBlender->gameEndState++;
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_8E[i] != 0xFF)
2017-11-19 22:48:46 +01:00
{
PutWindowTilemap(i);
CopyWindowToVram(i, 3);
}
}
break;
case 0:
2020-08-23 00:20:22 +02:00
sBerryBlender->yesNoAnswer = 0;
sBerryBlender->gameEndState++;
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_8E[i] != 0xFF)
2017-11-19 22:48:46 +01:00
{
PutWindowTilemap(i);
CopyWindowToVram(i, 3);
}
}
break;
}
break;
case 11:
sub_8081F94(&gSendCmd[0]);
2020-08-23 00:20:22 +02:00
if (sBerryBlender->yesNoAnswer == 0)
2017-11-19 22:48:46 +01:00
{
2018-04-29 15:34:14 +02:00
if (IsBagPocketNonEmpty(POCKET_BERRIES) == FALSE) // no berries
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->playAgainState = CANT_PLAY_NO_BERRIES;
gSendCmd[1] = LINKCMD_0x9999;
2017-11-19 22:48:46 +01:00
}
else if (GetFirstFreePokeblockSlot() == -1) // no space for pokeblocks
{
2020-08-23 00:20:22 +02:00
sBerryBlender->playAgainState = CANT_PLAY_NO_PKBLCK_SPACE;
gSendCmd[1] = LINKCMD_0xAAAA;
2017-11-19 22:48:46 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
sBerryBlender->playAgainState = PLAY_AGAIN_OK;
gSendCmd[1] = LINKCMD_0x7779;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
sBerryBlender->playAgainState = DONT_PLAY_AGAIN;
gSendCmd[1] = LINKCMD_CONT_BLOCK;
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
break;
case 12:
if (gInGameOpponentsNo)
{
SetMainCallback2(CB2_HandlePlayerPlayAgainChoice);
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState = 0;
sBerryBlender->mainState = 0;
2017-11-19 22:48:46 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
break;
case 8:
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
break;
case 13:
2020-08-23 00:20:22 +02:00
if (Blender_PrintText(&sBerryBlender->textState, sText_CommunicationStandby, GetPlayerTextSpeedDelay()))
2017-11-19 22:48:46 +01:00
{
SetMainCallback2(CB2_HandlePlayerLinkPlayAgainChoice);
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState = 0;
sBerryBlender->mainState = 0;
2017-11-19 22:48:46 +01:00
}
break;
}
sub_808330C();
2020-08-23 00:20:22 +02:00
UpdateRPM(sBerryBlender->speed);
2017-11-19 22:48:46 +01:00
sub_8082AD4();
2020-08-23 00:20:22 +02:00
Blender_DummiedOutFunc(sBerryBlender->bg_X, sBerryBlender->bg_Y);
2017-11-19 22:48:46 +01:00
RunTasks();
AnimateSprites();
BuildOamBuffer();
RunTextPrinters();
UpdatePaletteFade();
}
static bool8 LinkPlayAgainHandleSaving(void)
{
2020-08-23 00:20:22 +02:00
switch (sBerryBlender->field_1A0)
2017-11-19 22:48:46 +01:00
{
case 0:
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback();
2020-08-23 00:20:22 +02:00
sBerryBlender->field_1A0 = 1;
sBerryBlender->framesToWait = 0;
2017-11-19 22:48:46 +01:00
break;
case 1:
2018-12-31 09:22:21 +01:00
if (IsLinkTaskFinished())
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->field_1A0++;
2017-11-19 22:48:46 +01:00
gSoftResetDisabled = TRUE;
}
break;
case 2:
FullSaveGame();
2020-08-23 00:20:22 +02:00
sBerryBlender->field_1A0++;
sBerryBlender->framesToWait = 0;
2017-11-19 22:48:46 +01:00
break;
case 3:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait == 10)
2017-11-19 22:48:46 +01:00
{
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback();
2020-08-23 00:20:22 +02:00
sBerryBlender->field_1A0++;
2017-11-19 22:48:46 +01:00
}
break;
case 4:
2018-12-31 09:22:21 +01:00
if (IsLinkTaskFinished())
2017-11-19 22:48:46 +01:00
{
if (CheckSaveFile())
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->field_1A0 = 5;
2017-11-19 22:48:46 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->field_1A0 = 3;
2017-11-19 22:48:46 +01:00
}
}
break;
case 5:
2020-08-23 00:20:22 +02:00
sBerryBlender->field_1A0++;
sBerryBlender->framesToWait = 0;
2017-11-19 22:48:46 +01:00
break;
case 6:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait > 5)
2017-11-19 22:48:46 +01:00
{
gSoftResetDisabled = FALSE;
return TRUE;
}
break;
}
return FALSE;
}
static void CB2_HandlePlayerLinkPlayAgainChoice(void)
{
2020-08-23 00:20:22 +02:00
switch (sBerryBlender->gameEndState)
2017-11-19 22:48:46 +01:00
{
case 0:
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_64[0] == LINKCMD_SEND_LINK_TYPE)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState = 5;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
else if (sBerryBlender->field_64[0] == LINKCMD_0x1111)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_6C == LINKCMD_0x9999)
sBerryBlender->gameEndState = 2;
else if (sBerryBlender->field_6C == LINKCMD_0xAAAA)
sBerryBlender->gameEndState = 1;
2017-11-19 22:48:46 +01:00
else
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState = 5;
2017-11-19 22:48:46 +01:00
}
break;
case 1:
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState = 3;
StringCopy(gStringVar4, gLinkPlayers[sBerryBlender->field_6E].name);
2017-11-19 22:48:46 +01:00
StringAppend(gStringVar4, sText_ApostropheSPokeblockCaseIsFull);
break;
case 2:
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
StringCopy(gStringVar4, gLinkPlayers[sBerryBlender->field_6E].name);
2017-11-19 22:48:46 +01:00
StringAppend(gStringVar4, sText_HasNoBerriesToPut);
break;
case 3:
2020-08-23 00:20:22 +02:00
if (Blender_PrintText(&sBerryBlender->textState, gStringVar4, GetPlayerTextSpeedDelay()))
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
break;
case 4:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait > 60)
sBerryBlender->gameEndState = 5;
2017-11-19 22:48:46 +01:00
break;
case 5:
2020-08-23 00:20:22 +02:00
Blender_PrintText(&sBerryBlender->textState, gText_SavingDontTurnOff2, 0);
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback();
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
break;
case 6:
2018-12-31 09:22:21 +01:00
if (IsLinkTaskFinished())
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->gameEndState++;
sBerryBlender->field_1A0 = 0;
2017-11-19 22:48:46 +01:00
}
break;
case 7:
if (LinkPlayAgainHandleSaving())
{
PlaySE(SE_SAVE);
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
break;
case 8:
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback();
2017-11-19 22:48:46 +01:00
break;
case 9:
2018-12-31 09:22:21 +01:00
if (IsLinkTaskFinished())
2017-11-19 22:48:46 +01:00
{
2019-04-04 23:05:46 +02:00
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
break;
case 10:
if (!gPaletteFade.active)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_64[0] == LINKCMD_SEND_LINK_TYPE)
2017-11-19 22:48:46 +01:00
{
FreeAllWindowBuffers();
UnsetBgTilemapBuffer(2);
UnsetBgTilemapBuffer(1);
2020-08-23 00:20:22 +02:00
FREE_AND_SET_NULL(sBerryBlender);
2017-11-19 22:48:46 +01:00
SetMainCallback2(DoBerryBlending);
}
else
{
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
}
break;
case 11:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait > 30)
2017-11-19 22:48:46 +01:00
{
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback();
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
}
break;
case 12:
if (gReceivedRemoteLinkPlayers == 0)
{
2020-08-23 00:20:22 +02:00
FREE_AND_SET_NULL(sBerryBlender);
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
2017-11-19 22:48:46 +01:00
}
break;
}
sub_8082AD4();
2020-08-23 00:20:22 +02:00
Blender_DummiedOutFunc(sBerryBlender->bg_X, sBerryBlender->bg_Y);
2017-11-19 22:48:46 +01:00
RunTasks();
AnimateSprites();
BuildOamBuffer();
RunTextPrinters();
UpdatePaletteFade();
}
static void CB2_HandlePlayerPlayAgainChoice(void)
{
2020-08-23 00:20:22 +02:00
switch (sBerryBlender->gameEndState)
2017-11-19 22:48:46 +01:00
{
case 0:
2020-08-23 00:20:22 +02:00
if (sBerryBlender->playAgainState == PLAY_AGAIN_OK || sBerryBlender->playAgainState == DONT_PLAY_AGAIN)
sBerryBlender->gameEndState = 9;
if (sBerryBlender->playAgainState == CANT_PLAY_NO_BERRIES)
sBerryBlender->gameEndState = 2;
if (sBerryBlender->playAgainState == CANT_PLAY_NO_PKBLCK_SPACE)
sBerryBlender->gameEndState = 1;
2017-11-19 22:48:46 +01:00
break;
case 1:
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState = 3;
sBerryBlender->textState = 0;
2017-11-19 22:48:46 +01:00
StringCopy(gStringVar4, sText_YourPokeblockCaseIsFull);
break;
case 2:
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
sBerryBlender->textState = 0;
2017-11-19 22:48:46 +01:00
StringCopy(gStringVar4, sText_RunOutOfBerriesForBlending);
break;
case 3:
2020-08-23 00:20:22 +02:00
if (Blender_PrintText(&sBerryBlender->textState, gStringVar4, GetPlayerTextSpeedDelay()))
sBerryBlender->gameEndState = 9;
2017-11-19 22:48:46 +01:00
break;
case 9:
BeginFastPaletteFade(3);
2020-08-23 00:20:22 +02:00
sBerryBlender->gameEndState++;
2017-11-19 22:48:46 +01:00
break;
case 10:
if (!gPaletteFade.active)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->playAgainState == PLAY_AGAIN_OK)
2017-11-19 22:48:46 +01:00
SetMainCallback2(DoBerryBlending);
else
SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
2017-11-19 22:48:46 +01:00
FreeAllWindowBuffers();
UnsetBgTilemapBuffer(2);
UnsetBgTilemapBuffer(1);
2020-08-23 00:20:22 +02:00
FREE_AND_SET_NULL(sBerryBlender);
2017-11-19 22:48:46 +01:00
}
break;
}
sub_8082AD4();
2020-08-23 00:20:22 +02:00
Blender_DummiedOutFunc(sBerryBlender->bg_X, sBerryBlender->bg_Y);
2017-11-19 22:48:46 +01:00
RunTasks();
AnimateSprites();
BuildOamBuffer();
RunTextPrinters();
UpdatePaletteFade();
}
static void sub_8082AD4(void)
{
if (gReceivedRemoteLinkPlayers)
{
2020-08-23 00:20:22 +02:00
if (sub_80814B0(gRecvCmds[0][0], LINKCMD_0x2FFF, LINKCMD_0x2F00))
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
if (gRecvCmds[0][1] == LINKCMD_0x1111)
2017-11-19 22:48:46 +01:00
{
switch (gRecvCmds[0][2])
{
2020-08-23 00:20:22 +02:00
case LINKCMD_CONT_BLOCK:
sBerryBlender->field_6C = LINKCMD_CONT_BLOCK;
sBerryBlender->field_6E = gRecvCmds[0][3];
2017-11-19 22:48:46 +01:00
break;
2020-08-23 00:20:22 +02:00
case LINKCMD_0x9999:
sBerryBlender->field_6C = LINKCMD_0x9999;
sBerryBlender->field_6E = gRecvCmds[0][3];
2017-11-19 22:48:46 +01:00
break;
2020-08-23 00:20:22 +02:00
case LINKCMD_0xAAAA:
sBerryBlender->field_6C = LINKCMD_0xAAAA;
sBerryBlender->field_6E = gRecvCmds[0][3];
2017-11-19 22:48:46 +01:00
break;
}
2020-08-23 00:20:22 +02:00
sBerryBlender->field_64[0] = LINKCMD_0x1111;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
else if (gRecvCmds[0][1] == LINKCMD_SEND_LINK_TYPE)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->field_64[0] = LINKCMD_SEND_LINK_TYPE;
2017-11-19 22:48:46 +01:00
}
}
2020-08-23 00:20:22 +02:00
if (GetMultiplayerId() == 0 && sBerryBlender->field_64[0] != LINKCMD_0x1111 && sBerryBlender->field_64[0] != LINKCMD_SEND_LINK_TYPE)
2017-11-19 22:48:46 +01:00
{
u8 i;
for (i = 0; i < GetLinkPlayerCount(); i++)
{
2020-08-23 00:20:22 +02:00
if (sub_80814B0(gRecvCmds[i][0], LINKCMD_0x2FFF, LINKCMD_0x2F00))
2017-11-19 22:48:46 +01:00
{
switch (gRecvCmds[i][1])
{
2020-08-23 00:20:22 +02:00
case LINKCMD_CONT_BLOCK:
sBerryBlender->field_64[i] = LINKCMD_CONT_BLOCK;
2017-11-19 22:48:46 +01:00
break;
2020-08-23 00:20:22 +02:00
case LINKCMD_0x7779:
sBerryBlender->field_64[i] = LINKCMD_0x7779;
2017-11-19 22:48:46 +01:00
break;
2020-08-23 00:20:22 +02:00
case LINKCMD_0x9999:
sBerryBlender->field_64[i] = LINKCMD_0x9999;
2017-11-19 22:48:46 +01:00
break;
2020-08-23 00:20:22 +02:00
case LINKCMD_0xAAAA:
sBerryBlender->field_64[i] = LINKCMD_0xAAAA;
2017-11-19 22:48:46 +01:00
break;
}
}
}
for (i = 0; i < GetLinkPlayerCount(); i++)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_64[i] == 0)
2017-11-19 22:48:46 +01:00
break;
}
if (i == GetLinkPlayerCount())
{
for (i = 0; i < GetLinkPlayerCount(); i++)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_64[i] != LINKCMD_0x7779)
2017-11-19 22:48:46 +01:00
break;
}
sub_8081F94(&gSendCmd[0]);
if (i == GetLinkPlayerCount())
{
2020-08-23 00:20:22 +02:00
gSendCmd[1] = LINKCMD_SEND_LINK_TYPE;
2017-11-19 22:48:46 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
gSendCmd[1] = LINKCMD_0x1111;
gSendCmd[2] = sBerryBlender->field_64[i];
2017-11-19 22:48:46 +01:00
gSendCmd[3] = i;
}
}
}
}
}
2020-08-23 00:20:22 +02:00
static void DrawBlenderCenter(struct BgAffineSrcData *dest)
2017-11-19 22:48:46 +01:00
{
struct BgAffineSrcData affineSrc;
2017-11-27 20:03:41 +01:00
affineSrc.texX = 0x7800;
affineSrc.texY = 0x5000;
2020-08-23 00:20:22 +02:00
affineSrc.scrX = 0x78 - sBerryBlender->bg_X;
affineSrc.scrY = 0x50 - sBerryBlender->bg_Y;
affineSrc.sx = sBerryBlender->field_11A;
affineSrc.sy = sBerryBlender->field_11A;
affineSrc.alpha = sBerryBlender->arrowPos;
2017-11-19 22:48:46 +01:00
*dest = affineSrc;
}
u16 GetBlenderArrowPosition(void)
{
2020-08-23 00:20:22 +02:00
return sBerryBlender->arrowPos;
2017-11-19 22:48:46 +01:00
}
static void sub_8082D28(void)
{
u8 playerId = 0;
2020-08-23 00:20:22 +02:00
if (gReceivedRemoteLinkPlayers)
2017-11-19 22:48:46 +01:00
playerId = GetMultiplayerId();
2017-11-28 02:05:51 +01:00
if (gWirelessCommType && gReceivedRemoteLinkPlayers != 0)
2017-11-19 22:48:46 +01:00
{
if (playerId == 0)
{
2020-08-23 00:20:22 +02:00
sBerryBlender->arrowPos += sBerryBlender->speed;
gSendCmd[5] = sBerryBlender->progressBarValue;
gSendCmd[6] = sBerryBlender->arrowPos;
DrawBlenderCenter(&sBerryBlender->bgAffineSrc);
2017-11-19 22:48:46 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
if ((gRecvCmds[0][0] & 0xFF00) == LINKCMD_0x4400)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->progressBarValue = gRecvCmds[0][5];
sBerryBlender->arrowPos = gRecvCmds[0][6];
DrawBlenderCenter(&sBerryBlender->bgAffineSrc);
2017-11-19 22:48:46 +01:00
}
}
}
else
{
2020-08-23 00:20:22 +02:00
sBerryBlender->arrowPos += sBerryBlender->speed;
DrawBlenderCenter(&sBerryBlender->bgAffineSrc);
2017-11-19 22:48:46 +01:00
}
}
static void BerryBlender_SetBackgroundsPos(void)
{
2020-08-23 00:20:22 +02:00
SetGpuReg(REG_OFFSET_BG1HOFS, sBerryBlender->bg_X);
SetGpuReg(REG_OFFSET_BG1VOFS, sBerryBlender->bg_Y);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
SetGpuReg(REG_OFFSET_BG0HOFS, sBerryBlender->bg_X);
SetGpuReg(REG_OFFSET_BG0VOFS, sBerryBlender->bg_Y);
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
static void SpriteCB_Particle(struct Sprite* sprite)
2017-11-19 22:48:46 +01:00
{
2017-12-02 21:44:50 +01:00
sprite->data[2] += sprite->data[0];
sprite->data[3] += sprite->data[1];
sprite->pos2.x = sprite->data[2] / 8;
sprite->pos2.y = sprite->data[3] / 8;
2017-11-19 22:48:46 +01:00
if (sprite->animEnded)
DestroySprite(sprite);
}
2020-08-23 00:20:22 +02:00
static void CreateParticleSprites(void)
2017-11-19 22:48:46 +01:00
{
s32 limit = (Random() % 2) + 1;
s32 i;
for (i = 0; i < limit; i++)
{
u16 rand;
s32 x, y;
u8 spriteId;
2020-08-23 00:20:22 +02:00
rand = sBerryBlender->arrowPos + (Random() % 20);
2017-11-19 22:48:46 +01:00
x = gSineTable[(rand & 0xFF) + 64] / 4;
y = gSineTable[(rand & 0xFF)] / 4;
2020-08-23 00:20:22 +02:00
spriteId = CreateSprite(&sSpriteTemplate_Particles, x + 120, y + 80, 1);
2017-12-02 21:44:50 +01:00
gSprites[spriteId].data[0] = 16 - (Random() % 32);
gSprites[spriteId].data[1] = 16 - (Random() % 32);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
gSprites[spriteId].callback = SpriteCB_Particle;
2017-11-19 22:48:46 +01:00
}
}
2020-08-23 00:20:22 +02:00
static void SpriteCB_ScoreSymbol(struct Sprite* sprite)
2017-11-19 22:48:46 +01:00
{
2017-12-02 21:44:50 +01:00
sprite->data[0]++;
sprite->pos2.y = -(sprite->data[0] / 3);
2017-11-19 22:48:46 +01:00
if (sprite->animEnded)
DestroySprite(sprite);
}
2020-08-23 00:20:22 +02:00
static void SpriteCB_ScoreSymbolBest(struct Sprite* sprite)
2017-11-19 22:48:46 +01:00
{
2017-12-02 21:44:50 +01:00
sprite->data[0]++;
sprite->pos2.y = -(sprite->data[0] * 2);
2017-11-19 22:48:46 +01:00
if (sprite->pos2.y < -12)
sprite->pos2.y = -12;
if (sprite->animEnded)
DestroySprite(sprite);
}
2018-09-01 18:36:08 +02:00
static void Blender_SetParticipantBerryData(u8 participantId, u16 itemId)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->chosenItemId[participantId] = itemId;
ConvertItemToBlenderBerry(&sBerryBlender->blendedBerries[participantId], itemId);
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
#define sState data[0]
#define sYPos data[1]
#define sDelay data[2]
#define sAnimId data[3]
static void SpriteCB_CountdownNumber(struct Sprite* sprite)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
switch (sprite->sState)
2017-11-19 22:48:46 +01:00
{
case 0:
2020-08-23 00:20:22 +02:00
sprite->sYPos += 8;
if (sprite->sYPos > DISPLAY_HEIGHT / 2 + 8)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sprite->sYPos = DISPLAY_HEIGHT / 2 + 8;
sprite->sState++;
2017-11-19 22:48:46 +01:00
PlaySE(SE_KON);
}
break;
case 1:
2020-08-23 00:20:22 +02:00
if (++sprite->sDelay > 20)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sprite->sState++;
sprite->sDelay = 0;
2017-11-19 22:48:46 +01:00
}
break;
case 2:
2020-08-23 00:20:22 +02:00
sprite->sYPos += 4;
if (sprite->sYPos > DISPLAY_HEIGHT + 16)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
if (++sprite->sAnimId == 3)
2017-11-19 22:48:46 +01:00
{
DestroySprite(sprite);
2020-08-23 00:20:22 +02:00
CreateSprite(&sSpriteTemplate_Start, 120, -20, 2);
2017-11-19 22:48:46 +01:00
}
else
{
2020-08-23 00:20:22 +02:00
sprite->sState = 0;
sprite->sYPos = -16;
StartSpriteAnim(sprite, sprite->sAnimId);
2017-11-19 22:48:46 +01:00
}
}
break;
}
2020-08-23 00:20:22 +02:00
sprite->pos2.y = sprite->sYPos;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
#undef sState
#undef sYPos
#undef sDelay
#undef sAnimId
static void SpriteCB_Start(struct Sprite* sprite)
2017-11-19 22:48:46 +01:00
{
2017-12-02 21:44:50 +01:00
switch (sprite->data[0])
2017-11-19 22:48:46 +01:00
{
case 0:
2017-12-02 21:44:50 +01:00
sprite->data[1] += 8;
if (sprite->data[1] > 92)
2017-11-19 22:48:46 +01:00
{
2017-12-02 21:44:50 +01:00
sprite->data[1] = 92;
sprite->data[0]++;
2017-11-19 22:48:46 +01:00
PlaySE(SE_PIN);
}
break;
case 1:
2017-12-02 21:44:50 +01:00
sprite->data[2] += 1;
if (sprite->data[2] > 20)
sprite->data[0]++;
2017-11-19 22:48:46 +01:00
break;
case 2:
2017-12-02 21:44:50 +01:00
sprite->data[1] += 4;
2020-08-23 00:20:22 +02:00
if (sprite->data[1] > DISPLAY_HEIGHT + 16)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
DestroySprite(sprite);
}
break;
}
2017-12-02 21:44:50 +01:00
sprite->pos2.y = sprite->data[1];
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
static void TryUpdateProgressBar(u16 current, u16 limit)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
// Progress bar doesn't move unless it's going up
if (sBerryBlender->maxProgressBarValue < current)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->maxProgressBarValue += 2;
UpdateProgressBar(sBerryBlender->maxProgressBarValue, limit);
2017-11-19 22:48:46 +01:00
}
}
2020-08-23 00:20:22 +02:00
static void UpdateProgressBar(u16 value, u16 limit)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
s32 var1, var2, var3, i;
2017-11-19 22:48:46 +01:00
u16 *vram;
vram = (u16*)(BG_SCREEN_ADDR(12));
2020-08-23 00:20:22 +02:00
var1 = (value * 64) / limit;
2017-11-19 22:48:46 +01:00
var2 = var1 / 8;
2020-08-23 00:20:22 +02:00
for (i = 0; i < var2; i++)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
vram[11 + i] = 0x80E9;
vram[43 + i] = 0x80F9;
2017-11-19 22:48:46 +01:00
}
var3 = var1 % 8;
if (var3 != 0)
{
2020-08-23 00:20:22 +02:00
vram[11 + i] = var3 + 0x80E1;
vram[43 + i] = var3 + 0x80F1;
i++;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
for (; i < 8; i++)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
vram[11 + i] = 0x80E1;
vram[43 + i] = 0x80F1;
2017-11-19 22:48:46 +01:00
}
}
2020-08-23 00:20:22 +02:00
static u32 ArrowSpeedToRPM(u16 speed)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
return 60 * 60 * 100 * speed / 65536;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
static void UpdateRPM(u16 speed)
2017-11-19 22:48:46 +01:00
{
u8 i;
2020-08-23 00:20:22 +02:00
u8 digits[5];
// Check if new max RPM has been reached
u32 currentRPM = ArrowSpeedToRPM(speed);
if (sBerryBlender->maxRPM < currentRPM)
sBerryBlender->maxRPM = currentRPM;
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
// Draw the current RPM number at the bottom of the screen
2017-11-19 22:48:46 +01:00
for (i = 0; i < 5; i++)
{
2020-08-23 00:20:22 +02:00
digits[i] = currentRPM % 10;
currentRPM /= 10;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
*((u16*)(VRAM + 0x6458)) = digits[4] + 0x8072;
*((u16*)(VRAM + 0x645A)) = digits[3] + 0x8072;
*((u16*)(VRAM + 0x645C)) = digits[2] + 0x8072;
*((u16*)(VRAM + 0x6460)) = digits[1] + 0x8072;
*((u16*)(VRAM + 0x6462)) = digits[0] + 0x8072;
2017-11-19 22:48:46 +01:00
}
static void sub_80832BC(s16* a0, u16 a1)
{
if (*a0 == 0)
*a0 = (Random() % a1) - (a1 / 2);
}
static void sub_80832E8(s16* a0)
{
if (*a0 < 0)
(*a0)++;
if (*a0 > 0)
(*a0)--;
}
static void sub_808330C(void)
{
2020-08-23 00:20:22 +02:00
sub_80832E8((s16 *)&sBerryBlender->bg_X);
sub_80832E8((s16 *)&sBerryBlender->bg_Y);
2017-11-19 22:48:46 +01:00
}
static void sub_8083334(s16* a0, u16 a1)
{
u8 var;
2017-11-19 22:48:46 +01:00
if (a1 < 10)
var = 16;
else
var = 8;
if (*a0 == 0)
{
*a0 = (Random() % var) - (var / 2);
}
else
{
if (*a0 < 0)
(*a0)++;
if (*a0 > 0)
(*a0)--;
}
}
static bool8 sub_8083380(void)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->framesToWait == 0)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->bg_X = 0;
sBerryBlender->bg_Y = 0;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait++;
sub_8083334(&sBerryBlender->bg_X, sBerryBlender->framesToWait);
sub_8083334(&sBerryBlender->bg_Y, sBerryBlender->framesToWait);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
if (sBerryBlender->framesToWait == 20)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->bg_X = 0;
sBerryBlender->bg_Y = 0;
2017-11-19 22:48:46 +01:00
return TRUE;
}
return FALSE;
}
2020-08-23 00:20:22 +02:00
static void SpriteCB_PlayerArrow(struct Sprite* sprite)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sprite->pos2.x = -(sBerryBlender->bg_X);
sprite->pos2.y = -(sBerryBlender->bg_Y);
2017-11-19 22:48:46 +01:00
}
static void TryUpdateBerryBlenderRecord(void)
{
2020-08-23 00:20:22 +02:00
if (gSaveBlock1Ptr->berryBlenderRecords[sBerryBlender->numPlayers - 2] < sBerryBlender->maxRPM)
gSaveBlock1Ptr->berryBlenderRecords[sBerryBlender->numPlayers - 2] = sBerryBlender->maxRPM;
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
static bool8 PrintBlendingResults(void)
2017-11-19 22:48:46 +01:00
{
u16 i;
s32 xPos, yPos;
struct Pokeblock pokeblock;
2017-11-27 20:03:41 +01:00
u8 flavors[6];
2017-11-19 22:48:46 +01:00
u8 text[40];
u16 berryIds[4]; // unused
2020-08-23 00:20:22 +02:00
switch (sBerryBlender->mainState)
2017-11-19 22:48:46 +01:00
{
case 0:
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
sBerryBlender->framesToWait = 17;
2017-11-19 22:48:46 +01:00
break;
case 1:
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait -= 10;
if (sBerryBlender->framesToWait < 0)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
}
break;
case 2:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait > 20)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
for (i = 0; i < NUM_SCORE_TYPES; i++)
DestroySprite(&gSprites[sBerryBlender->scoreIconIds[i]]);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
}
break;
case 3:
{
u16 minutes, seconds;
u8 *txtPtr;
xPos = GetStringCenterAlignXOffset(1, sText_BlendingResults, 0xA8);
Blender_AddTextPrinter(5, sText_BlendingResults, xPos, 1, TEXT_SPEED_FF, 0);
2020-08-23 00:20:22 +02:00
if (sBerryBlender->numPlayers == BLENDER_MAX_PLAYERS)
2017-11-19 22:48:46 +01:00
yPos = 17;
else
yPos = 21;
2020-08-23 00:20:22 +02:00
for (i = 0; i < sBerryBlender->numPlayers; yPos += 16, i++)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
u8 place = sBerryBlender->playerPlaces[i];
ConvertIntToDecimalStringN(sBerryBlender->stringVar, i + 1, STR_CONV_MODE_LEFT_ALIGN, 1);
StringAppend(sBerryBlender->stringVar, sText_Dot);
StringAppend(sBerryBlender->stringVar, gText_Space);
StringAppend(sBerryBlender->stringVar, gLinkPlayers[place].name);
Blender_AddTextPrinter(5, sBerryBlender->stringVar, 8, yPos, TEXT_SPEED_FF, 3);
StringCopy(sBerryBlender->stringVar, sBerryBlender->blendedBerries[place].name);
ConvertInternationalString(sBerryBlender->stringVar, gLinkPlayers[place].language);
StringAppend(sBerryBlender->stringVar, sText_SpaceBerry);
Blender_AddTextPrinter(5, sBerryBlender->stringVar, 0x54, yPos, TEXT_SPEED_FF, 3);
2017-11-19 22:48:46 +01:00
}
Blender_AddTextPrinter(5, sText_MaximumSpeed, 0, 0x51, TEXT_SPEED_FF, 3);
2020-08-23 00:20:22 +02:00
ConvertIntToDecimalStringN(sBerryBlender->stringVar, sBerryBlender->maxRPM / 100, STR_CONV_MODE_RIGHT_ALIGN, 3);
StringAppend(sBerryBlender->stringVar, sText_Dot);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
ConvertIntToDecimalStringN(text, sBerryBlender->maxRPM % 100, STR_CONV_MODE_LEADING_ZEROS, 2);
StringAppend(sBerryBlender->stringVar, text);
StringAppend(sBerryBlender->stringVar, sText_RPM);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
xPos = GetStringRightAlignXOffset(1, sBerryBlender->stringVar, 0xA8);
Blender_AddTextPrinter(5, sBerryBlender->stringVar, xPos, 0x51, TEXT_SPEED_FF, 3);
2017-11-19 22:48:46 +01:00
Blender_AddTextPrinter(5, sText_Time, 0, 0x61, TEXT_SPEED_FF, 3);
2020-08-23 00:20:22 +02:00
seconds = (sBerryBlender->gameFrameTime / 60) % 60;
minutes = (sBerryBlender->gameFrameTime / (60 * 60));
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
ConvertIntToDecimalStringN(sBerryBlender->stringVar, minutes, STR_CONV_MODE_LEADING_ZEROS, 2);
txtPtr = StringAppend(sBerryBlender->stringVar, sText_Min);
2017-11-19 22:48:46 +01:00
ConvertIntToDecimalStringN(txtPtr, seconds, STR_CONV_MODE_LEADING_ZEROS, 2);
2020-08-23 00:20:22 +02:00
StringAppend(sBerryBlender->stringVar, sText_Sec);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
xPos = GetStringRightAlignXOffset(1, sBerryBlender->stringVar, 0xA8);
Blender_AddTextPrinter(5, sBerryBlender->stringVar, xPos, 0x61, TEXT_SPEED_FF, 3);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
CopyWindowToVram(5, 2);
}
break;
case 4:
if (gMain.newKeys & A_BUTTON)
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
break;
case 5:
ClearStdWindowAndFrameToTransparent(5, 1);
2017-11-19 22:48:46 +01:00
for (i = 0; i < BLENDER_MAX_PLAYERS; i++)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->chosenItemId[i] != 0)
berryIds[i] = sBerryBlender->chosenItemId[i] - FIRST_BERRY_INDEX;
if (sBerryBlender->field_8E[i] != 0xFF)
2017-11-19 22:48:46 +01:00
{
PutWindowTilemap(i);
CopyWindowToVram(i, 3);
}
}
sub_8081E20();
2020-08-23 00:20:22 +02:00
Blender_CalculatePokeblock(sBerryBlender->blendedBerries, &pokeblock, sBerryBlender->numPlayers, flavors, sBerryBlender->maxRPM);
Blender_PrintMadePokeblockString(&pokeblock, sBerryBlender->stringVar);
TryAddContestLinkTvShow(&pokeblock, &sBerryBlender->tvBlender);
2017-11-19 22:48:46 +01:00
CreateTask(sub_8083F3C, 6);
IncrementDailyBerryBlender();
2017-11-19 22:48:46 +01:00
RemoveBagItem(gSpecialVar_ItemId, 1);
AddPokeblock(&pokeblock);
2020-08-23 00:20:22 +02:00
sBerryBlender->textState = 0;
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
break;
case 6:
2020-08-23 00:20:22 +02:00
if (Blender_PrintText(&sBerryBlender->textState, sBerryBlender->stringVar, GetPlayerTextSpeedDelay()))
2017-11-19 22:48:46 +01:00
{
TryUpdateBerryBlenderRecord();
return TRUE;
}
break;
}
return FALSE;
}
static void Blender_PrintMadePokeblockString(struct Pokeblock *pokeblock, u8 *dst)
{
u8 text[12];
2017-11-27 20:03:41 +01:00
u8 flavorLvl, feel;
2017-11-19 22:48:46 +01:00
dst[0] = EOS;
StringCopy(dst, gPokeblockNames[pokeblock->color]);
StringAppend(dst, sText_WasMade);
StringAppend(dst, sText_NewLine);
2017-11-27 20:03:41 +01:00
flavorLvl = GetHighestPokeblocksFlavorLevel(pokeblock);
2017-11-19 22:48:46 +01:00
feel = GetPokeblocksFeel(pokeblock);
StringAppend(dst, sText_TheLevelIs);
2017-11-27 20:03:41 +01:00
ConvertIntToDecimalStringN(text, flavorLvl, STR_CONV_MODE_LEFT_ALIGN, 3);
2017-11-19 22:48:46 +01:00
StringAppend(dst, text);
StringAppend(dst, sText_TheFeelIs);
ConvertIntToDecimalStringN(text, feel, STR_CONV_MODE_LEFT_ALIGN, 3);
StringAppend(dst, text);
StringAppend(dst, sText_Dot2);
StringAppend(dst, sText_NewParagraph);
}
static void Blender_SortBasedOnPoints(u8 *places, u8 playersNum, u32 *scores)
{
s32 i, j;
for (i = 0; i < playersNum; i++)
{
for (j = 0; j < playersNum; j++)
{
if (scores[places[i]] > scores[places[j]])
{
u8 temp = places[i];
places[i] = places[j];
places[j] = temp;
}
}
}
}
static void Blender_SortScores(void)
{
u8 playerId;
u8 i;
u8 places[BLENDER_MAX_PLAYERS];
u32 points[BLENDER_MAX_PLAYERS];
2020-08-23 00:20:22 +02:00
for (i = 0; i < sBerryBlender->numPlayers; i++)
2017-11-19 22:48:46 +01:00
places[i] = i;
2020-08-23 00:20:22 +02:00
for (i = 0; i < sBerryBlender->numPlayers; i++)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
points[i] = 1000000 * sBerryBlender->scores[i][SCORE_BEST];
points[i] += 1000 * sBerryBlender->scores[i][SCORE_GOOD];
points[i] += 1000 - sBerryBlender->scores[i][SCORE_MISS];
2017-11-19 22:48:46 +01:00
}
2020-08-23 00:20:22 +02:00
Blender_SortBasedOnPoints(places, sBerryBlender->numPlayers, points);
for (i = 0; i < sBerryBlender->numPlayers; i++)
sBerryBlender->playerPlaces[i] = places[i];
2017-11-19 22:48:46 +01:00
if (gReceivedRemoteLinkPlayers == 0)
playerId = 0;
else
playerId = GetMultiplayerId();
2020-08-23 00:20:22 +02:00
for (i = 0; i < sBerryBlender->numPlayers; i++)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->playerPlaces[i] == playerId)
sBerryBlender->field_1A4 = i;
2017-11-19 22:48:46 +01:00
}
}
2020-08-23 00:20:22 +02:00
static bool8 PrintBlendingRanking(void)
2017-11-19 22:48:46 +01:00
{
u16 i;
s32 xPos, yPos;
2020-08-23 00:20:22 +02:00
switch (sBerryBlender->mainState)
2017-11-19 22:48:46 +01:00
{
case 0:
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
sBerryBlender->framesToWait = 255;
2017-11-19 22:48:46 +01:00
break;
case 1:
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait -= 10;
if (sBerryBlender->framesToWait < 0)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
}
break;
case 2:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait > 20)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
}
break;
case 3:
DrawStdFrameWithCustomTileAndPalette(5, 0, 1, 0xD);
2017-11-19 22:48:46 +01:00
xPos = GetStringCenterAlignXOffset(1, sText_Ranking, 0xA8);
Blender_AddTextPrinter(5, sText_Ranking, xPos, 1, TEXT_SPEED_FF, 0);
2020-08-23 00:20:22 +02:00
sBerryBlender->scoreIconIds[SCORE_BEST] = CreateSprite(&sSpriteTemplate_ScoreSymbols, 128, 52, 0);
StartSpriteAnim(&gSprites[sBerryBlender->scoreIconIds[SCORE_BEST]], SCOREANIM_BEST_STATIC);
gSprites[sBerryBlender->scoreIconIds[SCORE_BEST]].callback = SpriteCallbackDummy;
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
sBerryBlender->scoreIconIds[SCORE_GOOD] = CreateSprite(&sSpriteTemplate_ScoreSymbols, 160, 52, 0);
// implicitly uses SCOREANIM_GOOD, no need to assign
gSprites[sBerryBlender->scoreIconIds[SCORE_GOOD]].callback = SpriteCallbackDummy;
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
sBerryBlender->scoreIconIds[SCORE_MISS] = CreateSprite(&sSpriteTemplate_ScoreSymbols, 192, 52, 0);
StartSpriteAnim(&gSprites[sBerryBlender->scoreIconIds[SCORE_MISS]], SCOREANIM_MISS);
gSprites[sBerryBlender->scoreIconIds[SCORE_MISS]].callback = SpriteCallbackDummy;
2017-11-19 22:48:46 +01:00
Blender_SortScores();
2020-08-23 00:20:22 +02:00
for (yPos = 0x29, i = 0; i < sBerryBlender->numPlayers; yPos += 0x10, i++)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
u8 place = sBerryBlender->playerPlaces[i];
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
ConvertIntToDecimalStringN(sBerryBlender->stringVar, i + 1, STR_CONV_MODE_LEFT_ALIGN, 1);
StringAppend(sBerryBlender->stringVar, sText_Dot);
StringAppend(sBerryBlender->stringVar, gText_Space);
StringAppend(sBerryBlender->stringVar, gLinkPlayers[place].name);
Blender_AddTextPrinter(5, sBerryBlender->stringVar, 0, yPos, TEXT_SPEED_FF, 3);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
ConvertIntToDecimalStringN(sBerryBlender->stringVar, sBerryBlender->scores[place][SCORE_BEST], STR_CONV_MODE_RIGHT_ALIGN, 3);
Blender_AddTextPrinter(5, sBerryBlender->stringVar, 0x4E, yPos, TEXT_SPEED_FF, 3);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
ConvertIntToDecimalStringN(sBerryBlender->stringVar, sBerryBlender->scores[place][SCORE_GOOD], STR_CONV_MODE_RIGHT_ALIGN, 3);
Blender_AddTextPrinter(5, sBerryBlender->stringVar, 0x6E, yPos, TEXT_SPEED_FF, 3);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
ConvertIntToDecimalStringN(sBerryBlender->stringVar, sBerryBlender->scores[place][SCORE_MISS], STR_CONV_MODE_RIGHT_ALIGN, 3);
Blender_AddTextPrinter(5, sBerryBlender->stringVar, 0x8E, yPos, TEXT_SPEED_FF, 3);
2017-11-19 22:48:46 +01:00
}
PutWindowTilemap(5);
CopyWindowToVram(5, 3);
2020-08-23 00:20:22 +02:00
sBerryBlender->framesToWait = 0;
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
break;
case 4:
2020-08-23 00:20:22 +02:00
if (++sBerryBlender->framesToWait > 20)
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
break;
case 5:
if (gMain.newKeys & A_BUTTON)
{
PlaySE(SE_SELECT);
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState++;
2017-11-19 22:48:46 +01:00
}
break;
case 6:
2020-08-23 00:20:22 +02:00
sBerryBlender->mainState = 0;
2017-11-19 22:48:46 +01:00
return TRUE;
}
return FALSE;
}
void ShowBerryBlenderRecordWindow(void)
{
s32 i;
s32 xPos, yPos;
struct WindowTemplate winTemplate;
u8 text[32];
winTemplate = sBlenderRecordWindowTemplate;
gRecordsWindowId = AddWindow(&winTemplate);
DrawStdWindowFrame(gRecordsWindowId, 0);
FillWindowPixelBuffer(gRecordsWindowId, PIXEL_FILL(1));
2017-11-19 22:48:46 +01:00
xPos = GetStringCenterAlignXOffset(1, gText_BlenderMaxSpeedRecord, 0x90);
AddTextPrinterParameterized(gRecordsWindowId, 1, gText_BlenderMaxSpeedRecord, xPos, 1, 0, NULL);
AddTextPrinterParameterized(gRecordsWindowId, 1, gText_234Players, 4, 0x29, 0, NULL);
2017-11-19 22:48:46 +01:00
2020-08-23 00:20:22 +02:00
for (i = 0, yPos = 0x29; i < NUM_SCORE_TYPES; i++)
2017-11-19 22:48:46 +01:00
{
u8 *txtPtr;
u32 record;
record = gSaveBlock1Ptr->berryBlenderRecords[i];
txtPtr = ConvertIntToDecimalStringN(text, record / 100, STR_CONV_MODE_RIGHT_ALIGN, 3);
txtPtr = StringAppend(txtPtr, sText_Dot);
txtPtr = ConvertIntToDecimalStringN(txtPtr, record % 100, STR_CONV_MODE_LEADING_ZEROS, 2);
txtPtr = StringAppend(txtPtr, sText_RPM);
xPos = GetStringRightAlignXOffset(1, text, 0x8C);
AddTextPrinterParameterized(gRecordsWindowId, 1, text, xPos, yPos + (i * 16), 0, NULL);
2017-11-19 22:48:46 +01:00
}
PutWindowTilemap(gRecordsWindowId);
CopyWindowToVram(gRecordsWindowId, 3);
2017-11-19 22:48:46 +01:00
}
static void sub_8083F3C(u8 taskId)
{
if (gTasks[taskId].data[0] == 0)
{
2017-12-22 08:46:19 +01:00
PlayFanfare(MUS_FANFA1);
2017-11-19 22:48:46 +01:00
gTasks[taskId].data[0]++;
}
if (IsFanfareTaskInactive())
{
2020-08-23 00:20:22 +02:00
PlayBGM(sBerryBlender->savedMusic);
2017-11-19 22:48:46 +01:00
DestroyTask(taskId);
}
}
static bool32 TryAddContestLinkTvShow(struct Pokeblock *pokeblock, struct TvBlenderStruct *tvBlender)
{
2017-11-27 20:03:41 +01:00
u8 flavorLevel = GetHighestPokeblocksFlavorLevel(pokeblock);
u16 sheen = (flavorLevel * 10) / GetPokeblocksFeel(pokeblock);
2017-11-19 22:48:46 +01:00
tvBlender->pokeblockSheen = sheen;
tvBlender->pokeblockColor = pokeblock->color;
tvBlender->name[0] = EOS;
if (gReceivedRemoteLinkPlayers != 0)
{
2020-08-23 00:20:22 +02:00
if (sBerryBlender->field_1A4 == 0 && sheen > 20)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
StringCopy(tvBlender->name, gLinkPlayers[sBerryBlender->playerPlaces[sBerryBlender->numPlayers - 1]].name);
2017-11-27 20:03:41 +01:00
tvBlender->pokeblockFlavor = GetPokeblocksFlavor(pokeblock);
if (Put3CheersForPokeblocksOnTheAir(tvBlender->name, tvBlender->pokeblockFlavor,
2017-11-19 22:48:46 +01:00
tvBlender->pokeblockColor, tvBlender->pokeblockSheen,
2020-08-23 00:20:22 +02:00
gLinkPlayers[sBerryBlender->playerPlaces[sBerryBlender->numPlayers - 1]].language))
2017-11-19 22:48:46 +01:00
{
return TRUE;
}
return FALSE;
}
2020-08-23 00:20:22 +02:00
else if (sBerryBlender->field_1A4 == sBerryBlender->numPlayers - 1 && sheen <= 20)
2017-11-19 22:48:46 +01:00
{
2020-08-23 00:20:22 +02:00
StringCopy(tvBlender->name, gLinkPlayers[sBerryBlender->playerPlaces[0]].name);
2017-11-27 20:03:41 +01:00
tvBlender->pokeblockFlavor = GetPokeblocksFlavor(pokeblock);
if (Put3CheersForPokeblocksOnTheAir(tvBlender->name, tvBlender->pokeblockFlavor,
2017-11-19 22:48:46 +01:00
tvBlender->pokeblockColor, tvBlender->pokeblockSheen,
2020-08-23 00:20:22 +02:00
gLinkPlayers[sBerryBlender->playerPlaces[0]].language))
2017-11-19 22:48:46 +01:00
{
return TRUE;
}
return FALSE;
}
}
return FALSE;
}
static void Blender_AddTextPrinter(u8 windowId, const u8 *string, u8 x, u8 y, s32 speed, s32 caseId)
{
2018-02-07 03:37:54 +01:00
u8 txtColor[3];
2017-11-19 22:48:46 +01:00
u32 letterSpacing = 0;
switch (caseId)
{
case 0:
case 3:
2018-02-07 03:37:54 +01:00
txtColor[0] = 1;
txtColor[1] = 2;
txtColor[2] = 3;
2017-11-19 22:48:46 +01:00
break;
case 1:
2018-02-07 03:37:54 +01:00
txtColor[0] = 0;
txtColor[1] = 2;
txtColor[2] = 3;
2017-11-19 22:48:46 +01:00
break;
case 2:
2018-02-07 03:37:54 +01:00
txtColor[0] = 0;
txtColor[1] = 4;
txtColor[2] = 5;
2017-11-19 22:48:46 +01:00
break;
}
if (caseId != 3)
{
FillWindowPixelBuffer(windowId, PIXEL_FILL(txtColor[0]));
2017-11-19 22:48:46 +01:00
}
AddTextPrinterParameterized4(windowId, 1, x, y, letterSpacing, 1, txtColor, speed, string);
2017-11-19 22:48:46 +01:00
}
static bool32 Blender_PrintText(s16 *textState, const u8 *string, s32 textSpeed)
{
switch (*textState)
{
case 0:
DrawDialogFrameWithCustomTileAndPalette(4, FALSE, 0x14, 0xF);
2017-11-19 22:48:46 +01:00
Blender_AddTextPrinter(4, string, 0, 1, textSpeed, 0);
PutWindowTilemap(4);
CopyWindowToVram(4, 3);
(*textState)++;
break;
case 1:
if (!IsTextPrinterActive(4))
{
*textState = 0;
return TRUE;
}
break;
}
2017-09-30 16:12:35 +02:00
2017-11-19 22:48:46 +01:00
return FALSE;
}