summaryrefslogtreecommitdiff
path: root/src/contest_2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/contest_2.c')
-rw-r--r--src/contest_2.c4186
1 files changed, 4186 insertions, 0 deletions
diff --git a/src/contest_2.c b/src/contest_2.c
new file mode 100644
index 000000000..58da38acf
--- /dev/null
+++ b/src/contest_2.c
@@ -0,0 +1,4186 @@
+#include "global.h"
+#include "contest.h"
+#include "battle.h"
+#include "battle_anim.h"
+#include "blend_palette.h"
+#include "constants/event_objects.h"
+#include "constants/items.h"
+#include "constants/moves.h"
+#include "constants/songs.h"
+#include "constants/species.h"
+#include "contest_ai.h"
+#include "contest_effect.h"
+#include "data2.h"
+#include "decompress.h"
+#include "ewram.h"
+#include "graphics.h"
+#include "link.h"
+#include "m4a.h"
+#include "menu.h"
+#include "palette.h"
+#include "random.h"
+#include "rom_8077ABC.h"
+#include "sound.h"
+#include "sprite.h"
+#include "string_util.h"
+#include "task.h"
+#include "text.h"
+#include "util.h"
+
+#include "contest_internal.h"
+
+extern void Task_LinkContest_CommunicateAppealsState(u8 taskId);
+extern void Task_UpdateContestantBoxOrder(u8 taskId);
+
+extern struct MusicPlayerInfo gMPlayInfo_SE1;
+extern u8 gBattleMonForms[];
+extern u8 gDisplayedStringBattle[];
+extern u8 gBattlerTarget;
+extern u8 gBattlerSpriteIds[];
+extern struct Window gWindowTemplate_Contest_MoveDescription;
+extern struct SpriteTemplate gCreatingSpriteTemplate;
+extern void (*const gContestEffectFuncs[])(void);
+
+#include "data/contest_opponents.h"
+
+const u8 gUnknown_083CA308[][2] = {
+ {19, 0},
+ {19, 5},
+ {19, 10},
+ {19, 15},
+};
+
+const u8 gUnknown_083CA310[][2] = {
+ {25, 0},
+ {25, 5},
+ {25, 10},
+ {25, 15},
+};
+
+const u8 gUnknown_083CA318[][2] = {
+ { 20, 2 },
+ { 20, 7 },
+ { 20, 12 },
+ { 20, 17 },
+ { 24, 2 },
+ { 24, 7 },
+ { 24, 12 },
+ { 24, 17 },
+ { 220, 24 },
+ { 220, 64 },
+ { 220, 104 },
+ { 220, 144 },
+};
+
+const u8 gUnknown_083CA330[][2] = {
+ { 224, 24 },
+ { 224, 64 },
+ { 224, 104 },
+ { 224, 144 },
+};
+
+const u8 sSliderHeartYPositions[] = { 36, 76, 116, 156 };
+const u8 gUnknown_083CA33C[] = { 36, 76, 116, 156 };
+
+const u8 gUnknown_083CA340[][4] = {
+ { 0, 31, 9, 39 },
+ { 0, 33, 9, 39 },
+ { 0, 35, 9, 39 },
+ { 0, 37, 9, 39 },
+};
+
+const struct SpriteSheet sSpriteSheet_SliderHeart = {
+ .data = gTiles_8D1975C,
+ .size = 0x20,
+ .tag = 20004
+};
+
+const struct OamData gOamData_83CA358 = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(8x8),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(8x8),
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+// Idle
+const union AffineAnimCmd gSpriteAffineAnim_83CA360[] = {
+ AFFINEANIMCMD_FRAME(Q_8_8(1.0), Q_8_8(1.0), 0, 0),
+ AFFINEANIMCMD_END
+};
+
+// Shrink
+const union AffineAnimCmd gSpriteAffineAnim_83CA370[] = {
+ AFFINEANIMCMD_FRAME(256, 256, 0, 0),
+ AFFINEANIMCMD_FRAME(-10, -10, -20, 20),
+ AFFINEANIMCMD_END
+};
+
+// Grow
+const union AffineAnimCmd gSpriteAffineAnim_83CA388[] = {
+ AFFINEANIMCMD_FRAME(56, 56, 0, 0),
+ AFFINEANIMCMD_FRAME(10, 10, 20, 20),
+ AFFINEANIMCMD_END
+};
+
+const union AffineAnimCmd *const gSpriteAffineAnimTable_83CA3A0[] = {
+ gSpriteAffineAnim_83CA360,
+ gSpriteAffineAnim_83CA370,
+ gSpriteAffineAnim_83CA388,
+};
+
+const struct SpriteTemplate sSpriteTemplate_SliderHeart = {
+ .tileTag = 20004,
+ .paletteTag = 44000,
+ .oam = &gOamData_83CA358,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_83CA3A0,
+ .callback = SpriteCallbackDummy
+};
+
+// One graphic for each contestant.
+// Yes, it's loaded four times.
+const struct CompressedSpriteSheet gUnknown_083CA3C4[] = {
+ { .data = gContestNextTurnGfx, .size = 0x100, .tag = 20006 },
+ { .data = gContestNextTurnGfx, .size = 0x100, .tag = 20007 },
+ { .data = gContestNextTurnGfx, .size = 0x100, .tag = 20008 },
+ { .data = gContestNextTurnGfx, .size = 0x100, .tag = 20009 },
+};
+
+const struct SpritePalette gUnknown_083CA3E4 = {
+ .data = gContestPal, .tag = 20006
+};
+
+const struct OamData gOamData_83CA3EC = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(32x8),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(32x8),
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+const struct SpriteTemplate gSpriteTemplate_83CA3F4[] = {
+ { .tileTag = 20006, .paletteTag = 20006, .oam = &gOamData_83CA3EC, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy },
+ { .tileTag = 20007, .paletteTag = 20006, .oam = &gOamData_83CA3EC, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy },
+ { .tileTag = 20008, .paletteTag = 20006, .oam = &gOamData_83CA3EC, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy },
+ { .tileTag = 20009, .paletteTag = 20006, .oam = &gOamData_83CA3EC, .anims = gDummySpriteAnimTable, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy },
+};
+
+const struct Subsprite gSubspriteTable_83CA454[] = {
+ { .x = -26, .y = -4, .shape = ST_OAM_H_RECTANGLE, .size = 1, .tileOffset = 0, .priority = 0 },
+ { .x = 6, .y = -4, .shape = ST_OAM_H_RECTANGLE, .size = 1, .tileOffset = 4, .priority = 0 },
+};
+
+const struct SubspriteTable gSubspriteTables_83CA464[] = {
+ { 2, gSubspriteTable_83CA454 },
+};
+
+const struct CompressedSpriteSheet gUnknown_083CA46C = {
+ .data = gContestApplauseGfx,
+ .size = 0x400,
+ .tag = 44002
+};
+
+const struct SpritePalette gUnknown_083CA474 = {
+ .data = gContestPal,
+ .tag = 44002
+};
+
+const struct OamData gOamData_83CA47C = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x32),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(64x32),
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+const struct SpriteTemplate gSpriteTemplate_83CA484 = {
+ .tileTag = 44002,
+ .paletteTag = 44002,
+ .oam = &gOamData_83CA47C,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+const struct OamData gOamData_83CA49C = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0,
+ .priority = 3,
+ .paletteNum = 2
+};
+
+const struct SpriteTemplate sSpriteTemplate_Judge = {
+ .tileTag = 20005,
+ .paletteTag = 20005,
+ .oam = &gOamData_83CA49C,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+};
+
+const struct CompressedSpriteSheet sSpriteSheet_Judge = {
+ .data = gContestJudgeGfx,
+ .size = 0x800,
+ .tag = 20005
+};
+
+const struct CompressedSpriteSheet sSpriteSheet_JudgeSymbols = {
+ .data = gContestJudgeSymbolsGfx,
+ .size = 0x380,
+ .tag = 44000
+};
+
+const struct CompressedSpritePalette sSpritePalette_JudgeSymbols = {
+ .data = gContest3Pal,
+ .tag = 44000
+};
+
+const struct SpriteTemplate sSpriteTemplate_JudgeSpeechBubble = {
+ .tileTag = 44000,
+ .paletteTag = 44000,
+ .oam = &gOamData_837DF2C,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy,
+};
+
+#if defined(ENGLISH)
+#include "data/text/contest_en.h"
+#elif defined(GERMAN)
+#include "data/text/contest_de.h"
+#endif //ENGLISH
+
+UNUSED
+const u8 ALIGNED(2) _unk_83CC3BE[] = __("ピラ");
+const u8 gUnknownText_UnknownFormatting2[] = _("{COLOR GREEN}{SHADOW RED}");
+const u8 gUnknownText_UnknownFormatting3[] = _("{COLOR LIGHT_GREY}");
+
+const struct CompressedSpriteSheet gUnknown_083CC3AC = {
+ .data = gContestNumbers_UnusedGfx,
+ .size = 0x200,
+ .tag = 20000
+};
+
+const struct CompressedSpritePalette gUnknown_083CC3B4[] = {
+ { .data = gContestNumbers_UnusedPal, .tag = 20000 },
+ { .data = gContestNumbers_UnusedPal, .tag = 20001 },
+ { .data = gContestNumbers_UnusedPal, .tag = 20002 },
+ { .data = gContestNumbers_UnusedPal, .tag = 20003 },
+};
+
+const union AnimCmd gSpriteAnim_83CC3D4[] = {
+ ANIMCMD_FRAME( 0, 1),
+ ANIMCMD_END
+};
+
+const union AnimCmd gSpriteAnim_83CC3DC[] = {
+ ANIMCMD_FRAME( 4, 1),
+ ANIMCMD_END
+};
+
+const union AnimCmd gSpriteAnim_83CC3E4[] = {
+ ANIMCMD_FRAME( 8, 1),
+ ANIMCMD_END
+};
+
+const union AnimCmd gSpriteAnim_83CC3EC[] = {
+ ANIMCMD_FRAME(12, 1),
+ ANIMCMD_END
+};
+
+const union AnimCmd *const gSpriteAnimTable_83CC3F4[] = {
+ gSpriteAnim_83CC3D4,
+ gSpriteAnim_83CC3DC,
+ gSpriteAnim_83CC3E4,
+ gSpriteAnim_83CC3EC,
+};
+
+const union AffineAnimCmd gSpriteAffineAnim_83CC404[] = {
+ AFFINEANIMCMD_FRAME(0, 0, 0, 1),
+ AFFINEANIMCMD_END
+};
+
+const union AffineAnimCmd gSpriteAffineAnim_83CC414[] = {
+ AFFINEANIMCMD_FRAME(-15, -15, 0, 15),
+ AFFINEANIMCMD_END
+};
+
+const union AffineAnimCmd gSpriteAffineAnim_83CC424[] = {
+ AFFINEANIMCMD_FRAME(31, 31, 0, 0),
+ AFFINEANIMCMD_FRAME(15, 15, 0, 15),
+ AFFINEANIMCMD_END
+};
+
+const union AffineAnimCmd *const gSpriteAffineAnimTable_83CC43C[] = {
+ gSpriteAffineAnim_83CC404,
+ gSpriteAffineAnim_83CC414,
+ gSpriteAffineAnim_83CC424,
+ NULL,
+};
+
+const struct OamData gOamData_83CC44C = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(16x16),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(16x16),
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+const struct SpriteTemplate gSpriteTemplate_83CC454[] = {
+ {
+ .tileTag = 20000,
+ .paletteTag = 20000,
+ .oam = &gOamData_83CC44C,
+ .anims = gSpriteAnimTable_83CC3F4,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_83CC43C,
+ .callback = SpriteCallbackDummy,
+ },
+ {
+ .tileTag = 20000,
+ .paletteTag = 20001,
+ .oam = &gOamData_83CC44C,
+ .anims = gSpriteAnimTable_83CC3F4,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_83CC43C,
+ .callback = SpriteCallbackDummy,
+ },
+ {
+ .tileTag = 20000,
+ .paletteTag = 20002,
+ .oam = &gOamData_83CC44C,
+ .anims = gSpriteAnimTable_83CC3F4,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_83CC43C,
+ .callback = SpriteCallbackDummy,
+ },
+ {
+ .tileTag = 20000,
+ .paletteTag = 20003,
+ .oam = &gOamData_83CC44C,
+ .anims = gSpriteAnimTable_83CC3F4,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_83CC43C,
+ .callback = SpriteCallbackDummy,
+ },
+};
+
+const struct CompressedSpriteSheet gUnknown_083CC4B4[] = {
+ { .data = gBlankGfxCompressed, .size = 0x1000, .tag = 33000 },
+ { .data = gBlankGfxCompressed, .size = 0x1000, .tag = 33001 },
+ { .data = gBlankGfxCompressed, .size = 0x1000, .tag = 33002 },
+ { .data = gBlankGfxCompressed, .size = 0x1000, .tag = 33003 },
+};
+
+const struct SpritePalette gUnknown_083CC4D4[] = {
+ { .data = eContestTempSave.cachedWindowPalettes[5], .tag = 33000 },
+ { .data = eContestTempSave.cachedWindowPalettes[6], .tag = 33001 },
+ { .data = eContestTempSave.cachedWindowPalettes[7], .tag = 33002 },
+ { .data = eContestTempSave.cachedWindowPalettes[8], .tag = 33003 },
+};
+
+const struct OamData gOamData_83CC4F4 = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_DOUBLE,
+ .objMode = ST_OAM_OBJ_BLEND,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+const union AffineAnimCmd gSpriteAffineAnim_83CC4FC[] = {
+ AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
+ AFFINEANIMCMD_END
+};
+
+const union AffineAnimCmd gSpriteAffineAnim_83CC50C[] = {
+ AFFINEANIMCMD_FRAME( 3, 3, 0, 15),
+ AFFINEANIMCMD_FRAME(-3, -3, 0, 15),
+ AFFINEANIMCMD_FRAME( 3, 3, 0, 15),
+ AFFINEANIMCMD_FRAME(-3, -3, 0, 15),
+ AFFINEANIMCMD_END
+};
+
+const union AffineAnimCmd *const gSpriteAffineAnimTable_83CC534[] = {
+ gSpriteAffineAnim_83CC4FC,
+ gSpriteAffineAnim_83CC50C,
+};
+
+const struct SpriteTemplate gSpriteTemplate_83CC53C[] = {
+ {
+ .tileTag = 33000,
+ .paletteTag = 33000,
+ .oam = &gOamData_83CC4F4,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_83CC534,
+ .callback = SpriteCallbackDummy,
+ },
+ {
+ .tileTag = 33001,
+ .paletteTag = 33001,
+ .oam = &gOamData_83CC4F4,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_83CC534,
+ .callback = SpriteCallbackDummy,
+ },
+ {
+ .tileTag = 33002,
+ .paletteTag = 33002,
+ .oam = &gOamData_83CC4F4,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_83CC534,
+ .callback = SpriteCallbackDummy,
+ },
+ {
+ .tileTag = 33003,
+ .paletteTag = 33003,
+ .oam = &gOamData_83CC4F4,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gSpriteAffineAnimTable_83CC534,
+ .callback = SpriteCallbackDummy,
+ },
+};
+
+const u8 gUnknown_083CC59C[] = _("{HIGHLIGHT TRANSPARENT}{COLOR}");
+const u8 gText_Slash[] = _("/");
+
+const u16 gUnknown_083CC5A4[] = {
+ RGB(19, 3, 0),
+ RGB(6, 15, 6),
+ RGB(19, 18, 0),
+ RGB(4, 6, 19),
+ RGB(31, 0, 0),
+ RGB(0, 31, 0),
+ RGB(31, 31, 0),
+ RGB(0, 0, 31),
+};
+
+const u8 gContestExcitementTable[][5] =
+{
+ [CONTEST_CATEGORY_COOL] = {
+ [CONTEST_CATEGORY_COOL] = +1,
+ [CONTEST_CATEGORY_BEAUTY] = 0,
+ [CONTEST_CATEGORY_CUTE] = -1,
+ [CONTEST_CATEGORY_SMART] = -1,
+ [CONTEST_CATEGORY_TOUGH] = 0
+ },
+ [CONTEST_CATEGORY_BEAUTY] = {
+ [CONTEST_CATEGORY_COOL] = 0,
+ [CONTEST_CATEGORY_BEAUTY] = +1,
+ [CONTEST_CATEGORY_CUTE] = 0,
+ [CONTEST_CATEGORY_SMART] = -1,
+ [CONTEST_CATEGORY_TOUGH] = -1
+ },
+ [CONTEST_CATEGORY_CUTE] = {
+ [CONTEST_CATEGORY_COOL] = -1,
+ [CONTEST_CATEGORY_BEAUTY] = 0,
+ [CONTEST_CATEGORY_CUTE] = +1,
+ [CONTEST_CATEGORY_SMART] = 0,
+ [CONTEST_CATEGORY_TOUGH] = -1
+ },
+ [CONTEST_CATEGORY_SMART] = {
+ [CONTEST_CATEGORY_COOL] = -1,
+ [CONTEST_CATEGORY_BEAUTY] = -1,
+ [CONTEST_CATEGORY_CUTE] = 0,
+ [CONTEST_CATEGORY_SMART] = +1,
+ [CONTEST_CATEGORY_TOUGH] = 0
+ },
+ [CONTEST_CATEGORY_TOUGH] = {
+ [CONTEST_CATEGORY_COOL] = 0,
+ [CONTEST_CATEGORY_BEAUTY] = -1,
+ [CONTEST_CATEGORY_CUTE] = -1,
+ [CONTEST_CATEGORY_SMART] = 0,
+ [CONTEST_CATEGORY_TOUGH] = +1
+ }
+};
+
+#if defined(ENGLISH)
+#define CONTEST_WINNER_1_NICKNAME "TAILTA"
+#define CONTEST_WINNER_1_OTNAME "WYATT"
+#define CONTEST_WINNER_2_NICKNAME "BRELO"
+#define CONTEST_WINNER_2_OTNAME "LIANA"
+#define CONTEST_WINNER_3_NICKNAME "PELEP"
+#define CONTEST_WINNER_3_OTNAME "TIERA"
+#define CONTEST_WINNER_4_NICKNAME "PELEP"
+#define CONTEST_WINNER_4_OTNAME "TIERA"
+#define CONTEST_WINNER_5_NICKNAME "PELEP"
+#define CONTEST_WINNER_5_OTNAME "TIERA"
+#define CONTEST_WINNER_6_NICKNAME "KITSY"
+#define CONTEST_WINNER_6_OTNAME "OMAR"
+#define CONTEST_WINNER_7_NICKNAME "GULPS"
+#define CONTEST_WINNER_7_OTNAME "MACIE"
+#define CONTEST_WINNER_8_NICKNAME "LOUDED"
+#define CONTEST_WINNER_8_OTNAME "BRYANT"
+#elif defined(GERMAN)
+#define CONTEST_WINNER_1_NICKNAME "SCHWALBI"
+#define CONTEST_WINNER_1_OTNAME "ROSEL"
+#define CONTEST_WINNER_2_NICKNAME "TUFUNG"
+#define CONTEST_WINNER_2_OTNAME "WITOLD"
+#define CONTEST_WINNER_3_NICKNAME "LIPPER"
+#define CONTEST_WINNER_3_OTNAME "RUFUS"
+#define CONTEST_WINNER_4_NICKNAME "LIPPER"
+#define CONTEST_WINNER_4_OTNAME "ELLEN"
+#define CONTEST_WINNER_5_NICKNAME "LIPPER"
+#define CONTEST_WINNER_5_OTNAME "AVIA"
+#define CONTEST_WINNER_6_NICKNAME "CONEC"
+#define CONTEST_WINNER_6_OTNAME "HAUBERT"
+#define CONTEST_WINNER_7_NICKNAME "SCHLUCKI"
+#define CONTEST_WINNER_7_OTNAME "HEILWIG"
+#define CONTEST_WINNER_8_NICKNAME "KEELO"
+#define CONTEST_WINNER_8_OTNAME "ISEGRIM"
+#endif
+
+const struct ContestWinner gDefaultContestWinners[] = {
+ {
+ .personality = 0,
+ .otId = 0xFFFF,
+ .species = SPECIES_TAILLOW,
+ .contestCategory = CONTEST_CATEGORY_SMART,
+ .nickname = _(CONTEST_WINNER_1_NICKNAME),
+ .trainerName = _(CONTEST_WINNER_1_OTNAME),
+ },
+ {
+ .personality = 0,
+ .otId = 0xFFFF,
+ .species = SPECIES_BRELOOM,
+ .contestCategory = CONTEST_CATEGORY_BEAUTY,
+ .nickname = _(CONTEST_WINNER_2_NICKNAME),
+ .trainerName = _(CONTEST_WINNER_2_OTNAME),
+ },
+ {
+ .personality = 0,
+ .otId = 0xFFFF,
+ .species = SPECIES_PELIPPER,
+ .contestCategory = CONTEST_CATEGORY_COOL,
+ .nickname = _(CONTEST_WINNER_3_NICKNAME),
+ .trainerName = _(CONTEST_WINNER_3_OTNAME),
+ },
+ {
+ .personality = 0,
+ .otId = 0xFFFF,
+ .species = SPECIES_PELIPPER,
+ .contestCategory = CONTEST_CATEGORY_COOL,
+ .nickname = _(CONTEST_WINNER_4_NICKNAME),
+ .trainerName = _(CONTEST_WINNER_4_OTNAME),
+ },
+ {
+ .personality = 0,
+ .otId = 0xFFFF,
+ .species = SPECIES_PELIPPER,
+ .contestCategory = CONTEST_CATEGORY_COOL,
+ .nickname = _(CONTEST_WINNER_5_NICKNAME),
+ .trainerName = _(CONTEST_WINNER_5_OTNAME),
+ },
+ {
+ .personality = 0,
+ .otId = 0xFFFF,
+ .species = SPECIES_DELCATTY,
+ .contestCategory = CONTEST_CATEGORY_SMART,
+ .nickname = _(CONTEST_WINNER_6_NICKNAME),
+ .trainerName = _(CONTEST_WINNER_6_OTNAME),
+ },
+ {
+ .personality = 0,
+ .otId = 0xFFFF,
+ .species = SPECIES_GULPIN,
+ .contestCategory = CONTEST_CATEGORY_CUTE,
+ .nickname = _(CONTEST_WINNER_7_NICKNAME),
+ .trainerName = _(CONTEST_WINNER_7_OTNAME),
+ },
+ {
+ .personality = 0,
+ .otId = 0xFFFF,
+ .species = SPECIES_LOUDRED,
+ .contestCategory = CONTEST_CATEGORY_TOUGH,
+ .nickname = _(CONTEST_WINNER_8_NICKNAME),
+ .trainerName = _(CONTEST_WINNER_8_OTNAME),
+ },
+};
+
+void TryPutPlayerLast(void)
+{
+ if (!(gIsLinkContest & 1))
+ gContestPlayerMonIndex = 3;
+}
+
+bool8 IsPlayerLinkLeader(void)
+{
+ if (gContestPlayerMonIndex == gContestLinkLeaderIndex)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void Contest_CreatePlayerMon(u8 partyIndex)
+{
+ u8 name[20];
+ u16 heldItem;
+ s16 cool;
+ s16 beauty;
+ s16 cute;
+ s16 smart;
+ s16 tough;
+
+ StringCopy(name, gSaveBlock2.playerName);
+ Text_StripExtCtrlCodes(name);
+ if (gIsLinkContest & 1)
+ {
+ u8 temp = name[5];
+
+ name[5] = EOS;
+ name[7] = temp;
+ }
+ memcpy(gContestMons[gContestPlayerMonIndex].trainerName, name, 8);
+ if (gSaveBlock2.playerGender == MALE)
+ gContestMons[gContestPlayerMonIndex].trainerGfxId = OBJ_EVENT_GFX_LINK_BRENDAN;
+ else
+ gContestMons[gContestPlayerMonIndex].trainerGfxId = OBJ_EVENT_GFX_LINK_MAY;
+ gContestMons[gContestPlayerMonIndex].flags = 0;
+ gContestMons[gContestPlayerMonIndex].unk2C[0] = 0;
+ gContestMons[gContestPlayerMonIndex].species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES);
+ GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, name);
+ StringGetEnd10(name);
+ if (gIsLinkContest & 1)
+ {
+ Text_StripExtCtrlCodes(name);
+ if (GetMonData(&gPlayerParty[partyIndex], MON_DATA_LANGUAGE) == LANGUAGE_JAPANESE)
+ {
+ name[5] = EOS;
+ name[10] = EXT_CTRL_CODE_BEGIN;
+ }
+ else
+ {
+ u8 temp = name[5];
+
+ name[5] = EOS;
+ name[10] = temp;
+ }
+ }
+ memcpy(gContestMons[gContestPlayerMonIndex].nickname, name, 11);
+ gContestMons[gContestPlayerMonIndex].cool = GetMonData(&gPlayerParty[partyIndex], MON_DATA_COOL);
+ gContestMons[gContestPlayerMonIndex].beauty = GetMonData(&gPlayerParty[partyIndex], MON_DATA_BEAUTY);
+ gContestMons[gContestPlayerMonIndex].cute = GetMonData(&gPlayerParty[partyIndex], MON_DATA_CUTE);
+ gContestMons[gContestPlayerMonIndex].smart = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SMART);
+ gContestMons[gContestPlayerMonIndex].tough = GetMonData(&gPlayerParty[partyIndex], MON_DATA_TOUGH);
+ gContestMons[gContestPlayerMonIndex].sheen = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SHEEN);
+ gContestMons[gContestPlayerMonIndex].moves[0] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE1);
+ gContestMons[gContestPlayerMonIndex].moves[1] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE2);
+ gContestMons[gContestPlayerMonIndex].moves[2] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE3);
+ gContestMons[gContestPlayerMonIndex].moves[3] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE4);
+ gContestMons[gContestPlayerMonIndex].personality = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PERSONALITY);
+ gContestMons[gContestPlayerMonIndex].otId = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_ID);
+
+ heldItem = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HELD_ITEM);
+ cool = gContestMons[gContestPlayerMonIndex].cool;
+ beauty = gContestMons[gContestPlayerMonIndex].beauty;
+ cute = gContestMons[gContestPlayerMonIndex].cute;
+ smart = gContestMons[gContestPlayerMonIndex].smart;
+ tough = gContestMons[gContestPlayerMonIndex].tough;
+ if (heldItem == ITEM_RED_SCARF)
+ cool += 20;
+ else if (heldItem == ITEM_BLUE_SCARF)
+ beauty += 20;
+ else if (heldItem == ITEM_PINK_SCARF)
+ cute += 20;
+ else if (heldItem == ITEM_GREEN_SCARF)
+ smart += 20;
+ else if (heldItem == ITEM_YELLOW_SCARF)
+ tough += 20;
+ if (cool > 255)
+ cool = 255;
+ if (beauty > 255)
+ beauty = 255;
+ if (cute > 255)
+ cute = 255;
+ if (smart > 255)
+ smart = 255;
+ if (tough > 255)
+ tough = 255;
+ gContestMons[gContestPlayerMonIndex].cool = cool;
+ gContestMons[gContestPlayerMonIndex].beauty = beauty;
+ gContestMons[gContestPlayerMonIndex].cute = cute;
+ gContestMons[gContestPlayerMonIndex].smart = smart;
+ gContestMons[gContestPlayerMonIndex].tough = tough;
+}
+
+void Contest_InitAllPokemon(u8 contestType, u8 rank)
+{
+ s32 i;
+ u8 opponentsCount = 0;
+ u8 opponents[ARRAY_COUNT(gContestOpponents) + 1];
+
+ TryPutPlayerLast();
+
+ // Find all suitable opponents
+ for (i = 0; i < (s32)ARRAY_COUNT(gContestOpponents); i++)
+ {
+ if (rank == gContestOpponents[i].whichRank)
+ {
+ if (contestType == 0 && gContestOpponents[i].aiPool_Cool)
+ opponents[opponentsCount++] = i;
+ else if (contestType == 1 && gContestOpponents[i].aiPool_Beauty)
+ opponents[opponentsCount++] = i;
+ else if (contestType == 2 && gContestOpponents[i].aiPool_Cute)
+ opponents[opponentsCount++] = i;
+ else if (contestType == 3 && gContestOpponents[i].aiPool_Smart)
+ opponents[opponentsCount++] = i;
+ else if (contestType == 4 && gContestOpponents[i].aiPool_Tough)
+ opponents[opponentsCount++] = i;
+ }
+ }
+ opponents[opponentsCount] = 0xFF;
+
+ // Choose three random opponents from the list
+ for (i = 0; i < 3; i++)
+ {
+ u16 rnd = Random() % opponentsCount;
+ s32 j;
+
+ gContestMons[i] = gContestOpponents[opponents[rnd]];
+ for (j = rnd; opponents[j] != 0xFF; j++)
+ opponents[j] = opponents[j + 1];
+ opponentsCount--;
+ }
+
+#ifndef NONMATCHING
+ // Compiler, please put i in r5. Thanks.
+ asm(""::"r"(i));
+ asm(""::"r"(i));
+ asm(""::"r"(i));
+ asm(""::"r"(i));
+ asm(""::"r"(i));
+#endif
+
+ Contest_CreatePlayerMon(gContestMonPartyIndex);
+}
+
+// GetContestAvailability?
+u8 CanMonParticipateInContest(struct Pokemon *pkmn)
+{
+ u8 ribbon;
+ u8 retVal;
+
+ if (GetMonData(pkmn, MON_DATA_IS_EGG))
+ return 3;
+ if (GetMonData(pkmn, MON_DATA_HP) == 0)
+ return 4;
+ switch (gSpecialVar_ContestCategory)
+ {
+ case CONTEST_CATEGORY_COOL:
+ ribbon = GetMonData(pkmn, MON_DATA_COOL_RIBBON);
+ break;
+ case CONTEST_CATEGORY_BEAUTY:
+ ribbon = GetMonData(pkmn, MON_DATA_BEAUTY_RIBBON);
+ break;
+ case CONTEST_CATEGORY_CUTE:
+ ribbon = GetMonData(pkmn, MON_DATA_CUTE_RIBBON);
+ break;
+ case CONTEST_CATEGORY_SMART:
+ ribbon = GetMonData(pkmn, MON_DATA_SMART_RIBBON);
+ break;
+ case CONTEST_CATEGORY_TOUGH:
+ ribbon = GetMonData(pkmn, MON_DATA_TOUGH_RIBBON);
+ break;
+ default:
+ return 0;
+ }
+
+ // Couldn't get this to match any other way.
+ // Returns 2, 1, or 0 respectively if ribbon's rank is above, equal, or below
+ // the current contest rank.
+ if (ribbon > gSpecialVar_ContestRank)
+ retVal = 2;
+ else if (ribbon >= gSpecialVar_ContestRank)
+ retVal = 1;
+ else
+ retVal = 0;
+ return retVal;
+}
+
+void DrawContestantWindowText(void)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ Text_FillWindowRectDefPalette(
+ &gWindowTemplate_Contest_MoveDescription,
+ 0,
+ gUnknown_083CA308[gContestantTurnOrder[i]][0],
+ gUnknown_083CA308[gContestantTurnOrder[i]][1],
+ gUnknown_083CA310[gContestantTurnOrder[i]][0] + 5,
+ gUnknown_083CA310[gContestantTurnOrder[i]][1] + 1);
+ PrintContestantTrainerName(i);
+ PrintContestantMonName(i);
+ }
+}
+
+u8 *Contest_CopyStringWithColor(u8 *dest, const u8 *src, u8 color)
+{
+ dest = StringCopy(dest, gUnknown_083CC59C); // {HIGHLIGHT TRANSPARENT}{COLOR}$
+ *dest++ = color;
+ dest = StringCopy(dest, src);
+ return dest;
+}
+
+void PrintContestantTrainerName(u8 contestant)
+{
+ PrintContestantTrainerNameWithColor(contestant, contestant + 10);
+}
+
+void PrintContestantTrainerNameWithColor(u8 contestant, u8 color)
+{
+ u8 *str = gDisplayedStringBattle;
+
+ str = Contest_CopyStringWithColor(str, gEmptyString_81E72B0, color);
+ str[0] = EXT_CTRL_CODE_BEGIN;
+ str[1] = EXT_CTRL_CODE_SIZE;
+ str[2] = 4;
+ str += 3;
+
+ *str++ = CHAR_SLASH;
+
+ if ((gIsLinkContest & 1) && gLinkPlayers[contestant].language == LANGUAGE_JAPANESE)
+ {
+ StringCopy(str, gLinkPlayers[contestant].name);
+ Text_InitWindow8004D04(
+ &gWindowTemplate_Contest_MoveDescription,
+ gDisplayedStringBattle,
+ 592 + gContestantTurnOrder[contestant] * 22,
+ 251 + gUnknown_083CA310[gContestantTurnOrder[contestant]][0] * 8,
+ gUnknown_083CA310[gContestantTurnOrder[contestant]][1] * 8,
+ 1);
+ }
+ else
+ {
+ StringCopy(str, gContestMons[contestant].trainerName);
+ Text_InitWindowAndPrintText(
+ &gWindowTemplate_Contest_MoveDescription,
+ gDisplayedStringBattle,
+ 592 + gContestantTurnOrder[contestant] * 22,
+ gUnknown_083CA310[gContestantTurnOrder[contestant]][0],
+ gUnknown_083CA310[gContestantTurnOrder[contestant]][1]);
+ }
+}
+
+void PrintContestantMonName(u8 contestant)
+{
+ PrintContestantMonNameWithColor(contestant, contestant + 10);
+}
+
+void PrintContestantMonNameWithColor(u8 contestant, u8 color)
+{
+ u8 *str = gDisplayedStringBattle;
+
+ str[0] = EXT_CTRL_CODE_BEGIN;
+ str[1] = EXT_CTRL_CODE_SIZE;
+ str[2] = 4;
+ str += 3;
+
+ str = Contest_CopyStringWithColor(str, gContestMons[contestant].nickname, color);
+ *str = EOS;
+
+ Text_InitWindow8004D04(
+ &gWindowTemplate_Contest_MoveDescription,
+ gDisplayedStringBattle,
+ 512 + gContestantTurnOrder[contestant] * 20,
+ 253 + gUnknown_083CA308[gContestantTurnOrder[contestant]][0] * 8,
+ gUnknown_083CA308[gContestantTurnOrder[contestant]][1] * 8,
+ 1);
+}
+
+u16 CalculateContestantRound1Points(u8 who, u8 contestCategory)
+{
+ u8 statMain;
+ u8 statSub1;
+ u8 statSub2;
+
+ switch (contestCategory)
+ {
+ case CONTEST_CATEGORY_COOL:
+ statMain = gContestMons[who].cool;
+ statSub1 = gContestMons[who].tough;
+ statSub2 = gContestMons[who].beauty;
+ break;
+ case CONTEST_CATEGORY_BEAUTY:
+ statMain = gContestMons[who].beauty;
+ statSub1 = gContestMons[who].cool;
+ statSub2 = gContestMons[who].cute;
+ break;
+ case CONTEST_CATEGORY_CUTE:
+ statMain = gContestMons[who].cute;
+ statSub1 = gContestMons[who].beauty;
+ statSub2 = gContestMons[who].smart;
+ break;
+ case CONTEST_CATEGORY_SMART:
+ statMain = gContestMons[who].smart;
+ statSub1 = gContestMons[who].cute;
+ statSub2 = gContestMons[who].tough;
+ break;
+ case CONTEST_CATEGORY_TOUGH:
+ default:
+ statMain = gContestMons[who].tough;
+ statSub1 = gContestMons[who].smart;
+ statSub2 = gContestMons[who].cool;
+ break;
+ }
+ return statMain + (statSub1 + statSub2 + gContestMons[who].sheen) / 2;
+}
+
+void CalculateRound1Points(u8 contestCategory)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ gContestMonRound1Points[i] = CalculateContestantRound1Points(i, contestCategory);
+}
+
+u8 CreateJudgeSprite(void)
+{
+ u8 spriteId;
+
+ LoadCompressedObjectPic(&sSpriteSheet_Judge);
+ LoadCompressedPalette(gContest2Pal, 0x110, 32);
+ spriteId = CreateSprite(&sSpriteTemplate_Judge, 112, 36, 30);
+ gSprites[spriteId].oam.paletteNum = 1;
+ gSprites[spriteId].callback = SpriteCallbackDummy;
+ return spriteId;
+}
+
+u8 CreateJudgeSpeechBubbleSprite(void)
+{
+ u8 spriteId;
+
+ LoadCompressedObjectPic(&sSpriteSheet_JudgeSymbols);
+ LoadCompressedObjectPalette(&sSpritePalette_JudgeSymbols);
+ spriteId = CreateSprite(&sSpriteTemplate_JudgeSpeechBubble, 96, 10, 29);
+ gSprites[spriteId].invisible = TRUE;
+ gSprites[spriteId].data[0] = gSprites[spriteId].oam.tileNum;
+ return spriteId;
+}
+
+UNUSED
+u8 unref_sub_80AE908(void)
+{
+ u16 species = gContestMons[gContestPlayerMonIndex].species;
+ u8 spriteId;
+
+ DecompressPicFromTable_2(
+ &gMonFrontPicTable[species],
+ gMonFrontPicCoords[species].coords,
+ gMonFrontPicCoords[species].y_offset,
+ (void *)EWRAM,
+ gMonSpriteGfx_Sprite_ptr[1],
+ species);
+ LoadCompressedPalette(gMonPaletteTable[species].data, 0x110, 32);
+ GetMonSpriteTemplate_803C56C(gContestMons[gContestPlayerMonIndex].species, 1);
+ spriteId = CreateSprite(
+ &gCreatingSpriteTemplate,
+ 112, 80 + (8 - gMonFrontPicCoords[gContestMons[gContestPlayerMonIndex].species].coords) * 4,
+ 30);
+ gSprites[spriteId].oam.paletteNum = 1;
+ gSprites[spriteId].callback = SpriteCallbackDummy;
+ gSprites[spriteId].affineAnims = gAffineAnims_BattleSpriteContest;
+ StartSpriteAffineAnim(&gSprites[spriteId], 0);
+ return spriteId;
+}
+
+u8 CreateContestantSprite(u16 species, u32 otId, u32 personality)
+{
+ const u8 *lzPaletteData;
+ u8 spriteId;
+
+ species = SanitizeSpecies(species);
+ HandleLoadSpecialPokePic(
+ &gMonBackPicTable[species],
+ gMonBackPicCoords[species].coords,
+ gMonBackPicCoords[species].y_offset,
+ (void *)EWRAM,
+ gMonSpriteGfx_Sprite_ptr[0],
+ species,
+ personality);
+ lzPaletteData = GetMonSpritePalFromOtIdPersonality(species, otId, personality);
+ LoadCompressedPalette(lzPaletteData, 0x120, 32);
+ GetMonSpriteTemplate_803C56C(species, 0);
+ spriteId = CreateSprite(&gCreatingSpriteTemplate, 112, GetBattlerSpriteFinal_Y(2, species, 0), 30);
+ gSprites[spriteId].oam.paletteNum = 2;
+ gSprites[spriteId].oam.priority = 2;
+ gSprites[spriteId].subpriority = GetBattlerSubpriority(2);
+ gSprites[spriteId].callback = SpriteCallbackDummy;
+ gSprites[spriteId].data[0] = gSprites[spriteId].oam.paletteNum;
+ gSprites[spriteId].data[2] = species;
+ if (IsSpeciesNotUnown(species))
+ gSprites[spriteId].affineAnims = gAffineAnims_BattleSpriteContest;
+ else
+ gSprites[spriteId].affineAnims = gAffineAnims_BattleSpriteOpponentSide;
+ StartSpriteAffineAnim(&gSprites[spriteId], 0);
+ return spriteId;
+}
+
+bool8 IsSpeciesNotUnown(u16 species)
+{
+ if (species == SPECIES_UNOWN)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+// The contestant info windows and general-purpose text box are drawn on one half, while
+// the moves and move description windows are drawn on another screen. Only the first 32 * 20
+// tiles are actually drawn on screen.
+void SwapMoveDescAndContestTilemaps(void)
+{
+ __copy_tilemap((void *)(VRAM + 0xC000));
+ __copy_tilemap((void *)(VRAM + 0xE000));
+}
+
+void __copy_tilemap(void *a)
+{
+ DmaCopy16Defvars(3, a, (u8 *)a + 0x500, 0x280);
+}
+
+u16 GetMoveEffectSymbolTileOffset(u16 move, u8 b)
+{
+ u16 var;
+
+ switch (gContestEffects[gContestMoves[move].effect].effectType)
+ {
+ case 0:
+ case 1:
+ case 8:
+ var = 0x9082;
+ break;
+ case 2:
+ case 3:
+ var = 0x9088;
+ break;
+ default:
+ var = 0x9086;
+ break;
+ }
+ var += 0x9000 + (b << 12);
+ return var;
+}
+
+void PrintContestMoveDescription(u16 a)
+{
+ u8 category;
+ u16 categoryTile;
+ s32 i;
+ u8 numHearts;
+
+ Text_FillWindowRectDefPalette(&gWindowTemplate_Contest_MoveDescription, 0, 11, 31, 16, 34);
+
+ category = gContestMoves[a].contestCategory;
+ if (category == CONTEST_CATEGORY_COOL)
+ categoryTile = 0x4040;
+ else if (category == CONTEST_CATEGORY_BEAUTY)
+ categoryTile = 0x4045;
+ else if (category == CONTEST_CATEGORY_CUTE)
+ categoryTile = 0x404A;
+ else if (category == CONTEST_CATEGORY_SMART)
+ categoryTile = 0x406A;
+ else
+ categoryTile = 0x408A;
+
+ for (i = 0; i < 5; i++)
+ {
+ *(u16 *)(VRAM + 0xC7D6 + i * 2) = categoryTile;
+ *(u16 *)(VRAM + 0xC816 + i * 2) = categoryTile + 16;
+ categoryTile++;
+ }
+
+ if (gContestEffects[gContestMoves[a].effect].appeal == 0xFF)
+ numHearts = 0;
+ else
+ numHearts = gContestEffects[gContestMoves[a].effect].appeal / 10;
+ if (numHearts > 8)
+ numHearts = 8;
+ for (i = 0; i < 8; i++)
+ {
+ if (i < numHearts) // Empty hearts
+ *(u16 *)(VRAM + 0xC7EA + i * 2) = 0x5012;
+ else // Filled-in hearts
+ *(u16 *)(VRAM + 0xC7EA + i * 2) = 0x5035;
+ }
+
+ if (gContestEffects[gContestMoves[a].effect].jam == 0xFF)
+ numHearts = 0;
+ else
+ numHearts = gContestEffects[gContestMoves[a].effect].jam / 10;
+ if (numHearts > 8)
+ numHearts = 8;
+ for (i = 0; i < 8; i++)
+ {
+ if (i < numHearts) // Empty hearts
+ *(u16 *)(VRAM + 0xC82A + i * 2) = 0x5014;
+ else // Filled-in hearts
+ *(u16 *)(VRAM + 0xC82A + i * 2) = 0x5036;
+ }
+
+ Text_InitWindowAndPrintText(&gWindowTemplate_Contest_MoveDescription, gContestEffectStrings[gContestMoves[a].effect], 868, 11, 35);
+ Text_InitWindowAndPrintText(&gWindowTemplate_Contest_MoveDescription, gText_Slash, 866, 16, 31);
+}
+
+void Contest_ClearMoveDescriptionBox(void)
+{
+ Text_FillWindowRectDefPalette(&gWindowTemplate_Contest_MoveDescription, 0, 11, 35, 28, 40);
+}
+
+UNUSED
+void DrawMoveEffectSymbol(u16 move, u8 b)
+{
+ u8 r5 = gContestantTurnOrder[b] * 5 + 2;
+
+ if (!Contest_IsMonsTurnDisabled(b) && move != MOVE_NONE)
+ {
+ u16 tile = GetMoveEffectSymbolTileOffset(move, b);
+
+ *(u16 *)(VRAM + 0xC028 + r5 * 64) = tile;
+ *(u16 *)(VRAM + 0xC028 + r5 * 64 + 2) = tile + 1;
+
+ *(u16 *)(VRAM + 0xC068 + r5 * 64) = tile + 16;
+ *(u16 *)(VRAM + 0xC068 + r5 * 64 + 2) = tile + 17;
+
+ }
+ else
+ {
+ *(u16 *)(VRAM + 0xC028 + r5 * 64) = 0;
+ *(u16 *)(VRAM + 0xC028 + r5 * 64 + 2) = 0;
+
+ *(u16 *)(VRAM + 0xC068 + r5 * 64) = 0;
+ *(u16 *)(VRAM + 0xC068 + r5 * 64 + 2) = 0;
+ }
+}
+
+UNUSED
+void DrawMoveEffectSymbols(void)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ DrawMoveEffectSymbol(sContestantStatus[i].currMove, i);
+}
+
+u16 GetStarTileOffset(u8 unused)
+{
+ return 0x2034;
+}
+
+bool8 UpdateConditionStars(u8 a, u8 b)
+{
+ u8 r9;
+ u16 r8;
+ s32 r4;
+
+ if (sContestantStatus[a].conditionMod == 0)
+ return FALSE;
+ r9 = gContestantTurnOrder[a] * 5 + 2;
+ if (sContestantStatus[a].conditionMod == 1)
+ {
+ r8 = GetStarTileOffset(a);
+ r4 = 0;
+ while (sContestantStatus[a].condition / 10 > r4)
+ {
+ *(u16 *)(VRAM + 0xC026 + (r9 + r4) * 64) = r8;
+ r4++;
+ }
+ if (b != 0)
+ {
+ PlaySE(SE_EXP_MAX);
+ sContestantStatus[a].conditionMod = 0;
+ }
+ }
+ else // CONDITION_LOSE
+ {
+ r8 = 0;
+ r4 = 3;
+ while (sContestantStatus[a].condition / 10 < r4)
+ {
+ *(u16 *)(VRAM + 0xBFE6 + (r9 + r4) * 64) = r8;
+ r4--;
+ }
+ if (b != 0)
+ {
+ PlaySE(SE_CONTEST_CONDITION_LOSE);
+ sContestantStatus[a].conditionMod = 0;
+ }
+ }
+ return TRUE;
+}
+
+void DrawConditionStars(void)
+{
+ s32 i;
+ s32 r4;
+
+ for (i = 0; i < 4; i++)
+ {
+ u8 r8 = gContestantTurnOrder[i] * 5 + 2;
+ u16 r6 = GetStarTileOffset(i);
+
+ r4 = 0;
+ while (r4 < sContestantStatus[i].condition / 10)
+ {
+ *(u16 *)(VRAM + 0xC026 + (r8 + r4) * 64) = r6;
+ r4++;
+ }
+ r6 = 0;
+ while (r4 < 3)
+ {
+ *(u16 *)(VRAM + 0xC026 + (r8 + r4) * 64) = r6;
+ r4++;
+ }
+ }
+}
+
+u16 GetStatusSymbolTileOffset(u8 unused, u8 b)
+{
+ u16 var = 0;
+
+ switch (b)
+ {
+ case 0: // For resistant
+ var = 0x80;
+ break;
+ case 1: // For nervous
+ var = 0x84;
+ break;
+ case 2: // For turn skipped
+ var = 0x86;
+ break;
+ case 3: // For jammed/unnerved
+ var = 0x88;
+ break;
+ case 4: // Never used
+ var = 0x82;
+ break;
+ }
+ var += 0x9000;
+ return var;
+}
+
+bool8 DrawStatusSymbol(u8 a)
+{
+ bool8 r5 = TRUE;
+ u16 r4 = 0;
+ u8 r6 = gContestantTurnOrder[a] * 5 + 2;
+
+ if (sContestantStatus[a].resistant != 0 || sContestantStatus[a].immune != 0 || sContestantStatus[a].jamSafetyCount != 0 || sContestantStatus[a].jamReduction != 0)
+ r4 = GetStatusSymbolTileOffset(a, 0);
+ else if (sContestantStatus[a].nervous)
+ r4 = GetStatusSymbolTileOffset(a, 1);
+ else if (sContestantStatus[a].numTurnsSkipped != 0 || sContestantStatus[a].noMoreTurns)
+ r4 = GetStatusSymbolTileOffset(a, 2);
+ else
+ r5 = FALSE;
+ if (r5)
+ {
+ *(u16 *)(VRAM + 0xC028 + r6 * 64) = r4;
+ *(u16 *)(VRAM + 0xC028 + r6 * 64 + 2) = r4 + 1;
+ *(u16 *)(VRAM + 0xC068 + r6 * 64) = r4 + 16;
+ *(u16 *)(VRAM + 0xC068 + r6 * 64 + 2) = r4 + 17;
+ }
+ else
+ {
+ *(u16 *)(VRAM + 0xC028 + r6 * 64) = 0;
+ *(u16 *)(VRAM + 0xC028 + r6 * 64 + 2) = 0;
+ *(u16 *)(VRAM + 0xC068 + r6 * 64) = 0;
+ *(u16 *)(VRAM + 0xC068 + r6 * 64 + 2) = 0;
+ }
+ return r5;
+}
+
+void DrawStatusSymbols(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ DrawStatusSymbol(i);
+}
+
+void ContestClearGeneralTextWindow(void)
+{
+ Text_FillWindowRectDefPalette(&gWindowTemplate_Contest_MoveDescription, 0, 1, 15, 17, 18);
+}
+
+u16 GetChosenMove(u8 a)
+{
+ if (Contest_IsMonsTurnDisabled(a))
+ return 0;
+ if (a == gContestPlayerMonIndex)
+ {
+ return gContestMons[a].moves[sContest.playerMoveChoice];
+ }
+ else
+ {
+ u8 moveChoice;
+
+ ContestAI_ResetAI(a);
+ moveChoice = ContestAI_GetActionToUse();
+ return gContestMons[a].moves[moveChoice];
+ }
+}
+
+void GetAllChosenMoves(void)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ sContestantStatus[i].currMove = GetChosenMove(i);
+}
+
+UNUSED
+void sub_80AF1E4(u8 a, u8 b)
+{
+ u8 r3;
+
+ if (b == 0)
+ r3 = a + 10;
+ else
+ r3 = 14;
+ if (sContestantStatus[a].currMove == MOVE_NONE)
+ Contest_CopyStringWithColor(gDisplayedStringBattle, gUnknownText_MissedTurn, r3);
+ else
+ Contest_CopyStringWithColor(
+ gDisplayedStringBattle, gMoveNames[sContestantStatus[a].currMove], r3);
+ sub_80AF2A0(a);
+ Text_InitWindowAndPrintText(
+ &gWindowTemplate_Contest_MoveDescription,
+ gDisplayedStringBattle,
+ 696 + a * 20,
+ gUnknown_083CA318[a][0],
+ gUnknown_083CA318[a][1]);
+}
+
+UNUSED
+void unref_sub_80AF280(u8 a)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ sub_80AF1E4(i, a);
+}
+
+UNUSED
+void sub_80AF2A0(u8 a)
+{
+ Text_FillWindowRectDefPalette(
+ &gWindowTemplate_Contest_MoveDescription,
+ 0,
+ gUnknown_083CA318[a][0],
+ gUnknown_083CA318[a][1],
+ gUnknown_083CA318[a][0] + 7,
+ gUnknown_083CA318[a][1] + 1);
+}
+
+UNUSED
+void unref_sub_80AF2E0(void)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ sub_80AF2A0(i);
+}
+
+void RankContestants(void)
+{
+ u8 i;
+ u8 j;
+ s16 arr[4];
+
+ for (i = 0; i < 4; i++)
+ {
+ sContestantStatus[i].pointTotal += sContestantStatus[i].appeal;
+ arr[i] = sContestantStatus[i].pointTotal;
+ }
+
+ // Sort the point totals using bubble-sort.
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 3; j > i; j--)
+ {
+ if (arr[j - 1] < arr[j])
+ {
+ u16 temp = arr[j];
+
+ arr[j] = arr[j - 1];
+ arr[j - 1] = temp;
+ }
+ }
+ }
+
+ // For each contestant, find the best rank with their point total.
+ // Normally, each point total is different, and this will output the
+ // rankings as expected. However, if two pokemon are tied, then they
+ // both get the best rank for that point total.
+ //
+ // For example if the point totals are [100, 80, 80, 50], the ranks will
+ // be [1, 2, 2, 4]. The pokemon with a point total of 80 stop looking
+ // when they see the first 80 in the array, so they both share the '2'
+ // rank.
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ if (sContestantStatus[i].pointTotal == arr[j])
+ {
+ sContestantStatus[i].ranking = j;
+ break;
+ }
+ }
+ }
+ SortContestants(1);
+ ApplyNextTurnOrder();
+}
+
+void SetAttentionLevels(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ u8 attentionLevel;
+
+ if (sContestantStatus[i].currMove == MOVE_NONE)
+ attentionLevel = 5;
+ else if (sContestantStatus[i].appeal <= 0)
+ attentionLevel = 0;
+ else if (sContestantStatus[i].appeal < 30)
+ attentionLevel = 1;
+ else if (sContestantStatus[i].appeal < 60)
+ attentionLevel = 2;
+ else if (sContestantStatus[i].appeal < 80)
+ attentionLevel = 3;
+ else
+ attentionLevel = 4;
+
+ sContestantStatus[i].attentionLevel = attentionLevel;
+ }
+}
+
+bool8 ContestantCanUseTurn(u8 a)
+{
+ if (sContestantStatus[a].numTurnsSkipped != 0 || sContestantStatus[a].noMoreTurns)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+void SetContestantStatusesForNextRound(void)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ // This is bitfield hell...
+ sContestantStatus[i].appeal = 0;
+ sContestantStatus[i].baseAppeal = 0;
+ sContestantStatus[i].jamSafetyCount = 0;
+ if (sContestantStatus[i].numTurnsSkipped > 0)
+ sContestantStatus[i].numTurnsSkipped--;
+ sContestantStatus[i].jam = 0;
+ sContestantStatus[i].resistant = 0;
+ sContestantStatus[i].jamReduction = 0;
+ sContestantStatus[i].immune = 0;
+ sContestantStatus[i].moreEasilyStartled = 0;
+ sContestantStatus[i].usedRepeatableMove = 0;
+ sContestantStatus[i].nervous = 0;
+ sContestantStatus[i].effectStringId = CONTEST_STRING_NONE;
+ sContestantStatus[i].effectStringId2 = CONTEST_STRING_NONE;
+ sContestantStatus[i].conditionMod = 0;
+ sContestantStatus[i].repeatedPrevMove = sContestantStatus[i].repeatedMove;
+ sContestantStatus[i].repeatedMove = FALSE;
+ sContestantStatus[i].turnOrderModAction = 0;
+ sContestantStatus[i].appealTripleCondition = 0;
+ if (sContestantStatus[i].turnSkipped)
+ {
+ sContestantStatus[i].numTurnsSkipped = 1;
+ sContestantStatus[i].turnSkipped = 0;
+ }
+ if (sContestantStatus[i].exploded)
+ {
+ sContestantStatus[i].noMoreTurns = 1;
+ sContestantStatus[i].exploded = 0;
+ }
+ sContestantStatus[i].overrideCategoryExcitementMod = 0;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ sContestantStatus[i].prevMove = sContestantStatus[i].currMove;
+ sContest.moveHistory[sContest.appealNumber][i] = sContestantStatus[i].prevMove;
+ sContest.excitementHistory[sContest.appealNumber][i] = Contest_GetMoveExcitement(sContestantStatus[i].currMove);
+ sContestantStatus[i].currMove = MOVE_NONE;
+ }
+ eContestExcitement.excitementFrozen = 0;
+}
+
+bool8 Contest_IsMonsTurnDisabled(u8 a)
+{
+ if (sContestantStatus[a].numTurnsSkipped != 0 || sContestantStatus[a].noMoreTurns)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+UNUSED
+bool8 unref_sub_80AF5D0(u8 a, u8 b)
+{
+ u8 i;
+
+ if (a != gContestPlayerMonIndex)
+ return TRUE;
+ for (i = 0; i < 4; i++)
+ {
+ if (b == 3)
+ {
+ sContest.unk1920A_0 = 1;
+ return TRUE;
+ }
+ if (b == 4)
+ {
+ sContest.unk1920A_1 = 1;
+ return TRUE;
+ }
+ if (sContest.unk19206[i] == b)
+ return TRUE;
+ if (sContest.unk19206[i] == 0xFF)
+ {
+ sContest.unk19206[i] = b;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void CalculateTotalPointsForContestant(u8 a)
+{
+ gContestMonRound2Points[a] = GetContestantRound2Points(a);
+ gContestMonTotalPoints[a] = gContestMonRound1Points[a] + gContestMonRound2Points[a];
+}
+
+void CalculateFinalScores(void)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ CalculateTotalPointsForContestant(i);
+ DetermineFinalStandings();
+}
+
+s16 GetContestantRound2Points(u8 a)
+{
+ return gContestMonAppealPointTotals[a] * 2;
+}
+
+void DetermineFinalStandings(void)
+{
+ u16 randomOrdering[4] = {0};
+ struct ContestFinalStandings standings[4];
+ s32 i;
+
+ // Seed random order in case of ties
+ for (i = 0; i < 4; i++)
+ {
+ s32 j;
+ randomOrdering[i] = Random();
+ for (j = 0; j < i; j++)
+ {
+ if (randomOrdering[i] == randomOrdering[j])
+ {
+ i--;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ standings[i].totalPoints = gContestMonTotalPoints[i];
+ standings[i].round1Points = gContestMonRound1Points[i];
+ standings[i].random = randomOrdering[i];
+ standings[i].contestant = i;
+ }
+
+ // Rank contestants
+ for (i = 0; i < 3; i++)
+ {
+ s32 j;
+ for (j = 3; j > i; j--)
+ {
+ if (DidContestantPlaceHigher(j - 1, j, standings))
+ {
+ // Swap contestants in array
+ struct ContestFinalStandings temp;
+
+ temp.totalPoints = standings[j - 1].totalPoints;
+ temp.round1Points = standings[j - 1].round1Points;
+ temp.random = standings[j - 1].random;
+ temp.contestant = standings[j - 1].contestant;
+
+ standings[j - 1].totalPoints = standings[j].totalPoints;
+ standings[j - 1].round1Points = standings[j].round1Points;
+ standings[j - 1].random = standings[j].random;
+ standings[j - 1].contestant = standings[j].contestant;
+
+ standings[j].totalPoints = temp.totalPoints;
+ standings[j].round1Points = temp.round1Points;
+ standings[j].random = temp.random;
+ standings[j].contestant = temp.contestant;
+ }
+ }
+ }
+
+ // Assign placements. i is the placing (0 is 1st, 1 is 2nd...)
+ for (i = 0; i < 4; i++)
+ gContestFinalStandings[standings[i].contestant] = i;
+}
+
+bool8 DidContestantPlaceHigher(s32 a, s32 b, struct ContestFinalStandings *c)
+{
+ bool8 retVal;
+
+ if (c[a].totalPoints < c[b].totalPoints)
+ retVal = TRUE;
+ else if (c[a].totalPoints > c[b].totalPoints)
+ retVal = FALSE;
+ else if (c[a].round1Points < c[b].round1Points)
+ retVal = TRUE;
+ else if (c[a].round1Points > c[b].round1Points)
+ retVal = FALSE;
+ else if (c[a].random < c[b].random)
+ retVal = TRUE;
+ else
+ retVal = FALSE;
+ return retVal;
+}
+
+void ContestPrintLinkStandby(void)
+{
+ gBattle_BG0_Y = 0;
+ gBattle_BG2_Y = 0;
+ ContestClearGeneralTextWindow();
+ Text_InitWindowAndPrintText(&gMenuWindow, gUnknownText_LinkStandbyAndWinner, 776, 1, 15);
+}
+
+UNUSED
+u8 unref_sub_80AF89C(s16 appealStart, s16 appealDelta, u8 tileOffs, u8 contestant)
+{
+ u8 taskId;
+ u8 heartsStart;
+ s8 heartsDelta;
+ u16 baseBlock;
+
+ eContestGfxState[contestant].updatingAppealHearts = 1;
+ taskId = CreateTask(Task_unused_80AF94C, 20);
+ heartsStart = GetNumHeartsFromAppealPoints(appealStart);
+ heartsDelta = GetNumHeartsFromAppealPoints(appealStart + appealDelta) - heartsStart;
+ baseBlock = GetAppealHeartTileOffset(contestant);
+ gTasks[taskId].data[0] = heartsStart;
+ gTasks[taskId].data[1] = heartsDelta;
+ gTasks[taskId].data[2] = baseBlock + tileOffs;
+ gTasks[taskId].data[3] = contestant;
+ if (appealDelta < 0)
+ nullsub_19(contestant);
+ return taskId;
+}
+
+UNUSED
+void Task_unused_80AF94C(u8 taskId)
+{
+ u8 contestant = gTasks[taskId].data[3];
+
+ if (gTasks[taskId].data[1] == 0)
+ {
+ nullsub_19(contestant);
+ DestroyTask(taskId);
+ eContestGfxState[contestant].updatingAppealHearts = 0;
+ }
+ else if (++gTasks[taskId].data[10] > 29)
+ {
+ u8 numHearts;
+
+ gTasks[taskId].data[10] = 0;
+ if (gTasks[taskId].data[1] < 0)
+ {
+ numHearts = gTasks[taskId].data[0]--;
+ gTasks[taskId].data[1]++;
+ PlaySE(SE_BOO);
+ }
+ else
+ {
+ numHearts = ++gTasks[taskId].data[0];
+ gTasks[taskId].data[1]--;
+ PlaySE(SE_PIN);
+ }
+ if ((u16)gTasks[taskId].data[2] != 0xFFFF)
+ {
+ RequestSpriteCopy(
+ &gTasks[taskId].data[2],
+ (void *)(VRAM + 0xC000 + (147 + numHearts + contestant * 160) * 2),
+ 2);
+ }
+ else
+ {
+ u8 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (gTasks[taskId].data[i + 4] < 0)
+ {
+ RequestSpriteCopy(
+ &gTasks[taskId].data[i + 7],
+ (void *)(VRAM + 0xC000 + (147 + numHearts + contestant * 160) * 2),
+ 2);
+ gTasks[taskId].data[i + 4]++;
+ break;
+ }
+ }
+ }
+ }
+}
+
+void FillContestantWindowBgs(void)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ DmaClear16(3, (void *)(VRAM + 0xC000 + (86 + i * 160) * 2), 16);
+ DmaClear16(3, (void *)(VRAM + 0xC000 + (118 + i * 160) * 2), 16);
+ }
+}
+
+UNUSED
+void unref_sub_80AFAB8(s16 a, u8 b)
+{
+ u8 r5 = GetNumHeartsFromAppealPoints(a);
+ u16 r2;
+ u8 i;
+ u16 arr[9];
+
+ if (b == 0)
+ r2 = 0x50A2;
+ else if (b == 1)
+ r2 = 0x60A2;
+ else if (b == 2)
+ r2 = 0x70A2;
+ else
+ r2 = 0x80A2;
+
+ for (i = 0; i < 9; i++)
+ {
+ if (i < r5)
+ arr[i] = r2;
+ else
+ arr[i] = 0;
+ }
+
+ DmaCopy16Defvars(3, arr, (void *)(VRAM + 0xC000 + (148 + b * 160) * 2), sizeof(arr));
+}
+
+u16 GetAppealHeartTileOffset(u8 a)
+{
+ u16 var;
+
+ if (a == 0)
+ var = 0x5011;
+ else if (a == 1)
+ var = 0x6011;
+ else if (a == 2)
+ var = 0x7011;
+ else
+ var = 0x8011;
+ return var + 1;
+}
+
+s8 GetNumHeartsFromAppealPoints(s16 a)
+{
+ s8 retVal = a / 10;
+
+ if (retVal > 16)
+ retVal = 16;
+ else if (retVal < -16)
+ retVal = -16;
+ return retVal;
+}
+
+u8 UpdateAppealHearts(s16 startAppeal, s16 appealDelta, u8 contestant)
+{
+ u8 taskId;
+ s8 startHearts;
+ s8 heartsDelta;
+
+ eContestGfxState[contestant].updatingAppealHearts = 1;
+ taskId = CreateTask(Task_UpdateAppealHearts, 20);
+ startHearts = GetNumHeartsFromAppealPoints(startAppeal);
+ heartsDelta = GetNumHeartsFromAppealPoints(startAppeal + appealDelta) - startHearts;
+ GetAppealHeartTileOffset(contestant); // unused return value
+ gTasks[taskId].data[0] = abs(startHearts);
+ gTasks[taskId].data[1] = heartsDelta;
+ if (startHearts > 0 || (startHearts == 0 && heartsDelta > 0))
+ gTasks[taskId].data[2] = 1;
+ else
+ gTasks[taskId].data[2] = -1;
+ gTasks[taskId].data[3] = contestant;
+ if (appealDelta < 0)
+ nullsub_19(contestant);
+ return taskId;
+}
+
+void Task_UpdateAppealHearts(u8 taskId)
+{
+ u8 contestant = gTasks[taskId].data[3];
+ s16 startHearts = gTasks[taskId].data[0];
+ s16 heartsDelta = gTasks[taskId].data[1];
+
+ if (++gTasks[taskId].data[10] > 14)
+ {
+ u16 heartOffset;
+ u8 newNumHearts;
+ u8 pitchMod;
+
+ gTasks[taskId].data[10] = 0;
+ if (gTasks[taskId].data[1] == 0)
+ {
+ nullsub_19(contestant);
+ DestroyTask(taskId);
+ eContestGfxState[contestant].updatingAppealHearts = 0;
+ return;
+ }
+ else if (startHearts == 0)
+ {
+ if (heartsDelta < 0)
+ {
+ heartOffset = GetAppealHeartTileOffset(contestant) + 2;
+ gTasks[taskId].data[1]++;
+ }
+ else
+ {
+ heartOffset = GetAppealHeartTileOffset(contestant);
+ gTasks[taskId].data[1]--;
+ }
+ newNumHearts = gTasks[taskId].data[0]++;
+ }
+ else
+ {
+ if (gTasks[taskId].data[2] < 0)
+ {
+ if (heartsDelta < 0)
+ {
+ newNumHearts = gTasks[taskId].data[0]++;
+ gTasks[taskId].data[1]++;
+ heartOffset = GetAppealHeartTileOffset(contestant) + 2;
+ }
+ else
+ {
+ newNumHearts = --gTasks[taskId].data[0];
+ heartOffset = 0;
+ gTasks[taskId].data[1]--;
+ }
+ }
+ else
+ {
+ if (heartsDelta < 0)
+ {
+ newNumHearts = --gTasks[taskId].data[0];
+ heartOffset = 0;
+ gTasks[taskId].data[1]++;
+ }
+ else
+ {
+ newNumHearts = gTasks[taskId].data[0]++;
+ gTasks[taskId].data[1]--;
+ heartOffset = GetAppealHeartTileOffset(contestant);
+ }
+ }
+ }
+ pitchMod = newNumHearts;
+ if (newNumHearts >= 8)
+ newNumHearts += 32 - 8; // jump to second line
+ // Seriously, a 2-byte CpuFill? Why?
+ CpuFill16(heartOffset, (void *)(VRAM + 0xC000 + (0x56 + newNumHearts + gContestantTurnOrder[contestant] * 160) * 2), 2);
+ if (heartsDelta > 0) // Appeal
+ {
+ PlaySE(SE_CONTEST_HEART);
+ m4aMPlayImmInit(&gMPlayInfo_SE1);
+ m4aMPlayPitchControl(&gMPlayInfo_SE1, 0xFFFF, pitchMod * 256);
+ }
+ else // Jam
+ {
+ PlaySE(SE_BOO);
+ }
+ if (newNumHearts == 0 && heartOffset == 0)
+ gTasks[taskId].data[2] = -gTasks[taskId].data[2];
+ }
+}
+
+void CreateSliderHeartSprites(void)
+{
+ s32 i;
+
+ LoadSpriteSheet(&sSpriteSheet_SliderHeart);
+ for (i = 0; i < 4; i++)
+ {
+ u8 y = sSliderHeartYPositions[gContestantTurnOrder[i]];
+
+ eContestGfxState[i].sliderHeartSpriteId = CreateSprite(&sSpriteTemplate_SliderHeart, 180, y, 1);
+ }
+}
+
+void sub_80AFE78(u8 a)
+{
+ u8 spriteId;
+ s16 r5;
+
+ eContestGfxState[a].sliderUpdating = 1;
+ spriteId = eContestGfxState[a].sliderHeartSpriteId;
+ r5 = sContestantStatus[a].pointTotal / 10 * 2;
+ if (r5 > 56)
+ r5 = 56;
+ else if (r5 < 0)
+ r5 = 0;
+ gSprites[spriteId].invisible = FALSE;
+ gSprites[spriteId].data[0] = a;
+ gSprites[spriteId].data[1] = r5;
+ if (gSprites[spriteId].data[1] > gSprites[spriteId].pos2.x)
+ gSprites[spriteId].data[2] = 1;
+ else
+ gSprites[spriteId].data[2] = -1;
+ gSprites[spriteId].callback = sub_80AFF60;
+}
+
+void UpdateHeartSliders(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ sub_80AFE78(i);
+}
+
+bool8 SlidersDoneUpdating(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (eContestGfxState[i].sliderUpdating)
+ break;
+ }
+ if (i == 4)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void sub_80AFF60(struct Sprite *sprite)
+{
+ if (sprite->pos2.x == sprite->data[1])
+ {
+ eContestGfxState[sprite->data[0]].sliderUpdating = 0;
+ sprite->callback = SpriteCallbackDummy;
+ }
+ else
+ {
+ sprite->pos2.x += sprite->data[2];
+ }
+}
+
+void UpdateSliderHeartSpriteYPositions(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ gSprites[eContestGfxState[i].sliderHeartSpriteId].pos1.y = sSliderHeartYPositions[gContestantTurnOrder[i]];
+}
+
+void SetBottomSliderHeartsInvisibility(bool8 a)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gContestantTurnOrder[i] > 1)
+ {
+ if (!a)
+ gSprites[eContestGfxState[i].sliderHeartSpriteId].pos1.x = 180;
+ else
+ gSprites[eContestGfxState[i].sliderHeartSpriteId].pos1.x = 256;
+ }
+ }
+}
+
+void CreateNextTurnSprites(void)
+{
+ s32 i;
+
+ LoadSpritePalette(&gUnknown_083CA3E4);
+ for (i = 0; i < 4; i++)
+ {
+ LoadCompressedObjectPic(&gUnknown_083CA3C4[i]);
+ eContestGfxState[i].nextTurnSpriteId = CreateSprite(
+ &gSpriteTemplate_83CA3F4[i],
+ 204, gUnknown_083CA33C[gContestantTurnOrder[i]],
+ 0);
+ SetSubspriteTables(&gSprites[eContestGfxState[i].nextTurnSpriteId], gSubspriteTables_83CA464);
+ gSprites[eContestGfxState[i].nextTurnSpriteId].invisible = TRUE;
+ }
+}
+
+void CreateApplauseMeterSprite(void)
+{
+ u8 spriteId;
+
+ LoadCompressedObjectPic(&gUnknown_083CA46C);
+ LoadSpritePalette(&gUnknown_083CA474);
+ spriteId = CreateSprite(&gSpriteTemplate_83CA484, 30, 44, 1);
+ gSprites[spriteId].invisible = TRUE;
+ sContest.applauseMeterSpriteId = spriteId;
+}
+
+void nullsub_18(s8 unused)
+{
+}
+
+void unref_sub_80B011C(void)
+{
+ u8 i;
+
+ LoadCompressedObjectPic(&gUnknown_083CC3AC);
+ for (i = 0; i < 4; i++)
+ LoadCompressedObjectPalette(&gUnknown_083CC3B4[i]);
+ for (i = 0; i < 4; i++)
+ {
+ u8 spriteId = CreateSprite(
+ &gSpriteTemplate_83CC454[i],
+ gUnknown_083CA330[i][0], gUnknown_083CA330[i][1],
+ 5);
+
+ gSprites[spriteId].invisible = TRUE;
+ gSprites[spriteId].data[0] = i;
+ sContest.unk1920D[i] = spriteId;
+ }
+}
+
+void unref_sub_80B01B0(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ gSprites[sContest.unk1920D[i]].callback = sub_80B0238;
+}
+
+bool8 unref_sub_80B01E0(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gSprites[sContest.unk1920D[i]].callback != SpriteCallbackDummy)
+ break;
+ }
+ if (i == 4)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void sub_80B0238(struct Sprite *sprite)
+{
+ sprite->oam.affineMode = 1;
+ InitSpriteAffineAnim(sprite);
+ if (sprite->invisible)
+ {
+ sprite->callback = sub_80B02A8;
+ }
+ else
+ {
+ StartSpriteAffineAnim(sprite, 1);
+ sprite->callback = sub_80B0280;
+ }
+}
+
+void sub_80B0280(struct Sprite *sprite)
+{
+ if (sprite->affineAnimEnded)
+ {
+ sprite->invisible = TRUE;
+ sprite->callback = sub_80B02A8;
+ }
+}
+
+void sub_80B02A8(struct Sprite *sprite)
+{
+ sprite->invisible = FALSE;
+ StartSpriteAnim(sprite, sContestantStatus[sprite->data[0]].ranking);
+ StartSpriteAffineAnim(sprite, 2);
+ sprite->callback = sub_80B02F4;
+ PlaySE(SE_CONTEST_PLACE);
+}
+
+void sub_80B02F4(struct Sprite *sprite)
+{
+ if (sprite->affineAnimEnded)
+ {
+ FreeSpriteOamMatrix(sprite);
+ sprite->oam.affineMode = 0;
+ sprite->callback = SpriteCallbackDummy;
+ }
+}
+
+void CreateJudgeAttentionEyeTask(void)
+{
+ u8 i;
+ u8 taskId = CreateTask(sub_80B0458, 30);
+
+ sContest.judgeAttentionTaskId = taskId;
+ for (i = 0; i < 4; i++)
+ gTasks[taskId].data[i * 4] = 0xFF;
+}
+
+void sub_80B0368(u8 a)
+{
+ gTasks[sContest.judgeAttentionTaskId].data[a * 4 + 0] = 0;
+ gTasks[sContest.judgeAttentionTaskId].data[a * 4 + 1] = 0;
+}
+
+void sub_80B03A8(u8 a)
+{
+ u8 taskId = CreateTask(sub_80B03D8, 31);
+
+ gTasks[taskId].data[0] = a;
+}
+
+void sub_80B03D8(u8 taskId)
+{
+ u8 r4 = gTasks[taskId].data[0];
+
+ if (gTasks[sContest.judgeAttentionTaskId].data[r4 * 4 + 0] == 0
+ || gTasks[sContest.judgeAttentionTaskId].data[r4 * 4 + 0] == 0xFF)
+ {
+ gTasks[sContest.judgeAttentionTaskId].data[r4 * 4 + 0] = 0xFF;
+ gTasks[sContest.judgeAttentionTaskId].data[r4 * 4 + 1] = 0;
+ BlendPalette((sContest.prevTurnOrder[r4] + 5) * 16 + 6, 2, 0, RGB(31, 31, 18));
+ DestroyTask(taskId);
+ }
+}
+
+void sub_80B0458(u8 taskId)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ u8 r3 = i * 4;
+
+ if (gTasks[taskId].data[r3 + 0] != 0xFF)
+ {
+ if (gTasks[taskId].data[r3 + 1] == 0)
+ gTasks[taskId].data[r3 + 0]++;
+ else
+ gTasks[taskId].data[r3 + 0]--;
+
+ if (gTasks[taskId].data[r3 + 0] == 16
+ || gTasks[taskId].data[r3 + 0] == 0)
+ gTasks[taskId].data[r3 + 1] ^= 1;
+
+ BlendPalette(
+ (sContest.prevTurnOrder[i] + 5) * 16 + 6,
+ 2,
+ gTasks[taskId].data[r3 + 0],
+ RGB(31, 31, 18));
+ }
+ }
+}
+
+void CreateUnusedBlendTask(void)
+{
+ u8 i;
+
+ sContest.blendTaskId = CreateTask(Task_UnusedBlend, 30);
+ for (i = 0; i < 4; i++)
+ InitUnusedBlendTaskData(i);
+}
+
+void InitUnusedBlendTaskData(u8 contestant)
+{
+ gTasks[sContest.blendTaskId].data[contestant * 4 + 0] = 0xFF;
+ gTasks[sContest.blendTaskId].data[contestant * 4 + 1] = 0;
+}
+
+void UpdateBlendTaskContestantsData(void)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ UpdateBlendTaskContestantData(i);
+}
+
+void UpdateBlendTaskContestantData(u8 contestant)
+{
+ InitUnusedBlendTaskData(contestant);
+
+ // 2-byte DMA copy? Why?
+
+ DmaCopy16Defvars(
+ 3,
+ &gPlttBufferUnfaded[16 * (5 + contestant) + 10],
+ &gPlttBufferFaded[16 * (5 + contestant) + 10],
+ 2);
+
+ DmaCopy16Defvars(
+ 3,
+ &gPlttBufferUnfaded[16 * (5 + contestant) + 12 + contestant],
+ &gPlttBufferFaded[16 * (5 + contestant) + 12 + contestant],
+ 2);
+}
+
+void nullsub_19(int unused)
+{
+}
+
+void Task_UnusedBlend(u8 taskId)
+{
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ u8 r3 = i * 4;
+
+ if (gTasks[taskId].data[r3 + 0] != 0xFF)
+ {
+ if (++gTasks[taskId].data[r3 + 2] > 2)
+ {
+ gTasks[taskId].data[r3 + 2] = 0;
+
+ if (gTasks[taskId].data[r3 + 1] == 0)
+ gTasks[taskId].data[r3 + 0]++;
+ else
+ gTasks[taskId].data[r3 + 0]--;
+
+ if (gTasks[taskId].data[r3 + 0] == 16
+ || gTasks[taskId].data[r3 + 0] == 0)
+ gTasks[taskId].data[r3 + 1] ^= 1;
+
+ BlendPalette((i + 5) * 16 + 10, 1, gTasks[taskId].data[r3 + 0], RGB(31, 31, 18));
+ BlendPalette((i + 5) * 16 + 12 + i, 1, gTasks[taskId].data[r3 + 0], RGB(31, 31, 18));
+ }
+ }
+ }
+}
+
+// This task is never used
+u8 CreateUnusedBrokenBlendTask(u8 *a)
+{
+ u8 i;
+ u8 taskId = CreateTask(Task_UnusedBrokenBlend, 10);
+
+ for (i = 0; i < 4; i++)
+ {
+ u8 r0 = i * 4;
+
+ gTasks[taskId].data[r0] = a[i];
+ if (a[i] != 0)
+ eContestGfxState[i].boxBlinking = TRUE;
+ }
+ return taskId;
+}
+
+#ifdef NONMATCHING
+void Task_UnusedBrokenBlend(u8 taskId)
+{
+ u8 i;
+ u8 r4;
+ u8 r4_2;
+ u8 r1;
+ u8 r7;
+
+ for (i = 0; i < 4; i++)
+ {
+ //#define r4 r4_2
+ r4 = gContestantTurnOrder[i];
+ r1 = r4 * 4;
+ r7 = gTasks[taskId].data[r1 + 0];
+
+ if (r7 != 0)
+ {
+ //_080B079C
+ u8 r8 = gTasks[taskId].data[r1 + 1];
+ u8 r5 = gTasks[taskId].data[r1 + 2];
+ u8 r6 = gTasks[taskId].data[r1 + 3];
+
+ if (r7 == 1)
+ {
+ r6++;
+ if (r6 == 1)
+ {
+ //_080B07D2
+ r6 = 0;
+ BlendPalette((r4 + 5) * 16 + 1, 3, r5, RGB(31, 31, 31));
+ if (r5 == 0 && r8 == 4)
+ {
+ gTasks[taskId].data[r1 + 0] = 0;
+ //asm("");
+ }
+ //_080B0800
+ else
+ {
+ r5 += 2;
+ if (r5 > 13)
+ {
+ r5 = 0;
+ r8++;
+ }
+ }
+ }
+ //to _080B08EA
+ }
+ //_080B0818
+ else if (r7 == 2 || r7 == 4)
+ {
+ r6++;
+ if (r6 == 3)
+ {
+ r6 = 0;
+ BlendPalette((r4 + 5) * 16 + 1, 3, r5, gUnknown_083CC5A4[r4]);
+ if (r5 == 0 && r8 == 2)
+ {
+ gTasks[taskId].data[r1 + 0] = 0;
+ }
+ //_080B0858
+ else
+ {
+ r5 += 1;
+ if (r5 == 14)
+ {
+ r5 = 0;
+ r8++;
+ if (r7 == 4 && r8 == 1)
+ {
+ BlendPalette((r4 + 9) * 16 + 2, 1, 4, RGB(0, 0, 0));
+ BlendPalette((r4 + 9) * 16 + 5, 1, 4, RGB(0, 0, 0));
+ }
+ }
+ }
+ }
+ //to _080B08EA
+ }
+ //_080B0896
+ else if (r7 == 3)
+ {
+ r6++;
+ if (r6 == 12)
+ {
+ r6 = 0;
+ BlendPalette((r4 + 5) * 16 + 1, 3, r5, RGB(0, 0, 0));
+ r5 += 1;
+ if (r5 == 5)
+ {
+ // What the hell? These aren't pointers.
+ // This code would crash if run.
+ DmaCopy16Defvars(3, (void *)(u32)gPlttBufferFaded[(r4 + 5) * 16 + 1],
+ (void *)(u32)gPlttBufferUnfaded[(r4 + 5) * 16 + 1], 6);
+ gTasks[taskId].data[r1 + 0] = 0;
+ }
+ }
+ }
+ //_080B08EA
+ gTasks[taskId].data[r1 + 1] = r8;
+ gTasks[taskId].data[r1 + 2] = r5;
+ gTasks[taskId].data[r1 + 3] = r6;
+ }
+ //_080B0910
+ }
+ //_080B0920
+
+ #define i r4_2
+ for (i = 0; i < 4; i++) // r4 is i
+ {
+ if (gTasks[taskId].data[i * 4 + 0] != 0)
+ break;
+ }
+ //_080B0958
+ if (i == 4)
+ {
+ for (i = 0; i < 4; i++)
+ eContestGfxState[i].boxBlinking = FALSE;
+ DestroyTask(taskId);
+ }
+ #undef i
+}
+#else
+NAKED
+void Task_UnusedBrokenBlend(u8 taskId)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ sub sp, 0x20\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ str r0, [sp]\n\
+ movs r0, 0\n\
+ str r0, [sp, 0x4]\n\
+ ldr r2, _080B07F4 @ =gTasks\n\
+ movs r1, 0x8\n\
+ adds r1, r2\n\
+ mov r10, r1\n\
+ ldr r3, [sp]\n\
+ lsls r3, 2\n\
+ str r3, [sp, 0x1C]\n\
+ ldr r1, [sp]\n\
+ adds r0, r3, r1\n\
+ lsls r0, 3\n\
+ str r0, [sp, 0xC]\n\
+_080B0774:\n\
+ ldr r0, _080B07F8 @ =gContestantTurnOrder\n\
+ ldr r3, [sp, 0x4]\n\
+ adds r0, r3, r0\n\
+ ldrb r4, [r0]\n\
+ lsls r0, r4, 26\n\
+ lsrs r1, r0, 24\n\
+ lsls r0, r1, 1\n\
+ str r0, [sp, 0x8]\n\
+ ldr r3, [sp]\n\
+ lsls r0, r3, 2\n\
+ adds r0, r3\n\
+ lsls r6, r0, 3\n\
+ ldr r3, [sp, 0x8]\n\
+ adds r0, r3, r6\n\
+ add r0, r10\n\
+ mov r9, r0\n\
+ ldrb r7, [r0]\n\
+ cmp r7, 0\n\
+ bne _080B079C\n\
+ b _080B0910\n\
+_080B079C:\n\
+ adds r3, r1, 0x1\n\
+ lsls r0, r3, 1\n\
+ adds r0, r6\n\
+ add r0, r10\n\
+ ldrb r0, [r0]\n\
+ mov r8, r0\n\
+ adds r2, r1, 0x2\n\
+ lsls r0, r2, 1\n\
+ adds r0, r6\n\
+ add r0, r10\n\
+ ldrb r5, [r0]\n\
+ adds r1, 0x3\n\
+ lsls r0, r1, 1\n\
+ adds r0, r6\n\
+ add r0, r10\n\
+ ldrb r6, [r0]\n\
+ str r3, [sp, 0x10]\n\
+ str r2, [sp, 0x14]\n\
+ str r1, [sp, 0x18]\n\
+ cmp r7, 0x1\n\
+ bne _080B0818\n\
+ adds r0, r6, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r6, r0, 24\n\
+ cmp r6, 0x1\n\
+ beq _080B07D2\n\
+ b _080B08EA\n\
+_080B07D2:\n\
+ movs r6, 0\n\
+ adds r0, r4, 0x5\n\
+ lsls r0, 4\n\
+ adds r0, 0x1\n\
+ movs r1, 0x3\n\
+ adds r2, r5, 0\n\
+ ldr r3, _080B07FC @ =0x00007fff\n\
+ bl BlendPalette\n\
+ cmp r5, 0\n\
+ bne _080B0800\n\
+ mov r0, r8\n\
+ cmp r0, 0x4\n\
+ bne _080B0800\n\
+ mov r1, r9\n\
+ strh r6, [r1]\n\
+ b _080B08EA\n\
+ .align 2, 0\n\
+_080B07F4: .4byte gTasks\n\
+_080B07F8: .4byte gContestantTurnOrder\n\
+_080B07FC: .4byte 0x00007fff\n\
+_080B0800:\n\
+ adds r0, r5, 0x2\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ cmp r5, 0xD\n\
+ bls _080B08EA\n\
+ movs r5, 0\n\
+ mov r0, r8\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r8, r0\n\
+ b _080B08EA\n\
+_080B0818:\n\
+ cmp r7, 0x2\n\
+ beq _080B0820\n\
+ cmp r7, 0x4\n\
+ bne _080B0896\n\
+_080B0820:\n\
+ adds r0, r6, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r6, r0, 24\n\
+ cmp r6, 0x3\n\
+ bne _080B08EA\n\
+ movs r6, 0\n\
+ adds r0, r4, 0x5\n\
+ lsls r0, 4\n\
+ adds r0, 0x1\n\
+ ldr r2, _080B0854 @ =gUnknown_083CC5A4\n\
+ lsls r1, r4, 1\n\
+ adds r1, r2\n\
+ ldrh r3, [r1]\n\
+ movs r1, 0x3\n\
+ adds r2, r5, 0\n\
+ bl BlendPalette\n\
+ cmp r5, 0\n\
+ bne _080B0858\n\
+ mov r2, r8\n\
+ cmp r2, 0x2\n\
+ bne _080B0858\n\
+ mov r3, r9\n\
+ strh r6, [r3]\n\
+ b _080B08EA\n\
+ .align 2, 0\n\
+_080B0854: .4byte gUnknown_083CC5A4\n\
+_080B0858:\n\
+ adds r0, r5, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ cmp r5, 0xE\n\
+ bne _080B08EA\n\
+ movs r5, 0\n\
+ mov r0, r8\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r8, r0\n\
+ cmp r7, 0x4\n\
+ bne _080B08EA\n\
+ cmp r0, 0x1\n\
+ bne _080B08EA\n\
+ adds r4, 0x9\n\
+ lsls r4, 4\n\
+ adds r0, r4, 0x2\n\
+ movs r1, 0x1\n\
+ movs r2, 0x4\n\
+ movs r3, 0\n\
+ bl BlendPalette\n\
+ adds r4, 0x5\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x1\n\
+ movs r2, 0x4\n\
+ movs r3, 0\n\
+ bl BlendPalette\n\
+ b _080B08EA\n\
+_080B0896:\n\
+ cmp r7, 0x3\n\
+ bne _080B08EA\n\
+ adds r0, r6, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r6, r0, 24\n\
+ cmp r6, 0xC\n\
+ bne _080B08EA\n\
+ movs r6, 0\n\
+ adds r0, r4, 0x5\n\
+ lsls r0, 4\n\
+ adds r4, r0, 0x1\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x3\n\
+ adds r2, r5, 0\n\
+ movs r3, 0\n\
+ bl BlendPalette\n\
+ adds r0, r5, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ cmp r5, 0x5\n\
+ bne _080B08EA\n\
+ ldr r0, _080B0930 @ =gPlttBufferFaded\n\
+ lsls r1, r4, 1\n\
+ adds r0, r1, r0\n\
+ ldrh r2, [r0]\n\
+ ldr r0, _080B0934 @ =gPlttBufferUnfaded\n\
+ adds r1, r0\n\
+ ldrh r0, [r1]\n\
+ ldr r1, _080B0938 @ =0x040000d4\n\
+ str r2, [r1]\n\
+ str r0, [r1, 0x4]\n\
+ movs r0, 0x80\n\
+ lsls r0, 24\n\
+ orrs r7, r0\n\
+ str r7, [r1, 0x8]\n\
+ ldr r0, [r1, 0x8]\n\
+ ldr r1, [sp, 0x8]\n\
+ ldr r2, [sp, 0xC]\n\
+ adds r0, r1, r2\n\
+ add r0, r10\n\
+ strh r6, [r0]\n\
+_080B08EA:\n\
+ ldr r3, [sp, 0x10]\n\
+ lsls r0, r3, 1\n\
+ ldr r1, [sp, 0xC]\n\
+ adds r0, r1\n\
+ add r0, r10\n\
+ mov r2, r8\n\
+ strh r2, [r0]\n\
+ ldr r3, [sp, 0x14]\n\
+ lsls r0, r3, 1\n\
+ adds r0, r1\n\
+ add r0, r10\n\
+ strh r5, [r0]\n\
+ ldr r1, [sp, 0x18]\n\
+ lsls r0, r1, 1\n\
+ ldr r2, [sp, 0xC]\n\
+ adds r0, r2\n\
+ add r0, r10\n\
+ strh r6, [r0]\n\
+ ldr r2, _080B093C @ =gTasks\n\
+_080B0910:\n\
+ ldr r0, [sp, 0x4]\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ str r0, [sp, 0x4]\n\
+ cmp r0, 0x3\n\
+ bhi _080B0920\n\
+ b _080B0774\n\
+_080B0920:\n\
+ movs r4, 0\n\
+ ldr r3, [sp, 0x1C]\n\
+ ldr r1, [sp]\n\
+ adds r0, r3, r1\n\
+ lsls r1, r0, 3\n\
+ adds r2, 0x8\n\
+ adds r0, r1, r2\n\
+ b _080B0950\n\
+ .align 2, 0\n\
+_080B0930: .4byte gPlttBufferFaded\n\
+_080B0934: .4byte gPlttBufferUnfaded\n\
+_080B0938: .4byte 0x040000d4\n\
+_080B093C: .4byte gTasks\n\
+_080B0940:\n\
+ adds r0, r4, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r4, r0, 24\n\
+ cmp r4, 0x3\n\
+ bhi _080B0958\n\
+ lsls r0, r4, 3\n\
+ adds r0, r1\n\
+ adds r0, r2\n\
+_080B0950:\n\
+ movs r3, 0\n\
+ ldrsh r0, [r0, r3]\n\
+ cmp r0, 0\n\
+ beq _080B0940\n\
+_080B0958:\n\
+ cmp r4, 0x4\n\
+ bne _080B0980\n\
+ movs r4, 0\n\
+ ldr r3, _080B0990 @ =gSharedMem + 0x19338\n\
+ movs r5, 0x3\n\
+ negs r5, r5\n\
+_080B0964:\n\
+ lsls r1, r4, 2\n\
+ adds r1, r3\n\
+ ldrb r2, [r1, 0x2]\n\
+ adds r0, r5, 0\n\
+ ands r0, r2\n\
+ strb r0, [r1, 0x2]\n\
+ adds r0, r4, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r4, r0, 24\n\
+ cmp r4, 0x3\n\
+ bls _080B0964\n\
+ ldr r0, [sp]\n\
+ bl DestroyTask\n\
+_080B0980:\n\
+ add sp, 0x20\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+_080B0990: .4byte gSharedMem + 0x19338\n\
+ .syntax divided\n");
+}
+#endif
+
+void unref_sub_80B0994(u8 a)
+{
+ if (a != 0)
+ sContest.unk1920A_2 = 1;
+}
+
+void StartStopFlashJudgeAttentionEye(u8 a)
+{
+ if (sContestantStatus[a].hasJudgesAttention)
+ sub_80B0368(a);
+ else
+ sub_80B03A8(a);
+}
+
+extern const struct CompressedSpriteSheet gUnknown_083CC4B4[];
+extern const struct SpritePalette gUnknown_083CC4D4[];
+extern const struct SpriteTemplate gSpriteTemplate_83CC53C[];
+
+u8 CreateContestantBoxBlinkSprites(u8 a)
+{
+ u8 r5 = gContestantTurnOrder[a] * 40 + 32;
+ u8 r8;
+ u8 r6;
+ volatile u8 zero;
+
+ LoadCompressedObjectPic(&gUnknown_083CC4B4[a]);
+ LoadSpritePalette(&gUnknown_083CC4D4[a]);
+ r8 = CreateSprite(&gSpriteTemplate_83CC53C[a], 184, r5, 29);
+ r6 = CreateSprite(&gSpriteTemplate_83CC53C[a], 248, r5, 29);
+ gSprites[r6].oam.tileNum += 64;
+
+ CopySpriteTiles(0, 3, (void *)VRAM, (u16 *)(VRAM + 0xE000 + gContestantTurnOrder[a] * 5 * 64 + 0x26), (u8 *)(VRAM + 0x10000 + gSprites[r8].oam.tileNum * 32));
+ CopySpriteTiles(0, 3, (void *)VRAM, (u16 *)(VRAM + 0xE000 + gContestantTurnOrder[a] * 5 * 64 + 0x36), (u8 *)(VRAM + 0x10000 + gSprites[r6].oam.tileNum * 32));
+
+ DmaFill32Defvars(3, 0, (void *)(VRAM + 0x10000 + (0x28 + gSprites[r8].oam.tileNum) * 32), 0x300);
+
+ // What is this?
+ zero = 0;
+ zero = 0;
+
+ DmaFill32Defvars(3, 0, (void *)(VRAM + 0x10000 + (0x28 + gSprites[r6].oam.tileNum) * 32), 0x300);
+
+ gSprites[r8].data[0] = r6;
+ gSprites[r6].data[0] = r8;
+ gSprites[r8].data[1] = a;
+ gSprites[r6].data[1] = a;
+ return r8;
+}
+
+void DestroyContestantBoxBlinkSprites(u8 spriteId)
+{
+ u8 spriteId2 = gSprites[spriteId].data[0];
+
+ FreeSpriteOamMatrix(&gSprites[spriteId2]);
+ DestroySprite(&gSprites[spriteId2]);
+ DestroySpriteAndFreeResources(&gSprites[spriteId]);
+}
+
+void SetBlendForContestantBoxBlink(void)
+{
+ REG_BLDCNT = 0x3F40;
+ REG_BLDALPHA = 0x0907;
+}
+
+void ResetBlendForContestantBoxBlink(void)
+{
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+}
+
+void BlinkContestantBox(u8 a, bool8 b)
+{
+ u8 r5;
+
+ SetBlendForContestantBoxBlink();
+ eContestGfxState[gSprites[a].data[1]].boxBlinking = 1;
+ r5 = gSprites[a].data[0];
+ StartSpriteAffineAnim(&gSprites[a], 1);
+ StartSpriteAffineAnim(&gSprites[r5], 1);
+ gSprites[a].callback = SpriteCB_BlinkContestantBox;
+ gSprites[r5].callback = SpriteCallbackDummy;
+ if (b == FALSE)
+ PlaySE(SE_CONTEST_MONS_TURN);
+ else
+ PlaySE(SE_PC_LOGIN);
+}
+
+void SpriteCB_BlinkContestantBox(struct Sprite *sprite)
+{
+ if (sprite->affineAnimEnded)
+ {
+ u8 r1 = sprite->data[0];
+
+ if (gSprites[r1].affineAnimEnded)
+ {
+ sprite->invisible = TRUE;
+ gSprites[r1].invisible = TRUE;
+ sprite->callback = SpriteCB_EndBlinkContestantBox;
+ }
+ }
+}
+
+void SpriteCB_EndBlinkContestantBox(struct Sprite *sprite)
+{
+ eContestGfxState[sprite->data[1]].boxBlinking = 0;
+ DestroyContestantBoxBlinkSprites(sprite->data[0]);
+ ResetBlendForContestantBoxBlink();
+}
+
+void Unused_EndBlinkingState(u8 a, int unused)
+{
+ eContestGfxState[a].boxBlinking = 0;
+}
+
+void ContestDebugTogglePointTotal(void)
+{
+ eEnableContestDebugging ^= 1;
+ if (eEnableContestDebugging == 0)
+ {
+ u8 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ Text_FillWindowRectDefPalette(
+ &gWindowTemplate_Contest_MoveDescription,
+ 0,
+ gUnknown_083CA308[i][0],
+ gUnknown_083CA308[i][1],
+ gUnknown_083CA310[i][0] + 5,
+ gUnknown_083CA310[i][1] + 1);
+ }
+ DrawContestantWindowText();
+ SwapMoveDescAndContestTilemaps();
+ }
+ else
+ {
+ ContestDebugDoPrint();
+ }
+}
+
+void ContestDebugDoPrint(void)
+{
+ u8 r5 = 0;
+ u8 sp8[8];
+
+ if (eEnableContestDebugging != 0)
+ {
+ u8 i;
+ s16 r2;
+
+ for (i = 0; i < 4; i++)
+ {
+ Text_FillWindowRectDefPalette(
+ &gWindowTemplate_Contest_MoveDescription,
+ 0,
+ gUnknown_083CA308[i][0],
+ gUnknown_083CA308[i][1],
+ gUnknown_083CA310[i][0] + 5,
+ gUnknown_083CA310[i][1] + 1);
+ }
+ for (i = 0; i < 4; i++)
+ {
+ r2 = sContestantStatus[i].pointTotal;
+ if (r2 < 0)
+ {
+ r2 = -r2;
+ sp8[0] = CHAR_HYPHEN;
+ r5++;
+ }
+ ConvertIntToDecimalStringN(sp8 + r5, r2, 0, 4);
+ Text_InitWindowAndPrintText(
+ &gWindowTemplate_Contest_MoveDescription,
+ sp8,
+ 592 + gContestantTurnOrder[i] * 22,
+ gUnknown_083CA310[gContestantTurnOrder[i]][0],
+ gUnknown_083CA310[gContestantTurnOrder[i]][1]);
+ r5 = 0;
+ }
+ for (i = 0; i < 4; i++)
+ {
+ r2 = sContestantStatus[i].appeal;
+ if (r2 < 0)
+ {
+ r2 = -r2;
+ sp8[0] = CHAR_HYPHEN;
+ r5++;
+ }
+ ConvertIntToDecimalStringN(sp8 + r5, r2, 0, 4);
+ Text_InitWindowAndPrintText(
+ &gWindowTemplate_Contest_MoveDescription,
+ sp8,
+ 512 + gContestantTurnOrder[i] * 20,
+ gUnknown_083CA308[gContestantTurnOrder[i]][0],
+ gUnknown_083CA308[gContestantTurnOrder[i]][1]);
+ r5 = 0;
+ }
+ SwapMoveDescAndContestTilemaps();
+ }
+}
+
+void unref_sub_80B0EE8(s32 *a, s32 b)
+{
+ s32 i;
+ s32 j;
+
+ for (i = 0; i < b - 1; i++)
+ {
+ for (j = b - 1; j > i; j--)
+ {
+ if (a[j - 1] > a[j])
+ {
+ s32 temp = a[j];
+
+ a[j] = a[j - 1];
+ a[j - 1] = temp;
+ }
+ }
+ }
+}
+
+// something to do with contest NPC opponents, I think.
+void SortContestants(u8 a)
+{
+ u8 sp0[4];
+ u16 sp4[4] = {0};
+ s32 i;
+ s32 r2;
+ s32 r4;
+
+ // Generate a unique random number for each contestant.
+ for (i = 0; i < 4; i++)
+ {
+ sp4[i] = Random();
+
+ // Loop through all the numbers generated so far.
+ for (r2 = 0; r2 < i; r2++)
+ {
+ if (sp4[i] == sp4[r2])
+ {
+ // This number isn't unique; try generating again.
+ i--;
+ break;
+ }
+ }
+ }
+
+ if (a == 0)
+ {
+ // Order based on the results of the Conditions round using Insertion Sort.
+ // Use the randomOrdering to break ties.
+ for (i = 0; i < 4; i++)
+ {
+ // Append this contestant to the list.
+ gContestantTurnOrder[i] = i;
+
+ // Determine where the contestant should be ordered.
+ for (r4 = 0; r4 < i; r4++)
+ {
+ if (gContestMonRound1Points[gContestantTurnOrder[r4]] < gContestMonRound1Points[i]
+ || (gContestMonRound1Points[gContestantTurnOrder[r4]] == gContestMonRound1Points[i] && sp4[gContestantTurnOrder[r4]] < sp4[i]))
+ {
+ // Shift everything larger up to make room.
+ for (r2 = i; r2 > r4; r2--)
+ gContestantTurnOrder[r2] = gContestantTurnOrder[r2 - 1];
+
+ // Insert into the new spot.
+ gContestantTurnOrder[r4] = i;
+ break;
+ }
+ }
+
+ // This is redundant.
+ // Perhaps GF switched from true insertion sort to in-place insertion sort, and forgot to
+ // remove this check?
+ if (r4 == i)
+ gContestantTurnOrder[i] = i;
+ }
+
+ // Invert gContestantTurnOrder; above, it was a list of contestant IDs. Now it's a list of turn orderings.
+ //
+ // For example, if contestant 3 had the first turn, then `gContestantTurnOrder[1] = 3`. The turn is the index,
+ // the contestant is the data. After inverting the list, `gContestantTurnOrder[3] = 1`. The contestant is the index,
+ // and the turn is the data.
+ memcpy(sp0, gContestantTurnOrder, sizeof(sp0));
+ for (i = 0; i < 4; i++)
+ gContestantTurnOrder[sp0[i]] = i;
+ }
+ else
+ {
+ // Order contestants based on their ranking.
+ // If contestants have tied ranking, fill in the next available slot.
+ //
+ // Note that ranking is calculated so that shared places still take up a ranking
+ // space. A ranking like [1, 2, 2, 3] is not possible; it would be [1, 2, 2, 4]
+ // instead.
+ memset(sp0, 0xFF, sizeof(sp0));
+ for (i = 0; i < 4; i++)
+ {
+ u8 r2_2 = sContestantStatus[i].ranking;
+
+ while (1)
+ {
+ u8 *ptr = &sp0[r2_2];
+ if (*ptr == 0xFF)
+ {
+ *ptr = i;
+ gContestantTurnOrder[i] = r2_2;
+ break;
+ }
+ r2_2++;
+ }
+ }
+
+ // Randomize the order of contestants with tied rankings using Selection Sort.
+ //
+ // Look through the array for tied ranks, and use randomOrdering to break the tie.
+ // This ensures that contestants with the same rank will be randomly ordered. This
+ // uses an in-place slection sort, which involves a lot of extra swapping.
+ for (i = 0; i < 3; i++)
+ {
+ for (r4 = 3; r4 > i; r4--)
+ {
+ if (sContestantStatus[r4 - 1].ranking == sContestantStatus[r4].ranking && gContestantTurnOrder[r4 - 1] < gContestantTurnOrder[r4]
+ && sp4[r4 - 1] < sp4[r4])
+ {
+ u8 temp = gContestantTurnOrder[r4];
+
+ gContestantTurnOrder[r4] = gContestantTurnOrder[r4 - 1];
+ gContestantTurnOrder[r4 - 1] = temp;
+ }
+ }
+ }
+ }
+}
+
+void DrawContestantWindows(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ s32 windowId = i + 5;
+ LoadPalette(
+ eContestTempSave.cachedWindowPalettes[windowId], (gContestantTurnOrder[i] + 5) * 16, 32);
+ }
+ DrawContestantWindowText();
+}
+
+void CalculateAppealMoveImpact(u8 contestant)
+{
+ bool8 r8;
+ s32 i;
+
+ sContestantStatus[contestant].appeal = 0;
+ sContestantStatus[contestant].baseAppeal = 0;
+ r8 = ContestantCanUseTurn(contestant);
+ if (r8)
+ {
+ u16 move = sContestantStatus[contestant].currMove;
+ u8 effect = gContestMoves[move].effect;
+ u8 rnd;
+
+ sContestantStatus[contestant].moveCategory = gContestMoves[sContestantStatus[contestant].currMove].contestCategory;
+ if (sContestantStatus[contestant].currMove == sContestantStatus[contestant].prevMove && sContestantStatus[contestant].currMove != MOVE_NONE)
+ {
+ sContestantStatus[contestant].repeatedMove = TRUE;
+ sContestantStatus[contestant].moveRepeatCount++;
+ }
+ else
+ {
+ sContestantStatus[contestant].moveRepeatCount = 0;
+ }
+ sContestantStatus[contestant].baseAppeal = gContestEffects[effect].appeal;
+ sContestantStatus[contestant].appeal = gContestEffects[effect].appeal;
+ eContestAppealResults.jam = gContestEffects[effect].jam;
+ eContestAppealResults.jam2 = gContestEffects[effect].jam;
+ eContestAppealResults.contestant = contestant;
+ for (i = 0; i < 4; i++)
+ {
+ sContestantStatus[i].jam = 0;
+ eContestAppealResults.unnervedPokes[i] = 0;
+ }
+ if (sContestantStatus[contestant].hasJudgesAttention && AreMovesContestCombo(sContestantStatus[contestant].prevMove, sContestantStatus[contestant].currMove) == 0)
+ sContestantStatus[contestant].hasJudgesAttention = 0;
+ gContestEffectFuncs[effect]();
+ if (sContestantStatus[contestant].conditionMod == 1)
+ sContestantStatus[contestant].appeal += sContestantStatus[contestant].condition - 10;
+ else if (sContestantStatus[contestant].appealTripleCondition)
+ sContestantStatus[contestant].appeal += sContestantStatus[contestant].condition * 3;
+ else
+ sContestantStatus[contestant].appeal += sContestantStatus[contestant].condition;
+ sContestantStatus[contestant].completedCombo = 0;
+ sContestantStatus[contestant].usedComboMove = 0;
+ if (IsContestantAllowedToCombo(contestant))
+ {
+ u8 completedCombo = AreMovesContestCombo(sContestantStatus[contestant].prevMove, sContestantStatus[contestant].currMove);
+
+ if (completedCombo != 0 && sContestantStatus[contestant].hasJudgesAttention)
+ {
+ sContestantStatus[contestant].completedCombo = completedCombo;
+ sContestantStatus[contestant].usedComboMove = 1;
+ sContestantStatus[contestant].hasJudgesAttention = 0;
+ sContestantStatus[contestant].comboAppealBonus = sContestantStatus[contestant].baseAppeal * sContestantStatus[contestant].completedCombo;
+ sContestantStatus[contestant].completedComboFlag = 1;
+ }
+ else
+ {
+ if (gContestMoves[sContestantStatus[contestant].currMove].comboStarterId != 0)
+ {
+ sContestantStatus[contestant].hasJudgesAttention = 1;
+ sContestantStatus[contestant].usedComboMove = 1;
+ }
+ else
+ {
+ sContestantStatus[contestant].hasJudgesAttention = 0;
+ }
+ }
+ }
+ if (sContestantStatus[contestant].repeatedMove)
+ sContestantStatus[contestant].repeatJam = (sContestantStatus[contestant].moveRepeatCount + 1) * 10;
+ if (sContestantStatus[contestant].nervous)
+ {
+ sContestantStatus[contestant].hasJudgesAttention = 0;
+ sContestantStatus[contestant].appeal = 0;
+ sContestantStatus[contestant].baseAppeal = 0;
+ }
+ eContestExcitement.moveExcitement = Contest_GetMoveExcitement(sContestantStatus[contestant].currMove);
+ if (sContestantStatus[contestant].overrideCategoryExcitementMod)
+ eContestExcitement.moveExcitement = 1;
+ if (eContestExcitement.moveExcitement > 0)
+ {
+ if (sContest.applauseLevel + eContestExcitement.moveExcitement > 4)
+ eContestExcitement.excitementAppealBonus = 60;
+ else
+ eContestExcitement.excitementAppealBonus = 10;
+ }
+ else
+ {
+ eContestExcitement.excitementAppealBonus = 0;
+ }
+
+ rnd = Random() % 3;
+ for (i = 0; i < 4; i++)
+ {
+ if (i != contestant)
+ {
+ if (rnd == 0)
+ break;
+ rnd--;
+ }
+ }
+ sContestantStatus[contestant].contestantAnimTarget = i;
+ }
+}
+
+void SetContestantEffectStringID(u8 a, u8 b)
+{
+ sContestantStatus[a].effectStringId = b;
+}
+
+void SetContestantEffectStringID2(u8 a, u8 b)
+{
+ sContestantStatus[a].effectStringId2 = b;
+}
+
+void SetStartledString(u8 contestant, u8 jam)
+{
+ if (jam >= 60)
+ SetContestantEffectStringID(contestant, CONTEST_STRING_TRIPPED_OVER);
+ else if (jam >= 40)
+ SetContestantEffectStringID(contestant, CONTEST_STRING_LEAPT_UP);
+ else if (jam >= 30)
+ SetContestantEffectStringID(contestant, CONTEST_STRING_UTTER_CRY);
+ else if (jam >= 20)
+ SetContestantEffectStringID(contestant, CONTEST_STRING_TURNED_BACK);
+ else if (jam >= 10)
+ SetContestantEffectStringID(contestant, CONTEST_STRING_LOOKED_DOWN);
+}
+
+void PrintAppealMoveResultText(u8 contestant, u8 stringId)
+{
+ StringCopy(gStringVar1, gContestMons[contestant].nickname);
+ StringCopy(gStringVar2, gMoveNames[sContestantStatus[contestant].currMove]);
+ if (gContestMoves[sContestantStatus[eContestAppealResults.contestant].currMove].contestCategory == CONTEST_CATEGORY_COOL)
+ StringCopy(gStringVar3, gText_Contest_Shyness);
+ else if (gContestMoves[sContestantStatus[eContestAppealResults.contestant].currMove].contestCategory == CONTEST_CATEGORY_BEAUTY)
+ StringCopy(gStringVar3, gText_Contest_Anxiety);
+ else if (gContestMoves[sContestantStatus[eContestAppealResults.contestant].currMove].contestCategory == CONTEST_CATEGORY_CUTE)
+ StringCopy(gStringVar3, gText_Contest_Laziness);
+ else if (gContestMoves[sContestantStatus[eContestAppealResults.contestant].currMove].contestCategory == CONTEST_CATEGORY_SMART)
+ StringCopy(gStringVar3, gText_Contest_Hesitancy);
+ else
+ StringCopy(gStringVar3, gText_Contest_Fear);
+ StringExpandPlaceholders(gStringVar4, gUnknown_083CC188[stringId]);
+ ContestClearGeneralTextWindow();
+ Contest_StartTextPrinter(&gMenuWindow, gStringVar4, 776, 1, 15);
+}
+
+void MakeContestantNervous(u8 p)
+{
+ sContestantStatus[p].nervous = 1;
+ sContestantStatus[p].currMove = MOVE_NONE;
+}
+
+// This function calculates the new turn order for the next round. The
+// algorithm first checks for explicit turn assignments in the
+// ContestantStatus::nextTurnOrder field of each contestant. The remaining
+// turns are assigned such that the turn order will reverse.
+//
+// For example, if no pokemon have a defined nextTurnOrder, then the 4th
+// will become 1st, the 3rd will become 2nd, etc.
+//
+// Note: This function assumes that multiple pokemon cannot have the same
+// nextTurnOrder value.
+void ApplyNextTurnOrder(void)
+{
+ u8 nextContestant = 0;
+ s32 i;
+ s32 j;
+ u8 newTurnOrder[4];
+ bool8 isContestantOrdered[4];
+
+ for (i = 0; i < 4; i++)
+ {
+ newTurnOrder[i] = gContestantTurnOrder[i];
+ isContestantOrdered[i] = FALSE;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ if (sContestantStatus[j].nextTurnOrder == i)
+ {
+ newTurnOrder[j] = i;
+ isContestantOrdered[j] = TRUE;
+ break;
+ }
+ }
+ if (j == 4)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ if (isContestantOrdered[j] == 0 && sContestantStatus[j].nextTurnOrder == 0xFF)
+ {
+ nextContestant = j;
+ j++;
+ break;
+ }
+ }
+ for (; j < 4; j++)
+ {
+ if (isContestantOrdered[j] == 0 && sContestantStatus[j].nextTurnOrder == 0xFF
+ && gContestantTurnOrder[nextContestant] > gContestantTurnOrder[j])
+ nextContestant = j;
+ }
+ newTurnOrder[nextContestant] = i;
+ isContestantOrdered[nextContestant] = 1;
+ }
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ eContestAppealResults.turnOrder[i] = newTurnOrder[i];
+ sContestantStatus[i].nextTurnOrder = 0xFF;
+ sContestantStatus[i].turnOrderMod = 0;
+ gContestantTurnOrder[i] = newTurnOrder[i];
+ }
+}
+
+void SpriteCB_JudgeSpeechBubble(struct Sprite *sprite)
+{
+ if (sprite->data[1]++ > 84)
+ {
+ sprite->data[1] = 0;
+ sprite->invisible = TRUE;
+ sprite->callback = SpriteCallbackDummy;
+ sContest.waitForJudgeSpeechBubble = 0;
+ }
+}
+
+void DoJudgeSpeechBubble(u8 a)
+{
+ u8 spriteId = sContest.judgeSpeechBubbleSpriteId;
+
+ switch (a)
+ {
+ case 0:
+ case 1:
+ gSprites[spriteId].oam.tileNum = gSprites[spriteId].data[0];
+ PlaySE(SE_FAILURE);
+ break;
+ case 2:
+ gSprites[spriteId].oam.tileNum = gSprites[spriteId].data[0] + 4;
+ PlaySE(SE_SUCCESS);
+ break;
+ case 3:
+ gSprites[spriteId].oam.tileNum = gSprites[spriteId].data[0] + 8;
+ PlaySE(SE_SUCCESS);
+ break;
+ case 4:
+ gSprites[spriteId].oam.tileNum = gSprites[spriteId].data[0] + 12;
+ PlaySE(SE_WARP_IN);
+ break;
+ case 5: // exactly the same as case 4
+ gSprites[spriteId].oam.tileNum = gSprites[spriteId].data[0] + 12;
+ PlaySE(SE_WARP_IN);
+ break;
+ case 6:
+ gSprites[spriteId].oam.tileNum = gSprites[spriteId].data[0] + 16;
+ PlaySE(SE_WARP_IN);
+ break;
+ case 8:
+ gSprites[spriteId].oam.tileNum = gSprites[spriteId].data[0] + 24;
+ PlaySE(SE_M_HEAL_BELL);
+ break;
+ case 7:
+ default:
+ gSprites[spriteId].oam.tileNum = gSprites[spriteId].data[0] + 20;
+ PlaySE(SE_WARP_IN);
+ break;
+ }
+ gSprites[spriteId].data[1] = 0;
+ gSprites[spriteId].invisible = FALSE;
+ gSprites[spriteId].callback = SpriteCB_JudgeSpeechBubble;
+ sContest.waitForJudgeSpeechBubble = 1;
+}
+
+void UpdateApplauseMeter(void)
+{
+ s32 i;
+
+ for (i = 0; i < 5; i++)
+ {
+ const u8 *src;
+
+ if (i < sContest.applauseLevel)
+ src = gContestApplauseMeterGfx + 64;
+ else
+ src = gContestApplauseMeterGfx;
+ CpuCopy32(src, (void *)(VRAM + 0x10000 + (gSprites[sContest.applauseMeterSpriteId].oam.tileNum + 17 + i) * 32), 32);
+ CpuCopy32(src + 32, (void *)(VRAM + 0x10000 + (gSprites[sContest.applauseMeterSpriteId].oam.tileNum + 25 + i) * 32), 32);
+ if (sContest.applauseLevel > 4)
+ StartApplauseOverflowAnimation();
+ }
+}
+
+UNUSED
+void unref_sub_80B19D0(void)
+{
+ u8 str[20];
+ StringCopy(str, gUnknown_083CC2EC);
+ Text_InitWindowAndPrintText(&gWindowTemplate_Contest_MoveDescription, str, 680, 0, 0);
+}
+
+s8 Contest_GetMoveExcitement(u16 move)
+{
+ return gContestExcitementTable[gSpecialVar_ContestCategory][gContestMoves[move].contestCategory];
+}
+
+// Launches crowd movement task, maybe
+u8 StartApplauseOverflowAnimation(void)
+{
+ u8 taskId = CreateTask(Task_ApplauseOverflowAnimation, 10);
+
+ gTasks[taskId].data[1] = 1;
+ gTasks[taskId].data[2] = IndexOfSpritePaletteTag(0x0ABE2);
+ return taskId;
+}
+
+void Task_ApplauseOverflowAnimation(u8 taskId)
+{
+ if (++gTasks[taskId].data[0] == 1)
+ {
+ gTasks[taskId].data[0] = 0;
+ if (gTasks[taskId].data[3] == 0)
+ gTasks[taskId].data[4]++;
+ else
+ gTasks[taskId].data[4]--;
+ BlendPalette(264 + gTasks[taskId].data[2] * 16, 1, gTasks[taskId].data[4], RGB(31, 31, 31));
+ if (gTasks[taskId].data[4] == 0 || gTasks[taskId].data[4] == 16)
+ {
+ gTasks[taskId].data[3] ^= 1;
+ if (sContest.applauseLevel < 5)
+ {
+ BlendPalette(264 + gTasks[taskId].data[2] * 16, 1, 0, RGB(31, 0, 0));
+ DestroyTask(taskId);
+ }
+ }
+ }
+}
+
+void SlideApplauseMeterIn(void)
+{
+ CreateTask(Task_SlideApplauseMeterIn, 10);
+ gSprites[sContest.applauseMeterSpriteId].pos2.x = -70;
+ gSprites[sContest.applauseMeterSpriteId].invisible = FALSE;
+ sContest.applauseMeterIsMoving = 1;
+}
+
+void Task_SlideApplauseMeterIn(u8 taskId)
+{
+ struct Sprite *sprite = &gSprites[sContest.applauseMeterSpriteId];
+
+ gTasks[taskId].data[10] += 1664;
+ sprite->pos2.x += gTasks[taskId].data[10] >> 8;
+ gTasks[taskId].data[10] = gTasks[taskId].data[10] & 0xFF;
+ if (sprite->pos2.x > 0)
+ sprite->pos2.x = 0;
+ if (sprite->pos2.x == 0)
+ {
+ sContest.applauseMeterIsMoving = 0;
+ DestroyTask(taskId);
+ }
+}
+
+void SlideApplauseMeterOut(void)
+{
+ if (gSprites[sContest.applauseMeterSpriteId].invisible == TRUE)
+ {
+ sContest.applauseMeterIsMoving = 0;
+ }
+ else
+ {
+ CreateTask(Task_SlideApplauseMeterOut, 10);
+ gSprites[sContest.applauseMeterSpriteId].pos2.x = 0;
+ sContest.applauseMeterIsMoving = 1;
+ }
+}
+
+void Task_SlideApplauseMeterOut(u8 taskId)
+{
+ struct Sprite *sprite = &gSprites[sContest.applauseMeterSpriteId];
+
+ gTasks[taskId].data[10] += 1664;
+ sprite->pos2.x -= gTasks[taskId].data[10] >> 8;
+ gTasks[taskId].data[10] = gTasks[taskId].data[10] & 0xFF;
+ if (sprite->pos2.x < -70)
+ sprite->pos2.x = -70;
+ if (sprite->pos2.x == -70)
+ {
+ sprite->invisible = TRUE;
+ sContest.applauseMeterIsMoving = 0;
+ DestroyTask(taskId);
+ }
+}
+
+void ShowAndUpdateApplauseMeter(s8 a)
+{
+ u8 taskId = CreateTask(Task_ShowAndUpdateApplauseMeter, 5);
+
+ gTasks[taskId].data[0] = a;
+ sContest.isShowingApplauseMeter = 1;
+}
+
+void Task_ShowAndUpdateApplauseMeter(u8 taskId)
+{
+ switch (gTasks[taskId].data[10])
+ {
+ case 0:
+ SlideApplauseMeterIn();
+ gTasks[taskId].data[10]++;
+ break;
+ case 1:
+ if (!sContest.applauseMeterIsMoving)
+ {
+ nullsub_18(gTasks[taskId].data[0]);
+ gTasks[taskId].data[10]++;
+ }
+ break;
+ case 2:
+ if (gTasks[taskId].data[11]++ > 20)
+ {
+ gTasks[taskId].data[11] = 0;
+ UpdateApplauseMeter();
+ sContest.isShowingApplauseMeter = 0;
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+UNUSED
+void HideApplauseMeterNoAnim(void)
+{
+ gSprites[sContest.applauseMeterSpriteId].pos2.x = 0;
+ gSprites[sContest.applauseMeterSpriteId].invisible = FALSE;
+}
+
+UNUSED
+void ShowApplauseMeterNoAnim(void)
+{
+ gSprites[sContest.applauseMeterSpriteId].invisible = TRUE;
+}
+
+void AnimateAudience(void)
+{
+ CreateTask(Task_AnimateAudience, 15);
+ sContest.animatingAudience = 1;
+}
+
+void Task_AnimateAudience(u8 taskId)
+{
+ if (gTasks[taskId].data[10]++ > 6)
+ {
+#ifndef NONMATCHING
+ register struct Task *task asm("r0");
+ register u32 r4 asm("r4") = taskId * 4;
+#endif
+
+ gTasks[taskId].data[10] = 0;
+ if (gTasks[taskId].data[11] == 0)
+ {
+ DmaCopy32Defvars(3, ewram16800, (void *)(VRAM + 0x2000), 0x1000);
+ }
+ else
+ {
+ DmaCopy32Defvars(3, eUnzippedContestAudience_Gfx, (void *)(VRAM + 0x2000), 0x1000);
+ gTasks[taskId].data[12]++;
+ }
+
+#ifdef NONMATCHING
+ gTasks[taskId].data[11] ^= 1;
+ if (gTasks[taskId].data[12] == 9)
+#else
+ // Why won't this match the normal way?
+ asm("add %0, %1, #0\n\t"
+ "add %0, %3\n\t"
+ "lsl %0, #3\n\t"
+ "add %0, %2\n\t"
+ : "=r"(task):"r"(r4),"r"(gTasks),"r"(taskId));
+
+ task->data[11] ^= 1;
+ if (task->data[12] == 9)
+#endif
+ {
+ sContest.animatingAudience = 0;
+ DestroyTask(taskId);
+ }
+ }
+}
+
+#define tBlendColor data[0]
+#define tBlendCoeff data[1]
+
+void BlendAudienceBackground(s8 excitementDir, s8 blendDir)
+{
+ u8 taskId = CreateTask(Task_BlendAudienceBackground, 10);
+ u16 blendColor;
+ u8 blendCoeff;
+ u8 targetBlendCoeff;
+
+ if (excitementDir > 0)
+ {
+ blendColor = RGB(30, 27, 8);
+ if (blendDir > 0)
+ {
+ blendCoeff = 0;
+ targetBlendCoeff = sContest.applauseLevel * 3;
+ }
+ else
+ {
+ blendCoeff = sContest.applauseLevel * 3;
+ targetBlendCoeff = 0;
+ }
+ }
+ else
+ {
+ blendColor = 0;
+ if (blendDir > 0)
+ {
+ blendCoeff = 0;
+ targetBlendCoeff = 12;
+ }
+ else
+ {
+ blendCoeff = 12;
+ targetBlendCoeff = 0;
+ }
+ }
+ gTasks[taskId].tBlendColor = blendColor;
+ gTasks[taskId].tBlendCoeff = blendCoeff;
+ gTasks[taskId].data[2] = blendDir;
+ gTasks[taskId].data[3] = targetBlendCoeff;
+ // Because this isn't set to TRUE here, the main task doesn't wait for the color blend
+ // Unclear if this was intentional or not (perhaps waiting added too much delay). In any case it does nothing now
+ sContest.waitForAudienceBlend = 0;
+}
+
+void Task_BlendAudienceBackground(u8 taskId)
+{
+ if (gTasks[taskId].data[10]++ >= 0)
+ {
+ gTasks[taskId].data[10] = 0;
+ if (gTasks[taskId].data[2] > 0)
+ gTasks[taskId].tBlendCoeff++;
+ else
+ gTasks[taskId].tBlendCoeff--;
+ BlendPalette(17, 1, gTasks[taskId].tBlendCoeff, gTasks[taskId].tBlendColor);
+ BlendPalette(26, 1, gTasks[taskId].tBlendCoeff, gTasks[taskId].tBlendColor);
+ if (gTasks[taskId].tBlendCoeff == gTasks[taskId].data[3])
+ {
+ DestroyTask(taskId);
+ sContest.waitForAudienceBlend = 0;
+ }
+ }
+}
+
+#undef tBlendColor
+#undef tBlendCoeff
+
+void ShowHideNextTurnGfx(bool8 a)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (sContestantStatus[i].turnOrderMod != 0 && a)
+ {
+ CpuCopy32(
+ GetTurnOrderNumberGfx(i),
+ (void *)(VRAM + 0x10000 + (gSprites[eContestGfxState[i].nextTurnSpriteId].oam.tileNum + 5) * 32),
+ 64);
+ gSprites[eContestGfxState[i].nextTurnSpriteId].pos1.y = gUnknown_083CA33C[gContestantTurnOrder[i]];
+ gSprites[eContestGfxState[i].nextTurnSpriteId].invisible = FALSE;
+ }
+ else
+ {
+ gSprites[eContestGfxState[i].nextTurnSpriteId].invisible = TRUE;
+ }
+ }
+}
+
+const u8 *GetTurnOrderNumberGfx(u8 contestant)
+{
+ if (sContestantStatus[contestant].turnOrderMod != 1)
+ return gContestNextTurnRandomGfx;
+ else
+ return gContestNextTurnNumbersGfx + sContestantStatus[contestant].nextTurnOrder * 64;
+}
+
+void DrawUnnervedSymbols(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (eContestAppealResults.unnervedPokes[i] != 0 && !Contest_IsMonsTurnDisabled(i))
+ {
+ u8 r4 = gContestantTurnOrder[i] * 5 + 2;
+ u16 r0 = GetStatusSymbolTileOffset(i, 3);
+
+ *(u16 *)(VRAM + 0xC000 + r4 * 64 + 0x28) = r0;
+ *(u16 *)(VRAM + 0xC000 + r4 * 64 + 0x2A) = r0 + 1;
+ *(u16 *)(VRAM + 0xC000 + (r4 + 1) * 64 + 0x28) = r0 + 16;
+ *(u16 *)(VRAM + 0xC000 + (r4 + 1) * 64 + 0x2A) = r0 + 17;
+ PlaySE(SE_CONTEST_ICON_CHANGE);
+ }
+ }
+}
+
+bool8 IsContestantAllowedToCombo(u8 contestant)
+{
+ if (sContestantStatus[contestant].repeatedMove || sContestantStatus[contestant].nervous)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+void SetBgForCurtainDrop(void)
+{
+ s32 i;
+
+ ((vBgCnt *)&REG_BG1CNT)->priority = 0;
+ ((vBgCnt *)&REG_BG1CNT)->screenSize = 1;
+ ((vBgCnt *)&REG_BG1CNT)->areaOverflowMode = 0;
+
+ gBattle_BG1_X = DISPLAY_WIDTH;
+ gBattle_BG1_Y = DISPLAY_HEIGHT;
+ REG_BG1HOFS = DISPLAY_WIDTH;
+ REG_BG1VOFS = DISPLAY_HEIGHT;
+
+ DmaClear32(3, (void *)(VRAM + 0xF000), 0x1000);
+ LZDecompressVram(gUnknown_08D17C3C, (void *)(VRAM + 0xF000));
+
+ ((vBgCnt *)&REG_BG1CNT)->charBaseBlock = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ gSprites[eContestGfxState[i].sliderHeartSpriteId].oam.priority = 1;
+ gSprites[eContestGfxState[i].nextTurnSpriteId].oam.priority = 1;
+ }
+
+ ((vBgCnt *)&REG_BG2CNT)->priority = 1;
+ ((vBgCnt *)&REG_BG0CNT)->priority = 1;
+ ((vBgCnt *)&REG_BG1CNT)->screenSize = 2;
+}
+
+void UpdateContestantBoxOrder(void)
+{
+ s32 i;
+
+ DmaClearLarge32(3, (void *)(VRAM + 0x8000), 0x2000, 0x1000);
+ DmaClear32(3, (void *)(VRAM + 0xF000), 0x1000);
+
+ gBattle_BG1_X = 0;
+ gBattle_BG1_Y = 0;
+
+ ((vBgCnt *)&REG_BG1CNT)->priority = 1;
+ ((vBgCnt *)&REG_BG1CNT)->screenSize = 0;
+ ((vBgCnt *)&REG_BG1CNT)->areaOverflowMode = 0;
+ ((vBgCnt *)&REG_BG1CNT)->charBaseBlock = 2;
+
+ for (i = 0; i < 4; i++)
+ {
+ gSprites[eContestGfxState[i].sliderHeartSpriteId].oam.priority = 0;
+ gSprites[eContestGfxState[i].nextTurnSpriteId].oam.priority = 0;
+ }
+}
+
+void Task_StartDropCurtainAtRoundEnd(u8 taskId)
+{
+ gBattle_BG1_X = 0;
+ gBattle_BG1_Y = DISPLAY_HEIGHT;
+ PlaySE12WithPanning(SE_CONTEST_CURTAIN_FALL, 0);
+ gTasks[taskId].func = Task_UpdateCurtainDropAtRoundEnd;
+}
+
+void Task_UpdateCurtainDropAtRoundEnd(u8 taskId)
+{
+ if ((s16)(gBattle_BG1_Y -= 7) < 0)
+ gBattle_BG1_Y = 0;
+ if (gBattle_BG1_Y == 0) // Why cast?
+ {
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = 0;
+ gTasks[taskId].data[2] = 0;
+ gTasks[taskId].func = Task_ResetForNextRound;
+ }
+}
+
+void Task_ResetForNextRound(u8 taskId)
+{
+ s32 i;
+
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ for (i = 0; i < 4; i++)
+ sContest.prevTurnOrder[i] = gContestantTurnOrder[i];
+ FillContestantWindowBgs();
+ UpdateBlendTaskContestantsData();
+ DrawConditionStars();
+ DrawContestantWindows();
+ ShowHideNextTurnGfx(TRUE);
+ UpdateSliderHeartSpriteYPositions();
+ gTasks[taskId].data[0] = 1;
+ break;
+ case 1:
+ if (gIsLinkContest & 1)
+ {
+ u8 taskId2;
+
+ sContest.waitForLink = 1;
+ if (IsPlayerLinkLeader())
+ SetContestantStatusesForNextRound();
+ taskId2 = CreateTask(Task_LinkContest_CommunicateAppealsState, 0);
+ SetTaskFuncWithFollowupFunc(
+ taskId2, Task_LinkContest_CommunicateAppealsState, Task_EndWaitForLink);
+ ContestPrintLinkStandby();
+ gTasks[taskId].data[0] = 2;
+ }
+ else
+ {
+ SetContestantStatusesForNextRound();
+ gTasks[taskId].data[0] = 3;
+ }
+ break;
+ case 2:
+ if (!sContest.waitForLink)
+ gTasks[taskId].data[0] = 3;
+ break;
+ case 3:
+ DrawStatusSymbols();
+ SwapMoveDescAndContestTilemaps();
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].func = Task_WaitRaiseCurtainAtRoundEnd;
+ break;
+ }
+}
+
+void Task_UpdateRaiseCurtainAtRoundEnd(u8 taskId)
+{
+ if ((s16)(gBattle_BG1_Y += 7) > DISPLAY_HEIGHT)
+ gTasks[taskId].func = Task_UpdateContestantBoxOrder;
+}
+
+void Task_WaitRaiseCurtainAtRoundEnd(u8 taskId)
+{
+ if (gTasks[taskId].data[2] < 10)
+ {
+ gTasks[taskId].data[2]++;
+ }
+ else
+ {
+ if (gTasks[taskId].data[1] == 0)
+ {
+ if (gTasks[taskId].data[0] == 16)
+ gTasks[taskId].data[1]++;
+ else
+ gTasks[taskId].data[0]++;
+ }
+ else
+ {
+ if (gTasks[taskId].data[0] == 0)
+ {
+ gTasks[taskId].data[1] = 0;
+ gTasks[taskId].data[2] = 0;
+ gTasks[taskId].func = Task_StartRaiseCurtainAtRoundEnd;
+ }
+ else
+ {
+ gTasks[taskId].data[0]--;
+ }
+ }
+ }
+}
+
+void Task_StartRaiseCurtainAtRoundEnd(u8 taskId)
+{
+ if (gTasks[taskId].data[2] < 10)
+ {
+ gTasks[taskId].data[2]++;
+ }
+ else
+ {
+ gTasks[taskId].data[2] = 0;
+ PlaySE12WithPanning(SE_CONTEST_CURTAIN_RISE, 0);
+ gTasks[taskId].func = Task_UpdateRaiseCurtainAtRoundEnd;
+ }
+}
+
+void AnimateSliderHearts(u8 animId)
+{
+ s32 i;
+ u8 taskId;
+
+ for (i = 0; i < 4; i++)
+ {
+ gSprites[eContestGfxState[i].sliderHeartSpriteId].oam.matrixNum = AllocOamMatrix();
+ gSprites[eContestGfxState[i].sliderHeartSpriteId].oam.affineMode = 1;
+ StartSpriteAffineAnim(&gSprites[eContestGfxState[i].sliderHeartSpriteId], animId);
+ if (animId == 2)
+ {
+ AnimateSprite(&gSprites[eContestGfxState[i].sliderHeartSpriteId]);
+ gSprites[eContestGfxState[i].sliderHeartSpriteId].invisible = FALSE;
+ }
+ }
+ taskId = CreateTask(Task_WaitForSliderHeartAnim, 5);
+ gTasks[taskId].data[0] = animId;
+ sContest.sliderHeartsAnimating = 1;
+}
+
+void Task_WaitForSliderHeartAnim(u8 taskId)
+{
+ s32 i;
+
+ if (gSprites[eContestGfxState[0].sliderHeartSpriteId].affineAnimEnded)
+ {
+ if ((u8)gTasks[taskId].data[0] == 1)
+ {
+ for (i = 0; i < 4; i++)
+ gSprites[eContestGfxState[i].sliderHeartSpriteId].invisible = TRUE;
+ }
+ for (i = 0; i < 4; i++)
+ FreeSpriteOamMatrix(&gSprites[eContestGfxState[i].sliderHeartSpriteId]);
+ sContest.sliderHeartsAnimating = 0;
+ DestroyTask(taskId);
+ }
+}
+
+u16 SanitizeMove(u16 move)
+{
+ if (move >= NUM_MOVES)
+ move = MOVE_POUND;
+ return move;
+}
+
+u16 SanitizeSpecies(u16 species)
+{
+ if (species >= NUM_SPECIES)
+ species = SPECIES_NONE;
+ return species;
+}
+
+void SetMoveSpecificAnimData(u8 contestant)
+{
+ s32 i;
+ u16 move = SanitizeMove(sContestantStatus[contestant].currMove);
+ u16 species = SanitizeSpecies(gContestMons[contestant].species);
+ u8 r5_2;
+
+ memset(&gContestResources__moveAnim, 0, sizeof(gContestResources__moveAnim));
+ ClearBattleAnimationVars();
+ for (i = 0; i < 4; i++)
+ gBattleMonForms[i] = 0;
+ switch (move)
+ {
+ case MOVE_CURSE:
+ if (gBaseStats[species].type1 == TYPE_GHOST || gBaseStats[species].type2 == TYPE_GHOST)
+ gAnimMoveTurn = 0;
+ else
+ gAnimMoveTurn = 1;
+ break;
+ case MOVE_TRANSFORM:
+ case MOVE_ROLE_PLAY:
+ r5_2 = sContestantStatus[contestant].contestantAnimTarget;
+ gContestResources__moveAnim.targetSpecies = SanitizeSpecies(gContestMons[r5_2].species);
+ gContestResources__moveAnim.unk10 = gContestMons[r5_2].personality;
+ gContestResources__moveAnim.hasTargetAnim = 1;
+ break;
+ case MOVE_RETURN:
+ gAnimFriendship = 0xFF;
+ break;
+ case MOVE_FRUSTRATION:
+ gAnimFriendship = 0;
+ break;
+ case MOVE_SOLAR_BEAM:
+ case MOVE_RAZOR_WIND:
+ case MOVE_SKULL_BASH:
+ case MOVE_SKY_ATTACK:
+ if (sContest.moveAnimTurnCount == 0)
+ {
+ sContest.moveAnimTurnCount = 2;
+ gAnimMoveTurn = 0;
+ }
+ else
+ {
+ gAnimMoveTurn = 1;
+ }
+ break;
+ }
+ SetBattleTargetSpritePosition();
+}
+
+void ClearMoveAnimData(UNUSED u8 contestant)
+{
+ memset(&gContestResources__moveAnim, 0, sizeof(gContestResources__moveAnim));
+ if (sContest.moveAnimTurnCount != 0)
+ sContest.moveAnimTurnCount--;
+}
+
+void SetMoveAnimAttackerData(u8 contestant)
+{
+ gContestResources__moveAnim.contestant = contestant;
+ gContestResources__moveAnim.species = SanitizeSpecies(gContestMons[contestant].species);
+ gContestResources__moveAnim.personality = gContestMons[contestant].personality;
+ gContestResources__moveAnim.otId = gContestMons[contestant].otId;
+}
+
+void CreateInvisibleBattleTargetSprite(void)
+{
+ gBattlerSpriteIds[3] = CreateInvisibleSpriteWithCallback(SpriteCallbackDummy);
+ InitSpriteAffineAnim(&gSprites[gBattlerSpriteIds[gBattlerTarget]]);
+ SetBattleTargetSpritePosition();
+}
+
+void SetBattleTargetSpritePosition(void)
+{
+ struct Sprite *sprite = &gSprites[gBattlerSpriteIds[3]];
+
+ sprite->pos2.x = 0;
+ sprite->pos2.y = 0;
+ sprite->pos1.x = GetBattlerSpriteCoord(3, 0);
+ sprite->pos1.y = GetBattlerSpriteCoord(3, 1);
+ sprite->invisible = TRUE;
+}
+
+void SelectContestMoveBankTarget(u16 move)
+{
+ switch (gBattleMoves[move].target)
+ {
+ case TARGET_UNK2:
+ case TARGET_USER:
+ gBattlerTarget = 2;
+ break;
+ case TARGET_SELECTED_POKEMON:
+ case TARGET_RANDOM:
+ case TARGET_BOTH_ENEMIES:
+ case TARGET_ALL_EXCEPT_USER:
+ default:
+ gBattlerTarget = 3;
+ break;
+ }
+}
+
+bool8 Contest_SaveWinner(u8 rank)
+{
+ s32 i;
+ u8 captionId = Random() % 3;
+
+ // Get the index of the winner among the contestants
+ for (i = 0; i < 3; i++)
+ {
+ if (gContestFinalStandings[i] == 0)
+ break;
+ }
+
+ // Exit if attempting to save a Pokémon other than the player's to the museum
+ if (rank == CONTEST_SAVE_FOR_MUSEUM && i != gContestPlayerMonIndex)
+ return FALSE;
+
+ // Adjust the random painting caption depending on the category
+ switch (gSpecialVar_ContestCategory)
+ {
+ case CONTEST_CATEGORY_COOL:
+ captionId += 0;
+ break;
+ case CONTEST_CATEGORY_BEAUTY:
+ captionId += 3;
+ break;
+ case CONTEST_CATEGORY_CUTE:
+ captionId += 6;
+ break;
+ case CONTEST_CATEGORY_SMART:
+ captionId += 9;
+ break;
+ case CONTEST_CATEGORY_TOUGH:
+ captionId += 12;
+ break;
+ }
+ if (rank != CONTEST_SAVE_FOR_ARTIST)
+ {
+ // Save winner in the saveblock
+ // Used to save any winner for the Contest Hall or the Museum
+ // but excludes the temporary save used by the artist
+ u8 saveIdx = GetContestWinnerSaveIdx(rank, TRUE);
+
+ gSaveBlock1.contestWinners[saveIdx].personality = gContestMons[i].personality;
+ gSaveBlock1.contestWinners[saveIdx].species = gContestMons[i].species;
+ gSaveBlock1.contestWinners[saveIdx].otId = gContestMons[i].otId;
+ StringCopy(gSaveBlock1.contestWinners[saveIdx].nickname, gContestMons[i].nickname);
+ StringCopy(gSaveBlock1.contestWinners[saveIdx].trainerName, gContestMons[i].trainerName);
+ if (rank != CONTEST_SAVE_FOR_MUSEUM)
+ gSaveBlock1.contestWinners[saveIdx].contestCategory = gSpecialVar_ContestCategory;
+ else
+ gSaveBlock1.contestWinners[saveIdx].contestCategory = captionId;
+ }
+ else
+ {
+ eCurContestWinner.personality = gContestMons[i].personality;
+ eCurContestWinner.otId = gContestMons[i].otId;
+ eCurContestWinner.species = gContestMons[i].species;
+ StringCopy(eCurContestWinner.nickname, gContestMons[i].nickname);
+ if (gIsLinkContest & 1)
+ StringCopy(eCurContestWinner.trainerName, gLinkPlayers[i].name);
+ else
+ StringCopy(eCurContestWinner.trainerName, gContestMons[i].trainerName);
+ eCurContestWinner.contestCategory = captionId;
+ }
+ return TRUE;
+}
+
+// Rank is either a regular contest rank (for saving winners to show in the Contest Hall)
+// Or one of two special IDs listed below (for saving winners to show in Museum, or from the artist)
+// If just retrieving the index where the winner *would* go, shift is FALSE
+// If actually preparing to insert the winner into the saveblock, shift is TRUE
+u8 GetContestWinnerSaveIdx(u8 rank, u8 shift)
+{
+ s32 i;
+
+ switch (rank)
+ {
+ case CONTEST_RANK_NORMAL:
+ case CONTEST_RANK_SUPER:
+ return rank;
+ case CONTEST_RANK_HYPER:
+ if (shift)
+ {
+ for (i = CONTEST_WINNER_HYPER_3 - 1; i > CONTEST_WINNER_HYPER_1 - 1; i--)
+ memcpy(&gSaveBlock1.contestWinners[i], &gSaveBlock1.contestWinners[i - 1], sizeof(struct ContestWinner));
+ }
+ return CONTEST_WINNER_HYPER_1 - 1;
+ case CONTEST_RANK_MASTER:
+ if (shift)
+ {
+ for (i = CONTEST_WINNER_MASTER_3 - 1; i > CONTEST_WINNER_MASTER_1 - 1; i--)
+ memcpy(&gSaveBlock1.contestWinners[i], &gSaveBlock1.contestWinners[i - 1], sizeof(struct ContestWinner));
+ }
+ return CONTEST_WINNER_MASTER_1 - 1;
+ default:
+// case CONTEST_SAVE_FOR_MUSEUM:
+// case CONTEST_SAVE_FOR_ARTIST:
+ switch (gSpecialVar_ContestCategory)
+ {
+ case CONTEST_CATEGORY_COOL:
+ return CONTEST_WINNER_MUSEUM_COOL - 1;
+ case CONTEST_CATEGORY_BEAUTY:
+ return CONTEST_WINNER_MUSEUM_BEAUTY - 1;
+ case CONTEST_CATEGORY_CUTE:
+ return CONTEST_WINNER_MUSEUM_CUTE - 1;
+ case CONTEST_CATEGORY_SMART:
+ return CONTEST_WINNER_MUSEUM_SMART - 1;
+ case CONTEST_CATEGORY_TOUGH:
+ default:
+ return CONTEST_WINNER_MUSEUM_TOUGH - 1;
+ }
+ }
+}
+
+void Contest_ResetWinners(void)
+{
+ s32 i;
+
+ for (i = 0; i < 8; i++)
+ gSaveBlock1.contestWinners[i] = gDefaultContestWinners[i];
+}
+