mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-16 19:47:35 +01:00
Refactor battle intro, allow to speed it up
This commit is contained in:
parent
c23b1acc5e
commit
bd817d70d6
@ -584,6 +584,7 @@ struct BattleStruct
|
||||
struct MegaEvolutionData mega;
|
||||
const u8 *trainerSlideMsg;
|
||||
bool8 trainerSlideLowHpMsgDone;
|
||||
u8 introState;
|
||||
};
|
||||
|
||||
#define GET_MOVE_TYPE(move, typeArg) \
|
||||
|
@ -43,6 +43,7 @@ void PressurePPLose(u8 bankDef, u8 bankAtk, u16 move);
|
||||
void PressurePPLoseOnUsingPerishSong(u8 bankAtk);
|
||||
void PressurePPLoseOnUsingImprision(u8 bankAtk);
|
||||
void MarkAllBattlersForControllerExec(void); // unused
|
||||
bool32 IsBattlerMarkedForControllerExec(u8 battlerId);
|
||||
void MarkBattlerForControllerExec(u8 battlerId);
|
||||
void sub_803F850(u8 arg0);
|
||||
void CancelMultiTurnMoves(u8 battlerId);
|
||||
|
@ -15,4 +15,6 @@
|
||||
#define B_EXP_CATCH GEN_6 // Starting from gen6, pokemon get experience from catching.
|
||||
#define B_ABILITY_POP_UP GEN_6 // Starting from gen5, the pokemon abilities are displayed in a pop-up, when they activate in battle.
|
||||
|
||||
#define B_FAST_INTRO TRUE // If set to TRUE, battle intro texts print at the same time as animation of a pokemon, as opposing to waiting for the animation to end.
|
||||
|
||||
#endif // GUARD_CONSTANTS_BATTLE_CONFIG_H
|
||||
|
@ -117,18 +117,7 @@ static void SpecialStatusesClear(void);
|
||||
static void TurnValuesCleanUp(bool8 var0);
|
||||
static void SpriteCB_BounceEffect(struct Sprite *sprite);
|
||||
static void BattleStartClearSetData(void);
|
||||
static void BattleIntroGetMonsData(void);
|
||||
static void BattleIntroPrepareBackgroundSlide(void);
|
||||
static void BattleIntroDrawTrainersOrMonsSprites(void);
|
||||
static void BattleIntroDrawPartySummaryScreens(void);
|
||||
static void BattleIntroPrintTrainerWantsToBattle(void);
|
||||
static void BattleIntroPrintWildMonAttacked(void);
|
||||
static void BattleIntroPrintOpponentSendsOut(void);
|
||||
static void BattleIntroPrintPlayerSendsOut(void);
|
||||
static void BattleIntroOpponent1SendsOutMonAnimation(void);
|
||||
static void BattleIntroOpponent2SendsOutMonAnimation(void);
|
||||
static void BattleIntroRecordMonsToDex(void);
|
||||
static void BattleIntroPlayer1SendsOutMonAnimation(void);
|
||||
static void DoBattleIntro(void);
|
||||
static void TryDoEventsBeforeFirstTurn(void);
|
||||
static void HandleTurnActionSelectionState(void);
|
||||
static void RunTurnActionsFunctions(void);
|
||||
@ -2013,12 +2002,6 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir
|
||||
return gTrainers[trainerNum].partySize;
|
||||
}
|
||||
|
||||
void sub_8038A04(void) // unused
|
||||
{
|
||||
if (REG_VCOUNT < 0xA0 && REG_VCOUNT >= 0x6F)
|
||||
SetGpuReg(REG_OFFSET_BG0CNT, 0x9800);
|
||||
}
|
||||
|
||||
void VBlankCB_Battle(void)
|
||||
{
|
||||
// Change gRngSeed every vblank unless the battle could be recorded.
|
||||
@ -2661,13 +2644,6 @@ void SpriteCallbackDummy_2(struct Sprite *sprite)
|
||||
|
||||
}
|
||||
|
||||
static void sub_80398BC(struct Sprite *sprite) // unused?
|
||||
{
|
||||
sprite->data[3] = 6;
|
||||
sprite->data[4] = 1;
|
||||
sprite->callback = sub_80398D0;
|
||||
}
|
||||
|
||||
static void sub_80398D0(struct Sprite *sprite)
|
||||
{
|
||||
sprite->data[4]--;
|
||||
@ -2958,7 +2934,8 @@ void BeginBattleIntro(void)
|
||||
{
|
||||
BattleStartClearSetData();
|
||||
gBattleCommunication[1] = 0;
|
||||
gBattleMainFunc = BattleIntroGetMonsData;
|
||||
gBattleStruct->introState = 0;
|
||||
gBattleMainFunc = DoBattleIntro;
|
||||
}
|
||||
|
||||
static void BattleMainCB1(void)
|
||||
@ -3311,550 +3288,323 @@ void FaintClearSetData(void)
|
||||
UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]);
|
||||
}
|
||||
|
||||
static void BattleIntroGetMonsData(void)
|
||||
static void DoBattleIntro(void)
|
||||
{
|
||||
switch (gBattleCommunication[MULTIUSE_STATE])
|
||||
s32 i;
|
||||
u8 *state = &gBattleStruct->introState;
|
||||
|
||||
switch (*state)
|
||||
{
|
||||
case 0:
|
||||
case 0: // Get Data of all battlers.
|
||||
gActiveBattler = gBattleCommunication[1];
|
||||
BtlController_EmitGetMonData(0, REQUEST_ALL_BATTLE, 0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
gBattleCommunication[MULTIUSE_STATE]++;
|
||||
(*state)++;
|
||||
break;
|
||||
case 1:
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
case 1: // Loop through all battlers.
|
||||
if (!gBattleControllerExecFlags)
|
||||
{
|
||||
gBattleCommunication[1]++;
|
||||
if (gBattleCommunication[1] == gBattlersCount)
|
||||
gBattleMainFunc = BattleIntroPrepareBackgroundSlide;
|
||||
if (++gBattleCommunication[1] == gBattlersCount)
|
||||
(*state)++;
|
||||
else
|
||||
gBattleCommunication[MULTIUSE_STATE] = 0;
|
||||
*state = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void BattleIntroPrepareBackgroundSlide(void)
|
||||
{
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
{
|
||||
gActiveBattler = GetBattlerAtPosition(0);
|
||||
BtlController_EmitIntroSlide(0, gBattleTerrain);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
gBattleMainFunc = BattleIntroDrawTrainersOrMonsSprites;
|
||||
gBattleCommunication[0] = 0;
|
||||
gBattleCommunication[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void BattleIntroDrawTrainersOrMonsSprites(void)
|
||||
{
|
||||
u8 *ptr;
|
||||
s32 i;
|
||||
|
||||
if (gBattleControllerExecFlags)
|
||||
return;
|
||||
|
||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||
{
|
||||
if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI)
|
||||
&& GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
|
||||
case 2: // Start graphical intro slide.
|
||||
if (!gBattleControllerExecFlags)
|
||||
{
|
||||
ptr = (u8 *)&gBattleMons[gActiveBattler];
|
||||
for (i = 0; i < sizeof(struct BattlePokemon); i++)
|
||||
ptr[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
u16* hpOnSwitchout;
|
||||
|
||||
ptr = (u8 *)&gBattleMons[gActiveBattler];
|
||||
for (i = 0; i < sizeof(struct BattlePokemon); i++)
|
||||
ptr[i] = gBattleBufferB[gActiveBattler][4 + i];
|
||||
|
||||
gBattleMons[gActiveBattler].type1 = gBaseStats[gBattleMons[gActiveBattler].species].type1;
|
||||
gBattleMons[gActiveBattler].type2 = gBaseStats[gBattleMons[gActiveBattler].species].type2;
|
||||
gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY;
|
||||
gBattleMons[gActiveBattler].ability = GetAbilityBySpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].altAbility);
|
||||
hpOnSwitchout = &gBattleStruct->hpOnSwitchout[GetBattlerSide(gActiveBattler)];
|
||||
*hpOnSwitchout = gBattleMons[gActiveBattler].hp;
|
||||
for (i = 0; i < NUM_BATTLE_STATS; i++)
|
||||
gBattleMons[gActiveBattler].statStages[i] = 6;
|
||||
gBattleMons[gActiveBattler].status2 = 0;
|
||||
}
|
||||
|
||||
if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_LEFT)
|
||||
{
|
||||
BtlController_EmitDrawTrainerPic(0);
|
||||
gActiveBattler = GetBattlerAtPosition(0);
|
||||
BtlController_EmitIntroSlide(0, gBattleTerrain);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
gBattleCommunication[0] = 0;
|
||||
gBattleCommunication[1] = 0;
|
||||
(*state)++;
|
||||
}
|
||||
break;
|
||||
case 3: // Wait for intro slide.
|
||||
if (!gBattleControllerExecFlags)
|
||||
(*state)++;
|
||||
break;
|
||||
case 4: // Copy battler data gotten in cases 0 and 1. Draw trainer/mon sprite.
|
||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||
{
|
||||
if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI) && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
|
||||
{
|
||||
memset(&gBattleMons[gActiveBattler], 0, sizeof(struct BattlePokemon));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&gBattleMons[gActiveBattler], &gBattleBufferB[gActiveBattler][4], sizeof(struct BattlePokemon));
|
||||
gBattleMons[gActiveBattler].type1 = gBaseStats[gBattleMons[gActiveBattler].species].type1;
|
||||
gBattleMons[gActiveBattler].type2 = gBaseStats[gBattleMons[gActiveBattler].species].type2;
|
||||
gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY;
|
||||
gBattleMons[gActiveBattler].ability = GetAbilityBySpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].altAbility);
|
||||
gBattleStruct->hpOnSwitchout[GetBattlerSide(gActiveBattler)] = gBattleMons[gActiveBattler].hp;
|
||||
gBattleMons[gActiveBattler].status2 = 0;
|
||||
for (i = 0; i < NUM_BATTLE_STATS; i++)
|
||||
gBattleMons[gActiveBattler].statStages[i] = 6;
|
||||
}
|
||||
|
||||
// Draw sprite.
|
||||
switch (GetBattlerPosition(gActiveBattler))
|
||||
{
|
||||
case B_POSITION_PLAYER_LEFT: // player sprite
|
||||
BtlController_EmitDrawTrainerPic(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
break;
|
||||
case B_POSITION_OPPONENT_LEFT:
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER) // opponent 1 sprite
|
||||
{
|
||||
BtlController_EmitDrawTrainerPic(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
else // wild mon 1
|
||||
{
|
||||
BtlController_EmitLoadMonSprite(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
gBattleResults.lastOpponentSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES, NULL);
|
||||
}
|
||||
break;
|
||||
case B_POSITION_PLAYER_RIGHT:
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER)) // partner sprite
|
||||
{
|
||||
BtlController_EmitDrawTrainerPic(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
break;
|
||||
case B_POSITION_OPPONENT_RIGHT:
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
{
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS)) // opponent 2 if exists
|
||||
{
|
||||
BtlController_EmitDrawTrainerPic(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
}
|
||||
else // wild mon 2
|
||||
{
|
||||
BtlController_EmitLoadMonSprite(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
gBattleResults.lastOpponentSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES, NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
|
||||
BattleArena_InitPoints();
|
||||
}
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
{
|
||||
if (GetBattlerPosition(gActiveBattler) == B_POSITION_OPPONENT_LEFT)
|
||||
(*state)++;
|
||||
}
|
||||
else // Skip party summary since it is a wild battle.
|
||||
{
|
||||
if (B_FAST_INTRO)
|
||||
*state = 7; // Don't wait for sprite, print message at the same time.
|
||||
else
|
||||
*state = 6; // Wait for sprite to load.
|
||||
}
|
||||
break;
|
||||
case 5: // draw party summary in trainer battles
|
||||
if (!gBattleControllerExecFlags)
|
||||
{
|
||||
struct HpAndStatus hpStatus[PARTY_SIZE];
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
BtlController_EmitDrawTrainerPic(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE
|
||||
|| GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
|
||||
{
|
||||
hpStatus[i].hp = 0xFFFF;
|
||||
hpStatus[i].status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hpStatus[i].hp = GetMonData(&gEnemyParty[i], MON_DATA_HP);
|
||||
hpStatus[i].status = GetMonData(&gEnemyParty[i], MON_DATA_STATUS);
|
||||
}
|
||||
}
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER
|
||||
| BATTLE_TYPE_FRONTIER
|
||||
| BATTLE_TYPE_LINK
|
||||
| BATTLE_TYPE_x2000000
|
||||
| BATTLE_TYPE_TRAINER_HILL)))
|
||||
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
BtlController_EmitDrawPartyStatusSummary(0, hpStatus, 0x80);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBattler].species), FLAG_SET_SEEN, gBattleMons[gActiveBattler].personality);
|
||||
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_NONE
|
||||
|| GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
|
||||
{
|
||||
hpStatus[i].hp = 0xFFFF;
|
||||
hpStatus[i].status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hpStatus[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
|
||||
hpStatus[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
BtlController_EmitDrawPartyStatusSummary(0, hpStatus, 0x80);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
|
||||
(*state)++;
|
||||
}
|
||||
break;
|
||||
case 6: // wait for previous action to complete
|
||||
if (!gBattleControllerExecFlags)
|
||||
(*state)++;
|
||||
break;
|
||||
case 7: // print battle intro message
|
||||
if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)))
|
||||
{
|
||||
PrepareStringBattle(STRINGID_INTROMSG, GetBattlerAtPosition(B_POSITION_PLAYER_LEFT));
|
||||
(*state)++;
|
||||
}
|
||||
break;
|
||||
case 8: // wait for intro message to be printed
|
||||
if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)))
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
{
|
||||
(*state)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (B_FAST_INTRO)
|
||||
*state = 15; // Wait for text to be printed.
|
||||
else
|
||||
*state = 14; // Wait for text and sprite.
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 9: // print opponent sends out
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000))
|
||||
PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(B_POSITION_PLAYER_LEFT));
|
||||
else
|
||||
PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT));
|
||||
(*state)++;
|
||||
break;
|
||||
case 10: // wait for opponent sends out text
|
||||
if (!gBattleControllerExecFlags)
|
||||
(*state)++;
|
||||
break;
|
||||
case 11: // first opponent's mon send out animation
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000))
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
else
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
|
||||
BtlController_EmitIntroTrainerBallThrow(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
(*state)++;
|
||||
break;
|
||||
case 12: // nothing
|
||||
(*state)++;
|
||||
case 13: // second opponent's mon send out
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS))
|
||||
{
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT)
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000))
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
|
||||
else
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
||||
|
||||
BtlController_EmitIntroTrainerBallThrow(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
if (B_FAST_INTRO && !(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_x2000000 | BATTLE_TYPE_x80000000 | BATTLE_TYPE_LINK)))
|
||||
*state = 15; // Print at the same time as trainer sends out second mon.
|
||||
else
|
||||
(*state)++;
|
||||
break;
|
||||
case 14: // wait for opponent 2 send out
|
||||
if (!gBattleControllerExecFlags)
|
||||
(*state)++;
|
||||
break;
|
||||
case 15: // wait for wild battle message
|
||||
if (!IsBattlerMarkedForControllerExec(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)))
|
||||
(*state)++;
|
||||
break;
|
||||
case 16: // print player sends out
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI))
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000))
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
else
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
|
||||
// A hack that makes fast intro work in trainer battles too.
|
||||
if (B_FAST_INTRO
|
||||
&& gBattleTypeFlags & BATTLE_TYPE_TRAINER
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_RECORDED | BATTLE_TYPE_x2000000 | BATTLE_TYPE_x80000000 | BATTLE_TYPE_LINK))
|
||||
&& gSprites[gHealthboxSpriteIds[gActiveBattler ^ BIT_SIDE]].callback == SpriteCallbackDummy)
|
||||
{
|
||||
if (!(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER
|
||||
| BATTLE_TYPE_FRONTIER
|
||||
| BATTLE_TYPE_LINK
|
||||
| BATTLE_TYPE_x2000000
|
||||
| BATTLE_TYPE_TRAINER_HILL)))
|
||||
return;
|
||||
}
|
||||
|
||||
PrepareStringBattle(STRINGID_INTROSENDOUT, gActiveBattler);
|
||||
}
|
||||
(*state)++;
|
||||
break;
|
||||
case 17: // wait for player send out message
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleControllerExecFlags))
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000))
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
else
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
|
||||
if (!IsBattlerMarkedForControllerExec(gActiveBattler))
|
||||
(*state)++;
|
||||
}
|
||||
break;
|
||||
case 18: // player 1 send out
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000))
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
else
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
|
||||
BtlController_EmitIntroTrainerBallThrow(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
(*state)++;
|
||||
break;
|
||||
case 19: // player 2 send out
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER))
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x2000000 && !(gBattleTypeFlags & BATTLE_TYPE_x80000000))
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
|
||||
else
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
|
||||
|
||||
BtlController_EmitIntroTrainerBallThrow(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
(*state)++;
|
||||
break;
|
||||
case 20: // set dex and battle vars
|
||||
if (!gBattleControllerExecFlags)
|
||||
{
|
||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||
{
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER
|
||||
| BATTLE_TYPE_FRONTIER
|
||||
| BATTLE_TYPE_LINK
|
||||
| BATTLE_TYPE_x2000000
|
||||
| BATTLE_TYPE_TRAINER_HILL)))
|
||||
{
|
||||
HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBattler].species), FLAG_SET_SEEN, gBattleMons[gActiveBattler].personality);
|
||||
}
|
||||
BtlController_EmitLoadMonSprite(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
gBattleResults.lastOpponentSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES, NULL);
|
||||
}
|
||||
|
||||
gBattleStruct->switchInAbilitiesCounter = 0;
|
||||
gBattleStruct->switchInItemsCounter = 0;
|
||||
gBattleStruct->overworldWeatherDone = FALSE;
|
||||
|
||||
gBattleMainFunc = TryDoEventsBeforeFirstTurn;
|
||||
}
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
|
||||
{
|
||||
if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT
|
||||
|| (GetBattlerPosition(gActiveBattler) == B_POSITION_OPPONENT_RIGHT && gBattleTypeFlags & BATTLE_TYPE_TRAINER))
|
||||
{
|
||||
BtlController_EmitDrawTrainerPic(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
}
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetBattlerPosition(gActiveBattler) == B_POSITION_OPPONENT_RIGHT)
|
||||
{
|
||||
BtlController_EmitDrawTrainerPic(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
|
||||
BattleArena_InitPoints();
|
||||
}
|
||||
gBattleMainFunc = BattleIntroDrawPartySummaryScreens;
|
||||
}
|
||||
|
||||
static void BattleIntroDrawPartySummaryScreens(void)
|
||||
{
|
||||
s32 i;
|
||||
struct HpAndStatus hpStatus[PARTY_SIZE];
|
||||
|
||||
if (gBattleControllerExecFlags)
|
||||
return;
|
||||
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
|
||||
{
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE
|
||||
|| GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
|
||||
{
|
||||
hpStatus[i].hp = 0xFFFF;
|
||||
hpStatus[i].status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hpStatus[i].hp = GetMonData(&gEnemyParty[i], MON_DATA_HP);
|
||||
hpStatus[i].status = GetMonData(&gEnemyParty[i], MON_DATA_STATUS);
|
||||
}
|
||||
}
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
BtlController_EmitDrawPartyStatusSummary(0, hpStatus, 0x80);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_NONE
|
||||
|| GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
|
||||
{
|
||||
hpStatus[i].hp = 0xFFFF;
|
||||
hpStatus[i].status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hpStatus[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
|
||||
hpStatus[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS);
|
||||
}
|
||||
}
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
|
||||
BtlController_EmitDrawPartyStatusSummary(0, hpStatus, 0x80);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
|
||||
gBattleMainFunc = BattleIntroPrintTrainerWantsToBattle;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The struct gets set here, but nothing is ever done with it since
|
||||
// wild battles don't show the party summary.
|
||||
// Still, there's no point in having dead code.
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_NONE
|
||||
|| GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
|
||||
{
|
||||
hpStatus[i].hp = 0xFFFF;
|
||||
hpStatus[i].status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hpStatus[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
|
||||
hpStatus[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
gBattleMainFunc = BattleIntroPrintWildMonAttacked;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void BattleIntroPrintTrainerWantsToBattle(void)
|
||||
{
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
{
|
||||
gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
|
||||
PrepareStringBattle(STRINGID_INTROMSG, gActiveBattler);
|
||||
gBattleMainFunc = BattleIntroPrintOpponentSendsOut;
|
||||
}
|
||||
}
|
||||
|
||||
static void BattleIntroPrintWildMonAttacked(void)
|
||||
{
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
{
|
||||
gBattleMainFunc = BattleIntroPrintPlayerSendsOut;
|
||||
PrepareStringBattle(STRINGID_INTROMSG, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void BattleIntroPrintOpponentSendsOut(void)
|
||||
{
|
||||
u32 position;
|
||||
|
||||
if (gBattleControllerExecFlags)
|
||||
return;
|
||||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
|
||||
position = B_POSITION_OPPONENT_LEFT;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
|
||||
position = B_POSITION_OPPONENT_LEFT;
|
||||
else
|
||||
position = B_POSITION_PLAYER_LEFT;
|
||||
}
|
||||
else
|
||||
position = B_POSITION_OPPONENT_LEFT;
|
||||
|
||||
PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(position));
|
||||
gBattleMainFunc = BattleIntroOpponent1SendsOutMonAnimation;
|
||||
}
|
||||
|
||||
static void BattleIntroOpponent2SendsOutMonAnimation(void)
|
||||
{
|
||||
u32 position;
|
||||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
|
||||
position = B_POSITION_OPPONENT_RIGHT;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
|
||||
position = B_POSITION_OPPONENT_RIGHT;
|
||||
else
|
||||
position = B_POSITION_PLAYER_RIGHT;
|
||||
}
|
||||
else
|
||||
position = B_POSITION_OPPONENT_RIGHT;
|
||||
|
||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||
{
|
||||
if (GetBattlerPosition(gActiveBattler) == position)
|
||||
{
|
||||
BtlController_EmitIntroTrainerBallThrow(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
}
|
||||
|
||||
gBattleMainFunc = BattleIntroRecordMonsToDex;
|
||||
}
|
||||
|
||||
#ifdef NONMATCHING
|
||||
static void BattleIntroOpponent1SendsOutMonAnimation(void)
|
||||
{
|
||||
u32 position;
|
||||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
|
||||
position = B_POSITION_OPPONENT_LEFT;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
|
||||
position = B_POSITION_OPPONENT_LEFT;
|
||||
else
|
||||
position = B_POSITION_PLAYER_LEFT;
|
||||
}
|
||||
else
|
||||
position = B_POSITION_OPPONENT_LEFT;
|
||||
|
||||
if (gBattleControllerExecFlags)
|
||||
return;
|
||||
|
||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||
{
|
||||
if (GetBattlerPosition(gActiveBattler) == position)
|
||||
{
|
||||
BtlController_EmitIntroTrainerBallThrow(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS))
|
||||
{
|
||||
gBattleMainFunc = BattleIntroOpponent2SendsOutMonAnimation;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gBattleMainFunc = BattleIntroRecordMonsToDex;
|
||||
}
|
||||
#else
|
||||
NAKED
|
||||
static void BattleIntroOpponent1SendsOutMonAnimation(void)
|
||||
{
|
||||
asm(".syntax unified\n\
|
||||
push {r4-r6,lr}\n\
|
||||
ldr r0, =gBattleTypeFlags\n\
|
||||
ldr r2, [r0]\n\
|
||||
movs r0, 0x80\n\
|
||||
lsls r0, 17\n\
|
||||
ands r0, r2\n\
|
||||
cmp r0, 0\n\
|
||||
beq _0803B298\n\
|
||||
movs r0, 0x80\n\
|
||||
lsls r0, 18\n\
|
||||
ands r0, r2\n\
|
||||
cmp r0, 0\n\
|
||||
beq _0803B298\n\
|
||||
movs r1, 0x80\n\
|
||||
lsls r1, 24\n\
|
||||
ands r1, r2\n\
|
||||
negs r0, r1\n\
|
||||
orrs r0, r1\n\
|
||||
lsrs r5, r0, 31\n\
|
||||
b _0803B29A\n\
|
||||
.pool\n\
|
||||
_0803B288:\n\
|
||||
ldr r1, =gBattleMainFunc\n\
|
||||
ldr r0, =BattleIntroOpponent2SendsOutMonAnimation\n\
|
||||
b _0803B2F0\n\
|
||||
.pool\n\
|
||||
_0803B298:\n\
|
||||
movs r5, 0x1\n\
|
||||
_0803B29A:\n\
|
||||
ldr r0, =gBattleControllerExecFlags\n\
|
||||
ldr r2, [r0]\n\
|
||||
cmp r2, 0\n\
|
||||
bne _0803B2F2\n\
|
||||
ldr r0, =gActiveBattler\n\
|
||||
strb r2, [r0]\n\
|
||||
ldr r1, =gBattlersCount\n\
|
||||
adds r4, r0, 0\n\
|
||||
ldrb r1, [r1]\n\
|
||||
cmp r2, r1\n\
|
||||
bcs _0803B2EC\n\
|
||||
adds r6, r4, 0\n\
|
||||
_0803B2B2:\n\
|
||||
ldrb r0, [r4]\n\
|
||||
bl GetBattlerPosition\n\
|
||||
lsls r0, 24\n\
|
||||
lsrs r0, 24\n\
|
||||
cmp r0, r5\n\
|
||||
bne _0803B2D8\n\
|
||||
movs r0, 0\n\
|
||||
bl BtlController_EmitIntroTrainerBallThrow\n\
|
||||
ldrb r0, [r4]\n\
|
||||
bl MarkBattlerForControllerExec\n\
|
||||
ldr r0, =gBattleTypeFlags\n\
|
||||
ldr r0, [r0]\n\
|
||||
ldr r1, =0x00008040\n\
|
||||
ands r0, r1\n\
|
||||
cmp r0, 0\n\
|
||||
bne _0803B288\n\
|
||||
_0803B2D8:\n\
|
||||
ldrb r0, [r6]\n\
|
||||
adds r0, 0x1\n\
|
||||
strb r0, [r6]\n\
|
||||
ldr r1, =gBattlersCount\n\
|
||||
lsls r0, 24\n\
|
||||
lsrs r0, 24\n\
|
||||
ldr r4, =gActiveBattler\n\
|
||||
ldrb r1, [r1]\n\
|
||||
cmp r0, r1\n\
|
||||
bcc _0803B2B2\n\
|
||||
_0803B2EC:\n\
|
||||
ldr r1, =gBattleMainFunc\n\
|
||||
ldr r0, =BattleIntroRecordMonsToDex\n\
|
||||
_0803B2F0:\n\
|
||||
str r0, [r1]\n\
|
||||
_0803B2F2:\n\
|
||||
pop {r4-r6}\n\
|
||||
pop {r0}\n\
|
||||
bx r0\n\
|
||||
.pool\n\
|
||||
.syntax divided");
|
||||
}
|
||||
#endif // NONMATCHING
|
||||
|
||||
static void BattleIntroRecordMonsToDex(void)
|
||||
{
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
{
|
||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||
{
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT
|
||||
&& !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER
|
||||
| BATTLE_TYPE_FRONTIER
|
||||
| BATTLE_TYPE_LINK
|
||||
| BATTLE_TYPE_x2000000
|
||||
| BATTLE_TYPE_TRAINER_HILL)))
|
||||
{
|
||||
HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBattler].species), FLAG_SET_SEEN, gBattleMons[gActiveBattler].personality);
|
||||
}
|
||||
}
|
||||
gBattleMainFunc = BattleIntroPrintPlayerSendsOut;
|
||||
}
|
||||
}
|
||||
|
||||
void sub_803B3AC(void) // unused
|
||||
{
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
gBattleMainFunc = BattleIntroPrintPlayerSendsOut;
|
||||
}
|
||||
|
||||
static void BattleIntroPrintPlayerSendsOut(void)
|
||||
{
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
{
|
||||
u8 position;
|
||||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
|
||||
position = B_POSITION_PLAYER_LEFT;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
|
||||
position = B_POSITION_PLAYER_LEFT;
|
||||
else
|
||||
position = B_POSITION_OPPONENT_LEFT;
|
||||
}
|
||||
else
|
||||
position = B_POSITION_PLAYER_LEFT;
|
||||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI))
|
||||
PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(position));
|
||||
|
||||
gBattleMainFunc = BattleIntroPlayer1SendsOutMonAnimation;
|
||||
}
|
||||
}
|
||||
|
||||
static void BattleIntroPlayer2SendsOutMonAnimation(void)
|
||||
{
|
||||
u32 position;
|
||||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
|
||||
position = B_POSITION_PLAYER_RIGHT;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
|
||||
position = B_POSITION_PLAYER_RIGHT;
|
||||
else
|
||||
position = B_POSITION_OPPONENT_RIGHT;
|
||||
}
|
||||
else
|
||||
position = B_POSITION_PLAYER_RIGHT;
|
||||
|
||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||
{
|
||||
if (GetBattlerPosition(gActiveBattler) == position)
|
||||
{
|
||||
BtlController_EmitIntroTrainerBallThrow(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
}
|
||||
|
||||
gBattleStruct->switchInAbilitiesCounter = 0;
|
||||
gBattleStruct->switchInItemsCounter = 0;
|
||||
gBattleStruct->overworldWeatherDone = FALSE;
|
||||
|
||||
gBattleMainFunc = TryDoEventsBeforeFirstTurn;
|
||||
}
|
||||
|
||||
static void BattleIntroPlayer1SendsOutMonAnimation(void)
|
||||
{
|
||||
u32 position;
|
||||
|
||||
if (!(gBattleTypeFlags & BATTLE_TYPE_RECORDED))
|
||||
position = B_POSITION_PLAYER_LEFT;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_x2000000)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_x80000000)
|
||||
position = B_POSITION_PLAYER_LEFT;
|
||||
else
|
||||
position = B_POSITION_OPPONENT_LEFT;
|
||||
}
|
||||
else
|
||||
position = B_POSITION_PLAYER_LEFT;
|
||||
|
||||
if (gBattleControllerExecFlags)
|
||||
return;
|
||||
|
||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||
{
|
||||
if (GetBattlerPosition(gActiveBattler) == position)
|
||||
{
|
||||
BtlController_EmitIntroTrainerBallThrow(0);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
if (gBattleTypeFlags & (BATTLE_TYPE_MULTI))
|
||||
{
|
||||
gBattleMainFunc = BattleIntroPlayer2SendsOutMonAnimation;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gBattleStruct->switchInAbilitiesCounter = 0;
|
||||
gBattleStruct->switchInItemsCounter = 0;
|
||||
gBattleStruct->overworldWeatherDone = FALSE;
|
||||
|
||||
gBattleMainFunc = TryDoEventsBeforeFirstTurn;
|
||||
}
|
||||
|
||||
void sub_803B598(void) // unused
|
||||
{
|
||||
if (gBattleControllerExecFlags == 0)
|
||||
{
|
||||
for (gActiveBattler = 0; gActiveBattler < gBattlersCount; gActiveBattler++)
|
||||
{
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
|
||||
{
|
||||
BtlController_EmitSwitchInAnim(0, gBattlerPartyIndexes[gActiveBattler], FALSE);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
}
|
||||
}
|
||||
|
||||
gBattleStruct->switchInAbilitiesCounter = 0;
|
||||
gBattleStruct->switchInItemsCounter = 0;
|
||||
gBattleStruct->overworldWeatherDone = FALSE;
|
||||
|
||||
gBattleMainFunc = TryDoEventsBeforeFirstTurn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,6 +440,14 @@ void MarkAllBattlersForControllerExec(void) // unused
|
||||
}
|
||||
}
|
||||
|
||||
bool32 IsBattlerMarkedForControllerExec(u8 battlerId)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
return (gBattleControllerExecFlags & (gBitTable[battlerId] << 0x1C)) != 0;
|
||||
else
|
||||
return (gBattleControllerExecFlags & (gBitTable[battlerId])) != 0;
|
||||
}
|
||||
|
||||
void MarkBattlerForControllerExec(u8 battlerId)
|
||||
{
|
||||
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
|
||||
|
Loading…
Reference in New Issue
Block a user