summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/battle_ai_script_commands.c2
-rw-r--r--src/battle_anim_mons.c10
-rw-r--r--src/battle_controller_oak_old_man.c2295
-rw-r--r--src/battle_controller_opponent.c6
-rw-r--r--src/battle_controller_player.c3
-rw-r--r--src/battle_controllers.c18
-rw-r--r--src/battle_main.c4412
-rw-r--r--src/battle_script_commands.c10
-rw-r--r--src/battle_setup.c1060
-rw-r--r--src/battle_transition.c4
-rw-r--r--src/battle_util2.c1
-rw-r--r--src/berry.c4
-rw-r--r--src/dark.c2
-rw-r--r--src/data/text/abilities.h242
-rw-r--r--src/fame_checker.c3
-rw-r--r--src/field_fadetransition.c18
-rw-r--r--src/fldeff_rocksmash.c1
-rw-r--r--src/ground.c3
-rw-r--r--src/item.c2
-rw-r--r--src/item_use.c5
-rw-r--r--src/link.c2
-rw-r--r--src/map_obj_lock.c2
-rw-r--r--src/metatile_behavior.c12
-rw-r--r--src/mystery_gift_menu.c4
-rw-r--r--src/pokemon.c33
-rw-r--r--src/psychic.c4
-rw-r--r--src/quest_log.c4
-rw-r--r--src/quest_log_8150454.c4
-rw-r--r--src/quest_log_battle.c37
-rw-r--r--src/reshow_battle_screen.c6
-rw-r--r--src/scrcmd.c2
-rw-r--r--src/start_menu.c2
-rw-r--r--src/teachy_tv.c2
-rw-r--r--src/trainer_tower.c2
-rw-r--r--src/unk_8159F40.c4
-rw-r--r--src/vs_seeker.c24
36 files changed, 8128 insertions, 117 deletions
diff --git a/src/battle_ai_script_commands.c b/src/battle_ai_script_commands.c
index c57825b4f..e66fdb2af 100644
--- a/src/battle_ai_script_commands.c
+++ b/src/battle_ai_script_commands.c
@@ -1,6 +1,6 @@
#include "global.h"
#include "battle.h"
-#include "battle_main.h"
+#include "battle_anim.h"
#include "util.h"
#include "item.h"
#include "random.h"
diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c
index e871937e7..c19af4cb7 100644
--- a/src/battle_anim_mons.c
+++ b/src/battle_anim_mons.c
@@ -28,7 +28,7 @@ static u8 GetBattlerSpriteFinal_Y(u8 battlerId, u16 species, bool8 a3);
static void sub_8075658(struct Sprite *sprite);
static void sub_80757E8(struct Sprite *sprite);
static bool8 sub_80758DC(void);
-static void sub_8075EF0(struct Sprite *sprite);
+static void AnimThrowProjectile_Step(struct Sprite *sprite);
static void sub_80760D0(u8 taskId);
static void AnimTask_BlendMonInAndOutSetup(struct Task *task);
static void AnimTask_BlendMonInAndOutStep(u8 taskId);
@@ -1336,7 +1336,7 @@ static u8 GetBattlerAtPosition_(u8 position)
return GetBattlerAtPosition(position);
}
-void sub_8075D9C(struct Sprite *sprite)
+void AnimSpriteOnMonPos(struct Sprite *sprite)
{
bool8 var;
@@ -1390,7 +1390,7 @@ void TranslateAnimSpriteToTargetMonLocation(struct Sprite *sprite)
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
}
-void sub_8075E80(struct Sprite *sprite)
+void AnimThrowProjectile(struct Sprite *sprite)
{
InitSpritePosToAnimAttacker(sprite, 1);
if (GetBattlerSide(gBattleAnimAttacker))
@@ -1400,10 +1400,10 @@ void sub_8075E80(struct Sprite *sprite)
sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3];
sprite->data[5] = gBattleAnimArgs[5];
InitAnimArcTranslation(sprite);
- sprite->callback = sub_8075EF0;
+ sprite->callback = AnimThrowProjectile_Step;
}
-static void sub_8075EF0(struct Sprite *sprite)
+static void AnimThrowProjectile_Step(struct Sprite *sprite)
{
if (TranslateAnimHorizontalArc(sprite))
DestroyAnimSprite(sprite);
diff --git a/src/battle_controller_oak_old_man.c b/src/battle_controller_oak_old_man.c
new file mode 100644
index 000000000..99391ab3e
--- /dev/null
+++ b/src/battle_controller_oak_old_man.c
@@ -0,0 +1,2295 @@
+#include "global.h"
+#include "task.h"
+#include "pokemon.h"
+#include "pokeball.h"
+#include "party_menu.h"
+#include "bg.h"
+#include "data.h"
+#include "palette.h"
+#include "util.h"
+#include "m4a.h"
+#include "link.h"
+#include "sound.h"
+#include "item.h"
+#include "item_menu.h"
+#include "text.h"
+#include "strings.h"
+#include "string_util.h"
+#include "window.h"
+#include "battle.h"
+#include "battle_anim.h"
+#include "battle_controllers.h"
+#include "battle_interface.h"
+#include "battle_message.h"
+#include "reshow_battle_screen.h"
+#include "constants/songs.h"
+#include "constants/items.h"
+
+static void OakOldManHandleGetMonData(void);
+static void OakOldManHandleGetRawMonData(void);
+static void OakOldManHandleSetMonData(void);
+static void OakOldManHandleSetRawMonData(void);
+static void OakOldManHandleLoadMonSprite(void);
+static void OakOldManHandleSwitchInAnim(void);
+static void OakOldManHandleReturnMonToBall(void);
+static void OakOldManHandleDrawTrainerPic(void);
+static void OakOldManHandleTrainerSlide(void);
+static void OakOldManHandleTrainerSlideBack(void);
+static void OakOldManHandleFaintAnimation(void);
+static void OakOldManHandlePaletteFade(void);
+static void OakOldManHandleSuccessBallThrowAnim(void);
+static void OakOldManHandleBallThrowAnim(void);
+static void OakOldManHandlePause(void);
+static void OakOldManHandleMoveAnimation(void);
+static void OakOldManHandlePrintString(void);
+static void OakOldManHandlePrintSelectionString(void);
+static void OakOldManHandleChooseAction(void);
+static void OakOldManHandleUnknownYesNoBox(void);
+static void OakOldManHandleChooseMove(void);
+static void OakOldManHandleChooseItem(void);
+static void OakOldManHandleChoosePokemon(void);
+static void OakOldManHandleCmd23(void);
+static void OakOldManHandleHealthBarUpdate(void);
+static void OakOldManHandleExpUpdate(void);
+static void OakOldManHandleStatusIconUpdate(void);
+static void OakOldManHandleStatusAnimation(void);
+static void OakOldManHandleStatusXor(void);
+static void OakOldManHandleDataTransfer(void);
+static void OakOldManHandleDMA3Transfer(void);
+static void OakOldManHandlePlayBGM(void);
+static void OakOldManHandleCmd32(void);
+static void OakOldManHandleTwoReturnValues(void);
+static void OakOldManHandleChosenMonReturnValue(void);
+static void OakOldManHandleOneReturnValue(void);
+static void OakOldManHandleOneReturnValue_Duplicate(void);
+static void OakOldManHandleCmd37(void);
+static void OakOldManHandleCmd38(void);
+static void OakOldManHandleCmd39(void);
+static void OakOldManHandleCmd40(void);
+static void OakOldManHandleHitAnimation(void);
+static void OakOldManHandleCmd42(void);
+static void OakOldManHandlePlaySE(void);
+static void OakOldManHandlePlayFanfare(void);
+static void OakOldManHandleFaintingCry(void);
+static void OakOldManHandleIntroSlide(void);
+static void OakOldManHandleIntroTrainerBallThrow(void);
+static void OakOldManHandleDrawPartyStatusSummary(void);
+static void OakOldManHandleHidePartyStatusSummary(void);
+static void OakOldManHandleEndBounceEffect(void);
+static void OakOldManHandleSpriteInvisibility(void);
+static void OakOldManHandleBattleAnimation(void);
+static void OakOldManHandleLinkStandbyMsg(void);
+static void OakOldManHandleResetActionMoveSelection(void);
+static void OakOldManHandleCmd55(void);
+static void OakOldManCmdEnd(void);
+
+static void OakOldManBufferRunCommand(void);
+static void OakOldManBufferExecCompleted(void);
+static void WaitForMonSelection(void);
+static void CompleteWhenChoseItem(void);
+static void sub_80E8704(void);
+static void sub_80E7CD8(void);
+static void sub_80E835C(void);
+static void Task_LaunchLvlUpAnim(u8 taskId);
+static void DestroyExpTaskAndCompleteOnInactiveTextPrinter(u8 taskId);
+static void CompleteOnInactiveTextPrinter2(void);
+static void Task_PrepareToGiveExpWithExpBar(u8 taskId);
+static void sub_80E804C(u8 taskId);
+static void Task_UpdateLvlInHealthbox(u8 taskId);
+static void sub_80E85D4(const u8 *text, u8 a1);
+static u32 CopyOakOldManMonData(u8 monId, u8 *dst);
+static void SetOakOldManMonData(u8 monId);
+static void OakOldManDoMoveAnimation(void);
+static void HandleInputChooseAction(void);
+static void sub_80EB0A8(u8 taskId);
+
+static void (*const sOakOldManBufferCommands[CONTROLLER_CMDS_COUNT])(void) =
+{
+ OakOldManHandleGetMonData,
+ OakOldManHandleGetRawMonData,
+ OakOldManHandleSetMonData,
+ OakOldManHandleSetRawMonData,
+ OakOldManHandleLoadMonSprite,
+ OakOldManHandleSwitchInAnim,
+ OakOldManHandleReturnMonToBall,
+ OakOldManHandleDrawTrainerPic,
+ OakOldManHandleTrainerSlide,
+ OakOldManHandleTrainerSlideBack,
+ OakOldManHandleFaintAnimation,
+ OakOldManHandlePaletteFade,
+ OakOldManHandleSuccessBallThrowAnim,
+ OakOldManHandleBallThrowAnim,
+ OakOldManHandlePause,
+ OakOldManHandleMoveAnimation,
+ OakOldManHandlePrintString,
+ OakOldManHandlePrintSelectionString,
+ OakOldManHandleChooseAction,
+ OakOldManHandleUnknownYesNoBox,
+ OakOldManHandleChooseMove,
+ OakOldManHandleChooseItem,
+ OakOldManHandleChoosePokemon,
+ OakOldManHandleCmd23,
+ OakOldManHandleHealthBarUpdate,
+ OakOldManHandleExpUpdate,
+ OakOldManHandleStatusIconUpdate,
+ OakOldManHandleStatusAnimation,
+ OakOldManHandleStatusXor,
+ OakOldManHandleDataTransfer,
+ OakOldManHandleDMA3Transfer,
+ OakOldManHandlePlayBGM,
+ OakOldManHandleCmd32,
+ OakOldManHandleTwoReturnValues,
+ OakOldManHandleChosenMonReturnValue,
+ OakOldManHandleOneReturnValue,
+ OakOldManHandleOneReturnValue_Duplicate,
+ OakOldManHandleCmd37,
+ OakOldManHandleCmd38,
+ OakOldManHandleCmd39,
+ OakOldManHandleCmd40,
+ OakOldManHandleHitAnimation,
+ OakOldManHandleCmd42,
+ OakOldManHandlePlaySE,
+ OakOldManHandlePlayFanfare,
+ OakOldManHandleFaintingCry,
+ OakOldManHandleIntroSlide,
+ OakOldManHandleIntroTrainerBallThrow,
+ OakOldManHandleDrawPartyStatusSummary,
+ OakOldManHandleHidePartyStatusSummary,
+ OakOldManHandleEndBounceEffect,
+ OakOldManHandleSpriteInvisibility,
+ OakOldManHandleBattleAnimation,
+ OakOldManHandleLinkStandbyMsg,
+ OakOldManHandleResetActionMoveSelection,
+ OakOldManHandleCmd55,
+ OakOldManCmdEnd,
+};
+
+static void nullsub_81(void)
+{
+}
+
+void SetControllerToOakOrOldMan(void)
+{
+ gBattlerControllerFuncs[gActiveBattler] = OakOldManBufferRunCommand;
+ gBattleStruct->field_94 = 0;
+ gBattleStruct->field_95 = 0;
+ gBattleStruct->field_96 = 0;
+ gBattleStruct->field_97 = 0;
+}
+
+static void OakOldManBufferRunCommand(void)
+{
+ if (gBattleControllerExecFlags & gBitTable[gActiveBattler])
+ {
+ if (gBattleBufferA[gActiveBattler][0] < ARRAY_COUNT(sOakOldManBufferCommands))
+ sOakOldManBufferCommands[gBattleBufferA[gActiveBattler][0]]();
+ else
+ OakOldManBufferExecCompleted();
+ }
+}
+
+static void HandleInputChooseAction(void)
+{
+ u16 itemId = gBattleBufferA[gActiveBattler][2] | (gBattleBufferA[gActiveBattler][3] << 8);
+
+ DoBounceEffect(gActiveBattler, BOUNCE_HEALTHBOX, 7, 1);
+ DoBounceEffect(gActiveBattler, BOUNCE_MON, 7, 1);
+ if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_SELECT);
+
+ switch (gActionSelectionCursor[gActiveBattler])
+ {
+ case 0:
+ BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, 0);
+ break;
+ case 1:
+ BtlController_EmitTwoReturnValues(1, B_ACTION_USE_ITEM, 0);
+ break;
+ case 2:
+ BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
+ break;
+ case 3:
+ BtlController_EmitTwoReturnValues(1, B_ACTION_RUN, 0);
+ break;
+ }
+ OakOldManBufferExecCompleted();
+ }
+ else if (JOY_NEW(DPAD_LEFT))
+ {
+ if (gActionSelectionCursor[gActiveBattler] & 1) // if is B_ACTION_USE_ITEM or B_ACTION_RUN
+ {
+ PlaySE(SE_SELECT);
+ ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBattler]);
+ gActionSelectionCursor[gActiveBattler] ^= 1;
+ ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
+ }
+ }
+ else if (JOY_NEW(DPAD_RIGHT))
+ {
+ if (!(gActionSelectionCursor[gActiveBattler] & 1)) // if is B_ACTION_USE_MOVE or B_ACTION_SWITCH
+ {
+ PlaySE(SE_SELECT);
+ ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBattler]);
+ gActionSelectionCursor[gActiveBattler] ^= 1;
+ ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
+ }
+ }
+ else if (JOY_NEW(DPAD_UP))
+ {
+ if (gActionSelectionCursor[gActiveBattler] & 2) // if is B_ACTION_SWITCH or B_ACTION_RUN
+ {
+ PlaySE(SE_SELECT);
+ ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBattler]);
+ gActionSelectionCursor[gActiveBattler] ^= 2;
+ ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
+ }
+ }
+ else if (JOY_NEW(DPAD_DOWN))
+ {
+ if (!(gActionSelectionCursor[gActiveBattler] & 2)) // if is B_ACTION_USE_MOVE or B_ACTION_USE_ITEM
+ {
+ PlaySE(SE_SELECT);
+ ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBattler]);
+ gActionSelectionCursor[gActiveBattler] ^= 2;
+ ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
+ }
+ }
+ else if (JOY_NEW(B_BUTTON))
+ {
+ if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ && GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT
+ && !(gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)])
+ && !(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ {
+ if (gBattleBufferA[gActiveBattler][1] == B_ACTION_USE_ITEM)
+ {
+ // Add item to bag if it is a ball
+ if (itemId <= ITEM_PREMIER_BALL)
+ AddBagItem(itemId, 1);
+ else
+ return;
+ }
+ PlaySE(SE_SELECT);
+ BtlController_EmitTwoReturnValues(1, B_ACTION_CANCEL_PARTNER, 0);
+ OakOldManBufferExecCompleted();
+ }
+ }
+ else if (JOY_NEW(START_BUTTON))
+ {
+ SwapHpBarsWithHpText();
+ }
+}
+
+static void sub_80E7844(void)
+{
+ switch (gBattleStruct->field_94)
+ {
+ case 0:
+ gBattleStruct->field_96 = 64;
+ ++gBattleStruct->field_94;
+ // fall through
+ case 1:
+ if (--gBattleStruct->field_96 == 0)
+ {
+ PlaySE(SE_SELECT);
+ ActionSelectionDestroyCursorAt(0);
+ ActionSelectionCreateCursorAt(1, 0);
+ gBattleStruct->field_96 = 64;
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 2:
+ if (--gBattleStruct->field_96 == 0)
+ {
+ PlaySE(SE_SELECT);
+ BtlController_EmitTwoReturnValues(1, B_ACTION_USE_ITEM, 0);
+ OakOldManBufferExecCompleted();
+ }
+ break;
+ }
+}
+
+static void CompleteOnBattlerSpriteCallbackDummy(void)
+{
+ if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy)
+ OakOldManBufferExecCompleted();
+}
+
+static void CompleteOnInactiveTextPrinter(void)
+{
+ if (!IsTextPrinterActive(0))
+ OakOldManBufferExecCompleted();
+}
+
+static void sub_80E7930(void)
+{
+ if (!gPaletteFade.active)
+ {
+ gMain.inBattle = FALSE;
+ gMain.callback1 = gPreBattleCallback1;
+ SetMainCallback2(gMain.savedCallback);
+ }
+}
+
+static void CompleteOnSpecialAnimDone(void)
+{
+ if (!gDoingBattleAnim)
+ OakOldManBufferExecCompleted();
+}
+
+void sub_80E7988(void)
+{
+ HandleInputChooseMove();
+ if (!(gBattleControllerExecFlags & gBitTable[gActiveBattler]))
+ OakOldManBufferExecCompleted();
+}
+
+static void OpenPartyMenuToChooseMon(void)
+{
+ if (!gPaletteFade.active)
+ {
+ u8 caseId;
+
+ gBattlerControllerFuncs[gActiveBattler] = WaitForMonSelection;
+ caseId = gTasks[gUnknown_3004FFC[gActiveBattler]].data[0];
+ DestroyTask(gUnknown_3004FFC[gActiveBattler]);
+ FreeAllWindowBuffers();
+ OpenPartyMenuInBattle(caseId);
+ }
+}
+
+static void WaitForMonSelection(void)
+{
+ if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active)
+ {
+ if (gUnknown_203B0C0 == 1)
+ BtlController_EmitChosenMonReturnValue(1, gUnknown_203B0C1, gUnknown_203B0DC);
+ else
+ BtlController_EmitChosenMonReturnValue(1, 6, NULL);
+ OakOldManBufferExecCompleted();
+ }
+}
+
+static void OpenBagAndChooseItem(void)
+{
+ if (!gPaletteFade.active)
+ {
+ gBattlerControllerFuncs[gActiveBattler] = CompleteWhenChoseItem;
+ nullsub_44();
+ FreeAllWindowBuffers();
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ sub_8107ECC();
+ else
+ sub_810AF74();
+ }
+}
+
+static void CompleteWhenChoseItem(void)
+{
+ if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active)
+ {
+ if (!sub_80EB2E0(4)
+ && gSpecialVar_ItemId == ITEM_POTION
+ && gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ {
+ sub_80EB2F4(4);
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E8704;
+ }
+ else
+ {
+ BtlController_EmitOneReturnValue(1, gSpecialVar_ItemId);
+ OakOldManBufferExecCompleted();
+ }
+ }
+}
+
+static void sub_80E7B4C(void)
+{
+ if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80
+ && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive)
+ sub_80F1720(gActiveBattler, &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]]);
+ if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].flag_x80
+ && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].ballAnimActive)
+ sub_80F1720(gActiveBattler ^ BIT_FLANK, &gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]]);
+ if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].ballAnimActive)
+ {
+ if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ {
+ DestroySprite(&gSprites[gUnknown_3004FFC[gActiveBattler ^ BIT_FLANK]]);
+ UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK],
+ &gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]],
+ HEALTHBOX_ALL);
+ sub_804BD94(gActiveBattler ^ BIT_FLANK);
+ SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]);
+ }
+ DestroySprite(&gSprites[gUnknown_3004FFC[gActiveBattler]]);
+ UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler],
+ &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]],
+ HEALTHBOX_ALL);
+ sub_804BD94(gActiveBattler);
+ SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler]);
+ gBattleSpritesDataPtr->animationData->field_9_x1 = 0;
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E7CD8;
+ }
+}
+
+static void sub_80E7CD8(void)
+{
+ bool32 r4 = FALSE;
+
+ if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy)
+ r4 = TRUE;
+ if (r4
+ && gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1
+ && gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].field_1_x1)
+ {
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 = 0;
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1 = 0;
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].flag_x80 = 0;
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].field_1_x1 = 0;
+ FreeSpriteTilesByTag(0x27F9);
+ FreeSpritePaletteByTag(0x27F9);
+ CreateTask(c3_0802FDF4, 10);
+ HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler);
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E835C;
+ }
+}
+
+#define tExpTask_monId data[0]
+#define tExpTask_gainedExp data[1]
+#define tExpTask_battler data[2]
+#define tExpTask_frames data[10]
+
+static void Task_GiveExpToMon(u8 taskId)
+{
+ u32 monId = (u8)(gTasks[taskId].tExpTask_monId);
+ u8 battlerId = gTasks[taskId].tExpTask_battler;
+ s16 gainedExp = gTasks[taskId].tExpTask_gainedExp;
+
+ if (IsDoubleBattle() == TRUE || monId != gBattlerPartyIndexes[battlerId]) // Give exp without moving the expbar.
+ {
+ struct Pokemon *mon = &gPlayerParty[monId];
+ u16 species = GetMonData(mon, MON_DATA_SPECIES);
+ u8 level = GetMonData(mon, MON_DATA_LEVEL);
+ u32 currExp = GetMonData(mon, MON_DATA_EXP);
+ u32 nextLvlExp = gExperienceTables[gBaseStats[species].growthRate][level + 1];
+
+ if (currExp + gainedExp >= nextLvlExp)
+ {
+ u8 savedActiveBattler;
+
+ SetMonData(mon, MON_DATA_EXP, &nextLvlExp);
+ CalculateMonStats(mon);
+ gainedExp -= nextLvlExp - currExp;
+ savedActiveBattler = gActiveBattler;
+ gActiveBattler = battlerId;
+ BtlController_EmitTwoReturnValues(1, RET_VALUE_LEVELED_UP, gainedExp);
+ gActiveBattler = savedActiveBattler;
+ if (IsDoubleBattle() == TRUE
+ && ((u16)(monId) == gBattlerPartyIndexes[battlerId] || (u16)(monId) == gBattlerPartyIndexes[battlerId ^ BIT_FLANK]))
+ gTasks[taskId].func = Task_LaunchLvlUpAnim;
+ else
+ gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter;
+ }
+ else
+ {
+ currExp += gainedExp;
+ SetMonData(mon, MON_DATA_EXP, &currExp);
+ gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter2;
+ DestroyTask(taskId);
+ }
+ }
+ else
+ {
+ gTasks[taskId].func = Task_PrepareToGiveExpWithExpBar;
+ }
+}
+
+static void Task_PrepareToGiveExpWithExpBar(u8 taskId)
+{
+ u8 monIndex = gTasks[taskId].tExpTask_monId;
+ s32 gainedExp = gTasks[taskId].tExpTask_gainedExp;
+ u8 battlerId = gTasks[taskId].tExpTask_battler;
+ struct Pokemon *mon = &gPlayerParty[monIndex];
+ u8 level = GetMonData(mon, MON_DATA_LEVEL);
+ u16 species = GetMonData(mon, MON_DATA_SPECIES);
+ u32 exp = GetMonData(mon, MON_DATA_EXP);
+ u32 currLvlExp = gExperienceTables[gBaseStats[species].growthRate][level];
+ u32 expToNextLvl;
+
+ exp -= currLvlExp;
+ expToNextLvl = gExperienceTables[gBaseStats[species].growthRate][level + 1] - currLvlExp;
+ SetBattleBarStruct(battlerId, gHealthboxSpriteIds[battlerId], expToNextLvl, exp, -gainedExp);
+ PlaySE(SE_EXP);
+ gTasks[taskId].func = sub_80E804C;
+}
+
+static void sub_80E804C(u8 taskId)
+{
+ if (gTasks[taskId].tExpTask_frames < 13)
+ {
+ ++gTasks[taskId].tExpTask_frames;
+ }
+ else
+ {
+ u8 monId = gTasks[taskId].tExpTask_monId;
+ s16 gainedExp = gTasks[taskId].tExpTask_gainedExp;
+ u8 battlerId = gTasks[taskId].tExpTask_battler;
+ s16 newExpPoints;
+
+ newExpPoints = MoveBattleBar(battlerId, gHealthboxSpriteIds[battlerId], EXP_BAR, 0);
+ SetHealthboxSpriteVisible(gHealthboxSpriteIds[battlerId]);
+ if (newExpPoints == -1) // The bar has been filled with given exp points.
+ {
+ u8 level;
+ s32 currExp;
+ u16 species;
+ s32 expOnNextLvl;
+
+ m4aSongNumStop(SE_EXP);
+ level = GetMonData(&gPlayerParty[monId], MON_DATA_LEVEL);
+ currExp = GetMonData(&gPlayerParty[monId], MON_DATA_EXP);
+ species = GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES);
+ expOnNextLvl = gExperienceTables[gBaseStats[species].growthRate][level + 1];
+ if (currExp + gainedExp >= expOnNextLvl)
+ {
+ u8 savedActiveBattler;
+
+ SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &expOnNextLvl);
+ CalculateMonStats(&gPlayerParty[monId]);
+ gainedExp -= expOnNextLvl - currExp;
+ savedActiveBattler = gActiveBattler;
+ gActiveBattler = battlerId;
+ BtlController_EmitTwoReturnValues(1, RET_VALUE_LEVELED_UP, gainedExp);
+ gActiveBattler = savedActiveBattler;
+ gTasks[taskId].func = Task_LaunchLvlUpAnim;
+ }
+ else
+ {
+ currExp += gainedExp;
+ SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &currExp);
+ gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter2;
+ DestroyTask(taskId);
+ }
+ }
+ }
+}
+
+static void Task_LaunchLvlUpAnim(u8 taskId)
+{
+ u8 battlerId = gTasks[taskId].tExpTask_battler;
+ u8 monIndex = gTasks[taskId].tExpTask_monId;
+
+ if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[battlerId ^ BIT_FLANK])
+ battlerId ^= BIT_FLANK;
+ InitAndLaunchSpecialAnimation(battlerId, battlerId, battlerId, B_ANIM_LVL_UP);
+ gTasks[taskId].func = Task_UpdateLvlInHealthbox;
+}
+
+static void Task_UpdateLvlInHealthbox(u8 taskId)
+{
+ u8 battlerId = gTasks[taskId].tExpTask_battler;
+
+ if (!gBattleSpritesDataPtr->healthBoxesData[battlerId].specialAnimActive)
+ {
+ u8 monIndex = gTasks[taskId].tExpTask_monId;
+
+ GetMonData(&gPlayerParty[monIndex], MON_DATA_LEVEL); // Unused return value.
+ if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[battlerId ^ BIT_FLANK])
+ UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId ^ BIT_FLANK], &gPlayerParty[monIndex], HEALTHBOX_ALL);
+ else
+ UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId], &gPlayerParty[monIndex], HEALTHBOX_ALL);
+ gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter;
+ }
+}
+
+static void DestroyExpTaskAndCompleteOnInactiveTextPrinter(u8 taskId)
+{
+ u8 monIndex = gTasks[taskId].tExpTask_monId;
+ u8 battlerId;
+
+ GetMonData(&gPlayerParty[monIndex], MON_DATA_LEVEL); // Unused return value
+ battlerId = gTasks[taskId].tExpTask_battler;
+ gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter2;
+ DestroyTask(taskId);
+}
+
+static void sub_80E82F4(void)
+{
+ if (gSprites[gBattlerSpriteIds[gActiveBattler]].pos1.y + gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.y > DISPLAY_HEIGHT)
+ {
+ FreeOamMatrix(gSprites[gBattlerSpriteIds[gActiveBattler]].oam.matrixNum);
+ DestroySprite(&gSprites[gBattlerSpriteIds[gActiveBattler]]);
+ SetHealthboxSpriteInvisible(gHealthboxSpriteIds[gActiveBattler]);
+ OakOldManBufferExecCompleted();
+ }
+}
+
+static void sub_80E835C(void)
+{
+ u32 mask;
+
+ switch (gBattleStruct->field_94)
+ {
+ case 0:
+ if (!gPaletteFade.active)
+ {
+ sub_80EEFC8(&gBattleStruct->field_95, &gBattleStruct->field_97, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT));
+ BeginNormalPaletteFade(0xFFFFFF7E,
+ 4,
+ 0,
+ 8,
+ RGB_BLACK);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 1:
+ if (!gPaletteFade.active)
+ {
+ sub_80EB30C();
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 2:
+ BattleStringExpandPlaceholdersToDisplayedString(gUnknown_83FDAE2);
+ BattlePutTextOnWindow(gDisplayedStringBattle, 24);
+ ++gBattleStruct->field_94;
+ break;
+ case 3:
+ if (!IsTextPrinterActive(24))
+ {
+ mask = (gBitTable[gBattleStruct->field_95] | gBitTable[gBattleStruct->field_97]) << 16;
+ BeginNormalPaletteFade(mask,
+ 4,
+ 8,
+ 0,
+ RGB_BLACK);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 4:
+ if (!gPaletteFade.active)
+ {
+ BattleStringExpandPlaceholdersToDisplayedString(gUnknown_83FDB92);
+ BattlePutTextOnWindow(gDisplayedStringBattle, 24);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 5:
+ if (!IsTextPrinterActive(24))
+ {
+ mask = (gBitTable[gBattleStruct->field_95] | gBitTable[gBattleStruct->field_97]) << 16;
+ BeginNormalPaletteFade(mask,
+ 4,
+ 0,
+ 8,
+ RGB_BLACK);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 6:
+ if (!gPaletteFade.active)
+ {
+ BattleStringExpandPlaceholdersToDisplayedString(gUnknown_83FDBEF);
+ BattlePutTextOnWindow(gDisplayedStringBattle, 24);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 7:
+ if (!IsTextPrinterActive(24))
+ {
+ BeginNormalPaletteFade(0xFFFFFF7E,
+ 4,
+ 8,
+ 0,
+ RGB_BLACK);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 8:
+ if (!gPaletteFade.active)
+ {
+ sub_80EF0E0(GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT));
+ sub_80EB524();
+ gBattleStruct->field_94 = 0;
+ OakOldManBufferExecCompleted();
+ }
+ break;
+ }
+}
+
+void sub_80E8570(void)
+{
+ sub_80E85D4(gUnknown_83FDC58, 1);
+}
+
+static void sub_80E8584(void)
+{
+ sub_80E85D4(gUnknown_83FDC95, 64);
+}
+
+void sub_80E8598(void)
+{
+ sub_80E85D4(gUnknown_83FDD23, 1);
+}
+
+static void sub_80E85AC(void)
+{
+ sub_80E85D4(gUnknown_83FDD64, 64);
+}
+
+void sub_80E85C0(void)
+{
+ sub_80E85D4(gUnknown_83FDDEB, 64);
+}
+
+static void sub_80E85D4(const u8 *text, u8 a2)
+{
+ switch (gBattleStruct->field_94)
+ {
+ case 0:
+ if (!IsTextPrinterActive(0))
+ {
+ gBattleStruct->field_97 = a2;
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 1:
+ if (--gBattleStruct->field_97 == 0)
+ {
+ BeginNormalPaletteFade(0xFFFFFF7E,
+ 4,
+ 0,
+ 8,
+ RGB_BLACK);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ sub_80EB30C();
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 3:
+ BattleStringExpandPlaceholdersToDisplayedString(text);
+ BattlePutTextOnWindow(gDisplayedStringBattle, 24);
+ ++gBattleStruct->field_94;
+ break;
+ case 4:
+ if (!IsTextPrinterActive(24))
+ {
+ BeginNormalPaletteFade(0xFFFFFF7E,
+ 4,
+ 8,
+ 0,
+ RGB_BLACK);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 5:
+ if (!gPaletteFade.active)
+ {
+ sub_80EB524();
+ if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
+ OakOldManBufferExecCompleted();
+ else
+ OpponentBufferExecCompleted();
+ gBattleCommunication[MSG_DISPLAY] = 0;
+ gBattleStruct->field_94 = 0;
+ }
+ break;
+ }
+}
+
+static void sub_80E8704(void)
+{
+ u32 mask;
+
+ switch (gBattleStruct->field_94)
+ {
+ case 0:
+ if (!gPaletteFade.active)
+ {
+ sub_80EEFC8(&gBattleStruct->field_95, &gBattleStruct->field_97, gActiveBattler);
+ BeginNormalPaletteFade(0xFFFFFF7E,
+ 4,
+ 0,
+ 8,
+ RGB_BLACK);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 1:
+ if (!gPaletteFade.active)
+ {
+ mask = (gBitTable[gBattleStruct->field_95] | gBitTable[gBattleStruct->field_97]) << 16;
+ BeginNormalPaletteFade(mask,
+ 4,
+ 8,
+ 0,
+ RGB_BLACK);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ sub_80EB30C();
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 3:
+ BattleStringExpandPlaceholdersToDisplayedString(gUnknown_83FDCD2);
+ BattlePutTextOnWindow(gDisplayedStringBattle, 24);
+ ++gBattleStruct->field_94;
+ break;
+ case 4:
+ if (!IsTextPrinterActive(24))
+ {
+ mask = (gBitTable[gBattleStruct->field_95] | gBitTable[gBattleStruct->field_97]) << 16;
+ BeginNormalPaletteFade(mask,
+ 4,
+ 0,
+ 8,
+ RGB_BLACK);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 5:
+ if (!gPaletteFade.active)
+ {
+ BeginNormalPaletteFade(0xFFFFFF7E,
+ 4,
+ 8,
+ 0,
+ RGB_BLACK);
+ ++gBattleStruct->field_94;
+ }
+ break;
+ case 6:
+ if (!gPaletteFade.active)
+ {
+ sub_80EB524();
+ BtlController_EmitOneReturnValue(1, gSpecialVar_ItemId);
+ OakOldManBufferExecCompleted();
+ gBattleStruct->field_94 = 0;
+ }
+ break;
+ }
+}
+
+static void CompleteOnHealthbarDone(void)
+{
+ s16 hpValue = MoveBattleBar(gActiveBattler, gHealthboxSpriteIds[gActiveBattler], HEALTH_BAR, 0);
+
+ SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler]);
+ if (hpValue != -1)
+ {
+ UpdateHpTextInHealthbox(gHealthboxSpriteIds[gActiveBattler], hpValue, HP_CURRENT);
+ }
+ else
+ {
+ HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler);
+ OakOldManBufferExecCompleted();
+ }
+}
+
+static void CompleteOnInactiveTextPrinter2(void)
+{
+ if (!IsTextPrinterActive(0))
+ OakOldManBufferExecCompleted();
+}
+
+static void DoHitAnimBlinkSpriteEffect(void)
+{
+ u8 spriteId = gBattlerSpriteIds[gActiveBattler];
+
+ if (gSprites[spriteId].data[1] == 32)
+ {
+ gSprites[spriteId].data[1] = 0;
+ gSprites[spriteId].invisible = FALSE;
+ gDoingBattleAnim = FALSE;
+ OakOldManBufferExecCompleted();
+ }
+ else
+ {
+ if ((gSprites[spriteId].data[1] % 4) == 0)
+ gSprites[spriteId].invisible ^= 1;
+ ++gSprites[spriteId].data[1];
+ }
+}
+
+static void sub_80E89C4(void)
+{
+ if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive)
+ {
+ FreeSpriteOamMatrix(&gSprites[gBattlerSpriteIds[gActiveBattler]]);
+ DestroySprite(&gSprites[gBattlerSpriteIds[gActiveBattler]]);
+ SetHealthboxSpriteInvisible(gHealthboxSpriteIds[gActiveBattler]);
+ OakOldManBufferExecCompleted();
+ }
+}
+
+static void CompleteOnBattlerSpriteCallbackDummy2(void)
+{
+ if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy)
+ OakOldManBufferExecCompleted();
+}
+
+static void CompleteOnFinishedBattleAnimation(void)
+{
+ if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animFromTableActive)
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManBufferExecCompleted(void)
+{
+ gBattlerControllerFuncs[gActiveBattler] = OakOldManBufferRunCommand;
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ u8 playerId = GetMultiplayerId();
+
+ PrepareBufferDataTransferLink(2, 4, &playerId);
+ gBattleBufferA[gActiveBattler][0] = CONTROLLER_TERMINATOR_NOP;
+ }
+ else
+ {
+ gBattleControllerExecFlags &= ~gBitTable[gActiveBattler];
+ }
+}
+
+static void CompleteOnFinishedStatusAnimation(void)
+{
+ if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].statusAnimActive)
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleGetMonData(void)
+{
+ u8 monData[sizeof(struct Pokemon) * 2 + 56]; // this allows to get full data of two pokemon, trying to get more will result in overwriting data
+ u32 size = 0;
+ u8 monToCheck;
+ s32 i;
+
+ if (gBattleBufferA[gActiveBattler][2] == 0)
+ {
+ size += CopyOakOldManMonData(gBattlerPartyIndexes[gActiveBattler], monData);
+ }
+ else
+ {
+ monToCheck = gBattleBufferA[gActiveBattler][2];
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ if (monToCheck & 1)
+ size += CopyOakOldManMonData(i, monData + size);
+ monToCheck >>= 1;
+ }
+ }
+ BtlController_EmitDataTransfer(1, size, monData);
+ OakOldManBufferExecCompleted();
+}
+
+static u32 CopyOakOldManMonData(u8 monId, u8 *dst)
+{
+ struct BattlePokemon battleMon;
+ struct MovePpInfo moveData;
+ u8 nickname[20];
+ u8 *src;
+ s16 data16;
+ u32 data32;
+ s32 size = 0;
+
+ switch (gBattleBufferA[gActiveBattler][1])
+ {
+ case REQUEST_ALL_BATTLE:
+ battleMon.species = GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES);
+ battleMon.item = GetMonData(&gPlayerParty[monId], MON_DATA_HELD_ITEM);
+ for (size = 0; size < MAX_MON_MOVES; ++size)
+ {
+ battleMon.moves[size] = GetMonData(&gPlayerParty[monId], MON_DATA_MOVE1 + size);
+ battleMon.pp[size] = GetMonData(&gPlayerParty[monId], MON_DATA_PP1 + size);
+ }
+ battleMon.ppBonuses = GetMonData(&gPlayerParty[monId], MON_DATA_PP_BONUSES);
+ battleMon.friendship = GetMonData(&gPlayerParty[monId], MON_DATA_FRIENDSHIP);
+ battleMon.experience = GetMonData(&gPlayerParty[monId], MON_DATA_EXP);
+ battleMon.hpIV = GetMonData(&gPlayerParty[monId], MON_DATA_HP_IV);
+ battleMon.attackIV = GetMonData(&gPlayerParty[monId], MON_DATA_ATK_IV);
+ battleMon.defenseIV = GetMonData(&gPlayerParty[monId], MON_DATA_DEF_IV);
+ battleMon.speedIV = GetMonData(&gPlayerParty[monId], MON_DATA_SPEED_IV);
+ battleMon.spAttackIV = GetMonData(&gPlayerParty[monId], MON_DATA_SPATK_IV);
+ battleMon.spDefenseIV = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF_IV);
+ battleMon.personality = GetMonData(&gPlayerParty[monId], MON_DATA_PERSONALITY);
+ battleMon.status1 = GetMonData(&gPlayerParty[monId], MON_DATA_STATUS);
+ battleMon.level = GetMonData(&gPlayerParty[monId], MON_DATA_LEVEL);
+ battleMon.hp = GetMonData(&gPlayerParty[monId], MON_DATA_HP);
+ battleMon.maxHP = GetMonData(&gPlayerParty[monId], MON_DATA_MAX_HP);
+ battleMon.attack = GetMonData(&gPlayerParty[monId], MON_DATA_ATK);
+ battleMon.defense = GetMonData(&gPlayerParty[monId], MON_DATA_DEF);
+ battleMon.speed = GetMonData(&gPlayerParty[monId], MON_DATA_SPEED);
+ battleMon.spAttack = GetMonData(&gPlayerParty[monId], MON_DATA_SPATK);
+ battleMon.spDefense = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF);
+ battleMon.isEgg = GetMonData(&gPlayerParty[monId], MON_DATA_IS_EGG);
+ battleMon.abilityNum = GetMonData(&gPlayerParty[monId], MON_DATA_ABILITY_NUM);
+ battleMon.otId = GetMonData(&gPlayerParty[monId], MON_DATA_OT_ID);
+ GetMonData(&gPlayerParty[monId], MON_DATA_NICKNAME, nickname);
+ StringCopy10(battleMon.nickname, nickname);
+ GetMonData(&gPlayerParty[monId], MON_DATA_OT_NAME, battleMon.otName);
+ src = (u8 *)&battleMon;
+ for (size = 0; size < sizeof(battleMon); ++size)
+ dst[size] = src[size];
+ break;
+ case REQUEST_SPECIES_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_HELDITEM_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_HELD_ITEM);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_MOVES_PP_BATTLE:
+ for (size = 0; size < MAX_MON_MOVES; ++size)
+ {
+ moveData.moves[size] = GetMonData(&gPlayerParty[monId], MON_DATA_MOVE1 + size);
+ moveData.pp[size] = GetMonData(&gPlayerParty[monId], MON_DATA_PP1 + size);
+ }
+ moveData.ppBonuses = GetMonData(&gPlayerParty[monId], MON_DATA_PP_BONUSES);
+ src = (u8 *)(&moveData);
+ for (size = 0; size < sizeof(moveData); ++size)
+ dst[size] = src[size];
+ break;
+ case REQUEST_MOVE1_BATTLE:
+ case REQUEST_MOVE2_BATTLE:
+ case REQUEST_MOVE3_BATTLE:
+ case REQUEST_MOVE4_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_MOVE1 + gBattleBufferA[gActiveBattler][1] - REQUEST_MOVE1_BATTLE);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_PP_DATA_BATTLE:
+ for (size = 0; size < MAX_MON_MOVES; ++size)
+ dst[size] = GetMonData(&gPlayerParty[monId], MON_DATA_PP1 + size);
+ dst[size] = GetMonData(&gPlayerParty[monId], MON_DATA_PP_BONUSES);
+ ++size;
+ break;
+ case REQUEST_PPMOVE1_BATTLE:
+ case REQUEST_PPMOVE2_BATTLE:
+ case REQUEST_PPMOVE3_BATTLE:
+ case REQUEST_PPMOVE4_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_PP1 + gBattleBufferA[gActiveBattler][1] - REQUEST_PPMOVE1_BATTLE);
+ size = 1;
+ break;
+ case REQUEST_OTID_BATTLE:
+ data32 = GetMonData(&gPlayerParty[monId], MON_DATA_OT_ID);
+ dst[0] = (data32 & 0x000000FF);
+ dst[1] = (data32 & 0x0000FF00) >> 8;
+ dst[2] = (data32 & 0x00FF0000) >> 16;
+ size = 3;
+ break;
+ case REQUEST_EXP_BATTLE:
+ data32 = GetMonData(&gPlayerParty[monId], MON_DATA_EXP);
+ dst[0] = (data32 & 0x000000FF);
+ dst[1] = (data32 & 0x0000FF00) >> 8;
+ dst[2] = (data32 & 0x00FF0000) >> 16;
+ size = 3;
+ break;
+ case REQUEST_HP_EV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_HP_EV);
+ size = 1;
+ break;
+ case REQUEST_ATK_EV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_ATK_EV);
+ size = 1;
+ break;
+ case REQUEST_DEF_EV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_DEF_EV);
+ size = 1;
+ break;
+ case REQUEST_SPEED_EV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_SPEED_EV);
+ size = 1;
+ break;
+ case REQUEST_SPATK_EV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_SPATK_EV);
+ size = 1;
+ break;
+ case REQUEST_SPDEF_EV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF_EV);
+ size = 1;
+ break;
+ case REQUEST_FRIENDSHIP_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_FRIENDSHIP);
+ size = 1;
+ break;
+ case REQUEST_POKERUS_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_POKERUS);
+ size = 1;
+ break;
+ case REQUEST_MET_LOCATION_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_MET_LOCATION);
+ size = 1;
+ break;
+ case REQUEST_MET_LEVEL_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_MET_LEVEL);
+ size = 1;
+ break;
+ case REQUEST_MET_GAME_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_MET_GAME);
+ size = 1;
+ break;
+ case REQUEST_POKEBALL_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_POKEBALL);
+ size = 1;
+ break;
+ case REQUEST_ALL_IVS_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_HP_IV);
+ dst[1] = GetMonData(&gPlayerParty[monId], MON_DATA_ATK_IV);
+ dst[2] = GetMonData(&gPlayerParty[monId], MON_DATA_DEF_IV);
+ dst[3] = GetMonData(&gPlayerParty[monId], MON_DATA_SPEED_IV);
+ dst[4] = GetMonData(&gPlayerParty[monId], MON_DATA_SPATK_IV);
+ dst[5] = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF_IV);
+ size = 6;
+ break;
+ case REQUEST_HP_IV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_HP_IV);
+ size = 1;
+ break;
+ case REQUEST_ATK_IV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_ATK_IV);
+ size = 1;
+ break;
+ case REQUEST_DEF_IV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_DEF_IV);
+ size = 1;
+ break;
+ case REQUEST_SPEED_IV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_SPEED_IV);
+ size = 1;
+ break;
+ case REQUEST_SPATK_IV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_SPATK_IV);
+ size = 1;
+ break;
+ case REQUEST_SPDEF_IV_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF_IV);
+ size = 1;
+ break;
+ case REQUEST_PERSONALITY_BATTLE:
+ data32 = GetMonData(&gPlayerParty[monId], MON_DATA_PERSONALITY);
+ dst[0] = (data32 & 0x000000FF);
+ dst[1] = (data32 & 0x0000FF00) >> 8;
+ dst[2] = (data32 & 0x00FF0000) >> 16;
+ dst[3] = (data32 & 0xFF000000) >> 24;
+ size = 4;
+ break;
+ case REQUEST_CHECKSUM_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_CHECKSUM);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_STATUS_BATTLE:
+ data32 = GetMonData(&gPlayerParty[monId], MON_DATA_STATUS);
+ dst[0] = (data32 & 0x000000FF);
+ dst[1] = (data32 & 0x0000FF00) >> 8;
+ dst[2] = (data32 & 0x00FF0000) >> 16;
+ dst[3] = (data32 & 0xFF000000) >> 24;
+ size = 4;
+ break;
+ case REQUEST_LEVEL_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_LEVEL);
+ size = 1;
+ break;
+ case REQUEST_HP_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_HP);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_MAX_HP_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_MAX_HP);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_ATK_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_ATK);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_DEF_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_DEF);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_SPEED_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_SPEED);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_SPATK_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_SPATK);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_SPDEF_BATTLE:
+ data16 = GetMonData(&gPlayerParty[monId], MON_DATA_SPDEF);
+ dst[0] = data16;
+ dst[1] = data16 >> 8;
+ size = 2;
+ break;
+ case REQUEST_COOL_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_COOL);
+ size = 1;
+ break;
+ case REQUEST_BEAUTY_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_BEAUTY);
+ size = 1;
+ break;
+ case REQUEST_CUTE_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_CUTE);
+ size = 1;
+ break;
+ case REQUEST_SMART_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_SMART);
+ size = 1;
+ break;
+ case REQUEST_TOUGH_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_TOUGH);
+ size = 1;
+ break;
+ case REQUEST_SHEEN_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_SHEEN);
+ size = 1;
+ break;
+ case REQUEST_COOL_RIBBON_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_COOL_RIBBON);
+ size = 1;
+ break;
+ case REQUEST_BEAUTY_RIBBON_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_BEAUTY_RIBBON);
+ size = 1;
+ break;
+ case REQUEST_CUTE_RIBBON_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_CUTE_RIBBON);
+ size = 1;
+ break;
+ case REQUEST_SMART_RIBBON_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_SMART_RIBBON);
+ size = 1;
+ break;
+ case REQUEST_TOUGH_RIBBON_BATTLE:
+ dst[0] = GetMonData(&gPlayerParty[monId], MON_DATA_TOUGH_RIBBON);
+ size = 1;
+ break;
+ }
+ return size;
+}
+
+static void OakOldManHandleGetRawMonData(void)
+{
+ PlayerHandleGetRawMonData();
+}
+
+static void OakOldManHandleSetMonData(void)
+{
+ u8 monToCheck;
+ u8 i;
+
+ if (gBattleBufferA[gActiveBattler][2] == 0)
+ {
+ SetOakOldManMonData(gBattlerPartyIndexes[gActiveBattler]);
+ }
+ else
+ {
+ monToCheck = gBattleBufferA[gActiveBattler][2];
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ if (monToCheck & 1)
+ SetOakOldManMonData(i);
+ monToCheck >>= 1;
+ }
+ }
+ OakOldManBufferExecCompleted();
+}
+
+static void SetOakOldManMonData(u8 monId)
+{
+ struct BattlePokemon *battlePokemon = (struct BattlePokemon *)&gBattleBufferA[gActiveBattler][3];
+ struct MovePpInfo *moveData = (struct MovePpInfo *)&gBattleBufferA[gActiveBattler][3];
+ s32 i;
+
+ switch (gBattleBufferA[gActiveBattler][1])
+ {
+ case REQUEST_ALL_BATTLE:
+ {
+ u8 iv;
+
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &battlePokemon->species);
+ SetMonData(&gPlayerParty[monId], MON_DATA_HELD_ITEM, &battlePokemon->item);
+ for (i = 0; i < MAX_MON_MOVES; ++i)
+ {
+ SetMonData(&gPlayerParty[monId], MON_DATA_MOVE1 + i, &battlePokemon->moves[i]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_PP1 + i, &battlePokemon->pp[i]);
+ }
+ SetMonData(&gPlayerParty[monId], MON_DATA_PP_BONUSES, &battlePokemon->ppBonuses);
+ SetMonData(&gPlayerParty[monId], MON_DATA_FRIENDSHIP, &battlePokemon->friendship);
+ SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &battlePokemon->experience);
+ iv = battlePokemon->hpIV;
+ SetMonData(&gPlayerParty[monId], MON_DATA_HP_IV, &iv);
+ iv = battlePokemon->attackIV;
+ SetMonData(&gPlayerParty[monId], MON_DATA_ATK_IV, &iv);
+ iv = battlePokemon->defenseIV;
+ SetMonData(&gPlayerParty[monId], MON_DATA_DEF_IV, &iv);
+ iv = battlePokemon->speedIV;
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPEED_IV, &iv);
+ iv = battlePokemon->spAttackIV;
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPATK_IV, &iv);
+ iv = battlePokemon->spDefenseIV;
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPDEF_IV, &iv);
+ SetMonData(&gPlayerParty[monId], MON_DATA_PERSONALITY, &battlePokemon->personality);
+ SetMonData(&gPlayerParty[monId], MON_DATA_STATUS, &battlePokemon->status1);
+ SetMonData(&gPlayerParty[monId], MON_DATA_LEVEL, &battlePokemon->level);
+ SetMonData(&gPlayerParty[monId], MON_DATA_HP, &battlePokemon->hp);
+ SetMonData(&gPlayerParty[monId], MON_DATA_MAX_HP, &battlePokemon->maxHP);
+ SetMonData(&gPlayerParty[monId], MON_DATA_ATK, &battlePokemon->attack);
+ SetMonData(&gPlayerParty[monId], MON_DATA_DEF, &battlePokemon->defense);
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPEED, &battlePokemon->speed);
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPATK, &battlePokemon->spAttack);
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPDEF, &battlePokemon->spDefense);
+ }
+ break;
+ case REQUEST_SPECIES_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_HELDITEM_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_HELD_ITEM, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_MOVES_PP_BATTLE:
+ for (i = 0; i < MAX_MON_MOVES; ++i)
+ {
+ SetMonData(&gPlayerParty[monId], MON_DATA_MOVE1 + i, &moveData->moves[i]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_PP1 + i, &moveData->pp[i]);
+ }
+ SetMonData(&gPlayerParty[monId], MON_DATA_PP_BONUSES, &moveData->ppBonuses);
+ break;
+ case REQUEST_MOVE1_BATTLE:
+ case REQUEST_MOVE2_BATTLE:
+ case REQUEST_MOVE3_BATTLE:
+ case REQUEST_MOVE4_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_MOVE1 + gBattleBufferA[gActiveBattler][1] - REQUEST_MOVE1_BATTLE, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_PP_DATA_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_PP1, &gBattleBufferA[gActiveBattler][3]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_PP2, &gBattleBufferA[gActiveBattler][4]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_PP3, &gBattleBufferA[gActiveBattler][5]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_PP4, &gBattleBufferA[gActiveBattler][6]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_PP_BONUSES, &gBattleBufferA[gActiveBattler][7]);
+ break;
+ case REQUEST_PPMOVE1_BATTLE:
+ case REQUEST_PPMOVE2_BATTLE:
+ case REQUEST_PPMOVE3_BATTLE:
+ case REQUEST_PPMOVE4_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_PP1 + gBattleBufferA[gActiveBattler][1] - REQUEST_PPMOVE1_BATTLE, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_OTID_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_OT_ID, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_EXP_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_HP_EV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_HP_EV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_ATK_EV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_ATK_EV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_DEF_EV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_DEF_EV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SPEED_EV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPEED_EV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SPATK_EV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPATK_EV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SPDEF_EV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPDEF_EV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_FRIENDSHIP_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_FRIENDSHIP, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_POKERUS_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_POKERUS, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_MET_LOCATION_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_MET_LOCATION, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_MET_LEVEL_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_MET_LEVEL, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_MET_GAME_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_MET_GAME, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_POKEBALL_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_POKEBALL, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_ALL_IVS_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_HP_IV, &gBattleBufferA[gActiveBattler][3]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBattler][4]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBattler][5]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPEED_IV, &gBattleBufferA[gActiveBattler][6]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBattler][7]);
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBattler][8]);
+ break;
+ case REQUEST_HP_IV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_HP_IV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_ATK_IV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_ATK_IV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_DEF_IV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_DEF_IV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SPEED_IV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPEED_IV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SPATK_IV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SPDEF_IV_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_PERSONALITY_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_PERSONALITY, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_CHECKSUM_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_CHECKSUM, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_STATUS_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_STATUS, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_LEVEL_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_LEVEL, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_HP_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_HP, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_MAX_HP_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_MAX_HP, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_ATK_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_ATK, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_DEF_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_DEF, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SPEED_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPEED, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SPATK_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPATK, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SPDEF_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SPDEF, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_COOL_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_COOL, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_BEAUTY_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_BEAUTY, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_CUTE_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_CUTE, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SMART_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SMART, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_TOUGH_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_TOUGH, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SHEEN_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SHEEN, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_COOL_RIBBON_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_COOL_RIBBON, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_BEAUTY_RIBBON_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_BEAUTY_RIBBON, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_CUTE_RIBBON_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_CUTE_RIBBON, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_SMART_RIBBON_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_SMART_RIBBON, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ case REQUEST_TOUGH_RIBBON_BATTLE:
+ SetMonData(&gPlayerParty[monId], MON_DATA_TOUGH_RIBBON, &gBattleBufferA[gActiveBattler][3]);
+ break;
+ }
+ HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler);
+}
+
+static void OakOldManHandleSetRawMonData(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleLoadMonSprite(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleSwitchInAnim(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleReturnMonToBall(void)
+{
+ if (gBattleBufferA[gActiveBattler][1] == 0)
+ {
+ InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_SWITCH_OUT_PLAYER_MON);
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E89C4;
+ }
+ else
+ {
+ FreeSpriteOamMatrix(&gSprites[gBattlerSpriteIds[gActiveBattler]]);
+ DestroySprite(&gSprites[gBattlerSpriteIds[gActiveBattler]]);
+ SetHealthboxSpriteInvisible(gHealthboxSpriteIds[gActiveBattler]);
+ OakOldManBufferExecCompleted();
+ }
+}
+
+static void OakOldManHandleDrawTrainerPic(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ {
+ DecompressTrainerBackPalette(gSaveBlock2Ptr->playerGender, gActiveBattler);
+ SetMultiuseSpriteTemplateToTrainerBack(gSaveBlock2Ptr->playerGender, GetBattlerPosition(gActiveBattler));
+ gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate,
+ 80,
+ (8 - gTrainerBackPicCoords[gSaveBlock2Ptr->playerGender].size) * 4 + 80,
+ 30);
+ }
+ else
+ {
+ DecompressTrainerBackPalette(5, gActiveBattler);
+ SetMultiuseSpriteTemplateToTrainerBack(5, GetBattlerPosition(gActiveBattler));
+ gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate,
+ 80,
+ (8 - gTrainerBackPicCoords[5].size) * 4 + 80,
+ 30);
+ }
+ gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = gActiveBattler;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x = 240;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = -2;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_8033EEC;
+ gBattlerControllerFuncs[gActiveBattler] = CompleteOnBattlerSpriteCallbackDummy;
+}
+
+static void OakOldManHandleTrainerSlide(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ {
+ DecompressTrainerBackPalette(gSaveBlock2Ptr->playerGender, gActiveBattler);
+ SetMultiuseSpriteTemplateToTrainerBack(gSaveBlock2Ptr->playerGender, GetBattlerPosition(gActiveBattler));
+ gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate,
+ 80,
+ (8 - gTrainerBackPicCoords[gSaveBlock2Ptr->playerGender].size) * 4 + 80,
+ 30);
+ }
+ else
+ {
+ DecompressTrainerBackPalette(5, gActiveBattler);
+ SetMultiuseSpriteTemplateToTrainerBack(5, GetBattlerPosition(gActiveBattler));
+ gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate,
+ 80,
+ (8 - gTrainerBackPicCoords[5].size) * 4 + 80,
+ 30);
+ }
+ gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = gActiveBattler;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x = -96;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = 2;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_8033EEC;
+ gBattlerControllerFuncs[gActiveBattler] = CompleteOnBattlerSpriteCallbackDummy2;
+}
+
+static void OakOldManHandleTrainerSlideBack(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleFaintAnimation(void)
+{
+ if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState == 0)
+ {
+ if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute)
+ InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_SUBSTITUTE_TO_MON);
+ ++gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState;
+ }
+ else
+ {
+ if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive)
+ {
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0;
+ HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler);
+ PlaySE12WithPanning(SE_POKE_DEAD, SOUND_PAN_ATTACKER);
+ gSprites[gBattlerSpriteIds[gActiveBattler]].data[1] = 0;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].data[2] = 5;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_8012110;
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E82F4;
+ }
+ }
+}
+
+static void OakOldManHandlePaletteFade(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleSuccessBallThrowAnim(void)
+{
+ gBattleSpritesDataPtr->animationData->ballThrowCaseId = BALL_3_SHAKES_SUCCESS;
+ gDoingBattleAnim = TRUE;
+ InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), B_ANIM_SAFARI_BALL_THROW);
+ gBattlerControllerFuncs[gActiveBattler] = CompleteOnSpecialAnimDone;
+}
+
+static void OakOldManHandleBallThrowAnim(void)
+{
+ u8 ballThrowCaseId = gBattleBufferA[gActiveBattler][1];
+
+ gBattleSpritesDataPtr->animationData->ballThrowCaseId = ballThrowCaseId;
+ gDoingBattleAnim = TRUE;
+ InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), B_ANIM_SAFARI_BALL_THROW);
+ gBattlerControllerFuncs[gActiveBattler] = CompleteOnSpecialAnimDone;
+}
+
+static void OakOldManHandlePause(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleMoveAnimation(void)
+{
+ u16 move = gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8);
+
+ gAnimMoveTurn = gBattleBufferA[gActiveBattler][3];
+ gAnimMovePower = gBattleBufferA[gActiveBattler][4] | (gBattleBufferA[gActiveBattler][5] << 8);
+ gAnimMoveDmg = gBattleBufferA[gActiveBattler][6] | (gBattleBufferA[gActiveBattler][7] << 8) | (gBattleBufferA[gActiveBattler][8] << 16) | (gBattleBufferA[gActiveBattler][9] << 24);
+ gAnimFriendship = gBattleBufferA[gActiveBattler][10];
+ gWeatherMoveAnim = gBattleBufferA[gActiveBattler][12] | (gBattleBufferA[gActiveBattler][13] << 8);
+ gAnimDisableStructPtr = (struct DisableStruct *)&gBattleBufferA[gActiveBattler][16];
+ gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality;
+ if (IsMoveWithoutAnimation(move, gAnimMoveTurn)) // always returns FALSE
+ {
+ OakOldManBufferExecCompleted();
+ }
+ else
+ {
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0;
+ gBattlerControllerFuncs[gActiveBattler] = OakOldManDoMoveAnimation;
+ }
+}
+
+static void OakOldManDoMoveAnimation(void)
+{
+ u16 move = gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8);
+
+ switch (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState)
+ {
+ case 0:
+ if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute)
+ InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_SUBSTITUTE_TO_MON);
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 1;
+ break;
+ case 1:
+ if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive)
+ {
+ sub_8035450(0);
+ DoMoveAnim(move);
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 2;
+ }
+ break;
+ case 2:
+ gAnimScriptCallback();
+ if (!gAnimScriptActive)
+ {
+ sub_8035450(1);
+ if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute)
+ InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_MON_TO_SUBSTITUTE);
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 3;
+ }
+ break;
+ case 3:
+ if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive)
+ {
+ CopyAllBattleSpritesInvisibilities();
+ TrySetBehindSubstituteSpriteBit(gActiveBattler, gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8));
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0;
+ OakOldManBufferExecCompleted();
+ }
+ break;
+ }
+}
+
+static void OakOldManHandlePrintString(void)
+{
+ u16 *stringId;
+
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ stringId = (u16 *)(&gBattleBufferA[gActiveBattler][2]);
+ if (gBattleTypeFlags & BATTLE_TYPE_OLD_MAN_TUTORIAL && *stringId == 1)
+ {
+ OakOldManBufferExecCompleted();
+ }
+ else
+ {
+ BufferStringBattle(*stringId);
+ if (sub_80D89B0(*stringId))
+ BattlePutTextOnWindow(gDisplayedStringBattle, 64);
+ else
+ BattlePutTextOnWindow(gDisplayedStringBattle, 0);
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ {
+ switch (*stringId)
+ {
+ case 216:
+ if (!sub_80EB2E0(2))
+ {
+ sub_80EB2F4(2);
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E8584;
+ return;
+ }
+ break;
+ case 30:
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E85AC;
+ return;
+ case 383:
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E85C0;
+ return;
+ case 227:
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E8598;
+ return;
+ }
+ }
+ gBattlerControllerFuncs[gActiveBattler] = CompleteOnInactiveTextPrinter;
+ }
+}
+
+static void OakOldManHandlePrintSelectionString(void)
+{
+ if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
+ OakOldManHandlePrintString();
+ else
+ OakOldManBufferExecCompleted();
+}
+
+static void sub_80EA690(void)
+{
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 160;
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ gBattlerControllerFuncs[gActiveBattler] = HandleInputChooseAction;
+ else
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E7844;
+ }
+}
+
+static void OakOldManHandleChooseAction(void)
+{
+ s32 i;
+
+ gBattlerControllerFuncs[gActiveBattler] = sub_80EA690;
+ BattlePutTextOnWindow(gUnknown_83FDA4C, 0);
+ BattlePutTextOnWindow(gUnknown_83FE725, 2);
+ for (i = 0; i < MAX_MON_MOVES; ++i)
+ ActionSelectionDestroyCursorAt((u8)i);
+ ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ BattleStringExpandPlaceholdersToDisplayedString(gText_WhatWillPkmnDo);
+ else
+ BattleStringExpandPlaceholdersToDisplayedString(gUnknown_83FE6FA);
+ BattlePutTextOnWindow(gDisplayedStringBattle, 1);
+}
+
+static void OakOldManHandleUnknownYesNoBox(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void sub_80EA798(void)
+{
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 320;
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E7988;
+ }
+}
+
+static void OakOldManHandleChooseMove(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ {
+ InitMoveSelectionsVarsAndStrings();
+ gBattlerControllerFuncs[gActiveBattler] = sub_80EA798;
+ }
+ else
+ {
+ switch (gBattleStruct->field_95)
+ {
+ case 0:
+ InitMoveSelectionsVarsAndStrings();
+ ++gBattleStruct->field_95;
+ gBattleStruct->field_97 = 80;
+ // fall through
+ case 1:
+ if (--gBattleStruct->field_97 == 0)
+ {
+ PlaySE(SE_SELECT);
+ BtlController_EmitTwoReturnValues(1, 10, 0x100);
+ OakOldManBufferExecCompleted();
+ }
+ break;
+ }
+ }
+}
+
+static void OakOldManHandleChooseItem(void)
+{
+ s32 i;
+
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
+ gBattlerControllerFuncs[gActiveBattler] = OpenBagAndChooseItem;
+ gBattlerInMenuId = gActiveBattler;
+ for (i = 0; i < 3; ++i)
+ gUnknown_203B0DC[i] = gBattleBufferA[gActiveBattler][i + 1];
+}
+
+static void OakOldManHandleChoosePokemon(void)
+{
+ s32 i;
+
+ gUnknown_3004FFC[gActiveBattler] = CreateTask(TaskDummy, 0xFF);
+ gTasks[gUnknown_3004FFC[gActiveBattler]].data[0] = gBattleBufferA[gActiveBattler][1] & 0xF;
+ *(&gBattleStruct->battlerPreventingSwitchout) = gBattleBufferA[gActiveBattler][1] >> 4;
+ *(&gBattleStruct->field_8B) = gBattleBufferA[gActiveBattler][2];
+ *(&gBattleStruct->abilityPreventingSwitchout) = gBattleBufferA[gActiveBattler][3];
+ for (i = 0; i < 3; ++i)
+ gUnknown_203B0DC[i] = gBattleBufferA[gActiveBattler][4 + i];
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
+ gBattlerControllerFuncs[gActiveBattler] = OpenPartyMenuToChooseMon;
+ gBattlerInMenuId = gActiveBattler;
+}
+
+static void OakOldManHandleCmd23(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleHealthBarUpdate(void)
+{
+ s16 hpVal;
+
+ LoadBattleBarGfx(0);
+ hpVal = gBattleBufferA[gActiveBattler][2] | (gBattleBufferA[gActiveBattler][3] << 8);
+ if (hpVal != INSTANT_HP_BAR_DROP)
+ {
+ u32 maxHP = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MAX_HP);
+ u32 curHP = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_HP);
+
+ SetBattleBarStruct(gActiveBattler, gHealthboxSpriteIds[gActiveBattler], maxHP, curHP, hpVal);
+ }
+ else
+ {
+ u32 maxHP = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_MAX_HP);
+
+ SetBattleBarStruct(gActiveBattler, gHealthboxSpriteIds[gActiveBattler], maxHP, 0, hpVal);
+ UpdateHpTextInHealthbox(gHealthboxSpriteIds[gActiveBattler], 0, HP_CURRENT);
+ }
+ gBattlerControllerFuncs[gActiveBattler] = CompleteOnHealthbarDone;
+}
+
+static void OakOldManHandleExpUpdate(void)
+{
+ u8 monId = gBattleBufferA[gActiveBattler][1];
+
+ if (GetMonData(&gPlayerParty[monId], MON_DATA_LEVEL) >= MAX_LEVEL)
+ {
+ OakOldManBufferExecCompleted();
+ }
+ else
+ {
+ s16 expPointsToGive;
+ u8 taskId;
+
+ LoadBattleBarGfx(1);
+ GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES); // Unused return value.
+ expPointsToGive = T1_READ_16(&gBattleBufferA[gActiveBattler][2]);
+ taskId = CreateTask(Task_GiveExpToMon, 10);
+ gTasks[taskId].tExpTask_monId = monId;
+ gTasks[taskId].tExpTask_gainedExp = expPointsToGive;
+ gTasks[taskId].tExpTask_battler = gActiveBattler;
+ gBattlerControllerFuncs[gActiveBattler] = nullsub_81;
+ }
+}
+
+static void OakOldManHandleStatusIconUpdate(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleStatusAnimation(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleStatusXor(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleDataTransfer(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleDMA3Transfer(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandlePlayBGM(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleCmd32(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleTwoReturnValues(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleChosenMonReturnValue(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleOneReturnValue(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleOneReturnValue_Duplicate(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleCmd37(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleCmd38(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleCmd39(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleCmd40(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleHitAnimation(void)
+{
+ if (gSprites[gBattlerSpriteIds[gActiveBattler]].invisible == TRUE)
+ {
+ OakOldManBufferExecCompleted();
+ }
+ else
+ {
+ gDoingBattleAnim = TRUE;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].data[1] = 0;
+ DoHitAnimHealthboxEffect(gActiveBattler);
+ gBattlerControllerFuncs[gActiveBattler] = DoHitAnimBlinkSpriteEffect;
+ }
+}
+
+static void OakOldManHandleCmd42(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandlePlaySE(void)
+{
+ PlaySE(gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8));
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandlePlayFanfare(void)
+{
+ PlayFanfare(gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8));
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleFaintingCry(void)
+{
+ u16 species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES);
+
+ PlayCry1(species, 25);
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleIntroSlide(void)
+{
+ HandleIntroSlide(gBattleBufferA[gActiveBattler][1]);
+ gIntroSlideFlags |= 1;
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleIntroTrainerBallThrow(void)
+{
+ u8 paletteNum;
+ u8 taskId;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ {
+ SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattlerSpriteIds[gActiveBattler]]);
+ gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = 50;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].data[2] = -40;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].data[4] = gSprites[gBattlerSpriteIds[gActiveBattler]].pos1.y;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].callback = StartAnimLinearTranslation;
+ gSprites[gBattlerSpriteIds[gActiveBattler]].data[5] = gActiveBattler;
+ StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[gActiveBattler]], sub_80335F8);
+ StartSpriteAnim(&gSprites[gBattlerSpriteIds[gActiveBattler]], 1);
+ paletteNum = AllocSpritePalette(0xD6F8);
+ LoadCompressedPalette(gTrainerBackPicPaletteTable[gSaveBlock2Ptr->playerGender].data, 0x100 + paletteNum * 16, 32);
+ gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = paletteNum;
+ taskId = CreateTask(sub_80EB0A8, 5);
+ gTasks[taskId].data[0] = gActiveBattler;
+ if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].partyStatusSummaryShown)
+ gTasks[gBattlerStatusSummaryTaskId[gActiveBattler]].func = Task_HidePartyStatusSummary;
+ gBattleSpritesDataPtr->animationData->field_9_x1 = 1;
+ gBattlerControllerFuncs[gActiveBattler] = nullsub_13;
+ }
+ else
+ {
+ if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].partyStatusSummaryShown)
+ gTasks[gBattlerStatusSummaryTaskId[gActiveBattler]].func = Task_HidePartyStatusSummary;
+ OakOldManBufferExecCompleted();
+ }
+}
+
+static void sub_80EAF34(u8 battlerId)
+{
+ u16 species;
+
+ gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies = SPECIES_NONE;
+ gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1];
+ species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES);
+ gUnknown_3004FFC[battlerId] = CreateInvisibleSpriteWithCallback(sub_8033E3C);
+ SetMultiuseSpriteTemplateToPokemon(species, GetBattlerPosition(battlerId));
+ gBattlerSpriteIds[battlerId] = CreateSprite(&gMultiuseSpriteTemplate,
+ GetBattlerSpriteCoord(battlerId, 2),
+ GetBattlerSpriteDefault_Y(battlerId),
+ GetBattlerSpriteSubpriority(battlerId));
+ gSprites[gUnknown_3004FFC[battlerId]].data[1] = gBattlerSpriteIds[battlerId];
+ gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId;
+ gSprites[gBattlerSpriteIds[battlerId]].data[2] = species;
+ gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId;
+ StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]);
+ gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE;
+ gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy;
+ gSprites[gUnknown_3004FFC[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT);
+}
+
+static void sub_80EB0A8(u8 taskId)
+{
+ if (gTasks[taskId].data[1] < 31)
+ {
+ ++gTasks[taskId].data[1];
+ }
+ else
+ {
+ u8 savedActiveBattler = gActiveBattler;
+
+ gActiveBattler = gTasks[taskId].data[0];
+ gBattleBufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler];
+ sub_80EAF34(gActiveBattler);
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E7B4C;
+ gActiveBattler = savedActiveBattler;
+ DestroyTask(taskId);
+ }
+}
+
+static void OakOldManHandleDrawPartyStatusSummary(void)
+{
+ if (gBattleBufferA[gActiveBattler][1] != 0
+ && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
+ {
+ OakOldManBufferExecCompleted();
+ }
+ else
+ {
+ gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].partyStatusSummaryShown = TRUE;
+ gBattlerStatusSummaryTaskId[gActiveBattler] = CreatePartyStatusSummarySprites(gActiveBattler,
+ (struct HpAndStatus *)&gBattleBufferA[gActiveBattler][4],
+ gBattleBufferA[gActiveBattler][1],
+ gBattleBufferA[gActiveBattler][2]);
+ OakOldManBufferExecCompleted();
+ }
+}
+
+static void OakOldManHandleHidePartyStatusSummary(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleEndBounceEffect(void)
+{
+ EndBounceEffect(gActiveBattler, BOUNCE_HEALTHBOX);
+ EndBounceEffect(gActiveBattler, BOUNCE_MON);
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleSpriteInvisibility(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleBattleAnimation(void)
+{
+ u8 animationId = gBattleBufferA[gActiveBattler][1];
+ u16 argument = gBattleBufferA[gActiveBattler][2] | (gBattleBufferA[gActiveBattler][3] << 8);
+
+ if (TryHandleLaunchBattleTableAnimation(gActiveBattler, gActiveBattler, gActiveBattler, animationId, argument))
+ OakOldManBufferExecCompleted();
+ else
+ gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedBattleAnimation;
+}
+
+static void OakOldManHandleLinkStandbyMsg(void)
+{
+ switch (gBattleBufferA[gActiveBattler][1])
+ {
+ case 0:
+ case 1:
+ EndBounceEffect(gActiveBattler, BOUNCE_HEALTHBOX);
+ EndBounceEffect(gActiveBattler, BOUNCE_MON);
+ break;
+ case 2:
+ break;
+ }
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleResetActionMoveSelection(void)
+{
+ OakOldManBufferExecCompleted();
+}
+
+static void OakOldManHandleCmd55(void)
+{
+ gBattleOutcome = gBattleBufferA[gActiveBattler][1];
+ FadeOutMapMusic(5);
+ BeginFastPaletteFade(3);
+ OakOldManBufferExecCompleted();
+ if (!(gBattleTypeFlags & BATTLE_TYPE_IS_MASTER) && gBattleTypeFlags & BATTLE_TYPE_LINK)
+ gBattlerControllerFuncs[gActiveBattler] = sub_80E7930;
+}
+
+static void OakOldManCmdEnd(void)
+{
+}
+
+bool8 sub_80EB2E0(u8 a1)
+{
+ return gBattleStruct->field_96 & a1;
+}
+
+void sub_80EB2F4(u8 a1)
+{
+ gBattleStruct->field_96 |= a1;
+}
+
+void sub_80EB30C(void)
+{
+ u32 width = 0x1A;
+ u32 pal = 7;
+
+ FillBgTilemapBufferRect(0, 0x30, 0, 0xE, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x31, 1, 0xE, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x32, 2, 0xE, width, 1, pal);
+ FillBgTilemapBufferRect(0, 0x33, 0x1C, 0xE, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x34, 0x1D, 0xE, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x35, 0, 0xF, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x36, 1, 0xF, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x38, 0x1C, 0xF, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x39, 0x1D, 0xF, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x3A, 0, 0x10, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x3B, 1, 0x10, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x3C, 0x1C, 0x10, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x3D, 0x1D, 0x10, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x3A), 0, 0x11, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x3B), 1, 0x11, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x3C), 0x1C, 0x11, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x3D), 0x1D, 0x11, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x35), 0, 0x12, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x36), 1, 0x12, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x38), 0x1C, 0x12, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x39), 0x1D, 0x12, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x30), 0, 0x13, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x31), 1, 0x13, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x32), 2, 0x13, width, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x33), 0x1C, 0x13, 1, 1, pal);
+ FillBgTilemapBufferRect(0, BG_TILE_V_FLIP(0x34), 0x1D, 0x13, 1, 1, pal);
+}
+
+void sub_80EB524(void)
+{
+ u32 pal = 0;
+ u32 width = 0x1A;
+ u32 height;
+
+ FillBgTilemapBufferRect(0, 3, 0, 0xE, 1, 1, pal);
+ height = 4;
+ FillBgTilemapBufferRect(0, 4, 1, 0xE, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 5, 2, 0xE, width, 1, pal);
+ FillBgTilemapBufferRect(0, 6, 0x1C, 0xE, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 7, 0x1D, 0xE, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 8, 0, 0xF, 1, height, pal);
+ FillBgTilemapBufferRect(0, 9, 1, 0xF, 1, height, pal);
+ FillBgTilemapBufferRect(0, 0xA, 2, 0xF, width, height, pal);
+ FillBgTilemapBufferRect(0, 0xB, 0x1C, 0xF, 1, height, pal);
+ FillBgTilemapBufferRect(0, 0xC, 0x1D, 0xF, 1, height, pal);
+ FillBgTilemapBufferRect(0, 0xD, 0, 0x13, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0xE, 1, 0x13, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0xF, 2, 0x13, width, 1, pal);
+ FillBgTilemapBufferRect(0, 0x10, 0x1C, 0x13, 1, 1, pal);
+ FillBgTilemapBufferRect(0, 0x11, 0x1D, 0x13, 1, 1, pal);
+}
diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c
index 794b83b73..a9173f1a9 100644
--- a/src/battle_controller_opponent.c
+++ b/src/battle_controller_opponent.c
@@ -45,7 +45,7 @@ static void OpponentHandleTrainerSlideBack(void);
static void OpponentHandleFaintAnimation(void);
static void OpponentHandlePaletteFade(void);
static void OpponentHandleSuccessBallThrowAnim(void);
-static void OpponentHandleBallThrow(void);
+static void OpponentHandleBallThrowAnim(void);
static void OpponentHandlePause(void);
static void OpponentHandleMoveAnimation(void);
static void OpponentHandlePrintString(void);
@@ -116,7 +116,7 @@ static void (*const sOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(void) =
OpponentHandleFaintAnimation,
OpponentHandlePaletteFade,
OpponentHandleSuccessBallThrowAnim,
- OpponentHandleBallThrow,
+ OpponentHandleBallThrowAnim,
OpponentHandlePause,
OpponentHandleMoveAnimation,
OpponentHandlePrintString,
@@ -1231,7 +1231,7 @@ static void OpponentHandleSuccessBallThrowAnim(void)
OpponentBufferExecCompleted();
}
-static void OpponentHandleBallThrow(void)
+static void OpponentHandleBallThrowAnim(void)
{
OpponentBufferExecCompleted();
}
diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c
index a9bb5bc6e..f8d5958ba 100644
--- a/src/battle_controller_player.c
+++ b/src/battle_controller_player.c
@@ -839,7 +839,7 @@ void sub_802F6A8(void)
else
{
m4aSongNumStop(SE_HINSI);
- gMain.inBattle = 0;
+ gMain.inBattle = FALSE;
gMain.callback1 = gPreBattleCallback1;
SetMainCallback2(gMain.savedCallback);
}
@@ -1318,7 +1318,6 @@ static void WaitForMonSelection(void)
BtlController_EmitChosenMonReturnValue(1, gUnknown_203B0C1, gUnknown_203B0DC);
else
BtlController_EmitChosenMonReturnValue(1, 6, NULL);
-
if ((gBattleBufferA[gActiveBattler][1] & 0xF) == 1)
PrintLinkStandbyMsg();
PlayerBufferExecCompleted();
diff --git a/src/battle_controllers.c b/src/battle_controllers.c
index 544af1006..f3530fc4b 100644
--- a/src/battle_controllers.c
+++ b/src/battle_controllers.c
@@ -85,9 +85,9 @@ static void InitSinglePlayerBtlControllers(void)
gBattleMainFunc = BeginBattleIntro;
if (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE)
{
- gBattlerControllerFuncs[0] = SetControllerToPokedude;
+ gBattlerControllerFuncs[0] = SetControllerToPokeDude;
gBattlerPositions[0] = B_POSITION_PLAYER_LEFT;
- gBattlerControllerFuncs[1] = SetControllerToPokedude;
+ gBattlerControllerFuncs[1] = SetControllerToPokeDude;
gBattlerPositions[1] = B_POSITION_OPPONENT_LEFT;
gBattlersCount = 2;
}
@@ -95,8 +95,8 @@ static void InitSinglePlayerBtlControllers(void)
{
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
gBattlerControllerFuncs[0] = SetControllerToSafari;
- else if (gBattleTypeFlags & (BATTLE_TYPE_OLDMAN_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE))
- gBattlerControllerFuncs[0] = SetControllerToOakOrOldman;
+ else if (gBattleTypeFlags & (BATTLE_TYPE_OLD_MAN_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE))
+ gBattlerControllerFuncs[0] = SetControllerToOakOrOldMan;
else
gBattlerControllerFuncs[0] = SetControllerToPlayer;
gBattlerPositions[0] = B_POSITION_PLAYER_LEFT;
@@ -110,13 +110,13 @@ static void InitSinglePlayerBtlControllers(void)
gBattleMainFunc = BeginBattleIntro;
if (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE)
{
- gBattlerControllerFuncs[0] = SetControllerToPokedude;
+ gBattlerControllerFuncs[0] = SetControllerToPokeDude;
gBattlerPositions[0] = B_POSITION_PLAYER_LEFT;
- gBattlerControllerFuncs[1] = SetControllerToPokedude;
+ gBattlerControllerFuncs[1] = SetControllerToPokeDude;
gBattlerPositions[1] = B_POSITION_OPPONENT_LEFT;
- gBattlerControllerFuncs[2] = SetControllerToPokedude;
+ gBattlerControllerFuncs[2] = SetControllerToPokeDude;
gBattlerPositions[2] = B_POSITION_PLAYER_RIGHT;
- gBattlerControllerFuncs[3] = SetControllerToPokedude;
+ gBattlerControllerFuncs[3] = SetControllerToPokeDude;
gBattlerPositions[3] = B_POSITION_OPPONENT_RIGHT;
gBattlersCount = MAX_BATTLERS_COUNT;
}
@@ -774,7 +774,7 @@ void BtlController_EmitPrintSelectionString(u8 bufferId, u16 stringID)
sBattleBuffersTransferData[1] = CONTROLLER_PRINTSTRINGPLAYERONLY;
sBattleBuffersTransferData[2] = stringID;
sBattleBuffersTransferData[3] = (stringID & 0xFF00) >> 8;
- stringInfo = (struct BattleMsgData*)(&sBattleBuffersTransferData[4]);
+ stringInfo = (struct BattleMsgData *)(&sBattleBuffersTransferData[4]);
stringInfo->currentMove = gCurrentMove;
stringInfo->originallyUsedMove = gChosenMove;
stringInfo->lastItem = gLastUsedItem;
diff --git a/src/battle_main.c b/src/battle_main.c
new file mode 100644
index 000000000..1b1614a5a
--- /dev/null
+++ b/src/battle_main.c
@@ -0,0 +1,4412 @@
+#include "global.h"
+#include "battle.h"
+#include "battle_anim.h"
+#include "battle_ai_script_commands.h"
+#include "battle_controllers.h"
+#include "battle_interface.h"
+#include "battle_main.h"
+#include "battle_message.h"
+#include "battle_scripts.h"
+#include "battle_setup.h"
+#include "battle_tower.h"
+#include "battle_string_ids.h"
+#include "berry.h"
+#include "bg.h"
+#include "data.h"
+#include "decompress.h"
+#include "dma3.h"
+#include "event_data.h"
+#include "evolution_scene.h"
+#include "graphics.h"
+#include "gpu_regs.h"
+#include "help_system.h"
+#include "international_string_util.h"
+#include "item.h"
+#include "link.h"
+#include "link_rfu.h"
+#include "load_save.h"
+#include "main.h"
+#include "malloc.h"
+#include "m4a.h"
+#include "palette.h"
+#include "party_menu.h"
+#include "pokeball.h"
+#include "pokedex.h"
+#include "pokemon.h"
+#include "quest_log.h"
+#include "random.h"
+#include "roamer.h"
+#include "safari_zone.h"
+#include "scanline_effect.h"
+#include "sound.h"
+#include "sprite.h"
+#include "string_util.h"
+#include "strings.h"
+#include "task.h"
+#include "text.h"
+#include "trig.h"
+#include "vs_seeker.h"
+#include "util.h"
+#include "window.h"
+#include "cable_club.h"
+#include "constants/abilities.h"
+#include "constants/battle_move_effects.h"
+#include "constants/hold_effects.h"
+#include "constants/items.h"
+#include "constants/moves.h"
+#include "constants/pokemon.h"
+#include "constants/songs.h"
+#include "constants/species.h"
+#include "constants/trainers.h"
+#include "constants/trainer_classes.h"
+
+static void sub_80111EC(struct Sprite *sprite);
+static void HandleAction_UseMove(void);
+static void HandleAction_Switch(void);
+static void HandleAction_UseItem(void);
+static void HandleAction_Run(void);
+static void HandleAction_WatchesCarefully(void);
+static void HandleAction_SafariZoneBallThrow(void);
+static void HandleAction_ThrowPokeblock(void);
+static void HandleAction_GoNear(void);
+static void HandleAction_SafariZoneRun(void);
+static void HandleAction_OldManBallThrow(void);
+static void HandleAction_TryFinish(void);
+static void HandleAction_NothingIsFainted(void);
+static void HandleAction_ActionFinished(void);
+static void HandleEndTurn_ContinueBattle(void);
+static void HandleEndTurn_BattleWon(void);
+static void HandleEndTurn_BattleLost(void);
+static void HandleEndTurn_RanFromBattle(void);
+static void HandleEndTurn_MonFled(void);
+static void HandleEndTurn_FinishBattle(void);
+static void CB2_InitBattleInternal(void);
+static void CB2_PreInitMultiBattle(void);
+static void CB2_HandleStartMultiBattle(void);
+static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum);
+static void CB2_HandleStartBattle(void);
+static void TryCorrectShedinjaLanguage(struct Pokemon *mon);
+static void BattleMainCB1(void);
+static void CB2_QuitPokeDudeBattle(void);
+static void sub_80111FC(struct Sprite *sprite);
+static void sub_8011B94(void);
+static void sub_8011BB0(void);
+static void SpriteCB_MoveWildMonToRight(struct Sprite *sprite);
+static void SpriteCB_WildMonShowHealthbox(struct Sprite *sprite);
+static void sub_8011E3C(struct Sprite *sprite);
+static void SpriteCB_AnimFaintOpponent(struct Sprite *sprite);
+static void sub_8012060(struct Sprite *sprite);
+static void oac_poke_ally_(struct Sprite *sprite);
+static void SpriteCallbackDummy3(struct Sprite *sprite);
+static void SpriteCB_BounceEffect(struct Sprite *sprite);
+static void sub_8012398(struct Sprite *sprite);
+static void BattleStartClearSetData(void);
+static void BattleIntroGetMonsData(void);
+static void TurnValuesCleanUp(bool8 var0);
+static void SpecialStatusesClear(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 BattleIntroRecordMonsToDex(void);
+static void BattleIntroOpponentSendsOutMonAnimation(void);
+static void BattleIntroPlayerSendsOutMonAnimation(void);
+static void TryDoEventsBeforeFirstTurn(void);
+static void HandleTurnActionSelectionState(void);
+static void RunTurnActionsFunctions(void);
+static void SetActionsAndBattlersTurnOrder(void);
+static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void);
+static void HandleEndTurn_FinishBattle(void);
+static void FreeResetData_ReturnToOvOrDoEvolutions(void);
+static void ReturnFromBattleToOverworld(void);
+static void TryEvolvePokemon(void);
+static void WaitForEvoSceneToFinish(void);
+
+EWRAM_DATA u16 gBattle_BG0_X = 0;
+EWRAM_DATA u16 gBattle_BG0_Y = 0;
+EWRAM_DATA u16 gBattle_BG1_X = 0;
+EWRAM_DATA u16 gBattle_BG1_Y = 0;
+EWRAM_DATA u16 gBattle_BG2_X = 0;
+EWRAM_DATA u16 gBattle_BG2_Y = 0;
+EWRAM_DATA u16 gBattle_BG3_X = 0;
+EWRAM_DATA u16 gBattle_BG3_Y = 0;
+EWRAM_DATA u16 gBattle_WIN0H = 0;
+EWRAM_DATA u16 gBattle_WIN0V = 0;
+EWRAM_DATA u16 gBattle_WIN1H = 0;
+EWRAM_DATA u16 gBattle_WIN1V = 0;
+EWRAM_DATA u8 gDisplayedStringBattle[300] = {0};
+EWRAM_DATA u8 gBattleTextBuff1[TEXT_BUFF_ARRAY_COUNT] = {0};
+EWRAM_DATA u8 gBattleTextBuff2[TEXT_BUFF_ARRAY_COUNT] = {0};
+EWRAM_DATA u8 gBattleTextBuff3[TEXT_BUFF_ARRAY_COUNT] = {0};
+static EWRAM_DATA u32 gUnknown_2022AE8[25] = {0};
+EWRAM_DATA u32 gBattleTypeFlags = 0;
+EWRAM_DATA u8 gBattleTerrain = 0;
+EWRAM_DATA u32 gUnknown_2022B54 = 0;
+EWRAM_DATA struct UnknownPokemonStruct4 gUnknown_2022B58[3] = {0};
+EWRAM_DATA u8 *gUnknown_2022BB8 = NULL;
+EWRAM_DATA u8 *gUnknown_2022BBC = NULL;
+EWRAM_DATA u16 *gUnknown_2022BC0 = NULL;
+EWRAM_DATA u8 gBattleBufferA[MAX_BATTLERS_COUNT][0x200] = {0};
+EWRAM_DATA u8 gBattleBufferB[MAX_BATTLERS_COUNT][0x200] = {0};
+EWRAM_DATA u8 gActiveBattler = 0;
+EWRAM_DATA u32 gBattleControllerExecFlags = 0;
+EWRAM_DATA u8 gBattlersCount = 0;
+EWRAM_DATA u16 gBattlerPartyIndexes[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gBattlerPositions[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gActionsByTurnOrder[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gBattlerByTurnOrder[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gCurrentTurnActionNumber = 0;
+EWRAM_DATA u8 gCurrentActionFuncId = 0;
+EWRAM_DATA struct BattlePokemon gBattleMons[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gBattlerSpriteIds[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gCurrMovePos = 0;
+EWRAM_DATA u8 gChosenMovePos = 0;
+EWRAM_DATA u16 gCurrentMove = 0;
+EWRAM_DATA u16 gChosenMove = 0;
+EWRAM_DATA u16 gCalledMove = 0;
+EWRAM_DATA s32 gBattleMoveDamage = 0;
+EWRAM_DATA s32 gHpDealt = 0;
+EWRAM_DATA s32 gTakenDmg[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u16 gLastUsedItem = 0;
+EWRAM_DATA u8 gLastUsedAbility = 0;
+EWRAM_DATA u8 gBattlerAttacker = 0;
+EWRAM_DATA u8 gBattlerTarget = 0;
+EWRAM_DATA u8 gBattlerFainted = 0;
+EWRAM_DATA u8 gEffectBattler = 0;
+EWRAM_DATA u8 gPotentialItemEffectBattler = 0;
+EWRAM_DATA u8 gAbsentBattlerFlags = 0;
+EWRAM_DATA u8 gCritMultiplier = 0;
+EWRAM_DATA u8 gMultiHitCounter = 0;
+EWRAM_DATA const u8 *gBattlescriptCurrInstr = NULL;
+EWRAM_DATA u32 gUnusedBattleMainVar = 0;
+EWRAM_DATA u8 gChosenActionByBattler[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA const u8 *gSelectionBattleScripts[MAX_BATTLERS_COUNT] = {NULL};
+EWRAM_DATA u16 gLastPrintedMoves[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u16 gLastMoves[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u16 gLastLandedMoves[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u16 gLastHitByType[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u16 gLastResultingMoves[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u16 gLockedMoves[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gLastHitBy[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u16 gChosenMoveByBattler[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gMoveResultFlags = 0;
+EWRAM_DATA u32 gHitMarker = 0;
+static EWRAM_DATA u8 gUnknown_2023DD4[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gTakenDmgByBattler[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gUnknown_2023DDC = 0;
+EWRAM_DATA u16 gSideStatuses[2] = {0};
+EWRAM_DATA struct SideTimer gSideTimers[2] = {0};
+EWRAM_DATA u32 gStatuses3[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u16 gPauseCounterBattle = 0;
+EWRAM_DATA u16 gPaydayMoney = 0;
+EWRAM_DATA u16 gRandomTurnNumber = 0;
+EWRAM_DATA u8 gBattleCommunication[BATTLE_COMMUNICATION_ENTRIES_COUNT] = {0};
+EWRAM_DATA u8 gBattleOutcome = 0;
+EWRAM_DATA struct ProtectStruct gProtectStructs[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA struct SpecialStatus gSpecialStatuses[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u16 gBattleWeather = 0;
+EWRAM_DATA struct WishFutureKnock gWishFutureKnock = {0};
+EWRAM_DATA u16 gIntroSlideFlags = 0;
+EWRAM_DATA u8 gSentPokesToOpponent[2] = {0};
+EWRAM_DATA u16 gDynamicBasePower = 0;
+EWRAM_DATA u16 gExpShareExp = 0;
+EWRAM_DATA struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA struct BattleScripting gBattleScripting = {0};
+EWRAM_DATA struct BattleStruct *gBattleStruct = NULL;
+EWRAM_DATA u8 *gLinkBattleSendBuffer = NULL;
+EWRAM_DATA u8 *gLinkBattleRecvBuffer = NULL;
+EWRAM_DATA struct BattleResources *gBattleResources = NULL;
+EWRAM_DATA u8 gActionSelectionCursor[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gMoveSelectionCursor[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gBattlerStatusSummaryTaskId[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA u8 gBattlerInMenuId = 0;
+EWRAM_DATA bool8 gDoingBattleAnim = FALSE;
+EWRAM_DATA u32 gTransformedPersonalities[MAX_BATTLERS_COUNT] = {0};
+EWRAM_DATA struct BattleSpriteData *gBattleSpritesDataPtr = NULL;
+EWRAM_DATA struct MonSpritesGfx *gMonSpritesGfxPtr = NULL;
+EWRAM_DATA u16 gBattleMovePower = 0;
+EWRAM_DATA u16 gMoveToLearn = 0;
+EWRAM_DATA u8 gBattleMonForms[MAX_BATTLERS_COUNT] = {0};
+
+void (*gPreBattleCallback1)(void);
+void (*gBattleMainFunc)(void);
+struct BattleResults gBattleResults;
+u8 gLeveledUpInBattle;
+void (*gBattlerControllerFuncs[MAX_BATTLERS_COUNT])(void);
+u8 gHealthboxSpriteIds[MAX_BATTLERS_COUNT];
+u8 gMultiUsePlayerCursor;
+u8 gNumberOfMovesToChoose;
+u8 gUnknown_3004FFC[MAX_BATTLERS_COUNT];
+
+static const struct ScanlineEffectParams sIntroScanlineParams16Bit =
+{
+ &REG_BG3HOFS, SCANLINE_EFFECT_DMACNT_16BIT, 1
+};
+
+const struct SpriteTemplate gUnknown_824EFF0 =
+{
+ .tileTag = 0,
+ .paletteTag = 0,
+ .oam = &gDummyOamData,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = sub_80111EC,
+};
+
+static const u8 sText_ShedinjaJpnName[] = _("ヌケニン"); // Nukenin
+
+const struct OamData gOamData_824F010 =
+{
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_NORMAL,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0,
+ .priority = 2,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+const struct OamData gOamData_824F018 =
+{
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_NORMAL,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .bpp = ST_OAM_4BPP,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0,
+ .priority = 2,
+ .paletteNum = 2,
+ .affineParam = 0,
+};
+
+// not used
+static const union AnimCmd gUnknown_824F020[] =
+{
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_JUMP(0),
+};
+
+// not used
+static const union AnimCmd *const gUnknown_824F028[] =
+{
+ gUnknown_824F020,
+};
+
+// not used
+static const union AffineAnimCmd gUnknown_824F02C[] =
+{
+ AFFINEANIMCMD_FRAME(-0x10, 0x0, 0, 4),
+ AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 0x3C),
+ AFFINEANIMCMD_JUMP(1),
+};
+
+// not used
+static const union AffineAnimCmd *const gUnknown_824F044[] =
+{
+ gUnknown_824F02C,
+};
+
+static const s8 gUnknown_824F048[] = { -32, -16, -16, -32, -32, 0, 0, 0 };
+
+// format: attacking type, defending type, damage multiplier
+// the multiplier is a (decimal) fixed-point number:
+// 20 is ×2.0 TYPE_MUL_SUPER_EFFECTIVE
+// 10 is ×1.0 TYPE_MUL_NORMAL
+// 05 is ×0.5 TYPE_MUL_NOT_EFFECTIVE
+// 00 is ×0.0 TYPE_MUL_NO_EFFECT
+const u8 gTypeEffectiveness[336] =
+{
+ TYPE_NORMAL, TYPE_ROCK, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_NORMAL, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FIRE, TYPE_FIRE, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FIRE, TYPE_WATER, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FIRE, TYPE_GRASS, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FIRE, TYPE_ICE, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FIRE, TYPE_BUG, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FIRE, TYPE_ROCK, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FIRE, TYPE_DRAGON, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FIRE, TYPE_STEEL, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_WATER, TYPE_FIRE, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_WATER, TYPE_WATER, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_WATER, TYPE_GRASS, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_WATER, TYPE_GROUND, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_WATER, TYPE_ROCK, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_WATER, TYPE_DRAGON, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_ELECTRIC, TYPE_WATER, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_ELECTRIC, TYPE_ELECTRIC, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_ELECTRIC, TYPE_GRASS, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_ELECTRIC, TYPE_GROUND, TYPE_MUL_NO_EFFECT,
+ TYPE_ELECTRIC, TYPE_FLYING, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_ELECTRIC, TYPE_DRAGON, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GRASS, TYPE_FIRE, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GRASS, TYPE_WATER, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_GRASS, TYPE_GRASS, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GRASS, TYPE_POISON, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GRASS, TYPE_GROUND, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_GRASS, TYPE_FLYING, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GRASS, TYPE_BUG, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GRASS, TYPE_ROCK, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_GRASS, TYPE_DRAGON, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GRASS, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_ICE, TYPE_WATER, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_ICE, TYPE_GRASS, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_ICE, TYPE_ICE, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_ICE, TYPE_GROUND, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_ICE, TYPE_FLYING, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_ICE, TYPE_DRAGON, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_ICE, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_ICE, TYPE_FIRE, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FIGHTING, TYPE_NORMAL, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FIGHTING, TYPE_ICE, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FIGHTING, TYPE_POISON, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FIGHTING, TYPE_FLYING, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FIGHTING, TYPE_PSYCHIC, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FIGHTING, TYPE_BUG, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FIGHTING, TYPE_ROCK, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FIGHTING, TYPE_DARK, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FIGHTING, TYPE_STEEL, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_POISON, TYPE_GRASS, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_POISON, TYPE_POISON, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_POISON, TYPE_GROUND, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_POISON, TYPE_ROCK, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_POISON, TYPE_GHOST, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_POISON, TYPE_STEEL, TYPE_MUL_NO_EFFECT,
+ TYPE_GROUND, TYPE_FIRE, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_GROUND, TYPE_ELECTRIC, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_GROUND, TYPE_GRASS, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GROUND, TYPE_POISON, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_GROUND, TYPE_FLYING, TYPE_MUL_NO_EFFECT,
+ TYPE_GROUND, TYPE_BUG, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GROUND, TYPE_ROCK, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_GROUND, TYPE_STEEL, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FLYING, TYPE_ELECTRIC, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FLYING, TYPE_GRASS, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FLYING, TYPE_FIGHTING, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FLYING, TYPE_BUG, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_FLYING, TYPE_ROCK, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FLYING, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_PSYCHIC, TYPE_FIGHTING, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_PSYCHIC, TYPE_POISON, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_PSYCHIC, TYPE_PSYCHIC, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_PSYCHIC, TYPE_DARK, TYPE_MUL_NO_EFFECT,
+ TYPE_PSYCHIC, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_BUG, TYPE_FIRE, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_BUG, TYPE_GRASS, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_BUG, TYPE_FIGHTING, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_BUG, TYPE_POISON, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_BUG, TYPE_FLYING, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_BUG, TYPE_PSYCHIC, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_BUG, TYPE_GHOST, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_BUG, TYPE_DARK, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_BUG, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_ROCK, TYPE_FIRE, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_ROCK, TYPE_ICE, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_ROCK, TYPE_FIGHTING, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_ROCK, TYPE_GROUND, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_ROCK, TYPE_FLYING, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_ROCK, TYPE_BUG, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_ROCK, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GHOST, TYPE_NORMAL, TYPE_MUL_NO_EFFECT,
+ TYPE_GHOST, TYPE_PSYCHIC, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_GHOST, TYPE_DARK, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GHOST, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_GHOST, TYPE_GHOST, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_DRAGON, TYPE_DRAGON, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_DRAGON, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_DARK, TYPE_FIGHTING, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_DARK, TYPE_PSYCHIC, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_DARK, TYPE_GHOST, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_DARK, TYPE_DARK, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_DARK, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_STEEL, TYPE_FIRE, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_STEEL, TYPE_WATER, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_STEEL, TYPE_ELECTRIC, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_STEEL, TYPE_ICE, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_STEEL, TYPE_ROCK, TYPE_MUL_SUPER_EFFECTIVE,
+ TYPE_STEEL, TYPE_STEEL, TYPE_MUL_NOT_EFFECTIVE,
+ TYPE_FORESIGHT, TYPE_FORESIGHT, TYPE_MUL_NO_EFFECT,
+ TYPE_NORMAL, TYPE_GHOST, TYPE_MUL_NO_EFFECT,
+ TYPE_FIGHTING, TYPE_GHOST, TYPE_MUL_NO_EFFECT,
+ TYPE_ENDTABLE, TYPE_ENDTABLE, TYPE_MUL_NO_EFFECT
+};
+
+const u8 gTypeNames[][TYPE_NAME_LENGTH + 1] =
+{
+ _("NORMAL"),
+ _("FIGHT"),
+ _("FLYING"),
+ _("POISON"),
+ _("GROUND"),
+ _("ROCK"),
+ _("BUG"),
+ _("GHOST"),
+ _("STEEL"),
+ _("???"),
+ _("FIRE"),
+ _("WATER"),
+ _("GRASS"),
+ _("ELECTR"),
+ _("PSYCHC"),
+ _("ICE"),
+ _("DRAGON"),
+ _("DARK"),
+};
+
+// This is a factor in how much money you get for beating a trainer.
+const struct TrainerMoney gTrainerMoneyTable[] =
+{
+ { CLASS_LEADER_2, 25 },
+ { CLASS_ELITE_FOUR_2, 25 },
+ { CLASS_PKMN_PROF, 25 },
+ { CLASS_RIVAL, 4 },
+ { CLASS_RIVAL_2, 9 },
+ { CLASS_CHAMPION_2, 25 },
+ { CLASS_YOUNGSTER_2, 4 },
+ { CLASS_BUG_CATCHER_2, 3 },
+ { CLASS_HIKER_2, 9 },
+ { CLASS_BIRD_KEEPER_2, 6 },
+ { CLASS_PICNICKER_2, 5 },
+ { CLASS_SUPER_NERD, 6 },
+ { CLASS_FISHERMAN_2, 9 },
+ { CLASS_TEAM_ROCKET, 8 },
+ { CLASS_LASS_2, 4 },
+ { CLASS_BEAUTY_2, 18 },
+ { CLASS_BLACK_BELT_2, 6 },
+ { CLASS_CUE_BALL, 6 },
+ { CLASS_CHANNELER, 8 },
+ { CLASS_ROCKER, 6 },
+ { CLASS_GENTLEMAN_2, 18 },
+ { CLASS_BURGLAR, 22 },
+ { CLASS_SWIMMER_MALE_2, 1 },
+ { CLASS_ENGINEER, 12 },
+ { CLASS_JUGGLER, 10 },
+ { CLASS_SAILOR_2, 8 },
+ { CLASS_COOLTRAINER_2, 9 },
+ { CLASS_POKEMANIAC_2, 12 },
+ { CLASS_TAMER, 10 },
+ { CLASS_CAMPER_2, 5 },
+ { CLASS_PSYCHIC_2, 5 },
+ { CLASS_BIKER, 5 },
+ { CLASS_GAMER, 18 },
+ { CLASS_SCIENTIST, 12 },
+ { CLASS_CRUSH_GIRL, 6 },
+ { CLASS_TUBER_3, 1 },
+ { CLASS_PKMN_BREEDER_2, 7 },
+ { CLASS_PKMN_RANGER_2, 9 },
+ { CLASS_AROMA_LADY_2, 7 },
+ { CLASS_RUIN_MANIAC_2, 12 },
+ { CLASS_LADY_2, 50 },
+ { CLASS_PAINTER, 4 },
+ { CLASS_TWINS_2, 3 },
+ { CLASS_YOUNG_COUPLE_2, 7 },
+ { CLASS_SIS_AND_BRO_2, 1 },
+ { CLASS_COOL_COUPLE, 6 },
+ { CLASS_CRUSH_KIN, 6 },
+ { CLASS_SWIMMER_FEMALE_2, 1 },
+ { CLASS_PLAYER, 1 },
+ { CLASS_LEADER, 25 },
+ { CLASS_ELITE_FOUR, 25 },
+ { CLASS_LASS, 4 },
+ { CLASS_YOUNGSTER, 4 },
+ { CLASS_PKMN_TRAINER_3, 15 },
+ { CLASS_HIKER, 10 },
+ { CLASS_BEAUTY, 20 },
+ { CLASS_FISHERMAN, 10 },
+ { CLASS_LADY, 50 },
+ { CLASS_TRIATHLETE, 10 },
+ { CLASS_TEAM_AQUA, 5 },
+ { CLASS_TWINS, 3 },
+ { CLASS_SWIMMER_FEMALE, 2 },
+ { CLASS_BUG_CATCHER, 4 },
+ { CLASS_SCHOOL_KID, 5 },
+ { CLASS_RICH_BOY, 50 },
+ { CLASS_SR_AND_JR, 4 },
+ { CLASS_BLACK_BELT, 8 },
+ { CLASS_TUBER, 1 },
+ { CLASS_HEX_MANIAC, 6 },
+ { CLASS_PKMN_BREEDER, 10 },
+ { CLASS_TEAM_MAGMA, 5 },
+ { CLASS_INTERVIEWER, 12 },
+ { CLASS_TUBER_2, 1 },
+ { CLASS_YOUNG_COUPLE, 8 },
+ { CLASS_GUITARIST, 8 },
+ { CLASS_GENTLEMAN, 20 },
+ { CLASS_CHAMPION, 50 },
+ { CLASS_MAGMA_LEADER, 20 },
+ { CLASS_BATTLE_GIRL, 6 },
+ { CLASS_SWIMMER_MALE, 2 },
+ { CLASS_POKEFAN, 20 },
+ { CLASS_EXPERT, 10 },
+ { CLASS_DRAGON_TAMER, 12 },
+ { CLASS_BIRD_KEEPER, 8 },
+ { CLASS_NINJA_BOY, 3 },
+ { CLASS_PARASOL_LADY, 10 },
+ { CLASS_BUG_MANIAC, 15 },
+ { CLASS_SAILOR, 8 },
+ { CLASS_COLLECTOR, 15 },
+ { CLASS_PKMN_RANGER, 12 },
+ { CLASS_MAGMA_ADMIN, 10 },
+ { CLASS_AROMA_LADY, 10 },
+ { CLASS_RUIN_MANIAC, 15 },
+ { CLASS_COOLTRAINER, 12 },
+ { CLASS_POKEMANIAC, 15 },
+ { CLASS_KINDLER, 8 },
+ { CLASS_CAMPER, 4 },
+ { CLASS_PICNICKER, 4 },
+ { CLASS_PSYCHIC, 6 },
+ { CLASS_SIS_AND_BRO, 3 },
+ { CLASS_OLD_COUPLE, 10 },
+ { CLASS_AQUA_ADMIN, 10 },
+ { CLASS_AQUA_LEADER, 20 },
+ { CLASS_BOSS, 25 },
+ { 0xFF, 5 },
+};
+
+#include "data/text/abilities.h"
+
+static void (*const sTurnActionsFuncsTable[])(void) =
+{
+ [B_ACTION_USE_MOVE] = HandleAction_UseMove,
+ [B_ACTION_USE_ITEM] = HandleAction_UseItem,
+ [B_ACTION_SWITCH] = HandleAction_Switch,
+ [B_ACTION_RUN] = HandleAction_Run,
+ [B_ACTION_SAFARI_WATCH_CAREFULLY] = HandleAction_WatchesCarefully,
+ [B_ACTION_SAFARI_BALL] = HandleAction_SafariZoneBallThrow,
+ [B_ACTION_SAFARI_POKEBLOCK] = HandleAction_ThrowPokeblock,
+ [B_ACTION_SAFARI_GO_NEAR] = HandleAction_GoNear,
+ [B_ACTION_SAFARI_RUN] = HandleAction_SafariZoneRun,
+ [B_ACTION_OLDMAN_THROW] = HandleAction_OldManBallThrow,
+ [B_ACTION_EXEC_SCRIPT] = HandleAction_RunBattleScript,
+ [B_ACTION_TRY_FINISH] = HandleAction_TryFinish,
+ [B_ACTION_FINISHED] = HandleAction_ActionFinished,
+ [B_ACTION_NOTHING_FAINTED] = HandleAction_NothingIsFainted,
+};
+
+static void (*const sEndTurnFuncsTable[])(void) =
+{
+ [0] = HandleEndTurn_ContinueBattle, //B_OUTCOME_NONE?
+ [B_OUTCOME_WON] = HandleEndTurn_BattleWon,
+ [B_OUTCOME_LOST] = HandleEndTurn_BattleLost,
+ [B_OUTCOME_DREW] = HandleEndTurn_BattleLost,
+ [B_OUTCOME_RAN] = HandleEndTurn_RanFromBattle,
+ [B_OUTCOME_PLAYER_TELEPORTED] = HandleEndTurn_FinishBattle,
+ [B_OUTCOME_MON_FLED] = HandleEndTurn_MonFled,
+ [B_OUTCOME_CAUGHT] = HandleEndTurn_FinishBattle,
+ [B_OUTCOME_NO_SAFARI_BALLS] = HandleEndTurn_FinishBattle,
+};
+
+const u8 gStatusConditionString_PoisonJpn[8] = _("どく$$$$$");
+const u8 gStatusConditionString_SleepJpn[8] = _("ねむり$$$$");
+const u8 gStatusConditionString_ParalysisJpn[8] = _("まひ$$$$$");
+const u8 gStatusConditionString_BurnJpn[8] = _("やけど$$$$");
+const u8 gStatusConditionString_IceJpn[8] = _("こおり$$$$");
+const u8 gStatusConditionString_ConfusionJpn[8] = _("こんらん$$$");
+const u8 gStatusConditionString_LoveJpn[8] = _("メロメロ$$$");
+
+const u8 *const gStatusConditionStringsTable[7][2] =
+{
+ { gStatusConditionString_PoisonJpn, gText_Poison },
+ { gStatusConditionString_SleepJpn, gText_Sleep },
+ { gStatusConditionString_ParalysisJpn, gText_Paralysis },
+ { gStatusConditionString_BurnJpn, gText_Burn },
+ { gStatusConditionString_IceJpn, gText_Ice },
+ { gStatusConditionString_ConfusionJpn, gText_Confusion },
+ { gStatusConditionString_LoveJpn, gText_Love }
+};
+
+void CB2_InitBattle(void)
+{
+ MoveSaveBlocks_ResetHeap();
+ AllocateBattleResources();
+ AllocateBattleSpritesData();
+ AllocateMonSpritesGfx();
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ HandleLinkBattleSetup();
+ SetMainCallback2(CB2_PreInitMultiBattle);
+ gBattleCommunication[MULTIUSE_STATE] = 0;
+ }
+ else
+ {
+ CB2_InitBattleInternal();
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK))
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ HelpSystem_SetSomeVariable2(0x19);
+ else
+ HelpSystem_SetSomeVariable2(0x18);
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ {
+ HelpSystem_SetSomeVariable2(0x1A);
+ }
+ else
+ {
+ HelpSystem_SetSomeVariable2(0x17);
+ }
+ }
+ }
+}
+
+static void CB2_InitBattleInternal(void)
+{
+ s32 i;
+
+ SetHBlankCallback(NULL);
+ SetVBlankCallback(NULL);
+ CpuFill32(0, (void *)VRAM, VRAM_SIZE);
+ SetGpuReg(REG_OFFSET_MOSAIC, 0);
+ SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(0, 0xF0));
+ SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(0x50, 0x51));
+ SetGpuReg(REG_OFFSET_WININ, 0);
+ SetGpuReg(REG_OFFSET_WINOUT, 0);
+ gBattle_WIN0H = WIN_RANGE(0, 0xF0);
+ gBattle_WIN0V = WIN_RANGE(0x50, 0x51);
+ ScanlineEffect_Clear();
+ for (i = 0; i < 80; ++i)
+ {
+ gScanlineEffectRegBuffers[0][i] = 0xF0;
+ gScanlineEffectRegBuffers[1][i] = 0xF0;
+ }
+ for (; i < 160; ++i)
+ {
+ gScanlineEffectRegBuffers[0][i] = 0xFF10;
+ gScanlineEffectRegBuffers[1][i] = 0xFF10;
+ }
+ ScanlineEffect_SetParams(sIntroScanlineParams16Bit);
+ ResetPaletteFade();
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gBattle_BG1_X = 0;
+ gBattle_BG1_Y = 0;
+ gBattle_BG2_X = 0;
+ gBattle_BG2_Y = 0;
+ gBattle_BG3_X = 0;
+ gBattle_BG3_Y = 0;
+ gBattleTerrain = BattleSetup_GetTerrainId();
+ sub_800F34C();
+ LoadBattleTextboxAndBackground();
+ ResetSpriteData();
+ ResetTasks();
+ DrawBattleEntryBackground();
+ FreeAllSpritePalettes();
+ gReservedSpritePaletteCount = 4;
+ SetVBlankCallback(VBlankCB_Battle);
+ SetUpBattleVars();
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ SetMainCallback2(CB2_HandleStartMultiBattle);
+ else
+ SetMainCallback2(CB2_HandleStartBattle);
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK))
+ {
+ CreateNPCTrainerParty(&gEnemyParty[0], gTrainerBattleOpponent_A);
+ SetWildMonHeldItem();
+ }
+ gMain.inBattle = TRUE;
+ for (i = 0; i < PARTY_SIZE; ++i)
+ AdjustFriendship(&gPlayerParty[i], 3);
+ gBattleCommunication[MULTIUSE_STATE] = 0;
+}
+
+static void sub_800FFEC(void)
+{
+ u16 r6 = 0;
+ u16 species = SPECIES_NONE;
+ u16 hp = 0;
+ u32 status = 0;
+ s32 i;
+
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+ hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
+ status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS);
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp != 0 && status == 0)
+ r6 |= 1 << i * 2;
+ if (species == SPECIES_NONE)
+ continue;
+ if (hp != 0 && (species == SPECIES_EGG || status != 0))
+ r6 |= 2 << i * 2;
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp == 0)
+ r6 |= 3 << i * 2;
+ }
+ gBattleStruct->field_186 = r6;
+ *(&gBattleStruct->field_187) = r6 >> 8;
+}
+
+static void SetPlayerBerryDataInBattleStruct(void)
+{
+ s32 i;
+ struct BattleStruct *battleStruct = gBattleStruct;
+ struct BattleEnigmaBerry *battleBerry = &battleStruct->battleEnigmaBerry;
+
+ if (IsEnigmaBerryValid() == TRUE)
+ {
+ for (i = 0; i < BERRY_NAME_LENGTH; ++i)
+ battleBerry->name[i] = gSaveBlock1Ptr->enigmaBerry.berry.name[i];
+ battleBerry->name[i] = EOS;
+ for (i = 0; i < BERRY_ITEM_EFFECT_COUNT; ++i)
+ battleBerry->itemEffect[i] = gSaveBlock1Ptr->enigmaBerry.itemEffect[i];
+ battleBerry->holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ battleBerry->holdEffectParam = gSaveBlock1Ptr->enigmaBerry.holdEffectParam;
+ }
+ else
+ {
+ const struct Berry *berryData = GetBerryInfo(ItemIdToBerryType(ITEM_ENIGMA_BERRY));
+
+ for (i = 0; i < BERRY_NAME_LENGTH; ++i)
+ battleBerry->name[i] = berryData->name[i];
+ battleBerry->name[i] = EOS;
+ for (i = 0; i < BERRY_ITEM_EFFECT_COUNT; ++i)
+ battleBerry->itemEffect[i] = 0;
+ battleBerry->holdEffect = HOLD_EFFECT_NONE;
+ battleBerry->holdEffectParam = 0;
+ }
+}
+
+static void SetAllPlayersBerryData(void)
+{
+ s32 i, j;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK))
+ {
+ if (IsEnigmaBerryValid() == TRUE)
+ {
+ for (i = 0; i < BERRY_NAME_LENGTH; ++i)
+ {
+ gEnigmaBerries[0].name[i] = gSaveBlock1Ptr->enigmaBerry.berry.name[i];
+ gEnigmaBerries[2].name[i] = gSaveBlock1Ptr->enigmaBerry.berry.name[i];
+ }
+ gEnigmaBerries[0].name[i] = EOS;
+ gEnigmaBerries[2].name[i] = EOS;
+ for (i = 0; i < BERRY_ITEM_EFFECT_COUNT; ++i)
+ {
+ gEnigmaBerries[0].itemEffect[i] = gSaveBlock1Ptr->enigmaBerry.itemEffect[i];
+ gEnigmaBerries[2].itemEffect[i] = gSaveBlock1Ptr->enigmaBerry.itemEffect[i];
+ }
+ gEnigmaBerries[0].holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ gEnigmaBerries[2].holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ gEnigmaBerries[0].holdEffectParam = gSaveBlock1Ptr->enigmaBerry.holdEffectParam;
+ gEnigmaBerries[2].holdEffectParam = gSaveBlock1Ptr->enigmaBerry.holdEffectParam;
+ }
+ else
+ {
+ const struct Berry *berryData = GetBerryInfo(ItemIdToBerryType(ITEM_ENIGMA_BERRY));
+
+ for (i = 0; i < BERRY_NAME_LENGTH; ++i)
+ {
+ gEnigmaBerries[0].name[i] = berryData->name[i];
+ gEnigmaBerries[2].name[i] = berryData->name[i];
+ }
+ gEnigmaBerries[0].name[i] = EOS;
+ gEnigmaBerries[2].name[i] = EOS;
+ for (i = 0; i < BERRY_ITEM_EFFECT_COUNT; ++i)
+ {
+ gEnigmaBerries[0].itemEffect[i] = 0;
+ gEnigmaBerries[2].itemEffect[i] = 0;
+ }
+ gEnigmaBerries[0].holdEffect = HOLD_EFFECT_NONE;
+ gEnigmaBerries[2].holdEffect = HOLD_EFFECT_NONE;
+ gEnigmaBerries[0].holdEffectParam = 0;
+ gEnigmaBerries[2].holdEffectParam = 0;
+ }
+ }
+ else
+ {
+ s32 numPlayers;
+ struct BattleEnigmaBerry *src;
+ u8 battlerId;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ for (i = 0; i < 4; ++i)
+ {
+ src = (struct BattleEnigmaBerry *)(gBlockRecvBuffer[i] + 2);
+ battlerId = gLinkPlayers[i].id;
+ for (j = 0; j < BERRY_NAME_LENGTH; ++j)
+ gEnigmaBerries[battlerId].name[j] = src->name[j];
+ gEnigmaBerries[battlerId].name[j] = EOS;
+ for (j = 0; j < BERRY_ITEM_EFFECT_COUNT; ++j)
+ gEnigmaBerries[battlerId].itemEffect[j] = src->itemEffect[j];
+ gEnigmaBerries[battlerId].holdEffect = src->holdEffect;
+ gEnigmaBerries[battlerId].holdEffectParam = src->holdEffectParam;
+ }
+ }
+ else
+ {
+ for (i = 0; i < 2; ++i)
+ {
+ src = (struct BattleEnigmaBerry *)(gBlockRecvBuffer[i] + 2);
+ for (j = 0; j < BERRY_NAME_LENGTH; ++j)
+ {
+ gEnigmaBerries[i].name[j] = src->name[j];
+ gEnigmaBerries[i + 2].name[j] = src->name[j];
+ }
+ gEnigmaBerries[i].name[j] = EOS;
+ gEnigmaBerries[i + 2].name[j] = EOS;
+ for (j = 0; j < BERRY_ITEM_EFFECT_COUNT; ++j)
+ {
+ gEnigmaBerries[i].itemEffect[j] = src->itemEffect[j];
+ gEnigmaBerries[i + 2].itemEffect[j] = src->itemEffect[j];
+ }
+ gEnigmaBerries[i].holdEffect = src->holdEffect;
+ gEnigmaBerries[i + 2].holdEffect = src->holdEffect;
+ gEnigmaBerries[i].holdEffectParam = src->holdEffectParam;
+ gEnigmaBerries[i + 2].holdEffectParam = src->holdEffectParam;
+ }
+ }
+ }
+}
+
+static void sub_8010414(u8 arg0, u8 arg1)
+{
+ u8 var = 0;
+
+ if (gBlockRecvBuffer[0][0] == 256)
+ {
+ if (arg1 == 0)
+ gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER;
+ else
+ gBattleTypeFlags |= BATTLE_TYPE_TRAINER;
+ ++var;
+ }
+ if (var == 0)
+ {
+ s32 i;
+
+ for (i = 0; i < arg0; ++i)
+ if (gBlockRecvBuffer[0][0] != gBlockRecvBuffer[i][0])
+ break;
+ if (i == arg0)
+ {
+ if (arg1 == 0)
+ gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER;
+ else
+ gBattleTypeFlags |= BATTLE_TYPE_TRAINER;
+ ++var;
+ }
+ if (var == 0)
+ {
+ for (i = 0; i < arg0; ++i)
+ {
+ if (gBlockRecvBuffer[i][0] == 0x201)
+ if (i != arg1 && i < arg1)
+ break;
+ if (gBlockRecvBuffer[i][0] > 0x201 && i != arg1)
+ break;
+ }
+ if (i == arg0)
+ gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER;
+ else
+ gBattleTypeFlags |= BATTLE_TYPE_TRAINER;
+ }
+ }
+}
+
+static void CB2_HandleStartBattle(void)
+{
+ u8 playerMultiplayerId;
+ u8 enemyMultiplayerId;
+
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ playerMultiplayerId = GetMultiplayerId();
+ gBattleStruct->multiplayerId = playerMultiplayerId;
+ enemyMultiplayerId = playerMultiplayerId ^ BIT_SIDE;
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(3);
+ sub_80357C8();
+ gBattleCommunication[MULTIUSE_STATE] = 1;
+ }
+ if (gWirelessCommType)
+ LoadWirelessStatusIndicatorSpriteGfx();
+ break;
+ case 1:
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ if (IsLinkTaskFinished())
+ {
+ *(&gBattleStruct->field_184) = 1;
+ *(&gBattleStruct->field_185) = 2;
+ sub_800FFEC();
+ SetPlayerBerryDataInBattleStruct();
+ SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_184, 32);
+ gBattleCommunication[MULTIUSE_STATE] = 2;
+ }
+ if (gWirelessCommType != 0)
+ CreateWirelessStatusIndicatorSprite(0, 0);
+ }
+ }
+ else
+ {
+ gBattleTypeFlags |= BATTLE_TYPE_IS_MASTER;
+ gBattleCommunication[MULTIUSE_STATE] = 15;
+ SetAllPlayersBerryData();
+ }
+ break;
+ case 2:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ u8 taskId;
+
+ ResetBlockReceivedFlags();
+ sub_8010414(2, playerMultiplayerId);
+ SetAllPlayersBerryData();
+ taskId = CreateTask(sub_800F6FC, 0);
+ gTasks[taskId].data[1] = 270;
+ gTasks[taskId].data[2] = 90;
+ gTasks[taskId].data[5] = 0;
+ gTasks[taskId].data[3] = gBattleStruct->field_186 | (gBattleStruct->field_187 << 8);
+ gTasks[taskId].data[4] = gBlockRecvBuffer[enemyMultiplayerId][1];
+ SetDeoxysStats();
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 3:
+ if (IsLinkTaskFinished())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gPlayerParty, sizeof(struct Pokemon) * 2);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 4:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ memcpy(gEnemyParty, gBlockRecvBuffer[enemyMultiplayerId], sizeof(struct Pokemon) * 2);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 7:
+ if (IsLinkTaskFinished())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gPlayerParty + 2, sizeof(struct Pokemon) * 2);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 8:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ memcpy(gEnemyParty + 2, gBlockRecvBuffer[enemyMultiplayerId], sizeof(struct Pokemon) * 2);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 11:
+ if (IsLinkTaskFinished())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gPlayerParty + 4, sizeof(struct Pokemon) * 2);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 12:
+ if ((GetBlockReceivedStatus() & 3) == 3)
+ {
+ ResetBlockReceivedFlags();
+ memcpy(gEnemyParty + 4, gBlockRecvBuffer[enemyMultiplayerId], sizeof(struct Pokemon) * 2);
+ TryCorrectShedinjaLanguage(&gEnemyParty[0]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[1]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[2]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[3]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[4]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[5]);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 15:
+ sub_800D30C();
+ ++gBattleCommunication[MULTIUSE_STATE];
+ gBattleCommunication[SPRITES_INIT_STATE1] = 0;
+ gBattleCommunication[SPRITES_INIT_STATE2] = 0;
+ break;
+ case 16:
+ if (BattleInitAllSprites(&gBattleCommunication[SPRITES_INIT_STATE1], &gBattleCommunication[SPRITES_INIT_STATE2]))
+ {
+ gPreBattleCallback1 = gMain.callback1;
+ gMain.callback1 = BattleMainCB1;
+ SetMainCallback2(BattleMainCB2);
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ gBattleTypeFlags |= BATTLE_TYPE_20;
+ }
+ }
+ break;
+ case 5:
+ case 9:
+ case 13:
+ ++gBattleCommunication[MULTIUSE_STATE];
+ gBattleCommunication[1] = 1;
+ case 6:
+ case 10:
+ case 14:
+ if (--gBattleCommunication[1] == 0)
+ ++gBattleCommunication[MULTIUSE_STATE];
+ break;
+ }
+}
+
+static void sub_80108C4(void)
+{
+ s32 i, j;
+ u8 *nick, *cur;
+
+ for (i = 0; i < 3; ++i)
+ {
+ gUnknown_2022B58[i].species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES);
+ gUnknown_2022B58[i].heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
+ nick = gUnknown_2022B58[i].nickname;
+ GetMonData(&gPlayerParty[i], MON_DATA_NICKNAME, nick);
+ gUnknown_2022B58[i].level = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
+ gUnknown_2022B58[i].hp = GetMonData(&gPlayerParty[i], MON_DATA_HP);
+ gUnknown_2022B58[i].maxhp = GetMonData(&gPlayerParty[i], MON_DATA_MAX_HP);
+ gUnknown_2022B58[i].status = GetMonData(&gPlayerParty[i], MON_DATA_STATUS);
+ gUnknown_2022B58[i].personality = GetMonData(&gPlayerParty[i], MON_DATA_PERSONALITY);
+ gUnknown_2022B58[i].gender = GetMonGender(&gPlayerParty[i]);
+ StripExtCtrlCodes(nick);
+ if (GetMonData(&gPlayerParty[i], MON_DATA_LANGUAGE) != LANGUAGE_JAPANESE)
+ {
+ for (cur = nick, j = 0; cur[j] != EOS; ++j)
+ ;
+ while (j < 6)
+ cur[j++] = 0;
+ cur[j] = EOS;
+ }
+ }
+ memcpy(&gBattleStruct->field_184, gUnknown_2022B58, sizeof(gUnknown_2022B58));
+}
+
+static void CB2_PreInitMultiBattle(void)
+{
+ s32 i;
+ u8 playerMultiplierId;
+ u8 r4 = 0xF;
+ u16 *savedBattleTypeFlags;
+ void (**savedCallback)(void);
+
+ playerMultiplierId = GetMultiplayerId();
+ gBattleStruct->multiplayerId = playerMultiplierId;
+ savedCallback = &gBattleStruct->savedCallback;
+ savedBattleTypeFlags = &gBattleStruct->savedBattleTypeFlags;
+
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ if (gReceivedRemoteLinkPlayers != 0 && IsLinkTaskFinished())
+ {
+ sub_80108C4();
+ SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_184, sizeof(gUnknown_2022B58));
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 1:
+ if ((GetBlockReceivedStatus() & r4) == r4)
+ {
+ ResetBlockReceivedFlags();
+ for (i = 0; i < 4; ++i)
+ {
+ if (i == playerMultiplierId)
+ continue;
+ if ((!(gLinkPlayers[i].id & 1) && !(gLinkPlayers[playerMultiplierId].id & 1))
+ || (gLinkPlayers[i].id & 1 && gLinkPlayers[playerMultiplierId].id & 1))
+ memcpy(gUnknown_2022B58, gBlockRecvBuffer[i], sizeof(gUnknown_2022B58));
+ }
+ ++gBattleCommunication[MULTIUSE_STATE];
+ *savedCallback = gMain.savedCallback;
+ *savedBattleTypeFlags = gBattleTypeFlags;
+ gMain.savedCallback = CB2_PreInitMultiBattle;
+ sub_8128198();
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ ++gBattleCommunication[MULTIUSE_STATE];
+ if (gWirelessCommType)
+ sub_800AB9C();
+ else
+ sub_800AAC0();
+ }
+ break;
+ case 3:
+ if (gWirelessCommType)
+ {
+ if (IsLinkRfuTaskFinished())
+ {
+ gBattleTypeFlags = *savedBattleTypeFlags;
+ gMain.savedCallback = *savedCallback;
+ SetMainCallback2(CB2_InitBattleInternal);
+ }
+ }
+ else if (gReceivedRemoteLinkPlayers == 0)
+ {
+ gBattleTypeFlags = *savedBattleTypeFlags;
+ gMain.savedCallback = *savedCallback;
+ SetMainCallback2(CB2_InitBattleInternal);
+ }
+ break;
+ }
+}
+
+static void CB2_HandleStartMultiBattle(void)
+{
+ u8 playerMultiplayerId;
+ s32 id;
+ u8 taskId;
+
+ playerMultiplayerId = GetMultiplayerId();
+ gBattleStruct->multiplayerId = playerMultiplayerId;
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(3);
+ sub_80357C8();
+ gBattleCommunication[MULTIUSE_STATE] = 1;
+ }
+ if (gWirelessCommType)
+ LoadWirelessStatusIndicatorSpriteGfx();
+ break;
+ case 1:
+ if (gReceivedRemoteLinkPlayers != 0)
+ {
+ if (IsLinkTaskFinished())
+ {
+ *(&gBattleStruct->field_184) = 1;
+ *(&gBattleStruct->field_185) = 2;
+ sub_800FFEC();
+ SetPlayerBerryDataInBattleStruct();
+ SendBlock(bitmask_all_link_players_but_self(), &gBattleStruct->field_184, 32);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ if (gWirelessCommType)
+ CreateWirelessStatusIndicatorSprite(0, 0);
+ }
+ break;
+ case 2:
+ if ((GetBlockReceivedStatus() & 0xF) == 0xF)
+ {
+ ResetBlockReceivedFlags();
+ sub_8010414(4, playerMultiplayerId);
+ SetAllPlayersBerryData();
+ SetDeoxysStats();
+ memcpy(gDecompressionBuffer, gPlayerParty, sizeof(struct Pokemon) * 3);
+ taskId = CreateTask(sub_800F6FC, 0);
+ gTasks[taskId].data[1] = 270;
+ gTasks[taskId].data[2] = 90;
+ gTasks[taskId].data[5] = 0;
+ gTasks[taskId].data[3] = 0;
+ gTasks[taskId].data[4] = 0;
+ for (id = 0; id < MAX_LINK_PLAYERS; ++id)
+ {
+ switch (gLinkPlayers[id].id)
+ {
+ case 0:
+ gTasks[taskId].data[3] |= gBlockRecvBuffer[id][1] & 0x3F;
+ break;
+ case 1:
+ gTasks[taskId].data[4] |= gBlockRecvBuffer[id][1] & 0x3F;
+ break;
+ case 2:
+ gTasks[taskId].data[3] |= (gBlockRecvBuffer[id][1] & 0x3F) << 6;
+ break;
+ case 3:
+ gTasks[taskId].data[4] |= (gBlockRecvBuffer[id][1] & 0x3F) << 6;
+ break;
+ }
+ }
+ ZeroPlayerPartyMons();
+ ZeroEnemyPartyMons();
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ else
+ {
+ break;
+ }
+ // fall through
+ case 3:
+ if (IsLinkTaskFinished())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gDecompressionBuffer, sizeof(struct Pokemon) * 2);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 4:
+ if ((GetBlockReceivedStatus() & 0xF) == 0xF)
+ {
+ ResetBlockReceivedFlags();
+ for (id = 0; id < MAX_LINK_PLAYERS; ++id)
+ {
+ if (id == playerMultiplayerId)
+ {
+ switch (gLinkPlayers[id].id)
+ {
+ case 0:
+ case 3:
+ memcpy(gPlayerParty, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ case 1:
+ case 2:
+ memcpy(gPlayerParty + 3, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ }
+ }
+ else
+ {
+ if ((!(gLinkPlayers[id].id & 1) && !(gLinkPlayers[playerMultiplayerId].id & 1))
+ || ((gLinkPlayers[id].id & 1) && (gLinkPlayers[playerMultiplayerId].id & 1)))
+ {
+ switch (gLinkPlayers[id].id)
+ {
+ case 0:
+ case 3:
+ memcpy(gPlayerParty, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ case 1:
+ case 2:
+ memcpy(gPlayerParty + 3, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ }
+ }
+ else
+ {
+ switch (gLinkPlayers[id].id)
+ {
+ case 0:
+ case 3:
+ memcpy(gEnemyParty, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ case 1:
+ case 2:
+ memcpy(gEnemyParty + 3, gBlockRecvBuffer[id], sizeof(struct Pokemon) * 2);
+ break;
+ }
+ }
+ }
+ }
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 7:
+ if (IsLinkTaskFinished())
+ {
+ SendBlock(bitmask_all_link_players_but_self(), gDecompressionBuffer + sizeof(struct Pokemon) * 2, sizeof(struct Pokemon));
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 8:
+ if ((GetBlockReceivedStatus() & 0xF) == 0xF)
+ {
+ ResetBlockReceivedFlags();
+ for (id = 0; id < MAX_LINK_PLAYERS; ++id)
+ {
+ if (id == playerMultiplayerId)
+ {
+ switch (gLinkPlayers[id].id)
+ {
+ case 0:
+ case 3:
+ memcpy(gPlayerParty + 2, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ case 1:
+ case 2:
+ memcpy(gPlayerParty + 5, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ }
+ }
+ else
+ {
+ if ((!(gLinkPlayers[id].id & 1) && !(gLinkPlayers[playerMultiplayerId].id & 1))
+ || ((gLinkPlayers[id].id & 1) && (gLinkPlayers[playerMultiplayerId].id & 1)))
+ {
+ switch (gLinkPlayers[id].id)
+ {
+ case 0:
+ case 3:
+ memcpy(gPlayerParty + 2, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ case 1:
+ case 2:
+ memcpy(gPlayerParty + 5, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ }
+ }
+ else
+ {
+ switch (gLinkPlayers[id].id)
+ {
+ case 0:
+ case 3:
+ memcpy(gEnemyParty + 2, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ case 1:
+ case 2:
+ memcpy(gEnemyParty + 5, gBlockRecvBuffer[id], sizeof(struct Pokemon));
+ break;
+ }
+ }
+ }
+ }
+ TryCorrectShedinjaLanguage(&gPlayerParty[0]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[1]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[2]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[3]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[4]);
+ TryCorrectShedinjaLanguage(&gPlayerParty[5]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[0]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[1]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[2]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[3]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[4]);
+ TryCorrectShedinjaLanguage(&gEnemyParty[5]);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 11:
+ sub_800D30C();
+ ++gBattleCommunication[MULTIUSE_STATE];
+ gBattleCommunication[SPRITES_INIT_STATE1] = 0;
+ gBattleCommunication[SPRITES_INIT_STATE2] = 0;
+ break;
+ case 12:
+ if (BattleInitAllSprites(&gBattleCommunication[SPRITES_INIT_STATE1], &gBattleCommunication[SPRITES_INIT_STATE2]))
+ {
+ gPreBattleCallback1 = gMain.callback1;
+ gMain.callback1 = BattleMainCB1;
+ SetMainCallback2(BattleMainCB2);
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ gBattleTypeFlags |= BATTLE_TYPE_20;
+ }
+ break;
+ case 5:
+ case 9:
+ ++gBattleCommunication[0];
+ gBattleCommunication[SPRITES_INIT_STATE1] = 1;
+ // fall through
+ case 6:
+ case 10:
+ if (--gBattleCommunication[SPRITES_INIT_STATE1] == 0)
+ ++gBattleCommunication[0];
+ break;
+ }
+}
+
+void BattleMainCB2(void)
+{
+ AnimateSprites();
+ BuildOamBuffer();
+ RunTextPrinters();
+ UpdatePaletteFade();
+ RunTasks();
+ if (JOY_HELD(B_BUTTON) && gBattleTypeFlags & BATTLE_TYPE_POKEDUDE)
+ {
+ gSpecialVar_Result = gBattleOutcome = B_OUTCOME_DREW;
+ ResetPaletteFadeControl();
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
+ SetMainCallback2(CB2_QuitPokeDudeBattle);
+ }
+}
+
+void FreeRestoreBattleData(void)
+{
+ gMain.callback1 = gPreBattleCallback1;
+ gScanlineEffect.state = 3;
+ gMain.inBattle = FALSE;
+ ZeroEnemyPartyMons();
+ m4aSongNumStop(SE_HINSI);
+ FreeMonSpritesGfx();
+ FreeBattleSpritesData();
+ FreeBattleResources();
+}
+
+static void CB2_QuitPokeDudeBattle(void)
+{
+ UpdatePaletteFade();
+ if (!gPaletteFade.active)
+ {
+ FreeRestoreBattleData();
+ FreeAllWindowBuffers();
+ SetMainCallback2(gMain.savedCallback);
+ }
+}
+
+static void sub_80111EC(struct Sprite *sprite)
+{
+ sprite->data[0] = 0;
+ sprite->callback = sub_80111FC;
+}
+
+static void sub_80111FC(struct Sprite *sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ gUnknown_2022BC0 = AllocZeroed(0x1000);
+ ++sprite->data[0];
+ sprite->data[1] = 0;
+ sprite->data[2] = 0x281;
+ sprite->data[3] = 0;
+ sprite->data[4] = 1;
+ // fall through
+ case 1:
+ if (--sprite->data[4] == 0)
+ {
+ s32 i, r2, r0;
+
+ sprite->data[4] = 2;
+ r2 = sprite->data[1] + sprite->data[3] * 32;
+ r0 = sprite->data[2] - sprite->data[3] * 32;
+ for (i = 0; i <= 29; i += 2)
+ {
+ *(&gUnknown_2022BC0[r2] + i) = 0x3D;
+ *(&gUnknown_2022BC0[r0] + i) = 0x3D;
+ }
+ if (++sprite->data[3] == 21)
+ {
+ ++sprite->data[0];
+ sprite->data[1] = 32;
+ }
+ }
+ break;
+ case 2:
+ if (--sprite->data[1] == 20)
+ {
+ if (gUnknown_2022BC0 != NULL)
+ {
+ memset(gUnknown_2022BC0, 0, 0x1000);
+ FREE_AND_SET_NULL(gUnknown_2022BC0);
+ }
+ SetMainCallback2(CB2_InitBattle);
+ }
+ break;
+ }
+}
+
+static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum)
+{
+ u32 nameHash = 0;
+ u32 personalityValue;
+ u8 fixedIV;
+ s32 i, j;
+
+ if (trainerNum == TRAINER_SECRET_BASE)
+ return 0;
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
+ && !(gBattleTypeFlags & (BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_TOWER)))
+ {
+ ZeroEnemyPartyMons();
+ for (i = 0; i < gTrainers[trainerNum].partySize; ++i)
+ {
+
+ if (gTrainers[trainerNum].doubleBattle == TRUE)
+ personalityValue = 0x80;
+ else if (gTrainers[trainerNum].encounterMusic_gender & 0x80)
+ personalityValue = 0x78;
+ else
+ personalityValue = 0x88;
+ for (j = 0; gTrainers[trainerNum].trainerName[j] != EOS; ++j)
+ nameHash += gTrainers[trainerNum].trainerName[j];
+ switch (gTrainers[trainerNum].partyFlags)
+ {
+ case 0:
+ {
+ const struct TrainerMonNoItemDefaultMoves *partyData = gTrainers[trainerNum].party.NoItemDefaultMoves;
+
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; ++j)
+ nameHash += gSpeciesNames[partyData[i].species][j];
+ personalityValue += nameHash << 8;
+ fixedIV = partyData[i].iv * 31 / 255;
+ CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
+ break;
+ }
+ case F_TRAINER_PARTY_CUSTOM_MOVESET:
+ {
+ const struct TrainerMonNoItemCustomMoves *partyData = gTrainers[trainerNum].party.NoItemCustomMoves;
+
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; ++j)
+ nameHash += gSpeciesNames[partyData[i].species][j];
+ personalityValue += nameHash << 8;
+ fixedIV = partyData[i].iv * 31 / 255;
+ CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
+ for (j = 0; j < MAX_MON_MOVES; ++j)
+ {
+ SetMonData(&party[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]);
+ SetMonData(&party[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp);
+ }
+ break;
+ }
+ case F_TRAINER_PARTY_HELD_ITEM:
+ {
+ const struct TrainerMonItemDefaultMoves *partyData = gTrainers[trainerNum].party.ItemDefaultMoves;
+
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; ++j)
+ nameHash += gSpeciesNames[partyData[i].species][j];
+ personalityValue += nameHash << 8;
+ fixedIV = partyData[i].iv * 31 / 255;
+ CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
+
+ SetMonData(&party[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem);
+ break;
+ }
+ case F_TRAINER_PARTY_CUSTOM_MOVESET | F_TRAINER_PARTY_HELD_ITEM:
+ {
+ const struct TrainerMonItemCustomMoves *partyData = gTrainers[trainerNum].party.ItemCustomMoves;
+
+ for (j = 0; gSpeciesNames[partyData[i].species][j] != EOS; ++j)
+ nameHash += gSpeciesNames[partyData[i].species][j];
+ personalityValue += nameHash << 8;
+ fixedIV = partyData[i].iv * 31 / 255;
+ CreateMon(&party[i], partyData[i].species, partyData[i].lvl, fixedIV, TRUE, personalityValue, OT_ID_RANDOM_NO_SHINY, 0);
+ SetMonData(&party[i], MON_DATA_HELD_ITEM, &partyData[i].heldItem);
+ for (j = 0; j < MAX_MON_MOVES; ++j)
+ {
+ SetMonData(&party[i], MON_DATA_MOVE1 + j, &partyData[i].moves[j]);
+ SetMonData(&party[i], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp);
+ }
+ break;
+ }
+ }
+ }
+ gBattleTypeFlags |= gTrainers[trainerNum].doubleBattle;
+ }
+ return gTrainers[trainerNum].partySize;
+}
+
+// not used
+static void sub_80116CC(void)
+{
+ if (REG_VCOUNT < 0xA0 && REG_VCOUNT >= 0x6F)
+ REG_BG0CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(24) | BGCNT_16COLOR | BGCNT_TXT256x512;
+}
+
+void VBlankCB_Battle(void)
+{
+ // Change gRngSeed every vblank.
+ Random();
+ SetGpuReg(REG_OFFSET_BG0HOFS, gBattle_BG0_X);
+ SetGpuReg(REG_OFFSET_BG0VOFS, gBattle_BG0_Y);
+ SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X);
+ SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y);
+ SetGpuReg(REG_OFFSET_BG2HOFS, gBattle_BG2_X);
+ SetGpuReg(REG_OFFSET_BG2VOFS, gBattle_BG2_Y);
+ SetGpuReg(REG_OFFSET_BG3HOFS, gBattle_BG3_X);
+ SetGpuReg(REG_OFFSET_BG3VOFS, gBattle_BG3_Y);
+ SetGpuReg(REG_OFFSET_WIN0H, gBattle_WIN0H);
+ SetGpuReg(REG_OFFSET_WIN0V, gBattle_WIN0V);
+ SetGpuReg(REG_OFFSET_WIN1H, gBattle_WIN1H);
+ SetGpuReg(REG_OFFSET_WIN1V, gBattle_WIN1V);
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+ ScanlineEffect_InitHBlankDmaTransfer();
+}
+
+void nullsub_9(struct Sprite *sprite)
+{
+}
+
+static void sub_80117BC(struct Sprite *sprite)
+{
+ if (sprite->data[0] != 0)
+ sprite->pos1.x = sprite->data[1] + ((sprite->data[2] & 0xFF00) >> 8);
+ else
+ sprite->pos1.x = sprite->data[1] - ((sprite->data[2] & 0xFF00) >> 8);
+ sprite->data[2] += 0x180;
+ if (sprite->affineAnimEnded)
+ {
+ FreeSpriteTilesByTag(ANIM_SPRITES_START);
+ FreeSpritePaletteByTag(ANIM_SPRITES_START);
+ FreeSpriteOamMatrix(sprite);
+ DestroySprite(sprite);
+ }
+}
+
+void sub_801182C(struct Sprite *sprite)
+{
+ StartSpriteAffineAnim(sprite, 1);
+ sprite->callback = sub_80117BC;
+ PlaySE(SE_BT_START);
+}
+
+static void sub_801184C(u8 taskId)
+{
+ struct Pokemon *party1 = NULL;
+ struct Pokemon *party2 = NULL;
+ u8 multiplayerId = gBattleStruct->multiplayerId;
+ u32 r7;
+ s32 i;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ switch (gLinkPlayers[multiplayerId].id)
+ {
+ case 0:
+ case 2:
+ party1 = gPlayerParty;
+ party2 = gEnemyParty;
+ break;
+ case 1:
+ case 3:
+ party1 = gEnemyParty;
+ party2 = gPlayerParty;
+ break;
+ }
+ }
+ else
+ {
+ party1 = gPlayerParty;
+ party2 = gEnemyParty;
+ }
+ r7 = 0;
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ u16 species = GetMonData(&party1[i], MON_DATA_SPECIES2);
+ u16 hp = GetMonData(&party1[i], MON_DATA_HP);
+ u32 status = GetMonData(&party1[i], MON_DATA_STATUS);
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp != 0 && status == 0)
+ r7 |= 1 << i * 2;
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (hp != 0 && (species == SPECIES_EGG || status != 0))
+ r7 |= 2 << i * 2;
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp == 0)
+ r7 |= 3 << i * 2;
+ }
+ gTasks[taskId].data[3] = r7;
+ r7 = 0;
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ u16 species = GetMonData(&party2[i], MON_DATA_SPECIES2);
+ u16 hp = GetMonData(&party2[i], MON_DATA_HP);
+ u32 status = GetMonData(&party2[i], MON_DATA_STATUS);
+
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp != 0 && status == 0)
+ r7 |= 1 << i * 2;
+ if (species == SPECIES_NONE)
+ continue;
+ if (hp != 0 && (species == SPECIES_EGG || status != 0))
+ r7 |= 2 << i * 2;
+ if (species == SPECIES_NONE)
+ continue;
+ if (species != SPECIES_EGG && hp == 0)
+ r7 |= 3 << i * 2;
+ }
+ gTasks[taskId].data[4] = r7;
+}
+
+void sub_8011A1C(void)
+{
+ s32 i;
+ u8 taskId;
+
+ SetHBlankCallback(NULL);
+ SetVBlankCallback(NULL);
+ CpuFill32(0, (void *)VRAM, VRAM_SIZE);
+ SetGpuReg(REG_OFFSET_MOSAIC, 0);
+ SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(0, 0xF0));
+ SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(0x50, 0x51));
+ SetGpuReg(REG_OFFSET_WININ, 0);
+ SetGpuReg(REG_OFFSET_WINOUT, 0);
+ gBattle_WIN0H = WIN_RANGE(0, 0xF0);
+ gBattle_WIN0V = WIN_RANGE(0x50, 0x51);
+ ScanlineEffect_Clear();
+ for (i = 0; i < 80; ++i)
+ {
+ gScanlineEffectRegBuffers[0][i] = 0xF0;
+ gScanlineEffectRegBuffers[1][i] = 0xF0;
+ }
+
+ for (; i < 160; ++i)
+ {
+ gScanlineEffectRegBuffers[0][i] = 0xFF10;
+ gScanlineEffectRegBuffers[1][i] = 0xFF10;
+ }
+ ResetPaletteFade();
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gBattle_BG1_X = 0;
+ gBattle_BG1_Y = 0;
+ gBattle_BG2_X = 0;
+ gBattle_BG2_Y = 0;
+ gBattle_BG3_X = 0;
+ gBattle_BG3_Y = 0;
+ sub_800F34C();
+ LoadCompressedPalette(gBattleTextboxPalette, 0, 64);
+ LoadBattleMenuWindowGfx();
+ ResetSpriteData();
+ ResetTasks();
+ DrawBattleEntryBackground();
+ SetGpuReg(REG_OFFSET_WINOUT, WININ_WIN0_BG0 | WININ_WIN0_BG1 | WININ_WIN0_BG2 | WININ_WIN0_OBJ | WININ_WIN0_CLR);
+ FreeAllSpritePalettes();
+ gReservedSpritePaletteCount = 4;
+ SetVBlankCallback(VBlankCB_Battle);
+ taskId = CreateTask(sub_800F6FC, 0);
+ gTasks[taskId].data[1] = 270;
+ gTasks[taskId].data[2] = 90;
+ gTasks[taskId].data[5] = 1;
+ sub_801184C(taskId);
+ SetMainCallback2(sub_8011B94);
+ gBattleCommunication[MULTIUSE_STATE] = 0;
+}
+
+static void sub_8011B94(void)
+{
+ sub_8011BB0();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+ RunTasks();
+}
+
+static void sub_8011BB0(void)
+{
+ s32 i;
+
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ ShowBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ gBattleCommunication[1] = 0xFF;
+ ++gBattleCommunication[MULTIUSE_STATE];
+ break;
+ case 1:
+ if (--gBattleCommunication[1] == 0)
+ {
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(gMain.savedCallback);
+ sub_812C224();
+ FreeMonSpritesGfx();
+ FreeBattleSpritesData();
+ FreeBattleResources();
+ }
+ break;
+ }
+}
+
+u32 sub_8011C44(u8 arrayId, u8 caseId)
+{
+ u32 ret = 0;
+
+ switch (caseId)
+ {
+ case 0:
+ ret = gBattleBgTemplates[arrayId].bg;
+ break;
+ case 1:
+ ret = gBattleBgTemplates[arrayId].charBaseIndex;
+ break;
+ case 2:
+ ret = gBattleBgTemplates[arrayId].mapBaseIndex;
+ break;
+ case 3:
+ ret = gBattleBgTemplates[arrayId].screenSize;
+ break;
+ case 4:
+ ret = gBattleBgTemplates[arrayId].paletteMode;
+ break;
+ case 5:
+ ret = gBattleBgTemplates[arrayId].priority;
+ break;
+ case 6:
+ ret = gBattleBgTemplates[arrayId].baseTile;
+ break;
+ }
+ return ret;
+}
+
+static void TryCorrectShedinjaLanguage(struct Pokemon *mon)
+{
+ u8 nickname[POKEMON_NAME_LENGTH + 1];
+ u8 language = LANGUAGE_JAPANESE;
+
+ if (GetMonData(mon, MON_DATA_SPECIES) == SPECIES_SHEDINJA
+ && GetMonData(mon, MON_DATA_LANGUAGE) != language)
+ {
+ GetMonData(mon, MON_DATA_NICKNAME, nickname);
+ if (StringCompareWithoutExtCtrlCodes(nickname, sText_ShedinjaJpnName) == 0)
+ SetMonData(mon, MON_DATA_LANGUAGE, &language);
+ }
+}
+
+#define sBattler data[0]
+#define sSpeciesId data[2]
+
+void SpriteCB_WildMon(struct Sprite *sprite)
+{
+ sprite->callback = SpriteCB_MoveWildMonToRight;
+ StartSpriteAnimIfDifferent(sprite, 0);
+ BeginNormalPaletteFade(0x20000, 0, 10, 10, RGB(8, 8, 8));
+}
+
+static void SpriteCB_MoveWildMonToRight(struct Sprite *sprite)
+{
+ if ((gIntroSlideFlags & 1) == 0)
+ {
+ sprite->pos2.x += 2;
+ if (sprite->pos2.x == 0)
+ {
+ sprite->callback = SpriteCB_WildMonShowHealthbox;
+ PlayCry1(sprite->data[2], 25);
+ }
+ }
+}
+
+static void SpriteCB_WildMonShowHealthbox(struct Sprite *sprite)
+{
+ if (sprite->animEnded)
+ {
+ sub_804BD94(sprite->sBattler);
+ SetHealthboxSpriteVisible(gHealthboxSpriteIds[sprite->sBattler]);
+ sprite->callback = SpriteCallbackDummy2;
+ StartSpriteAnimIfDifferent(sprite, 0);
+ BeginNormalPaletteFade(0x20000, 0, 10, 0, RGB(8, 8, 8));
+ }
+}
+
+void SpriteCallbackDummy2(struct Sprite *sprite)
+{
+}
+
+// not used
+static void sub_8011E28(struct Sprite *sprite)
+{
+ sprite->data[3] = 6;
+ sprite->data[4] = 1;
+ sprite->callback = sub_8011E3C;
+}
+
+// not used
+static void sub_8011E3C(struct Sprite *sprite)
+{
+ --sprite->data[4];
+ if (sprite->data[4] == 0)
+ {
+ sprite->data[4] = 8;
+ sprite->invisible ^= 1;
+ --sprite->data[3];
+ if (sprite->data[3] == 0)
+ {
+ sprite->invisible = FALSE;
+ sprite->callback = SpriteCallbackDummy2;
+ gUnknown_2022AE8[0] = 0;
+ }
+ }
+}
+
+void SpriteCB_FaintOpponentMon(struct Sprite *sprite)
+{
+ u8 battler = sprite->sBattler;
+ u16 species;
+ u8 yOffset;
+
+ if (gBattleSpritesDataPtr->battlerData[battler].transformSpecies != 0)
+ species = gBattleSpritesDataPtr->battlerData[battler].transformSpecies;
+ else
+ species = sprite->sSpeciesId;
+ GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_PERSONALITY); // Unused return value.
+ if (species == SPECIES_UNOWN)
+ {
+ u32 personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_PERSONALITY);
+ u16 unownForm = ((((personalityValue & 0x3000000) >> 18) | ((personalityValue & 0x30000) >> 12) | ((personalityValue & 0x300) >> 6) | (personalityValue & 3)) % 0x1C);
+ u16 unownSpecies;
+
+ if (unownForm == 0)
+ unownSpecies = SPECIES_UNOWN; // Use the A Unown form.
+ else
+ unownSpecies = NUM_SPECIES + unownForm; // Use one of the other Unown letters.
+ yOffset = gMonFrontPicCoords[unownSpecies].y_offset;
+ }
+ else if (species == SPECIES_CASTFORM)
+ {
+ yOffset = gCastformFrontSpriteCoords[gBattleMonForms[battler]].y_offset;
+ }
+ else if (species > NUM_SPECIES)
+ {
+ yOffset = gMonFrontPicCoords[SPECIES_NONE].y_offset;
+ }
+ else
+ {
+ yOffset = gMonFrontPicCoords[species].y_offset;
+ }
+ sprite->data[3] = 8 - yOffset / 8;
+ sprite->data[4] = 1;
+ sprite->callback = SpriteCB_AnimFaintOpponent;
+}
+
+static void SpriteCB_AnimFaintOpponent(struct Sprite *sprite)
+{
+ s32 i;
+
+ if (--sprite->data[4] == 0)
+ {
+ sprite->data[4] = 2;
+ sprite->pos2.y += 8; // Move the sprite down.
+ if (--sprite->data[3] < 0)
+ {
+ FreeSpriteOamMatrix(sprite);
+ DestroySprite(sprite);
+ }
+ else // Erase bottom part of the sprite to create a smooth illusion of mon falling down.
+ {
+ u8 *dst = (u8 *)gMonSpritesGfxPtr->sprites[GetBattlerPosition(sprite->sBattler)] + (gBattleMonForms[sprite->sBattler] << 11) + (sprite->data[3] << 8);
+
+ for (i = 0; i < 0x100; ++i)
+ *(dst++) = 0;
+ StartSpriteAnim(sprite, gBattleMonForms[sprite->sBattler]);
+ }
+ }
+}
+
+void sub_8012044(struct Sprite *sprite)
+{
+ sprite->data[3] = 8;
+ sprite->data[4] = sprite->invisible;
+ sprite->callback = sub_8012060;
+}
+
+static void sub_8012060(struct Sprite *sprite)
+{
+ --sprite->data[3];
+ if (sprite->data[3] == 0)
+ {
+ sprite->invisible ^= 1;
+ sprite->data[3] = 8;
+ }
+}
+
+void sub_8012098(struct Sprite *sprite)
+{
+ sprite->invisible = sprite->data[4];
+ sprite->data[4] = FALSE;
+ sprite->callback = SpriteCallbackDummy2;
+}
+
+void sub_80120C4(struct Sprite *sprite)
+{
+ sprite->callback = oac_poke_ally_;
+}
+
+static void oac_poke_ally_(struct Sprite *sprite)
+{
+ if (!(gIntroSlideFlags & 1))
+ {
+ sprite->pos2.x -= 2;
+ if (sprite->pos2.x == 0)
+ {
+ sprite->callback = SpriteCallbackDummy3;
+ sprite->data[1] = 0;
+ }
+ }
+}
+
+void sub_8012100(struct Sprite *sprite)
+{
+ sprite->callback = SpriteCallbackDummy3;
+}
+
+static void SpriteCallbackDummy3(struct Sprite *sprite)
+{
+}
+
+void sub_8012110(struct Sprite *sprite)
+{
+ if (!(gIntroSlideFlags & 1))
+ {
+ sprite->pos2.x += sprite->data[1];
+ sprite->pos2.y += sprite->data[2];
+ }
+}
+
+#define sSinIndex data[0]
+#define sDelta data[1]
+#define sAmplitude data[2]
+#define sBouncerSpriteId data[3]
+#define sWhich data[4]
+
+void DoBounceEffect(u8 battler, u8 which, s8 delta, s8 amplitude)
+{
+ u8 invisibleSpriteId;
+ u8 bouncerSpriteId;
+
+ switch (which)
+ {
+ case BOUNCE_HEALTHBOX:
+ default:
+ if (gBattleSpritesDataPtr->healthBoxesData[battler].healthboxIsBouncing)
+ return;
+ break;
+ case BOUNCE_MON:
+ if (gBattleSpritesDataPtr->healthBoxesData[battler].battlerIsBouncing)
+ return;
+ break;
+ }
+ invisibleSpriteId = CreateInvisibleSpriteWithCallback(SpriteCB_BounceEffect);
+ if (which == BOUNCE_HEALTHBOX)
+ {
+ bouncerSpriteId = gHealthboxSpriteIds[battler];
+ gBattleSpritesDataPtr->healthBoxesData[battler].healthboxBounceSpriteId = invisibleSpriteId;
+ gBattleSpritesDataPtr->healthBoxesData[battler].healthboxIsBouncing = 1;
+ gSprites[invisibleSpriteId].sSinIndex = 128; // 0
+ }
+ else
+ {
+ bouncerSpriteId = gBattlerSpriteIds[battler];
+ gBattleSpritesDataPtr->healthBoxesData[battler].battlerBounceSpriteId = invisibleSpriteId;
+ gBattleSpritesDataPtr->healthBoxesData[battler].battlerIsBouncing = 1;
+ gSprites[invisibleSpriteId].sSinIndex = 192; // -1
+ }
+ gSprites[invisibleSpriteId].sDelta = delta;
+ gSprites[invisibleSpriteId].sAmplitude = amplitude;
+ gSprites[invisibleSpriteId].sBouncerSpriteId = bouncerSpriteId;
+ gSprites[invisibleSpriteId].sWhich = which;
+ gSprites[bouncerSpriteId].pos2.x = 0;
+ gSprites[bouncerSpriteId].pos2.y = 0;
+}
+
+void EndBounceEffect(u8 battler, u8 which)
+{
+ u8 bouncerSpriteId;
+
+ if (which == BOUNCE_HEALTHBOX)
+ {
+ if (!gBattleSpritesDataPtr->healthBoxesData[battler].healthboxIsBouncing)
+ return;
+
+ bouncerSpriteId = gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].healthboxBounceSpriteId].sBouncerSpriteId;
+ DestroySprite(&gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].healthboxBounceSpriteId]);
+ gBattleSpritesDataPtr->healthBoxesData[battler].healthboxIsBouncing = 0;
+ }
+ else
+ {
+ if (!gBattleSpritesDataPtr->healthBoxesData[battler].battlerIsBouncing)
+ return;
+
+ bouncerSpriteId = gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].battlerBounceSpriteId].sBouncerSpriteId;
+ DestroySprite(&gSprites[gBattleSpritesDataPtr->healthBoxesData[battler].battlerBounceSpriteId]);
+ gBattleSpritesDataPtr->healthBoxesData[battler].battlerIsBouncing = 0;
+ }
+ gSprites[bouncerSpriteId].pos2.x = 0;
+ gSprites[bouncerSpriteId].pos2.y = 0;
+}
+
+static void SpriteCB_BounceEffect(struct Sprite *sprite)
+{
+ u8 bouncerSpriteId = sprite->sBouncerSpriteId;
+ s32 index;
+
+ if (sprite->sWhich == BOUNCE_HEALTHBOX)
+ index = sprite->sSinIndex;
+ else
+ index = sprite->sSinIndex;
+ gSprites[bouncerSpriteId].pos2.y = Sin(index, sprite->sAmplitude) + sprite->sAmplitude;
+ sprite->sSinIndex = (sprite->sSinIndex + sprite->sDelta) & 0xFF;
+}
+
+void sub_8012354(struct Sprite *sprite)
+{
+ StartSpriteAnim(sprite, 1);
+ sprite->callback = sub_8012398;
+}
+
+void sub_801236C(struct Sprite *sprite)
+{
+ if (sprite->animDelayCounter == 0)
+ sprite->centerToCornerVecX = gUnknown_824F048[sprite->animCmdIndex];
+}
+
+static void sub_8012398(struct Sprite *sprite)
+{
+ sub_801236C(sprite);
+ if (sprite->animEnded)
+ sprite->callback = SpriteCallbackDummy3;
+}
+
+void nullsub_12(void)
+{
+}
+
+void BeginBattleIntro(void)
+{
+ BattleStartClearSetData();
+ gBattleCommunication[1] = 0;
+ gBattleMainFunc = BattleIntroGetMonsData;
+}
+
+static void BattleMainCB1(void)
+{
+ gBattleMainFunc();
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ gBattlerControllerFuncs[gActiveBattler]();
+}
+
+static void BattleStartClearSetData(void)
+{
+ s32 i;
+ u32 j;
+ u8 *dataPtr;
+
+ TurnValuesCleanUp(FALSE);
+ SpecialStatusesClear();
+ for (i = 0; i < MAX_BATTLERS_COUNT; ++i)
+ {
+ gStatuses3[i] = 0;
+ dataPtr = (u8 *)&gDisableStructs[i];
+ for (j = 0; j < sizeof(struct DisableStruct); ++j)
+ dataPtr[j] = 0;
+ gDisableStructs[i].isFirstTurn = 2;
+ gUnknown_2023DD4[i] = 0;
+ gLastMoves[i] = MOVE_NONE;
+ gLastLandedMoves[i] = MOVE_NONE;
+ gLastHitByType[i] = 0;
+ gLastResultingMoves[i] = MOVE_NONE;
+ gLastHitBy[i] = 0xFF;
+ gLockedMoves[i] = MOVE_NONE;
+ gLastPrintedMoves[i] = MOVE_NONE;
+ gBattleResources->flags->flags[i] = 0;
+ }
+ for (i = 0; i < 2; ++i)
+ {
+ gSideStatuses[i] = 0;
+ dataPtr = (u8 *)&gSideTimers[i];
+ for (j = 0; j < sizeof(struct SideTimer); ++j)
+ dataPtr[j] = 0;
+ }
+ gBattlerAttacker = 0;
+ gBattlerTarget = 0;
+ gBattleWeather = 0;
+ dataPtr = (u8 *)&gWishFutureKnock;
+ for (i = 0; i < sizeof(struct WishFutureKnock); ++i)
+ dataPtr[i] = 0;
+ gHitMarker = 0;
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_POKEDUDE)) && gSaveBlock2Ptr->optionsBattleSceneOff)
+ gHitMarker |= HITMARKER_NO_ANIMATIONS;
+ gBattleScripting.battleStyle = gSaveBlock2Ptr->optionsBattleStyle;
+ gMultiHitCounter = 0;
+ gBattleOutcome = 0;
+ gBattleControllerExecFlags = 0;
+ gPaydayMoney = 0;
+ gBattleResources->battleScriptsStack->size = 0;
+ gBattleResources->battleCallbackStack->size = 0;
+ for (i = 0; i < BATTLE_COMMUNICATION_ENTRIES_COUNT; ++i)
+ gBattleCommunication[i] = 0;
+ gPauseCounterBattle = 0;
+ gBattleMoveDamage = 0;
+ gIntroSlideFlags = 0;
+ gBattleScripting.animTurn = 0;
+ gBattleScripting.animTargetsHit = 0;
+ gLeveledUpInBattle = 0;
+ gAbsentBattlerFlags = 0;
+ gBattleStruct->runTries = 0;
+ gBattleStruct->safariGoNearCounter = 0;
+ gBattleStruct->safariPkblThrowCounter = 0;
+ *(&gBattleStruct->safariCatchFactor) = gBaseStats[GetMonData(&gEnemyParty[0], MON_DATA_SPECIES)].catchRate * 100 / 1275;
+ *(&gBattleStruct->safariEscapeFactor) = gBaseStats[GetMonData(&gEnemyParty[0], MON_DATA_SPECIES)].safariZoneFleeRate * 100 / 1275;
+ if (gBattleStruct->safariEscapeFactor <= 1)
+ gBattleStruct->safariEscapeFactor = 2;
+ gBattleStruct->wildVictorySong = 0;
+ gBattleStruct->moneyMultiplier = 1;
+ for (i = 0; i < 8; ++i)
+ {
+ *((u8 *)gBattleStruct->lastTakenMove + i) = MOVE_NONE;
+ *((u8 *)gBattleStruct->usedHeldItems + i) = ITEM_NONE;
+ *((u8 *)gBattleStruct->choicedMove + i) = MOVE_NONE;
+ *((u8 *)gBattleStruct->changedItems + i) = ITEM_NONE;
+ *(i + 0 * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(i + 1 * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(i + 2 * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(i + 3 * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ }
+ *(gBattleStruct->AI_monToSwitchIntoId + 0) = PARTY_SIZE;
+ *(gBattleStruct->AI_monToSwitchIntoId + 1) = PARTY_SIZE;
+ *(&gBattleStruct->givenExpMons) = 0;
+ for (i = 0; i < 11; ++i)
+ gBattleResults.catchAttempts[i] = 0;
+ gBattleResults.battleTurnCounter = 0;
+ gBattleResults.playerFaintCounter = 0;
+ gBattleResults.opponentFaintCounter = 0;
+ gBattleResults.playerSwitchesCounter = 0;
+ gBattleResults.numHealingItemsUsed = 0;
+ gBattleResults.numRevivesUsed = 0;
+ gBattleResults.playerMonWasDamaged = FALSE;
+ gBattleResults.usedMasterBall = FALSE;
+ gBattleResults.lastOpponentSpecies = SPECIES_NONE;
+ gBattleResults.lastUsedMovePlayer = MOVE_NONE;
+ gBattleResults.lastUsedMoveOpponent = MOVE_NONE;
+ gBattleResults.playerMon1Species = SPECIES_NONE;
+ gBattleResults.playerMon2Species = SPECIES_NONE;
+ gBattleResults.caughtMonSpecies = SPECIES_NONE;
+ for (i = 0; i < POKEMON_NAME_LENGTH; ++i)
+ {
+ gBattleResults.playerMon1Name[i] = 0;
+ gBattleResults.playerMon2Name[i] = 0;
+ gBattleResults.caughtMonNick[i] = 0;
+ }
+}
+
+void SwitchInClearSetData(void)
+{
+ struct DisableStruct disableStructCopy = gDisableStructs[gActiveBattler];
+ s32 i;
+ u8 *ptr;
+
+ if (gBattleMoves[gCurrentMove].effect != EFFECT_BATON_PASS)
+ {
+ for (i = 0; i < NUM_BATTLE_STATS; ++i)
+ gBattleMons[gActiveBattler].statStages[i] = 6;
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ if ((gBattleMons[i].status2 & STATUS2_ESCAPE_PREVENTION) && gDisableStructs[i].battlerPreventingEscape == gActiveBattler)
+ gBattleMons[i].status2 &= ~STATUS2_ESCAPE_PREVENTION;
+ if ((gStatuses3[i] & STATUS3_ALWAYS_HITS) && gDisableStructs[i].battlerWithSureHit == gActiveBattler)
+ {
+ gStatuses3[i] &= ~STATUS3_ALWAYS_HITS;
+ gDisableStructs[i].battlerWithSureHit = 0;
+ }
+ }
+ }
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS)
+ {
+ gBattleMons[gActiveBattler].status2 &= (STATUS2_CONFUSION | STATUS2_FOCUS_ENERGY | STATUS2_SUBSTITUTE | STATUS2_ESCAPE_PREVENTION | STATUS2_CURSED);
+ gStatuses3[gActiveBattler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED | STATUS3_MUDSPORT | STATUS3_WATERSPORT);
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ if (GetBattlerSide(gActiveBattler) != GetBattlerSide(i)
+ && (gStatuses3[i] & STATUS3_ALWAYS_HITS) != 0
+ && (gDisableStructs[i].battlerWithSureHit == gActiveBattler))
+ {
+ gStatuses3[i] &= ~(STATUS3_ALWAYS_HITS);
+ gStatuses3[i] |= 0x10;
+ }
+ }
+ }
+ else
+ {
+ gBattleMons[gActiveBattler].status2 = 0;
+ gStatuses3[gActiveBattler] = 0;
+ }
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ if (gBattleMons[i].status2 & STATUS2_INFATUATED_WITH(gActiveBattler))
+ gBattleMons[i].status2 &= ~(STATUS2_INFATUATED_WITH(gActiveBattler));
+ if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && *(gBattleStruct->wrappedBy + i) == gActiveBattler)
+ gBattleMons[i].status2 &= ~(STATUS2_WRAPPED);
+ }
+ gActionSelectionCursor[gActiveBattler] = 0;
+ gMoveSelectionCursor[gActiveBattler] = 0;
+ ptr = (u8 *)&gDisableStructs[gActiveBattler];
+ for (i = 0; i < sizeof(struct DisableStruct); ++i)
+ ptr[i] = 0;
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS)
+ {
+ gDisableStructs[gActiveBattler].substituteHP = disableStructCopy.substituteHP;
+ gDisableStructs[gActiveBattler].battlerWithSureHit = disableStructCopy.battlerWithSureHit;
+ gDisableStructs[gActiveBattler].perishSongTimer = disableStructCopy.perishSongTimer;
+ gDisableStructs[gActiveBattler].perishSongTimerStartValue = disableStructCopy.perishSongTimerStartValue;
+ gDisableStructs[gActiveBattler].battlerPreventingEscape = disableStructCopy.battlerPreventingEscape;
+ }
+ gMoveResultFlags = 0;
+ gDisableStructs[gActiveBattler].isFirstTurn = 2;
+ gLastMoves[gActiveBattler] = MOVE_NONE;
+ gLastLandedMoves[gActiveBattler] = MOVE_NONE;
+ gLastHitByType[gActiveBattler] = 0;
+ gLastResultingMoves[gActiveBattler] = MOVE_NONE;
+ gLastPrintedMoves[gActiveBattler] = MOVE_NONE;
+ gLastHitBy[gActiveBattler] = 0xFF;
+ *(gBattleStruct->lastTakenMove + gActiveBattler * 2 + 0) = MOVE_NONE;
+ *(gBattleStruct->lastTakenMove + gActiveBattler * 2 + 1) = MOVE_NONE;
+ *(0 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(0 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 1) = 0;
+ *(1 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(1 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 1) = 0;
+ *(2 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(2 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 1) = 0;
+ *(3 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(3 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 1) = 0;
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ if (i != gActiveBattler)
+ {
+ *(gBattleStruct->lastTakenMove + i * 2 + 0) = MOVE_NONE;
+ *(gBattleStruct->lastTakenMove + i * 2 + 1) = MOVE_NONE;
+ }
+ *(i * 8 + gActiveBattler * 2 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(i * 8 + gActiveBattler * 2 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 1) = 0;
+ }
+ *((u8 *)(&gBattleStruct->choicedMove[gActiveBattler]) + 0) = MOVE_NONE;
+ *((u8 *)(&gBattleStruct->choicedMove[gActiveBattler]) + 1) = MOVE_NONE;
+ gBattleResources->flags->flags[gActiveBattler] = 0;
+ gCurrentMove = MOVE_NONE;
+}
+
+void FaintClearSetData(void)
+{
+ s32 i;
+ u8 *ptr;
+
+ for (i = 0; i < NUM_BATTLE_STATS; ++i)
+ gBattleMons[gActiveBattler].statStages[i] = 6;
+ gBattleMons[gActiveBattler].status2 = 0;
+ gStatuses3[gActiveBattler] = 0;
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ if ((gBattleMons[i].status2 & STATUS2_ESCAPE_PREVENTION) && gDisableStructs[i].battlerPreventingEscape == gActiveBattler)
+ gBattleMons[i].status2 &= ~STATUS2_ESCAPE_PREVENTION;
+ if (gBattleMons[i].status2 & STATUS2_INFATUATED_WITH(gActiveBattler))
+ gBattleMons[i].status2 &= ~(STATUS2_INFATUATED_WITH(gActiveBattler));
+ if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && *(gBattleStruct->wrappedBy + i) == gActiveBattler)
+ gBattleMons[i].status2 &= ~(STATUS2_WRAPPED);
+ }
+ gActionSelectionCursor[gActiveBattler] = 0;
+ gMoveSelectionCursor[gActiveBattler] = 0;
+ ptr = (u8 *)&gDisableStructs[gActiveBattler];
+ for (i = 0; i < sizeof(struct DisableStruct); ++i)
+ ptr[i] = 0;
+ gProtectStructs[gActiveBattler].protected = FALSE;
+ gProtectStructs[gActiveBattler].endured = FALSE;
+ gProtectStructs[gActiveBattler].noValidMoves = FALSE;
+ gProtectStructs[gActiveBattler].helpingHand = FALSE;
+ gProtectStructs[gActiveBattler].bounceMove = FALSE;
+ gProtectStructs[gActiveBattler].stealMove = FALSE;
+ gProtectStructs[gActiveBattler].flag0Unknown = FALSE;
+ gProtectStructs[gActiveBattler].prlzImmobility = FALSE;
+ gProtectStructs[gActiveBattler].confusionSelfDmg = FALSE;
+ gProtectStructs[gActiveBattler].targetNotAffected = FALSE;
+ gProtectStructs[gActiveBattler].chargingTurn = FALSE;
+ gProtectStructs[gActiveBattler].fleeFlag = 0;
+ gProtectStructs[gActiveBattler].usedImprisonedMove = FALSE;
+ gProtectStructs[gActiveBattler].loveImmobility = FALSE;
+ gProtectStructs[gActiveBattler].usedDisabledMove = FALSE;
+ gProtectStructs[gActiveBattler].usedTauntedMove = FALSE;
+ gProtectStructs[gActiveBattler].flag2Unknown = FALSE;
+ gProtectStructs[gActiveBattler].flinchImmobility = FALSE;
+ gProtectStructs[gActiveBattler].notFirstStrike = FALSE;
+ gDisableStructs[gActiveBattler].isFirstTurn = 2;
+ gLastMoves[gActiveBattler] = MOVE_NONE;
+ gLastLandedMoves[gActiveBattler] = MOVE_NONE;
+ gLastHitByType[gActiveBattler] = MOVE_NONE;
+ gLastResultingMoves[gActiveBattler] = MOVE_NONE;
+ gLastPrintedMoves[gActiveBattler] = MOVE_NONE;
+ gLastHitBy[gActiveBattler] = 0xFF;
+ *((u8 *)(&gBattleStruct->choicedMove[gActiveBattler]) + 0) = MOVE_NONE;
+ *((u8 *)(&gBattleStruct->choicedMove[gActiveBattler]) + 1) = MOVE_NONE;
+ *(gBattleStruct->lastTakenMove + gActiveBattler * 2 + 0) = MOVE_NONE;
+ *(gBattleStruct->lastTakenMove + gActiveBattler * 2 + 1) = MOVE_NONE;
+ *(0 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(0 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 1) = 0;
+ *(1 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(1 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 1) = 0;
+ *(2 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(2 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 1) = 0;
+ *(3 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(3 * 2 + gActiveBattler * 8 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 1) = 0;
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ if (i != gActiveBattler)
+ {
+ *(gBattleStruct->lastTakenMove + i * 2 + 0) = MOVE_NONE;
+ *(gBattleStruct->lastTakenMove + i * 2 + 1) = MOVE_NONE;
+ }
+ *(i * 8 + gActiveBattler * 2 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 0) = 0;
+ *(i * 8 + gActiveBattler * 2 + (u8 *)(gBattleStruct->lastTakenMoveFrom) + 1) = 0;
+ }
+ gBattleResources->flags->flags[gActiveBattler] = 0;
+ gBattleMons[gActiveBattler].type1 = gBaseStats[gBattleMons[gActiveBattler].species].type1;
+ gBattleMons[gActiveBattler].type2 = gBaseStats[gBattleMons[gActiveBattler].species].type2;
+}
+
+static void BattleIntroGetMonsData(void)
+{
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ gActiveBattler = gBattleCommunication[1];
+ BtlController_EmitGetMonData(0, REQUEST_ALL_BATTLE, 0);
+ MarkBattlerForControllerExec(gActiveBattler);
+ ++gBattleCommunication[MULTIUSE_STATE];
+ break;
+ case 1:
+ if (gBattleControllerExecFlags == 0)
+ {
+ ++gBattleCommunication[1];
+ if (gBattleCommunication[1] == gBattlersCount)
+ gBattleMainFunc = BattleIntroPrepareBackgroundSlide;
+ else
+ gBattleCommunication[MULTIUSE_STATE] = 0;
+ }
+ break;
+ }
+}
+
+static void BattleIntroPrepareBackgroundSlide(void)
+{
+ if (gBattleControllerExecFlags == 0)
+ {
+ gActiveBattler = GetBattlerAtPosition(0);
+ BtlController_EmitIntroSlide(0, gBattleTerrain);
+ MarkBattlerForControllerExec(gActiveBattler);
+ gBattleMainFunc = BattleIntroDrawTrainersOrMonsSprites;
+ gBattleCommunication[MULTIUSE_STATE] = 0;
+ gBattleCommunication[SPRITES_INIT_STATE1] = 0;
+ }
+}
+
+static void BattleIntroDrawTrainersOrMonsSprites(void)
+{
+ u8 *ptr;
+ s32 i;
+
+ if (!gBattleControllerExecFlags)
+ {
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ if ((gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
+ {
+ 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].ability = GetAbilityBySpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].abilityNum);
+ 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);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ {
+ if (GetBattlerPosition(gActiveBattler) == B_POSITION_OPPONENT_LEFT)
+ {
+ BtlController_EmitDrawTrainerPic(0);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT
+ && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_POKEDUDE
+ | BATTLE_TYPE_LINK
+ | BATTLE_TYPE_GHOST
+ | BATTLE_TYPE_OLD_MAN_TUTORIAL
+ | BATTLE_TYPE_LEGENDARY)))
+ HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBattler].species), FLAG_SET_SEEN, gBattleMons[gActiveBattler].personality);
+ }
+ else
+ {
+ if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT)
+ {
+ if (gBattleTypeFlags & (BATTLE_TYPE_GHOST | BATTLE_TYPE_LEGENDARY))
+ {
+ if ((gBattleTypeFlags & (BATTLE_TYPE_GHOST | BATTLE_TYPE_LEGENDARY)) != BATTLE_TYPE_GHOST)
+ HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBattler].species), FLAG_SET_SEEN, gBattleMons[gActiveBattler].personality);
+ }
+ else if (!(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_POKEDUDE
+ | BATTLE_TYPE_LINK
+ | BATTLE_TYPE_GHOST
+ | BATTLE_TYPE_OLD_MAN_TUTORIAL
+ | BATTLE_TYPE_LEGENDARY)))
+ {
+ HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBattler].species), FLAG_SET_SEEN, gBattleMons[gActiveBattler].personality);
+ }
+ BtlController_EmitLoadMonSprite(0);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ }
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI
+ && (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT || GetBattlerPosition(gActiveBattler) == B_POSITION_OPPONENT_RIGHT))
+ {
+ BtlController_EmitDrawTrainerPic(0);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ }
+ gBattleMainFunc = BattleIntroDrawPartySummaryScreens;
+ }
+}
+
+static void BattleIntroDrawPartySummaryScreens(void)
+{
+ s32 i;
+ struct HpAndStatus hpStatus[PARTY_SIZE];
+
+ if (!gBattleControllerExecFlags)
+ {
+ 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)
+ {
+ gActiveBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
+ PrepareStringBattle(STRINGID_INTROMSG, gActiveBattler);
+ gBattleMainFunc = BattleIntroPrintOpponentSendsOut;
+ }
+}
+
+static void BattleIntroPrintWildMonAttacked(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ gBattleMainFunc = BattleIntroPrintPlayerSendsOut;
+ PrepareStringBattle(STRINGID_INTROMSG, 0);
+ if ((gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_GHOST)) == (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_GHOST))
+ {
+ gBattleScripting.battler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
+ BattleScriptExecute(gUnknown_81D91A1);
+ }
+ }
+}
+
+static void BattleIntroPrintOpponentSendsOut(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT));
+ gBattleMainFunc = BattleIntroOpponentSendsOutMonAnimation;
+ }
+}
+
+static void BattleIntroOpponentSendsOutMonAnimation(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ if (GetBattlerPosition(gActiveBattler) == B_POSITION_OPPONENT_LEFT)
+ {
+ BtlController_EmitIntroTrainerBallThrow(0);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI && GetBattlerPosition(gActiveBattler) == B_POSITION_OPPONENT_RIGHT)
+ {
+ BtlController_EmitIntroTrainerBallThrow(0);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ }
+ gBattleMainFunc = BattleIntroRecordMonsToDex;
+ }
+}
+
+static void BattleIntroRecordMonsToDex(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT
+ && !(gBattleTypeFlags & (BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_POKEDUDE
+ | BATTLE_TYPE_LINK
+ | BATTLE_TYPE_GHOST
+ | BATTLE_TYPE_OLD_MAN_TUTORIAL
+ | BATTLE_TYPE_LEGENDARY)))
+ HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBattler].species), FLAG_SET_SEEN, gBattleMons[gActiveBattler].personality);
+ gBattleMainFunc = BattleIntroPrintPlayerSendsOut;
+ }
+}
+
+// not used
+static void sub_80136C4(void)
+{
+ if (!gBattleControllerExecFlags)
+ gBattleMainFunc = BattleIntroPrintPlayerSendsOut;
+}
+
+void BattleIntroPrintPlayerSendsOut(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI))
+ PrepareStringBattle(STRINGID_INTROSENDOUT, GetBattlerAtPosition(B_POSITION_PLAYER_LEFT));
+ gBattleMainFunc = BattleIntroPlayerSendsOutMonAnimation;
+ }
+}
+
+static void BattleIntroPlayerSendsOutMonAnimation(void)
+{
+ u32 position;
+
+ if (!gBattleControllerExecFlags)
+ {
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_LEFT)
+ {
+ BtlController_EmitIntroTrainerBallThrow(0);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI && GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT)
+ {
+ BtlController_EmitIntroTrainerBallThrow(0);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ }
+ gBattleStruct->switchInAbilitiesCounter = 0;
+ gBattleStruct->switchInItemsCounter = 0;
+ gBattleStruct->overworldWeatherDone = FALSE;
+ gBattleMainFunc = TryDoEventsBeforeFirstTurn;
+ }
+}
+
+// not used
+static void sub_80137D0(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ 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;
+ }
+}
+
+static void TryDoEventsBeforeFirstTurn(void)
+{
+ s32 i, j;
+ u8 effect = 0;
+
+ if (!gBattleControllerExecFlags)
+ {
+
+ if (gBattleStruct->switchInAbilitiesCounter == 0)
+ {
+ for (i = 0; i < gBattlersCount; ++i)
+ gBattlerByTurnOrder[i] = i;
+ for (i = 0; i < gBattlersCount - 1; ++i)
+ for (j = i + 1; j < gBattlersCount; ++j)
+ if (GetWhoStrikesFirst(gBattlerByTurnOrder[i], gBattlerByTurnOrder[j], TRUE) != 0)
+ SwapTurnOrder(i, j);
+ }
+ if (!gBattleStruct->overworldWeatherDone
+ && AbilityBattleEffects(0, 0, 0, ABILITYEFFECT_SWITCH_IN_WEATHER, 0) != 0)
+ {
+ gBattleStruct->overworldWeatherDone = TRUE;
+ return;
+ }
+ // Check all switch in abilities happening from the fastest mon to slowest.
+ while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount)
+ {
+ if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBattlerByTurnOrder[gBattleStruct->switchInAbilitiesCounter], 0, 0, 0) != 0)
+ ++effect;
+ ++gBattleStruct->switchInAbilitiesCounter;
+ if (effect)
+ return;
+ }
+ if (AbilityBattleEffects(ABILITYEFFECT_INTIMIDATE1, 0, 0, 0, 0) != 0)
+ return;
+ if (AbilityBattleEffects(ABILITYEFFECT_TRACE, 0, 0, 0, 0) != 0)
+ return;
+ // Check all switch in items having effect from the fastest mon to slowest.
+ while (gBattleStruct->switchInItemsCounter < gBattlersCount)
+ {
+ if (ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, gBattlerByTurnOrder[gBattleStruct->switchInItemsCounter], FALSE))
+ ++effect;
+ ++gBattleStruct->switchInItemsCounter;
+ if (effect)
+ return;
+ }
+ for (i = 0; i < gBattlersCount; ++i) // pointless, ruby leftover
+ ;
+ for (i = 0; i < MAX_BATTLERS_COUNT; ++i)
+ {
+ *(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE;
+ gChosenActionByBattler[i] = B_ACTION_NONE;
+ gChosenMoveByBattler[i] = MOVE_NONE;
+ }
+ TurnValuesCleanUp(FALSE);
+ SpecialStatusesClear();
+ *(&gBattleStruct->field_91) = gAbsentBattlerFlags;
+ gBattleMainFunc = HandleTurnActionSelectionState;
+ ResetSentPokesToOpponentValue();
+ for (i = 0; i < BATTLE_COMMUNICATION_ENTRIES_COUNT; ++i)
+ gBattleCommunication[i] = 0;
+ for (i = 0; i < gBattlersCount; ++i)
+ gBattleMons[i].status2 &= ~(STATUS2_FLINCHED);
+ *(&gBattleStruct->turnEffectsTracker) = 0;
+ *(&gBattleStruct->turnEffectsBattlerId) = 0;
+ *(&gBattleStruct->wishPerishSongState) = 0;
+ *(&gBattleStruct->wishPerishSongBattlerId) = 0;
+ gBattleScripting.atk49_state = 0;
+ gBattleStruct->faintedActionsState = 0;
+ gBattleStruct->turnCountersTracker = 0;
+ gMoveResultFlags = 0;
+ gRandomTurnNumber = Random();
+ }
+}
+
+static void HandleEndTurn_ContinueBattle(void)
+{
+ s32 i;
+
+ if (!gBattleControllerExecFlags)
+ {
+ gBattleMainFunc = BattleTurnPassed;
+ for (i = 0; i < BATTLE_COMMUNICATION_ENTRIES_COUNT; ++i)
+ gBattleCommunication[i] = 0;
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ gBattleMons[i].status2 &= ~(STATUS2_FLINCHED);
+ if ((gBattleMons[i].status1 & STATUS1_SLEEP) && (gBattleMons[i].status2 & STATUS2_MULTIPLETURNS))
+ CancelMultiTurnMoves(i);
+ }
+ gBattleStruct->turnEffectsTracker = 0;
+ gBattleStruct->turnEffectsBattlerId = 0;
+ gBattleStruct->wishPerishSongState = 0;
+ gBattleStruct->wishPerishSongBattlerId = 0;
+ gBattleStruct->turnCountersTracker = 0;
+ gMoveResultFlags = 0;
+ }
+}
+
+void BattleTurnPassed(void)
+{
+ s32 i;
+
+ TurnValuesCleanUp(TRUE);
+ if (gBattleOutcome == 0)
+ {
+ if (DoFieldEndTurnEffects())
+ return;
+ if (DoBattlerEndTurnEffects())
+ return;
+ }
+ if (HandleFaintedMonActions())
+ return;
+ gBattleStruct->faintedActionsState = 0;
+ if (HandleWishPerishSongOnTurnEnd())
+ return;
+ TurnValuesCleanUp(FALSE);
+ gHitMarker &= ~(HITMARKER_NO_ATTACKSTRING);
+ gHitMarker &= ~(HITMARKER_UNABLE_TO_USE_MOVE);
+ gHitMarker &= ~(HITMARKER_x400000);
+ gHitMarker &= ~(HITMARKER_x100000);
+ gBattleScripting.animTurn = 0;
+ gBattleScripting.animTargetsHit = 0;
+ gBattleScripting.atk49_state = 0;
+ gBattleMoveDamage = 0;
+ gMoveResultFlags = 0;
+ for (i = 0; i < 5; ++i)
+ gBattleCommunication[i] = 0;
+ if (gBattleOutcome != 0)
+ {
+ gCurrentActionFuncId = B_ACTION_FINISHED;
+ gBattleMainFunc = RunTurnActionsFunctions;
+ return;
+ }
+ if (gBattleResults.battleTurnCounter < 0xFF)
+ ++gBattleResults.battleTurnCounter;
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ gChosenActionByBattler[i] = B_ACTION_NONE;
+ gChosenMoveByBattler[i] = MOVE_NONE;
+ }
+ for (i = 0; i < MAX_BATTLERS_COUNT; ++i)
+ *(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE;
+ *(&gBattleStruct->field_91) = gAbsentBattlerFlags;
+ gBattleMainFunc = HandleTurnActionSelectionState;
+ gRandomTurnNumber = Random();
+}
+
+u8 IsRunningFromBattleImpossible(void)
+{
+ u8 holdEffect;
+ u8 side;
+ s32 i;
+
+ if (gBattleMons[gActiveBattler].item == ITEM_ENIGMA_BERRY)
+ holdEffect = gEnigmaBerries[gActiveBattler].holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gActiveBattler].item);
+ gPotentialItemEffectBattler = gActiveBattler;
+ if (holdEffect == HOLD_EFFECT_CAN_ALWAYS_RUN
+ || (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ || gBattleMons[gActiveBattler].ability == ABILITY_RUN_AWAY)
+ return BATTLE_RUN_SUCCESS;
+ side = GetBattlerSide(gActiveBattler);
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ if (side != GetBattlerSide(i)
+ && gBattleMons[i].ability == ABILITY_SHADOW_TAG)
+ {
+ gBattleScripting.battler = i;
+ gLastUsedAbility = gBattleMons[i].ability;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ return BATTLE_RUN_FAILURE;
+ }
+ if (side != GetBattlerSide(i)
+ && gBattleMons[gActiveBattler].ability != ABILITY_LEVITATE
+ && !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_FLYING)
+ && gBattleMons[i].ability == ABILITY_ARENA_TRAP)
+ {
+ gBattleScripting.battler = i;
+ gLastUsedAbility = gBattleMons[i].ability;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ return BATTLE_RUN_FAILURE;
+ }
+ }
+ i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BATTLER, gActiveBattler, ABILITY_MAGNET_PULL, 0, 0);
+ if (i != 0 && IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL))
+ {
+ gBattleScripting.battler = i - 1;
+ gLastUsedAbility = gBattleMons[i - 1].ability;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ return BATTLE_RUN_FAILURE;
+ }
+ if ((gBattleMons[gActiveBattler].status2 & (STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED))
+ || (gStatuses3[gActiveBattler] & STATUS3_ROOTED))
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ return BATTLE_RUN_FORBIDDEN;
+ }
+ if (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ return BATTLE_RUN_FORBIDDEN;
+ }
+ return BATTLE_RUN_SUCCESS;
+}
+
+void sub_8013F6C(u8 battler)
+{
+ s32 i;
+ u8 r4, r1;
+
+ for (i = 0; i < 3; ++i)
+ gUnknown_203B0DC[i] = *(battler * 3 + i + (u8 *)(gBattleStruct->field_60));
+ r4 = pokemon_order_func(gBattlerPartyIndexes[battler]);
+ r1 = pokemon_order_func(*(gBattleStruct->monToSwitchIntoId + battler));
+ sub_8127FF4(r4, r1);
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ {
+ for (i = 0; i < 3; ++i)
+ {
+ *(battler * 3 + i + (u8 *)(gBattleStruct->field_60)) = gUnknown_203B0DC[i];
+ *(BATTLE_PARTNER(battler) * 3 + i + (u8 *)(gBattleStruct->field_60)) = gUnknown_203B0DC[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i < 3; ++i)
+ *(battler * 3 + i + (u8 *)(gBattleStruct->field_60)) = gUnknown_203B0DC[i];
+ }
+}
+
+enum
+{
+ STATE_BEFORE_ACTION_CHOSEN,
+ STATE_WAIT_ACTION_CHOSEN,
+ STATE_WAIT_ACTION_CASE_CHOSEN,
+ STATE_WAIT_ACTION_CONFIRMED_STANDBY,
+ STATE_WAIT_ACTION_CONFIRMED,
+ STATE_SELECTION_SCRIPT,
+ STATE_WAIT_SET_BEFORE_ACTION,
+};
+
+static void HandleTurnActionSelectionState(void)
+{
+ s32 i;
+
+ gBattleCommunication[ACTIONS_CONFIRMED_COUNT] = 0;
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ u8 position = GetBattlerPosition(gActiveBattler);
+
+ switch (gBattleCommunication[gActiveBattler])
+ {
+ case STATE_BEFORE_ACTION_CHOSEN: // Choose an action.
+ *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = PARTY_SIZE;
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI
+ || (position & BIT_FLANK) == B_FLANK_LEFT
+ || gBattleStruct->field_91 & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(position))]
+ || gBattleCommunication[GetBattlerAtPosition(BATTLE_PARTNER(position))] == STATE_WAIT_ACTION_CONFIRMED)
+ {
+ if (gBattleStruct->field_91 & gBitTable[gActiveBattler])
+ {
+ gChosenActionByBattler[gActiveBattler] = B_ACTION_NOTHING_FAINTED;
+ if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ gBattleCommunication[gActiveBattler] = STATE_WAIT_ACTION_CONFIRMED;
+ else
+ gBattleCommunication[gActiveBattler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
+ }
+ else
+ {
+ if (gBattleMons[gActiveBattler].status2 & STATUS2_MULTIPLETURNS
+ || gBattleMons[gActiveBattler].status2 & STATUS2_RECHARGE)
+ {
+ gChosenActionByBattler[gActiveBattler] = B_ACTION_USE_MOVE;
+ gBattleCommunication[gActiveBattler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
+ }
+ else
+ {
+ BtlController_EmitChooseAction(0, gChosenActionByBattler[0], gBattleBufferB[0][1] | (gBattleBufferB[0][2] << 8));
+ MarkBattlerForControllerExec(gActiveBattler);
+ ++gBattleCommunication[gActiveBattler];
+ }
+ }
+ }
+ break;
+ case STATE_WAIT_ACTION_CHOSEN: // Try to perform an action.
+ if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) | (0xF0000000) | (gBitTable[gActiveBattler] << 4) | (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 0xC))))
+ {
+ gChosenActionByBattler[gActiveBattler] = gBattleBufferB[gActiveBattler][1];
+ switch (gBattleBufferB[gActiveBattler][1])
+ {
+ case B_ACTION_USE_MOVE:
+ if (AreAllMovesUnusable())
+ {
+ gBattleCommunication[gActiveBattler] = STATE_SELECTION_SCRIPT;
+ *(gBattleStruct->selectionScriptFinished + gActiveBattler) = FALSE;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBattler) = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
+ *(gBattleStruct->moveTarget + gActiveBattler) = gBattleBufferB[gActiveBattler][3];
+ return;
+ }
+ else if (gDisableStructs[gActiveBattler].encoredMove != MOVE_NONE)
+ {
+ gChosenMoveByBattler[gActiveBattler] = gDisableStructs[gActiveBattler].encoredMove;
+ *(gBattleStruct->chosenMovePositions + gActiveBattler) = gDisableStructs[gActiveBattler].encoredMovePos;
+ gBattleCommunication[gActiveBattler] = STATE_WAIT_ACTION_CONFIRMED_STANDBY;
+ return;
+ }
+ else
+ {
+ struct ChooseMoveStruct moveInfo;
+
+ moveInfo.species = gBattleMons[gActiveBattler].species;
+ moveInfo.monType1 = gBattleMons[gActiveBattler].type1;
+ moveInfo.monType2 = gBattleMons[gActiveBattler].type2;
+ for (i = 0; i < MAX_MON_MOVES; ++i)
+ {
+ moveInfo.moves[i] = gBattleMons[gActiveBattler].moves[i];
+ moveInfo.currentPp[i] = gBattleMons[gActiveBattler].pp[i];
+ moveInfo.maxPp[i] = CalculatePPWithBonus(gBattleMons[gActiveBattler].moves[i],
+ gBattleMons[gActiveBattler].ppBonuses,
+ i);
+ }
+ BtlController_EmitChooseMove(0, (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) != 0, FALSE, &moveInfo);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ break;
+ case B_ACTION_USE_ITEM:
+ if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_EREADER_TRAINER))
+ {
+ gSelectionBattleScripts[gActiveBattler] = BattleScript_ActionSelectionItemsCantBeUsed;
+ gBattleCommunication[gActiveBattler] = STATE_SELECTION_SCRIPT;
+ *(gBattleStruct->selectionScriptFinished + gActiveBattler) = FALSE;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBattler) = STATE_BEFORE_ACTION_CHOSEN;
+ return;
+ }
+ else
+ {
+ BtlController_EmitChooseItem(0, gBattleStruct->field_60[gActiveBattler]);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ break;
+ case B_ACTION_SWITCH:
+ *(gBattleStruct->field_58 + gActiveBattler) = gBattlerPartyIndexes[gActiveBattler];
+ if (gBattleMons[gActiveBattler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION) || gStatuses3[gActiveBattler] & STATUS3_ROOTED)
+ {
+ BtlController_EmitChoosePokemon(0, PARTY_CANT_SWITCH, 6, ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
+ }
+ else if ((i = ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_SHADOW_TAG))
+ || ((i = ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_ARENA_TRAP))
+ && !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_FLYING)
+ && gBattleMons[gActiveBattler].ability != ABILITY_LEVITATE)
+ || ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BATTLER, gActiveBattler, ABILITY_MAGNET_PULL, 0, 0))
+ && IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL)))
+ {
+ BtlController_EmitChoosePokemon(0, ((i - 1) << 4) | PARTY_ABILITY_PREVENTS, 6, gLastUsedAbility, gBattleStruct->field_60[gActiveBattler]);
+ }
+ else
+ {
+ if (gActiveBattler == 2 && gChosenActionByBattler[0] == B_ACTION_SWITCH)
+ BtlController_EmitChoosePokemon(0, PARTY_CHOOSE_MON, *(gBattleStruct->monToSwitchIntoId + 0), ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
+ else if (gActiveBattler == 3 && gChosenActionByBattler[1] == B_ACTION_SWITCH)
+ BtlController_EmitChoosePokemon(0, PARTY_CHOOSE_MON, *(gBattleStruct->monToSwitchIntoId + 1), ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
+ else
+ BtlController_EmitChoosePokemon(0, PARTY_CHOOSE_MON, 6, ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
+ }
+ MarkBattlerForControllerExec(gActiveBattler);
+ break;
+ case B_ACTION_SAFARI_BALL:
+ if (IsPlayerPartyAndPokemonStorageFull())
+ {
+ gSelectionBattleScripts[gActiveBattler] = BattleScript_PrintFullBox;
+ gBattleCommunication[gActiveBattler] = STATE_SELECTION_SCRIPT;
+ *(gBattleStruct->selectionScriptFinished + gActiveBattler) = FALSE;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBattler) = STATE_BEFORE_ACTION_CHOSEN;
+ return;
+ }
+ break;
+ case B_ACTION_CANCEL_PARTNER:
+ gBattleCommunication[gActiveBattler] = STATE_WAIT_SET_BEFORE_ACTION;
+ gBattleCommunication[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gActiveBattler)))] = STATE_BEFORE_ACTION_CHOSEN;
+ BtlController_EmitEndBounceEffect(0);
+ MarkBattlerForControllerExec(gActiveBattler);
+ return;
+ }
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER
+ && !(gBattleTypeFlags & BATTLE_TYPE_LINK)
+ && gBattleBufferB[gActiveBattler][1] == B_ACTION_RUN)
+ {
+ BattleScriptExecute(BattleScript_PrintCantRunFromTrainer);
+ gBattleCommunication[gActiveBattler] = STATE_BEFORE_ACTION_CHOSEN;
+ }
+ else if (IsRunningFromBattleImpossible() != BATTLE_RUN_SUCCESS
+ && gBattleBufferB[gActiveBattler][1] == B_ACTION_RUN)
+ {
+ gSelectionBattleScripts[gActiveBattler] = BattleScript_PrintCantEscapeFromBattle;
+ gBattleCommunication[gActiveBattler] = STATE_SELECTION_SCRIPT;
+ *(gBattleStruct->selectionScriptFinished + gActiveBattler) = FALSE;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBattler) = STATE_BEFORE_ACTION_CHOSEN;
+ return;
+ }
+ else
+ {
+ ++gBattleCommunication[gActiveBattler];
+ }
+ }
+ break;
+ case STATE_WAIT_ACTION_CASE_CHOSEN:
+ if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) | (0xF0000000) | (gBitTable[gActiveBattler] << 4) | (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 0xC))))
+ {
+ switch (gChosenActionByBattler[gActiveBattler])
+ {
+ case B_ACTION_USE_MOVE:
+ switch (gBattleBufferB[gActiveBattler][1])
+ {
+ case 3 ... 9:
+ gChosenActionByBattler[gActiveBattler] = gBattleBufferB[gActiveBattler][1];
+ return;
+ default:
+ if ((gBattleBufferB[gActiveBattler][2] | (gBattleBufferB[gActiveBattler][3] << 8)) == 0xFFFF)
+ {
+ gBattleCommunication[gActiveBattler] = STATE_BEFORE_ACTION_CHOSEN;
+ }
+ else if (TrySetCantSelectMoveBattleScript())
+ {
+ gBattleCommunication[gActiveBattler] = STATE_SELECTION_SCRIPT;
+ *(gBattleStruct->selectionScriptFinished + gActiveBattler) = FALSE;
+ gBattleBufferB[gActiveBattler][1] = 0;
+ *(gBattleStruct->stateIdAfterSelScript + gActiveBattler) = STATE_WAIT_ACTION_CHOSEN;
+ return;
+ }
+ else
+ {
+ *(gBattleStruct->chosenMovePositions + gActiveBattler) = gBattleBufferB[gActiveBattler][2];
+ gChosenMoveByBattler[gActiveBattler] = gBattleMons[gActiveBattler].moves[*(gBattleStruct->chosenMovePositions + gActiveBattler)];
+ *(gBattleStruct->moveTarget + gActiveBattler) = gBattleBufferB[gActiveBattler][3];
+ ++gBattleCommunication[gActiveBattler];
+ }
+ break;
+ }
+ break;
+ case B_ACTION_USE_ITEM:
+ if ((gBattleBufferB[gActiveBattler][1] | (gBattleBufferB[gActiveBattler][2] << 8)) == 0)
+ {
+ gBattleCommunication[gActiveBattler] = STATE_BEFORE_ACTION_CHOSEN;
+ }
+ else
+ {
+ gLastUsedItem = (gBattleBufferB[gActiveBattler][1] | (gBattleBufferB[gActiveBattler][2] << 8));
+ ++gBattleCommunication[gActiveBattler];
+ }
+ break;
+ case B_ACTION_SWITCH:
+ if (gBattleBufferB[gActiveBattler][1] == PARTY_SIZE)
+ {
+ gBattleCommunication[gActiveBattler] = STATE_BEFORE_ACTION_CHOSEN;
+ }
+ else
+ {
+ *(gBattleStruct->monToSwitchIntoId + gActiveBattler) = gBattleBufferB[gActiveBattler][1];
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ *(gActiveBattler * 3 + (u8 *)(gBattleStruct->field_60) + 0) &= 0xF;
+ *(gActiveBattler * 3 + (u8 *)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBattler][2] & 0xF0);
+ *(gActiveBattler * 3 + (u8 *)(gBattleStruct->field_60) + 1) = gBattleBufferB[gActiveBattler][3];
+ *((gActiveBattler ^ BIT_FLANK) * 3 + (u8 *)(gBattleStruct->field_60) + 0) &= (0xF0);
+ *((gActiveBattler ^ BIT_FLANK) * 3 + (u8 *)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBattler][2] & 0xF0) >> 4;
+ *((gActiveBattler ^ BIT_FLANK) * 3 + (u8 *)(gBattleStruct->field_60) + 2) = gBattleBufferB[gActiveBattler][3];
+ }
+ ++gBattleCommunication[gActiveBattler];
+ }
+ break;
+ case B_ACTION_RUN:
+ gHitMarker |= HITMARKER_RUN;
+ ++gBattleCommunication[gActiveBattler];
+ break;
+ case B_ACTION_SAFARI_WATCH_CAREFULLY:
+ ++gBattleCommunication[gActiveBattler];
+ break;
+ case B_ACTION_SAFARI_BALL:
+ ++gBattleCommunication[gActiveBattler];
+ break;
+ case B_ACTION_SAFARI_POKEBLOCK:
+ case B_ACTION_SAFARI_GO_NEAR:
+ ++gBattleCommunication[gActiveBattler];
+ break;
+ case B_ACTION_SAFARI_RUN:
+ gHitMarker |= HITMARKER_RUN;
+ ++gBattleCommunication[gActiveBattler];
+ break;
+ case B_ACTION_OLDMAN_THROW:
+ ++gBattleCommunication[gActiveBattler];
+ break;
+ }
+ }
+ break;
+ case STATE_WAIT_ACTION_CONFIRMED_STANDBY:
+ if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) | (0xF0000000) | (gBitTable[gActiveBattler] << 4) | (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 0xC))))
+ {
+ if (((gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_DOUBLE)) != BATTLE_TYPE_DOUBLE)
+ || (position & BIT_FLANK) != B_FLANK_LEFT
+ || (*(&gBattleStruct->field_91) & gBitTable[GetBattlerAtPosition(position ^ BIT_FLANK)]))
+ BtlController_EmitLinkStandbyMsg(0, 0);
+ else
+ BtlController_EmitLinkStandbyMsg(0, 1);
+ MarkBattlerForControllerExec(gActiveBattler);
+ ++gBattleCommunication[gActiveBattler];
+ }
+ break;
+ case STATE_WAIT_ACTION_CONFIRMED:
+ if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) | (0xF0000000) | (gBitTable[gActiveBattler] << 4) | (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 0xC))))
+ ++gBattleCommunication[ACTIONS_CONFIRMED_COUNT];
+ break;
+ case STATE_SELECTION_SCRIPT:
+ if (*(gBattleStruct->selectionScriptFinished + gActiveBattler))
+ {
+ gBattleCommunication[gActiveBattler] = *(gBattleStruct->stateIdAfterSelScript + gActiveBattler);
+ }
+ else
+ {
+ gBattlerAttacker = gActiveBattler;
+ gBattlescriptCurrInstr = gSelectionBattleScripts[gActiveBattler];
+ if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) | (0xF0000000) | (gBitTable[gActiveBattler] << 4) | (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 0xC))))
+ gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+ gSelectionBattleScripts[gActiveBattler] = gBattlescriptCurrInstr;
+ }
+ break;
+ case STATE_WAIT_SET_BEFORE_ACTION:
+ if (!(gBattleControllerExecFlags & ((gBitTable[gActiveBattler]) | (0xF0000000) | (gBitTable[gActiveBattler] << 4) | (gBitTable[gActiveBattler] << 8) | (gBitTable[gActiveBattler] << 0xC))))
+ gBattleCommunication[gActiveBattler] = STATE_BEFORE_ACTION_CHOSEN;
+ break;
+ }
+ }
+ // Check if everyone chose actions.
+ if (gBattleCommunication[ACTIONS_CONFIRMED_COUNT] == gBattlersCount)
+ gBattleMainFunc = SetActionsAndBattlersTurnOrder;
+}
+
+void SwapTurnOrder(u8 id1, u8 id2)
+{
+ u32 temp;
+
+ SWAP(gActionsByTurnOrder[id1], gActionsByTurnOrder[id2], temp);
+ SWAP(gBattlerByTurnOrder[id1], gBattlerByTurnOrder[id2], temp);
+}
+
+u8 GetWhoStrikesFirst(u8 battler1, u8 battler2, bool8 ignoreChosenMoves)
+{
+ u8 strikesFirst = 0;
+ u8 speedMultiplierBattler1 = 0, speedMultiplierBattler2 = 0;
+ u32 speedBattler1 = 0, speedBattler2 = 0;
+ u8 holdEffect = 0;
+ u8 holdEffectParam = 0;
+ u16 moveBattler1 = 0, moveBattler2 = 0;
+
+ if (WEATHER_HAS_EFFECT)
+ {
+ if ((gBattleMons[battler1].ability == ABILITY_SWIFT_SWIM && gBattleWeather & WEATHER_RAIN_ANY)
+ || (gBattleMons[battler1].ability == ABILITY_CHLOROPHYLL && gBattleWeather & WEATHER_SUN_ANY))
+ speedMultiplierBattler1 = 2;
+ else
+ speedMultiplierBattler1 = 1;
+ if ((gBattleMons[battler2].ability == ABILITY_SWIFT_SWIM && gBattleWeather & WEATHER_RAIN_ANY)
+ || (gBattleMons[battler2].ability == ABILITY_CHLOROPHYLL && gBattleWeather & WEATHER_SUN_ANY))
+ speedMultiplierBattler2 = 2;
+ else
+ speedMultiplierBattler2 = 1;
+ }
+ else
+ {
+ speedMultiplierBattler1 = 1;
+ speedMultiplierBattler2 = 1;
+ }
+ speedBattler1 = (gBattleMons[battler1].speed * speedMultiplierBattler1)
+ * (gStatStageRatios[gBattleMons[battler1].statStages[STAT_SPEED]][0])
+ / (gStatStageRatios[gBattleMons[battler1].statStages[STAT_SPEED]][1]);
+ if (gBattleMons[battler1].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[battler1].holdEffect;
+ holdEffectParam = gEnigmaBerries[battler1].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[battler1].item);
+ holdEffectParam = ItemId_GetHoldEffectParam(gBattleMons[battler1].item);
+ }
+ // badge boost
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK)
+ && FlagGet(FLAG_BADGE03_GET)
+ && GetBattlerSide(battler1) == B_SIDE_PLAYER)
+ speedBattler1 = (speedBattler1 * 110) / 100;
+ if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
+ speedBattler1 /= 2;
+ if (gBattleMons[battler1].status1 & STATUS1_PARALYSIS)
+ speedBattler1 /= 4;
+ if (holdEffect == HOLD_EFFECT_QUICK_CLAW && gRandomTurnNumber < (0xFFFF * holdEffectParam) / 100)
+ speedBattler1 = UINT_MAX;
+ // check second battlerId's speed
+ speedBattler2 = (gBattleMons[battler2].speed * speedMultiplierBattler2)
+ * (gStatStageRatios[gBattleMons[battler2].statStages[STAT_SPEED]][0])
+ / (gStatStageRatios[gBattleMons[battler2].statStages[STAT_SPEED]][1]);
+ if (gBattleMons[battler2].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[battler2].holdEffect;
+ holdEffectParam = gEnigmaBerries[battler2].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[battler2].item);
+ holdEffectParam = ItemId_GetHoldEffectParam(gBattleMons[battler2].item);
+ }
+ // badge boost
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK)
+ && FlagGet(FLAG_BADGE03_GET)
+ && GetBattlerSide(battler2) == B_SIDE_PLAYER)
+ speedBattler2 = (speedBattler2 * 110) / 100;
+ if (holdEffect == HOLD_EFFECT_MACHO_BRACE)
+ speedBattler2 /= 2;
+ if (gBattleMons[battler2].status1 & STATUS1_PARALYSIS)
+ speedBattler2 /= 4;
+ if (holdEffect == HOLD_EFFECT_QUICK_CLAW && gRandomTurnNumber < (0xFFFF * holdEffectParam) / 100)
+ speedBattler2 = UINT_MAX;
+ if (ignoreChosenMoves)
+ {
+ moveBattler1 = MOVE_NONE;
+ moveBattler2 = MOVE_NONE;
+ }
+ else
+ {
+ if (gChosenActionByBattler[battler1] == B_ACTION_USE_MOVE)
+ {
+ if (gProtectStructs[battler1].noValidMoves)
+ moveBattler1 = MOVE_STRUGGLE;
+ else
+ moveBattler1 = gBattleMons[battler1].moves[*(gBattleStruct->chosenMovePositions + battler1)];
+ }
+ else
+ moveBattler1 = MOVE_NONE;
+ if (gChosenActionByBattler[battler2] == B_ACTION_USE_MOVE)
+ {
+ if (gProtectStructs[battler2].noValidMoves)
+ moveBattler2 = MOVE_STRUGGLE;
+ else
+ moveBattler2 = gBattleMons[battler2].moves[*(gBattleStruct->chosenMovePositions + battler2)];
+ }
+ else
+ moveBattler2 = MOVE_NONE;
+ }
+ // both move priorities are different than 0
+ if (gBattleMoves[moveBattler1].priority != 0 || gBattleMoves[moveBattler2].priority != 0)
+ {
+ // both priorities are the same
+ if (gBattleMoves[moveBattler1].priority == gBattleMoves[moveBattler2].priority)
+ {
+ if (speedBattler1 == speedBattler2 && Random() & 1)
+ strikesFirst = 2; // same speeds, same priorities
+ else if (speedBattler1 < speedBattler2)
+ strikesFirst = 1; // battler2 has more speed
+ // else battler1 has more speed
+ }
+ else if (gBattleMoves[moveBattler1].priority < gBattleMoves[moveBattler2].priority)
+ strikesFirst = 1; // battler2's move has greater priority
+ // else battler1's move has greater priority
+ }
+ // both priorities are equal to 0
+ else
+ {
+ if (speedBattler1 == speedBattler2 && Random() & 1)
+ strikesFirst = 2; // same speeds, same priorities
+ else if (speedBattler1 < speedBattler2)
+ strikesFirst = 1; // battler2 has more speed
+ // else battler1 has more speed
+ }
+ return strikesFirst;
+}
+
+static void SetActionsAndBattlersTurnOrder(void)
+{
+ s32 turnOrderId = 0;
+ s32 i, j;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ {
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ gActionsByTurnOrder[turnOrderId] = gChosenActionByBattler[gActiveBattler];
+ gBattlerByTurnOrder[turnOrderId] = gActiveBattler;
+ ++turnOrderId;
+ }
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ if (gChosenActionByBattler[gActiveBattler] == B_ACTION_RUN)
+ {
+ turnOrderId = 5;
+ break;
+ }
+ }
+ }
+ else if (gChosenActionByBattler[0] == B_ACTION_RUN)
+ {
+ gActiveBattler = 0;
+ turnOrderId = 5;
+ }
+ if (turnOrderId == 5) // One of battlers wants to run.
+ {
+ gActionsByTurnOrder[0] = gChosenActionByBattler[gActiveBattler];
+ gBattlerByTurnOrder[0] = gActiveBattler;
+ turnOrderId = 1;
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ if (i != gActiveBattler)
+ {
+ gActionsByTurnOrder[turnOrderId] = gChosenActionByBattler[i];
+ gBattlerByTurnOrder[turnOrderId] = i;
+ ++turnOrderId;
+ }
+ }
+ gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts;
+ gBattleStruct->focusPunchBattlerId = 0;
+ return;
+ }
+ else
+ {
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ if (gChosenActionByBattler[gActiveBattler] == B_ACTION_USE_ITEM || gChosenActionByBattler[gActiveBattler] == B_ACTION_SWITCH)
+ {
+ gActionsByTurnOrder[turnOrderId] = gChosenActionByBattler[gActiveBattler];
+ gBattlerByTurnOrder[turnOrderId] = gActiveBattler;
+ ++turnOrderId;
+ }
+ }
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ if (gChosenActionByBattler[gActiveBattler] != B_ACTION_USE_ITEM && gChosenActionByBattler[gActiveBattler] != B_ACTION_SWITCH)
+ {
+ gActionsByTurnOrder[turnOrderId] = gChosenActionByBattler[gActiveBattler];
+ gBattlerByTurnOrder[turnOrderId] = gActiveBattler;
+ ++turnOrderId;
+ }
+ }
+ for (i = 0; i < gBattlersCount - 1; ++i)
+ {
+ for (j = i + 1; j < gBattlersCount; ++j)
+ {
+ u8 battler1 = gBattlerByTurnOrder[i];
+ u8 battler2 = gBattlerByTurnOrder[j];
+
+ if (gActionsByTurnOrder[i] != B_ACTION_USE_ITEM
+ && gActionsByTurnOrder[j] != B_ACTION_USE_ITEM
+ && gActionsByTurnOrder[i] != B_ACTION_SWITCH
+ && gActionsByTurnOrder[j] != B_ACTION_SWITCH)
+ if (GetWhoStrikesFirst(battler1, battler2, FALSE))
+ SwapTurnOrder(i, j);
+ }
+ }
+ }
+ }
+ gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts;
+ gBattleStruct->focusPunchBattlerId = 0;
+}
+
+static void TurnValuesCleanUp(bool8 var0)
+{
+ s32 i;
+ u8 *dataPtr;
+
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ if (var0)
+ {
+ gProtectStructs[gActiveBattler].protected = FALSE;
+ gProtectStructs[gActiveBattler].endured = FALSE;
+ }
+ else
+ {
+ dataPtr = (u8 *)(&gProtectStructs[gActiveBattler]);
+ for (i = 0; i < sizeof(struct ProtectStruct); ++i)
+ dataPtr[i] = 0;
+ if (gDisableStructs[gActiveBattler].isFirstTurn)
+ --gDisableStructs[gActiveBattler].isFirstTurn;
+ if (gDisableStructs[gActiveBattler].rechargeTimer)
+ {
+ --gDisableStructs[gActiveBattler].rechargeTimer;
+ if (gDisableStructs[gActiveBattler].rechargeTimer == 0)
+ gBattleMons[gActiveBattler].status2 &= ~(STATUS2_RECHARGE);
+ }
+ }
+
+ if (gDisableStructs[gActiveBattler].substituteHP == 0)
+ gBattleMons[gActiveBattler].status2 &= ~(STATUS2_SUBSTITUTE);
+ }
+ gSideTimers[0].followmeTimer = 0;
+ gSideTimers[1].followmeTimer = 0;
+}
+
+static void SpecialStatusesClear(void)
+{
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ s32 i;
+ u8 *dataPtr = (u8 *)(&gSpecialStatuses[gActiveBattler]);
+
+ for (i = 0; i < sizeof(struct SpecialStatus); ++i)
+ dataPtr[i] = 0;
+ }
+}
+
+static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void)
+{
+ if (!(gHitMarker & HITMARKER_RUN))
+ {
+ while (gBattleStruct->focusPunchBattlerId < gBattlersCount)
+ {
+ gActiveBattler = gBattlerAttacker = gBattleStruct->focusPunchBattlerId;
+ ++gBattleStruct->focusPunchBattlerId;
+ if (gChosenMoveByBattler[gActiveBattler] == MOVE_FOCUS_PUNCH
+ && !(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP)
+ && !(gDisableStructs[gBattlerAttacker].truantCounter)
+ && !(gProtectStructs[gActiveBattler].noValidMoves))
+ {
+ BattleScriptExecute(BattleScript_FocusPunchSetUp);
+ return;
+ }
+ }
+ }
+ TryClearRageStatuses();
+ gCurrentTurnActionNumber = 0;
+ {
+ // something stupid needed to match
+ u8 zero;
+
+ gCurrentActionFuncId = gActionsByTurnOrder[(zero = 0)];
+ }
+ gDynamicBasePower = 0;
+ gBattleStruct->dynamicMoveType = 0;
+ gBattleMainFunc = RunTurnActionsFunctions;
+ gBattleCommunication[3] = 0;
+ gBattleCommunication[4] = 0;
+ gBattleScripting.multihitMoveEffect = 0;
+ gBattleResources->battleScriptsStack->size = 0;
+}
+
+static void RunTurnActionsFunctions(void)
+{
+ if (gBattleOutcome != 0)
+ gCurrentActionFuncId = B_ACTION_FINISHED;
+ *(&gBattleStruct->savedTurnActionNumber) = gCurrentTurnActionNumber;
+ sTurnActionsFuncsTable[gCurrentActionFuncId]();
+
+ if (gCurrentTurnActionNumber >= gBattlersCount) // everyone did their actions, turn finished
+ {
+ gHitMarker &= ~(HITMARKER_x100000);
+ gBattleMainFunc = sEndTurnFuncsTable[gBattleOutcome & 0x7F];
+ }
+ else
+ {
+ if (gBattleStruct->savedTurnActionNumber != gCurrentTurnActionNumber) // action turn has been done, clear hitmarker bits for another battlerId
+ {
+ gHitMarker &= ~(HITMARKER_NO_ATTACKSTRING);
+ gHitMarker &= ~(HITMARKER_UNABLE_TO_USE_MOVE);
+ }
+ }
+}
+
+static void HandleEndTurn_BattleWon(void)
+{
+ gCurrentActionFuncId = 0;
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ gBattleTextBuff1[0] = gBattleOutcome;
+ gBattlerAttacker = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
+ gBattlescriptCurrInstr = BattleScript_LinkBattleWonOrLost;
+ gBattleOutcome &= ~(B_OUTCOME_LINK_BATTLE_RAN);
+ }
+ else if (gBattleTypeFlags & (BATTLE_TYPE_TRAINER_TOWER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_BATTLE_TOWER))
+ {
+ BattleStopLowHpSound();
+ PlayBGM(MUS_WIN_TRE);
+ gBattlescriptCurrInstr = gUnknown_81D88D7;
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && !(gBattleTypeFlags & BATTLE_TYPE_LINK))
+ {
+ BattleStopLowHpSound();
+ gBattlescriptCurrInstr = BattleScript_LocalTrainerBattleWon;
+ switch (gTrainers[gTrainerBattleOpponent_A].trainerClass)
+ {
+ case CLASS_LEADER_2:
+ case CLASS_CHAMPION_2:
+ PlayBGM(MUS_WIN_GYM);
+ break;
+ case CLASS_BOSS:
+ case CLASS_TEAM_ROCKET:
+ case CLASS_COOLTRAINER_2:
+ case CLASS_ELITE_FOUR_2:
+ case CLASS_GENTLEMAN_2:
+ default:
+ PlayBGM(MUS_WIN_TRE);
+ break;
+ }
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BattleScript_PayDayMoneyAndPickUpItems;
+ }
+ gBattleMainFunc = HandleEndTurn_FinishBattle;
+}
+
+static void HandleEndTurn_BattleLost(void)
+{
+ gCurrentActionFuncId = 0;
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ gBattleTextBuff1[0] = gBattleOutcome;
+ gBattlerAttacker = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
+ gBattlescriptCurrInstr = BattleScript_LinkBattleWonOrLost;
+ gBattleOutcome &= ~(B_OUTCOME_LINK_BATTLE_RAN);
+ }
+ else
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && ScrSpecial_GetTrainerBattleMode() == 9)
+ {
+ if (sub_80803D8() & 1)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ gBattlerAttacker = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ gBattlescriptCurrInstr = BattleScript_LocalBattleLost;
+ }
+ gBattleMainFunc = HandleEndTurn_FinishBattle;
+}
+
+static void HandleEndTurn_RanFromBattle(void)
+{
+ gCurrentActionFuncId = 0;
+ switch (gProtectStructs[gBattlerAttacker].fleeFlag)
+ {
+ default:
+ gBattlescriptCurrInstr = BattleScript_GotAwaySafely;
+ break;
+ case 1:
+ gBattlescriptCurrInstr = BattleScript_SmokeBallEscape;
+ break;
+ case 2:
+ gBattlescriptCurrInstr = BattleScript_RanAwayUsingMonAbility;
+ break;
+ }
+ gBattleMainFunc = HandleEndTurn_FinishBattle;
+}
+
+static void HandleEndTurn_MonFled(void)
+{
+ gCurrentActionFuncId = 0;
+ PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBattlerAttacker, gBattlerPartyIndexes[gBattlerAttacker]);
+ gBattlescriptCurrInstr = BattleScript_WildMonFled;
+ gBattleMainFunc = HandleEndTurn_FinishBattle;
+}
+
+static void HandleEndTurn_FinishBattle(void)
+{
+ if (gCurrentActionFuncId == B_ACTION_TRY_FINISH || gCurrentActionFuncId == B_ACTION_FINISHED)
+ {
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_TRAINER_TOWER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_OLD_MAN_TUTORIAL | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_SAFARI | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_LINK)))
+ {
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
+ {
+ if (gBattleResults.playerMon1Species == SPECIES_NONE)
+ {
+ gBattleResults.playerMon1Species = gBattleMons[gActiveBattler].species;
+ StringCopy(gBattleResults.playerMon1Name, gBattleMons[gActiveBattler].nickname);
+ }
+ else
+ {
+ gBattleResults.playerMon2Species = gBattleMons[gActiveBattler].species;
+ StringCopy(gBattleResults.playerMon2Name, gBattleMons[gActiveBattler].nickname);
+ }
+ }
+ }
+ }
+ sub_812BFDC();
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ sub_810CB90();
+ BeginFastPaletteFade(3);
+ FadeOutMapMusic(5);
+ gBattleMainFunc = FreeResetData_ReturnToOvOrDoEvolutions;
+ gCB2_AfterEvolution = BattleMainCB2;
+ }
+ else if (!gBattleControllerExecFlags)
+ {
+ gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+ }
+}
+
+static void FreeResetData_ReturnToOvOrDoEvolutions(void)
+{
+ if (!gPaletteFade.active)
+ {
+ ResetSpriteData();
+ if (gLeveledUpInBattle == 0 || gBattleOutcome != B_OUTCOME_WON)
+ gBattleMainFunc = ReturnFromBattleToOverworld;
+ else
+ gBattleMainFunc = TryEvolvePokemon;
+ FreeAllWindowBuffers();
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK))
+ {
+ FreeMonSpritesGfx();
+ FreeBattleSpritesData();
+ FreeBattleResources();
+ }
+ }
+}
+
+static void TryEvolvePokemon(void)
+{
+ s32 i;
+
+ while (gLeveledUpInBattle != 0)
+ {
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ if (gLeveledUpInBattle & gBitTable[i])
+ {
+ u16 species;
+ u8 levelUpBits = gLeveledUpInBattle;
+
+ levelUpBits &= ~(gBitTable[i]);
+ gLeveledUpInBattle = levelUpBits;
+ species = GetEvolutionTargetSpecies(&gPlayerParty[i], 0, levelUpBits);
+ if (species != SPECIES_NONE)
+ {
+ gBattleMainFunc = WaitForEvoSceneToFinish;
+ EvolutionScene(&gPlayerParty[i], species, 0x81, i);
+ return;
+ }
+ }
+ }
+ }
+ gBattleMainFunc = ReturnFromBattleToOverworld;
+}
+
+static void WaitForEvoSceneToFinish(void)
+{
+ if (gMain.callback2 == BattleMainCB2)
+ gBattleMainFunc = TryEvolvePokemon;
+}
+
+static void ReturnFromBattleToOverworld(void)
+{
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK))
+ {
+ RandomlyGivePartyPokerus(gPlayerParty);
+ PartySpreadPokerus(gPlayerParty);
+ }
+ if (!(gBattleTypeFlags & BATTLE_TYPE_LINK) || gReceivedRemoteLinkPlayers == 0)
+ {
+ gSpecialVar_Result = gBattleOutcome;
+ gMain.inBattle = FALSE;
+ gMain.callback1 = gPreBattleCallback1;
+ if (gBattleTypeFlags & BATTLE_TYPE_ROAMER)
+ {
+ UpdateRoamerHPStatus(&gEnemyParty[0]);
+ if ((gBattleOutcome & B_OUTCOME_WON) || gBattleOutcome == B_OUTCOME_CAUGHT)
+ SetRoamerInactive();
+ }
+ m4aSongNumStop(SE_HINSI);
+ SetMainCallback2(gMain.savedCallback);
+ }
+}
+
+void RunBattleScriptCommands_PopCallbacksStack(void)
+{
+ if (gCurrentActionFuncId == B_ACTION_TRY_FINISH || gCurrentActionFuncId == B_ACTION_FINISHED)
+ {
+ if (gBattleResources->battleCallbackStack->size != 0)
+ --gBattleResources->battleCallbackStack->size;
+ gBattleMainFunc = gBattleResources->battleCallbackStack->function[gBattleResources->battleCallbackStack->size];
+ }
+ else
+ {
+ if (!gBattleControllerExecFlags)
+ gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+ }
+}
+
+void RunBattleScriptCommands(void)
+{
+ if (!gBattleControllerExecFlags)
+ gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]]();
+}
+
+static void HandleAction_UseMove(void)
+{
+ u8 side;
+ u8 var = 4;
+
+ gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
+ if (*(&gBattleStruct->field_91) & gBitTable[gBattlerAttacker])
+ {
+ gCurrentActionFuncId = B_ACTION_FINISHED;
+ return;
+ }
+ gCritMultiplier = 1;
+ gBattleScripting.dmgMultiplier = 1;
+ gBattleStruct->atkCancellerTracker = 0;
+ gMoveResultFlags = 0;
+ gMultiHitCounter = 0;
+ gBattleCommunication[6] = 0;
+ gCurrMovePos = gChosenMovePos = *(gBattleStruct->chosenMovePositions + gBattlerAttacker);
+ // choose move
+ if (gProtectStructs[gBattlerAttacker].noValidMoves)
+ {
+ gProtectStructs[gBattlerAttacker].noValidMoves = 0;
+ gCurrentMove = gChosenMove = MOVE_STRUGGLE;
+ gHitMarker |= HITMARKER_NO_PPDEDUCT;
+ *(gBattleStruct->moveTarget + gBattlerAttacker) = GetMoveTarget(MOVE_STRUGGLE, 0);
+ }
+ else if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS || gBattleMons[gBattlerAttacker].status2 & STATUS2_RECHARGE)
+ {
+ gCurrentMove = gChosenMove = gLockedMoves[gBattlerAttacker];
+ }
+ // encore forces you to use the same move
+ else if (gDisableStructs[gBattlerAttacker].encoredMove != MOVE_NONE
+ && gDisableStructs[gBattlerAttacker].encoredMove == gBattleMons[gBattlerAttacker].moves[gDisableStructs[gBattlerAttacker].encoredMovePos])
+ {
+ gCurrentMove = gChosenMove = gDisableStructs[gBattlerAttacker].encoredMove;
+ gCurrMovePos = gChosenMovePos = gDisableStructs[gBattlerAttacker].encoredMovePos;
+ *(gBattleStruct->moveTarget + gBattlerAttacker) = GetMoveTarget(gCurrentMove, 0);
+ }
+ // check if the encored move wasn't overwritten
+ else if (gDisableStructs[gBattlerAttacker].encoredMove != MOVE_NONE
+ && gDisableStructs[gBattlerAttacker].encoredMove != gBattleMons[gBattlerAttacker].moves[gDisableStructs[gBattlerAttacker].encoredMovePos])
+ {
+ gCurrMovePos = gChosenMovePos = gDisableStructs[gBattlerAttacker].encoredMovePos;
+ gCurrentMove = gChosenMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
+ gDisableStructs[gBattlerAttacker].encoredMove = MOVE_NONE;
+ gDisableStructs[gBattlerAttacker].encoredMovePos = 0;
+ gDisableStructs[gBattlerAttacker].encoreTimer = 0;
+ *(gBattleStruct->moveTarget + gBattlerAttacker) = GetMoveTarget(gCurrentMove, 0);
+ }
+ else if (gBattleMons[gBattlerAttacker].moves[gCurrMovePos] != gChosenMoveByBattler[gBattlerAttacker])
+ {
+ gCurrentMove = gChosenMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
+ *(gBattleStruct->moveTarget + gBattlerAttacker) = GetMoveTarget(gCurrentMove, 0);
+ }
+ else
+ {
+ gCurrentMove = gChosenMove = gBattleMons[gBattlerAttacker].moves[gCurrMovePos];
+ }
+ if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
+ gBattleResults.lastUsedMovePlayer = gCurrentMove;
+ else
+ gBattleResults.lastUsedMoveOpponent = gCurrentMove;
+ // choose target
+ side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
+ if (gSideTimers[side].followmeTimer != 0
+ && gBattleMoves[gCurrentMove].target == MOVE_TARGET_SELECTED
+ && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget)
+ && gBattleMons[gSideTimers[side].followmeTarget].hp != 0)
+ {
+ gBattlerTarget = gSideTimers[side].followmeTarget;
+ }
+ else if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ && gSideTimers[side].followmeTimer == 0
+ && (gBattleMoves[gCurrentMove].power != 0
+ || gBattleMoves[gCurrentMove].target != MOVE_TARGET_USER)
+ && gBattleMons[*(gBattleStruct->moveTarget + gBattlerAttacker)].ability != ABILITY_LIGHTNING_ROD
+ && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC)
+ {
+ side = GetBattlerSide(gBattlerAttacker);
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ if (side != GetBattlerSide(gActiveBattler)
+ && *(gBattleStruct->moveTarget + gBattlerAttacker) != gActiveBattler
+ && gBattleMons[gActiveBattler].ability == ABILITY_LIGHTNING_ROD
+ && GetBattlerTurnOrderNum(gActiveBattler) < var)
+ var = GetBattlerTurnOrderNum(gActiveBattler);
+ if (var == 4)
+ {
+ if (gBattleMoves[gChosenMove].target & MOVE_TARGET_RANDOM)
+ {
+ if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
+ {
+ if (Random() & 1)
+ gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
+ else
+ gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
+ }
+ else
+ {
+ if (Random() & 1)
+ gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
+ else
+ gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
+ }
+ }
+ else
+ {
+ gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker);
+ }
+ if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
+ {
+ if (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget))
+ {
+ gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerTarget) ^ BIT_FLANK);
+ }
+ else
+ {
+ gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerAttacker) ^ BIT_SIDE);
+ if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
+ gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerTarget) ^ BIT_FLANK);
+ }
+ }
+ }
+ else
+ {
+ gActiveBattler = gBattlerByTurnOrder[var];
+ RecordAbilityBattle(gActiveBattler, gBattleMons[gActiveBattler].ability);
+ gSpecialStatuses[gActiveBattler].lightningRodRedirected = 1;
+ gBattlerTarget = gActiveBattler;
+ }
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
+ && gBattleMoves[gChosenMove].target & MOVE_TARGET_RANDOM)
+ {
+ if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
+ {
+ if (Random() & 1)
+ gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
+ else
+ gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
+ }
+ else
+ {
+ if (Random() & 1)
+ gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
+ else
+ gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT);
+ }
+ if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]
+ && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget))
+ gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerTarget) ^ BIT_FLANK);
+ }
+ else
+ {
+ gBattlerTarget = *(gBattleStruct->moveTarget + gBattlerAttacker);
+ if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
+ {
+ if (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget))
+ {
+ gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerTarget) ^ BIT_FLANK);
+ }
+ else
+ {
+ gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerAttacker) ^ BIT_SIDE);
+ if (gAbsentBattlerFlags & gBitTable[gBattlerTarget])
+ gBattlerTarget = GetBattlerAtPosition(GetBattlerPosition(gBattlerTarget) ^ BIT_FLANK);
+ }
+ }
+ }
+ gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
+ gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
+}
+
+static void HandleAction_Switch(void)
+{
+ gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gActionSelectionCursor[gBattlerAttacker] = 0;
+ gMoveSelectionCursor[gBattlerAttacker] = 0;
+ PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBattlerAttacker, *(gBattleStruct->field_58 + gBattlerAttacker));
+ gBattleScripting.battler = gBattlerAttacker;
+ gBattlescriptCurrInstr = BattleScript_ActionSwitch;
+ gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
+ if (gBattleResults.playerSwitchesCounter < 255)
+ ++gBattleResults.playerSwitchesCounter;
+}
+
+static void HandleAction_UseItem(void)
+{
+ gBattlerAttacker = gBattlerTarget = gBattlerByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ ClearFuryCutterDestinyBondGrudge(gBattlerAttacker);
+ gLastUsedItem = gBattleBufferB[gBattlerAttacker][1] | (gBattleBufferB[gBattlerAttacker][2] << 8);
+ if (gLastUsedItem <= ITEM_PREMIER_BALL) // is ball
+ {
+ gBattlescriptCurrInstr = gBattlescriptsForBallThrow[gLastUsedItem];
+ }
+ else if (gLastUsedItem == ITEM_POKE_DOLL || gLastUsedItem == ITEM_FLUFFY_TAIL)
+ {
+ gBattlescriptCurrInstr = gBattlescriptsForRunningByItem[0];
+ }
+ else if (gLastUsedItem == ITEM_POKE_FLUTE)
+ {
+ gBattlescriptCurrInstr = gBattlescriptsForRunningByItem[1];
+ }
+ else if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
+ {
+ gBattlescriptCurrInstr = gBattlescriptsForUsingItem[0];
+ }
+ else
+ {
+ gBattleScripting.battler = gBattlerAttacker;
+ switch (*(gBattleStruct->AI_itemType + (gBattlerAttacker >> 1)))
+ {
+ case AI_ITEM_FULL_RESTORE:
+ case AI_ITEM_HEAL_HP:
+ break;
+ case AI_ITEM_CURE_CONDITION:
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ if (*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) & 1)
+ {
+ if (*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) & 0x3E)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 5;
+ }
+ else
+ {
+ while (!(*(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) & 1))
+ {
+ *(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) >>= 1;
+ ++gBattleCommunication[MULTISTRING_CHOOSER];
+ }
+ }
+ break;
+ case AI_ITEM_X_STAT:
+ gBattleCommunication[MULTISTRING_CHOOSER] = 4;
+ if (*(gBattleStruct->AI_itemFlags + (gBattlerAttacker >> 1)) & 0x80)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 5;
+ }
+ else
+ {
+ PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK);
+ PREPARE_STRING_BUFFER(gBattleTextBuff2, CHAR_X);
+ while (!((*(gBattleStruct->AI_itemFlags + (gBattlerAttacker >> 1))) & 1))
+ {
+ *(gBattleStruct->AI_itemFlags + gBattlerAttacker / 2) >>= 1;
+ ++gBattleTextBuff1[2];
+ }
+ gBattleScripting.animArg1 = gBattleTextBuff1[2] + 14;
+ gBattleScripting.animArg2 = 0;
+ }
+ break;
+ case AI_ITEM_GUARD_SPECS:
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ break;
+ }
+
+ gBattlescriptCurrInstr = gBattlescriptsForUsingItem[*(gBattleStruct->AI_itemType + gBattlerAttacker / 2)];
+ }
+ gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
+}
+
+bool8 TryRunFromBattle(u8 battler)
+{
+ bool8 effect = FALSE;
+ u8 holdEffect;
+ u8 pyramidMultiplier;
+ u8 speedVar;
+
+ if (gBattleMons[battler].item == ITEM_ENIGMA_BERRY)
+ holdEffect = gEnigmaBerries[battler].holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[battler].item);
+ gPotentialItemEffectBattler = battler;
+ if (holdEffect == HOLD_EFFECT_CAN_ALWAYS_RUN)
+ {
+ gLastUsedItem = gBattleMons[battler].item;
+ gProtectStructs[battler].fleeFlag = 1;
+ ++effect;
+ }
+ else if (gBattleMons[battler].ability == ABILITY_RUN_AWAY)
+ {
+ gLastUsedAbility = ABILITY_RUN_AWAY;
+ gProtectStructs[battler].fleeFlag = 2;
+ ++effect;
+ }
+ else if ((gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_GHOST)) == BATTLE_TYPE_GHOST)
+ {
+ if (GetBattlerSide(battler) == B_SIDE_PLAYER)
+ ++effect;
+ }
+ else
+ {
+ if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ {
+ if (gBattleMons[battler].speed < gBattleMons[BATTLE_OPPOSITE(battler)].speed)
+ {
+ speedVar = (gBattleMons[battler].speed * 128) / (gBattleMons[BATTLE_OPPOSITE(battler)].speed) + (gBattleStruct->runTries * 30);
+ if (speedVar > (Random() & 0xFF))
+ ++effect;
+ }
+ else // same speed or faster
+ {
+ ++effect;
+ }
+ }
+
+ ++gBattleStruct->runTries;
+ }
+ if (effect)
+ {
+ gCurrentTurnActionNumber = gBattlersCount;
+ gBattleOutcome = B_OUTCOME_RAN;
+ }
+ return effect;
+}
+
+static void HandleAction_Run(void)
+{
+ gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
+
+ if (gBattleTypeFlags & BATTLE_TYPE_LINK)
+ {
+ gCurrentTurnActionNumber = gBattlersCount;
+ for (gActiveBattler = 0; gActiveBattler < gBattlersCount; ++gActiveBattler)
+ {
+ if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
+ {
+ if (gChosenActionByBattler[gActiveBattler] == B_ACTION_RUN)
+ gBattleOutcome |= B_OUTCOME_LOST;
+ }
+ else
+ {
+ if (gChosenActionByBattler[gActiveBattler] == B_ACTION_RUN)
+ gBattleOutcome |= B_OUTCOME_WON;
+ }
+ }
+ gBattleOutcome |= B_OUTCOME_LINK_BATTLE_RAN;
+ }
+ else
+ {
+ if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
+ {
+ if (!TryRunFromBattle(gBattlerAttacker)) // failed to run away
+ {
+ ClearFuryCutterDestinyBondGrudge(gBattlerAttacker);
+ gBattleCommunication[MULTISTRING_CHOOSER] = 3;
+ gBattlescriptCurrInstr = BattleScript_PrintFailedToRunString;
+ gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
+ }
+ }
+ else
+ {
+ if (gBattleMons[gBattlerAttacker].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 4;
+ gBattlescriptCurrInstr = BattleScript_PrintFailedToRunString;
+ gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
+ }
+ else
+ {
+ gCurrentTurnActionNumber = gBattlersCount;
+ gBattleOutcome = B_OUTCOME_MON_FLED;
+ }
+ }
+ }
+}
+
+static void HandleAction_WatchesCarefully(void)
+{
+ gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ if (gBattleStruct->safariGoNearCounter != 0)
+ {
+ --gBattleStruct->safariGoNearCounter;
+ if (gBattleStruct->safariGoNearCounter == 0)
+ {
+ *(&gBattleStruct->safariCatchFactor) = gBaseStats[GetMonData(gEnemyParty, MON_DATA_SPECIES)].catchRate * 100 / 1275;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ }
+ else
+ {
+ if (gBattleStruct->safariPkblThrowCounter != 0)
+ {
+ --gBattleStruct->safariPkblThrowCounter;
+ if (gBattleStruct->safariPkblThrowCounter == 0)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ else
+ gBattleCommunication[5] = 2;
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ }
+ gBattlescriptCurrInstr = gBattlescriptsForSafariActions[0];
+ gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
+}
+
+static void HandleAction_SafariZoneBallThrow(void)
+{
+ gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ --gNumSafariBalls;
+ gLastUsedItem = ITEM_SAFARI_BALL;
+ gBattlescriptCurrInstr = gBattlescriptsForBallThrow[ITEM_SAFARI_BALL];
+ gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
+}
+
+static void HandleAction_ThrowPokeblock(void)
+{
+ gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gBattleStruct->safariPkblThrowCounter += Random() % 5 + 2;
+ if (gBattleStruct->safariPkblThrowCounter > 6)
+ gBattleStruct->safariPkblThrowCounter = 6;
+ gBattleStruct->safariGoNearCounter = 0;
+ gBattleStruct->safariCatchFactor >>= 1;
+ if (gBattleStruct->safariCatchFactor <= 2)
+ gBattleStruct->safariCatchFactor = 3;
+ gBattlescriptCurrInstr = gBattlescriptsForSafariActions[2];
+ gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
+}
+
+static void HandleAction_GoNear(void)
+{
+ gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ gBattleStruct->safariGoNearCounter += Random() % 5 + 2;
+ if (gBattleStruct->safariGoNearCounter > 6)
+ gBattleStruct->safariGoNearCounter = 6;
+ gBattleStruct->safariPkblThrowCounter = 0;
+ gBattleStruct->safariCatchFactor <<= 1;
+ if (gBattleStruct->safariCatchFactor > 20)
+ gBattleStruct->safariCatchFactor = 20;
+ gBattlescriptCurrInstr = gBattlescriptsForSafariActions[1];
+ gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
+}
+
+static void HandleAction_SafariZoneRun(void)
+{
+ gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
+ PlaySE(SE_NIGERU);
+ gCurrentTurnActionNumber = gBattlersCount;
+ gBattleOutcome = B_OUTCOME_RAN;
+}
+
+static void HandleAction_OldManBallThrow(void)
+{
+ gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber];
+ gBattle_BG0_X = 0;
+ gBattle_BG0_Y = 0;
+ PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBattlerAttacker, gBattlerPartyIndexes[gBattlerAttacker])
+ gBattlescriptCurrInstr = gBattlescriptsForSafariActions[3];
+ gCurrentActionFuncId = B_ACTION_EXEC_SCRIPT;
+ gActionsByTurnOrder[1] = B_ACTION_FINISHED;
+}
+
+static void HandleAction_TryFinish(void)
+{
+ if (!HandleFaintedMonActions())
+ {
+ gBattleStruct->faintedActionsState = 0;
+ gCurrentActionFuncId = B_ACTION_FINISHED;
+ }
+}
+
+static void HandleAction_NothingIsFainted(void)
+{
+ ++gCurrentTurnActionNumber;
+ gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber];
+ gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED
+ | HITMARKER_NO_PPDEDUCT | HITMARKER_IGNORE_SAFEGUARD | HITMARKER_IGNORE_ON_AIR
+ | HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_x100000
+ | HITMARKER_OBEYS | HITMARKER_x10 | HITMARKER_SYNCHRONISE_EFFECT
+ | HITMARKER_CHARGING | HITMARKER_x4000000);
+}
+
+static void HandleAction_ActionFinished(void)
+{
+ ++gCurrentTurnActionNumber;
+ gCurrentActionFuncId = gActionsByTurnOrder[gCurrentTurnActionNumber];
+ SpecialStatusesClear();
+ gHitMarker &= ~(HITMARKER_DESTINYBOND | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_ATTACKSTRING_PRINTED
+ | HITMARKER_NO_PPDEDUCT | HITMARKER_IGNORE_SAFEGUARD | HITMARKER_IGNORE_ON_AIR
+ | HITMARKER_IGNORE_UNDERGROUND | HITMARKER_IGNORE_UNDERWATER | HITMARKER_x100000
+ | HITMARKER_OBEYS | HITMARKER_x10 | HITMARKER_SYNCHRONISE_EFFECT
+ | HITMARKER_CHARGING | HITMARKER_x4000000);
+ gCurrentMove = MOVE_NONE;
+ gBattleMoveDamage = 0;
+ gMoveResultFlags = 0;
+ gBattleScripting.animTurn = 0;
+ gBattleScripting.animTargetsHit = 0;
+ gLastLandedMoves[gBattlerAttacker] = 0;
+ gLastHitByType[gBattlerAttacker] = 0;
+ gBattleStruct->dynamicMoveType = 0;
+ gDynamicBasePower = 0;
+ gBattleScripting.atk49_state = 0;
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
+ gBattleCommunication[ACTIONS_CONFIRMED_COUNT] = 0;
+ gBattleScripting.multihitMoveEffect = 0;
+ gBattleResources->battleScriptsStack->size = 0;
+}
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index 3de2a6dea..a7d8cb6fa 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -48,6 +48,7 @@
#include "constants/abilities.h"
#include "constants/pokemon.h"
#include "constants/trainers.h"
+#include "constants/map_types.h"
#define DEFENDER_IS_PROTECTED ((gProtectStructs[gBattlerTarget].protected) && (gBattleMoves[gCurrentMove].flags & FLAG_PROTECT_AFFECTED))
@@ -1222,7 +1223,7 @@ static void atk04_critcalc(void)
critChance = NELEMS(sCriticalHitChance) - 1;
if ((gBattleMons[gBattlerTarget].ability != ABILITY_BATTLE_ARMOR && gBattleMons[gBattlerTarget].ability != ABILITY_SHELL_ARMOR)
&& !(gStatuses3[gBattlerAttacker] & STATUS3_CANT_SCORE_A_CRIT)
- && !(gBattleTypeFlags & BATTLE_TYPE_OLDMAN_TUTORIAL)
+ && !(gBattleTypeFlags & BATTLE_TYPE_OLD_MAN_TUTORIAL)
&& !(Random() % sCriticalHitChance[critChance])
&& (!(gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) || sub_80EB2E0(1))
&& !(gBattleTypeFlags & BATTLE_TYPE_POKEDUDE))
@@ -4414,7 +4415,7 @@ static void atk4E_switchinanim(void)
&& !(gBattleTypeFlags &
(BATTLE_TYPE_LINK
| BATTLE_TYPE_LEGENDARY
- | BATTLE_TYPE_OLDMAN_TUTORIAL
+ | BATTLE_TYPE_OLD_MAN_TUTORIAL
| BATTLE_TYPE_POKEDUDE
| BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_GHOST)))
@@ -9436,7 +9437,7 @@ static void atkEF_handleballthrow(void)
MarkBattlerForControllerExec(gActiveBattler);
gBattlescriptCurrInstr = BattleScript_TrainerBallBlock;
}
- else if (gBattleTypeFlags & (BATTLE_TYPE_POKEDUDE | BATTLE_TYPE_OLDMAN_TUTORIAL))
+ else if (gBattleTypeFlags & (BATTLE_TYPE_POKEDUDE | BATTLE_TYPE_OLD_MAN_TUTORIAL))
{
BtlController_EmitBallThrowAnim(0, BALL_3_SHAKES_SUCCESS);
MarkBattlerForControllerExec(gActiveBattler);
@@ -9451,7 +9452,6 @@ static void atkEF_handleballthrow(void)
catchRate = gBattleStruct->safariCatchFactor * 1275 / 100;
else
catchRate = gBaseStats[gBattleMons[gBattlerTarget].species].catchRate;
-
if (gLastUsedItem > ITEM_SAFARI_BALL)
{
switch (gLastUsedItem)
@@ -9515,7 +9515,7 @@ static void atkEF_handleballthrow(void)
else
{
if (gBattleResults.catchAttempts[gLastUsedItem - ITEM_ULTRA_BALL] < 0xFF)
- gBattleResults.catchAttempts[gLastUsedItem - ITEM_ULTRA_BALL]++;
+ ++gBattleResults.catchAttempts[gLastUsedItem - ITEM_ULTRA_BALL];
}
}
if (odds > 254) // mon caught
diff --git a/src/battle_setup.c b/src/battle_setup.c
new file mode 100644
index 000000000..98437e279
--- /dev/null
+++ b/src/battle_setup.c
@@ -0,0 +1,1060 @@
+#include "global.h"
+#include "task.h"
+#include "help_system.h"
+#include "overworld.h"
+#include "item.h"
+#include "sound.h"
+#include "pokemon.h"
+#include "load_save.h"
+#include "safari_zone.h"
+#include "quest_log.h"
+#include "script.h"
+#include "script_pokemon_util_80A0058.h"
+#include "strings.h"
+#include "string_util.h"
+#include "event_data.h"
+#include "unk_8159F40.h"
+#include "map_obj_80688E4.h"
+#include "metatile_behavior.h"
+#include "event_scripts.h"
+#include "fldeff.h"
+#include "fieldmap.h"
+#include "field_control_avatar.h"
+#include "field_player_avatar.h"
+#include "field_screen_effect.h"
+#include "field_message_box.h"
+#include "field_map_obj.h"
+#include "vs_seeker.h"
+#include "battle.h"
+#include "battle_setup.h"
+#include "battle_transition.h"
+#include "constants/battle_setup.h"
+#include "constants/flags.h"
+#include "constants/items.h"
+#include "constants/maps.h"
+#include "constants/songs.h"
+#include "constants/species.h"
+#include "constants/pokemon.h"
+#include "constants/trainers.h"
+#include "constants/trainer_classes.h"
+#include "constants/map_types.h"
+
+enum
+{
+ TRAINER_PARAM_LOAD_VAL_8BIT,
+ TRAINER_PARAM_LOAD_VAL_16BIT,
+ TRAINER_PARAM_LOAD_VAL_32BIT,
+ TRAINER_PARAM_CLEAR_VAL_8BIT,
+ TRAINER_PARAM_CLEAR_VAL_16BIT,
+ TRAINER_PARAM_CLEAR_VAL_32BIT,
+ TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR,
+};
+
+struct TrainerBattleParameter
+{
+ void *varPtr;
+ u8 ptrType;
+};
+
+static void DoSafariBattle(void);
+static void DoGhostBattle(void);
+static void DoStandardWildBattle(void);
+static void CB2_EndWildBattle(void);
+static u8 GetWildBattleTransition(void);
+static u8 GetTrainerBattleTransition(void);
+static void CB2_EndScriptedWildBattle(void);
+static void CB2_EndMarowakBattle(void);
+static bool32 IsPlayerDefeated(u32 battleOutcome);
+static void CB2_EndTrainerBattle(void);
+static const u8 *GetIntroSpeechOfApproachingTrainer(void);
+static const u8 *GetTrainerCantBattleSpeech(void);
+
+static EWRAM_DATA u16 sTrainerBattleMode = 0;
+EWRAM_DATA u16 gTrainerBattleOpponent_A = 0;
+static EWRAM_DATA u16 sTrainerEventObjectLocalId = 0;
+static EWRAM_DATA u8 *sTrainerAIntroSpeech = NULL;
+static EWRAM_DATA u8 *sTrainerADefeatSpeech = NULL;
+static EWRAM_DATA u8 *sTrainerVictorySpeech = NULL;
+static EWRAM_DATA u8 *sTrainerCannotBattleSpeech = NULL;
+static EWRAM_DATA u8 *sTrainerBattleEndScript = NULL;
+static EWRAM_DATA u8 *sTrainerABattleScriptRetAddr = NULL;
+static EWRAM_DATA u16 gUnknown_20386CC = 0;
+
+static const u8 sBattleTransitionTable_Wild[][2] =
+{
+ B_TRANSITION_SLICED_SCREEN, B_TRANSITION_WHITEFADE_IN_STRIPES,
+ B_TRANSITION_CLOCKWISE_BLACKFADE, B_TRANSITION_GRID_SQUARES,
+ B_TRANSITION_BLUR, B_TRANSITION_GRID_SQUARES,
+ B_TRANSITION_BLACK_WAVE_TO_RIGHT, B_TRANSITION_FULLSCREEN_WAVE,
+};
+
+static const u8 sBattleTransitionTable_Trainer[][2] =
+{
+ B_TRANSITION_SLIDING_POKEBALLS, B_TRANSITION_BLACK_DOODLES,
+ B_TRANSITION_HORIZONTAL_CORRUGATE, B_TRANSITION_BIG_POKEBALL,
+ B_TRANSITION_BLUR, B_TRANSITION_GRID_SQUARES,
+ B_TRANSITION_DISTORTED_WAVE, B_TRANSITION_FULLSCREEN_WAVE,
+};
+
+static const struct TrainerBattleParameter sOrdinaryBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerEventObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sContinueScriptBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerEventObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sDoubleBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerEventObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sOrdinaryNoIntroBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerEventObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sTutorialBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&gUnknown_20386CC, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+static const struct TrainerBattleParameter sContinueScriptDoubleBattleParams[] =
+{
+ {&sTrainerBattleMode, TRAINER_PARAM_LOAD_VAL_8BIT},
+ {&gTrainerBattleOpponent_A, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerEventObjectLocalId, TRAINER_PARAM_LOAD_VAL_16BIT},
+ {&sTrainerAIntroSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerADefeatSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerVictorySpeech, TRAINER_PARAM_CLEAR_VAL_32BIT},
+ {&sTrainerCannotBattleSpeech, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerABattleScriptRetAddr, TRAINER_PARAM_LOAD_VAL_32BIT},
+ {&sTrainerBattleEndScript, TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR},
+};
+
+
+#define tState data[0]
+#define tTransition data[1]
+
+static void Task_BattleStart(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (tState)
+ {
+ case 0:
+ if (!FldEffPoison_IsActive())
+ {
+ HelpSystem_Disable();
+ BT_StartOnField(tTransition);
+ ++tState;
+ }
+ break;
+ case 1:
+ if (BT_IsDone() == TRUE)
+ {
+ HelpSystem_Enable();
+ CleanupOverworldWindowsAndTilemaps();
+ SetMainCallback2(CB2_InitBattle);
+ RestartWildEncounterImmunitySteps();
+ ClearPoisonStepCounter();
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
+
+static void CreateBattleStartTask(u8 transition, u16 song) // song == 0 means default music for current map
+{
+ u8 taskId = CreateTask(Task_BattleStart, 1);
+
+ gTasks[taskId].tTransition = transition;
+ PlayMapChosenOrBattleBGM(song);
+}
+
+static bool8 CheckSilphScopeInPokemonTower(u16 mapGroup, u16 mapNum)
+{
+ if (mapGroup == MAP_GROUP(POKEMON_TOWER_1F)
+ && ((u16)(mapNum - MAP_NUM(POKEMON_TOWER_1F)) <= 6)
+ && !(CheckBagHasItem(ITEM_SILPH_SCOPE, 1)))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void BattleSetup_StartWildBattle(void)
+{
+ if (GetSafariZoneFlag())
+ DoSafariBattle();
+ else if (CheckSilphScopeInPokemonTower(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum))
+ DoGhostBattle();
+ else
+ DoStandardWildBattle();
+}
+
+static void DoStandardWildBattle(void)
+{
+ ScriptContext2_Enable();
+ FreezeEventObjects();
+ sub_805C780();
+ gMain.savedCallback = CB2_EndWildBattle;
+ gBattleTypeFlags = 0;
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+}
+
+void BattleSetup_StartRoamerBattle(void)
+{
+ ScriptContext2_Enable();
+ FreezeEventObjects();
+ sub_805C780();
+ gMain.savedCallback = CB2_EndWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_ROAMER;
+ CreateBattleStartTask(GetWildBattleTransition(), MUS_VS_DEN);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+}
+
+static void DoSafariBattle(void)
+{
+ ScriptContext2_Enable();
+ FreezeEventObjects();
+ sub_805C780();
+ gMain.savedCallback = CB2_EndSafariBattle;
+ gBattleTypeFlags = BATTLE_TYPE_SAFARI;
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+}
+
+static void DoGhostBattle(void)
+{
+ ScriptContext2_Enable();
+ FreezeEventObjects();
+ sub_805C780();
+ gMain.savedCallback = CB2_EndWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_GHOST;
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+ SetMonData(&gEnemyParty[0], MON_DATA_NICKNAME, gUnknown_841D148);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+}
+
+static void DoTrainerBattle(void)
+{
+ CreateBattleStartTask(GetTrainerBattleTransition(), 0);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_TRAINER_BATTLES);
+}
+
+void ScrSpecial_StartOldManTutorialBattle(void)
+{
+ CreateMaleMon(&gEnemyParty[0], SPECIES_WEEDLE, 5);
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_ReturnToFieldContinueScriptPlayMapMusic;
+ gBattleTypeFlags = BATTLE_TYPE_OLD_MAN_TUTORIAL;
+ CreateBattleStartTask(B_TRANSITION_SLICED_SCREEN, 0);
+}
+
+void BattleSetup_StartScriptedWildBattle(void)
+{
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndScriptedWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_PALACE;
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+}
+
+void ScrSpecial_StartMarowakBattle(void)
+{
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndMarowakBattle;
+ if (CheckBagHasItem(ITEM_SILPH_SCOPE, 1))
+ {
+ gBattleTypeFlags = BATTLE_TYPE_GHOST | BATTLE_TYPE_LEGENDARY;
+ CreateMonWithGenderNatureLetter(gEnemyParty, SPECIES_MAROWAK, 30, 31, MON_FEMALE, NATURE_SERIOUS, 0);
+ }
+ else
+ {
+ gBattleTypeFlags = BATTLE_TYPE_GHOST;
+ }
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+ SetMonData(&gEnemyParty[0], MON_DATA_NICKNAME, gUnknown_841D148);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+}
+
+void ScrSpecial_StartSouthernIslandBattle(void)
+{
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndScriptedWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_LEGENDARY;
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+}
+
+void Special_StartLegendaryBattle(void)
+{
+ u16 species;
+
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndScriptedWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_ARENA;
+ species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES);
+ switch (species)
+ {
+ case SPECIES_MEWTWO:
+ CreateBattleStartTask(B_TRANSITION_BLUR, MUS_VS_MYU2);
+ break;
+ case SPECIES_DEOXYS:
+ CreateBattleStartTask(B_TRANSITION_BLUR, MUS_VS_DEO);
+ break;
+ case SPECIES_MOLTRES:
+ case SPECIES_ARTICUNO:
+ case SPECIES_ZAPDOS:
+ case SPECIES_HO_OH:
+ case SPECIES_LUGIA:
+ CreateBattleStartTask(B_TRANSITION_BLUR, MUS_VS_DEN);
+ break;
+ default:
+ CreateBattleStartTask(B_TRANSITION_BLUR, MUS_BATTLE20);
+ break;
+ }
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+}
+
+void Special_StartGroudonKyogreBattle(void)
+{
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndScriptedWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_KYOGRE_GROUDON;
+ if (gGameVersion == VERSION_FIRE_RED)
+ CreateBattleStartTask(B_TRANSITION_BLACK_DOODLES, MUS_BATTLE20);
+ else // pointless, exactly the same
+ CreateBattleStartTask(B_TRANSITION_BLACK_DOODLES, MUS_BATTLE20);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+}
+
+void Special_StartRegiBattle(void)
+{
+ ScriptContext2_Enable();
+ gMain.savedCallback = CB2_EndScriptedWildBattle;
+ gBattleTypeFlags = BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_REGI;
+ CreateBattleStartTask(B_TRANSITION_BLUR, MUS_BATTLE20);
+ IncrementGameStat(GAME_STAT_TOTAL_BATTLES);
+ IncrementGameStat(GAME_STAT_WILD_BATTLES);
+}
+
+// not used
+static void sub_807FAF8(void)
+{
+ LoadPlayerParty();
+ CB2_EndWildBattle();
+}
+
+// not used
+static void sub_807FB08(void)
+{
+ ScriptContext2_Enable();
+ FreezeEventObjects();
+ sub_805C780();
+ gMain.savedCallback = sub_807FAF8;
+ SavePlayerParty();
+ InitPokedudePartyAndOpponent();
+ CreateBattleStartTask(GetWildBattleTransition(), 0);
+}
+
+static void CB2_EndWildBattle(void)
+{
+ CpuFill16(0, (void *)BG_PLTT, BG_PLTT_SIZE);
+ ResetOamRange(0, 128);
+ if (IsPlayerDefeated(gBattleOutcome) == TRUE)
+ {
+ SetMainCallback2(CB2_WhiteOut);
+ }
+ else
+ {
+ SetMainCallback2(CB2_ReturnToField);
+ gFieldCallback = sub_807E3EC;
+ }
+}
+
+static void CB2_EndScriptedWildBattle(void)
+{
+ CpuFill16(0, (void *)BG_PLTT, BG_PLTT_SIZE);
+ ResetOamRange(0, 128);
+ if (IsPlayerDefeated(gBattleOutcome) == TRUE)
+ SetMainCallback2(CB2_WhiteOut);
+ else
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+}
+
+static void CB2_EndMarowakBattle(void)
+{
+ CpuFill16(0, (void *)BG_PLTT, BG_PLTT_SIZE);
+ ResetOamRange(0, 128);
+ if (IsPlayerDefeated(gBattleOutcome))
+ {
+ SetMainCallback2(CB2_WhiteOut);
+ }
+ else
+ {
+ if (gBattleOutcome == B_OUTCOME_WON)
+ gSpecialVar_Result = 0;
+ else
+ gSpecialVar_Result = 1;
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+ }
+}
+
+u8 BattleSetup_GetTerrainId(void)
+{
+ u16 tileBehavior;
+ s16 x, y;
+
+ PlayerGetDestCoords(&x, &y);
+ tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
+ if (MetatileBehavior_IsTallGrass_2(tileBehavior))
+ return BATTLE_TERRAIN_GRASS;
+ if (MetatileBehavior_IsLongGrass(tileBehavior))
+ return BATTLE_TERRAIN_LONG_GRASS;
+ if (MetatileBehavior_IsSandOrDeepSand(tileBehavior))
+ return BATTLE_TERRAIN_SAND;
+ switch (gMapHeader.mapType)
+ {
+ case MAP_TYPE_TOWN:
+ case MAP_TYPE_CITY:
+ case MAP_TYPE_ROUTE:
+ break;
+ case MAP_TYPE_UNDERGROUND:
+ if (MetatileBehavior_IsIndoorEncounter(tileBehavior))
+ return BATTLE_TERRAIN_BUILDING;
+ if (MetatileBehavior_IsSurfable(tileBehavior))
+ return BATTLE_TERRAIN_POND;
+ return BATTLE_TERRAIN_CAVE;
+ case MAP_TYPE_INDOOR:
+ case MAP_TYPE_SECRET_BASE:
+ return BATTLE_TERRAIN_BUILDING;
+ case MAP_TYPE_UNDERWATER:
+ return BATTLE_TERRAIN_UNDERWATER;
+ case MAP_TYPE_OCEAN_ROUTE:
+ if (MetatileBehavior_IsSurfable(tileBehavior))
+ return BATTLE_TERRAIN_WATER;
+ return BATTLE_TERRAIN_PLAIN;
+ }
+ if (MetatileBehavior_IsDeepSemiDeepOrSplashingWater(tileBehavior))
+ return BATTLE_TERRAIN_WATER;
+ if (MetatileBehavior_IsSurfable(tileBehavior))
+ return BATTLE_TERRAIN_POND;
+ if (MetatileBehavior_IsMountain(tileBehavior))
+ return BATTLE_TERRAIN_MOUNTAIN;
+ if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING))
+ {
+ if (MetatileBehavior_GetBridgeType(tileBehavior))
+ return BATTLE_TERRAIN_POND;
+ if (MetatileBehavior_IsBridge(tileBehavior) == TRUE)
+ return BATTLE_TERRAIN_WATER;
+ }
+ return BATTLE_TERRAIN_PLAIN;
+}
+
+static u8 GetBattleTransitionTypeByMap(void)
+{
+ u16 tileBehavior;
+ s16 x, y;
+
+ PlayerGetDestCoords(&x, &y);
+ tileBehavior = MapGridGetMetatileBehaviorAt(x, y);
+ if (Overworld_GetFlashLevel())
+ return B_TRANSITION_HORIZONTAL_CORRUGATE;
+ if (!MetatileBehavior_IsSurfable(tileBehavior))
+ {
+ switch (gMapHeader.mapType)
+ {
+ case MAP_TYPE_UNDERGROUND:
+ return B_TRANSITION_DISTORTED_WAVE;
+ case MAP_TYPE_UNDERWATER:
+ return B_TRANSITION_BIG_POKEBALL;
+ default:
+ return B_TRANSITION_BLUR;
+ }
+ }
+ return B_TRANSITION_BIG_POKEBALL;
+}
+
+static u16 GetSumOfPlayerPartyLevel(u8 numMons)
+{
+ u8 sum = 0;
+ s32 i;
+
+ for (i = 0; i < PARTY_SIZE; ++i)
+ {
+ u32 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+
+ if (species != SPECIES_EGG && species != SPECIES_NONE && GetMonData(&gPlayerParty[i], MON_DATA_HP) != 0)
+ {
+ sum += GetMonData(&gPlayerParty[i], MON_DATA_LEVEL);
+ if (--numMons == 0)
+ break;
+ }
+ }
+ return sum;
+}
+
+static u8 GetSumOfEnemyPartyLevel(u16 opponentId, u8 numMons)
+{
+ u8 i;
+ u8 sum;
+ u32 count = numMons;
+
+ if (gTrainers[opponentId].partySize < count)
+ count = gTrainers[opponentId].partySize;
+ sum = 0;
+ switch (gTrainers[opponentId].partyFlags)
+ {
+ case 0:
+ {
+ const struct TrainerMonNoItemDefaultMoves *party;
+
+ party = gTrainers[opponentId].party.NoItemDefaultMoves;
+ for (i = 0; i < count; ++i)
+ sum += party[i].lvl;
+ }
+ break;
+ case F_TRAINER_PARTY_CUSTOM_MOVESET:
+ {
+ const struct TrainerMonNoItemCustomMoves *party;
+
+ party = gTrainers[opponentId].party.NoItemCustomMoves;
+ for (i = 0; i < count; ++i)
+ sum += party[i].lvl;
+ }
+ break;
+ case F_TRAINER_PARTY_HELD_ITEM:
+ {
+ const struct TrainerMonItemDefaultMoves *party;
+
+ party = gTrainers[opponentId].party.ItemDefaultMoves;
+ for (i = 0; i < count; ++i)
+ sum += party[i].lvl;
+ }
+ break;
+ case F_TRAINER_PARTY_CUSTOM_MOVESET | F_TRAINER_PARTY_HELD_ITEM:
+ {
+ const struct TrainerMonItemCustomMoves *party;
+
+ party = gTrainers[opponentId].party.ItemCustomMoves;
+ for (i = 0; i < count; ++i)
+ sum += party[i].lvl;
+ }
+ break;
+ }
+ return sum;
+}
+
+static u8 GetWildBattleTransition(void)
+{
+ u8 transitionType = GetBattleTransitionTypeByMap();
+ u8 enemyLevel = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL);
+ u8 playerLevel = GetSumOfPlayerPartyLevel(1);
+
+ if (enemyLevel < playerLevel)
+ return sBattleTransitionTable_Wild[transitionType][0];
+ else
+ return sBattleTransitionTable_Wild[transitionType][1];
+}
+
+static u8 GetTrainerBattleTransition(void)
+{
+ u8 minPartyCount;
+ u8 transitionType;
+ u8 enemyLevel;
+ u8 playerLevel;
+
+ if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE)
+ return B_TRANSITION_BLUE;
+ if (gTrainers[gTrainerBattleOpponent_A].trainerClass == CLASS_ELITE_FOUR_2)
+ {
+ if (gTrainerBattleOpponent_A == TRAINER_ELITE_FOUR_LORELEI || gTrainerBattleOpponent_A == TRAINER_ELITE_FOUR_LORELEI_2)
+ return B_TRANSITION_LORELEI;
+ if (gTrainerBattleOpponent_A == TRAINER_ELITE_FOUR_BRUNO || gTrainerBattleOpponent_A == TRAINER_ELITE_FOUR_BRUNO_2)
+ return B_TRANSITION_BRUNO;
+ if (gTrainerBattleOpponent_A == TRAINER_ELITE_FOUR_AGATHA || gTrainerBattleOpponent_A == TRAINER_ELITE_FOUR_AGATHA_2)
+ return B_TRANSITION_AGATHA;
+ if (gTrainerBattleOpponent_A == TRAINER_ELITE_FOUR_LANCE || gTrainerBattleOpponent_A == TRAINER_ELITE_FOUR_LANCE_2)
+ return B_TRANSITION_LANCE;
+ return B_TRANSITION_BLUE;
+ }
+ if (gTrainers[gTrainerBattleOpponent_A].trainerClass == CLASS_CHAMPION_2)
+ return B_TRANSITION_BLUE;
+ if (gTrainers[gTrainerBattleOpponent_A].doubleBattle == TRUE)
+ minPartyCount = 2; // double battles always at least have 2 pokemon.
+ else
+ minPartyCount = 1;
+ transitionType = GetBattleTransitionTypeByMap();
+ enemyLevel = GetSumOfEnemyPartyLevel(gTrainerBattleOpponent_A, minPartyCount);
+ playerLevel = GetSumOfPlayerPartyLevel(minPartyCount);
+ if (enemyLevel < playerLevel)
+ return sBattleTransitionTable_Trainer[transitionType][0];
+ else
+ return sBattleTransitionTable_Trainer[transitionType][1];
+}
+
+u8 sub_8080060(void)
+{
+ u8 enemyLevel = GetMonData(&gEnemyParty[0], MON_DATA_LEVEL);
+ u8 playerLevel = GetSumOfPlayerPartyLevel(1);
+
+ if (enemyLevel < playerLevel)
+ return 4;
+ else
+ return 3;
+}
+
+static u32 TrainerBattleLoadArg32(const u8 *ptr)
+{
+ return T1_READ_32(ptr);
+}
+
+static u16 TrainerBattleLoadArg16(const u8 *ptr)
+{
+ return T1_READ_16(ptr);
+}
+
+static u8 TrainerBattleLoadArg8(const u8 *ptr)
+{
+ return T1_READ_8(ptr);
+}
+
+static u16 GetTrainerAFlag(void)
+{
+ return FLAG_TRAINER_FLAG_START + gTrainerBattleOpponent_A;
+}
+
+static bool32 IsPlayerDefeated(u32 battleOutcome)
+{
+ switch (battleOutcome)
+ {
+ case B_OUTCOME_LOST:
+ case B_OUTCOME_DREW:
+ return TRUE;
+ case B_OUTCOME_WON:
+ case B_OUTCOME_RAN:
+ case B_OUTCOME_PLAYER_TELEPORTED:
+ case B_OUTCOME_MON_FLED:
+ case B_OUTCOME_CAUGHT:
+ return FALSE;
+ default:
+ return FALSE;
+ }
+}
+
+static void InitTrainerBattleVariables(void)
+{
+ sTrainerBattleMode = 0;
+ gTrainerBattleOpponent_A = 0;
+ sTrainerEventObjectLocalId = 0;
+ sTrainerAIntroSpeech = NULL;
+ sTrainerADefeatSpeech = NULL;
+ sTrainerVictorySpeech = NULL;
+ sTrainerCannotBattleSpeech = NULL;
+ sTrainerBattleEndScript = NULL;
+ sTrainerABattleScriptRetAddr = NULL;
+ gUnknown_20386CC = 0;
+}
+
+static inline void SetU8(void *ptr, u8 value)
+{
+ *(u8 *)(ptr) = value;
+}
+
+static inline void SetU16(void *ptr, u16 value)
+{
+ *(u16 *)(ptr) = value;
+}
+
+static inline void SetU32(void *ptr, u32 value)
+{
+ *(u32 *)(ptr) = value;
+}
+
+static inline void SetPtr(const void *ptr, const void *value)
+{
+ *(const void **)(ptr) = value;
+}
+
+static void TrainerBattleLoadArgs(const struct TrainerBattleParameter *specs, const u8 *data)
+{
+ while (1)
+ {
+ switch (specs->ptrType)
+ {
+ case TRAINER_PARAM_LOAD_VAL_8BIT:
+ SetU8(specs->varPtr, TrainerBattleLoadArg8(data));
+ data += 1;
+ break;
+ case TRAINER_PARAM_LOAD_VAL_16BIT:
+ SetU16(specs->varPtr, TrainerBattleLoadArg16(data));
+ data += 2;
+ break;
+ case TRAINER_PARAM_LOAD_VAL_32BIT:
+ SetU32(specs->varPtr, TrainerBattleLoadArg32(data));
+ data += 4;
+ break;
+ case TRAINER_PARAM_CLEAR_VAL_8BIT:
+ SetU8(specs->varPtr, 0);
+ break;
+ case TRAINER_PARAM_CLEAR_VAL_16BIT:
+ SetU16(specs->varPtr, 0);
+ break;
+ case TRAINER_PARAM_CLEAR_VAL_32BIT:
+ SetU32(specs->varPtr, 0);
+ break;
+ case TRAINER_PARAM_LOAD_SCRIPT_RET_ADDR:
+ SetPtr(specs->varPtr, data);
+ return;
+ }
+ ++specs;
+ }
+}
+
+static void SetMapVarsToTrainer(void)
+{
+ if (sTrainerEventObjectLocalId != 0)
+ {
+ gSpecialVar_LastTalked = sTrainerEventObjectLocalId;
+ gSelectedEventObject = GetFieldObjectIdByLocalIdAndMap(sTrainerEventObjectLocalId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
+ }
+}
+
+const u8 *BattleSetup_ConfigureTrainerBattle(const u8 *data)
+{
+ InitTrainerBattleVariables();
+ sTrainerBattleMode = TrainerBattleLoadArg8(data);
+ switch (sTrainerBattleMode)
+ {
+ case TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT:
+ TrainerBattleLoadArgs(sOrdinaryNoIntroBattleParams, data);
+ return EventScript_DoTrainerBattle;
+ case TRAINER_BATTLE_DOUBLE:
+ TrainerBattleLoadArgs(sDoubleBattleParams, data);
+ SetMapVarsToTrainer();
+ return EventScript_TryDoDoubleTrainerBattle;
+ case TRAINER_BATTLE_CONTINUE_SCRIPT:
+ case TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC:
+ TrainerBattleLoadArgs(sContinueScriptBattleParams, data);
+ SetMapVarsToTrainer();
+ return EventScript_TryDoNormalTrainerBattle;
+ case TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE:
+ case TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC:
+ TrainerBattleLoadArgs(sContinueScriptDoubleBattleParams, data);
+ SetMapVarsToTrainer();
+ return EventScript_TryDoDoubleTrainerBattle;
+ case TRAINER_BATTLE_REMATCH_DOUBLE:
+ sub_811231C();
+ TrainerBattleLoadArgs(sDoubleBattleParams, data);
+ SetMapVarsToTrainer();
+ gTrainerBattleOpponent_A = GetRematchTrainerId(gTrainerBattleOpponent_A);
+ return EventScript_TryDoDoubleRematchBattle;
+ case TRAINER_BATTLE_REMATCH:
+ sub_811231C();
+ TrainerBattleLoadArgs(sOrdinaryBattleParams, data);
+ SetMapVarsToTrainer();
+ gTrainerBattleOpponent_A = GetRematchTrainerId(gTrainerBattleOpponent_A);
+ return EventScript_TryDoRematchBattle;
+ case TRAINER_BATTLE_TUTORIAL:
+ TrainerBattleLoadArgs(sTutorialBattleParams, data);
+ return EventScript_DoTrainerBattle;
+ default:
+ TrainerBattleLoadArgs(sOrdinaryBattleParams, data);
+ SetMapVarsToTrainer();
+ return EventScript_TryDoNormalTrainerBattle;
+ }
+}
+
+void ConfigureAndSetUpOneTrainerBattle(u8 trainerEventObjId, const u8 *trainerScript)
+{
+ gSelectedEventObject = trainerEventObjId;
+ gSpecialVar_LastTalked = gMapObjects[trainerEventObjId].localId;
+ BattleSetup_ConfigureTrainerBattle(trainerScript + 1);
+ ScriptContext1_SetupScript(gUnknown_81A4EB4);
+ ScriptContext2_Enable();
+}
+
+bool32 GetTrainerFlagFromScriptPointer(const u8 *data)
+{
+ u32 flag = TrainerBattleLoadArg16(data + 2);
+
+ return FlagGet(FLAG_TRAINER_FLAG_START + flag);
+}
+
+void SetUpTrainerMovement(void)
+{
+ struct MapObject *eventObject = &gMapObjects[gSelectedEventObject];
+
+ SetTrainerMovementType(eventObject, GetTrainerFacingDirectionMovementType(eventObject->facingDirection));
+}
+
+u8 ScrSpecial_GetTrainerBattleMode(void)
+{
+ return sTrainerBattleMode;
+}
+
+u16 sub_80803D8(void)
+{
+ return gUnknown_20386CC;
+}
+
+u16 ScrSpecial_HasTrainerBeenFought(void)
+{
+ return FlagGet(GetTrainerAFlag());
+}
+
+void SetBattledTrainerFlag(void)
+{
+ FlagSet(GetTrainerAFlag());
+}
+
+// not used
+static void SetBattledTrainerFlag2(void)
+{
+ FlagSet(GetTrainerAFlag());
+}
+
+bool8 HasTrainerBeenFought(u16 trainerId)
+{
+ return FlagGet(FLAG_TRAINER_FLAG_START + trainerId);
+}
+
+void SetTrainerFlag(u16 trainerId)
+{
+ FlagSet(FLAG_TRAINER_FLAG_START + trainerId);
+}
+
+void ClearTrainerFlag(u16 trainerId)
+{
+ FlagClear(FLAG_TRAINER_FLAG_START + trainerId);
+}
+
+void BattleSetup_StartTrainerBattle(void)
+{
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER;
+ if (ScrSpecial_GetTrainerBattleMode() == TRAINER_BATTLE_TUTORIAL
+ && sub_80803D8() & 3)
+ gBattleTypeFlags |= BATTLE_TYPE_FIRST_BATTLE;
+ gMain.savedCallback = CB2_EndTrainerBattle;
+ DoTrainerBattle();
+ ScriptContext1_Stop();
+}
+
+static void CB2_EndTrainerBattle(void)
+{
+ if (sTrainerBattleMode == TRAINER_BATTLE_TUTORIAL)
+ {
+ if (IsPlayerDefeated(gBattleOutcome) == TRUE)
+ {
+ gSpecialVar_Result = 1;
+ if (gUnknown_20386CC & 1)
+ {
+ sp000_heal_pokemon();
+ }
+ else
+ {
+ SetMainCallback2(CB2_WhiteOut);
+ return;
+ }
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+ SetBattledTrainerFlag();
+ sub_81139BC();
+ }
+ else
+ {
+ gSpecialVar_Result = 0;
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+ SetBattledTrainerFlag();
+ sub_81139BC();
+ }
+
+ }
+ else
+ {
+ if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE)
+ {
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+ }
+ else if (IsPlayerDefeated(gBattleOutcome) == TRUE)
+ {
+ SetMainCallback2(CB2_WhiteOut);
+ }
+ else
+ {
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+ SetBattledTrainerFlag();
+ sub_81139BC();
+ }
+ }
+}
+
+static void CB2_EndRematchBattle(void)
+{
+ if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE)
+ {
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+ }
+ else if (IsPlayerDefeated(gBattleOutcome) == TRUE)
+ {
+ SetMainCallback2(CB2_WhiteOut);
+ }
+ else
+ {
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+ SetBattledTrainerFlag();
+ sub_810CDE8();
+ sub_81138F8();
+ }
+}
+
+void ScrSpecial_StartTrainerEyeRematch(void)
+{
+ gBattleTypeFlags = BATTLE_TYPE_TRAINER;
+ gMain.savedCallback = CB2_EndRematchBattle;
+ DoTrainerBattle();
+ ScriptContext1_Stop();
+}
+
+void ScrSpecial_ShowTrainerIntroSpeech(void)
+{
+ ShowFieldMessage(GetIntroSpeechOfApproachingTrainer());
+}
+
+const u8 *BattleSetup_GetScriptAddrAfterBattle(void)
+{
+ if (sTrainerBattleEndScript != NULL)
+ return sTrainerBattleEndScript;
+ else
+ return EventScript_1C555B;
+}
+
+const u8 *BattleSetup_GetTrainerPostBattleScript(void)
+{
+ if (sTrainerABattleScriptRetAddr != NULL)
+ return sTrainerABattleScriptRetAddr;
+ else
+ return EventScript_1C555B;
+}
+
+void ScrSpecial_ShowTrainerNonBattlingSpeech(void)
+{
+ ShowFieldMessage(GetTrainerCantBattleSpeech());
+}
+
+void PlayTrainerEncounterMusic(void)
+{
+ u16 music;
+
+ if (gUnknown_203ADFA != 2
+ && gUnknown_203ADFA != 3
+ && sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC
+ && sTrainerBattleMode != TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC)
+ {
+ switch (GetTrainerEncounterMusicId(gTrainerBattleOpponent_A))
+ {
+ case TRAINER_ENCOUNTER_MUSIC_FEMALE:
+ case TRAINER_ENCOUNTER_MUSIC_GIRL:
+ case TRAINER_ENCOUNTER_MUSIC_TWINS:
+ music = MUS_SHOUJO;
+ break;
+ case TRAINER_ENCOUNTER_MUSIC_MALE:
+ case TRAINER_ENCOUNTER_MUSIC_INTENSE:
+ case TRAINER_ENCOUNTER_MUSIC_COOL:
+ case TRAINER_ENCOUNTER_MUSIC_SWIMMER:
+ case TRAINER_ENCOUNTER_MUSIC_ELITE_FOUR:
+ case TRAINER_ENCOUNTER_MUSIC_HIKER:
+ case TRAINER_ENCOUNTER_MUSIC_INTERVIEWER:
+ case TRAINER_ENCOUNTER_MUSIC_RICH:
+ music = MUS_SHOUNEN;
+ break;
+ default:
+ music = MUS_ROCKET;
+ break;
+ }
+ PlayNewMapMusic(music);
+ }
+}
+
+static const u8 *ReturnEmptyStringIfNull(const u8 *string)
+{
+ if (string == NULL)
+ return gString_Dummy;
+ else
+ return string;
+}
+
+static const u8 *GetIntroSpeechOfApproachingTrainer(void)
+{
+ return ReturnEmptyStringIfNull(sTrainerAIntroSpeech);
+}
+
+const u8 *GetTrainerALoseText(void)
+{
+ const u8 *string = sTrainerADefeatSpeech;
+
+ StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(string));
+ return gStringVar4;
+}
+
+const u8 *GetTrainerWonSpeech(void)
+{
+ StringExpandPlaceholders(gStringVar4, ReturnEmptyStringIfNull(sTrainerVictorySpeech));
+ return gStringVar4;
+}
+
+static const u8 *GetTrainerCantBattleSpeech(void)
+{
+ return ReturnEmptyStringIfNull(sTrainerCannotBattleSpeech);
+}
diff --git a/src/battle_transition.c b/src/battle_transition.c
index 19d76fed1..1dbfe3aed 100644
--- a/src/battle_transition.c
+++ b/src/battle_transition.c
@@ -27,7 +27,7 @@ struct TransitionData
u16 winOut;
u16 win0H;
u16 win0V;
- u16 unused_A;
+ u16 win1H; // not used
u16 win1V;
u16 bldCnt;
u16 bldAlpha;
@@ -3175,7 +3175,7 @@ static bool8 BT_Phase2WhiteFadeInStripes_Stop(struct Task *task)
DmaStop(0);
SetVBlankCallback(NULL);
SetHBlankCallback(NULL);
- sTransitionStructPtr->win0H = 240;
+ sTransitionStructPtr->win0H = WIN_RANGE(0, 240);
sTransitionStructPtr->bldY = 0;
sTransitionStructPtr->bldCnt = BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_DARKEN;
sTransitionStructPtr->winIn = WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ | WININ_WIN0_CLR;
diff --git a/src/battle_util2.c b/src/battle_util2.c
index d940d8508..a3a748767 100644
--- a/src/battle_util2.c
+++ b/src/battle_util2.c
@@ -1,6 +1,7 @@
#include "global.h"
#include "bg.h"
#include "battle.h"
+#include "battle_anim.h"
#include "pokemon.h"
#include "malloc.h"
#include "trainer_tower.h"
diff --git a/src/berry.c b/src/berry.c
index 91d83f40c..d349109d2 100644
--- a/src/berry.c
+++ b/src/berry.c
@@ -134,7 +134,7 @@ bool32 IsEnigmaBerryValid(void)
return TRUE;
}
-const struct Berry * sub_809C8A0(u8 berryIdx)
+const struct Berry * GetBerryInfo(u8 berryIdx)
{
if (berryIdx == ITEM_TO_BERRY(ITEM_ENIGMA_BERRY) && IsEnigmaBerryValid())
return (struct Berry *)&gSaveBlock1Ptr->enigmaBerry.berry;
@@ -163,7 +163,7 @@ u16 BerryTypeToItemId(u16 berryType)
void GetBerryNameByBerryType(u8 berryType, u8 * dest)
{
- const struct Berry * berry = sub_809C8A0(berryType);
+ const struct Berry * berry = GetBerryInfo(berryType);
memcpy(dest, berry->name, 6);
dest[6] = EOS;
}
diff --git a/src/dark.c b/src/dark.c
index cb34b991e..b6d13afe3 100644
--- a/src/dark.c
+++ b/src/dark.c
@@ -613,7 +613,7 @@ static void sub_80B82C0(u8 taskId)
{
case 0:
task->data[5] += 8;
- if (task->data[5] >= task->data[7])
+ if (task->data[5] >= task->data[7])
task->data[5] = task->data[7];
sub_80B843C(task);
if (task->data[5] == task->data[7])
diff --git a/src/data/text/abilities.h b/src/data/text/abilities.h
new file mode 100644
index 000000000..c2002bed7
--- /dev/null
+++ b/src/data/text/abilities.h
@@ -0,0 +1,242 @@
+static const u8 sNoneDescription[] = _("No special ability.");
+static const u8 sStenchDescription[] = _("Helps repel wild POKéMON.");
+static const u8 sDrizzleDescription[] = _("Summons rain in battle.");
+static const u8 sSpeedBoostDescription[] = _("Gradually boosts SPEED.");
+static const u8 sBattleArmorDescription[] = _("Blocks critical hits.");
+static const u8 sSturdyDescription[] = _("Negates 1-hit KO attacks.");
+static const u8 sDampDescription[] = _("Prevents self-destruction.");
+static const u8 sLimberDescription[] = _("Prevents paralysis.");
+static const u8 sSandVeilDescription[] = _("Ups evasion in a sandstorm.");
+static const u8 sStaticDescription[] = _("Paralyzes on contact.");
+static const u8 sVoltAbsorbDescription[] = _("Turns electricity into HP.");
+static const u8 sWaterAbsorbDescription[] = _("Changes water into HP.");
+static const u8 sObliviousDescription[] = _("Prevents attraction.");
+static const u8 sCloudNineDescription[] = _("Negates weather effects.");
+static const u8 sCompoundEyesDescription[] = _("Raises accuracy.");
+static const u8 sInsomniaDescription[] = _("Prevents sleep.");
+static const u8 sColorChangeDescription[] = _("Changes type to foe's move.");
+static const u8 sImmunityDescription[] = _("Prevents poisoning.");
+static const u8 sFlashFireDescription[] = _("Powers up if hit by fire.");
+static const u8 sShieldDustDescription[] = _("Prevents added effects.");
+static const u8 sOwnTempoDescription[] = _("Prevents confusion.");
+static const u8 sSuctionCupsDescription[] = _("Firmly anchors the body.");
+static const u8 sIntimidateDescription[] = _("Lowers the foe's ATTACK.");
+static const u8 sShadowTagDescription[] = _("Prevents the foe's escape.");
+static const u8 sRoughSkinDescription[] = _("Hurts to touch.");
+static const u8 sWonderGuardDescription[] = _("“Super effective” hits.");
+static const u8 sLevitateDescription[] = _("Not hit by GROUND attacks.");
+static const u8 sEffectSporeDescription[] = _("Leaves spores on contact.");
+static const u8 sSynchronizeDescription[] = _("Passes on status problems.");
+static const u8 sClearBodyDescription[] = _("Prevents ability reduction.");
+static const u8 sNaturalCureDescription[] = _("Heals upon switching out.");
+static const u8 sLightningRodDescription[] = _("Draws electrical moves.");
+static const u8 sSereneGraceDescription[] = _("Promotes added effects.");
+static const u8 sSwiftSwimDescription[] = _("Raises SPEED in rain.");
+static const u8 sChlorophyllDescription[] = _("Raises SPEED in sunshine.");
+static const u8 sIlluminateDescription[] = _("Encounter rate increases.");
+static const u8 sTraceDescription[] = _("Copies special ability.");
+static const u8 sHugePowerDescription[] = _("Raises ATTACK.");
+static const u8 sPoisonPointDescription[] = _("Poisons foe on contact.");
+static const u8 sInnerFocusDescription[] = _("Prevents flinching.");
+static const u8 sMagmaArmorDescription[] = _("Prevents freezing.");
+static const u8 sWaterVeilDescription[] = _("Prevents burns.");
+static const u8 sMagnetPullDescription[] = _("Traps STEEL-type POKéMON.");
+static const u8 sSoundproofDescription[] = _("Avoids sound-based moves.");
+static const u8 sRainDishDescription[] = _("Slight HP recovery in rain.");
+static const u8 sSandStreamDescription[] = _("Summons a sandstorm.");
+static const u8 sPressureDescription[] = _("Raises foe's PP usage.");
+static const u8 sThickFatDescription[] = _("Heat-and-cold protection.");
+static const u8 sEarlyBirdDescription[] = _("Awakens quickly from sleep.");
+static const u8 sFlameBodyDescription[] = _("Burns the foe on contact.");
+static const u8 sRunAwayDescription[] = _("Makes escaping easier.");
+static const u8 sKeenEyeDescription[] = _("Prevents loss of accuracy.");
+static const u8 sHyperCutterDescription[] = _("Prevents ATTACK reduction.");
+static const u8 sPickupDescription[] = _("May pick up items.");
+static const u8 sTruantDescription[] = _("Moves only every two turns.");
+static const u8 sHustleDescription[] = _("Trades accuracy for power.");
+static const u8 sCuteCharmDescription[] = _("Infatuates on contact.");
+static const u8 sPlusDescription[] = _("Powers up with MINUS.");
+static const u8 sMinusDescription[] = _("Powers up with PLUS.");
+static const u8 sForecastDescription[] = _("Changes with the weather.");
+static const u8 sStickyHoldDescription[] = _("Prevents item theft.");
+static const u8 sShedSkinDescription[] = _("Heals the body by shedding.");
+static const u8 sGutsDescription[] = _("Ups ATTACK if suffering.");
+static const u8 sMarvelScaleDescription[] = _("Ups DEFENSE if suffering.");
+static const u8 sLiquidOozeDescription[] = _("Draining causes injury.");
+static const u8 sOvergrowDescription[] = _("Ups GRASS moves in a pinch.");
+static const u8 sBlazeDescription[] = _("Ups FIRE moves in a pinch.");
+static const u8 sTorrentDescription[] = _("Ups WATER moves in a pinch.");
+static const u8 sSwarmDescription[] = _("Ups BUG moves in a pinch.");
+static const u8 sRockHeadDescription[] = _("Prevents recoil damage.");
+static const u8 sDroughtDescription[] = _("Summons sunlight in battle.");
+static const u8 sArenaTrapDescription[] = _("Prevents fleeing.");
+static const u8 sVitalSpiritDescription[] = _("Prevents sleep.");
+static const u8 sWhiteSmokeDescription[] = _("Prevents ability reduction.");
+static const u8 sPurePowerDescription[] = _("Raises ATTACK.");
+static const u8 sShellArmorDescription[] = _("Blocks critical hits.");
+static const u8 sCacophonyDescription[] = _("Avoids sound-based moves.");
+static const u8 sAirLockDescription[] = _("Negates weather effects.");
+
+const u8 *const gAbilityDescriptionPointers[ABILITIES_COUNT] =
+{
+ [ABILITY_NONE] = sNoneDescription,
+ [ABILITY_STENCH] = sStenchDescription,
+ [ABILITY_DRIZZLE] = sDrizzleDescription,
+ [ABILITY_SPEED_BOOST] = sSpeedBoostDescription,
+ [ABILITY_BATTLE_ARMOR] = sBattleArmorDescription,
+ [ABILITY_STURDY] = sSturdyDescription,
+ [ABILITY_DAMP] = sDampDescription,
+ [ABILITY_LIMBER] = sLimberDescription,
+ [ABILITY_SAND_VEIL] = sSandVeilDescription,
+ [ABILITY_STATIC] = sStaticDescription,
+ [ABILITY_VOLT_ABSORB] = sVoltAbsorbDescription,
+ [ABILITY_WATER_ABSORB] = sWaterAbsorbDescription,
+ [ABILITY_OBLIVIOUS] = sObliviousDescription,
+ [ABILITY_CLOUD_NINE] = sCloudNineDescription,
+ [ABILITY_COMPOUND_EYES] = sCompoundEyesDescription,
+ [ABILITY_INSOMNIA] = sInsomniaDescription,
+ [ABILITY_COLOR_CHANGE] = sColorChangeDescription,
+ [ABILITY_IMMUNITY] = sImmunityDescription,
+ [ABILITY_FLASH_FIRE] = sFlashFireDescription,
+ [ABILITY_SHIELD_DUST] = sShieldDustDescription,
+ [ABILITY_OWN_TEMPO] = sOwnTempoDescription,
+ [ABILITY_SUCTION_CUPS] = sSuctionCupsDescription,
+ [ABILITY_INTIMIDATE] = sIntimidateDescription,
+ [ABILITY_SHADOW_TAG] = sShadowTagDescription,
+ [ABILITY_ROUGH_SKIN] = sRoughSkinDescription,
+ [ABILITY_WONDER_GUARD] = sWonderGuardDescription,
+ [ABILITY_LEVITATE] = sLevitateDescription,
+ [ABILITY_EFFECT_SPORE] = sEffectSporeDescription,
+ [ABILITY_SYNCHRONIZE] = sSynchronizeDescription,
+ [ABILITY_CLEAR_BODY] = sClearBodyDescription,
+ [ABILITY_NATURAL_CURE] = sNaturalCureDescription,
+ [ABILITY_LIGHTNING_ROD] = sLightningRodDescription,
+ [ABILITY_SERENE_GRACE] = sSereneGraceDescription,
+ [ABILITY_SWIFT_SWIM] = sSwiftSwimDescription,
+ [ABILITY_CHLOROPHYLL] = sChlorophyllDescription,
+ [ABILITY_ILLUMINATE] = sIlluminateDescription,
+ [ABILITY_TRACE] = sTraceDescription,
+ [ABILITY_HUGE_POWER] = sHugePowerDescription,
+ [ABILITY_POISON_POINT] = sPoisonPointDescription,
+ [ABILITY_INNER_FOCUS] = sInnerFocusDescription,
+ [ABILITY_MAGMA_ARMOR] = sMagmaArmorDescription,
+ [ABILITY_WATER_VEIL] = sWaterVeilDescription,
+ [ABILITY_MAGNET_PULL] = sMagnetPullDescription,
+ [ABILITY_SOUNDPROOF] = sSoundproofDescription,
+ [ABILITY_RAIN_DISH] = sRainDishDescription,
+ [ABILITY_SAND_STREAM] = sSandStreamDescription,
+ [ABILITY_PRESSURE] = sPressureDescription,
+ [ABILITY_THICK_FAT] = sThickFatDescription,
+ [ABILITY_EARLY_BIRD] = sEarlyBirdDescription,
+ [ABILITY_FLAME_BODY] = sFlameBodyDescription,
+ [ABILITY_RUN_AWAY] = sRunAwayDescription,
+ [ABILITY_KEEN_EYE] = sKeenEyeDescription,
+ [ABILITY_HYPER_CUTTER] = sHyperCutterDescription,
+ [ABILITY_PICKUP] = sPickupDescription,
+ [ABILITY_TRUANT] = sTruantDescription,
+ [ABILITY_HUSTLE] = sHustleDescription,
+ [ABILITY_CUTE_CHARM] = sCuteCharmDescription,
+ [ABILITY_PLUS] = sPlusDescription,
+ [ABILITY_MINUS] = sMinusDescription,
+ [ABILITY_FORECAST] = sForecastDescription,
+ [ABILITY_STICKY_HOLD] = sStickyHoldDescription,
+ [ABILITY_SHED_SKIN] = sShedSkinDescription,
+ [ABILITY_GUTS] = sGutsDescription,
+ [ABILITY_MARVEL_SCALE] = sMarvelScaleDescription,
+ [ABILITY_LIQUID_OOZE] = sLiquidOozeDescription,
+ [ABILITY_OVERGROW] = sOvergrowDescription,
+ [ABILITY_BLAZE] = sBlazeDescription,
+ [ABILITY_TORRENT] = sTorrentDescription,
+ [ABILITY_SWARM] = sSwarmDescription,
+ [ABILITY_ROCK_HEAD] = sRockHeadDescription,
+ [ABILITY_DROUGHT] = sDroughtDescription,
+ [ABILITY_ARENA_TRAP] = sArenaTrapDescription,
+ [ABILITY_VITAL_SPIRIT] = sVitalSpiritDescription,
+ [ABILITY_WHITE_SMOKE] = sWhiteSmokeDescription,
+ [ABILITY_PURE_POWER] = sPurePowerDescription,
+ [ABILITY_SHELL_ARMOR] = sShellArmorDescription,
+ [ABILITY_CACOPHONY] = sCacophonyDescription,
+ [ABILITY_AIR_LOCK] = sAirLockDescription,
+};
+
+const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] =
+{
+ [ABILITY_NONE] = _("-------"),
+ [ABILITY_STENCH] = _("STENCH"),
+ [ABILITY_DRIZZLE] = _("DRIZZLE"),
+ [ABILITY_SPEED_BOOST] = _("SPEED BOOST"),
+ [ABILITY_BATTLE_ARMOR] = _("BATTLE ARMOR"),
+ [ABILITY_STURDY] = _("STURDY"),
+ [ABILITY_DAMP] = _("DAMP"),
+ [ABILITY_LIMBER] = _("LIMBER"),
+ [ABILITY_SAND_VEIL] = _("SAND VEIL"),
+ [ABILITY_STATIC] = _("STATIC"),
+ [ABILITY_VOLT_ABSORB] = _("VOLT ABSORB"),
+ [ABILITY_WATER_ABSORB] = _("WATER ABSORB"),
+ [ABILITY_OBLIVIOUS] = _("OBLIVIOUS"),
+ [ABILITY_CLOUD_NINE] = _("CLOUD NINE"),
+ [ABILITY_COMPOUND_EYES] = _("COMPOUNDEYES"),
+ [ABILITY_INSOMNIA] = _("INSOMNIA"),
+ [ABILITY_COLOR_CHANGE] = _("COLOR CHANGE"),
+ [ABILITY_IMMUNITY] = _("IMMUNITY"),
+ [ABILITY_FLASH_FIRE] = _("FLASH FIRE"),
+ [ABILITY_SHIELD_DUST] = _("SHIELD DUST"),
+ [ABILITY_OWN_TEMPO] = _("OWN TEMPO"),
+ [ABILITY_SUCTION_CUPS] = _("SUCTION CUPS"),
+ [ABILITY_INTIMIDATE] = _("INTIMIDATE"),
+ [ABILITY_SHADOW_TAG] = _("SHADOW TAG"),
+ [ABILITY_ROUGH_SKIN] = _("ROUGH SKIN"),
+ [ABILITY_WONDER_GUARD] = _("WONDER GUARD"),
+ [ABILITY_LEVITATE] = _("LEVITATE"),
+ [ABILITY_EFFECT_SPORE] = _("EFFECT SPORE"),
+ [ABILITY_SYNCHRONIZE] = _("SYNCHRONIZE"),
+ [ABILITY_CLEAR_BODY] = _("CLEAR BODY"),
+ [ABILITY_NATURAL_CURE] = _("NATURAL CURE"),
+ [ABILITY_LIGHTNING_ROD] = _("LIGHTNINGROD"),
+ [ABILITY_SERENE_GRACE] = _("SERENE GRACE"),
+ [ABILITY_SWIFT_SWIM] = _("SWIFT SWIM"),
+ [ABILITY_CHLOROPHYLL] = _("CHLOROPHYLL"),
+ [ABILITY_ILLUMINATE] = _("ILLUMINATE"),
+ [ABILITY_TRACE] = _("TRACE"),
+ [ABILITY_HUGE_POWER] = _("HUGE POWER"),
+ [ABILITY_POISON_POINT] = _("POISON POINT"),
+ [ABILITY_INNER_FOCUS] = _("INNER FOCUS"),
+ [ABILITY_MAGMA_ARMOR] = _("MAGMA ARMOR"),
+ [ABILITY_WATER_VEIL] = _("WATER VEIL"),
+ [ABILITY_MAGNET_PULL] = _("MAGNET PULL"),
+ [ABILITY_SOUNDPROOF] = _("SOUNDPROOF"),
+ [ABILITY_RAIN_DISH] = _("RAIN DISH"),
+ [ABILITY_SAND_STREAM] = _("SAND STREAM"),
+ [ABILITY_PRESSURE] = _("PRESSURE"),
+ [ABILITY_THICK_FAT] = _("THICK FAT"),
+ [ABILITY_EARLY_BIRD] = _("EARLY BIRD"),
+ [ABILITY_FLAME_BODY] = _("FLAME BODY"),
+ [ABILITY_RUN_AWAY] = _("RUN AWAY"),
+ [ABILITY_KEEN_EYE] = _("KEEN EYE"),
+ [ABILITY_HYPER_CUTTER] = _("HYPER CUTTER"),
+ [ABILITY_PICKUP] = _("PICKUP"),
+ [ABILITY_TRUANT] = _("TRUANT"),
+ [ABILITY_HUSTLE] = _("HUSTLE"),
+ [ABILITY_CUTE_CHARM] = _("CUTE CHARM"),
+ [ABILITY_PLUS] = _("PLUS"),
+ [ABILITY_MINUS] = _("MINUS"),
+ [ABILITY_FORECAST] = _("FORECAST"),
+ [ABILITY_STICKY_HOLD] = _("STICKY HOLD"),
+ [ABILITY_SHED_SKIN] = _("SHED SKIN"),
+ [ABILITY_GUTS] = _("GUTS"),
+ [ABILITY_MARVEL_SCALE] = _("MARVEL SCALE"),
+ [ABILITY_LIQUID_OOZE] = _("LIQUID OOZE"),
+ [ABILITY_OVERGROW] = _("OVERGROW"),
+ [ABILITY_BLAZE] = _("BLAZE"),
+ [ABILITY_TORRENT] = _("TORRENT"),
+ [ABILITY_SWARM] = _("SWARM"),
+ [ABILITY_ROCK_HEAD] = _("ROCK HEAD"),
+ [ABILITY_DROUGHT] = _("DROUGHT"),
+ [ABILITY_ARENA_TRAP] = _("ARENA TRAP"),
+ [ABILITY_VITAL_SPIRIT] = _("VITAL SPIRIT"),
+ [ABILITY_WHITE_SMOKE] = _("WHITE SMOKE"),
+ [ABILITY_PURE_POWER] = _("PURE POWER"),
+ [ABILITY_SHELL_ARMOR] = _("SHELL ARMOR"),
+ [ABILITY_CACOPHONY] = _("CACOPHONY"),
+ [ABILITY_AIR_LOCK] = _("AIR LOCK"),
+};
diff --git a/src/fame_checker.c b/src/fame_checker.c
index e803a9700..50a8aa0bc 100644
--- a/src/fame_checker.c
+++ b/src/fame_checker.c
@@ -26,6 +26,7 @@
#include "menu_indicators.h"
#include "text_window.h"
#include "fame_checker.h"
+#include "constants/trainers.h"
#define SPRITETAG_SELECTOR_CURSOR 1000
#define SPRITETAG_QUESTION_MARK 1001
@@ -878,7 +879,7 @@ static void FC_DestroyWindow(u8 windowId)
static u8 AdjustGiovanniIndexIfBeatenInGym(u8 a0)
{
- if (HasTrainerAlreadyBeenFought(0x15e) == TRUE)
+ if (HasTrainerBeenFought(TRAINER_LEADER_GIOVANNI) == TRUE)
{
if (a0 == 9)
return FAMECHECKER_GIOVANNI;
diff --git a/src/field_fadetransition.c b/src/field_fadetransition.c
index de9f09ff0..58caad509 100644
--- a/src/field_fadetransition.c
+++ b/src/field_fadetransition.c
@@ -323,14 +323,14 @@ static void sub_807DFBC(u8 taskId)
{
case 0: // Never reached
sub_807DCB0(0);
- player_bitmagic();
+ FreezeEventObjects();
PlayerGetDestCoords(x, y);
FieldSetDoorOpened(*x, *y);
task->data[0] = 1;
break;
case 5:
sub_807DCB0(0);
- player_bitmagic();
+ FreezeEventObjects();
sub_807F114();
sub_807DBAC();
task->data[0] = 6;
@@ -408,7 +408,7 @@ static void task_map_chg_seq_0807E20C(u8 taskId)
{
case 0:
sub_807DCB0(0);
- player_bitmagic();
+ FreezeEventObjects();
PlayerGetDestCoords(x, y);
task->data[0] = 1;
break;
@@ -439,7 +439,7 @@ static void task_map_chg_seq_0807E2CC(u8 taskId)
switch (gTasks[taskId].data[0])
{
case 0:
- player_bitmagic();
+ FreezeEventObjects();
ScriptContext2_Enable();
gTasks[taskId].data[0]++;
break;
@@ -459,7 +459,7 @@ static void sub_807E31C(u8 taskId)
switch (gTasks[taskId].data[0])
{
case 0:
- player_bitmagic();
+ FreezeEventObjects();
ScriptContext2_Enable();
sub_805DC04();
gTasks[taskId].data[0]++;
@@ -689,7 +689,7 @@ static void sub_807E718(u8 taskId)
switch (task->data[0])
{
case 0:
- player_bitmagic();
+ FreezeEventObjects();
ScriptContext2_Enable();
task->data[0]++;
break;
@@ -711,7 +711,7 @@ static void sub_807E784(u8 taskId)
switch (task->data[0])
{
case 0:
- player_bitmagic();
+ FreezeEventObjects();
ScriptContext2_Enable();
PlaySE(SE_TK_WARPIN);
sub_805DAB0();
@@ -744,7 +744,7 @@ static void sub_807E80C(u8 taskId)
switch (task->data[0])
{
case 0:
- player_bitmagic();
+ FreezeEventObjects();
PlayerGetDestCoords(xp, yp);
PlaySE(GetDoorSoundEffect(*xp, *yp - 1));
task->data[1] = FieldAnimateDoorOpen(*xp, *yp - 1);
@@ -798,7 +798,7 @@ static void sub_807E980(u8 taskId)
{
case 0:
ScriptContext2_Enable();
- player_bitmagic();
+ FreezeEventObjects();
CameraObjectReset2();
data[0]++;
break;
diff --git a/src/fldeff_rocksmash.c b/src/fldeff_rocksmash.c
index 56a607fff..90abda81f 100644
--- a/src/fldeff_rocksmash.c
+++ b/src/fldeff_rocksmash.c
@@ -16,6 +16,7 @@
#include "field_map_obj.h"
#include "constants/songs.h"
#include "constants/map_objects.h"
+#include "constants/map_types.h"
static void task08_080C9820(u8 taskId);
static void sub_80C98FC(u8 taskId);
diff --git a/src/ground.c b/src/ground.c
index 4ae4d8370..97f42e5c5 100644
--- a/src/ground.c
+++ b/src/ground.c
@@ -416,8 +416,7 @@ static void sub_80B91B0(u8 taskId)
task->data[12] = gBattle_BG1_X;
else
task->data[12] = gBattle_BG2_X;
-
- var0 = GetBattlerYCoordWithElevation(gBattleAnimAttacker);
+ var0 = GetBattlerYCoordWithElevation(gBattleAnimAttacker);
task->data[14] = var0 - 32;
task->data[15] = var0 + 32;
++task->data[0];
diff --git a/src/item.c b/src/item.c
index e76cb10d3..677c13ad7 100644
--- a/src/item.c
+++ b/src/item.c
@@ -73,7 +73,7 @@ void CopyItemName(u16 itemId, u8 * dest)
{
if (itemId == ITEM_ENIGMA_BERRY)
{
- StringCopy(dest, sub_809C8A0(43)->name);
+ StringCopy(dest, GetBerryInfo(ITEM_TO_BERRY(ITEM_ENIGMA_BERRY))->name);
StringAppend(dest, gUnknown_84162BD);
}
else
diff --git a/src/item_use.c b/src/item_use.c
index 679a3b8cc..873ce4ab4 100644
--- a/src/item_use.c
+++ b/src/item_use.c
@@ -42,6 +42,7 @@
#include "constants/maps.h"
#include "constants/moves.h"
#include "constants/songs.h"
+#include "constants/map_types.h"
EWRAM_DATA void (*sItemUseOnFieldCB)(u8 taskId) = NULL;
@@ -162,7 +163,7 @@ void sub_80A1184(void)
bool8 sub_80A1194(void)
{
- player_bitmagic();
+ FreezeEventObjects();
ScriptContext2_Enable();
sub_807DC00();
CreateTask(sub_80A11C0, 10);
@@ -259,7 +260,7 @@ bool8 ItemUseCheckFunc_Rod(void)
{
if (MetatileBehavior_IsSurfable(behavior) && !MapGridIsImpassableAt(x, y))
return TRUE;
- if (MetatileBehavior_ReturnFalse_6(behavior) == TRUE)
+ if (MetatileBehavior_IsBridge(behavior) == TRUE)
return TRUE;
}
return FALSE;
diff --git a/src/link.c b/src/link.c
index c8c7932df..ac9cf9cfe 100644
--- a/src/link.c
+++ b/src/link.c
@@ -1025,7 +1025,7 @@ bool8 IsLinkTaskFinished(void)
{
if (gWirelessCommType == 1)
{
- return IsRfuTaskFinished();
+ return IsLinkRfuTaskFinished();
}
return gLinkCallback == NULL;
}
diff --git a/src/map_obj_lock.c b/src/map_obj_lock.c
index f89819647..e28872fd4 100644
--- a/src/map_obj_lock.c
+++ b/src/map_obj_lock.c
@@ -38,7 +38,7 @@ bool8 sub_8069590(void)
void ScriptFreezeMapObjects(void)
{
- player_bitmagic();
+ FreezeEventObjects();
CreateTask(sub_8069570, 80);
}
diff --git a/src/metatile_behavior.c b/src/metatile_behavior.c
index 62a102a09..bca99d38f 100644
--- a/src/metatile_behavior.c
+++ b/src/metatile_behavior.c
@@ -69,7 +69,7 @@ bool8 MetatileBehavior_IsMB21OrSand(u8 metatileBehavior)
return FALSE;
}
-bool8 MetatileBehavior_IsMB21OrWaterfallBottom(u8 metatileBehavior)
+bool8 MetatileBehavior_IsSandOrDeepSand(u8 metatileBehavior)
{
if(metatileBehavior == MB_21 || metatileBehavior == MB_WATERFALL_BOTTOM)
return TRUE;
@@ -428,11 +428,11 @@ bool8 MetatileBehavior_IsTallGrass_2(u8 metatileBehavior)
return FALSE;
}
-bool8 MetatileBehavior_ReturnFalse_3(u8 metatileBehavior) { return FALSE; }
+bool8 MetatileBehavior_IsLongGrass(u8 metatileBehavior) { return FALSE; }
bool8 MetatileBehavior_ReturnFalse_4(u8 metatileBehavior) { return FALSE; }
bool8 MetatileBehavior_ReturnFalse_5(u8 metatileBehavior) { return FALSE; }
-bool8 MetatileBehavior_ReturnFalse_6(u8 metatileBehavior) { return FALSE; }
-bool8 MetatileBehavior_ReturnFalse_7(u8 metatileBehavior) { return FALSE; }
+bool8 MetatileBehavior_IsBridge(u8 metatileBehavior) { return FALSE; }
+bool8 MetatileBehavior_GetBridgeType(u8 metatileBehavior) { return FALSE; }
bool8 MetatileBehavior_UnusedIsMB_01(u8 metatileBehavior)
{
@@ -450,7 +450,7 @@ bool8 MetatileBehavior_UnusedIsTallGrass(u8 metatileBehavior)
return FALSE;
}
-bool8 MetatileBehavior_IsMB0B(u8 metatileBehavior)
+bool8 MetatileBehavior_IsIndoorEncounter(u8 metatileBehavior)
{
if(metatileBehavior == MB_0B)
return TRUE;
@@ -458,7 +458,7 @@ bool8 MetatileBehavior_IsMB0B(u8 metatileBehavior)
return FALSE;
}
-bool8 MetatileBehavior_IsMB0C(u8 metatileBehavior)
+bool8 MetatileBehavior_IsMountain(u8 metatileBehavior)
{
if(metatileBehavior == MB_0C)
return TRUE;
diff --git a/src/mystery_gift_menu.c b/src/mystery_gift_menu.c
index f76d70c04..13a6d37e2 100644
--- a/src/mystery_gift_menu.c
+++ b/src/mystery_gift_menu.c
@@ -1374,7 +1374,7 @@ void task00_mystery_gift(u8 taskId)
}
break;
case 13:
- if (IsRfuTaskFinished())
+ if (IsLinkRfuTaskFinished())
{
DestroyWirelessStatusIndicatorSprite();
data->state = 14;
@@ -1650,7 +1650,7 @@ void task00_mystery_gift(u8 taskId)
data->state = 34;
break;
case 34:
- if (IsRfuTaskFinished())
+ if (IsLinkRfuTaskFinished())
{
DestroyWirelessStatusIndicatorSprite();
data->state = 35;
diff --git a/src/pokemon.c b/src/pokemon.c
index f9fe72007..17f28c7a6 100644
--- a/src/pokemon.c
+++ b/src/pokemon.c
@@ -8,7 +8,7 @@
#include "data.h"
#include "string_util.h"
#include "battle.h"
-#include "battle_main.h"
+#include "battle_anim.h"
#include "item.h"
#include "event_data.h"
#include "util.h"
@@ -1467,7 +1467,7 @@ const struct SpriteTemplate gUnknown_825DEF0[] =
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = 0,
- .oam = &gUnknown_824F018,
+ .oam = &gOamData_824F018,
.anims = NULL,
.images = gUnknown_8234698,
.affineAnims = gSpriteAffineAnimTable_82348C8,
@@ -1476,16 +1476,16 @@ const struct SpriteTemplate gUnknown_825DEF0[] =
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = 0,
- .oam = &gUnknown_824F010,
+ .oam = &gOamData_824F010,
.anims = NULL,
.images = gUnknown_82346B8,
.affineAnims = gSpriteAffineAnimTable_8234944,
- .callback = oac_poke_opponent,
+ .callback = SpriteCB_WildMon,
},
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = 0,
- .oam = &gUnknown_824F018,
+ .oam = &gOamData_824F018,
.anims = NULL,
.images = gUnknown_82346D8,
.affineAnims = gSpriteAffineAnimTable_82348C8,
@@ -1494,11 +1494,11 @@ const struct SpriteTemplate gUnknown_825DEF0[] =
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = 0,
- .oam = &gUnknown_824F010,
+ .oam = &gOamData_824F010,
.anims = NULL,
.images = gUnknown_82346F8,
.affineAnims = gSpriteAffineAnimTable_8234944,
- .callback = oac_poke_opponent,
+ .callback = SpriteCB_WildMon,
},
};
@@ -1507,7 +1507,7 @@ const struct SpriteTemplate gUnknown_825DF50[] =
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = 0,
- .oam = &gUnknown_824F018,
+ .oam = &gOamData_824F018,
.anims = NULL,
.images = gTrainerBackPicTable_Red,
.affineAnims = gSpriteAffineAnimTable_82348C8,
@@ -1516,7 +1516,7 @@ const struct SpriteTemplate gUnknown_825DF50[] =
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = 0,
- .oam = &gUnknown_824F018,
+ .oam = &gOamData_824F018,
.anims = NULL,
.images = gTrainerBackPicTable_Leaf,
.affineAnims = gSpriteAffineAnimTable_82348C8,
@@ -1525,7 +1525,7 @@ const struct SpriteTemplate gUnknown_825DF50[] =
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = 0,
- .oam = &gUnknown_824F018,
+ .oam = &gOamData_824F018,
.anims = NULL,
.images = gTrainerBackPicTable_RSBrendan,
.affineAnims = gSpriteAffineAnimTable_82348C8,
@@ -1534,7 +1534,7 @@ const struct SpriteTemplate gUnknown_825DF50[] =
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = 0,
- .oam = &gUnknown_824F018,
+ .oam = &gOamData_824F018,
.anims = NULL,
.images = gTrainerBackPicTable_RSMay,
.affineAnims = gSpriteAffineAnimTable_82348C8,
@@ -1543,7 +1543,7 @@ const struct SpriteTemplate gUnknown_825DF50[] =
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = 0,
- .oam = &gUnknown_824F018,
+ .oam = &gOamData_824F018,
.anims = NULL,
.images = gTrainerBackPicTable_PokeDude,
.affineAnims = gSpriteAffineAnimTable_82348C8,
@@ -1552,7 +1552,7 @@ const struct SpriteTemplate gUnknown_825DF50[] =
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = 0,
- .oam = &gUnknown_824F018,
+ .oam = &gOamData_824F018,
.anims = NULL,
.images = gTrainerBackPicTable_OldMan,
.affineAnims = gSpriteAffineAnimTable_82348C8,
@@ -4652,8 +4652,7 @@ bool8 PokemonUseItemEffects2(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mo
sp18 = itemEffect[r10];
r10++;
break;
- case 7:\
-
+ case 7:
if (GetMonData(mon, MON_DATA_FRIENDSHIP, NULL) >= 200
&& retVal == FALSE
&& sp18 == 0)
@@ -5406,7 +5405,7 @@ u16 GetMonEVCount(struct Pokemon *mon)
return count;
}
-void sub_8043A68(void)
+void RandomlyGivePartyPokerus(struct Pokemon *party)
{
u8 foo[4]; // huh?
}
@@ -5472,7 +5471,7 @@ static void sub_8043B38(void)
u8 foo[4]; // huh?
}
-void sub_8043B40(void)
+void PartySpreadPokerus(struct Pokemon *party)
{
u8 foo[4]; // huh?
}
diff --git a/src/psychic.c b/src/psychic.c
index 662320a2b..a8108c55a 100644
--- a/src/psychic.c
+++ b/src/psychic.c
@@ -47,7 +47,7 @@ const struct SpriteTemplate gUnknown_83E6DF8 =
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gUnknown_83E6DF4,
- .callback = sub_8075D9C,
+ .callback = AnimSpriteOnMonPos,
};
const struct SpriteTemplate gUnknown_83E6E10 =
@@ -376,7 +376,7 @@ const struct SpriteTemplate gUnknown_83E7148 =
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gUnknown_83E7144,
- .callback = sub_8075D9C,
+ .callback = AnimSpriteOnMonPos,
};
static const union AffineAnimCmd gUnknown_83E7160[] =
diff --git a/src/quest_log.c b/src/quest_log.c
index ffced87ee..e3ff53417 100644
--- a/src/quest_log.c
+++ b/src/quest_log.c
@@ -1513,7 +1513,7 @@ static void sub_8111F8C(u8 taskId)
if (ScriptContext2_IsEnabled() != TRUE)
{
- player_bitmagic();
+ FreezeEventObjects();
sub_805C270();
sub_805C780();
ScriptContext2_Enable();
@@ -1536,7 +1536,7 @@ static void sub_8111FCC(u8 taskId)
task->data[0] = 0;
task->data[1] = 0;
task->func = sub_8112044;
- player_bitmagic();
+ FreezeEventObjects();
ScriptContext2_Enable();
}
}
diff --git a/src/quest_log_8150454.c b/src/quest_log_8150454.c
index 3d61dee72..fbd3b4487 100644
--- a/src/quest_log_8150454.c
+++ b/src/quest_log_8150454.c
@@ -88,7 +88,7 @@ void sub_8150530(void)
else
{
sub_81507BC(mapObject, sub_805C808(4));
- StartSpriteAnim(sprite, sub_80634F0(mapObject->mapobj_unk_18));
+ StartSpriteAnim(sprite, sub_80634F0(mapObject->facingDirection));
}
}
@@ -103,7 +103,7 @@ void sub_81505C4(u8 taskId)
FieldObjectClearAnimIfSpecialAnimActive(mapObject);
mapObject->mapobj_bit_11 = TRUE;
sub_81507BC(mapObject, sub_805C808(4));
- StartSpriteAnim(sprite, sub_80634F0(mapObject->mapobj_unk_18));
+ StartSpriteAnim(sprite, sub_80634F0(mapObject->facingDirection));
gTasks[taskId].data[0]++;
gTasks[taskId].data[1] = 0;
break;
diff --git a/src/quest_log_battle.c b/src/quest_log_battle.c
index 2687e4ea5..efe866dea 100644
--- a/src/quest_log_battle.c
+++ b/src/quest_log_battle.c
@@ -2,6 +2,7 @@
#include "constants/species.h"
#include "malloc.h"
#include "battle.h"
+#include "battle_anim.h"
#include "link.h"
#include "overworld.h"
#include "quest_log.h"
@@ -22,11 +23,11 @@ struct QuestLogStruct_WildBattleRecord
u8 v4;
};
-void sub_812C334(s32 *, s32 *);
+static void sub_812C334(s32 *, s32 *);
void sub_812BFDC(void)
{
- if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_OLDMAN_TUTORIAL | BATTLE_TYPE_POKEDUDE)) && (gBattleOutcome == B_OUTCOME_WON || gBattleOutcome == B_OUTCOME_CAUGHT))
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_OLD_MAN_TUTORIAL | BATTLE_TYPE_POKEDUDE)) && (gBattleOutcome == B_OUTCOME_WON || gBattleOutcome == B_OUTCOME_CAUGHT))
{
struct QuestLogStruct_TrainerBattleRecord * questLogTrainerBattleRecord = Alloc(sizeof(struct QuestLogStruct_TrainerBattleRecord));
struct QuestLogStruct_WildBattleRecord * questLogWildBattleRecord = Alloc(sizeof(struct QuestLogStruct_WildBattleRecord));
@@ -38,18 +39,18 @@ void sub_812BFDC(void)
{
switch (gTrainers[gTrainerBattleOpponent_A].trainerClass)
{
- case 0x54:
- questLogMessageType = 30;
- break;
- case 0x5a:
- questLogMessageType = 33;
- break;
- case 0x57:
- questLogMessageType = 32;
- break;
- default:
- questLogMessageType = 34;
- break;
+ case 0x54:
+ questLogMessageType = 30;
+ break;
+ case 0x5a:
+ questLogMessageType = 33;
+ break;
+ case 0x57:
+ questLogMessageType = 32;
+ break;
+ default:
+ questLogMessageType = 34;
+ break;
}
questLogTrainerBattleRecord->v0 = gTrainerBattleOpponent_A;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
@@ -141,7 +142,7 @@ void sub_812C224(void)
}
for (r3 = 0; r3 < 7; r3++)
{
- r5->v1[0][r3] = gLinkPlayers[gBattleStruct->field_B5 ^ 1].name[r3];
+ r5->v1[0][r3] = gLinkPlayers[gBattleStruct->multiplayerId ^ 1].name[r3];
}
}
sub_8113550(r8, (const u16 *)r5);
@@ -149,16 +150,16 @@ void sub_812C224(void)
}
}
-void sub_812C334(s32 * a0, s32 * a1)
+static void sub_812C334(s32 * a0, s32 * a1)
{
s32 r5;
s32 _optimized_out = 0;
- u8 r2 = gLinkPlayers[gBattleStruct->field_B5].id ^ 2;
+ u8 r2 = gLinkPlayers[gBattleStruct->multiplayerId].id ^ 2;
for (r5 = 0; r5 < 4; r5++)
{
if (r2 == gLinkPlayers[r5].id)
a0[0] = r5;
- else if (r5 != gBattleStruct->field_B5)
+ else if (r5 != gBattleStruct->multiplayerId)
a1[_optimized_out++] = r5;
}
}
diff --git a/src/reshow_battle_screen.c b/src/reshow_battle_screen.c
index 6dd743176..5ab38e461 100644
--- a/src/reshow_battle_screen.c
+++ b/src/reshow_battle_screen.c
@@ -211,7 +211,7 @@ static bool8 LoadBattlerSpriteGfx(u8 battler)
}
else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI && battler == B_POSITION_PLAYER_LEFT) // Should be checking position, not battler.
DecompressTrainerBackPalette(gSaveBlock2Ptr->playerGender, battler);
- else if (gBattleTypeFlags & BATTLE_TYPE_OLDMAN_TUTORIAL && battler == B_POSITION_PLAYER_LEFT) // Should be checking position, not battler.
+ else if (gBattleTypeFlags & BATTLE_TYPE_OLD_MAN_TUTORIAL && battler == B_POSITION_PLAYER_LEFT) // Should be checking position, not battler.
DecompressTrainerBackPalette(5, battler);
else if (!gBattleSpritesDataPtr->battlerData[battler].behindSubstitute)
BattleLoadPlayerMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battler]], battler);
@@ -256,7 +256,7 @@ static void CreateBattlerSprite(u8 battler)
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCallbackDummy;
gSprites[gBattlerSpriteIds[battler]].data[0] = battler;
}
- else if (gBattleTypeFlags & BATTLE_TYPE_OLDMAN_TUTORIAL && battler == B_POSITION_PLAYER_LEFT)
+ else if (gBattleTypeFlags & BATTLE_TYPE_OLD_MAN_TUTORIAL && battler == B_POSITION_PLAYER_LEFT)
{
SetMultiuseSpriteTemplateToTrainerBack(5, GetBattlerPosition(0));
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate, 0x50,
@@ -292,7 +292,7 @@ static void CreateHealthboxSprite(u8 battler)
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI && battler == B_POSITION_PLAYER_LEFT)
healthboxSpriteId = CreateSafariPlayerHealthboxSprites();
- else if (gBattleTypeFlags & BATTLE_TYPE_OLDMAN_TUTORIAL && battler == B_POSITION_PLAYER_LEFT)
+ else if (gBattleTypeFlags & BATTLE_TYPE_OLD_MAN_TUTORIAL && battler == B_POSITION_PLAYER_LEFT)
return;
else
healthboxSpriteId = CreateBattlerHealthboxSprites(battler);
diff --git a/src/scrcmd.c b/src/scrcmd.c
index 7a70d09c7..b59f97420 100644
--- a/src/scrcmd.c
+++ b/src/scrcmd.c
@@ -1916,7 +1916,7 @@ bool8 ScrCmd_checktrainerflag(struct ScriptContext *ctx)
{
u16 index = VarGet(ScriptReadHalfword(ctx));
- ctx->comparisonResult = HasTrainerAlreadyBeenFought(index);
+ ctx->comparisonResult = HasTrainerBeenFought(index);
return FALSE;
}
diff --git a/src/start_menu.c b/src/start_menu.c
index 221ae1f1f..dddb5f44e 100644
--- a/src/start_menu.c
+++ b/src/start_menu.c
@@ -392,7 +392,7 @@ void ShowStartMenu(void)
{
if (!IsUpdateLinkStateCBActive())
{
- player_bitmagic();
+ FreezeEventObjects();
sub_805C270();
sub_805C780();
}
diff --git a/src/teachy_tv.c b/src/teachy_tv.c
index c1d6dc6c8..e33cb9d2e 100644
--- a/src/teachy_tv.c
+++ b/src/teachy_tv.c
@@ -1214,7 +1214,7 @@ static void TeachyTvPreBattleAnimAndSetBattleCallback(u8 taskId)
case 1:
if (BT_IsDone())
{
- SetMainCallback2(sub_800FD9C);
+ SetMainCallback2(CB2_InitBattle);
DestroyTask(taskId);
}
break;
diff --git a/src/trainer_tower.c b/src/trainer_tower.c
index 5acac299f..cd796bf3a 100644
--- a/src/trainer_tower.c
+++ b/src/trainer_tower.c
@@ -940,7 +940,7 @@ static void sub_815E124(u8 taskId)
{
gMain.savedCallback = sub_815E114;
CleanupOverworldWindowsAndTilemaps();
- SetMainCallback2(sub_800FD9C);
+ SetMainCallback2(CB2_InitBattle);
DestroyTask(taskId);
}
}
diff --git a/src/unk_8159F40.c b/src/unk_8159F40.c
index f2cb1764f..ef21d19d0 100644
--- a/src/unk_8159F40.c
+++ b/src/unk_8159F40.c
@@ -177,7 +177,7 @@ void sub_815A008(struct QuestLog * questLog)
questLog->unk_008[i].mapobj_bit_24 = gMapObjects[i].mapobj_bit_24;
questLog->unk_008[i].mapobj_bit_25 = gMapObjects[i].mapobj_bit_25;
questLog->unk_008[i].mapobj_bit_26 = gMapObjects[i].mapobj_bit_26;
- questLog->unk_008[i].mapobj_unk_18 = gMapObjects[i].mapobj_unk_18;
+ questLog->unk_008[i].mapobj_unk_18 = gMapObjects[i].facingDirection;
questLog->unk_008[i].mapobj_unk_0B_0 = gMapObjects[i].mapobj_unk_0B_0;
questLog->unk_008[i].elevation = gMapObjects[i].elevation;
questLog->unk_008[i].graphicsId = gMapObjects[i].graphicsId;
@@ -222,7 +222,7 @@ void sub_815A1F8(const struct QuestLog * questLog, const struct MapObjectTemplat
gMapObjects[i].mapobj_bit_24 = questLogMapObjects[i].mapobj_bit_24;
gMapObjects[i].mapobj_bit_25 = questLogMapObjects[i].mapobj_bit_25;
gMapObjects[i].mapobj_bit_26 = questLogMapObjects[i].mapobj_bit_26;
- gMapObjects[i].mapobj_unk_18 = questLogMapObjects[i].mapobj_unk_18;
+ gMapObjects[i].facingDirection = questLogMapObjects[i].mapobj_unk_18;
gMapObjects[i].mapobj_unk_0B_0 = questLogMapObjects[i].mapobj_unk_0B_0;
gMapObjects[i].elevation = questLogMapObjects[i].elevation;
gMapObjects[i].graphicsId = questLogMapObjects[i].graphicsId;
diff --git a/src/vs_seeker.c b/src/vs_seeker.c
index 6ae92236f..9a8ff5dd6 100644
--- a/src/vs_seeker.c
+++ b/src/vs_seeker.c
@@ -628,7 +628,7 @@ void sub_810C444(void)
mapObject = &gMapObjects[sp0];
if (sub_810CF04(sp0) == TRUE)
{
- npc_set_running_behaviour_etc(mapObject, r6);
+ SetTrainerMovementType(mapObject, r6);
}
templates[i].movementType = r6;
}
@@ -766,7 +766,7 @@ static void sub_810C594(void)
{
gSprites[mapObject->spriteId].pos2.x = 0;
gSprites[mapObject->spriteId].pos2.y = 0;
- npc_set_running_behaviour_etc(mapObject, r3);
+ SetTrainerMovementType(mapObject, r3);
}
}
}
@@ -931,7 +931,7 @@ static u8 GetVsSeekerResponseInArea(const VsSeekerData * a0)
if (IsTrainerVisibleOnScreen(&sVsSeeker->trainerInfo[vsSeekerIdx]) == 1)
{
r8 = sVsSeeker->trainerInfo[vsSeekerIdx].trainerIdx;
- if (!HasTrainerAlreadyBeenFought(r8))
+ if (!HasTrainerBeenFought(r8))
{
StartTrainerObjectMovementScript(&sVsSeeker->trainerInfo[vsSeekerIdx], gUnknown_8453F60);
sVsSeeker->trainerHasNotYetBeenFought = 1;
@@ -1027,7 +1027,7 @@ static u8 GetVsSeekerResponseInArea(const VsSeekerData * a0)
"\tadds r0, r5\n"
"\tldrh r0, [r0, 0x4]\n"
"\tmov r8, r0\n"
- "\tbl HasTrainerAlreadyBeenFought\n"
+ "\tbl HasTrainerBeenFought\n"
"\tlsls r0, 24\n"
"\tcmp r0, 0\n"
"\tbne _0810CA20\n"
@@ -1239,10 +1239,10 @@ void sub_810CB90(void)
TryGetFieldObjectIdByLocalIdAndMap(r4[r8].localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &sp0);
r4_2 = &gMapObjects[sp0];
sub_810CF54(&r4[r8]); // You are using this function incorrectly. Please consult the manual.
- sub_805FE7C(r4_2, gUnknown_8453F67[r4_2->mapobj_unk_18]);
+ sub_805FE7C(r4_2, gUnknown_8453F67[r4_2->facingDirection]);
gSaveBlock1Ptr->trainerRematches[r4[r8].localId] = 0;
if (gSelectedEventObject == sp0)
- r4_2->animPattern = gUnknown_8453F67[r4_2->mapobj_unk_18];
+ r4_2->animPattern = gUnknown_8453F67[r4_2->facingDirection];
else
r4_2->animPattern = 0x08;
}
@@ -1319,7 +1319,7 @@ static bool8 HasRematchTrainerAlreadyBeenFought(const VsSeekerData *vsSeekerData
if (rematchIdx == -1)
return FALSE;
- if (!HasTrainerAlreadyBeenFought(vsSeekerData[rematchIdx].trainerIdxs[0]))
+ if (!HasTrainerBeenFought(vsSeekerData[rematchIdx].trainerIdxs[0]))
return FALSE;
return TRUE;
}
@@ -1327,7 +1327,7 @@ static bool8 HasRematchTrainerAlreadyBeenFought(const VsSeekerData *vsSeekerData
void sub_810CDE8(void)
{
gSaveBlock1Ptr->trainerRematches[gSpecialVar_LastTalked] = 0;
- sub_80803FC();
+ SetBattledTrainerFlag();
}
static s32 sub_810CE10(const VsSeekerData * a0, u16 a1)
@@ -1353,7 +1353,7 @@ static s32 sub_810CE10(const VsSeekerData * a0, u16 a1)
return -1;
}
-s32 sub_810CE64(u16 a0)
+s32 GetRematchTrainerId(u16 a0)
{
u8 i;
u8 j;
@@ -1529,7 +1529,7 @@ static u8 GetNextAvailableRematchTrainer(const VsSeekerData * vsSeekerData, u16
return j - 1;
if (vsSeekerData[i].trainerIdxs[j] == 0xffff)
continue;
- if (HasTrainerAlreadyBeenFought(vsSeekerData[i].trainerIdxs[j]))
+ if (HasTrainerBeenFought(vsSeekerData[i].trainerIdxs[j]))
continue;
return j;
}
@@ -1550,7 +1550,7 @@ static u8 GetRematchableTrainerLocalId(void)
{
if (IsTrainerVisibleOnScreen(&sVsSeeker->trainerInfo[i]) == 1)
{
- if (HasTrainerAlreadyBeenFought(sVsSeeker->trainerInfo[i].trainerIdx) != 1 || GetNextAvailableRematchTrainer(sVsSeekerData, sVsSeeker->trainerInfo[i].trainerIdx, &idx))
+ if (HasTrainerBeenFought(sVsSeeker->trainerInfo[i].trainerIdx) != 1 || GetNextAvailableRematchTrainer(sVsSeekerData, sVsSeeker->trainerInfo[i].trainerIdx, &idx))
return sVsSeeker->trainerInfo[i].localId;
}
}
@@ -1599,7 +1599,7 @@ static void StartAllRespondantIdleMovements(void)
struct MapObject *r4 = &gMapObjects[sVsSeeker->trainerInfo[j].fieldObjectId];
if (sub_810CF04(sVsSeeker->trainerInfo[j].fieldObjectId) == 1)
- npc_set_running_behaviour_etc(r4, sVsSeeker->runningBehaviourEtcArray[i]);
+ SetTrainerMovementType(r4, sVsSeeker->runningBehaviourEtcArray[i]);
sub_805FE7C(r4, sVsSeeker->runningBehaviourEtcArray[i]);
gSaveBlock1Ptr->trainerRematches[sVsSeeker->trainerInfo[j].localId] = GetNextAvailableRematchTrainer(sVsSeekerData, sVsSeeker->trainerInfo[j].trainerIdx, &dummy);
}