pokeemerald/src/battle_arena.c

821 lines
24 KiB
C
Raw Normal View History

2018-11-07 22:54:42 +01:00
#include "global.h"
#include "battle.h"
2018-11-14 01:01:50 +01:00
#include "battle_arena.h"
2018-11-07 22:54:42 +01:00
#include "battle_message.h"
2018-11-14 01:01:50 +01:00
#include "battle_setup.h"
#include "battle_tower.h"
2018-11-07 22:54:42 +01:00
#include "bg.h"
2018-11-14 01:01:50 +01:00
#include "decompress.h"
#include "event_data.h"
#include "frontier_util.h"
2018-12-19 03:15:59 +01:00
#include "graphics.h"
2018-11-14 01:01:50 +01:00
#include "gpu_regs.h"
#include "item.h"
2018-11-07 22:54:42 +01:00
#include "m4a.h"
2018-11-11 16:44:27 +01:00
#include "overworld.h"
2018-11-14 01:01:50 +01:00
#include "palette.h"
2018-11-11 16:44:27 +01:00
#include "random.h"
2018-11-14 01:01:50 +01:00
#include "sound.h"
2018-11-21 21:58:35 +01:00
#include "string_util.h"
2018-11-14 01:01:50 +01:00
#include "text.h"
#include "util.h"
2018-11-07 22:54:42 +01:00
#include "constants/songs.h"
2019-11-26 23:20:08 +01:00
#include "constants/battle_arena.h"
2018-11-11 16:44:27 +01:00
#include "constants/battle_string_ids.h"
#include "constants/battle_frontier.h"
2019-11-24 22:58:40 +01:00
#include "constants/frontier_util.h"
2019-02-08 16:41:36 +01:00
#include "constants/items.h"
2018-11-11 18:33:16 +01:00
#include "constants/moves.h"
2019-02-08 16:41:36 +01:00
#include "constants/rgb.h"
2018-11-07 22:54:42 +01:00
2019-02-08 16:41:36 +01:00
static void InitArenaChallenge(void);
static void GetArenaData(void);
static void SetArenaData(void);
2019-11-26 23:20:08 +01:00
static void SaveArenaChallenge(void);
static void SetArenaPrize(void);
static void GiveArenaPrize(void);
2019-02-08 16:41:36 +01:00
static void BufferArenaOpponentName(void);
2018-11-11 18:33:16 +01:00
static void SpriteCb_JudgmentIcon(struct Sprite *sprite);
2019-02-08 16:41:36 +01:00
static void ShowJudgmentSprite(u8 x, u8 y, u8 category, u8 battler);
2018-11-11 16:44:27 +01:00
#define JUDGEMENT_STATE_FINISHED 8
#define TAG_JUDGEMENT_ICON 1000
enum {
ANIM_ICON_X, // Player lost
ANIM_ICON_TRIANGLE, // Tie
ANIM_ICON_CIRCLE, // Player won
ANIM_ICON_LINE, // Line segment for separating the score total at the bottom
};
// This table holds the number of points to add to the 'mind' score for each move.
// All moves with power != 0 give 1 point, with the following exceptions:
// - Counter, Mirror Coat, and Bide give 0 points
// - Fake Out subtracts 1 point
// All moves with power == 0 give 0 points, with the following exceptions:
// - Protect, Detect, and Endure subtract 1 point
static const s8 sMindRatings[MOVES_COUNT] =
2018-11-11 18:33:16 +01:00
{
[MOVE_POUND] = 1,
[MOVE_KARATE_CHOP] = 1,
[MOVE_DOUBLE_SLAP] = 1,
[MOVE_COMET_PUNCH] = 1,
[MOVE_MEGA_PUNCH] = 1,
[MOVE_PAY_DAY] = 1,
[MOVE_FIRE_PUNCH] = 1,
[MOVE_ICE_PUNCH] = 1,
[MOVE_THUNDER_PUNCH] = 1,
[MOVE_SCRATCH] = 1,
[MOVE_VICE_GRIP] = 1,
[MOVE_GUILLOTINE] = 1,
[MOVE_RAZOR_WIND] = 1,
[MOVE_CUT] = 1,
[MOVE_GUST] = 1,
[MOVE_WING_ATTACK] = 1,
[MOVE_FLY] = 1,
[MOVE_BIND] = 1,
[MOVE_SLAM] = 1,
[MOVE_VINE_WHIP] = 1,
[MOVE_STOMP] = 1,
[MOVE_DOUBLE_KICK] = 1,
[MOVE_MEGA_KICK] = 1,
[MOVE_JUMP_KICK] = 1,
[MOVE_ROLLING_KICK] = 1,
[MOVE_HEADBUTT] = 1,
[MOVE_HORN_ATTACK] = 1,
[MOVE_FURY_ATTACK] = 1,
[MOVE_HORN_DRILL] = 1,
[MOVE_TACKLE] = 1,
[MOVE_BODY_SLAM] = 1,
[MOVE_WRAP] = 1,
[MOVE_TAKE_DOWN] = 1,
[MOVE_THRASH] = 1,
[MOVE_DOUBLE_EDGE] = 1,
[MOVE_POISON_STING] = 1,
[MOVE_TWINEEDLE] = 1,
[MOVE_PIN_MISSILE] = 1,
[MOVE_BITE] = 1,
[MOVE_SONIC_BOOM] = 1,
[MOVE_ACID] = 1,
[MOVE_EMBER] = 1,
[MOVE_FLAMETHROWER] = 1,
[MOVE_WATER_GUN] = 1,
[MOVE_HYDRO_PUMP] = 1,
[MOVE_SURF] = 1,
[MOVE_ICE_BEAM] = 1,
[MOVE_BLIZZARD] = 1,
[MOVE_PSYBEAM] = 1,
[MOVE_BUBBLE_BEAM] = 1,
[MOVE_AURORA_BEAM] = 1,
[MOVE_HYPER_BEAM] = 1,
[MOVE_PECK] = 1,
[MOVE_DRILL_PECK] = 1,
[MOVE_SUBMISSION] = 1,
[MOVE_LOW_KICK] = 1,
[MOVE_SEISMIC_TOSS] = 1,
[MOVE_STRENGTH] = 1,
[MOVE_ABSORB] = 1,
[MOVE_MEGA_DRAIN] = 1,
[MOVE_RAZOR_LEAF] = 1,
[MOVE_SOLAR_BEAM] = 1,
[MOVE_PETAL_DANCE] = 1,
[MOVE_DRAGON_RAGE] = 1,
[MOVE_FIRE_SPIN] = 1,
[MOVE_THUNDER_SHOCK] = 1,
[MOVE_THUNDERBOLT] = 1,
[MOVE_THUNDER] = 1,
[MOVE_ROCK_THROW] = 1,
[MOVE_EARTHQUAKE] = 1,
[MOVE_FISSURE] = 1,
[MOVE_DIG] = 1,
[MOVE_CONFUSION] = 1,
[MOVE_PSYCHIC] = 1,
[MOVE_QUICK_ATTACK] = 1,
[MOVE_RAGE] = 1,
[MOVE_NIGHT_SHADE] = 1,
[MOVE_SELF_DESTRUCT] = 1,
[MOVE_EGG_BOMB] = 1,
[MOVE_LICK] = 1,
[MOVE_SMOG] = 1,
[MOVE_SLUDGE] = 1,
[MOVE_BONE_CLUB] = 1,
[MOVE_FIRE_BLAST] = 1,
[MOVE_WATERFALL] = 1,
[MOVE_CLAMP] = 1,
[MOVE_SWIFT] = 1,
[MOVE_SKULL_BASH] = 1,
[MOVE_SPIKE_CANNON] = 1,
[MOVE_CONSTRICT] = 1,
[MOVE_HI_JUMP_KICK] = 1,
[MOVE_DREAM_EATER] = 1,
[MOVE_BARRAGE] = 1,
[MOVE_LEECH_LIFE] = 1,
[MOVE_SKY_ATTACK] = 1,
[MOVE_BUBBLE] = 1,
[MOVE_DIZZY_PUNCH] = 1,
[MOVE_PSYWAVE] = 1,
[MOVE_CRABHAMMER] = 1,
[MOVE_EXPLOSION] = 1,
[MOVE_FURY_SWIPES] = 1,
[MOVE_BONEMERANG] = 1,
[MOVE_ROCK_SLIDE] = 1,
[MOVE_HYPER_FANG] = 1,
[MOVE_TRI_ATTACK] = 1,
[MOVE_SUPER_FANG] = 1,
[MOVE_SLASH] = 1,
[MOVE_STRUGGLE] = 1,
[MOVE_TRIPLE_KICK] = 1,
[MOVE_THIEF] = 1,
[MOVE_FLAME_WHEEL] = 1,
[MOVE_SNORE] = 1,
[MOVE_FLAIL] = 1,
[MOVE_AEROBLAST] = 1,
[MOVE_REVERSAL] = 1,
[MOVE_POWDER_SNOW] = 1,
[MOVE_PROTECT] = -1,
[MOVE_MACH_PUNCH] = 1,
[MOVE_FAINT_ATTACK] = 1,
[MOVE_SLUDGE_BOMB] = 1,
[MOVE_MUD_SLAP] = 1,
[MOVE_OCTAZOOKA] = 1,
[MOVE_ZAP_CANNON] = 1,
[MOVE_ICY_WIND] = 1,
[MOVE_DETECT] = -1,
[MOVE_BONE_RUSH] = 1,
[MOVE_OUTRAGE] = 1,
[MOVE_GIGA_DRAIN] = 1,
[MOVE_ENDURE] = -1,
[MOVE_ROLLOUT] = 1,
[MOVE_FALSE_SWIPE] = 1,
[MOVE_SPARK] = 1,
[MOVE_FURY_CUTTER] = 1,
[MOVE_STEEL_WING] = 1,
[MOVE_RETURN] = 1,
[MOVE_PRESENT] = 1,
[MOVE_FRUSTRATION] = 1,
[MOVE_SACRED_FIRE] = 1,
[MOVE_MAGNITUDE] = 1,
[MOVE_DYNAMIC_PUNCH] = 1,
[MOVE_MEGAHORN] = 1,
[MOVE_DRAGON_BREATH] = 1,
[MOVE_PURSUIT] = 1,
[MOVE_RAPID_SPIN] = 1,
[MOVE_IRON_TAIL] = 1,
[MOVE_METAL_CLAW] = 1,
[MOVE_VITAL_THROW] = 1,
[MOVE_HIDDEN_POWER] = 1,
[MOVE_CROSS_CHOP] = 1,
[MOVE_TWISTER] = 1,
[MOVE_CRUNCH] = 1,
[MOVE_EXTREME_SPEED] = 1,
[MOVE_ANCIENT_POWER] = 1,
[MOVE_SHADOW_BALL] = 1,
[MOVE_FUTURE_SIGHT] = 1,
[MOVE_ROCK_SMASH] = 1,
[MOVE_WHIRLPOOL] = 1,
[MOVE_BEAT_UP] = 1,
[MOVE_FAKE_OUT] = -1,
[MOVE_UPROAR] = 1,
[MOVE_SPIT_UP] = 1,
[MOVE_HEAT_WAVE] = 1,
[MOVE_FACADE] = 1,
[MOVE_FOCUS_PUNCH] = 1,
[MOVE_SMELLING_SALT] = 1,
[MOVE_SUPERPOWER] = 1,
[MOVE_REVENGE] = 1,
[MOVE_BRICK_BREAK] = 1,
[MOVE_KNOCK_OFF] = 1,
[MOVE_ENDEAVOR] = 1,
[MOVE_ERUPTION] = 1,
[MOVE_SECRET_POWER] = 1,
[MOVE_DIVE] = 1,
[MOVE_ARM_THRUST] = 1,
[MOVE_LUSTER_PURGE] = 1,
[MOVE_MIST_BALL] = 1,
[MOVE_BLAZE_KICK] = 1,
[MOVE_ICE_BALL] = 1,
[MOVE_NEEDLE_ARM] = 1,
[MOVE_HYPER_VOICE] = 1,
[MOVE_POISON_FANG] = 1,
[MOVE_CRUSH_CLAW] = 1,
[MOVE_BLAST_BURN] = 1,
[MOVE_HYDRO_CANNON] = 1,
[MOVE_METEOR_MASH] = 1,
[MOVE_ASTONISH] = 1,
[MOVE_WEATHER_BALL] = 1,
[MOVE_AIR_CUTTER] = 1,
[MOVE_OVERHEAT] = 1,
[MOVE_ROCK_TOMB] = 1,
[MOVE_SILVER_WIND] = 1,
[MOVE_WATER_SPOUT] = 1,
[MOVE_SIGNAL_BEAM] = 1,
[MOVE_SHADOW_PUNCH] = 1,
[MOVE_EXTRASENSORY] = 1,
[MOVE_SKY_UPPERCUT] = 1,
[MOVE_SAND_TOMB] = 1,
[MOVE_SHEER_COLD] = 1,
[MOVE_MUDDY_WATER] = 1,
[MOVE_BULLET_SEED] = 1,
[MOVE_AERIAL_ACE] = 1,
[MOVE_ICICLE_SPEAR] = 1,
[MOVE_DRAGON_CLAW] = 1,
[MOVE_FRENZY_PLANT] = 1,
[MOVE_BOUNCE] = 1,
[MOVE_MUD_SHOT] = 1,
[MOVE_POISON_TAIL] = 1,
[MOVE_COVET] = 1,
[MOVE_VOLT_TACKLE] = 1,
[MOVE_MAGICAL_LEAF] = 1,
[MOVE_LEAF_BLADE] = 1,
[MOVE_ROCK_BLAST] = 1,
[MOVE_SHOCK_WAVE] = 1,
[MOVE_WATER_PULSE] = 1,
[MOVE_DOOM_DESIRE] = 1,
[MOVE_PSYCHO_BOOST] = 1,
};
static const struct OamData sOam_JudgementIcon =
2018-11-11 18:33:16 +01:00
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
2022-07-30 03:27:39 +02:00
.mosaic = FALSE,
.bpp = ST_OAM_4BPP,
.shape = SPRITE_SHAPE(16x16),
2018-11-11 18:33:16 +01:00
.x = 0,
.matrixNum = 0,
.size = SPRITE_SIZE(16x16),
2018-11-11 18:33:16 +01:00
.tileNum = 0,
.priority = 0,
.paletteNum = 15,
.affineParam = 0
};
static const union AnimCmd sAnim_JudgementIcon_X[] =
2018-11-11 18:33:16 +01:00
{
ANIMCMD_FRAME(0, 1),
ANIMCMD_END
};
static const union AnimCmd sAnim_JudgementIcon_Triangle[] =
2018-11-11 18:33:16 +01:00
{
ANIMCMD_FRAME(4, 1),
ANIMCMD_END
};
static const union AnimCmd sAnim_JudgementIcon_Circle[] =
2018-11-11 18:33:16 +01:00
{
ANIMCMD_FRAME(8, 1),
ANIMCMD_END
};
static const union AnimCmd sAnim_JudgementIcon_Line[] =
2018-11-11 18:33:16 +01:00
{
ANIMCMD_FRAME(12, 1),
ANIMCMD_END
};
static const union AnimCmd *const sAnims_JudgementIcon[] =
2018-11-11 18:33:16 +01:00
{
[ANIM_ICON_X] = sAnim_JudgementIcon_X,
[ANIM_ICON_TRIANGLE] = sAnim_JudgementIcon_Triangle,
[ANIM_ICON_CIRCLE] = sAnim_JudgementIcon_Circle,
[ANIM_ICON_LINE] = sAnim_JudgementIcon_Line,
2018-11-11 18:33:16 +01:00
};
static const struct SpriteTemplate sSpriteTemplate_JudgmentIcon =
{
2019-02-08 16:41:36 +01:00
.tileTag = TAG_JUDGEMENT_ICON,
2021-09-14 19:14:14 +02:00
.paletteTag = TAG_NONE,
.oam = &sOam_JudgementIcon,
.anims = sAnims_JudgementIcon,
2018-11-11 18:33:16 +01:00
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCb_JudgmentIcon,
};
2019-02-08 16:41:36 +01:00
static const struct CompressedSpriteSheet sBattleArenaJudgementSymbolsSpriteSheet[] =
2018-11-11 16:44:27 +01:00
{
2019-02-08 16:41:36 +01:00
{gBattleArenaJudgementSymbolsGfx, 0x200, TAG_JUDGEMENT_ICON},
2018-11-11 16:44:27 +01:00
{0}
};
2018-11-11 18:33:16 +01:00
static void (* const sArenaFunctions[])(void) =
2018-11-11 16:44:27 +01:00
{
2019-11-26 23:20:08 +01:00
[BATTLE_ARENA_FUNC_INIT] = InitArenaChallenge,
[BATTLE_ARENA_FUNC_GET_DATA] = GetArenaData,
[BATTLE_ARENA_FUNC_SET_DATA] = SetArenaData,
[BATTLE_ARENA_FUNC_SAVE] = SaveArenaChallenge,
[BATTLE_ARENA_FUNC_SET_PRIZE] = SetArenaPrize,
[BATTLE_ARENA_FUNC_GIVE_PRIZE] = GiveArenaPrize,
2019-11-26 23:20:08 +01:00
[BATTLE_ARENA_FUNC_GET_TRAINER_NAME] = BufferArenaOpponentName,
2018-11-11 16:44:27 +01:00
};
static const u16 sShortStreakPrizeItems[] =
2018-11-11 16:44:27 +01:00
{
2019-02-08 16:41:36 +01:00
ITEM_HP_UP,
ITEM_PROTEIN,
ITEM_IRON,
ITEM_CALCIUM,
ITEM_CARBOS,
ITEM_ZINC,
2018-11-11 16:44:27 +01:00
};
static const u16 sLongStreakPrizeItems[] =
2018-11-11 16:44:27 +01:00
{
2019-02-08 16:41:36 +01:00
ITEM_BRIGHT_POWDER,
ITEM_WHITE_HERB,
ITEM_QUICK_CLAW,
ITEM_LEFTOVERS,
ITEM_MENTAL_HERB,
ITEM_KINGS_ROCK,
ITEM_FOCUS_BAND,
ITEM_SCOPE_LENS,
ITEM_CHOICE_BAND,
2018-11-11 16:44:27 +01:00
};
2018-11-07 22:54:42 +01:00
void CallBattleArenaFunction(void)
{
2018-11-11 18:33:16 +01:00
sArenaFunctions[gSpecialVar_0x8004]();
2018-11-07 22:54:42 +01:00
}
2018-11-11 18:33:16 +01:00
u8 BattleArena_ShowJudgmentWindow(u8 *state)
2018-11-07 22:54:42 +01:00
{
2019-02-08 16:41:36 +01:00
int i;
u8 result = ARENA_RESULT_RUNNING;
2018-11-07 22:54:42 +01:00
switch (*state)
{
case 0:
2019-02-08 16:41:36 +01:00
BeginNormalPaletteFade(0x7FFFFF1C, 4, 0, 8, RGB_BLACK);
SetGpuReg(REG_OFFSET_WININ, (WININ_WIN0_ALL & ~WININ_WIN0_BG0) | WININ_WIN1_ALL);
2019-02-08 16:41:36 +01:00
LoadCompressedSpriteSheet(sBattleArenaJudgementSymbolsSpriteSheet);
LoadCompressedPalette(gBattleArenaJudgementSymbolsPalette, 0x1F0, 0x20);
2018-11-07 22:54:42 +01:00
gBattle_WIN0H = 0xFF;
gBattle_WIN0V = 0x70;
(*state)++;
break;
case 1:
if (!gPaletteFade.active)
{
HandleBattleWindow(5, 0, 24, 13, 0);
(*state)++;
}
break;
case 2:
if (!IsDma3ManagerBusyWithBgCopy())
{
gBattleTextBuff1[0] = CHAR_0;
gBattleTextBuff1[1] = EOS;
gBattleTextBuff2[0] = CHAR_0;
gBattleTextBuff2[1] = EOS;
BattleStringExpandPlaceholdersToDisplayedString(gText_PlayerMon1Name);
2021-10-08 22:50:52 +02:00
BattlePutTextOnWindow(gDisplayedStringBattle, ARENA_WIN_PLAYER_NAME);
BattlePutTextOnWindow(gText_Vs, ARENA_WIN_VS);
2018-11-07 22:54:42 +01:00
BattleStringExpandPlaceholdersToDisplayedString(gText_OpponentMon1Name);
2021-10-08 22:50:52 +02:00
BattlePutTextOnWindow(gDisplayedStringBattle, ARENA_WIN_OPPONENT_NAME);
BattlePutTextOnWindow(gText_Mind, ARENA_WIN_MIND);
BattlePutTextOnWindow(gText_Skill, ARENA_WIN_SKILL);
BattlePutTextOnWindow(gText_Body, ARENA_WIN_BODY);
2018-11-07 22:54:42 +01:00
BattleStringExpandPlaceholdersToDisplayedString(gText_Judgement);
2021-10-08 22:50:52 +02:00
BattlePutTextOnWindow(gDisplayedStringBattle, ARENA_WIN_JUDGEMENT_TITLE);
2018-11-07 22:54:42 +01:00
(*state)++;
}
break;
case 3:
if (!IsDma3ManagerBusyWithBgCopy())
{
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_ALL | WININ_WIN1_ALL);
// Create dividing line for the the score totals at the bottom
2018-11-07 22:54:42 +01:00
for (i = 0; i < 8; i++)
{
2019-02-08 16:41:36 +01:00
u8 spriteId = CreateSprite(&sSpriteTemplate_JudgmentIcon, 64 + i * 16, 84, 0);
StartSpriteAnim(&gSprites[spriteId], ANIM_ICON_LINE);
2018-11-07 22:54:42 +01:00
}
result = ARENA_RESULT_STEP_DONE;
2018-11-07 22:54:42 +01:00
(*state)++;
}
break;
case 4:
2020-08-21 00:02:00 +02:00
PlaySE(SE_ARENA_TIMEUP1);
2019-11-26 23:20:08 +01:00
ShowJudgmentSprite(80, 40, ARENA_CATEGORY_MIND, B_POSITION_PLAYER_LEFT);
ShowJudgmentSprite(160, 40, ARENA_CATEGORY_MIND, B_POSITION_OPPONENT_LEFT);
2018-11-07 22:54:42 +01:00
BattleStringExpandPlaceholdersToDisplayedString(gText_Judgement);
2021-10-08 22:50:52 +02:00
BattlePutTextOnWindow(gDisplayedStringBattle, ARENA_WIN_JUDGEMENT_TITLE);
2018-11-07 22:54:42 +01:00
(*state)++;
result = ARENA_RESULT_STEP_DONE;
2018-11-07 22:54:42 +01:00
break;
case 5:
2020-08-21 00:02:00 +02:00
PlaySE(SE_ARENA_TIMEUP1);
2019-11-26 23:20:08 +01:00
ShowJudgmentSprite(80, 56, ARENA_CATEGORY_SKILL, B_POSITION_PLAYER_LEFT);
ShowJudgmentSprite(160, 56, ARENA_CATEGORY_SKILL, B_POSITION_OPPONENT_LEFT);
2018-11-07 22:54:42 +01:00
BattleStringExpandPlaceholdersToDisplayedString(gText_Judgement);
2021-10-08 22:50:52 +02:00
BattlePutTextOnWindow(gDisplayedStringBattle, ARENA_WIN_JUDGEMENT_TITLE);
2018-11-07 22:54:42 +01:00
(*state)++;
result = ARENA_RESULT_STEP_DONE;
2018-11-07 22:54:42 +01:00
break;
case 6:
2020-08-21 00:02:00 +02:00
PlaySE(SE_ARENA_TIMEUP1);
2019-11-26 23:20:08 +01:00
ShowJudgmentSprite(80, 72, ARENA_CATEGORY_BODY, B_POSITION_PLAYER_LEFT);
ShowJudgmentSprite(160, 72, ARENA_CATEGORY_BODY, B_POSITION_OPPONENT_LEFT);
2018-11-07 22:54:42 +01:00
BattleStringExpandPlaceholdersToDisplayedString(gText_Judgement);
2021-10-08 22:50:52 +02:00
BattlePutTextOnWindow(gDisplayedStringBattle, ARENA_WIN_JUDGEMENT_TITLE);
2018-11-07 22:54:42 +01:00
(*state)++;
result = ARENA_RESULT_STEP_DONE;
2018-11-07 22:54:42 +01:00
break;
case 7:
2020-08-21 00:02:00 +02:00
PlaySE(SE_ARENA_TIMEUP2);
2018-11-07 22:54:42 +01:00
if (gBattleTextBuff1[0] > gBattleTextBuff2[0])
{
result = ARENA_RESULT_PLAYER_WON;
2018-11-07 22:54:42 +01:00
gBattleScripting.battler = 0;
}
else if (gBattleTextBuff1[0] < gBattleTextBuff2[0])
{
result = AREAN_RESULT_PLAYER_LOST;
2018-11-07 22:54:42 +01:00
gBattleScripting.battler = 1;
}
else
{
result = AREAN_RESULT_TIE;
2018-11-07 22:54:42 +01:00
}
(*state)++;
break;
case JUDGEMENT_STATE_FINISHED:
// Finishing this state is the indicator to SpriteCB_JudgmentIcon that its safe to destroy the judgement icon sprites
2018-11-07 22:54:42 +01:00
(*state)++;
break;
case JUDGEMENT_STATE_FINISHED + 1:
SetGpuReg(REG_OFFSET_WININ, (WININ_WIN0_ALL & ~WININ_WIN0_BG0) | WININ_WIN1_ALL);
2018-11-07 22:54:42 +01:00
HandleBattleWindow(5, 0, 24, 13, WINDOW_CLEAR);
CopyBgTilemapBufferToVram(0);
2021-10-09 17:33:37 +02:00
m4aMPlayVolumeControl(&gMPlayInfo_BGM, TRACKS_ALL, 256);
2019-02-08 16:41:36 +01:00
BeginNormalPaletteFade(0x7FFFFF1C, 4, 8, 0, RGB_BLACK);
2018-11-07 22:54:42 +01:00
(*state)++;
break;
case JUDGEMENT_STATE_FINISHED + 2:
2018-11-07 22:54:42 +01:00
if (!gPaletteFade.active)
{
SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_ALL | WININ_WIN1_ALL);
2019-02-08 16:41:36 +01:00
FreeSpriteTilesByTag(TAG_JUDGEMENT_ICON);
result = ARENA_RESULT_STEP_DONE;
2018-11-07 22:54:42 +01:00
(*state)++;
}
break;
}
return result;
2018-11-07 22:54:42 +01:00
}
2018-11-11 18:33:16 +01:00
static void ShowJudgmentSprite(u8 x, u8 y, u8 category, u8 battler)
2018-11-07 22:54:42 +01:00
{
2019-02-08 16:41:36 +01:00
int animNum = 0;
int pointsPlayer = 0;
int pointsOpponent = 0;
2018-11-11 18:33:16 +01:00
s8 *mindPoints = gBattleStruct->arenaMindPoints;
s8 *skillPoints = gBattleStruct->arenaSkillPoints;
u16 *hpAtStart = gBattleStruct->arenaStartHp;
2018-11-07 22:54:42 +01:00
2018-11-11 18:33:16 +01:00
switch (category)
2018-11-07 22:54:42 +01:00
{
2019-11-26 23:20:08 +01:00
case ARENA_CATEGORY_MIND:
2018-11-11 18:33:16 +01:00
pointsPlayer = mindPoints[battler];
pointsOpponent = mindPoints[BATTLE_OPPOSITE(battler)];
2018-11-07 22:54:42 +01:00
break;
2019-11-26 23:20:08 +01:00
case ARENA_CATEGORY_SKILL:
2018-11-11 18:33:16 +01:00
pointsPlayer = skillPoints[battler];
pointsOpponent = skillPoints[BATTLE_OPPOSITE(battler)];
2018-11-07 22:54:42 +01:00
break;
2019-11-26 23:20:08 +01:00
case ARENA_CATEGORY_BODY:
2018-11-11 18:33:16 +01:00
pointsPlayer = (gBattleMons[battler].hp * 100) / hpAtStart[battler];
pointsOpponent = (gBattleMons[BATTLE_OPPOSITE(battler)].hp * 100) / hpAtStart[BATTLE_OPPOSITE(battler)];
2018-11-07 22:54:42 +01:00
break;
}
2018-11-11 18:33:16 +01:00
if (pointsPlayer > pointsOpponent)
2018-11-07 22:54:42 +01:00
{
animNum = ANIM_ICON_CIRCLE;
// +2 to score total for winning
2018-11-07 22:54:42 +01:00
if (battler != 0)
gBattleTextBuff2[0] += 2;
else
gBattleTextBuff1[0] += 2;
}
2018-11-11 18:33:16 +01:00
else if (pointsPlayer == pointsOpponent)
2018-11-07 22:54:42 +01:00
{
animNum = ANIM_ICON_TRIANGLE;
// +1 to score total for a tie
2018-11-07 22:54:42 +01:00
if (battler != 0)
gBattleTextBuff2[0] += 1;
else
gBattleTextBuff1[0] += 1;
}
else
{
animNum = ANIM_ICON_X;
2018-11-07 22:54:42 +01:00
}
2018-11-11 18:33:16 +01:00
pointsPlayer = CreateSprite(&sSpriteTemplate_JudgmentIcon, x, y, 0);
StartSpriteAnim(&gSprites[pointsPlayer], animNum);
2018-11-07 22:54:42 +01:00
}
2018-11-11 18:33:16 +01:00
static void SpriteCb_JudgmentIcon(struct Sprite *sprite)
2018-11-07 22:54:42 +01:00
{
if (gBattleCommunication[0] > JUDGEMENT_STATE_FINISHED)
2018-11-07 22:54:42 +01:00
DestroySprite(sprite);
}
2018-11-11 18:33:16 +01:00
void BattleArena_InitPoints(void)
2018-11-07 22:54:42 +01:00
{
2018-11-11 18:33:16 +01:00
s8 *mindPoints = gBattleStruct->arenaMindPoints;
s8 *skillPoints = gBattleStruct->arenaSkillPoints;
u16 *hpAtStart = gBattleStruct->arenaStartHp;
mindPoints[0] = 0;
mindPoints[1] = 0;
skillPoints[0] = 0;
skillPoints[1] = 0;
hpAtStart[0] = gBattleMons[0].hp;
hpAtStart[1] = gBattleMons[1].hp;
2018-11-07 22:54:42 +01:00
}
2018-11-11 16:44:27 +01:00
2018-11-11 18:33:16 +01:00
void BattleArena_AddMindPoints(u8 battler)
2018-11-11 16:44:27 +01:00
{
gBattleStruct->arenaMindPoints[battler] += sMindRatings[gCurrentMove];
2018-11-11 16:44:27 +01:00
}
2018-11-11 18:33:16 +01:00
void BattleArena_AddSkillPoints(u8 battler)
2018-11-11 16:44:27 +01:00
{
2018-11-11 18:33:16 +01:00
s8 *skillPoints = gBattleStruct->arenaSkillPoints;
2018-11-11 16:44:27 +01:00
if (gHitMarker & HITMARKER_OBEYS)
{
2018-11-11 18:33:16 +01:00
u8 *failedMoveBits = &gBattleStruct->alreadyStatusedMoveAttempt;
if (*failedMoveBits & gBitTable[battler])
2018-11-11 16:44:27 +01:00
{
2018-11-11 18:33:16 +01:00
*failedMoveBits &= ~(gBitTable[battler]);
skillPoints[battler] -= 2;
2018-11-11 16:44:27 +01:00
}
else if (gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
{
2022-07-29 21:38:23 +02:00
if (!(gMoveResultFlags & MOVE_RESULT_MISSED) || gBattleCommunication[MISS_TYPE] != B_MSG_PROTECTED)
2018-11-11 18:33:16 +01:00
skillPoints[battler] -= 2;
2018-11-11 16:44:27 +01:00
}
2019-02-08 16:41:36 +01:00
else if ((gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE) && (gMoveResultFlags & MOVE_RESULT_NOT_VERY_EFFECTIVE))
2018-11-11 16:44:27 +01:00
{
2018-11-11 18:33:16 +01:00
skillPoints[battler] += 1;
2018-11-11 16:44:27 +01:00
}
else if (gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE)
{
2018-11-11 18:33:16 +01:00
skillPoints[battler] += 2;
2018-11-11 16:44:27 +01:00
}
else if (gMoveResultFlags & MOVE_RESULT_NOT_VERY_EFFECTIVE)
{
2018-11-11 18:33:16 +01:00
skillPoints[battler] -= 1;
2018-11-11 16:44:27 +01:00
}
else if (!gProtectStructs[battler].protected)
{
2018-11-11 18:33:16 +01:00
skillPoints[battler] += 1;
2018-11-11 16:44:27 +01:00
}
}
}
void BattleArena_DeductSkillPoints(u8 battler, u16 stringId)
2018-11-11 16:44:27 +01:00
{
2018-11-11 18:33:16 +01:00
s8 *skillPoints = gBattleStruct->arenaSkillPoints;
2018-11-11 16:44:27 +01:00
switch (stringId)
{
case STRINGID_PKMNSXMADEYUSELESS:
case STRINGID_PKMNSXMADEITINEFFECTIVE:
case STRINGID_PKMNSXPREVENTSFLINCHING:
case STRINGID_PKMNSXBLOCKSY2:
case STRINGID_PKMNSXPREVENTSYLOSS:
case STRINGID_PKMNSXMADEYINEFFECTIVE:
case STRINGID_PKMNSXPREVENTSBURNS:
case STRINGID_PKMNSXBLOCKSY:
case STRINGID_PKMNPROTECTEDBY:
case STRINGID_PKMNPREVENTSUSAGE:
case STRINGID_PKMNRESTOREDHPUSING:
case STRINGID_PKMNPREVENTSPARALYSISWITH:
case STRINGID_PKMNPREVENTSROMANCEWITH:
case STRINGID_PKMNPREVENTSPOISONINGWITH:
case STRINGID_PKMNPREVENTSCONFUSIONWITH:
case STRINGID_PKMNRAISEDFIREPOWERWITH:
case STRINGID_PKMNANCHORSITSELFWITH:
case STRINGID_PKMNPREVENTSSTATLOSSWITH:
case STRINGID_PKMNSTAYEDAWAKEUSING:
2018-11-11 18:33:16 +01:00
skillPoints[battler] -= 3;
2018-11-11 16:44:27 +01:00
break;
}
}
2021-03-21 04:47:08 +01:00
// Unused
static void UpdateHPAtStart(u8 battler)
2018-11-11 16:44:27 +01:00
{
2018-11-11 18:33:16 +01:00
u16 *hpAtStart = gBattleStruct->arenaStartHp;
2018-11-11 16:44:27 +01:00
2018-11-11 18:33:16 +01:00
hpAtStart[battler] = gBattleMons[battler].hp;
if (hpAtStart[BATTLE_OPPOSITE(battler)] > gBattleMons[BATTLE_OPPOSITE(battler)].hp)
hpAtStart[BATTLE_OPPOSITE(battler)] = gBattleMons[BATTLE_OPPOSITE(battler)].hp;
2018-11-11 16:44:27 +01:00
}
2019-02-08 16:41:36 +01:00
static void InitArenaChallenge(void)
2018-11-11 16:44:27 +01:00
{
bool32 isCurrent;
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
2019-11-24 22:58:40 +01:00
gSaveBlock2Ptr->frontier.challengeStatus = 0;
2018-11-11 16:44:27 +01:00
gSaveBlock2Ptr->frontier.curChallengeBattleNum = 0;
2019-11-24 22:58:40 +01:00
gSaveBlock2Ptr->frontier.challengePaused = FALSE;
2019-12-14 09:58:20 +01:00
gSaveBlock2Ptr->frontier.disableRecordBattle = FALSE;
2018-11-11 16:44:27 +01:00
if (lvlMode != FRONTIER_LVL_50)
2019-11-24 22:58:40 +01:00
isCurrent = gSaveBlock2Ptr->frontier.winStreakActiveFlags & STREAK_ARENA_OPEN;
2018-11-11 16:44:27 +01:00
else
2019-11-24 22:58:40 +01:00
isCurrent = gSaveBlock2Ptr->frontier.winStreakActiveFlags & STREAK_ARENA_50;
2018-11-11 16:44:27 +01:00
if (!isCurrent)
gSaveBlock2Ptr->frontier.arenaWinStreaks[lvlMode] = 0;
SetDynamicWarp(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, WARP_ID_NONE);
2018-11-11 16:44:27 +01:00
gTrainerBattleOpponent_A = 0;
}
2019-02-08 16:41:36 +01:00
static void GetArenaData(void)
2018-11-11 16:44:27 +01:00
{
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
switch (gSpecialVar_0x8005)
{
case ARENA_DATA_PRIZE:
gSpecialVar_Result = gSaveBlock2Ptr->frontier.arenaPrize;
2018-11-11 16:44:27 +01:00
break;
2019-11-26 23:20:08 +01:00
case ARENA_DATA_WIN_STREAK:
2018-11-11 16:44:27 +01:00
gSpecialVar_Result = gSaveBlock2Ptr->frontier.arenaWinStreaks[lvlMode];
break;
2019-11-26 23:20:08 +01:00
case ARENA_DATA_WIN_STREAK_ACTIVE:
2018-11-11 16:44:27 +01:00
if (lvlMode != FRONTIER_LVL_50)
2019-11-24 22:58:40 +01:00
gSpecialVar_Result = gSaveBlock2Ptr->frontier.winStreakActiveFlags & STREAK_ARENA_OPEN;
2018-11-11 16:44:27 +01:00
else
2019-11-24 22:58:40 +01:00
gSpecialVar_Result = gSaveBlock2Ptr->frontier.winStreakActiveFlags & STREAK_ARENA_50;
2018-11-11 16:44:27 +01:00
break;
}
}
2019-02-08 16:41:36 +01:00
static void SetArenaData(void)
2018-11-11 16:44:27 +01:00
{
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
switch (gSpecialVar_0x8005)
{
case ARENA_DATA_PRIZE:
gSaveBlock2Ptr->frontier.arenaPrize = gSpecialVar_0x8006;
2018-11-11 16:44:27 +01:00
break;
2019-11-26 23:20:08 +01:00
case ARENA_DATA_WIN_STREAK:
2018-11-11 16:44:27 +01:00
gSaveBlock2Ptr->frontier.arenaWinStreaks[lvlMode] = gSpecialVar_0x8006;
break;
2019-11-26 23:20:08 +01:00
case ARENA_DATA_WIN_STREAK_ACTIVE:
2018-11-11 16:44:27 +01:00
if (lvlMode != FRONTIER_LVL_50)
{
if (gSpecialVar_0x8006)
2019-11-24 22:58:40 +01:00
gSaveBlock2Ptr->frontier.winStreakActiveFlags |= STREAK_ARENA_OPEN;
2018-11-11 16:44:27 +01:00
else
2019-11-24 22:58:40 +01:00
gSaveBlock2Ptr->frontier.winStreakActiveFlags &= ~(STREAK_ARENA_OPEN);
2018-11-11 16:44:27 +01:00
}
else
{
if (gSpecialVar_0x8006)
2019-11-24 22:58:40 +01:00
gSaveBlock2Ptr->frontier.winStreakActiveFlags |= STREAK_ARENA_50;
2018-11-11 16:44:27 +01:00
else
2019-11-24 22:58:40 +01:00
gSaveBlock2Ptr->frontier.winStreakActiveFlags &= ~(STREAK_ARENA_50);
2018-11-11 16:44:27 +01:00
}
break;
}
}
2019-11-26 23:20:08 +01:00
static void SaveArenaChallenge(void)
2018-11-11 16:44:27 +01:00
{
2019-11-24 22:58:40 +01:00
gSaveBlock2Ptr->frontier.challengeStatus = gSpecialVar_0x8005;
2018-11-11 16:44:27 +01:00
VarSet(VAR_TEMP_0, 0);
2019-11-24 22:58:40 +01:00
gSaveBlock2Ptr->frontier.challengePaused = TRUE;
SaveGameFrontier();
2018-11-11 16:44:27 +01:00
}
static void SetArenaPrize(void)
2018-11-11 16:44:27 +01:00
{
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
if (gSaveBlock2Ptr->frontier.arenaWinStreaks[lvlMode] > 41)
gSaveBlock2Ptr->frontier.arenaPrize = sLongStreakPrizeItems[Random() % ARRAY_COUNT(sLongStreakPrizeItems)];
2018-11-11 16:44:27 +01:00
else
gSaveBlock2Ptr->frontier.arenaPrize = sShortStreakPrizeItems[Random() % ARRAY_COUNT(sShortStreakPrizeItems)];
2018-11-11 16:44:27 +01:00
}
static void GiveArenaPrize(void)
2018-11-11 16:44:27 +01:00
{
if (AddBagItem(gSaveBlock2Ptr->frontier.arenaPrize, 1) == TRUE)
2018-11-11 16:44:27 +01:00
{
CopyItemName(gSaveBlock2Ptr->frontier.arenaPrize, gStringVar1);
gSaveBlock2Ptr->frontier.arenaPrize = ITEM_NONE;
2018-11-11 16:44:27 +01:00
gSpecialVar_Result = TRUE;
}
else
{
gSpecialVar_Result = FALSE;
}
}
2019-02-08 16:41:36 +01:00
static void BufferArenaOpponentName(void)
2018-11-11 16:44:27 +01:00
{
GetFrontierTrainerName(gStringVar1, gTrainerBattleOpponent_A);
}
2019-02-08 16:41:36 +01:00
void DrawArenaRefereeTextBox(void)
2018-11-11 16:44:27 +01:00
{
u8 width = 27;
u8 palNum = 7;
FillBgTilemapBufferRect(0, 0, 254, 14, 1, 6, palNum);
FillBgTilemapBufferRect(0, 0, 32, 14, 1, 6, palNum);
FillBgTilemapBufferRect(0, 0x31, 0, 14, 1, 1, palNum);
FillBgTilemapBufferRect(0, 0x33, 1, 14, 1, 1, palNum);
FillBgTilemapBufferRect(0, 0x34, 2, 14, width, 1, palNum);
width++;
FillBgTilemapBufferRect(0, 0x35, 28, 14, 1, 1, palNum);
FillBgTilemapBufferRect(0, 0x36, 29, 14, 1, 1, palNum);
FillBgTilemapBufferRect(0, 0x37, 0, 15, 1, 5, palNum);
FillBgTilemapBufferRect(0, 0x39, 1, 15, width, 5, palNum);
FillBgTilemapBufferRect(0, 0x3A, 29, 15, 1, 5, palNum);
FillBgTilemapBufferRect(0, 0x831, 0, 19, 1, 1, palNum);
FillBgTilemapBufferRect(0, 0x833, 1, 19, 1, 1, palNum);
FillBgTilemapBufferRect(0, 0x834, 2, 19, width - 2, 1, palNum);
FillBgTilemapBufferRect(0, 0x835, 28, 19, 1, 1, palNum);
FillBgTilemapBufferRect(0, 0x836, 29, 19, 1, 1, palNum);
}
2021-09-24 20:30:15 +02:00
void EraseArenaRefereeTextBox(void)
2018-11-11 16:44:27 +01:00
{
u8 width;
u8 height;
u8 palNum = 0;
FillBgTilemapBufferRect(0, 3, 0, 14, 1, 1, palNum);
height = 4;
FillBgTilemapBufferRect(0, 4, 1, 14, 1, 1, palNum);
width = 27;
FillBgTilemapBufferRect(0, 5, 2, 14, width, 1, palNum);
FillBgTilemapBufferRect(0, 6, 28, 14, 1, 1, palNum);
FillBgTilemapBufferRect(0, 7, 29, 14, 1, 1, palNum);
FillBgTilemapBufferRect(0, 8, 0, 15, 1, height, palNum);
FillBgTilemapBufferRect(0, 9, 1, 15, 1, height, palNum);
FillBgTilemapBufferRect(0, 0xA, 2, 15, width, height, palNum);
FillBgTilemapBufferRect(0, 0xB, 28, 15, 1, height, palNum);
FillBgTilemapBufferRect(0, 0xC, 29, 15, 1, height, palNum);
FillBgTilemapBufferRect(0, 0xD, 0, 19, 1, 1, palNum);
FillBgTilemapBufferRect(0, 0xE, 1, 19, 1, 1, palNum);
FillBgTilemapBufferRect(0, 0xF, 2, 19, width, 1, palNum);
FillBgTilemapBufferRect(0, 0x10, 28, 19, 1, 1, palNum);
FillBgTilemapBufferRect(0, 0x11, 29, 19, 1, 1, palNum);
}