summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/battle_1.c17
-rw-r--r--src/battle_3.c6408
-rw-r--r--src/battle_4.c601
-rw-r--r--src/battle_ai_script_commands.c (renamed from src/battle_ai.c)13
-rw-r--r--src/battle_dome_cards.c430
-rw-r--r--src/battle_script_commands.c11415
-rw-r--r--src/berry.c55
-rw-r--r--src/berry_blender.c18
-rw-r--r--src/berry_fix_program.c530
-rw-r--r--src/bg.c501
-rw-r--r--src/calculate_base_damage.c1
-rw-r--r--src/coins.c3
-rw-r--r--src/dma3_manager.c52
-rw-r--r--src/egg_hatch.c893
-rw-r--r--src/field_camera.c28
-rw-r--r--src/field_effect.c15
-rwxr-xr-xsrc/field_map_obj.c5118
-rw-r--r--src/field_screen.c15
-rwxr-xr-xsrc/field_special_scene.c363
-rw-r--r--src/fldeff_cut.c19
-rw-r--r--src/gpu_regs.c25
-rw-r--r--src/hall_of_fame.c4
-rw-r--r--src/item.c12
-rw-r--r--src/lilycove_lady.c1101
-rw-r--r--src/link.c56
-rw-r--r--src/load_save.c4
-rw-r--r--src/main.c2
-rw-r--r--src/main_menu.c15
-rw-r--r--src/malloc.c6
-rw-r--r--src/metatile_behavior.c1436
-rw-r--r--src/money.c145
-rw-r--r--src/multiboot.c2
-rw-r--r--src/new_game.c6
-rw-r--r--src/palette.c75
-rw-r--r--src/pokemon_2.c32
-rw-r--r--src/pokemon_3.c48
-rw-r--r--src/pokemon_size_record.c8
-rw-r--r--src/pokemon_storage_system.c15
-rw-r--r--src/record_mixing.c28
-rw-r--r--src/reset_save_heap.c32
-rw-r--r--src/roamer.c218
-rw-r--r--src/rom4.c19
-rw-r--r--src/safari_zone.c4
-rw-r--r--src/save.c162
-rw-r--r--src/scrcmd.c15
-rw-r--r--src/script_menu.c16
-rw-r--r--src/start_menu.c8
-rw-r--r--src/text.c23
-rw-r--r--src/tileset_anims.c1411
-rw-r--r--src/trig.c6
-rw-r--r--src/unk_text_util_2.c219
-rw-r--r--src/window.c4
52 files changed, 30529 insertions, 1123 deletions
diff --git a/src/battle_1.c b/src/battle_1.c
new file mode 100644
index 000000000..5e4ef5583
--- /dev/null
+++ b/src/battle_1.c
@@ -0,0 +1,17 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u32 gUnknown_03000DD4;
+IWRAM_DATA u32 gUnknown_03000DD8;
+IWRAM_DATA u32 gUnknown_03000DDC;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/battle_3.c b/src/battle_3.c
new file mode 100644
index 000000000..e42d9317d
--- /dev/null
+++ b/src/battle_3.c
@@ -0,0 +1,6408 @@
+#include "global.h"
+#include "battle.h"
+#include "abilities.h"
+#include "moves.h"
+#include "hold_effects.h"
+#include "pokemon.h"
+#include "species.h"
+#include "item.h"
+#include "items.h"
+#include "util.h"
+#include "battle_move_effects.h"
+#include "rng.h"
+#include "text.h"
+#include "string_util.h"
+#include "battle_message.h"
+#include "battle_ai_script_commands.h"
+#include "battle_controllers.h"
+#include "event_data.h"
+#include "calculate_base_damage.h"
+
+extern const u8* gBattlescriptCurrInstr;
+extern const u8* gUnknown_02024220[BATTLE_BANKS_COUNT];
+extern const u8* gUnknown_02024230[BATTLE_BANKS_COUNT];
+extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT];
+extern u8 gActiveBank;
+extern u8 gStringBank;
+extern u16 gCurrentMove;
+extern u16 gLastUsedItem;
+extern u8 gNoOfAllBanks;
+extern u32 gStatuses3[BATTLE_BANKS_COUNT];
+extern u8 gBankAttacker;
+extern u8 gBankTarget;
+extern u8 gAbsentBankFlags;
+extern u16 gBattleWeather;
+extern u8 gTurnOrder[BATTLE_BANKS_COUNT];
+extern u16 gSideAffecting[];
+extern u8 gBattleCommunication[];
+extern void (*gBattleMainFunc)(void);
+extern s32 gBattleMoveDamage;
+extern struct BattleEnigmaBerry gEnigmaBerries[BATTLE_BANKS_COUNT];
+extern u8 gBattleBufferB[BATTLE_BANKS_COUNT][0x200];
+extern u32 gBattleTypeFlags;
+extern u16 gLastUsedMovesByBanks[BATTLE_BANKS_COUNT];
+extern u32 gHitMarker;
+extern u8 gEffectBank;
+extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
+extern u8 gBank1;
+extern u16 gChosenMovesByBanks[];
+extern u8 gBattleMoveFlags;
+extern s32 gTakenDmg[BATTLE_BANKS_COUNT];
+extern u8 gTakenDmgBanks[BATTLE_BANKS_COUNT];
+extern u8 gLastUsedAbility;
+extern u8 gFightStateTracker;
+extern u32 gBattleExecBuffer;
+extern u16 gRandomMove;
+extern u8 gCurrMovePos;
+extern u8 gUnknown_020241E9;
+
+extern const struct BattleMove gBattleMoves[];
+
+// scripts
+extern const u8 gUnknown_082DAE2A[];
+extern const u8 gUnknown_082DAE1F[];
+extern const u8 gUnknown_082DB089[];
+extern const u8 gUnknown_082DB098[];
+extern const u8 gUnknown_082DB0AF[];
+extern const u8 gUnknown_082DB0A0[];
+extern const u8 gUnknown_082DB185[];
+extern const u8 gUnknown_082DB181[];
+extern const u8 gUnknown_082DB812[];
+extern const u8 gUnknown_082DB076[];
+extern const u8 BattleScript_NoMovesLeft[];
+extern const u8 gUnknown_082DACFA[];
+extern const u8 gUnknown_082DAD0B[];
+extern const u8 gUnknown_082DACC9[];
+extern const u8 gUnknown_082DAC47[];
+extern const u8 gUnknown_082DACE0[];
+extern const u8 gUnknown_082DACD2[];
+extern const u8 BattleScript_WishComesTrue[];
+extern const u8 gUnknown_082DACC9[];
+extern const u8 gUnknown_082DAC2C[];
+extern const u8 BattleScript_IngrainTurnHeal[];
+extern const u8 BattleScript_LeechSeedTurnDrain[];
+extern const u8 BattleScript_PoisonTurnDmg[];
+extern const u8 BattleScript_BurnTurnDmg[];
+extern const u8 BattleScript_NightmareTurnDmg[];
+extern const u8 BattleScript_CurseTurnDmg[];
+extern const u8 BattleScript_WrapTurnDmg[];
+extern const u8 BattleScript_WrapEnds[];
+extern const u8 gUnknown_082DB234[];
+extern const u8 gUnknown_082DB2A6[];
+extern const u8 BattleScript_ThrashConfuses[];
+extern const u8 BattleScript_DisabledNoMore[];
+extern const u8 BattleScript_EncoredNoMore[];
+extern const u8 BattleScript_YawnMakesAsleep[];
+extern const u8 gUnknown_082DAFE4[];
+extern const u8 gUnknown_082DB8F3[];
+extern const u8 gUnknown_082DAF05[];
+extern const u8 gUnknown_082DAF20[];
+extern const u8 gUnknown_082DA7C4[];
+extern const u8 gUnknown_082DA7CD[];
+extern const u8 BattleScript_MoveUsedWokeUp[];
+extern const u8 BattleScript_MoveUsedIsAsleep[];
+extern const u8 BattleScript_MoveUsedIsFrozen[];
+extern const u8 BattleScript_MoveUsedUnfroze[];
+extern const u8 BattleScript_MoveUsedLoafingAround[];
+extern const u8 BattleScript_MoveUsedMustRecharge[];
+extern const u8 BattleScript_MoveUsedFlinched[];
+extern const u8 BattleScript_MoveUsedIsDisabled[];
+extern const u8 BattleScript_MoveUsedIsTaunted[];
+extern const u8 BattleScript_MoveUsedIsImprisoned[];
+extern const u8 BattleScript_MoveUsedIsConfused[];
+extern const u8 BattleScript_MoveUsedIsConfusedNoMore[];
+extern const u8 BattleScript_MoveUsedIsParalyzed[];
+extern const u8 BattleScript_MoveUsedIsParalyzedCantAttack[];
+extern const u8 BattleScript_MoveUsedIsInLove[];
+extern const u8 BattleScript_BideStoringEnergy[];
+extern const u8 BattleScript_BideAttack[];
+extern const u8 BattleScript_BideNoEnergyToAttack[];
+extern const u8 gUnknown_082DACE7[];
+extern const u8 BattleScript_DrizzleActivates[];
+extern const u8 BattleScript_SandstreamActivates[];
+extern const u8 BattleScript_DroughtActivates[];
+extern const u8 BattleScript_CastformChange[];
+extern const u8 BattleScript_RainDishActivates[];
+extern const u8 BattleScript_ShedSkinActivates[];
+extern const u8 BattleScript_SpeedBoostActivates[];
+extern const u8 BattleScript_SoundproofProtected[];
+extern const u8 BattleScript_MoveHPDrain[];
+extern const u8 BattleScript_MoveHPDrain_PPLoss[];
+extern const u8 BattleScript_FlashFireBoost[];
+extern const u8 BattleScript_FlashFireBoost_PPLoss[];
+extern const u8 BattleScript_ColorChangeActivates[];
+extern const u8 BattleScript_RoughSkinActivates[];
+extern const u8 BattleScript_ApplySecondaryEffect[];
+extern const u8 BattleScript_CuteCharmActivates[];
+extern const u8 gUnknown_082DB68C[];
+extern const u8 BattleScript_SynchronizeActivates[];
+extern const u8 gUnknown_082DB4B8[];
+extern const u8 gUnknown_082DB4C1[];
+extern const u8 BattleScript_TraceActivates[];
+
+extern const u8 BattleScript_WhiteHerbEnd2[];
+extern const u8 BattleScript_WhiteHerbRet[];
+extern const u8 BattleScript_ItemHealHP_RemoveItem[];
+extern const u8 BattleScript_BerryPPHealEnd2[];
+extern const u8 BattleScript_ItemHealHP_End2[];
+extern const u8 BattleScript_BerryConfuseHealEnd2[];
+extern const u8 BattleScript_BerryStatRaiseEnd2[];
+extern const u8 BattleScript_BerryFocusEnergyEnd2[];
+extern const u8 BattleScript_BerryCurePrlzEnd2[];
+extern const u8 BattleScript_BerryCurePsnEnd2[];
+extern const u8 BattleScript_BerryCureBrnEnd2[];
+extern const u8 BattleScript_BerryCureFrzEnd2[];
+extern const u8 BattleScript_BerryCureSlpEnd2[];
+extern const u8 BattleScript_BerryCureConfusionEnd2[];
+extern const u8 BattleScript_BerryCureChosenStatusEnd2[];
+extern const u8 BattleScript_BerryCureParRet[];
+extern const u8 BattleScript_BerryCurePsnRet[];
+extern const u8 BattleScript_BerryCureBrnRet[];
+extern const u8 BattleScript_BerryCureFrzRet[];
+extern const u8 BattleScript_BerryCureSlpRet[];
+extern const u8 BattleScript_BerryCureConfusionRet[];
+extern const u8 BattleScript_BerryCureChosenStatusRet[];
+extern const u8 BattleScript_ItemHealHP_Ret[];
+
+extern const u8 gUnknown_082DB695[]; //disobedient while asleep
+extern const u8 gUnknown_082DB6A5[]; //disobedient, uses a random move
+extern const u8 gUnknown_082DB6D9[]; //disobedient, went to sleep
+extern const u8 gUnknown_082DB6F0[]; //disobedient, hits itself
+
+extern const u8 gStatusConditionString_PoisonJpn[];
+extern const u8 gStatusConditionString_SleepJpn[];
+extern const u8 gStatusConditionString_ParalysisJpn[];
+extern const u8 gStatusConditionString_BurnJpn[];
+extern const u8 gStatusConditionString_IceJpn[];
+extern const u8 gStatusConditionString_ConfusionJpn[];
+extern const u8 gStatusConditionString_LoveJpn[];
+extern const u16 gSoundMovesTable[];
+
+extern u8 b_first_side(u8, u8, u8);
+extern void sub_803CEDC(u8, u8);
+extern void BattleTurnPassed(void);
+extern void sub_803F9EC();
+extern bool8 sub_80423F4(u8 bank, u8, u8);
+extern u8 weather_get_current(void);
+extern void sub_803E08C(void);
+extern void bc_move_exec_returning(void);
+extern s8 GetFlavourRelationByPersonality(u32 personality, u8 flavor);
+
+void BattleScriptPush(const u8* bsPtr)
+{
+ BATTLESCRIPTS_STACK->ptr[BATTLESCRIPTS_STACK->size++] = bsPtr;
+}
+
+void BattleScriptPushCursor(void)
+{
+ BATTLESCRIPTS_STACK->ptr[BATTLESCRIPTS_STACK->size++] = gBattlescriptCurrInstr;
+}
+
+void BattleScriptPop(void)
+{
+ gBattlescriptCurrInstr = BATTLESCRIPTS_STACK->ptr[--BATTLESCRIPTS_STACK->size];
+}
+
+u8 sub_803FB4C(void) // msg, can't select a move
+{
+ u8 limitations = 0;
+ u16 move = gBattleMons[gActiveBank].moves[gBattleBufferB[gActiveBank][2]];
+ u8 holdEffect;
+ u16* choicedMove = &gBattleStruct->choicedMove[gActiveBank];
+
+ if (gDisableStructs[gActiveBank].disabledMove == move && move != 0)
+ {
+ gBattleScripting.bank = gActiveBank;
+ gCurrentMove = move;
+ if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
+ {
+ gUnknown_02024230[gActiveBank] = gUnknown_082DAE2A;
+ gProtectStructs[gActiveBank].flag_x10 = 1;
+ }
+ else
+ {
+ gUnknown_02024220[gActiveBank] = gUnknown_082DAE1F;
+ limitations = 1;
+ }
+ }
+
+ if (move == gLastUsedMovesByBanks[gActiveBank] && move != MOVE_STRUGGLE && (gBattleMons[gActiveBank].status2 & STATUS2_TORMENT))
+ {
+ CancelMultiTurnMoves(gActiveBank);
+ if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
+ {
+ gUnknown_02024230[gActiveBank] = gUnknown_082DB098;
+ gProtectStructs[gActiveBank].flag_x10 = 1;
+ }
+ else
+ {
+ gUnknown_02024220[gActiveBank] = gUnknown_082DB089;
+ limitations++;
+ }
+ }
+
+ if (gDisableStructs[gActiveBank].tauntTimer1 != 0 && gBattleMoves[move].power == 0)
+ {
+ gCurrentMove = move;
+ if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
+ {
+ gUnknown_02024230[gActiveBank] = gUnknown_082DB0AF;
+ gProtectStructs[gActiveBank].flag_x10 = 1;
+ }
+ else
+ {
+ gUnknown_02024220[gActiveBank] = gUnknown_082DB0A0;
+ limitations++;
+ }
+ }
+
+ if (GetImprisonedMovesCount(gActiveBank, move))
+ {
+ gCurrentMove = move;
+ if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
+ {
+ gUnknown_02024230[gActiveBank] = gUnknown_082DB185;
+ gProtectStructs[gActiveBank].flag_x10 = 1;
+ }
+ else
+ {
+ gUnknown_02024220[gActiveBank] = gUnknown_082DB181;
+ limitations++;
+ }
+ }
+
+ if (gBattleMons[gActiveBank].item == ITEM_ENIGMA_BERRY)
+ holdEffect = gEnigmaBerries[gActiveBank].holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gActiveBank].item);
+
+ gStringBank = gActiveBank;
+
+ if (holdEffect == HOLD_EFFECT_CHOICE_BAND && *choicedMove != 0 && *choicedMove != 0xFFFF && *choicedMove != move)
+ {
+ gCurrentMove = *choicedMove;
+ gLastUsedItem = gBattleMons[gActiveBank].item;
+ if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
+ {
+ gProtectStructs[gActiveBank].flag_x10 = 1;
+ }
+ else
+ {
+ gUnknown_02024220[gActiveBank] = gUnknown_082DB812;
+ limitations++;
+ }
+ }
+
+ if (gBattleMons[gActiveBank].pp[gBattleBufferB[gActiveBank][2]] == 0)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
+ {
+ gProtectStructs[gActiveBank].flag_x10 = 1;
+ }
+ else
+ {
+ gUnknown_02024220[gActiveBank] = gUnknown_082DB076;
+ limitations++;
+ }
+ }
+
+ return limitations;
+}
+
+u8 CheckMoveLimitations(u8 bank, u8 unusableMoves, u8 check)
+{
+ u8 holdEffect;
+ u16* choicedMove = &gBattleStruct->choicedMove[bank];
+ s32 i;
+
+ if (gBattleMons[bank].item == ITEM_ENIGMA_BERRY)
+ holdEffect = gEnigmaBerries[bank].holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[bank].item);
+
+ gStringBank = bank;
+
+ for (i = 0; i < BATTLE_BANKS_COUNT; i++)
+ {
+ if (gBattleMons[bank].moves[i] == 0 && check & MOVE_LIMITATION_ZEROMOVE)
+ unusableMoves |= gBitTable[i];
+ if (gBattleMons[bank].pp[i] == 0 && check & MOVE_LIMITATION_PP)
+ unusableMoves |= gBitTable[i];
+ if (gBattleMons[bank].moves[i] == gDisableStructs[bank].disabledMove && check & MOVE_LIMITATION_DISABLED)
+ unusableMoves |= gBitTable[i];
+ if (gBattleMons[bank].moves[i] == gLastUsedMovesByBanks[bank] && check & MOVE_LIMITATION_TORMENTED && gBattleMons[bank].status2 & STATUS2_TORMENT)
+ unusableMoves |= gBitTable[i];
+ if (gDisableStructs[bank].tauntTimer1 && check & MOVE_LIMITATION_TAUNT && gBattleMoves[gBattleMons[bank].moves[i]].power == 0)
+ unusableMoves |= gBitTable[i];
+ if (GetImprisonedMovesCount(bank, gBattleMons[bank].moves[i]) && check & MOVE_LIMITATION_IMPRISION)
+ unusableMoves |= gBitTable[i];
+ if (gDisableStructs[bank].encoreTimer1 && gDisableStructs[bank].encoredMove != gBattleMons[bank].moves[i])
+ unusableMoves |= gBitTable[i];
+ if (holdEffect == HOLD_EFFECT_CHOICE_BAND && *choicedMove != 0 && *choicedMove != 0xFFFF && *choicedMove != gBattleMons[bank].moves[i])
+ unusableMoves |= gBitTable[i];
+ }
+ return unusableMoves;
+}
+
+bool8 AreAllMovesUnusable(void)
+{
+ u8 unusable;
+ unusable = CheckMoveLimitations(gActiveBank, 0, 0xFF);
+
+ if (unusable == 0xF) // all moves are unusable
+ {
+ gProtectStructs[gActiveBank].onlyStruggle = 1;
+ gUnknown_02024220[gActiveBank] = BattleScript_NoMovesLeft;
+ }
+ else
+ {
+ gProtectStructs[gActiveBank].onlyStruggle = 0;
+ }
+
+ return (unusable == 0xF);
+}
+
+u8 GetImprisonedMovesCount(u8 bank, u16 move)
+{
+ s32 i;
+ u8 imprisionedMoves = 0;
+ u8 bankSide = GetBankSide(bank);
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (bankSide != GetBankSide(i) && gStatuses3[i] & STATUS3_IMPRISONED_OTHERS)
+ {
+ s32 j;
+ for (j = 0; j < 4; j++)
+ {
+ if (move == gBattleMons[i].moves[j])
+ break;
+ }
+ if (j < 4)
+ imprisionedMoves++;
+ }
+ }
+
+ return imprisionedMoves;
+}
+
+u8 UpdateTurnCounters(void)
+{
+ u8 effect = 0;
+ s32 i;
+
+ for (gBankAttacker = 0; gBankAttacker < gNoOfAllBanks && gAbsentBankFlags & gBitTable[gBankAttacker]; gBankAttacker++)
+ {
+ }
+ for (gBankTarget = 0; gBankTarget < gNoOfAllBanks && gAbsentBankFlags & gBitTable[gBankTarget]; gBankTarget++)
+ {
+ }
+
+ do
+ {
+ u8 sideBank;
+
+ switch (gBattleStruct->turncountersTracker)
+ {
+ case 0:
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ gTurnOrder[i] = i;
+ }
+ for (i = 0; i < gNoOfAllBanks - 1; i++)
+ {
+ s32 j;
+ for (j = i + 1; j < gNoOfAllBanks; j++)
+ {
+ if (b_first_side(gTurnOrder[i], gTurnOrder[j], 0))
+ sub_803CEDC(i, j);
+ }
+ }
+
+ // It's stupid, but won't match without it
+ {
+ u8* var = &gBattleStruct->turncountersTracker;
+ (*var)++;
+ gBattleStruct->turnSideTracker = 0;
+ }
+ // fall through
+ case 1:
+ while (gBattleStruct->turnSideTracker < 2)
+ {
+ sideBank = gBattleStruct->turnSideTracker;
+ gActiveBank = gBankAttacker = gSideTimers[sideBank].reflectBank;
+ if (gSideAffecting[sideBank] & SIDE_STATUS_REFLECT)
+ {
+ if (--gSideTimers[sideBank].reflectTimer == 0)
+ {
+ gSideAffecting[sideBank] &= ~SIDE_STATUS_REFLECT;
+ BattleScriptExecute(gUnknown_082DACFA);
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 2;
+ gBattleTextBuff1[2] = MOVE_REFLECT;
+ gBattleTextBuff1[3] = MOVE_REFLECT >> 8;
+ gBattleTextBuff1[4] = EOS;
+ effect++;
+ }
+ }
+ gBattleStruct->turnSideTracker++;
+ if (effect)
+ break;
+ }
+ if (!effect)
+ {
+ gBattleStruct->turncountersTracker++;
+ gBattleStruct->turnSideTracker = 0;
+ }
+ break;
+ case 2:
+ while (gBattleStruct->turnSideTracker < 2)
+ {
+ sideBank = gBattleStruct->turnSideTracker;
+ gActiveBank = gBankAttacker = gSideTimers[sideBank].lightscreenBank;
+ if (gSideAffecting[sideBank] & SIDE_STATUS_LIGHTSCREEN)
+ {
+ if (--gSideTimers[sideBank].lightscreenTimer == 0)
+ {
+ gSideAffecting[sideBank] &= ~SIDE_STATUS_LIGHTSCREEN;
+ BattleScriptExecute(gUnknown_082DACFA);
+ gBattleCommunication[MULTISTRING_CHOOSER] = sideBank;
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 2;
+ gBattleTextBuff1[2] = MOVE_LIGHT_SCREEN;
+ gBattleTextBuff1[3] = MOVE_LIGHT_SCREEN >> 8;
+ gBattleTextBuff1[4] = EOS;
+ effect++;
+ }
+ }
+ gBattleStruct->turnSideTracker++;
+ if (effect)
+ break;
+ }
+ if (!effect)
+ {
+ gBattleStruct->turncountersTracker++;
+ gBattleStruct->turnSideTracker = 0;
+ }
+ break;
+ case 3:
+ while (gBattleStruct->turnSideTracker < 2)
+ {
+ sideBank = gBattleStruct->turnSideTracker;
+ gActiveBank = gBankAttacker = gSideTimers[sideBank].mistBank;
+ if (gSideTimers[sideBank].mistTimer != 0
+ && --gSideTimers[sideBank].mistTimer == 0)
+ {
+ gSideAffecting[sideBank] &= ~SIDE_STATUS_MIST;
+ BattleScriptExecute(gUnknown_082DACFA);
+ gBattleCommunication[MULTISTRING_CHOOSER] = sideBank;
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 2;
+ gBattleTextBuff1[2] = MOVE_MIST;
+ gBattleTextBuff1[3] = MOVE_MIST >> 8;
+ gBattleTextBuff1[4] = EOS;
+ effect++;
+ }
+ gBattleStruct->turnSideTracker++;
+ if (effect)
+ break;
+ }
+ if (!effect)
+ {
+ gBattleStruct->turncountersTracker++;
+ gBattleStruct->turnSideTracker = 0;
+ }
+ break;
+ case 4:
+ while (gBattleStruct->turnSideTracker < 2)
+ {
+ sideBank = gBattleStruct->turnSideTracker;
+ gActiveBank = gBankAttacker = gSideTimers[sideBank].safeguardBank;
+ if (gSideAffecting[sideBank] & SIDE_STATUS_SAFEGUARD)
+ {
+ if (--gSideTimers[sideBank].safeguardTimer == 0)
+ {
+ gSideAffecting[sideBank] &= ~SIDE_STATUS_SAFEGUARD;
+ BattleScriptExecute(gUnknown_082DAD0B);
+ effect++;
+ }
+ }
+ gBattleStruct->turnSideTracker++;
+ if (effect)
+ break;
+ }
+ if (!effect)
+ {
+ gBattleStruct->turncountersTracker++;
+ gBattleStruct->turnSideTracker = 0;
+ }
+ break;
+ case 5:
+ while (gBattleStruct->turnSideTracker < gNoOfAllBanks)
+ {
+ gActiveBank = gTurnOrder[gBattleStruct->turnSideTracker];
+ if (gWishFutureKnock.wishCounter[gActiveBank] != 0
+ && --gWishFutureKnock.wishCounter[gActiveBank] == 0
+ && gBattleMons[gActiveBank].hp != 0)
+ {
+ gBankTarget = gActiveBank;
+ BattleScriptExecute(BattleScript_WishComesTrue);
+ effect++;
+ }
+ gBattleStruct->turnSideTracker++;
+ if (effect)
+ break;
+ }
+ if (!effect)
+ {
+ gBattleStruct->turncountersTracker++;
+ }
+ break;
+ case 6:
+ if (gBattleWeather & WEATHER_RAIN_ANY)
+ {
+ if (!(gBattleWeather & WEATHER_RAIN_PERMANENT))
+ {
+ if (--gWishFutureKnock.weatherDuration == 0)
+ {
+ gBattleWeather &= ~WEATHER_RAIN_TEMPORARY;
+ gBattleWeather &= ~WEATHER_RAIN_DOWNPOUR;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ }
+ else if (gBattleWeather & WEATHER_RAIN_DOWNPOUR)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ else if (gBattleWeather & WEATHER_RAIN_DOWNPOUR)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ BattleScriptExecute(gUnknown_082DAC2C);
+ effect++;
+ }
+ gBattleStruct->turncountersTracker++;
+ break;
+ case 7:
+ if (gBattleWeather & WEATHER_SANDSTORM_ANY)
+ {
+ if (!(gBattleWeather & WEATHER_SANDSTORM_PERMANENT) && --gWishFutureKnock.weatherDuration == 0)
+ {
+ gBattleWeather &= ~WEATHER_SANDSTORM_TEMPORARY;
+ gBattlescriptCurrInstr = gUnknown_082DACC9;
+ }
+ else
+ gBattlescriptCurrInstr = gUnknown_082DAC47;
+
+ gBattleScripting.animArg1 = 0xC;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ BattleScriptExecute(gBattlescriptCurrInstr);
+ effect++;
+ }
+ gBattleStruct->turncountersTracker++;
+ break;
+ case 8:
+ if (gBattleWeather & WEATHER_SUN_ANY)
+ {
+ if (!(gBattleWeather & WEATHER_SUN_PERMANENT) && --gWishFutureKnock.weatherDuration == 0)
+ {
+ gBattleWeather &= ~WEATHER_SUN_TEMPORARY;
+ gBattlescriptCurrInstr = gUnknown_082DACE0;
+ }
+ else
+ gBattlescriptCurrInstr = gUnknown_082DACD2;
+
+ BattleScriptExecute(gBattlescriptCurrInstr);
+ effect++;
+ }
+ gBattleStruct->turncountersTracker++;
+ break;
+ case 9:
+ if (gBattleWeather & WEATHER_HAIL)
+ {
+ if (--gWishFutureKnock.weatherDuration == 0)
+ {
+ gBattleWeather &= ~WEATHER_HAIL;
+ gBattlescriptCurrInstr = gUnknown_082DACC9;
+ }
+ else
+ gBattlescriptCurrInstr = gUnknown_082DAC47;
+
+ gBattleScripting.animArg1 = 0xD;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ BattleScriptExecute(gBattlescriptCurrInstr);
+ effect++;
+ }
+ gBattleStruct->turncountersTracker++;
+ break;
+ case 10:
+ effect++;
+ break;
+ }
+ } while (effect == 0);
+ return (gBattleMainFunc != BattleTurnPassed);
+}
+
+#define TURNBASED_MAX_CASE 19
+
+u8 TurnBasedEffects(void)
+{
+ u8 effect = 0;
+
+ gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_x20);
+ while (gBattleStruct->turnEffectsBank < gNoOfAllBanks && gBattleStruct->turnEffectsTracker <= TURNBASED_MAX_CASE)
+ {
+ gActiveBank = gBankAttacker = gTurnOrder[gBattleStruct->turnEffectsBank];
+ if (gAbsentBankFlags & gBitTable[gActiveBank])
+ {
+ gBattleStruct->turnEffectsBank++;
+ }
+ else
+ {
+ switch (gBattleStruct->turnEffectsTracker)
+ {
+ case 0: // ingrain
+ if ((gStatuses3[gActiveBank] & STATUS3_ROOTED)
+ && gBattleMons[gActiveBank].hp != gBattleMons[gActiveBank].maxHP
+ && gBattleMons[gActiveBank].hp != 0)
+ {
+ gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 16;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ gBattleMoveDamage *= -1;
+ BattleScriptExecute(BattleScript_IngrainTurnHeal);
+ effect++;
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 1: // end turn abilities
+ if (AbilityBattleEffects(ABILITYEFFECT_ENDTURN, gActiveBank, 0, 0, 0))
+ effect++;
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 2: // item effects
+ if (ItemBattleEffects(1, gActiveBank, 0))
+ effect++;
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 18: // item effects again
+ if (ItemBattleEffects(1, gActiveBank, 1))
+ effect++;
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 3: // leech seed
+ if ((gStatuses3[gActiveBank] & STATUS3_LEECHSEED)
+ && gBattleMons[gStatuses3[gActiveBank] & STATUS3_LEECHSEED_BANK].hp != 0
+ && gBattleMons[gActiveBank].hp != 0)
+ {
+ gBankTarget = gStatuses3[gActiveBank] & STATUS3_LEECHSEED_BANK; //funny how the 'target' is actually the bank that receives HP
+ gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 8;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ gBattleScripting.animArg1 = gBankTarget;
+ gBattleScripting.animArg2 = gBankAttacker;
+ BattleScriptExecute(BattleScript_LeechSeedTurnDrain);
+ effect++;
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 4: // poison
+ if ((gBattleMons[gActiveBank].status1 & STATUS_POISON) && gBattleMons[gActiveBank].hp != 0)
+ {
+ gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 8;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ BattleScriptExecute(BattleScript_PoisonTurnDmg);
+ effect++;
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 5: // toxic poison
+ if ((gBattleMons[gActiveBank].status1 & STATUS_TOXIC_POISON) && gBattleMons[gActiveBank].hp != 0)
+ {
+ gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 16;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ if ((gBattleMons[gActiveBank].status1 & 0xF00) != 0xF00) //not 16 turns
+ gBattleMons[gActiveBank].status1 += 0x100;
+ gBattleMoveDamage *= (gBattleMons[gActiveBank].status1 & 0xF00) >> 8;
+ BattleScriptExecute(BattleScript_PoisonTurnDmg);
+ effect++;
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 6: // burn
+ if ((gBattleMons[gActiveBank].status1 & STATUS_BURN) && gBattleMons[gActiveBank].hp != 0)
+ {
+ gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 8;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ BattleScriptExecute(BattleScript_BurnTurnDmg);
+ effect++;
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 7: // spooky nightmares
+ if ((gBattleMons[gActiveBank].status2 & STATUS2_NIGHTMARE) && gBattleMons[gActiveBank].hp != 0)
+ {
+ // R/S does not perform this sleep check, which causes the nighmare effect to
+ // persist even after the affected Pokemon has been awakened by Shed Skin
+ if (gBattleMons[gActiveBank].status1 & STATUS_SLEEP)
+ {
+ gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 4;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ BattleScriptExecute(BattleScript_NightmareTurnDmg);
+ effect++;
+ }
+ else
+ {
+ gBattleMons[gActiveBank].status2 &= ~STATUS2_NIGHTMARE;
+ }
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 8: // curse
+ if ((gBattleMons[gActiveBank].status2 & STATUS2_CURSED) && gBattleMons[gActiveBank].hp != 0)
+ {
+ gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 4;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ BattleScriptExecute(BattleScript_CurseTurnDmg);
+ effect++;
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 9: // wrap
+ if ((gBattleMons[gActiveBank].status2 & STATUS2_WRAPPED) && gBattleMons[gActiveBank].hp != 0)
+ {
+ gBattleMons[gActiveBank].status2 -= 0x2000;
+ if (gBattleMons[gActiveBank].status2 & STATUS2_WRAPPED) // damaged by wrap
+ {
+ // This is the only way I could get this array access to match.
+ gBattleScripting.animArg1 = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 0);
+ gBattleScripting.animArg2 = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 1);
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 2;
+ gBattleTextBuff1[2] = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 0);
+ gBattleTextBuff1[3] = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 1);
+ gBattleTextBuff1[4] = EOS;
+ gBattlescriptCurrInstr = BattleScript_WrapTurnDmg;
+ gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / 16;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ }
+ else // broke free
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 2;
+ gBattleTextBuff1[2] = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 0);
+ gBattleTextBuff1[3] = *(gBattleStruct->wrappedMove + gActiveBank * 2 + 1);
+ gBattleTextBuff1[4] = EOS;
+ gBattlescriptCurrInstr = BattleScript_WrapEnds;
+ }
+ BattleScriptExecute(gBattlescriptCurrInstr);
+ effect++;
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 10: // uproar
+ if (gBattleMons[gActiveBank].status2 & STATUS2_UPROAR)
+ {
+ for (gBankAttacker = 0; gBankAttacker < gNoOfAllBanks; gBankAttacker++)
+ {
+ if ((gBattleMons[gBankAttacker].status1 & STATUS_SLEEP)
+ && gBattleMons[gBankAttacker].ability != ABILITY_SOUNDPROOF)
+ {
+ gBattleMons[gBankAttacker].status1 &= ~(STATUS_SLEEP);
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE);
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ BattleScriptExecute(gUnknown_082DB234);
+ gActiveBank = gBankAttacker;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ break;
+ }
+ }
+ if (gBankAttacker != gNoOfAllBanks)
+ {
+ effect = 2; // a pokemon was awaken
+ break;
+ }
+ else
+ {
+ gBankAttacker = gActiveBank;
+ gBattleMons[gActiveBank].status2 -= 0x10; // uproar timer goes down
+ if (HasMoveFailed(gActiveBank))
+ {
+ CancelMultiTurnMoves(gActiveBank);
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ else if (gBattleMons[gActiveBank].status2 & STATUS2_UPROAR)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ gBattleMons[gActiveBank].status2 |= STATUS2_MULTIPLETURNS;
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ CancelMultiTurnMoves(gActiveBank);
+ }
+ BattleScriptExecute(gUnknown_082DB2A6);
+ effect = 1;
+ }
+ }
+ if (effect != 2)
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 11: // thrash
+ if (gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE)
+ {
+ gBattleMons[gActiveBank].status2 -= 0x400;
+ if (HasMoveFailed(gActiveBank))
+ CancelMultiTurnMoves(gActiveBank);
+ else if (!(gBattleMons[gActiveBank].status2 & STATUS2_LOCK_CONFUSE)
+ && (gBattleMons[gActiveBank].status2 & STATUS2_MULTIPLETURNS))
+ {
+ gBattleMons[gActiveBank].status2 &= ~(STATUS2_MULTIPLETURNS);
+ if (!(gBattleMons[gActiveBank].status2 & STATUS2_CONFUSION))
+ {
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0x47;
+ SetMoveEffect(1, 0);
+ if (gBattleMons[gActiveBank].status2 & STATUS2_CONFUSION)
+ BattleScriptExecute(BattleScript_ThrashConfuses);
+ effect++;
+ }
+ }
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 12: // disable
+ if (gDisableStructs[gActiveBank].disableTimer1 != 0)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ if (gDisableStructs[gActiveBank].disabledMove == gBattleMons[gActiveBank].moves[i])
+ break;
+ }
+ if (i == 4) // pokemon does not have the disabled move anymore
+ {
+ gDisableStructs[gActiveBank].disabledMove = 0;
+ gDisableStructs[gActiveBank].disableTimer1 = 0;
+ }
+ else if (--gDisableStructs[gActiveBank].disableTimer1 == 0) // disable ends
+ {
+ gDisableStructs[gActiveBank].disabledMove = 0;
+ BattleScriptExecute(BattleScript_DisabledNoMore);
+ effect++;
+ }
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 13: // encore
+ if (gDisableStructs[gActiveBank].encoreTimer1 != 0)
+ {
+ if (gBattleMons[gActiveBank].moves[gDisableStructs[gActiveBank].encoredMovePos] != gDisableStructs[gActiveBank].encoredMove) // pokemon does not have the encored move anymore
+ {
+ gDisableStructs[gActiveBank].encoredMove = 0;
+ gDisableStructs[gActiveBank].encoreTimer1 = 0;
+ }
+ else if (--gDisableStructs[gActiveBank].encoreTimer1 == 0
+ || gBattleMons[gActiveBank].pp[gDisableStructs[gActiveBank].encoredMovePos] == 0)
+ {
+ gDisableStructs[gActiveBank].encoredMove = 0;
+ gDisableStructs[gActiveBank].encoreTimer1 = 0;
+ BattleScriptExecute(BattleScript_EncoredNoMore);
+ effect++;
+ }
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 14: // lock-on decrement
+ if (gStatuses3[gActiveBank] & STATUS3_ALWAYS_HITS)
+ gStatuses3[gActiveBank] -= 0x8;
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 15: // charge
+ if (gDisableStructs[gActiveBank].chargeTimer1 && --gDisableStructs[gActiveBank].chargeTimer1 == 0)
+ gStatuses3[gActiveBank] &= ~STATUS3_CHARGED_UP;
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 16: // taunt
+ if (gDisableStructs[gActiveBank].tauntTimer1)
+ gDisableStructs[gActiveBank].tauntTimer1--;
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 17: // yawn
+ if (gStatuses3[gActiveBank] & STATUS3_YAWN)
+ {
+ gStatuses3[gActiveBank] -= 0x800;
+ if (!(gStatuses3[gActiveBank] & STATUS3_YAWN) && !(gBattleMons[gActiveBank].status1 & STATUS_ANY)
+ && gBattleMons[gActiveBank].ability != ABILITY_VITAL_SPIRIT
+ && gBattleMons[gActiveBank].ability != ABILITY_INSOMNIA && !UproarWakeUpCheck(gActiveBank))
+ {
+ CancelMultiTurnMoves(gActiveBank);
+ gBattleMons[gActiveBank].status1 |= (Random() & 3) + 2;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ gEffectBank = gActiveBank;
+ BattleScriptExecute(BattleScript_YawnMakesAsleep);
+ effect++;
+ }
+ }
+ gBattleStruct->turnEffectsTracker++;
+ break;
+ case 19: // done
+ gBattleStruct->turnEffectsTracker = 0;
+ gBattleStruct->turnEffectsBank++;
+ break;
+ }
+ if (effect != 0)
+ return effect;
+ }
+ }
+ gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_x20);
+ return 0;
+}
+
+bool8 sub_8041364(void)
+{
+ gHitMarker |= (HITMARKER_GRUDGE | HITMARKER_x20);
+
+ switch (gBattleStruct->field_1A0)
+ {
+ case 0:
+ while (gBattleStruct->field_1A1 < gNoOfAllBanks)
+ {
+ gActiveBank = gBattleStruct->field_1A1;
+ if (gAbsentBankFlags & gBitTable[gActiveBank])
+ {
+ gBattleStruct->field_1A1++;
+ continue;
+ }
+
+ gBattleStruct->field_1A1++;
+ if (gWishFutureKnock.futureSightCounter[gActiveBank] != 0
+ && --gWishFutureKnock.futureSightCounter[gActiveBank] == 0
+ && gBattleMons[gActiveBank].hp != 0)
+ {
+ if (gWishFutureKnock.futureSightMove[gActiveBank] == MOVE_FUTURE_SIGHT)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 2;
+ gBattleTextBuff1[2] = gWishFutureKnock.futureSightMove[gActiveBank];
+ gBattleTextBuff1[3] = gWishFutureKnock.futureSightMove[gActiveBank] >> 8;
+ gBattleTextBuff1[4] = EOS;
+ gBankTarget = gActiveBank;
+ gBankAttacker = gWishFutureKnock.futureSightAttacker[gActiveBank];
+ gBattleMoveDamage = gWishFutureKnock.futureSightDmg[gActiveBank];
+ gSpecialStatuses[gBankTarget].moveturnLostHP = 0xFFFF;
+ BattleScriptExecute(gUnknown_082DAFE4);
+
+ if (gWishFutureKnock.futureSightCounter[gActiveBank] == 0
+ && gWishFutureKnock.futureSightCounter[gActiveBank ^ 2] == 0)
+ {
+ gSideAffecting[GetBankIdentity(gBankTarget) & 1] &= ~SIDE_STATUS_FUTUREATTACK;
+ }
+ return 1;
+ }
+ }
+ // Why do I have to keep doing this to match?
+ {
+ u8* var = &gBattleStruct->field_1A0;
+ *var = 1;
+ gBattleStruct->field_1A1 = 0;
+ }
+ // fall through
+ case 1:
+ while (gBattleStruct->field_1A1 < gNoOfAllBanks)
+ {
+ gActiveBank = gBankAttacker = gTurnOrder[gBattleStruct->field_1A1];
+ if (gAbsentBankFlags & gBitTable[gActiveBank])
+ {
+ gBattleStruct->field_1A1++;
+ continue;
+ }
+ gBattleStruct->field_1A1++;
+ if (gStatuses3[gActiveBank] & STATUS3_PERISH_SONG)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 1;
+ gBattleTextBuff1[2] = 1;
+ gBattleTextBuff1[3] = 1;
+ gBattleTextBuff1[4] = gDisableStructs[gActiveBank].perishSong1;
+ gBattleTextBuff1[5] = EOS;
+ if (gDisableStructs[gActiveBank].perishSong1 == 0)
+ {
+ gStatuses3[gActiveBank] &= ~STATUS3_PERISH_SONG;
+ gBattleMoveDamage = gBattleMons[gActiveBank].hp;
+ gBattlescriptCurrInstr = gUnknown_082DAF05;
+ }
+ else
+ {
+ gDisableStructs[gActiveBank].perishSong1--;
+ gBattlescriptCurrInstr = gUnknown_082DAF20;
+ }
+ BattleScriptExecute(gBattlescriptCurrInstr);
+ return 1;
+ }
+ }
+ // Hm...
+ {
+ u8* var = &gBattleStruct->field_1A0;
+ *var = 2;
+ gBattleStruct->field_1A1 = 0;
+ }
+ // fall through
+ case 2:
+ if ((gBattleTypeFlags & BATTLE_TYPE_ARENA)
+ && gBattleStruct->field_DA == 2
+ && gBattleMons[0].hp != 0 && gBattleMons[1].hp != 0)
+ {
+ s32 i;
+
+ for (i = 0; i < 2; i++)
+ CancelMultiTurnMoves(i);
+
+ gBattlescriptCurrInstr = gUnknown_082DB8F3;
+ BattleScriptExecute(gUnknown_082DB8F3);
+ gBattleStruct->field_1A0++;
+ return 1;
+ }
+ break;
+ }
+
+ gHitMarker &= ~(HITMARKER_GRUDGE | HITMARKER_x20);
+
+ return 0;
+}
+
+#define sub_8041728_MAX_CASE 7
+
+bool8 sub_8041728(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
+ return FALSE;
+ do
+ {
+ int i;
+ switch (gBattleStruct->field_4D)
+ {
+ case 0:
+ gBattleStruct->field_4E = 0;
+ gBattleStruct->field_4D++;
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gAbsentBankFlags & gBitTable[i] && !sub_80423F4(i, 6, 6))
+ gAbsentBankFlags &= ~(gBitTable[i]);
+ }
+ // fall through
+ case 1:
+ do
+ {
+ gBank1 = gBankTarget = gBattleStruct->field_4E;
+ if (gBattleMons[gBattleStruct->field_4E].hp == 0
+ && !(gBattleStruct->field_DF & gBitTable[gBattlePartyID[gBattleStruct->field_4E]])
+ && !(gAbsentBankFlags & gBitTable[gBattleStruct->field_4E]))
+ {
+ BattleScriptExecute(gUnknown_082DA7C4);
+ gBattleStruct->field_4D = 2;
+ return TRUE;
+ }
+ } while (++gBattleStruct->field_4E != gNoOfAllBanks);
+ gBattleStruct->field_4D = 3;
+ break;
+ case 2:
+ sub_803F9EC(gBank1);
+ if (++gBattleStruct->field_4E == gNoOfAllBanks)
+ gBattleStruct->field_4D = 3;
+ else
+ gBattleStruct->field_4D = 1;
+ break;
+ case 3:
+ gBattleStruct->field_4E = 0;
+ gBattleStruct->field_4D++;
+ // fall through
+ case 4:
+ do
+ {
+ gBank1 = gBankTarget = gBattleStruct->field_4E; //or should banks be switched?
+ if (gBattleMons[gBattleStruct->field_4E].hp == 0
+ && !(gAbsentBankFlags & gBitTable[gBattleStruct->field_4E]))
+ {
+ BattleScriptExecute(gUnknown_082DA7CD);
+ gBattleStruct->field_4D = 5;
+ return TRUE;
+ }
+ } while (++gBattleStruct->field_4E != gNoOfAllBanks);
+ gBattleStruct->field_4D = 6;
+ break;
+ case 5:
+ if (++gBattleStruct->field_4E == gNoOfAllBanks)
+ gBattleStruct->field_4D = 6;
+ else
+ gBattleStruct->field_4D = 4;
+ break;
+ case 6:
+ if (AbilityBattleEffects(ABILITYEFFECT_INTIMIDATE1, 0, 0, 0, 0) || AbilityBattleEffects(ABILITYEFFECT_TRACE, 0, 0, 0, 0) || ItemBattleEffects(1, 0, 1) || AbilityBattleEffects(ABILITYEFFECT_FORECAST, 0, 0, 0, 0))
+ return TRUE;
+ gBattleStruct->field_4D++;
+ break;
+ case 7:
+ break;
+ }
+ } while (gBattleStruct->field_4D != sub_8041728_MAX_CASE);
+ return FALSE;
+}
+
+void b_clear_atk_up_if_hit_flag_unless_enraged(void)
+{
+ int i;
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if ((gBattleMons[i].status2 & STATUS2_RAGE) && gChosenMovesByBanks[i] != MOVE_RAGE)
+ gBattleMons[i].status2 &= ~(STATUS2_RAGE);
+ }
+}
+
+#define ATKCANCELLER_MAX_CASE 14
+
+u8 AtkCanceller_UnableToUseMove(void)
+{
+ u8 effect = 0;
+ s32* bideDmg = &gBattleScripting.bideDmg;
+ do
+ {
+ switch (gBattleStruct->atkCancellerTracker)
+ {
+ case 0: // flags clear
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_DESTINY_BOND);
+ gStatuses3[gBankAttacker] &= ~(STATUS3_GRUDGE);
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 1: // check being asleep
+ if (gBattleMons[gBankAttacker].status1 & STATUS_SLEEP)
+ {
+ if (UproarWakeUpCheck(gBankAttacker))
+ {
+ gBattleMons[gBankAttacker].status1 &= ~(STATUS_SLEEP);
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE);
+ BattleScriptPushCursor();
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp;
+ effect = 2;
+ }
+ else
+ {
+ u8 toSub;
+ if (gBattleMons[gBankAttacker].ability == ABILITY_EARLY_BIRD)
+ toSub = 2;
+ else
+ toSub = 1;
+ if ((gBattleMons[gBankAttacker].status1 & STATUS_SLEEP) < toSub)
+ gBattleMons[gBankAttacker].status1 &= ~(STATUS_SLEEP);
+ else
+ gBattleMons[gBankAttacker].status1 -= toSub;
+ if (gBattleMons[gBankAttacker].status1 & STATUS_SLEEP)
+ {
+ if (gCurrentMove != MOVE_SNORE && gCurrentMove != MOVE_SLEEP_TALK)
+ {
+ gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep;
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ effect = 2;
+ }
+ }
+ else
+ {
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE);
+ BattleScriptPushCursor();
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ gBattlescriptCurrInstr = BattleScript_MoveUsedWokeUp;
+ effect = 2;
+ }
+ }
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 2: // check being frozen
+ if (gBattleMons[gBankAttacker].status1 & STATUS_FREEZE)
+ {
+ if (Random() % 5)
+ {
+ if (gBattleMoves[gCurrentMove].effect != EFFECT_THAW_HIT) // unfreezing via a move effect happens in case 13
+ {
+ gBattlescriptCurrInstr = BattleScript_MoveUsedIsFrozen;
+ gHitMarker |= HITMARKER_NO_ATTACKSTRING;
+ }
+ else
+ {
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ }
+ }
+ else // unfreeze
+ {
+ gBattleMons[gBankAttacker].status1 &= ~(STATUS_FREEZE);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ effect = 2;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 3: // truant
+ if (gBattleMons[gBankAttacker].ability == ABILITY_TRUANT && gDisableStructs[gBankAttacker].truantCounter)
+ {
+ CancelMultiTurnMoves(gBankAttacker);
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround;
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ effect = 1;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 4: // recharge
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_RECHARGE)
+ {
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_RECHARGE);
+ gDisableStructs[gBankAttacker].rechargeCounter = 0;
+ CancelMultiTurnMoves(gBankAttacker);
+ gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge;
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ effect = 1;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 5: // flinch
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_FLINCHED)
+ {
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_FLINCHED);
+ gProtectStructs[gBankAttacker].flinchImmobility = 1;
+ CancelMultiTurnMoves(gBankAttacker);
+ gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched;
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ effect = 1;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 6: // disabled move
+ if (gDisableStructs[gBankAttacker].disabledMove == gCurrentMove && gDisableStructs[gBankAttacker].disabledMove != 0)
+ {
+ gProtectStructs[gBankAttacker].usedDisabledMove = 1;
+ gBattleScripting.bank = gBankAttacker;
+ CancelMultiTurnMoves(gBankAttacker);
+ gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled;
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ effect = 1;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 7: // taunt
+ if (gDisableStructs[gBankAttacker].tauntTimer1 && gBattleMoves[gCurrentMove].power == 0)
+ {
+ gProtectStructs[gBankAttacker].usedTauntedMove = 1;
+ CancelMultiTurnMoves(gBankAttacker);
+ gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted;
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ effect = 1;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 8: // imprisoned
+ if (GetImprisonedMovesCount(gBankAttacker, gCurrentMove))
+ {
+ gProtectStructs[gBankAttacker].usedImprisionedMove = 1;
+ CancelMultiTurnMoves(gBankAttacker);
+ gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned;
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ effect = 1;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 9: // confusion
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_CONFUSION)
+ {
+ gBattleMons[gBankAttacker].status2--;
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_CONFUSION)
+ {
+ if (Random() & 1)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ BattleScriptPushCursor();
+ }
+ else // confusion dmg
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ gBankTarget = gBankAttacker;
+ gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankAttacker], MOVE_POUND, 0, 40, 0, gBankAttacker, gBankAttacker);
+ gProtectStructs[gBankAttacker].confusionSelfDmg = 1;
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ }
+ gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfused;
+ }
+ else // snapped out of confusion
+ {
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_MoveUsedIsConfusedNoMore;
+ }
+ effect = 1;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 10: // paralysis
+ if ((gBattleMons[gBankAttacker].status1 & STATUS_PARALYSIS) && (Random() % 4) == 0)
+ {
+ gProtectStructs[gBankAttacker].prlzImmobility = 1;
+ // This is removed in Emerald for some reason
+ //CancelMultiTurnMoves(gBankAttacker);
+ gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed;
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ effect = 1;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 11: // infatuation
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_INFATUATION)
+ {
+ gBattleScripting.bank = CountTrailingZeroBits((gBattleMons[gBankAttacker].status2 & STATUS2_INFATUATION) >> 0x10);
+ if (Random() & 1)
+ BattleScriptPushCursor();
+ else
+ {
+ BattleScriptPush(BattleScript_MoveUsedIsParalyzedCantAttack);
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ gProtectStructs[gBankAttacker].loveImmobility = 1;
+ CancelMultiTurnMoves(gBankAttacker);
+ }
+ gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove;
+ effect = 1;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 12: // bide
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_BIDE)
+ {
+ gBattleMons[gBankAttacker].status2 -= 0x100;
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_BIDE)
+ gBattlescriptCurrInstr = BattleScript_BideStoringEnergy;
+ else
+ {
+ // This is removed in Emerald for some reason
+ //gBattleMons[gBankAttacker].status2 &= ~(STATUS2_MULTIPLETURNS);
+ if (gTakenDmg[gBankAttacker])
+ {
+ gCurrentMove = MOVE_BIDE;
+ *bideDmg = gTakenDmg[gBankAttacker] * 2;
+ gBankTarget = gTakenDmgBanks[gBankAttacker];
+ if (gAbsentBankFlags & gBitTable[gBankTarget])
+ gBankTarget = GetMoveTarget(MOVE_BIDE, 1);
+ gBattlescriptCurrInstr = BattleScript_BideAttack;
+ }
+ else
+ gBattlescriptCurrInstr = BattleScript_BideNoEnergyToAttack;
+ }
+ effect = 1;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 13: // move thawing
+ if (gBattleMons[gBankAttacker].status1 & STATUS_FREEZE)
+ {
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_THAW_HIT)
+ {
+ gBattleMons[gBankAttacker].status1 &= ~(STATUS_FREEZE);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_MoveUsedUnfroze;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ effect = 2;
+ }
+ gBattleStruct->atkCancellerTracker++;
+ break;
+ case 14: // last case
+ break;
+ }
+
+ } while (gBattleStruct->atkCancellerTracker != ATKCANCELLER_MAX_CASE && effect == 0);
+
+ if (effect == 2)
+ {
+ gActiveBank = gBankAttacker;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ return effect;
+}
+
+bool8 sub_80423F4(u8 bank, u8 r1, u8 r2)
+{
+ struct Pokemon* party;
+ u8 r7;
+ u8 r6;
+ s32 i;
+ if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ return FALSE;
+ if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
+ {
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ party = gPlayerParty;
+ else
+ party = gEnemyParty;
+ r6 = ((bank & 2) / 2);
+ for (i = r6 * 3; i < r6 * 3 + 3; i++)
+ {
+ if (GetMonData(&party[i], MON_DATA_HP) != 0
+ && GetMonData(&party[i], MON_DATA_SPECIES2) != 0
+ && GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG)
+ break;
+ }
+ return (i == r6 * 3 + 3);
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x800000)
+ {
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ {
+ party = gPlayerParty;
+ r7 = sub_806D864(bank);
+ r6 = sub_806D82C(r7);
+ }
+ else
+ {
+ // FIXME: Compiler insists on moving r4 into r1 before doing the eor
+ #ifndef NONMATCHING
+ register u32 var asm("r1");
+ #else
+ u32 var;
+ #endif // NONMATCHING
+
+ party = gEnemyParty;
+ var = bank ^ 1;
+ r6 = (var != 0) ? 1 : 0;
+ }
+ }
+ else
+ {
+ r7 = sub_806D864(bank);
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ party = gPlayerParty;
+ else
+ party = gEnemyParty;
+ r6 = sub_806D82C(r7);
+ }
+ for (i = r6 * 3; i < r6 * 3 + 3; i++)
+ {
+ if (GetMonData(&party[i], MON_DATA_HP) != 0
+ && GetMonData(&party[i], MON_DATA_SPECIES2) != 0
+ && GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG)
+ break;
+ }
+ return (i == r6 * 3 + 3);
+ }
+ else if ((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) && GetBankSide(bank) == SIDE_OPPONENT)
+ {
+ party = gEnemyParty;
+
+ if (bank == 1)
+ r6 = 0;
+ else
+ r6 = 3;
+ for (i = r6; i < r6 + 3; i++)
+ {
+ if (GetMonData(&party[i], MON_DATA_HP) != 0
+ && GetMonData(&party[i], MON_DATA_SPECIES2) != 0
+ && GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG)
+ break;
+ }
+ return (i == r6 + 3);
+ }
+ else
+ {
+ if (GetBankSide(bank) == SIDE_OPPONENT)
+ {
+ r7 = GetBankByIdentity(1);
+ r6 = GetBankByIdentity(3);
+ party = gEnemyParty;
+ }
+ else
+ {
+ r7 = GetBankByIdentity(0);
+ r6 = GetBankByIdentity(2);
+ party = gPlayerParty;
+ }
+ if (r1 == 6)
+ r1 = gBattlePartyID[r7];
+ if (r2 == 6)
+ r2 = gBattlePartyID[r6];
+ for (i = 0; i < 6; i++)
+ {
+ if (GetMonData(&party[i], MON_DATA_HP) != 0
+ && GetMonData(&party[i], MON_DATA_SPECIES2) != 0
+ && GetMonData(&party[i], MON_DATA_SPECIES2) != SPECIES_EGG
+ // FIXME: Using index[array] instead of array[index] is BAD!
+ && i != r1 && i != r2 && i != r7[gBattleStruct->field_5C] && i != r6[gBattleStruct->field_5C])
+ break;
+ }
+ return (i == 6);
+ }
+}
+
+enum
+{
+ CASTFORM_NO_CHANGE, //0
+ CASTFORM_TO_NORMAL, //1
+ CASTFORM_TO_FIRE, //2
+ CASTFORM_TO_WATER, //3
+ CASTFORM_TO_ICE, //4
+};
+
+u8 CastformDataTypeChange(u8 bank)
+{
+ u8 formChange = 0;
+ if (gBattleMons[bank].species != SPECIES_CASTFORM || gBattleMons[bank].ability != ABILITY_FORECAST || gBattleMons[bank].hp == 0)
+ return CASTFORM_NO_CHANGE;
+ if (!WEATHER_HAS_EFFECT && gBattleMons[bank].type1 != TYPE_NORMAL && gBattleMons[bank].type2 != TYPE_NORMAL)
+ {
+ gBattleMons[bank].type1 = TYPE_NORMAL;
+ gBattleMons[bank].type2 = TYPE_NORMAL;
+ return CASTFORM_TO_NORMAL;
+ }
+ if (!WEATHER_HAS_EFFECT)
+ return CASTFORM_NO_CHANGE;
+ if (!(gBattleWeather & (WEATHER_RAIN_ANY | WEATHER_SUN_ANY | WEATHER_HAIL)) && gBattleMons[bank].type1 != TYPE_NORMAL && gBattleMons[bank].type2 != TYPE_NORMAL)
+ {
+ gBattleMons[bank].type1 = TYPE_NORMAL;
+ gBattleMons[bank].type2 = TYPE_NORMAL;
+ formChange = CASTFORM_TO_NORMAL;
+ }
+ if (gBattleWeather & WEATHER_SUN_ANY && gBattleMons[bank].type1 != TYPE_FIRE && gBattleMons[bank].type2 != TYPE_FIRE)
+ {
+ gBattleMons[bank].type1 = TYPE_FIRE;
+ gBattleMons[bank].type2 = TYPE_FIRE;
+ formChange = CASTFORM_TO_FIRE;
+ }
+ if (gBattleWeather & WEATHER_RAIN_ANY && gBattleMons[bank].type1 != TYPE_WATER && gBattleMons[bank].type2 != TYPE_WATER)
+ {
+ gBattleMons[bank].type1 = TYPE_WATER;
+ gBattleMons[bank].type2 = TYPE_WATER;
+ formChange = CASTFORM_TO_WATER;
+ }
+ if (gBattleWeather & WEATHER_HAIL && gBattleMons[bank].type1 != TYPE_ICE && gBattleMons[bank].type2 != TYPE_ICE)
+ {
+ gBattleMons[bank].type1 = TYPE_ICE;
+ gBattleMons[bank].type2 = TYPE_ICE;
+ formChange = CASTFORM_TO_ICE;
+ }
+ return formChange;
+}
+
+// We meet again, ABE.
+#ifdef NONMATCHING
+u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg)
+{
+ u8 effect = 0;
+ struct Pokemon* pokeAtk;
+ struct Pokemon* pokeDef;
+ u16 speciesAtk;
+ u16 speciesDef;
+ u32 pidAtk;
+ u32 pidDef;
+
+ if (gBankAttacker >= gNoOfAllBanks)
+ gBankAttacker = bank;
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ pokeAtk = &gPlayerParty[gBattlePartyID[gBankAttacker]];
+ else
+ pokeAtk = &gEnemyParty[gBattlePartyID[gBankAttacker]];
+
+ if (gBankTarget >= gNoOfAllBanks)
+ gBankTarget = bank;
+ if (GetBankSide(gBankTarget) == SIDE_PLAYER)
+ pokeDef = &gPlayerParty[gBattlePartyID[gBankTarget]];
+ else
+ pokeDef = &gEnemyParty[gBattlePartyID[gBankTarget]];
+
+ speciesAtk = GetMonData(pokeAtk, MON_DATA_SPECIES);
+ pidAtk = GetMonData(pokeAtk, MON_DATA_PERSONALITY);
+
+ speciesDef = GetMonData(pokeDef, MON_DATA_SPECIES);
+ pidDef = GetMonData(pokeDef, MON_DATA_PERSONALITY);
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) // why isn't that check done at the beginning?
+ {
+ int i; // r4
+ u16 move;
+ // Hmm...
+ #define moveType moveArg
+ //u16 moveType;
+ u8 side;
+
+ if (special)
+ gLastUsedAbility = special;
+ else
+ gLastUsedAbility = gBattleMons[bank].ability;
+
+ if (moveArg)
+ move = moveArg;
+ else
+ move = gCurrentMove;
+
+ if (gBattleStruct->dynamicMoveType)
+ moveType = gBattleStruct->dynamicMoveType & 0x3F;
+ else
+ moveType = gBattleMoves[move].type;
+
+ switch (caseID)
+ {
+ case ABILITYEFFECT_ON_SWITCHIN: // 0
+ //_08042A18
+ if (gBankAttacker >= gNoOfAllBanks)
+ gBankAttacker = bank;
+ switch (gLastUsedAbility)
+ {
+ case 0xFF: //weather from overworld
+ //_08042A86
+ switch (weather_get_current())
+ {
+ case 3:
+ case 5:
+ case 13:
+ if (!(gBattleWeather & WEATHER_RAIN_ANY))
+ {
+ gBattleWeather = (WEATHER_RAIN_TEMPORARY | WEATHER_RAIN_PERMANENT);
+ gBattleScripting.animArg1 = 0xA;
+ gBattleScripting.bank = bank;
+ effect++;
+ }
+ break;
+ case 8:
+ if (!(gBattleWeather & WEATHER_SANDSTORM_ANY))
+ {
+ gBattleWeather = (WEATHER_SANDSTORM_PERMANENT | WEATHER_SANDSTORM_TEMPORARY);
+ gBattleScripting.animArg1 = 0xC;
+ gBattleScripting.bank = bank;
+ effect++;
+ }
+ break;
+ case 12:
+ if (!(gBattleWeather & WEATHER_SUN_ANY))
+ {
+ gBattleWeather = (WEATHER_SUN_PERMANENT | WEATHER_SUN_TEMPORARY);
+ gBattleScripting.animArg1 = 0xB;
+ gBattleScripting.bank = bank;
+ effect++;
+ }
+ break;
+ }
+ if (effect)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = weather_get_current();
+ BattleScriptPushCursorAndCallback(gUnknown_082DACE7);
+ }
+ break;
+ case ABILITY_DRIZZLE:
+ //_08042B78
+ if (!(gBattleWeather & WEATHER_RAIN_PERMANENT))
+ {
+ gBattleWeather = (WEATHER_RAIN_PERMANENT | WEATHER_RAIN_TEMPORARY);
+ BattleScriptPushCursorAndCallback(BattleScript_DrizzleActivates);
+ gBattleScripting.bank = bank;
+ effect++;
+ }
+ break;
+ case ABILITY_SAND_STREAM:
+ //_08042BA8
+ if (!(gBattleWeather & WEATHER_SANDSTORM_PERMANENT))
+ {
+ gBattleWeather = (WEATHER_SANDSTORM_PERMANENT | WEATHER_SANDSTORM_TEMPORARY);
+ BattleScriptPushCursorAndCallback(BattleScript_SandstreamActivates);
+ gBattleScripting.bank = bank;
+ effect++;
+ }
+ break;
+ case ABILITY_DROUGHT:
+ //_08042BD8
+ if (!(gBattleWeather & WEATHER_SUN_PERMANENT))
+ {
+ gBattleWeather = (WEATHER_SUN_PERMANENT | WEATHER_SUN_TEMPORARY);
+ BattleScriptPushCursorAndCallback(BattleScript_DroughtActivates);
+ gBattleScripting.bank = bank;
+ effect++;
+ }
+ break;
+ case ABILITY_INTIMIDATE:
+ //_08042C08
+ if (!(gSpecialStatuses[bank].intimidatedPoke))
+ {
+ gStatuses3[bank] |= STATUS3_INTIMIDATE_POKES;
+ gSpecialStatuses[bank].intimidatedPoke = 1;
+ }
+ break;
+ case ABILITY_FORECAST:
+ //_08042C3C
+ effect = CastformDataTypeChange(bank);
+ if (effect != 0)
+ {
+ BattleScriptPushCursorAndCallback(BattleScript_CastformChange);
+ gBattleScripting.bank = bank;
+ gBattleStruct->formToChangeInto = effect - 1;
+ }
+ break;
+ case ABILITY_TRACE:
+ if (!(gSpecialStatuses[bank].traced))
+ {
+ gStatuses3[bank] |= STATUS3_TRACE;
+ gSpecialStatuses[bank].traced = 1;
+ }
+ break;
+ case ABILITY_CLOUD_NINE:
+ case ABILITY_AIR_LOCK:
+ {
+ u8 i;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ // TODO: i should be in r6 here
+ //asm("":::"r4","r5");
+ effect = CastformDataTypeChange(i);
+ if (effect != 0)
+ {
+ BattleScriptPushCursorAndCallback(BattleScript_CastformChange);
+ gBattleScripting.bank = i;
+ gBattleStruct->formToChangeInto = effect - 1;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case ABILITYEFFECT_ENDTURN: // 1
+ //_08042CDC
+ if (gBattleMons[bank].hp != 0)
+ {
+ gBankAttacker = bank;
+ switch (gLastUsedAbility)
+ {
+ case ABILITY_RAIN_DISH:
+ //_08042D22
+ if (WEATHER_HAS_EFFECT && (gBattleWeather & WEATHER_RAIN_ANY)
+ && gBattleMons[bank].maxHP > gBattleMons[bank].hp)
+ {
+ gLastUsedAbility = ABILITY_RAIN_DISH; //why
+ BattleScriptPushCursorAndCallback(BattleScript_RainDishActivates);
+ gBattleMoveDamage = gBattleMons[bank].maxHP / 16;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ gBattleMoveDamage *= -1;
+ effect++;
+ }
+ break;
+ case ABILITY_SHED_SKIN:
+ //_08042DA0
+ if ((gBattleMons[bank].status1 & STATUS_ANY) && (Random() % 3) == 0)
+ {
+ if (gBattleMons[bank].status1 & (STATUS_POISON | STATUS_TOXIC_POISON))
+ StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
+ if (gBattleMons[bank].status1 & STATUS_SLEEP)
+ StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
+ if (gBattleMons[bank].status1 & STATUS_PARALYSIS)
+ StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
+ if (gBattleMons[bank].status1 & STATUS_BURN)
+ StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn);
+ if (gBattleMons[bank].status1 & STATUS_FREEZE)
+ StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn);
+ gBattleMons[bank].status1 = 0;
+ gBattleMons[bank].status2 &= ~(STATUS2_NIGHTMARE); // fix nighmare glitch
+ gBattleScripting.bank = gActiveBank = bank;
+ BattleScriptPushCursorAndCallback(BattleScript_ShedSkinActivates);
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[bank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ effect++;
+ }
+ break;
+ case ABILITY_SPEED_BOOST:
+ //_08042E84
+ if (gBattleMons[bank].statStages[STAT_STAGE_SPEED] < 0xC && gDisableStructs[bank].isFirstTurn != 2)
+ {
+ gBattleMons[bank].statStages[STAT_STAGE_SPEED]++;
+ gBattleScripting.animArg1 = 0x11;
+ gBattleScripting.animArg2 = 0;
+ BattleScriptPushCursorAndCallback(BattleScript_SpeedBoostActivates);
+ gBattleScripting.bank = bank;
+ effect++;
+ }
+ break;
+ case ABILITY_TRUANT:
+ gDisableStructs[gBankAttacker].truantCounter ^= 1;
+ break;
+ }
+ }
+ break;
+ case ABILITYEFFECT_MOVES_BLOCK: // 2
+ //_08042EF8
+ if (gLastUsedAbility == ABILITY_SOUNDPROOF)
+ {
+ for (i = 0; gSoundMovesTable[i] != 0xFFFF; i++)
+ {
+ if (gSoundMovesTable[i] == move)
+ break;
+ }
+ if (gSoundMovesTable[i] != 0xFFFF)
+ {
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)
+ gHitMarker |= HITMARKER_NO_PPDEDUCT;
+ gBattlescriptCurrInstr = BattleScript_SoundproofProtected;
+ effect = 1;
+ }
+ }
+ break;
+ case ABILITYEFFECT_ABSORBING: // 3
+ if (move)
+ {
+ switch (gLastUsedAbility)
+ {
+ case ABILITY_VOLT_ABSORB:
+ if (moveType == TYPE_ELECTRIC && gBattleMoves[move].power != 0)
+ {
+ if (gProtectStructs[gBankAttacker].notFirstStrike)
+ gBattlescriptCurrInstr = BattleScript_MoveHPDrain;
+ else
+ gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss;
+ effect = 1;
+ }
+ break;
+ case ABILITY_WATER_ABSORB:
+ if (moveType == TYPE_WATER && gBattleMoves[move].power != 0)
+ {
+ if (gProtectStructs[gBankAttacker].notFirstStrike)
+ gBattlescriptCurrInstr = BattleScript_MoveHPDrain;
+ else
+ gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss;
+ effect = 1;
+ }
+ break;
+ case ABILITY_FLASH_FIRE:
+ //_0804305C
+ if (moveType == TYPE_FIRE && !(gBattleMons[bank].status1 & STATUS_FREEZE))
+ {
+ if (!(gBattleResources->flags->flags[bank] & UNKNOWN_FLAG_FLASH_FIRE))
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ if (gProtectStructs[gBankAttacker].notFirstStrike)
+ gBattlescriptCurrInstr = BattleScript_FlashFireBoost;
+ else
+ gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss;
+ gBattleResources->flags->flags[bank] |= UNKNOWN_FLAG_FLASH_FIRE;
+ effect = 2;
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ if (gProtectStructs[gBankAttacker].notFirstStrike)
+ gBattlescriptCurrInstr = BattleScript_FlashFireBoost;
+ else
+ gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss;
+ effect = 2;
+ }
+ }
+ break;
+ }
+ if (effect == 1)
+ {
+ if (gBattleMons[bank].maxHP == gBattleMons[bank].hp)
+ {
+ if ((gProtectStructs[gBankAttacker].notFirstStrike))
+ gBattlescriptCurrInstr = BattleScript_MoveHPDrain;
+ else
+ gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss;
+ }
+ else
+ {
+ gBattleMoveDamage = gBattleMons[bank].maxHP / 4;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ gBattleMoveDamage *= -1;
+ }
+ }
+ }
+ break;
+ case ABILITYEFFECT_CONTACT: // 4
+ //_080431AC
+ switch (gLastUsedAbility)
+ {
+ case ABILITY_COLOR_CHANGE:
+ //_08043288
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ && move != MOVE_STRUGGLE
+ && gBattleMoves[move].power != 0
+ && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special)
+ && gBattleMons[bank].type1 != moveType
+ && gBattleMons[bank].type2 != moveType
+ && gBattleMons[bank].hp != 0)
+ {
+ gBattleMons[bank].type1 = moveType;
+ gBattleMons[bank].type2 = moveType;
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 3;
+ gBattleTextBuff1[2] = moveType;
+ gBattleTextBuff1[3] = 0xFF;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_ColorChangeActivates;
+ effect++;
+ }
+ break;
+ case ABILITY_ROUGH_SKIN:
+ //_08043350
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ && gBattleMons[gBankAttacker].hp != 0
+ && !gProtectStructs[gBankAttacker].confusionSelfDmg
+ && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special)
+ && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT))
+ {
+ gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 16;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_RoughSkinActivates;
+ effect++;
+ }
+ break;
+ case ABILITY_EFFECT_SPORE:
+ //_08043410
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ && gBattleMons[gBankAttacker].hp != 0
+ && !gProtectStructs[gBankAttacker].confusionSelfDmg
+ && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special)
+ && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
+ && (Random() % 10) == 0)
+ {
+ do
+ {
+ gBattleCommunication[MOVE_EFFECT_BYTE] = Random() & 3;
+ } while (gBattleCommunication[MOVE_EFFECT_BYTE] == 0);
+ if (gBattleCommunication[MOVE_EFFECT_BYTE] == 3)
+ gBattleCommunication[MOVE_EFFECT_BYTE] += 2;
+ gBattleCommunication[MOVE_EFFECT_BYTE] += 0x40;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect;
+ gHitMarker |= HITMARKER_IGNORE_SAFEGUARD;
+ effect++;
+ }
+ break;
+ case ABILITY_POISON_POINT:
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ && gBattleMons[gBankAttacker].hp != 0
+ && !gProtectStructs[gBankAttacker].confusionSelfDmg
+ && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special)
+ && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
+ && (Random() % 3) == 0)
+ {
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0x42;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect;
+ gHitMarker |= HITMARKER_IGNORE_SAFEGUARD;
+ effect++;
+ }
+ break;
+ case ABILITY_STATIC:
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ && gBattleMons[gBankAttacker].hp != 0
+ && !gProtectStructs[gBankAttacker].confusionSelfDmg
+ && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special)
+ && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
+ && (Random() % 3) == 0)
+ {
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0x45;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect;
+ gHitMarker |= HITMARKER_IGNORE_SAFEGUARD;
+ effect++;
+ }
+ break;
+ case ABILITY_FLAME_BODY:
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ && gBattleMons[gBankAttacker].hp != 0
+ && !gProtectStructs[gBankAttacker].confusionSelfDmg
+ && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
+ && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special)
+ && (Random() % 3) == 0)
+ {
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0x43;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_ApplySecondaryEffect;
+ gHitMarker |= HITMARKER_IGNORE_SAFEGUARD;
+ effect++;
+ }
+ break;
+ case ABILITY_CUTE_CHARM:
+ //_0804379C
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ && gBattleMons[gBankAttacker].hp != 0
+ && !gProtectStructs[gBankAttacker].confusionSelfDmg
+ && (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
+ && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special)
+ && gBattleMons[gBankTarget].hp != 0
+ && (Random() % 3) == 0
+ && gBattleMons[gBankAttacker].ability != ABILITY_OBLIVIOUS
+ && GetGenderFromSpeciesAndPersonality(speciesAtk, pidAtk) != GetGenderFromSpeciesAndPersonality(speciesDef, pidDef)
+ && !(gBattleMons[gBankAttacker].status2 & STATUS2_INFATUATION)
+ && GetGenderFromSpeciesAndPersonality(speciesAtk, pidAtk) != 0xFF
+ && GetGenderFromSpeciesAndPersonality(speciesDef, pidDef) != 0xFF)
+ {
+ gBattleMons[gBankAttacker].status2 |= (gBitTable[gBankTarget] << 0x10);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_CuteCharmActivates;
+ effect++;
+ }
+ break;
+ }
+ break;
+ case ABILITYEFFECT_IMMUNITY: // 5
+ {
+ #define i bank
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ switch (gBattleMons[i].ability)
+ {
+ case ABILITY_IMMUNITY:
+ if (gBattleMons[i].status1 & (STATUS_POISON | STATUS_TOXIC_POISON | 0xF00)) // TODO: what is 0xF00?
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
+ effect = 1;
+ }
+ break;
+ case ABILITY_OWN_TEMPO:
+ //_08043A7C
+ if (gBattleMons[i].status2 & STATUS2_CONFUSION)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn);
+ effect = 2;
+ }
+ break;
+ case ABILITY_LIMBER:
+ if (gBattleMons[i].status1 & STATUS_PARALYSIS)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
+ effect = 1;
+ }
+ break;
+ case ABILITY_INSOMNIA:
+ case ABILITY_VITAL_SPIRIT:
+ if (gBattleMons[i].status1 & STATUS_SLEEP)
+ {
+ gBattleMons[i].status2 &= ~(STATUS2_NIGHTMARE);
+ StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
+ effect = 1;
+ }
+ break;
+ case ABILITY_WATER_VEIL:
+ if (gBattleMons[i].status1 & STATUS_BURN)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn);
+ effect = 1;
+ }
+ break;
+ case ABILITY_MAGMA_ARMOR:
+ if (gBattleMons[i].status1 & STATUS_FREEZE)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn);
+ effect = 1;
+ }
+ break;
+ case ABILITY_OBLIVIOUS:
+ //_08043B70
+ if (gBattleMons[i].status2 & STATUS2_INFATUATION)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn);
+ effect = 3;
+ }
+ break;
+ }
+ if (effect)
+ {
+ switch (effect)
+ {
+ case 1: // status cleared
+ gBattleMons[i].status1 = 0;
+ break;
+ case 2: // get rid of confusion
+ gBattleMons[i].status2 &= ~(STATUS2_CONFUSION);
+ break;
+ case 3: // get rid of infatuation
+ gBattleMons[i].status2 &= ~(STATUS2_INFATUATION);
+ break;
+ }
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = gUnknown_082DB68C;
+ gBattleScripting.bank = i;
+ gActiveBank = i;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ return effect;
+ }
+ }
+ #undef i
+ }
+ break;
+ case ABILITYEFFECT_FORECAST: // 6
+ {
+ #define i bank
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].ability == ABILITY_FORECAST)
+ {
+ effect = CastformDataTypeChange(i);
+ if (effect)
+ {
+ BattleScriptPushCursorAndCallback(BattleScript_CastformChange);
+ gBattleScripting.bank = i;
+ gBattleStruct->formToChangeInto = effect - 1;
+ return effect;
+ }
+ }
+ }
+ #undef i
+ }
+ break;
+ case ABILITYEFFECT_SYNCHRONIZE: // 7
+ //_08043CBC
+ if (gLastUsedAbility == ABILITY_SYNCHRONIZE && (gHitMarker & HITMARKER_SYNCHRONISE_EFFECT))
+ {
+ gHitMarker &= ~(HITMARKER_SYNCHRONISE_EFFECT);
+ gBattleStruct->synchronizeMoveEffect &= 0x3F;
+ if (gBattleStruct->synchronizeMoveEffect == 6)
+ gBattleStruct->synchronizeMoveEffect = 2;
+ gBattleCommunication[MOVE_EFFECT_BYTE] = gBattleStruct->synchronizeMoveEffect + 0x40;
+ gBattleScripting.bank = gBankTarget;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_SynchronizeActivates;
+ gHitMarker |= HITMARKER_IGNORE_SAFEGUARD;
+ effect++;
+ }
+ break;
+ case ABILITYEFFECT_ATK_SYNCHRONIZE: // 8
+ if (gLastUsedAbility == ABILITY_SYNCHRONIZE && (gHitMarker & HITMARKER_SYNCHRONISE_EFFECT))
+ {
+ gHitMarker &= ~(HITMARKER_SYNCHRONISE_EFFECT);
+ gBattleStruct->synchronizeMoveEffect &= 0x3F;
+ if (gBattleStruct->synchronizeMoveEffect == 6)
+ gBattleStruct->synchronizeMoveEffect = 2;
+ gBattleCommunication[MOVE_EFFECT_BYTE] = gBattleStruct->synchronizeMoveEffect;
+ gBattleScripting.bank = gBankAttacker;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_SynchronizeActivates;
+ gHitMarker |= HITMARKER_IGNORE_SAFEGUARD;
+ effect++;
+ }
+ break;
+ case ABILITYEFFECT_INTIMIDATE1: // 9
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].ability == ABILITY_INTIMIDATE && gStatuses3[i] & STATUS3_INTIMIDATE_POKES)
+ {
+ gLastUsedAbility = ABILITY_INTIMIDATE;
+ gStatuses3[i] &= ~(STATUS3_INTIMIDATE_POKES);
+ BattleScriptPushCursorAndCallback(gUnknown_082DB4B8);
+ gBattleStruct->intimidateBank = i;
+ effect++;
+ break;
+ }
+ }
+ break;
+ case ABILITYEFFECT_TRACE: // 11
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].ability == ABILITY_TRACE && (gStatuses3[i] & STATUS3_TRACE))
+ {
+ u8 opposite = (GetBankIdentity(i) ^ 1) & 1;
+ u8 target1 = GetBankByIdentity(opposite);
+ u8 target2 = GetBankByIdentity(opposite + 2);
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ {
+ if (gBattleMons[target1].ability != 0 && gBattleMons[target1].hp != 0
+ && gBattleMons[target2].ability != 0 && gBattleMons[target2].hp != 0)
+ {
+ gActiveBank = GetBankByIdentity(((Random() & 1) * 2) | opposite);
+ gBattleMons[i].ability = gBattleMons[gActiveBank].ability;
+ gLastUsedAbility = gBattleMons[gActiveBank].ability;
+ effect++;
+ }
+ else if (gBattleMons[target1].ability != 0 && gBattleMons[target1].hp != 0)
+ {
+ gActiveBank = target1;
+ gBattleMons[i].ability = gBattleMons[gActiveBank].ability;
+ gLastUsedAbility = gBattleMons[gActiveBank].ability;
+ effect++;
+ }
+ else if (gBattleMons[target2].ability != 0 && gBattleMons[target2].hp != 0)
+ {
+ gActiveBank = target2;
+ gBattleMons[i].ability = gBattleMons[gActiveBank].ability;
+ gLastUsedAbility = gBattleMons[gActiveBank].ability;
+ effect++;
+ }
+ }
+ else
+ {
+ gActiveBank = target1;
+ if (gBattleMons[target1].ability && gBattleMons[target1].hp)
+ {
+ gBattleMons[i].ability = gBattleMons[target1].ability;
+ gLastUsedAbility = gBattleMons[target1].ability;
+ effect++;
+ }
+ }
+ if (effect)
+ {
+ BattleScriptPushCursorAndCallback(BattleScript_TraceActivates);
+ gStatuses3[i] &= ~(STATUS3_TRACE);
+ gBattleScripting.bank = i;
+
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 4;
+ gBattleTextBuff1[2] = gActiveBank;
+ gBattleTextBuff1[3] = gBattlePartyID[gActiveBank];
+ gBattleTextBuff1[4] = EOS;
+
+ gBattleTextBuff2[0] = 0xFD;
+ gBattleTextBuff2[1] = 9;
+ gBattleTextBuff2[2] = gLastUsedAbility;
+ gBattleTextBuff2[3] = EOS;
+ break;
+ }
+ }
+ }
+ break;
+ case ABILITYEFFECT_INTIMIDATE2: // 10
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].ability == ABILITY_INTIMIDATE && (gStatuses3[i] & STATUS3_INTIMIDATE_POKES))
+ {
+ gLastUsedAbility = ABILITY_INTIMIDATE;
+ gStatuses3[i] &= ~(STATUS3_INTIMIDATE_POKES);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = gUnknown_082DB4C1;
+ gBattleStruct->intimidateBank = i;
+ effect++;
+ break;
+ }
+ }
+ break;
+ case ABILITYEFFECT_CHECK_OTHER_SIDE: // 12
+ side = GetBankSide(bank);
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (GetBankSide(i) != side && gBattleMons[i].ability == ability)
+ {
+ gLastUsedAbility = ability;
+ effect = i + 1;
+ }
+ }
+ break;
+ case ABILITYEFFECT_CHECK_BANK_SIDE: // 13
+ side = GetBankSide(bank);
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (GetBankSide(i) == side && gBattleMons[i].ability == ability)
+ {
+ gLastUsedAbility = ability;
+ effect = i + 1;
+ }
+ }
+ break;
+ case ABILITYEFFECT_FIELD_SPORT: // 14
+ switch (gLastUsedAbility)
+ {
+ case 0xFD:
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gStatuses3[i] & STATUS3_MUDSPORT)
+ effect = i + 1;
+ }
+ break;
+ case 0xFE:
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gStatuses3[i] & STATUS3_WATERSPORT)
+ effect = i + 1;
+ }
+ break;
+ default:
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].ability == ability)
+ {
+ gLastUsedAbility = ability;
+ effect = i + 1;
+ }
+ }
+ break;
+ }
+ break;
+ case ABILITYEFFECT_CHECK_ON_FIELD: // 19
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].ability == ability && gBattleMons[i].hp != 0)
+ {
+ gLastUsedAbility = ability;
+ effect = i + 1;
+ }
+ }
+ break;
+ case ABILITYEFFECT_CHECK_FIELD_EXCEPT_BANK: // 15
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].ability == ability && i != bank)
+ {
+ gLastUsedAbility = ability;
+ effect = i + 1;
+ }
+ }
+ break;
+ case ABILITYEFFECT_COUNT_OTHER_SIDE: // 16
+ side = GetBankSide(bank);
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (GetBankSide(i) != side && gBattleMons[i].ability == ability)
+ {
+ gLastUsedAbility = ability;
+ effect++;
+ }
+ }
+ break;
+ case ABILITYEFFECT_COUNT_BANK_SIDE: // 17
+ side = GetBankSide(bank);
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (GetBankSide(i) == side && gBattleMons[i].ability == ability)
+ {
+ gLastUsedAbility = ability;
+ effect++;
+ }
+ }
+ break;
+ case ABILITYEFFECT_COUNT_ON_FIELD: // 18
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].ability == ability && i != bank)
+ {
+ gLastUsedAbility = ability;
+ effect++;
+ }
+ }
+ break;
+ }
+ if (effect && caseID < 0xC && gLastUsedAbility != 0xFF)
+ RecordAbilityBattle(bank, gLastUsedAbility);
+ }
+
+ return effect;
+}
+#else
+__attribute__((naked))
+u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg)
+{
+ asm(
+ "\n\
+ .syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ sub sp, 0x28\n\
+ ldr r4, [sp, 0x48]\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ str r0, [sp, 0x4]\n\
+ lsls r1, 24\n\
+ lsrs r1, 24\n\
+ mov r10, r1\n\
+ lsls r2, 24\n\
+ lsrs r6, r2, 24\n\
+ lsls r3, 24\n\
+ lsrs r3, 24\n\
+ mov r8, r3\n\
+ lsls r4, 16\n\
+ lsrs r4, 16\n\
+ movs r0, 0\n\
+ mov r9, r0\n\
+ ldr r5, =gBankAttacker\n\
+ ldr r1, =gNoOfAllBanks\n\
+ ldrb r0, [r5]\n\
+ ldrb r1, [r1]\n\
+ cmp r0, r1\n\
+ bcc _08042864\n\
+ mov r1, r10\n\
+ strb r1, [r5]\n\
+_08042864:\n\
+ ldrb r0, [r5]\n\
+ bl GetBankSide\n\
+ lsls r0, 24\n\
+ cmp r0, 0\n\
+ bne _08042894\n\
+ ldr r1, =gBattlePartyID\n\
+ ldrb r0, [r5]\n\
+ lsls r0, 1\n\
+ adds r0, r1\n\
+ ldrh r1, [r0]\n\
+ movs r0, 0x64\n\
+ muls r1, r0\n\
+ ldr r0, =gPlayerParty\n\
+ b _080428A4\n\
+ .pool\n\
+_08042894:\n\
+ ldr r1, =gBattlePartyID\n\
+ ldrb r0, [r5]\n\
+ lsls r0, 1\n\
+ adds r0, r1\n\
+ ldrh r1, [r0]\n\
+ movs r0, 0x64\n\
+ muls r1, r0\n\
+ ldr r0, =gEnemyParty\n\
+_080428A4:\n\
+ adds r7, r1, r0\n\
+ ldr r5, =gBankTarget\n\
+ ldr r1, =gNoOfAllBanks\n\
+ ldrb r0, [r5]\n\
+ ldrb r1, [r1]\n\
+ cmp r0, r1\n\
+ bcc _080428B6\n\
+ mov r2, r10\n\
+ strb r2, [r5]\n\
+_080428B6:\n\
+ ldrb r0, [r5]\n\
+ bl GetBankSide\n\
+ lsls r0, 24\n\
+ cmp r0, 0\n\
+ bne _080428E8\n\
+ ldr r1, =gBattlePartyID\n\
+ ldrb r0, [r5]\n\
+ lsls r0, 1\n\
+ adds r0, r1\n\
+ ldrh r1, [r0]\n\
+ movs r0, 0x64\n\
+ muls r1, r0\n\
+ ldr r0, =gPlayerParty\n\
+ b _080428F8\n\
+ .pool\n\
+_080428E8:\n\
+ ldr r1, =gBattlePartyID\n\
+ ldrb r0, [r5]\n\
+ lsls r0, 1\n\
+ adds r0, r1\n\
+ ldrh r1, [r0]\n\
+ movs r0, 0x64\n\
+ muls r1, r0\n\
+ ldr r0, =gEnemyParty\n\
+_080428F8:\n\
+ adds r5, r1, r0\n\
+ adds r0, r7, 0\n\
+ movs r1, 0xB\n\
+ bl GetMonData\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ str r0, [sp, 0x8]\n\
+ adds r0, r7, 0\n\
+ movs r1, 0\n\
+ bl GetMonData\n\
+ str r0, [sp, 0x10]\n\
+ adds r0, r5, 0\n\
+ movs r1, 0xB\n\
+ bl GetMonData\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ str r0, [sp, 0xC]\n\
+ adds r0, r5, 0\n\
+ movs r1, 0\n\
+ bl GetMonData\n\
+ str r0, [sp, 0x14]\n\
+ ldr r0, =gBattleTypeFlags\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x80\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0804293A\n\
+ bl _0804443A\n\
+_0804293A:\n\
+ mov r3, r8\n\
+ cmp r3, 0\n\
+ beq _08042958\n\
+ ldr r0, =gLastUsedAbility\n\
+ strb r3, [r0]\n\
+ adds r7, r0, 0\n\
+ b _0804296E\n\
+ .pool\n\
+_08042958:\n\
+ ldr r2, =gLastUsedAbility\n\
+ ldr r1, =gBattleMons\n\
+ movs r0, 0x58\n\
+ mov r5, r10\n\
+ muls r5, r0\n\
+ adds r0, r5, 0\n\
+ adds r0, r1\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ strb r0, [r2]\n\
+ adds r7, r2, 0\n\
+_0804296E:\n\
+ cmp r4, 0\n\
+ beq _08042980\n\
+ adds r5, r4, 0\n\
+ b _08042984\n\
+ .pool\n\
+_08042980:\n\
+ ldr r0, =gCurrentMove\n\
+ ldrh r5, [r0]\n\
+_08042984:\n\
+ ldr r1, =gBattleStruct\n\
+ ldr r0, [r1]\n\
+ ldrb r0, [r0, 0x13]\n\
+ mov r8, r1\n\
+ cmp r0, 0\n\
+ beq _080429A0\n\
+ movs r3, 0x3F\n\
+ ands r3, r0\n\
+ b _080429AC\n\
+ .pool\n\
+_080429A0:\n\
+ ldr r1, =gBattleMoves\n\
+ lsls r0, r5, 1\n\
+ adds r0, r5\n\
+ lsls r0, 2\n\
+ adds r0, r1\n\
+ ldrb r3, [r0, 0x2]\n\
+_080429AC:\n\
+ ldr r0, [sp, 0x4]\n\
+ cmp r0, 0x13\n\
+ bls _080429B6\n\
+ bl _0804441E\n\
+_080429B6:\n\
+ lsls r0, 2\n\
+ ldr r1, =_080429C8\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ mov pc, r0\n\
+ .pool\n\
+ .align 2, 0\n\
+_080429C8:\n\
+ .4byte _08042A18\n\
+ .4byte _08042CDC\n\
+ .4byte _08042EF8\n\
+ .4byte _08042F8C\n\
+ .4byte _080431AC\n\
+ .4byte _08043908\n\
+ .4byte _08043C6C\n\
+ .4byte _08043CBC\n\
+ .4byte _08043D40\n\
+ .4byte _08043DC4\n\
+ .4byte _08043FE4\n\
+ .4byte _08043E08\n\
+ .4byte _08044028\n\
+ .4byte _08044084\n\
+ .4byte _080440E0\n\
+ .4byte _080441DC\n\
+ .4byte _08044220\n\
+ .4byte _0804427C\n\
+ .4byte _080443EC\n\
+ .4byte _08044196\n\
+_08042A18:\n\
+ ldr r2, =gBankAttacker\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r1, [r2]\n\
+ adds r5, r0, 0\n\
+ ldrb r3, [r5]\n\
+ cmp r1, r3\n\
+ bcc _08042A2A\n\
+ mov r0, r10\n\
+ strb r0, [r2]\n\
+_08042A2A:\n\
+ ldrb r0, [r7]\n\
+ cmp r0, 0x2D\n\
+ bne _08042A32\n\
+ b _08042BA8\n\
+_08042A32:\n\
+ cmp r0, 0x2D\n\
+ bgt _08042A64\n\
+ cmp r0, 0xD\n\
+ bne _08042A3C\n\
+ b _08042CA4\n\
+_08042A3C:\n\
+ cmp r0, 0xD\n\
+ bgt _08042A54\n\
+ cmp r0, 0x2\n\
+ bne _08042A46\n\
+ b _08042B78\n\
+_08042A46:\n\
+ bl _0804441E\n\
+ .pool\n\
+_08042A54:\n\
+ cmp r0, 0x16\n\
+ bne _08042A5A\n\
+ b _08042C08\n\
+_08042A5A:\n\
+ cmp r0, 0x24\n\
+ bne _08042A60\n\
+ b _08042C68\n\
+_08042A60:\n\
+ bl _0804441E\n\
+_08042A64:\n\
+ cmp r0, 0x46\n\
+ bne _08042A6A\n\
+ b _08042BD8\n\
+_08042A6A:\n\
+ cmp r0, 0x46\n\
+ bgt _08042A78\n\
+ cmp r0, 0x3B\n\
+ bne _08042A74\n\
+ b _08042C3C\n\
+_08042A74:\n\
+ bl _0804441E\n\
+_08042A78:\n\
+ cmp r0, 0x4D\n\
+ bne _08042A7E\n\
+ b _08042CA4\n\
+_08042A7E:\n\
+ cmp r0, 0xFF\n\
+ beq _08042A86\n\
+ bl _0804441E\n\
+_08042A86:\n\
+ ldr r0, =gBattleTypeFlags\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x80\n\
+ lsls r1, 17\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08042B4C\n\
+ bl weather_get_current\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ subs r0, 0x3\n\
+ cmp r0, 0xA\n\
+ bhi _08042B4C\n\
+ lsls r0, 2\n\
+ ldr r1, =_08042AB4\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ mov pc, r0\n\
+ .pool\n\
+ .align 2, 0\n\
+_08042AB4:\n\
+ .4byte _08042AE0\n\
+ .4byte _08042B4C\n\
+ .4byte _08042AE0\n\
+ .4byte _08042B4C\n\
+ .4byte _08042B4C\n\
+ .4byte _08042B04\n\
+ .4byte _08042B4C\n\
+ .4byte _08042B4C\n\
+ .4byte _08042B4C\n\
+ .4byte _08042B28\n\
+ .4byte _08042AE0\n\
+_08042AE0:\n\
+ ldr r2, =gBattleWeather\n\
+ ldrh r1, [r2]\n\
+ movs r0, 0x7\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08042B4C\n\
+ movs r0, 0x5\n\
+ strh r0, [r2]\n\
+ ldr r1, =gBattleScripting\n\
+ movs r0, 0xA\n\
+ strb r0, [r1, 0x10]\n\
+ mov r2, r10\n\
+ strb r2, [r1, 0x17]\n\
+ b _08042B42\n\
+ .pool\n\
+_08042B04:\n\
+ ldr r3, =gBattleWeather\n\
+ ldrh r1, [r3]\n\
+ movs r2, 0x18\n\
+ adds r0, r2, 0\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08042B4C\n\
+ strh r2, [r3]\n\
+ ldr r1, =gBattleScripting\n\
+ movs r0, 0xC\n\
+ strb r0, [r1, 0x10]\n\
+ mov r3, r10\n\
+ strb r3, [r1, 0x17]\n\
+ b _08042B42\n\
+ .pool\n\
+_08042B28:\n\
+ ldr r3, =gBattleWeather\n\
+ ldrh r1, [r3]\n\
+ movs r2, 0x60\n\
+ adds r0, r2, 0\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08042B4C\n\
+ strh r2, [r3]\n\
+ ldr r1, =gBattleScripting\n\
+ movs r0, 0xB\n\
+ strb r0, [r1, 0x10]\n\
+ mov r5, r10\n\
+ strb r5, [r1, 0x17]\n\
+_08042B42:\n\
+ mov r0, r9\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_08042B4C:\n\
+ mov r0, r9\n\
+ cmp r0, 0\n\
+ bne _08042B56\n\
+ bl _0804443A\n\
+_08042B56:\n\
+ bl weather_get_current\n\
+ ldr r1, =gBattleCommunication\n\
+ strb r0, [r1, 0x5]\n\
+ ldr r0, =gUnknown_082DACE7\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ bl _0804441E\n\
+ .pool\n\
+_08042B78:\n\
+ ldr r2, =gBattleWeather\n\
+ ldrh r1, [r2]\n\
+ movs r0, 0x4\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08042B88\n\
+ bl _0804441E\n\
+_08042B88:\n\
+ movs r0, 0x5\n\
+ strh r0, [r2]\n\
+ ldr r0, =BattleScript_DrizzleActivates\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ ldr r0, =gBattleScripting\n\
+ mov r1, r10\n\
+ strb r1, [r0, 0x17]\n\
+ bl _080443D0\n\
+ .pool\n\
+_08042BA8:\n\
+ ldr r2, =gBattleWeather\n\
+ ldrh r1, [r2]\n\
+ movs r0, 0x10\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08042BB8\n\
+ bl _0804441E\n\
+_08042BB8:\n\
+ movs r0, 0x18\n\
+ strh r0, [r2]\n\
+ ldr r0, =BattleScript_SandstreamActivates\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ ldr r0, =gBattleScripting\n\
+ mov r2, r10\n\
+ strb r2, [r0, 0x17]\n\
+ bl _080443D0\n\
+ .pool\n\
+_08042BD8:\n\
+ ldr r2, =gBattleWeather\n\
+ ldrh r1, [r2]\n\
+ movs r0, 0x40\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08042BE8\n\
+ bl _0804441E\n\
+_08042BE8:\n\
+ movs r0, 0x60\n\
+ strh r0, [r2]\n\
+ ldr r0, =BattleScript_DroughtActivates\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ ldr r0, =gBattleScripting\n\
+ mov r3, r10\n\
+ strb r3, [r0, 0x17]\n\
+ bl _080443D0\n\
+ .pool\n\
+_08042C08:\n\
+ ldr r0, =gSpecialStatuses\n\
+ mov r5, r10\n\
+ lsls r2, r5, 2\n\
+ adds r1, r2, r5\n\
+ lsls r1, 2\n\
+ adds r3, r1, r0\n\
+ ldrb r0, [r3]\n\
+ lsls r0, 28\n\
+ cmp r0, 0\n\
+ bge _08042C20\n\
+ bl _0804441E\n\
+_08042C20:\n\
+ ldr r1, =gStatuses3\n\
+ adds r1, r2, r1\n\
+ ldr r0, [r1]\n\
+ movs r2, 0x80\n\
+ lsls r2, 12\n\
+ orrs r0, r2\n\
+ str r0, [r1]\n\
+ ldrb r0, [r3]\n\
+ movs r1, 0x8\n\
+ b _08042C92\n\
+ .pool\n\
+_08042C3C:\n\
+ mov r0, r10\n\
+ bl CastformDataTypeChange\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+ cmp r0, 0\n\
+ bne _08042C50\n\
+ bl _0804443A\n\
+_08042C50:\n\
+ ldr r0, =BattleScript_CastformChange\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ ldr r0, =gBattleScripting\n\
+ mov r1, r10\n\
+ strb r1, [r0, 0x17]\n\
+ bl _080442E2\n\
+ .pool\n\
+_08042C68:\n\
+ ldr r0, =gSpecialStatuses\n\
+ mov r3, r10\n\
+ lsls r2, r3, 2\n\
+ adds r1, r2, r3\n\
+ lsls r1, 2\n\
+ adds r3, r1, r0\n\
+ ldrb r0, [r3]\n\
+ lsls r0, 27\n\
+ cmp r0, 0\n\
+ bge _08042C80\n\
+ bl _0804441E\n\
+_08042C80:\n\
+ ldr r1, =gStatuses3\n\
+ adds r1, r2, r1\n\
+ ldr r0, [r1]\n\
+ movs r2, 0x80\n\
+ lsls r2, 13\n\
+ orrs r0, r2\n\
+ str r0, [r1]\n\
+ ldrb r0, [r3]\n\
+ movs r1, 0x10\n\
+_08042C92:\n\
+ orrs r0, r1\n\
+ strb r0, [r3]\n\
+ bl _0804441E\n\
+ .pool\n\
+_08042CA4:\n\
+ movs r6, 0\n\
+ ldrb r5, [r5]\n\
+ cmp r6, r5\n\
+ bcc _08042CB0\n\
+ bl _0804441E\n\
+_08042CB0:\n\
+ adds r0, r6, 0\n\
+ bl CastformDataTypeChange\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+ cmp r0, 0\n\
+ beq _08042CC4\n\
+ bl _080442D8\n\
+_08042CC4:\n\
+ adds r0, r6, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r6, r0, 24\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r6, r0\n\
+ bcc _08042CB0\n\
+ bl _0804441E\n\
+ .pool\n\
+_08042CDC:\n\
+ ldr r5, =gBattleMons\n\
+ mov r8, r5\n\
+ movs r0, 0x58\n\
+ mov r6, r10\n\
+ muls r6, r0\n\
+ adds r4, r6, r5\n\
+ ldrh r0, [r4, 0x28]\n\
+ cmp r0, 0\n\
+ bne _08042CF2\n\
+ bl _0804441E\n\
+_08042CF2:\n\
+ ldr r0, =gBankAttacker\n\
+ mov r1, r10\n\
+ strb r1, [r0]\n\
+ ldrb r5, [r7]\n\
+ cmp r5, 0x2C\n\
+ beq _08042D22\n\
+ cmp r5, 0x2C\n\
+ bgt _08042D14\n\
+ cmp r5, 0x3\n\
+ bne _08042D08\n\
+ b _08042E84\n\
+_08042D08:\n\
+ bl _0804441E\n\
+ .pool\n\
+_08042D14:\n\
+ cmp r5, 0x36\n\
+ bne _08042D1A\n\
+ b _08042ED0\n\
+_08042D1A:\n\
+ cmp r5, 0x3D\n\
+ beq _08042DA0\n\
+ bl _0804441E\n\
+_08042D22:\n\
+ movs r0, 0\n\
+ str r0, [sp]\n\
+ movs r0, 0x13\n\
+ movs r1, 0\n\
+ movs r2, 0xD\n\
+ movs r3, 0\n\
+ bl AbilityBattleEffects\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ cmp r0, 0\n\
+ beq _08042D3E\n\
+ bl _0804441E\n\
+_08042D3E:\n\
+ str r0, [sp]\n\
+ movs r0, 0x13\n\
+ movs r1, 0\n\
+ movs r2, 0x4D\n\
+ movs r3, 0\n\
+ bl AbilityBattleEffects\n\
+ lsls r0, 24\n\
+ cmp r0, 0\n\
+ beq _08042D56\n\
+ bl _0804441E\n\
+_08042D56:\n\
+ ldr r0, =gBattleWeather\n\
+ ldrh r1, [r0]\n\
+ movs r0, 0x7\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08042D66\n\
+ bl _0804441E\n\
+_08042D66:\n\
+ ldrh r0, [r4, 0x2C]\n\
+ ldrh r2, [r4, 0x28]\n\
+ cmp r0, r2\n\
+ bhi _08042D72\n\
+ bl _0804441E\n\
+_08042D72:\n\
+ strb r5, [r7]\n\
+ ldr r0, =BattleScript_RainDishActivates\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ ldr r1, =gBattleMoveDamage\n\
+ ldrh r0, [r4, 0x2C]\n\
+ lsrs r0, 4\n\
+ str r0, [r1]\n\
+ cmp r0, 0\n\
+ bne _08042D8A\n\
+ movs r0, 0x1\n\
+ str r0, [r1]\n\
+_08042D8A:\n\
+ ldr r0, [r1]\n\
+ negs r0, r0\n\
+ str r0, [r1]\n\
+ bl _080443D0\n\
+ .pool\n\
+_08042DA0:\n\
+ mov r0, r8\n\
+ adds r0, 0x4C\n\
+ adds r5, r6, r0\n\
+ ldrb r0, [r5]\n\
+ cmp r0, 0\n\
+ bne _08042DB0\n\
+ bl _0804441E\n\
+_08042DB0:\n\
+ bl Random\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ movs r1, 0x3\n\
+ bl __umodsi3\n\
+ lsls r0, 16\n\
+ lsrs r4, r0, 16\n\
+ cmp r4, 0\n\
+ beq _08042DCA\n\
+ bl _0804441E\n\
+_08042DCA:\n\
+ ldr r0, [r5]\n\
+ movs r1, 0x88\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08042DDC\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_PoisonJpn\n\
+ bl StringCopy\n\
+_08042DDC:\n\
+ ldr r0, [r5]\n\
+ movs r1, 0x7\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08042DEE\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_SleepJpn\n\
+ bl StringCopy\n\
+_08042DEE:\n\
+ ldr r0, [r5]\n\
+ movs r1, 0x40\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08042E00\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_ParalysisJpn\n\
+ bl StringCopy\n\
+_08042E00:\n\
+ ldr r0, [r5]\n\
+ movs r1, 0x10\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08042E12\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_BurnJpn\n\
+ bl StringCopy\n\
+_08042E12:\n\
+ ldr r0, [r5]\n\
+ movs r1, 0x20\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08042E24\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_IceJpn\n\
+ bl StringCopy\n\
+_08042E24:\n\
+ str r4, [r5]\n\
+ mov r1, r8\n\
+ adds r1, 0x50\n\
+ adds r1, r6, r1\n\
+ ldr r0, [r1]\n\
+ ldr r2, =0xf7ffffff\n\
+ ands r0, r2\n\
+ str r0, [r1]\n\
+ ldr r0, =gBattleScripting\n\
+ ldr r4, =gActiveBank\n\
+ mov r3, r10\n\
+ strb r3, [r4]\n\
+ strb r3, [r0, 0x17]\n\
+ ldr r0, =BattleScript_ShedSkinActivates\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ str r5, [sp]\n\
+ movs r0, 0\n\
+ movs r1, 0x28\n\
+ movs r2, 0\n\
+ movs r3, 0x4\n\
+ bl EmitSetMonData\n\
+ ldrb r0, [r4]\n\
+ bl MarkBufferBankForExecution\n\
+ bl _080443D0\n\
+ .pool\n\
+_08042E84:\n\
+ ldrb r2, [r4, 0x1B]\n\
+ movs r0, 0x1B\n\
+ ldrsb r0, [r4, r0]\n\
+ cmp r0, 0xB\n\
+ ble _08042E92\n\
+ bl _0804441E\n\
+_08042E92:\n\
+ ldr r0, =gDisableStructs\n\
+ mov r5, r10\n\
+ lsls r1, r5, 3\n\
+ subs r1, r5\n\
+ lsls r1, 2\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x16]\n\
+ cmp r0, 0x2\n\
+ bne _08042EA8\n\
+ bl _0804441E\n\
+_08042EA8:\n\
+ adds r0, r2, 0x1\n\
+ movs r1, 0\n\
+ strb r0, [r4, 0x1B]\n\
+ ldr r4, =gBattleScripting\n\
+ movs r0, 0x11\n\
+ strb r0, [r4, 0x10]\n\
+ strb r1, [r4, 0x11]\n\
+ ldr r0, =BattleScript_SpeedBoostActivates\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ strb r5, [r4, 0x17]\n\
+ bl _080443D0\n\
+ .pool\n\
+_08042ED0:\n\
+ ldr r2, =gDisableStructs\n\
+ ldrb r0, [r0]\n\
+ lsls r1, r0, 3\n\
+ subs r1, r0\n\
+ lsls r1, 2\n\
+ adds r1, r2\n\
+ ldrb r3, [r1, 0x18]\n\
+ lsls r0, r3, 31\n\
+ lsrs r0, 31\n\
+ movs r2, 0x1\n\
+ eors r2, r0\n\
+ movs r0, 0x2\n\
+ negs r0, r0\n\
+ ands r0, r3\n\
+ orrs r0, r2\n\
+ strb r0, [r1, 0x18]\n\
+ bl _0804441E\n\
+ .pool\n\
+_08042EF8:\n\
+ ldrb r0, [r7]\n\
+ cmp r0, 0x2B\n\
+ beq _08042F02\n\
+ bl _0804441E\n\
+_08042F02:\n\
+ movs r4, 0\n\
+ ldr r0, =gSoundMovesTable\n\
+ ldrh r2, [r0]\n\
+ ldr r3, =0x0000ffff\n\
+ adds r1, r0, 0\n\
+ cmp r2, r3\n\
+ bne _08042F14\n\
+ bl _0804441E\n\
+_08042F14:\n\
+ cmp r2, r5\n\
+ beq _08042F2C\n\
+ adds r2, r1, 0\n\
+_08042F1A:\n\
+ adds r2, 0x2\n\
+ adds r4, 0x1\n\
+ ldrh r0, [r2]\n\
+ cmp r0, r3\n\
+ bne _08042F28\n\
+ bl _0804441E\n\
+_08042F28:\n\
+ cmp r0, r5\n\
+ bne _08042F1A\n\
+_08042F2C:\n\
+ lsls r0, r4, 1\n\
+ adds r0, r1\n\
+ ldrh r1, [r0]\n\
+ ldr r0, =0x0000ffff\n\
+ cmp r1, r0\n\
+ bne _08042F3C\n\
+ bl _0804441E\n\
+_08042F3C:\n\
+ ldr r1, =gBattleMons\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r2, [r0]\n\
+ movs r0, 0x58\n\
+ muls r0, r2\n\
+ adds r1, 0x50\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x80\n\
+ lsls r1, 5\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08042F62\n\
+ ldr r0, =gHitMarker\n\
+ ldr r1, [r0]\n\
+ movs r2, 0x80\n\
+ lsls r2, 4\n\
+ orrs r1, r2\n\
+ str r1, [r0]\n\
+_08042F62:\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_SoundproofProtected\n\
+ str r0, [r1]\n\
+ movs r0, 0x1\n\
+ mov r9, r0\n\
+ bl _08044424\n\
+ .pool\n\
+_08042F8C:\n\
+ cmp r5, 0\n\
+ bne _08042F94\n\
+ bl _0804441E\n\
+_08042F94:\n\
+ ldrb r0, [r7]\n\
+ cmp r0, 0xB\n\
+ beq _08043004\n\
+ cmp r0, 0xB\n\
+ bgt _08042FA4\n\
+ cmp r0, 0xA\n\
+ beq _08042FAA\n\
+ b _08043126\n\
+_08042FA4:\n\
+ cmp r0, 0x12\n\
+ beq _0804305C\n\
+ b _08043126\n\
+_08042FAA:\n\
+ cmp r3, 0xD\n\
+ beq _08042FB0\n\
+ b _08043126\n\
+_08042FB0:\n\
+ ldr r0, =gBattleMoves\n\
+ lsls r1, r5, 1\n\
+ adds r1, r5\n\
+ lsls r1, 2\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x1]\n\
+ cmp r0, 0\n\
+ bne _08042FC2\n\
+ b _08043126\n\
+_08042FC2:\n\
+ ldr r1, =gProtectStructs\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r0, [r0]\n\
+ lsls r0, 4\n\
+ adds r0, r1\n\
+ ldrb r0, [r0, 0x2]\n\
+ lsls r0, 28\n\
+ cmp r0, 0\n\
+ bge _08042FF0\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_MoveHPDrain\n\
+ b _08042FF4\n\
+ .pool\n\
+_08042FF0:\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_MoveHPDrain_PPLoss\n\
+_08042FF4:\n\
+ str r0, [r1]\n\
+ movs r1, 0x1\n\
+ b _08043124\n\
+ .pool\n\
+_08043004:\n\
+ cmp r3, 0xB\n\
+ beq _0804300A\n\
+ b _08043126\n\
+_0804300A:\n\
+ ldr r0, =gBattleMoves\n\
+ lsls r1, r5, 1\n\
+ adds r1, r5\n\
+ lsls r1, 2\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x1]\n\
+ cmp r0, 0\n\
+ bne _0804301C\n\
+ b _08043126\n\
+_0804301C:\n\
+ ldr r1, =gProtectStructs\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r0, [r0]\n\
+ lsls r0, 4\n\
+ adds r0, r1\n\
+ ldrb r0, [r0, 0x2]\n\
+ lsls r0, 28\n\
+ cmp r0, 0\n\
+ bge _08043048\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_MoveHPDrain\n\
+ b _0804304C\n\
+ .pool\n\
+_08043048:\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_MoveHPDrain_PPLoss\n\
+_0804304C:\n\
+ str r0, [r1]\n\
+ movs r2, 0x1\n\
+ mov r9, r2\n\
+ b _08043126\n\
+ .pool\n\
+_0804305C:\n\
+ cmp r3, 0xA\n\
+ bne _08043126\n\
+ ldr r1, =gBattleMons\n\
+ movs r0, 0x58\n\
+ mov r3, r10\n\
+ muls r3, r0\n\
+ adds r0, r3, 0\n\
+ adds r1, 0x4C\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x20\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08043126\n\
+ ldr r2, =gBattleResources\n\
+ ldr r0, [r2]\n\
+ ldr r0, [r0, 0x4]\n\
+ mov r5, r10\n\
+ lsls r1, r5, 2\n\
+ adds r0, r1\n\
+ ldr r3, [r0]\n\
+ movs r4, 0x1\n\
+ ands r3, r4\n\
+ adds r5, r1, 0\n\
+ cmp r3, 0\n\
+ bne _080430EC\n\
+ ldr r0, =gBattleCommunication\n\
+ strb r3, [r0, 0x5]\n\
+ ldr r1, =gProtectStructs\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r0, [r0]\n\
+ lsls r0, 4\n\
+ adds r0, r1\n\
+ ldrb r0, [r0, 0x2]\n\
+ lsls r0, 28\n\
+ cmp r0, 0\n\
+ bge _080430C8\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_FlashFireBoost\n\
+ b _080430CC\n\
+ .pool\n\
+_080430C8:\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_FlashFireBoost_PPLoss\n\
+_080430CC:\n\
+ str r0, [r1]\n\
+ ldr r0, [r2]\n\
+ ldr r1, [r0, 0x4]\n\
+ adds r1, r5\n\
+ ldr r0, [r1]\n\
+ movs r2, 0x1\n\
+ orrs r0, r2\n\
+ str r0, [r1]\n\
+ movs r0, 0x2\n\
+ mov r9, r0\n\
+ b _08043126\n\
+ .pool\n\
+_080430EC:\n\
+ ldr r0, =gBattleCommunication\n\
+ strb r4, [r0, 0x5]\n\
+ ldr r1, =gProtectStructs\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r0, [r0]\n\
+ lsls r0, 4\n\
+ adds r0, r1\n\
+ ldrb r0, [r0, 0x2]\n\
+ lsls r0, 28\n\
+ cmp r0, 0\n\
+ bge _0804311C\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_FlashFireBoost\n\
+ b _08043120\n\
+ .pool\n\
+_0804311C:\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_FlashFireBoost_PPLoss\n\
+_08043120:\n\
+ str r0, [r1]\n\
+ movs r1, 0x2\n\
+_08043124:\n\
+ mov r9, r1\n\
+_08043126:\n\
+ mov r2, r9\n\
+ cmp r2, 0x1\n\
+ beq _08043130\n\
+ bl _0804441E\n\
+_08043130:\n\
+ ldr r1, =gBattleMons\n\
+ movs r0, 0x58\n\
+ mov r3, r10\n\
+ muls r3, r0\n\
+ adds r0, r3, 0\n\
+ adds r1, r0, r1\n\
+ ldrh r0, [r1, 0x2C]\n\
+ ldrh r5, [r1, 0x28]\n\
+ cmp r0, r5\n\
+ bne _0804318C\n\
+ ldr r1, =gProtectStructs\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r0, [r0]\n\
+ lsls r0, 4\n\
+ adds r0, r1\n\
+ ldrb r0, [r0, 0x2]\n\
+ lsls r0, 28\n\
+ cmp r0, 0\n\
+ bge _08043178\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =gUnknown_082DB592\n\
+ str r0, [r1]\n\
+ bl _0804441E\n\
+ .pool\n\
+_08043178:\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =gUnknown_082DB591\n\
+ str r0, [r1]\n\
+ bl _0804441E\n\
+ .pool\n\
+_0804318C:\n\
+ ldr r2, =gBattleMoveDamage\n\
+ ldrh r0, [r1, 0x2C]\n\
+ lsrs r0, 2\n\
+ str r0, [r2]\n\
+ cmp r0, 0\n\
+ bne _0804319C\n\
+ mov r0, r9\n\
+ str r0, [r2]\n\
+_0804319C:\n\
+ ldr r0, [r2]\n\
+ negs r0, r0\n\
+ str r0, [r2]\n\
+ bl _0804441E\n\
+ .pool\n\
+_080431AC:\n\
+ ldrb r0, [r7]\n\
+ subs r0, 0x9\n\
+ cmp r0, 0x2F\n\
+ bls _080431B8\n\
+ bl _0804441E\n\
+_080431B8:\n\
+ lsls r0, 2\n\
+ ldr r1, =_080431C8\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ mov pc, r0\n\
+ .pool\n\
+ .align 2, 0\n\
+_080431C8:\n\
+ .4byte _080435E4\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _08043288\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _08043350\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _08043410\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _08043508\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _080436C0\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804441E\n\
+ .4byte _0804379C\n\
+_08043288:\n\
+ ldr r0, =gBattleMoveFlags\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x29\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08043298\n\
+ bl _0804441E\n\
+_08043298:\n\
+ cmp r5, 0xA5\n\
+ bne _080432A0\n\
+ bl _0804441E\n\
+_080432A0:\n\
+ ldr r0, =gBattleMoves\n\
+ lsls r1, r5, 1\n\
+ adds r1, r5\n\
+ lsls r1, 2\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x1]\n\
+ cmp r0, 0\n\
+ bne _080432B4\n\
+ bl _0804441E\n\
+_080432B4:\n\
+ ldr r2, =gSpecialStatuses\n\
+ ldr r0, =gBankTarget\n\
+ ldrb r1, [r0]\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ lsls r1, r0, 2\n\
+ adds r0, r2, 0\n\
+ adds r0, 0x8\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _080432DC\n\
+ adds r0, r2, 0\n\
+ adds r0, 0xC\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _080432DC\n\
+ bl _0804441E\n\
+_080432DC:\n\
+ ldr r1, =gBattleMons\n\
+ movs r0, 0x58\n\
+ mov r2, r10\n\
+ muls r2, r0\n\
+ adds r0, r2, 0\n\
+ adds r1, r0, r1\n\
+ adds r4, r1, 0\n\
+ adds r4, 0x21\n\
+ ldrb r0, [r4]\n\
+ cmp r0, r3\n\
+ bne _080432F6\n\
+ bl _0804441E\n\
+_080432F6:\n\
+ adds r2, r1, 0\n\
+ adds r2, 0x22\n\
+ ldrb r0, [r2]\n\
+ cmp r0, r3\n\
+ bne _08043304\n\
+ bl _0804441E\n\
+_08043304:\n\
+ ldrh r0, [r1, 0x28]\n\
+ cmp r0, 0\n\
+ bne _0804330E\n\
+ bl _0804441E\n\
+_0804330E:\n\
+ strb r3, [r4]\n\
+ strb r3, [r2]\n\
+ ldr r1, =gBattleTextBuff1\n\
+ movs r0, 0xFD\n\
+ strb r0, [r1]\n\
+ movs r0, 0x3\n\
+ strb r0, [r1, 0x1]\n\
+ strb r3, [r1, 0x2]\n\
+ movs r0, 0xFF\n\
+ strb r0, [r1, 0x3]\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_ColorChangeActivates\n\
+ str r0, [r1]\n\
+ bl _080443D0\n\
+ .pool\n\
+_08043350:\n\
+ ldr r0, =gBattleMoveFlags\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x29\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08043360\n\
+ bl _0804441E\n\
+_08043360:\n\
+ ldr r1, =gBattleMons\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r2, [r0]\n\
+ movs r0, 0x58\n\
+ muls r0, r2\n\
+ adds r3, r0, r1\n\
+ ldrh r0, [r3, 0x28]\n\
+ cmp r0, 0\n\
+ bne _08043376\n\
+ bl _0804441E\n\
+_08043376:\n\
+ ldr r0, =gProtectStructs\n\
+ lsls r1, r2, 4\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x1]\n\
+ lsls r0, 31\n\
+ cmp r0, 0\n\
+ beq _08043388\n\
+ bl _0804441E\n\
+_08043388:\n\
+ ldr r2, =gSpecialStatuses\n\
+ ldr r0, =gBankTarget\n\
+ ldrb r1, [r0]\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ lsls r1, r0, 2\n\
+ adds r0, r2, 0\n\
+ adds r0, 0x8\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _080433B0\n\
+ adds r0, r2, 0\n\
+ adds r0, 0xC\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _080433B0\n\
+ bl _0804441E\n\
+_080433B0:\n\
+ ldr r1, =gBattleMoves\n\
+ lsls r0, r5, 1\n\
+ adds r0, r5\n\
+ lsls r0, 2\n\
+ adds r0, r1\n\
+ ldrb r1, [r0, 0x8]\n\
+ movs r2, 0x1\n\
+ adds r0, r2, 0\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _080433CA\n\
+ bl _0804441E\n\
+_080433CA:\n\
+ ldr r1, =gBattleMoveDamage\n\
+ ldrh r0, [r3, 0x2C]\n\
+ lsrs r0, 4\n\
+ str r0, [r1]\n\
+ cmp r0, 0\n\
+ bne _080433D8\n\
+ str r2, [r1]\n\
+_080433D8:\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_RoughSkinActivates\n\
+ str r0, [r1]\n\
+ bl _080443D0\n\
+ .pool\n\
+_08043410:\n\
+ ldr r0, =gBattleMoveFlags\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x29\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08043420\n\
+ bl _0804441E\n\
+_08043420:\n\
+ ldr r1, =gBattleMons\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r2, [r0]\n\
+ movs r0, 0x58\n\
+ muls r0, r2\n\
+ adds r0, r1\n\
+ ldrh r0, [r0, 0x28]\n\
+ cmp r0, 0\n\
+ bne _08043436\n\
+ bl _0804441E\n\
+_08043436:\n\
+ ldr r0, =gProtectStructs\n\
+ lsls r1, r2, 4\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x1]\n\
+ lsls r0, 31\n\
+ cmp r0, 0\n\
+ beq _08043448\n\
+ bl _0804441E\n\
+_08043448:\n\
+ ldr r2, =gSpecialStatuses\n\
+ ldr r0, =gBankTarget\n\
+ ldrb r1, [r0]\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ lsls r1, r0, 2\n\
+ adds r0, r2, 0\n\
+ adds r0, 0x8\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _08043470\n\
+ adds r0, r2, 0\n\
+ adds r0, 0xC\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _08043470\n\
+ bl _0804441E\n\
+_08043470:\n\
+ ldr r1, =gBattleMoves\n\
+ lsls r0, r5, 1\n\
+ adds r0, r5\n\
+ lsls r0, 2\n\
+ adds r0, r1\n\
+ ldrb r1, [r0, 0x8]\n\
+ movs r0, 0x1\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08043488\n\
+ bl _0804441E\n\
+_08043488:\n\
+ bl Random\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ movs r1, 0xA\n\
+ bl __umodsi3\n\
+ lsls r0, 16\n\
+ cmp r0, 0\n\
+ beq _080434A0\n\
+ bl _0804441E\n\
+_080434A0:\n\
+ ldr r5, =gBattleCommunication\n\
+ movs r4, 0x3\n\
+_080434A4:\n\
+ bl Random\n\
+ ands r0, r4\n\
+ strb r0, [r5, 0x3]\n\
+ cmp r0, 0\n\
+ beq _080434A4\n\
+ ldr r1, =gBattleCommunication\n\
+ ldrb r0, [r1, 0x3]\n\
+ cmp r0, 0x3\n\
+ bne _080434BC\n\
+ adds r0, 0x2\n\
+ strb r0, [r1, 0x3]\n\
+_080434BC:\n\
+ ldrb r0, [r1, 0x3]\n\
+ adds r0, 0x40\n\
+ strb r0, [r1, 0x3]\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_ApplySecondaryEffect\n\
+ str r0, [r1]\n\
+ ldr r2, =gHitMarker\n\
+ ldr r0, [r2]\n\
+ movs r1, 0x80\n\
+ lsls r1, 6\n\
+ orrs r0, r1\n\
+ str r0, [r2]\n\
+ bl _080443D0\n\
+ .pool\n\
+_08043508:\n\
+ ldr r0, =gBattleMoveFlags\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x29\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08043518\n\
+ bl _0804441E\n\
+_08043518:\n\
+ ldr r1, =gBattleMons\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r2, [r0]\n\
+ movs r0, 0x58\n\
+ muls r0, r2\n\
+ adds r0, r1\n\
+ ldrh r0, [r0, 0x28]\n\
+ cmp r0, 0\n\
+ bne _0804352E\n\
+ bl _0804441E\n\
+_0804352E:\n\
+ ldr r0, =gProtectStructs\n\
+ lsls r1, r2, 4\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x1]\n\
+ lsls r0, 31\n\
+ cmp r0, 0\n\
+ beq _08043540\n\
+ bl _0804441E\n\
+_08043540:\n\
+ ldr r2, =gSpecialStatuses\n\
+ ldr r0, =gBankTarget\n\
+ ldrb r1, [r0]\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ lsls r1, r0, 2\n\
+ adds r0, r2, 0\n\
+ adds r0, 0x8\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _08043568\n\
+ adds r0, r2, 0\n\
+ adds r0, 0xC\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _08043568\n\
+ bl _0804441E\n\
+_08043568:\n\
+ ldr r1, =gBattleMoves\n\
+ lsls r0, r5, 1\n\
+ adds r0, r5\n\
+ lsls r0, 2\n\
+ adds r0, r1\n\
+ ldrb r1, [r0, 0x8]\n\
+ movs r0, 0x1\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08043580\n\
+ bl _0804441E\n\
+_08043580:\n\
+ bl Random\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ movs r1, 0x3\n\
+ bl __umodsi3\n\
+ lsls r0, 16\n\
+ cmp r0, 0\n\
+ beq _08043598\n\
+ bl _0804441E\n\
+_08043598:\n\
+ ldr r1, =gBattleCommunication\n\
+ movs r0, 0x42\n\
+ strb r0, [r1, 0x3]\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_ApplySecondaryEffect\n\
+ str r0, [r1]\n\
+ ldr r2, =gHitMarker\n\
+ ldr r0, [r2]\n\
+ movs r1, 0x80\n\
+ lsls r1, 6\n\
+ orrs r0, r1\n\
+ str r0, [r2]\n\
+ bl _080443D0\n\
+ .pool\n\
+_080435E4:\n\
+ ldr r0, =gBattleMoveFlags\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x29\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _080435F4\n\
+ bl _0804441E\n\
+_080435F4:\n\
+ ldr r1, =gBattleMons\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r2, [r0]\n\
+ movs r0, 0x58\n\
+ muls r0, r2\n\
+ adds r0, r1\n\
+ ldrh r0, [r0, 0x28]\n\
+ cmp r0, 0\n\
+ bne _0804360A\n\
+ bl _0804441E\n\
+_0804360A:\n\
+ ldr r0, =gProtectStructs\n\
+ lsls r1, r2, 4\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x1]\n\
+ lsls r0, 31\n\
+ cmp r0, 0\n\
+ beq _0804361C\n\
+ bl _0804441E\n\
+_0804361C:\n\
+ ldr r2, =gSpecialStatuses\n\
+ ldr r0, =gBankTarget\n\
+ ldrb r1, [r0]\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ lsls r1, r0, 2\n\
+ adds r0, r2, 0\n\
+ adds r0, 0x8\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _08043644\n\
+ adds r0, r2, 0\n\
+ adds r0, 0xC\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _08043644\n\
+ bl _0804441E\n\
+_08043644:\n\
+ ldr r1, =gBattleMoves\n\
+ lsls r0, r5, 1\n\
+ adds r0, r5\n\
+ lsls r0, 2\n\
+ adds r0, r1\n\
+ ldrb r1, [r0, 0x8]\n\
+ movs r0, 0x1\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _0804365C\n\
+ bl _0804441E\n\
+_0804365C:\n\
+ bl Random\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ movs r1, 0x3\n\
+ bl __umodsi3\n\
+ lsls r0, 16\n\
+ cmp r0, 0\n\
+ beq _08043674\n\
+ bl _0804441E\n\
+_08043674:\n\
+ ldr r1, =gBattleCommunication\n\
+ movs r0, 0x45\n\
+ strb r0, [r1, 0x3]\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_ApplySecondaryEffect\n\
+ str r0, [r1]\n\
+ ldr r2, =gHitMarker\n\
+ ldr r0, [r2]\n\
+ movs r1, 0x80\n\
+ lsls r1, 6\n\
+ orrs r0, r1\n\
+ str r0, [r2]\n\
+ bl _080443D0\n\
+ .pool\n\
+_080436C0:\n\
+ ldr r0, =gBattleMoveFlags\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x29\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _080436D0\n\
+ bl _0804441E\n\
+_080436D0:\n\
+ ldr r1, =gBattleMons\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r2, [r0]\n\
+ movs r0, 0x58\n\
+ muls r0, r2\n\
+ adds r0, r1\n\
+ ldrh r0, [r0, 0x28]\n\
+ cmp r0, 0\n\
+ bne _080436E6\n\
+ bl _0804441E\n\
+_080436E6:\n\
+ ldr r0, =gProtectStructs\n\
+ lsls r1, r2, 4\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x1]\n\
+ lsls r0, 31\n\
+ cmp r0, 0\n\
+ beq _080436F8\n\
+ bl _0804441E\n\
+_080436F8:\n\
+ ldr r1, =gBattleMoves\n\
+ lsls r0, r5, 1\n\
+ adds r0, r5\n\
+ lsls r0, 2\n\
+ adds r0, r1\n\
+ ldrb r1, [r0, 0x8]\n\
+ movs r0, 0x1\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08043710\n\
+ bl _0804441E\n\
+_08043710:\n\
+ ldr r2, =gSpecialStatuses\n\
+ ldr r0, =gBankTarget\n\
+ ldrb r1, [r0]\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ lsls r1, r0, 2\n\
+ adds r0, r2, 0\n\
+ adds r0, 0x8\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _08043738\n\
+ adds r0, r2, 0\n\
+ adds r0, 0xC\n\
+ adds r0, r1, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _08043738\n\
+ bl _0804441E\n\
+_08043738:\n\
+ bl Random\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ movs r1, 0x3\n\
+ bl __umodsi3\n\
+ lsls r0, 16\n\
+ cmp r0, 0\n\
+ beq _08043750\n\
+ bl _0804441E\n\
+_08043750:\n\
+ ldr r1, =gBattleCommunication\n\
+ movs r0, 0x43\n\
+ strb r0, [r1, 0x3]\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_ApplySecondaryEffect\n\
+ str r0, [r1]\n\
+ ldr r2, =gHitMarker\n\
+ ldr r0, [r2]\n\
+ movs r1, 0x80\n\
+ lsls r1, 6\n\
+ orrs r0, r1\n\
+ str r0, [r2]\n\
+ bl _080443D0\n\
+ .pool\n\
+_0804379C:\n\
+ ldr r0, =gBattleMoveFlags\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x29\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _080437AC\n\
+ bl _0804441E\n\
+_080437AC:\n\
+ ldr r6, =gBattleMons\n\
+ ldr r3, =gBankAttacker\n\
+ mov r8, r3\n\
+ ldrb r1, [r3]\n\
+ movs r7, 0x58\n\
+ adds r0, r1, 0\n\
+ muls r0, r7\n\
+ adds r0, r6\n\
+ ldrh r0, [r0, 0x28]\n\
+ cmp r0, 0\n\
+ bne _080437C6\n\
+ bl _0804441E\n\
+_080437C6:\n\
+ ldr r0, =gProtectStructs\n\
+ lsls r1, 4\n\
+ adds r1, r0\n\
+ ldrb r0, [r1, 0x1]\n\
+ lsls r0, 31\n\
+ cmp r0, 0\n\
+ beq _080437D8\n\
+ bl _0804441E\n\
+_080437D8:\n\
+ ldr r1, =gBattleMoves\n\
+ lsls r0, r5, 1\n\
+ adds r0, r5\n\
+ lsls r0, 2\n\
+ adds r0, r1\n\
+ ldrb r1, [r0, 0x8]\n\
+ movs r0, 0x1\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _080437F0\n\
+ bl _0804441E\n\
+_080437F0:\n\
+ ldr r3, =gSpecialStatuses\n\
+ ldr r5, =gBankTarget\n\
+ ldrb r1, [r5]\n\
+ lsls r0, r1, 2\n\
+ adds r0, r1\n\
+ lsls r2, r0, 2\n\
+ adds r0, r3, 0\n\
+ adds r0, 0x8\n\
+ adds r0, r2, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _08043818\n\
+ adds r0, r3, 0\n\
+ adds r0, 0xC\n\
+ adds r0, r2, r0\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ bne _08043818\n\
+ bl _0804441E\n\
+_08043818:\n\
+ adds r0, r1, 0\n\
+ muls r0, r7\n\
+ adds r0, r6\n\
+ ldrh r0, [r0, 0x28]\n\
+ cmp r0, 0\n\
+ bne _08043828\n\
+ bl _0804441E\n\
+_08043828:\n\
+ bl Random\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ movs r1, 0x3\n\
+ bl __umodsi3\n\
+ lsls r0, 16\n\
+ cmp r0, 0\n\
+ beq _08043840\n\
+ bl _0804441E\n\
+_08043840:\n\
+ mov r1, r8\n\
+ ldrb r0, [r1]\n\
+ muls r0, r7\n\
+ adds r0, r6\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, 0xC\n\
+ bne _08043854\n\
+ bl _0804441E\n\
+_08043854:\n\
+ ldr r0, [sp, 0x8]\n\
+ ldr r1, [sp, 0x10]\n\
+ bl GetGenderFromSpeciesAndPersonality\n\
+ adds r4, r0, 0\n\
+ ldr r0, [sp, 0xC]\n\
+ ldr r1, [sp, 0x14]\n\
+ bl GetGenderFromSpeciesAndPersonality\n\
+ lsls r4, 24\n\
+ lsls r0, 24\n\
+ cmp r4, r0\n\
+ bne _08043872\n\
+ bl _0804441E\n\
+_08043872:\n\
+ mov r2, r8\n\
+ ldrb r0, [r2]\n\
+ muls r0, r7\n\
+ adds r4, r6, 0\n\
+ adds r4, 0x50\n\
+ adds r0, r4\n\
+ ldr r0, [r0]\n\
+ movs r1, 0xF0\n\
+ lsls r1, 12\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0804388E\n\
+ bl _0804441E\n\
+_0804388E:\n\
+ ldr r0, [sp, 0x8]\n\
+ ldr r1, [sp, 0x10]\n\
+ bl GetGenderFromSpeciesAndPersonality\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ cmp r0, 0xFF\n\
+ bne _080438A2\n\
+ bl _0804441E\n\
+_080438A2:\n\
+ ldr r0, [sp, 0xC]\n\
+ ldr r1, [sp, 0x14]\n\
+ bl GetGenderFromSpeciesAndPersonality\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ cmp r0, 0xFF\n\
+ bne _080438B6\n\
+ bl _0804441E\n\
+_080438B6:\n\
+ mov r3, r8\n\
+ ldrb r0, [r3]\n\
+ adds r2, r0, 0\n\
+ muls r2, r7\n\
+ adds r2, r4\n\
+ ldr r1, =gBitTable\n\
+ ldrb r0, [r5]\n\
+ lsls r0, 2\n\
+ adds r0, r1\n\
+ ldr r1, [r0]\n\
+ lsls r1, 16\n\
+ ldr r0, [r2]\n\
+ orrs r0, r1\n\
+ str r0, [r2]\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_CuteCharmActivates\n\
+ str r0, [r1]\n\
+ bl _080443D0\n\
+ .pool\n\
+_08043908:\n\
+ movs r5, 0\n\
+ mov r10, r5\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r10, r0\n\
+ bcc _08043918\n\
+ bl _0804441E\n\
+_08043918:\n\
+ ldr r1, =gBattleMons\n\
+ movs r0, 0x58\n\
+ mov r2, r10\n\
+ muls r2, r0\n\
+ adds r0, r2, 0\n\
+ adds r0, r1\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ subs r0, 0x7\n\
+ adds r2, r1, 0\n\
+ cmp r0, 0x41\n\
+ bls _08043932\n\
+ b _08043B96\n\
+_08043932:\n\
+ lsls r0, 2\n\
+ ldr r1, =_08043948\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ mov pc, r0\n\
+ .pool\n\
+ .align 2, 0\n\
+_08043948:\n\
+ .4byte _08043AAC\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B70\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043AD4\n\
+ .4byte _08043B96\n\
+ .4byte _08043A50\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043A7C\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B40\n\
+ .4byte _08043B10\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043B96\n\
+ .4byte _08043AD4\n\
+_08043A50:\n\
+ movs r0, 0x58\n\
+ mov r3, r10\n\
+ muls r3, r0\n\
+ adds r0, r3, 0\n\
+ adds r1, r2, 0\n\
+ adds r1, 0x4C\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ ldr r1, =0x00000f88\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08043A6A\n\
+ b _08043B96\n\
+_08043A6A:\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_PoisonJpn\n\
+ b _08043B5C\n\
+ .pool\n\
+_08043A7C:\n\
+ movs r0, 0x58\n\
+ mov r1, r10\n\
+ muls r1, r0\n\
+ adds r0, r1, 0\n\
+ adds r1, r2, 0\n\
+ adds r1, 0x50\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x7\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08043A96\n\
+ b _08043B96\n\
+_08043A96:\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_ConfusionJpn\n\
+ bl StringCopy\n\
+ movs r2, 0x2\n\
+ mov r9, r2\n\
+ b _08043B9C\n\
+ .pool\n\
+_08043AAC:\n\
+ movs r0, 0x58\n\
+ mov r3, r10\n\
+ muls r3, r0\n\
+ adds r0, r3, 0\n\
+ adds r1, r2, 0\n\
+ adds r1, 0x4C\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x40\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08043B96\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_ParalysisJpn\n\
+ b _08043B5C\n\
+ .pool\n\
+_08043AD4:\n\
+ movs r0, 0x58\n\
+ mov r3, r10\n\
+ muls r3, r0\n\
+ adds r0, r2, 0\n\
+ adds r0, 0x4C\n\
+ adds r0, r3, r0\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x7\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08043B96\n\
+ adds r2, 0x50\n\
+ adds r2, r3, r2\n\
+ ldr r0, [r2]\n\
+ ldr r1, =0xf7ffffff\n\
+ ands r0, r1\n\
+ str r0, [r2]\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_SleepJpn\n\
+ bl StringCopy\n\
+ movs r0, 0x1\n\
+ mov r9, r0\n\
+ b _08043B9C\n\
+ .pool\n\
+_08043B10:\n\
+ movs r0, 0x58\n\
+ mov r1, r10\n\
+ muls r1, r0\n\
+ adds r0, r1, 0\n\
+ adds r1, r2, 0\n\
+ adds r1, 0x4C\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x10\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08043B96\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_BurnJpn\n\
+ bl StringCopy\n\
+ movs r2, 0x1\n\
+ mov r9, r2\n\
+ b _08043B9C\n\
+ .pool\n\
+_08043B40:\n\
+ movs r0, 0x58\n\
+ mov r3, r10\n\
+ muls r3, r0\n\
+ adds r0, r3, 0\n\
+ adds r1, r2, 0\n\
+ adds r1, 0x4C\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x20\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08043B96\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_IceJpn\n\
+_08043B5C:\n\
+ bl StringCopy\n\
+ movs r5, 0x1\n\
+ mov r9, r5\n\
+ b _08043B9C\n\
+ .pool\n\
+_08043B70:\n\
+ movs r0, 0x58\n\
+ mov r1, r10\n\
+ muls r1, r0\n\
+ adds r0, r1, 0\n\
+ adds r1, r2, 0\n\
+ adds r1, 0x50\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ movs r1, 0xF0\n\
+ lsls r1, 12\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08043B96\n\
+ ldr r0, =gBattleTextBuff1\n\
+ ldr r1, =gStatusConditionString_LoveJpn\n\
+ bl StringCopy\n\
+ movs r2, 0x3\n\
+ mov r9, r2\n\
+_08043B96:\n\
+ mov r3, r9\n\
+ cmp r3, 0\n\
+ beq _08043C50\n\
+_08043B9C:\n\
+ mov r5, r9\n\
+ cmp r5, 0x2\n\
+ beq _08043BD0\n\
+ cmp r5, 0x2\n\
+ bgt _08043BB4\n\
+ cmp r5, 0x1\n\
+ beq _08043BBC\n\
+ b _08043BFC\n\
+ .pool\n\
+_08043BB4:\n\
+ mov r0, r9\n\
+ cmp r0, 0x3\n\
+ beq _08043BE8\n\
+ b _08043BFC\n\
+_08043BBC:\n\
+ ldr r1, =gBattleMons\n\
+ movs r0, 0x58\n\
+ mov r2, r10\n\
+ muls r2, r0\n\
+ adds r1, 0x4C\n\
+ adds r2, r1\n\
+ movs r0, 0\n\
+ b _08043BFA\n\
+ .pool\n\
+_08043BD0:\n\
+ ldr r1, =gBattleMons\n\
+ movs r0, 0x58\n\
+ mov r2, r10\n\
+ muls r2, r0\n\
+ adds r1, 0x50\n\
+ adds r2, r1\n\
+ ldr r0, [r2]\n\
+ movs r1, 0x8\n\
+ negs r1, r1\n\
+ b _08043BF8\n\
+ .pool\n\
+_08043BE8:\n\
+ ldr r1, =gBattleMons\n\
+ movs r0, 0x58\n\
+ mov r2, r10\n\
+ muls r2, r0\n\
+ adds r1, 0x50\n\
+ adds r2, r1\n\
+ ldr r0, [r2]\n\
+ ldr r1, =0xfff0ffff\n\
+_08043BF8:\n\
+ ands r0, r1\n\
+_08043BFA:\n\
+ str r0, [r2]\n\
+_08043BFC:\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =gUnknown_082DB68C\n\
+ str r0, [r1]\n\
+ ldr r0, =gBattleScripting\n\
+ mov r1, r10\n\
+ strb r1, [r0, 0x17]\n\
+ ldr r4, =gActiveBank\n\
+ strb r1, [r4]\n\
+ ldrb r1, [r4]\n\
+ movs r0, 0x58\n\
+ muls r0, r1\n\
+ ldr r1, =gBattleMons + 0x4C\n\
+ adds r0, r1\n\
+ str r0, [sp]\n\
+ movs r0, 0\n\
+ movs r1, 0x28\n\
+ movs r2, 0\n\
+ movs r3, 0x4\n\
+ bl EmitSetMonData\n\
+ ldrb r0, [r4]\n\
+ bl MarkBufferBankForExecution\n\
+ bl _0804443A\n\
+ .pool\n\
+_08043C50:\n\
+ mov r0, r10\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r10, r0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r10, r0\n\
+ bcs _08043C64\n\
+ b _08043918\n\
+_08043C64:\n\
+ bl _0804441E\n\
+ .pool\n\
+_08043C6C:\n\
+ movs r2, 0\n\
+ mov r10, r2\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r10, r0\n\
+ bcc _08043C7A\n\
+ b _0804441E\n\
+_08043C7A:\n\
+ ldr r4, =gBattleMons\n\
+_08043C7C:\n\
+ movs r0, 0x58\n\
+ mov r3, r10\n\
+ muls r3, r0\n\
+ adds r0, r3, 0\n\
+ adds r0, r4\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, 0x3B\n\
+ bne _08043CA0\n\
+ mov r0, r10\n\
+ bl CastformDataTypeChange\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+ cmp r0, 0\n\
+ beq _08043CA0\n\
+ b _080442FC\n\
+_08043CA0:\n\
+ mov r0, r10\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r10, r0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r10, r0\n\
+ bcc _08043C7C\n\
+ b _0804441E\n\
+ .pool\n\
+_08043CBC:\n\
+ ldrb r0, [r7]\n\
+ cmp r0, 0x1C\n\
+ beq _08043CC4\n\
+ b _0804441E\n\
+_08043CC4:\n\
+ ldr r4, =gHitMarker\n\
+ ldr r1, [r4]\n\
+ movs r0, 0x80\n\
+ lsls r0, 7\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08043CD4\n\
+ b _0804441E\n\
+_08043CD4:\n\
+ ldr r0, =0xffffbfff\n\
+ ands r1, r0\n\
+ str r1, [r4]\n\
+ mov r5, r8\n\
+ ldr r1, [r5]\n\
+ adds r1, 0xB2\n\
+ ldrb r2, [r1]\n\
+ movs r0, 0x3F\n\
+ ands r0, r2\n\
+ strb r0, [r1]\n\
+ ldr r0, [r5]\n\
+ adds r1, r0, 0\n\
+ adds r1, 0xB2\n\
+ ldrb r0, [r1]\n\
+ cmp r0, 0x6\n\
+ bne _08043CF8\n\
+ movs r0, 0x2\n\
+ strb r0, [r1]\n\
+_08043CF8:\n\
+ ldr r1, =gBattleCommunication\n\
+ mov r2, r8\n\
+ ldr r0, [r2]\n\
+ adds r0, 0xB2\n\
+ ldrb r0, [r0]\n\
+ adds r0, 0x40\n\
+ strb r0, [r1, 0x3]\n\
+ ldr r1, =gBattleScripting\n\
+ ldr r0, =gBankTarget\n\
+ ldrb r0, [r0]\n\
+ strb r0, [r1, 0x17]\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_SynchronizeActivates\n\
+ str r0, [r1]\n\
+ ldr r0, [r4]\n\
+ movs r1, 0x80\n\
+ lsls r1, 6\n\
+ orrs r0, r1\n\
+ str r0, [r4]\n\
+ b _080443D0\n\
+ .pool\n\
+_08043D40:\n\
+ ldrb r0, [r7]\n\
+ cmp r0, 0x1C\n\
+ beq _08043D48\n\
+ b _0804441E\n\
+_08043D48:\n\
+ ldr r4, =gHitMarker\n\
+ ldr r1, [r4]\n\
+ movs r0, 0x80\n\
+ lsls r0, 7\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _08043D58\n\
+ b _0804441E\n\
+_08043D58:\n\
+ ldr r0, =0xffffbfff\n\
+ ands r1, r0\n\
+ str r1, [r4]\n\
+ mov r3, r8\n\
+ ldr r1, [r3]\n\
+ adds r1, 0xB2\n\
+ ldrb r2, [r1]\n\
+ movs r0, 0x3F\n\
+ ands r0, r2\n\
+ strb r0, [r1]\n\
+ ldr r0, [r3]\n\
+ adds r1, r0, 0\n\
+ adds r1, 0xB2\n\
+ ldrb r0, [r1]\n\
+ cmp r0, 0x6\n\
+ bne _08043D7C\n\
+ movs r0, 0x2\n\
+ strb r0, [r1]\n\
+_08043D7C:\n\
+ ldr r1, =gBattleCommunication\n\
+ mov r3, r8\n\
+ ldr r0, [r3]\n\
+ adds r0, 0xB2\n\
+ ldrb r0, [r0]\n\
+ strb r0, [r1, 0x3]\n\
+ ldr r1, =gBattleScripting\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r0, [r0]\n\
+ strb r0, [r1, 0x17]\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =BattleScript_SynchronizeActivates\n\
+ str r0, [r1]\n\
+ ldr r0, [r4]\n\
+ movs r1, 0x80\n\
+ lsls r1, 6\n\
+ orrs r0, r1\n\
+ str r0, [r4]\n\
+ b _080443D0\n\
+ .pool\n\
+_08043DC4:\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r1, [r0]\n\
+ cmp r4, r1\n\
+ blt _08043DD0\n\
+ b _0804441E\n\
+_08043DD0:\n\
+ ldr r0, =gBattleMons\n\
+ adds r5, r1, 0\n\
+ ldr r2, =gStatuses3\n\
+ adds r3, r0, 0\n\
+ adds r3, 0x20\n\
+ movs r6, 0x80\n\
+ lsls r6, 12\n\
+_08043DDE:\n\
+ ldrb r1, [r3]\n\
+ cmp r1, 0x16\n\
+ bne _08043DEE\n\
+ ldr r0, [r2]\n\
+ ands r0, r6\n\
+ cmp r0, 0\n\
+ beq _08043DEE\n\
+ b _08044324\n\
+_08043DEE:\n\
+ adds r2, 0x4\n\
+ adds r3, 0x58\n\
+ adds r4, 0x1\n\
+ cmp r4, r5\n\
+ blt _08043DDE\n\
+ b _0804441E\n\
+ .pool\n\
+_08043E08:\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _08043E14\n\
+ b _0804441E\n\
+_08043E14:\n\
+ ldr r5, =gActiveBank\n\
+ mov r8, r5\n\
+ ldr r0, =gBattleMons\n\
+ adds r0, 0x20\n\
+ str r0, [sp, 0x1C]\n\
+ movs r1, 0\n\
+ str r1, [sp, 0x20]\n\
+_08043E22:\n\
+ ldr r2, [sp, 0x1C]\n\
+ ldrb r0, [r2]\n\
+ cmp r0, 0x24\n\
+ beq _08043E2C\n\
+ b _08043FBE\n\
+_08043E2C:\n\
+ ldr r0, =gStatuses3\n\
+ ldr r3, [sp, 0x20]\n\
+ adds r0, r3, r0\n\
+ ldr r1, [r0]\n\
+ movs r0, 0x80\n\
+ lsls r0, 13\n\
+ ands r1, r0\n\
+ str r3, [sp, 0x18]\n\
+ cmp r1, 0\n\
+ bne _08043E42\n\
+ b _08043FBE\n\
+_08043E42:\n\
+ lsls r0, r4, 24\n\
+ lsrs r0, 24\n\
+ bl GetBankIdentity\n\
+ movs r1, 0x1\n\
+ adds r5, r0, 0\n\
+ eors r5, r1\n\
+ ands r5, r1\n\
+ adds r0, r5, 0\n\
+ bl GetBankByIdentity\n\
+ lsls r0, 24\n\
+ lsrs r6, r0, 24\n\
+ adds r0, r5, 0x2\n\
+ bl GetBankByIdentity\n\
+ lsls r0, 24\n\
+ lsrs r7, r0, 24\n\
+ ldr r0, =gBattleTypeFlags\n\
+ ldr r0, [r0]\n\
+ movs r2, 0x1\n\
+ ands r0, r2\n\
+ cmp r0, 0\n\
+ bne _08043E74\n\
+ b _08043F84\n\
+_08043E74:\n\
+ movs r1, 0x58\n\
+ adds r0, r6, 0\n\
+ muls r0, r1\n\
+ ldr r3, =gBattleMons\n\
+ adds r1, r0, r3\n\
+ adds r0, r1, 0\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, 0\n\
+ beq _08043F40\n\
+ ldrh r0, [r1, 0x28]\n\
+ cmp r0, 0\n\
+ beq _08043EFC\n\
+ movs r1, 0x58\n\
+ adds r0, r7, 0\n\
+ muls r0, r1\n\
+ adds r1, r0, r3\n\
+ adds r0, r1, 0\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, 0\n\
+ beq _08043EFC\n\
+ ldrh r0, [r1, 0x28]\n\
+ cmp r0, 0\n\
+ beq _08043EFC\n\
+ str r2, [sp, 0x24]\n\
+ bl Random\n\
+ ldr r2, [sp, 0x24]\n\
+ adds r1, r2, 0\n\
+ ands r1, r0\n\
+ lsls r1, 1\n\
+ orrs r5, r1\n\
+ adds r0, r5, 0\n\
+ bl GetBankByIdentity\n\
+ mov r2, r8\n\
+ strb r0, [r2]\n\
+ ldrb r0, [r2]\n\
+ movs r3, 0x58\n\
+ muls r0, r3\n\
+ ldr r5, =gBattleMons\n\
+ adds r0, r5\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ ldr r1, [sp, 0x1C]\n\
+ strb r0, [r1]\n\
+ ldrb r0, [r2]\n\
+ muls r0, r3\n\
+ adds r0, r5\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ ldr r2, =gLastUsedAbility\n\
+ strb r0, [r2]\n\
+ b _08043FAC\n\
+ .pool\n\
+_08043EFC:\n\
+ ldr r3, =gBattleMons\n\
+ movs r2, 0x58\n\
+ adds r0, r6, 0\n\
+ muls r0, r2\n\
+ adds r1, r0, r3\n\
+ adds r0, r1, 0\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, 0\n\
+ beq _08043F40\n\
+ ldrh r0, [r1, 0x28]\n\
+ cmp r0, 0\n\
+ beq _08043F40\n\
+ mov r5, r8\n\
+ strb r6, [r5]\n\
+ adds r1, r4, 0\n\
+ muls r1, r2\n\
+ adds r1, r3\n\
+ ldrb r0, [r5]\n\
+ muls r0, r2\n\
+ adds r0, r3\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ adds r1, 0x20\n\
+ strb r0, [r1]\n\
+ ldrb r0, [r5]\n\
+ muls r0, r2\n\
+ adds r0, r3\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ b _08043FA8\n\
+ .pool\n\
+_08043F40:\n\
+ ldr r3, =gBattleMons\n\
+ movs r2, 0x58\n\
+ adds r0, r7, 0\n\
+ muls r0, r2\n\
+ adds r1, r0, r3\n\
+ adds r0, r1, 0\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, 0\n\
+ beq _08043FB6\n\
+ ldrh r0, [r1, 0x28]\n\
+ cmp r0, 0\n\
+ beq _08043FB6\n\
+ mov r5, r8\n\
+ strb r7, [r5]\n\
+ adds r1, r4, 0\n\
+ muls r1, r2\n\
+ adds r1, r3\n\
+ ldrb r0, [r5]\n\
+ muls r0, r2\n\
+ adds r0, r3\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ adds r1, 0x20\n\
+ strb r0, [r1]\n\
+ ldrb r0, [r5]\n\
+ muls r0, r2\n\
+ adds r0, r3\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ b _08043FA8\n\
+ .pool\n\
+_08043F84:\n\
+ mov r2, r8\n\
+ strb r6, [r2]\n\
+ movs r3, 0x58\n\
+ adds r0, r6, 0\n\
+ muls r0, r3\n\
+ ldr r5, =gBattleMons\n\
+ adds r0, r5\n\
+ adds r2, r0, 0\n\
+ adds r2, 0x20\n\
+ ldrb r1, [r2]\n\
+ cmp r1, 0\n\
+ beq _08043FB6\n\
+ ldrh r0, [r0, 0x28]\n\
+ cmp r0, 0\n\
+ beq _08043FB6\n\
+ ldr r0, [sp, 0x1C]\n\
+ strb r1, [r0]\n\
+ ldrb r0, [r2]\n\
+_08043FA8:\n\
+ ldr r1, =gLastUsedAbility\n\
+ strb r0, [r1]\n\
+_08043FAC:\n\
+ mov r0, r9\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_08043FB6:\n\
+ mov r2, r9\n\
+ cmp r2, 0\n\
+ beq _08043FBE\n\
+ b _08044340\n\
+_08043FBE:\n\
+ ldr r3, [sp, 0x1C]\n\
+ adds r3, 0x58\n\
+ str r3, [sp, 0x1C]\n\
+ ldr r5, [sp, 0x20]\n\
+ adds r5, 0x4\n\
+ str r5, [sp, 0x20]\n\
+ adds r4, 0x1\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ bge _08043FD6\n\
+ b _08043E22\n\
+_08043FD6:\n\
+ b _0804441E\n\
+ .pool\n\
+_08043FE4:\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r1, [r0]\n\
+ cmp r4, r1\n\
+ blt _08043FF0\n\
+ b _0804441E\n\
+_08043FF0:\n\
+ ldr r0, =gBattleMons\n\
+ adds r5, r1, 0\n\
+ ldr r2, =gStatuses3\n\
+ adds r3, r0, 0\n\
+ adds r3, 0x20\n\
+ movs r6, 0x80\n\
+ lsls r6, 12\n\
+_08043FFE:\n\
+ ldrb r1, [r3]\n\
+ cmp r1, 0x16\n\
+ bne _0804400E\n\
+ ldr r0, [r2]\n\
+ ands r0, r6\n\
+ cmp r0, 0\n\
+ beq _0804400E\n\
+ b _080443B4\n\
+_0804400E:\n\
+ adds r2, 0x4\n\
+ adds r3, 0x58\n\
+ adds r4, 0x1\n\
+ cmp r4, r5\n\
+ blt _08043FFE\n\
+ b _0804441E\n\
+ .pool\n\
+_08044028:\n\
+ mov r0, r10\n\
+ bl GetBankSide\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _0804403E\n\
+ b _0804441E\n\
+_0804403E:\n\
+ ldr r7, =gBattleMons\n\
+_08044040:\n\
+ lsls r0, r4, 24\n\
+ lsrs r0, 24\n\
+ bl GetBankSide\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ adds r3, r4, 0x1\n\
+ cmp r0, r5\n\
+ beq _0804406A\n\
+ movs r0, 0x58\n\
+ muls r0, r4\n\
+ adds r0, r7\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, r6\n\
+ bne _0804406A\n\
+ ldr r0, =gLastUsedAbility\n\
+ strb r6, [r0]\n\
+ lsls r0, r3, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_0804406A:\n\
+ adds r4, r3, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _08044040\n\
+ b _0804441E\n\
+ .pool\n\
+_08044084:\n\
+ mov r0, r10\n\
+ bl GetBankSide\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _0804409A\n\
+ b _0804441E\n\
+_0804409A:\n\
+ ldr r7, =gBattleMons\n\
+_0804409C:\n\
+ lsls r0, r4, 24\n\
+ lsrs r0, 24\n\
+ bl GetBankSide\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ adds r3, r4, 0x1\n\
+ cmp r0, r5\n\
+ bne _080440C6\n\
+ movs r0, 0x58\n\
+ muls r0, r4\n\
+ adds r0, r7\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, r6\n\
+ bne _080440C6\n\
+ ldr r0, =gLastUsedAbility\n\
+ strb r6, [r0]\n\
+ lsls r0, r3, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_080440C6:\n\
+ adds r4, r3, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _0804409C\n\
+ b _0804441E\n\
+ .pool\n\
+_080440E0:\n\
+ ldrb r0, [r7]\n\
+ cmp r0, 0xFD\n\
+ beq _08044104\n\
+ cmp r0, 0xFE\n\
+ beq _0804413C\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ adds r5, r0, 0\n\
+ ldrb r0, [r5]\n\
+ cmp r4, r0\n\
+ blt _080440F8\n\
+ b _0804441E\n\
+_080440F8:\n\
+ ldr r2, =gBattleMons\n\
+ b _08044174\n\
+ .pool\n\
+_08044104:\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _08044110\n\
+ b _0804441E\n\
+_08044110:\n\
+ ldr r5, =gStatuses3\n\
+ movs r2, 0x80\n\
+ lsls r2, 9\n\
+ adds r1, r0, 0\n\
+_08044118:\n\
+ lsls r0, r4, 2\n\
+ adds r0, r5\n\
+ ldr r0, [r0]\n\
+ ands r0, r2\n\
+ adds r3, r4, 0x1\n\
+ cmp r0, 0\n\
+ beq _0804412C\n\
+ lsls r0, r3, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_0804412C:\n\
+ adds r4, r3, 0\n\
+ cmp r4, r1\n\
+ blt _08044118\n\
+ b _0804441E\n\
+ .pool\n\
+_0804413C:\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _08044148\n\
+ b _0804441E\n\
+_08044148:\n\
+ ldr r5, =gStatuses3\n\
+ movs r2, 0x80\n\
+ lsls r2, 10\n\
+ adds r1, r0, 0\n\
+_08044150:\n\
+ lsls r0, r4, 2\n\
+ adds r0, r5\n\
+ ldr r0, [r0]\n\
+ ands r0, r2\n\
+ adds r3, r4, 0x1\n\
+ cmp r0, 0\n\
+ beq _08044164\n\
+ lsls r0, r3, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_08044164:\n\
+ adds r4, r3, 0\n\
+ cmp r4, r1\n\
+ blt _08044150\n\
+ b _0804441E\n\
+ .pool\n\
+_08044174:\n\
+ movs r0, 0x58\n\
+ muls r0, r4\n\
+ adds r0, r2\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ adds r3, r4, 0x1\n\
+ cmp r0, r6\n\
+ bne _0804418C\n\
+ strb r6, [r7]\n\
+ lsls r0, r3, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_0804418C:\n\
+ adds r4, r3, 0\n\
+ ldrb r1, [r5]\n\
+ cmp r4, r1\n\
+ blt _08044174\n\
+ b _0804441E\n\
+_08044196:\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _080441A2\n\
+ b _0804441E\n\
+_080441A2:\n\
+ ldr r2, =gBattleMons\n\
+ mov r8, r2\n\
+ adds r2, r0, 0\n\
+ movs r5, 0x58\n\
+_080441AA:\n\
+ adds r0, r4, 0\n\
+ muls r0, r5\n\
+ mov r3, r8\n\
+ adds r1, r0, r3\n\
+ adds r0, r1, 0\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ adds r3, r4, 0x1\n\
+ cmp r0, r6\n\
+ bne _080441CC\n\
+ ldrh r0, [r1, 0x28]\n\
+ cmp r0, 0\n\
+ beq _080441CC\n\
+ strb r6, [r7]\n\
+ lsls r0, r3, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_080441CC:\n\
+ adds r4, r3, 0\n\
+ cmp r4, r2\n\
+ blt _080441AA\n\
+ b _0804441E\n\
+ .pool\n\
+_080441DC:\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _080441E8\n\
+ b _0804441E\n\
+_080441E8:\n\
+ ldr r7, =gBattleMons\n\
+ adds r1, r0, 0\n\
+ movs r5, 0x58\n\
+ ldr r2, =gLastUsedAbility\n\
+_080441F0:\n\
+ adds r0, r4, 0\n\
+ muls r0, r5\n\
+ adds r0, r7\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ adds r3, r4, 0x1\n\
+ cmp r0, r6\n\
+ bne _0804420C\n\
+ cmp r4, r10\n\
+ beq _0804420C\n\
+ strb r6, [r2]\n\
+ lsls r0, r3, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_0804420C:\n\
+ adds r4, r3, 0\n\
+ cmp r4, r1\n\
+ blt _080441F0\n\
+ b _0804441E\n\
+ .pool\n\
+_08044220:\n\
+ mov r0, r10\n\
+ bl GetBankSide\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _08044236\n\
+ b _0804441E\n\
+_08044236:\n\
+ ldr r7, =gBattleMons\n\
+_08044238:\n\
+ lsls r0, r4, 24\n\
+ lsrs r0, 24\n\
+ bl GetBankSide\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ cmp r0, r5\n\
+ beq _08044264\n\
+ movs r0, 0x58\n\
+ muls r0, r4\n\
+ adds r0, r7\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, r6\n\
+ bne _08044264\n\
+ ldr r0, =gLastUsedAbility\n\
+ strb r6, [r0]\n\
+ mov r0, r9\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_08044264:\n\
+ adds r4, 0x1\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _08044238\n\
+ b _0804441E\n\
+ .pool\n\
+_0804427C:\n\
+ mov r0, r10\n\
+ bl GetBankSide\n\
+ lsls r0, 24\n\
+ lsrs r5, r0, 24\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _08044292\n\
+ b _0804441E\n\
+_08044292:\n\
+ ldr r7, =gBattleMons\n\
+_08044294:\n\
+ lsls r0, r4, 24\n\
+ lsrs r0, 24\n\
+ bl GetBankSide\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ cmp r0, r5\n\
+ bne _080442C0\n\
+ movs r0, 0x58\n\
+ muls r0, r4\n\
+ adds r0, r7\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, r6\n\
+ bne _080442C0\n\
+ ldr r0, =gLastUsedAbility\n\
+ strb r6, [r0]\n\
+ mov r0, r9\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_080442C0:\n\
+ adds r4, 0x1\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r0, [r0]\n\
+ cmp r4, r0\n\
+ blt _08044294\n\
+ b _0804441E\n\
+ .pool\n\
+_080442D8:\n\
+ ldr r0, =BattleScript_CastformChange\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ ldr r0, =gBattleScripting\n\
+ strb r6, [r0, 0x17]\n\
+_080442E2:\n\
+ ldr r0, =gBattleStruct\n\
+ ldr r0, [r0]\n\
+ adds r0, 0x7F\n\
+ mov r1, r9\n\
+ subs r1, 0x1\n\
+ strb r1, [r0]\n\
+ b _0804441E\n\
+ .pool\n\
+_080442FC:\n\
+ ldr r0, =BattleScript_CastformChange\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ ldr r0, =gBattleScripting\n\
+ mov r5, r10\n\
+ strb r5, [r0, 0x17]\n\
+ ldr r0, =gBattleStruct\n\
+ ldr r0, [r0]\n\
+ adds r0, 0x7F\n\
+ mov r1, r9\n\
+ subs r1, 0x1\n\
+ strb r1, [r0]\n\
+ b _0804443A\n\
+ .pool\n\
+_08044324:\n\
+ strb r1, [r7]\n\
+ ldr r0, [r2]\n\
+ ldr r1, =0xfff7ffff\n\
+ ands r0, r1\n\
+ str r0, [r2]\n\
+ ldr r0, =gUnknown_082DB4B8\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ b _080443C8\n\
+ .pool\n\
+_08044340:\n\
+ ldr r0, =BattleScript_TraceActivates\n\
+ bl BattleScriptPushCursorAndCallback\n\
+ ldr r1, =gStatuses3\n\
+ ldr r0, [sp, 0x18]\n\
+ adds r1, r0, r1\n\
+ ldr r0, [r1]\n\
+ ldr r2, =0xffefffff\n\
+ ands r0, r2\n\
+ str r0, [r1]\n\
+ ldr r0, =gBattleScripting\n\
+ strb r4, [r0, 0x17]\n\
+ ldr r1, =gBattleTextBuff1\n\
+ movs r4, 0xFD\n\
+ strb r4, [r1]\n\
+ movs r0, 0x4\n\
+ strb r0, [r1, 0x1]\n\
+ ldr r2, =gActiveBank\n\
+ ldrb r0, [r2]\n\
+ strb r0, [r1, 0x2]\n\
+ ldr r3, =gBattlePartyID\n\
+ ldrb r0, [r2]\n\
+ lsls r0, 1\n\
+ adds r0, r3\n\
+ ldrh r0, [r0]\n\
+ strb r0, [r1, 0x3]\n\
+ movs r0, 0xFF\n\
+ strb r0, [r1, 0x4]\n\
+ ldr r1, =gBattleTextBuff2\n\
+ strb r4, [r1]\n\
+ movs r0, 0x9\n\
+ strb r0, [r1, 0x1]\n\
+ ldr r0, =gLastUsedAbility\n\
+ ldrb r0, [r0]\n\
+ strb r0, [r1, 0x2]\n\
+ movs r0, 0x1\n\
+ negs r0, r0\n\
+ strb r0, [r1, 0x3]\n\
+ b _0804441E\n\
+ .pool\n\
+_080443B4:\n\
+ strb r1, [r7]\n\
+ ldr r0, [r2]\n\
+ ldr r1, =0xfff7ffff\n\
+ ands r0, r1\n\
+ str r0, [r2]\n\
+ bl BattleScriptPushCursor\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, =gUnknown_082DB4C1\n\
+ str r0, [r1]\n\
+_080443C8:\n\
+ ldr r0, =gBattleStruct\n\
+ ldr r0, [r0]\n\
+ adds r0, 0xD8\n\
+ strb r4, [r0]\n\
+_080443D0:\n\
+ mov r0, r9\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+ b _0804441E\n\
+ .pool\n\
+_080443EC:\n\
+ movs r4, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r1, [r0]\n\
+ cmp r4, r1\n\
+ bge _0804441E\n\
+ ldr r0, =gBattleMons\n\
+ adds r2, r1, 0\n\
+ adds r1, r0, 0\n\
+ adds r1, 0x20\n\
+ ldr r3, =gLastUsedAbility\n\
+_08044400:\n\
+ ldrb r0, [r1]\n\
+ cmp r0, r6\n\
+ bne _08044416\n\
+ cmp r4, r10\n\
+ beq _08044416\n\
+ strb r6, [r3]\n\
+ mov r0, r9\n\
+ adds r0, 0x1\n\
+ lsls r0, 24\n\
+ lsrs r0, 24\n\
+ mov r9, r0\n\
+_08044416:\n\
+ adds r1, 0x58\n\
+ adds r4, 0x1\n\
+ cmp r4, r2\n\
+ blt _08044400\n\
+_0804441E:\n\
+ mov r1, r9\n\
+ cmp r1, 0\n\
+ beq _0804443A\n\
+_08044424:\n\
+ ldr r2, [sp, 0x4]\n\
+ cmp r2, 0xB\n\
+ bhi _0804443A\n\
+ ldr r1, =gLastUsedAbility\n\
+ ldrb r0, [r1]\n\
+ cmp r0, 0xFF\n\
+ beq _0804443A\n\
+ adds r1, r0, 0\n\
+ mov r0, r10\n\
+ bl RecordAbilityBattle\n\
+_0804443A:\n\
+ mov r0, r9\n\
+ add sp, 0x28\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r1}\n\
+ bx r1\n\
+ .pool\n\
+ .syntax divided");
+}
+#endif // NONMATCHING
+
+void BattleScriptExecute(const u8* BS_ptr)
+{
+ gBattlescriptCurrInstr = BS_ptr;
+ BATTLE_CALLBACKS_STACK->function[BATTLE_CALLBACKS_STACK->size++] = gBattleMainFunc;
+ gBattleMainFunc = bc_move_exec_returning;
+ gFightStateTracker = 0;
+}
+
+void BattleScriptPushCursorAndCallback(const u8* BS_ptr)
+{
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BS_ptr;
+ BATTLE_CALLBACKS_STACK->function[BATTLE_CALLBACKS_STACK->size++] = gBattleMainFunc;
+ gBattleMainFunc = sub_803E08C;
+}
+
+enum
+{
+ ITEM_NO_EFFECT, // 0
+ ITEM_STATUS_CHANGE, // 1
+ ITEM_EFFECT_OTHER, // 2
+ ITEM_PP_CHANGE, // 3
+ ITEM_HP_CHANGE, // 4
+ ITEM_STATS_CHANGE, // 5
+};
+
+enum
+{
+ FLAVOR_SPICY, // 0
+ FLAVOR_DRY, // 1
+ FLAVOR_SWEET, // 2
+ FLAVOR_BITTER, // 3
+ FLAVOR_SOUR, // 4
+};
+
+u8 ItemBattleEffects(u8 caseID, u8 bank, bool8 moveTurn)
+{
+ int i = 0;
+ u8 effect = ITEM_NO_EFFECT;
+ u8 changedPP = 0;
+ u8 bankHoldEffect, atkHoldEffect, defHoldEffect;
+ u8 bankQuality, atkQuality, defQuality;
+ u16 atkItem, defItem;
+
+ gLastUsedItem = gBattleMons[bank].item;
+ if (gLastUsedItem == ITEM_ENIGMA_BERRY)
+ {
+ bankHoldEffect = gEnigmaBerries[bank].holdEffect;
+ bankQuality = gEnigmaBerries[bank].holdEffectParam;
+ }
+ else
+ {
+ bankHoldEffect = ItemId_GetHoldEffect(gLastUsedItem);
+ bankQuality = ItemId_GetHoldEffectParam(gLastUsedItem);
+ }
+
+ atkItem = gBattleMons[gBankAttacker].item;
+ if (atkItem == ITEM_ENIGMA_BERRY)
+ {
+ atkHoldEffect = gEnigmaBerries[gBankAttacker].holdEffect;
+ atkQuality = gEnigmaBerries[gBankAttacker].holdEffectParam;
+ }
+ else
+ {
+ atkHoldEffect = ItemId_GetHoldEffect(atkItem);
+ atkQuality = ItemId_GetHoldEffectParam(atkItem);
+ }
+
+ // def variables are unused
+ defItem = gBattleMons[gBankTarget].item;
+ if (defItem == ITEM_ENIGMA_BERRY)
+ {
+ defHoldEffect = gEnigmaBerries[gBankTarget].holdEffect;
+ defQuality = gEnigmaBerries[gBankTarget].holdEffectParam;
+ }
+ else
+ {
+ defHoldEffect = ItemId_GetHoldEffect(defItem);
+ defQuality = ItemId_GetHoldEffectParam(defItem);
+ }
+
+ switch (caseID)
+ {
+ case 0:
+ switch (bankHoldEffect)
+ {
+ case HOLD_EFFECT_DOUBLE_PRIZE:
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ gBattleStruct->moneyMultiplier = 2;
+ break;
+ case HOLD_EFFECT_RESTORE_STATS:
+ for (i = 0; i < 8; i++)
+ {
+ if (gBattleMons[bank].statStages[i] < 6)
+ {
+ gBattleMons[bank].statStages[i] = 6;
+ effect = ITEM_STATS_CHANGE;
+ }
+ }
+ if (effect)
+ {
+ gBattleScripting.bank = bank;
+ gStringBank = bank;
+ gActiveBank = gBankAttacker = bank;
+ BattleScriptExecute(BattleScript_WhiteHerbEnd2);
+ }
+ break;
+ }
+ break;
+ case 1:
+ if (gBattleMons[bank].hp)
+ {
+ switch (bankHoldEffect)
+ {
+ case HOLD_EFFECT_RESTORE_HP:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn)
+ {
+ gBattleMoveDamage = bankQuality;
+ if (gBattleMons[bank].hp + bankQuality > gBattleMons[bank].maxHP)
+ gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp;
+ gBattleMoveDamage *= -1;
+ BattleScriptExecute(BattleScript_ItemHealHP_RemoveItem);
+ effect = 4;
+ }
+ break;
+ case HOLD_EFFECT_RESTORE_PP:
+ if (!moveTurn)
+ {
+ struct Pokemon* poke;
+ u8 ppBonuses;
+ u16 move;
+
+ if (GetBankSide(bank) == SIDE_PLAYER)
+ poke = &gPlayerParty[gBattlePartyID[bank]];
+ else
+ poke = &gEnemyParty[gBattlePartyID[bank]];
+ for (i = 0; i < 4; i++)
+ {
+ move = GetMonData(poke, MON_DATA_MOVE1 + i);
+ changedPP = GetMonData(poke, MON_DATA_PP1 + i);
+ ppBonuses = GetMonData(poke, MON_DATA_PP_BONUSES);
+ if (move && changedPP == 0)
+ break;
+ }
+ if (i != 4)
+ {
+ u8 maxPP = CalculatePPWithBonus(move, ppBonuses, i);
+ if (changedPP + bankQuality > maxPP)
+ changedPP = maxPP;
+ else
+ changedPP = changedPP + bankQuality;
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 2;
+ gBattleTextBuff1[2] = move;
+ gBattleTextBuff1[3] = move >> 8;
+ gBattleTextBuff1[4] = 0xFF;
+ BattleScriptExecute(BattleScript_BerryPPHealEnd2);
+ EmitSetMonData(0, i + REQUEST_PPMOVE1_BATTLE, 0, 1, &changedPP);
+ MarkBufferBankForExecution(gActiveBank);
+ effect = ITEM_PP_CHANGE;
+ }
+ }
+ break;
+ case HOLD_EFFECT_RESTORE_STATS:
+ for (i = 0; i < 8; i++)
+ {
+ if (gBattleMons[bank].statStages[i] < 6)
+ {
+ gBattleMons[bank].statStages[i] = 6;
+ effect = ITEM_STATS_CHANGE;
+ }
+ }
+ if (effect)
+ {
+ gBattleScripting.bank = bank;
+ gStringBank = bank;
+ gActiveBank = gBankAttacker = bank;
+ BattleScriptExecute(BattleScript_WhiteHerbEnd2);
+ }
+ break;
+ case HOLD_EFFECT_LEFTOVERS:
+ if (gBattleMons[bank].hp < gBattleMons[bank].maxHP && !moveTurn)
+ {
+ gBattleMoveDamage = gBattleMons[bank].maxHP / 16;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP)
+ gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp;
+ gBattleMoveDamage *= -1;
+ BattleScriptExecute(BattleScript_ItemHealHP_End2);
+ effect = ITEM_HP_CHANGE;
+ RecordItemEffectBattle(bank, bankHoldEffect);
+ }
+ break;
+ // nice copy/paste there gamefreak, making a function for confuse berries was too much eh?
+ case HOLD_EFFECT_CONFUSE_SPICY:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 8;
+ gBattleTextBuff1[2] = FLAVOR_SPICY;
+ gBattleTextBuff1[3] = EOS;
+ gBattleMoveDamage = gBattleMons[bank].maxHP / bankQuality;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP)
+ gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp;
+ gBattleMoveDamage *= -1;
+ if (GetFlavourRelationByPersonality(gBattleMons[bank].personality, FLAVOR_SPICY) < 0)
+ BattleScriptExecute(BattleScript_BerryConfuseHealEnd2);
+ else
+ BattleScriptExecute(BattleScript_ItemHealHP_RemoveItem);
+ effect = ITEM_HP_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CONFUSE_DRY:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 8;
+ gBattleTextBuff1[2] = FLAVOR_DRY;
+ gBattleTextBuff1[3] = EOS;
+ gBattleMoveDamage = gBattleMons[bank].maxHP / bankQuality;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP)
+ gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp;
+ gBattleMoveDamage *= -1;
+ if (GetFlavourRelationByPersonality(gBattleMons[bank].personality, FLAVOR_DRY) < 0)
+ BattleScriptExecute(BattleScript_BerryConfuseHealEnd2);
+ else
+ BattleScriptExecute(BattleScript_ItemHealHP_RemoveItem);
+ effect = ITEM_HP_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CONFUSE_SWEET:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 8;
+ gBattleTextBuff1[2] = FLAVOR_SWEET;
+ gBattleTextBuff1[3] = EOS;
+ gBattleMoveDamage = gBattleMons[bank].maxHP / bankQuality;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP)
+ gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp;
+ gBattleMoveDamage *= -1;
+ if (GetFlavourRelationByPersonality(gBattleMons[bank].personality, FLAVOR_SWEET) < 0)
+ BattleScriptExecute(BattleScript_BerryConfuseHealEnd2);
+ else
+ BattleScriptExecute(BattleScript_ItemHealHP_RemoveItem);
+ effect = ITEM_HP_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CONFUSE_BITTER:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 8;
+ gBattleTextBuff1[2] = FLAVOR_BITTER;
+ gBattleTextBuff1[3] = EOS;
+ gBattleMoveDamage = gBattleMons[bank].maxHP / bankQuality;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP)
+ gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp;
+ gBattleMoveDamage *= -1;
+ if (GetFlavourRelationByPersonality(gBattleMons[bank].personality, FLAVOR_BITTER) < 0)
+ BattleScriptExecute(BattleScript_BerryConfuseHealEnd2);
+ else
+ BattleScriptExecute(BattleScript_ItemHealHP_RemoveItem);
+ effect = ITEM_HP_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CONFUSE_SOUR:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / 2 && !moveTurn)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 8;
+ gBattleTextBuff1[2] = FLAVOR_SOUR;
+ gBattleTextBuff1[3] = EOS;
+ gBattleMoveDamage = gBattleMons[bank].maxHP / bankQuality;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ if (gBattleMons[bank].hp + gBattleMoveDamage > gBattleMons[bank].maxHP)
+ gBattleMoveDamage = gBattleMons[bank].maxHP - gBattleMons[bank].hp;
+ gBattleMoveDamage *= -1;
+ if (GetFlavourRelationByPersonality(gBattleMons[bank].personality, FLAVOR_SOUR) < 0)
+ BattleScriptExecute(BattleScript_BerryConfuseHealEnd2);
+ else
+ BattleScriptExecute(BattleScript_ItemHealHP_RemoveItem);
+ effect = ITEM_HP_CHANGE;
+ }
+ break;
+ // copy/paste again, smh
+ case HOLD_EFFECT_ATTACK_UP:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && gBattleMons[bank].statStages[STAT_STAGE_ATK] < 0xC)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 5;
+ gBattleTextBuff1[2] = STAT_STAGE_ATK;
+ gBattleTextBuff1[3] = EOS;
+
+ gBattleTextBuff2[0] = 0xFD;
+ gBattleTextBuff2[1] = 0;
+ gBattleTextBuff2[2] = 0xD2;
+ gBattleTextBuff2[3] = 0xD2 >> 8;
+ gBattleTextBuff2[4] = EOS;
+
+ gEffectBank = bank;
+ gBattleScripting.statChanger = 0x10 + STAT_STAGE_ATK;
+ gBattleScripting.animArg1 = 0xE + STAT_STAGE_ATK;
+ gBattleScripting.animArg2 = 0;
+ BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
+ effect = ITEM_STATS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_DEFENSE_UP:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && gBattleMons[bank].statStages[STAT_STAGE_DEF] < 0xC)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 5;
+ gBattleTextBuff1[2] = STAT_STAGE_DEF;
+ gBattleTextBuff1[3] = EOS;
+
+ gEffectBank = bank;
+ gBattleScripting.statChanger = 0x10 + STAT_STAGE_DEF;
+ gBattleScripting.animArg1 = 0xE + STAT_STAGE_DEF;
+ gBattleScripting.animArg2 = 0;
+ BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
+ effect = ITEM_STATS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_SPEED_UP:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && gBattleMons[bank].statStages[STAT_STAGE_SPEED] < 0xC)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 5;
+ gBattleTextBuff1[2] = STAT_STAGE_SPEED;
+ gBattleTextBuff1[3] = EOS;
+
+ gEffectBank = bank;
+ gBattleScripting.statChanger = 0x10 + STAT_STAGE_SPEED;
+ gBattleScripting.animArg1 = 0xE + STAT_STAGE_SPEED;
+ gBattleScripting.animArg2 = 0;
+ BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
+ effect = ITEM_STATS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_SP_ATTACK_UP:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && gBattleMons[bank].statStages[STAT_STAGE_SPATK] < 0xC)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 5;
+ gBattleTextBuff1[2] = STAT_STAGE_SPATK;
+ gBattleTextBuff1[3] = EOS;
+
+ gEffectBank = bank;
+ gBattleScripting.statChanger = 0x10 + STAT_STAGE_SPATK;
+ gBattleScripting.animArg1 = 0xE + STAT_STAGE_SPATK;
+ gBattleScripting.animArg2 = 0;
+ BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
+ effect = ITEM_STATS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_SP_DEFENSE_UP:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && gBattleMons[bank].statStages[STAT_STAGE_SPDEF] < 0xC)
+ {
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 5;
+ gBattleTextBuff1[2] = STAT_STAGE_SPDEF;
+ gBattleTextBuff1[3] = EOS;
+
+ gEffectBank = bank;
+ gBattleScripting.statChanger = 0x10 + STAT_STAGE_SPDEF;
+ gBattleScripting.animArg1 = 0xE + STAT_STAGE_SPDEF;
+ gBattleScripting.animArg2 = 0;
+ BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
+ effect = ITEM_STATS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CRITICAL_UP:
+ if (gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality && !moveTurn && !(gBattleMons[bank].status2 & STATUS2_FOCUS_ENERGY))
+ {
+ gBattleMons[bank].status2 |= STATUS2_FOCUS_ENERGY;
+ BattleScriptExecute(BattleScript_BerryFocusEnergyEnd2);
+ effect = ITEM_EFFECT_OTHER;
+ }
+ break;
+ case HOLD_EFFECT_RANDOM_STAT_UP:
+ if (!moveTurn && gBattleMons[bank].hp <= gBattleMons[bank].maxHP / bankQuality)
+ {
+ for (i = 0; i < 5; i++)
+ {
+ if (gBattleMons[bank].statStages[STAT_STAGE_ATK + i] < 0xC)
+ break;
+ }
+ if (i != 5)
+ {
+ do
+ {
+ i = Random() % 5;
+ } while (gBattleMons[bank].statStages[STAT_STAGE_ATK + i] == 0xC);
+
+ gBattleTextBuff1[0] = 0xFD;
+ gBattleTextBuff1[1] = 5;
+ gBattleTextBuff1[2] = i + 1;
+ gBattleTextBuff1[3] = EOS;
+
+ gBattleTextBuff2[0] = 0xFD;
+ gBattleTextBuff2[1] = 0;
+ gBattleTextBuff2[2] = 0xD1;
+ gBattleTextBuff2[3] = 0xD1 >> 8;
+ gBattleTextBuff2[4] = 0;
+ gBattleTextBuff2[5] = 0xD2;
+ gBattleTextBuff2[6] = 0xD2 >> 8;
+ gBattleTextBuff2[7] = EOS;
+
+ gEffectBank = bank;
+ gBattleScripting.statChanger = 0x21 + i;
+ gBattleScripting.animArg1 = 0x21 + i + 6;
+ gBattleScripting.animArg2 = 0;
+ BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
+ effect = ITEM_STATS_CHANGE;
+ }
+ }
+ break;
+ case HOLD_EFFECT_CURE_PAR:
+ if (gBattleMons[bank].status1 & STATUS_PARALYSIS)
+ {
+ gBattleMons[bank].status1 &= ~(STATUS_PARALYSIS);
+ BattleScriptExecute(BattleScript_BerryCurePrlzEnd2);
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_PSN:
+ if (gBattleMons[bank].status1 & STATUS_PSN_ANY)
+ {
+ gBattleMons[bank].status1 &= ~(STATUS_PSN_ANY | STATUS_TOXIC_COUNTER);
+ BattleScriptExecute(BattleScript_BerryCurePsnEnd2);
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_BRN:
+ if (gBattleMons[bank].status1 & STATUS_BURN)
+ {
+ gBattleMons[bank].status1 &= ~(STATUS_BURN);
+ BattleScriptExecute(BattleScript_BerryCureBrnEnd2);
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_FRZ:
+ if (gBattleMons[bank].status1 & STATUS_FREEZE)
+ {
+ gBattleMons[bank].status1 &= ~(STATUS_FREEZE);
+ BattleScriptExecute(BattleScript_BerryCureFrzEnd2);
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_SLP:
+ if (gBattleMons[bank].status1 & STATUS_SLEEP)
+ {
+ gBattleMons[bank].status1 &= ~(STATUS_SLEEP);
+ gBattleMons[bank].status2 &= ~(STATUS2_NIGHTMARE);
+ BattleScriptExecute(BattleScript_BerryCureSlpEnd2);
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_CONFUSION:
+ if (gBattleMons[bank].status2 & STATUS2_CONFUSION)
+ {
+ gBattleMons[bank].status2 &= ~(STATUS2_CONFUSION);
+ BattleScriptExecute(BattleScript_BerryCureConfusionEnd2);
+ effect = ITEM_EFFECT_OTHER;
+ }
+ break;
+ case HOLD_EFFECT_CURE_STATUS:
+ if (gBattleMons[bank].status1 & STATUS_ANY || gBattleMons[bank].status2 & STATUS2_CONFUSION)
+ {
+ i = 0;
+ if (gBattleMons[bank].status1 & STATUS_PSN_ANY)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
+ i++;
+ }
+ if (gBattleMons[bank].status1 & STATUS_SLEEP)
+ {
+ gBattleMons[bank].status2 &= ~(STATUS2_NIGHTMARE);
+ StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
+ i++;
+ }
+ if (gBattleMons[bank].status1 & STATUS_PARALYSIS)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
+ i++;
+ }
+ if (gBattleMons[bank].status1 & STATUS_BURN)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn);
+ i++;
+ }
+ if (gBattleMons[bank].status1 & STATUS_FREEZE)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn);
+ i++;
+ }
+ if (gBattleMons[bank].status2 & STATUS2_CONFUSION)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn);
+ i++;
+ }
+ if (!(i > 1))
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ gBattleMons[bank].status1 = 0;
+ gBattleMons[bank].status2 &= ~(STATUS2_CONFUSION);
+ BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2);
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_ATTRACT:
+ if (gBattleMons[bank].status2 & STATUS2_INFATUATION)
+ {
+ gBattleMons[bank].status2 &= ~(STATUS2_INFATUATION);
+ StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn);
+ BattleScriptExecute(BattleScript_BerryCureChosenStatusEnd2);
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ effect = ITEM_EFFECT_OTHER;
+ }
+ break;
+ }
+ if (effect)
+ {
+ gBattleScripting.bank = bank;
+ gStringBank = bank;
+ gActiveBank = gBankAttacker = bank;
+ switch (effect)
+ {
+ case ITEM_STATUS_CHANGE:
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[bank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ break;
+ case ITEM_PP_CHANGE:
+ if (!(gBattleMons[bank].status2 & STATUS2_TRANSFORMED) && !(gDisableStructs[bank].unk18_b & gBitTable[i]))
+ gBattleMons[bank].pp[i] = changedPP;
+ break;
+ }
+ }
+ }
+ break;
+ case 2:
+ break;
+ case 3:
+ for (bank = 0; bank < gNoOfAllBanks; bank++)
+ {
+ gLastUsedItem = gBattleMons[bank].item;
+ if (gBattleMons[bank].item == ITEM_ENIGMA_BERRY)
+ {
+ bankHoldEffect = gEnigmaBerries[bank].holdEffect;
+ bankQuality = gEnigmaBerries[bank].holdEffectParam;
+ }
+ else
+ {
+ bankHoldEffect = ItemId_GetHoldEffect(gLastUsedItem);
+ bankQuality = ItemId_GetHoldEffectParam(gLastUsedItem);
+ }
+ switch (bankHoldEffect)
+ {
+ case HOLD_EFFECT_CURE_PAR:
+ if (gBattleMons[bank].status1 & STATUS_PARALYSIS)
+ {
+ gBattleMons[bank].status1 &= ~(STATUS_PARALYSIS);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_BerryCureParRet;
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_PSN:
+ if (gBattleMons[bank].status1 & STATUS_PSN_ANY)
+ {
+ gBattleMons[bank].status1 &= ~(STATUS_PSN_ANY | STATUS_TOXIC_COUNTER);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_BerryCurePsnRet;
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_BRN:
+ if (gBattleMons[bank].status1 & STATUS_BURN)
+ {
+ gBattleMons[bank].status1 &= ~(STATUS_BURN);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_BerryCureBrnRet;
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_FRZ:
+ if (gBattleMons[bank].status1 & STATUS_FREEZE)
+ {
+ gBattleMons[bank].status1 &= ~(STATUS_FREEZE);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_BerryCureFrzRet;
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_SLP:
+ if (gBattleMons[bank].status1 & STATUS_SLEEP)
+ {
+ gBattleMons[bank].status1 &= ~(STATUS_SLEEP);
+ gBattleMons[bank].status2 &= ~(STATUS2_NIGHTMARE);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_BerryCureSlpRet;
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_CURE_CONFUSION:
+ if (gBattleMons[bank].status2 & STATUS2_CONFUSION)
+ {
+ gBattleMons[bank].status2 &= ~(STATUS2_CONFUSION);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_BerryCureConfusionRet;
+ effect = ITEM_EFFECT_OTHER;
+ }
+ break;
+ case HOLD_EFFECT_CURE_ATTRACT:
+ if (gBattleMons[bank].status2 & STATUS2_INFATUATION)
+ {
+ gBattleMons[bank].status2 &= ~(STATUS2_INFATUATION);
+ StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn);
+ BattleScriptPushCursor();
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet;
+ effect = ITEM_EFFECT_OTHER;
+ }
+ break;
+ case HOLD_EFFECT_CURE_STATUS:
+ if (gBattleMons[bank].status1 & STATUS_ANY || gBattleMons[bank].status2 & STATUS2_CONFUSION)
+ {
+ if (gBattleMons[bank].status1 & STATUS_PSN_ANY)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
+ }
+ if (gBattleMons[bank].status1 & STATUS_SLEEP)
+ {
+ gBattleMons[bank].status2 &= ~(STATUS2_NIGHTMARE);
+ StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
+ }
+ if (gBattleMons[bank].status1 & STATUS_PARALYSIS)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
+ }
+ if (gBattleMons[bank].status1 & STATUS_BURN)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn);
+ }
+ if (gBattleMons[bank].status1 & STATUS_FREEZE)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn);
+ }
+ if (gBattleMons[bank].status2 & STATUS2_CONFUSION)
+ {
+ StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn);
+ }
+ gBattleMons[bank].status1 = 0;
+ gBattleMons[bank].status2 &= ~(STATUS2_CONFUSION);
+ BattleScriptPushCursor();
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ gBattlescriptCurrInstr = BattleScript_BerryCureChosenStatusRet;
+ effect = ITEM_STATUS_CHANGE;
+ }
+ break;
+ case HOLD_EFFECT_RESTORE_STATS:
+ for (i = 0; i < 8; i++)
+ {
+ if (gBattleMons[bank].statStages[i] < 6)
+ {
+ gBattleMons[bank].statStages[i] = 6;
+ effect = ITEM_STATS_CHANGE;
+ }
+ }
+ if (effect)
+ {
+ gBattleScripting.bank = bank;
+ gStringBank = bank;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_WhiteHerbRet;
+ return effect; // unnecessary return
+ }
+ break;
+ }
+ if (effect)
+ {
+ gBattleScripting.bank = bank;
+ gStringBank = bank;
+ gActiveBank = bank;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ break;
+ }
+ }
+ break;
+ case 4:
+ if (gBattleMoveDamage)
+ {
+ switch (atkHoldEffect)
+ {
+ case HOLD_EFFECT_FLINCH:
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ && (gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special)
+ && (Random() % 100) < atkQuality
+ && gBattleMoves[gCurrentMove].flags & FLAG_KINGSROCK_AFFECTED
+ && gBattleMons[gBankTarget].hp)
+ {
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 8;
+ BattleScriptPushCursor();
+ SetMoveEffect(0, 0);
+ BattleScriptPop();
+ }
+ break;
+ case HOLD_EFFECT_SHELL_BELL:
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ && gSpecialStatuses[gBankTarget].moveturnLostHP != 0
+ && gSpecialStatuses[gBankTarget].moveturnLostHP != 0xFFFF
+ && gBankAttacker != gBankTarget
+ && gBattleMons[gBankAttacker].hp != gBattleMons[gBankAttacker].maxHP
+ && gBattleMons[gBankAttacker].hp != 0)
+ {
+ gLastUsedItem = atkItem;
+ gStringBank = gBankAttacker;
+ gBattleScripting.bank = gBankAttacker;
+ gBattleMoveDamage = (gSpecialStatuses[gBankTarget].moveturnLostHP / atkQuality) * -1;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = -1;
+ gSpecialStatuses[gBankTarget].moveturnLostHP = 0;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret;
+ effect++;
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ return effect;
+}
+
+void sub_8045868(u8 bank)
+{
+ gDisableStructs[bank].furyCutterCounter = 0;
+ gBattleMons[bank].status2 &= ~(STATUS2_DESTINY_BOND);
+ gStatuses3[bank] &= ~(STATUS3_GRUDGE);
+}
+
+void sub_80458B4(void)
+{
+ if (gBattleExecBuffer == 0)
+ gBattleScriptingCommandsTable[*gBattlescriptCurrInstr]();
+}
+
+u8 GetMoveTarget(u16 move, u8 useMoveTarget)
+{
+ u8 targetBank = 0;
+ u8 moveTarget;
+ u8 side;
+
+ if (useMoveTarget)
+ moveTarget = useMoveTarget - 1;
+ else
+ moveTarget = gBattleMoves[move].target;
+
+ switch (moveTarget)
+ {
+ case MOVE_TARGET_SELECTED:
+ side = GetBankSide(gBankAttacker) ^ 1;
+ if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp)
+ targetBank = gSideTimers[side].followmeTarget;
+ else
+ {
+ side = GetBankSide(gBankAttacker);
+ do
+ {
+ targetBank = Random() % gNoOfAllBanks;
+ } while (targetBank == gBankAttacker || side == GetBankSide(targetBank) || gAbsentBankFlags & gBitTable[targetBank]);
+ if (gBattleMoves[move].type == TYPE_ELECTRIC
+ && AbilityBattleEffects(ABILITYEFFECT_COUNT_OTHER_SIDE, gBankAttacker, ABILITY_LIGHTNING_ROD, 0, 0)
+ && gBattleMons[targetBank].ability != ABILITY_LIGHTNING_ROD)
+ {
+ targetBank ^= 2;
+ RecordAbilityBattle(targetBank, gBattleMons[targetBank].ability);
+ gSpecialStatuses[targetBank].lightningRodRedirected = 1;
+ }
+ }
+ break;
+ case MOVE_TARGET_DEPENDS:
+ case MOVE_TARGET_BOTH:
+ case MOVE_TARGET_FOES_AND_ALLY:
+ case MOVE_TARGET_OPPONENTS_FIELD:
+ targetBank = GetBankByIdentity((GetBankIdentity(gBankAttacker) & 1) ^ 1);
+ if (gAbsentBankFlags & gBitTable[targetBank])
+ targetBank ^= 2;
+ break;
+ case MOVE_TARGET_RANDOM:
+ side = GetBankSide(gBankAttacker) ^ 1;
+ if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp)
+ targetBank = gSideTimers[side].followmeTarget;
+ else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && moveTarget & MOVE_TARGET_RANDOM)
+ {
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ {
+ if (Random() & 1)
+ targetBank = GetBankByIdentity(1);
+ else
+ targetBank = GetBankByIdentity(3);
+ }
+ else
+ {
+ if (Random() & 1)
+ targetBank = GetBankByIdentity(0);
+ else
+ targetBank = GetBankByIdentity(2);
+ }
+ if (gAbsentBankFlags & gBitTable[targetBank])
+ targetBank ^= 2;
+ }
+ else
+ targetBank = GetBankByIdentity((GetBankIdentity(gBankAttacker) & 1) ^ 1);
+ break;
+ case MOVE_TARGET_USER:
+ case MOVE_TARGET_x10:
+ targetBank = gBankAttacker;
+ break;
+ }
+
+ #ifndef NONMATCHING
+ MEME_ACCESS_U8(BattleStruct, gBattleStruct, gBankAttacker, moveTarget, targetBank);
+ #else
+ gBattleStruct->moveTarget[gBankAttacker] = targetBank;
+ #endif // NONMATCHING
+
+ return targetBank;
+}
+
+static bool32 HasObedientBitSet(u8 bank)
+{
+ if (GetBankSide(bank) == SIDE_OPPONENT)
+ return TRUE;
+ if (GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_SPECIES, NULL) != SPECIES_DEOXYS
+ && GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_SPECIES, NULL) != SPECIES_MEW)
+ return TRUE;
+ return GetMonData(&gPlayerParty[gBattlePartyID[bank]], MON_DATA_OBEDIENCE, NULL);
+}
+
+u8 IsPokeDisobedient(void)
+{
+ s32 rnd;
+ s32 calc;
+ u8 obedienceLevel = 0;
+
+ if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
+ return 0;
+ if (GetBankSide(gBankAttacker) == SIDE_OPPONENT)
+ return 0;
+
+ if (HasObedientBitSet(gBankAttacker)) // only if species is Mew or Deoxys
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBankIdentity(gBankAttacker) == 2)
+ return 0;
+ if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
+ return 0;
+ if (gBattleTypeFlags & BATTLE_TYPE_RECORDED)
+ return 0;
+ if (!IsOtherTrainer(gBattleMons[gBankAttacker].otId, gBattleMons[gBankAttacker].otName))
+ return 0;
+ if (FlagGet(BADGE08_GET))
+ return 0;
+
+ obedienceLevel = 10;
+
+ if (FlagGet(BADGE02_GET))
+ obedienceLevel = 30;
+ if (FlagGet(BADGE04_GET))
+ obedienceLevel = 50;
+ if (FlagGet(BADGE06_GET))
+ obedienceLevel = 70;
+ }
+
+ if (gBattleMons[gBankAttacker].level <= obedienceLevel)
+ return 0;
+ rnd = (Random() & 255);
+ calc = (gBattleMons[gBankAttacker].level + obedienceLevel) * rnd >> 8;
+ if (calc < obedienceLevel)
+ return 0;
+
+ // is not obedient
+ if (gCurrentMove == MOVE_RAGE)
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_RAGE);
+ if (gBattleMons[gBankAttacker].status1 & STATUS_SLEEP && (gCurrentMove == MOVE_SNORE || gCurrentMove == MOVE_SLEEP_TALK))
+ {
+ gBattlescriptCurrInstr = gUnknown_082DB695;
+ return 1;
+ }
+
+ rnd = (Random() & 255);
+ calc = (gBattleMons[gBankAttacker].level + obedienceLevel) * rnd >> 8;
+ if (calc < obedienceLevel)
+ {
+ calc = CheckMoveLimitations(gBankAttacker, gBitTable[gCurrMovePos], 0xFF);
+ if (calc == 0xF) // all moves cannot be used
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = Random() & 3;
+ gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround;
+ return 1;
+ }
+ else // use a random move
+ {
+ do
+ {
+ gCurrMovePos = gUnknown_020241E9 = Random() & 3;
+ } while (gBitTable[gCurrMovePos] & calc);
+
+ gRandomMove = gBattleMons[gBankAttacker].moves[gCurrMovePos];
+ gBattlescriptCurrInstr = gUnknown_082DB6A5;
+ gBankTarget = GetMoveTarget(gRandomMove, 0);
+ gHitMarker |= HITMARKER_x200000;
+ return 2;
+ }
+ }
+ else
+ {
+ obedienceLevel = gBattleMons[gBankAttacker].level - obedienceLevel;
+
+ calc = (Random() & 255);
+ if (calc < obedienceLevel && !(gBattleMons[gBankAttacker].status1 & STATUS_ANY) && gBattleMons[gBankAttacker].ability != ABILITY_VITAL_SPIRIT && gBattleMons[gBankAttacker].ability != ABILITY_INSOMNIA)
+ {
+ // try putting asleep
+ int i;
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleMons[i].status2 & STATUS2_UPROAR)
+ break;
+ }
+ if (i == gNoOfAllBanks)
+ {
+ gBattlescriptCurrInstr = gUnknown_082DB6D9;
+ return 1;
+ }
+ }
+ calc -= obedienceLevel;
+ if (calc < obedienceLevel)
+ {
+ gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankAttacker], MOVE_POUND, 0, 40, 0, gBankAttacker, gBankAttacker);
+ gBankTarget = gBankAttacker;
+ gBattlescriptCurrInstr = gUnknown_082DB6F0;
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ return 2;
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = Random() & 3;
+ gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround;
+ return 1;
+ }
+ }
+}
diff --git a/src/battle_4.c b/src/battle_4.c
deleted file mode 100644
index 92561251f..000000000
--- a/src/battle_4.c
+++ /dev/null
@@ -1,601 +0,0 @@
-#include "global.h"
-#include "battle.h"
-#include "battle_move_effects.h"
-#include "moves.h"
-#include "abilities.h"
-#include "item.h"
-#include "items.h"
-#include "hold_effects.h"
-
-void atk00_attackcanceler(void);
-void atk01_accuracycheck(void);
-void atk02_attackstring(void);
-void atk03_ppreduce(void);
-void atk04_critcalc(void);
-void atk05_damagecalc1(void);
-void atk06_typecalc(void);
-void atk07_dmg_adjustment(void);
-void atk08_dmg_adjustment2(void);
-void atk09_attackanimation(void);
-void atk0A_waitanimation(void);
-void atk0B_healthbarupdate(void);
-void atk0C_datahpupdate(void);
-void atk0D_critmessage(void);
-void atk0E_effectiveness_sound(void);
-void atk0F_resultmessage(void);
-void atk10_printstring(void);
-void atk11_printstring_playeronly(void);
-void atk12_waitmessage(void);
-void atk13_printfromtable(void);
-void atk14_printfromtable_playeronly(void);
-void atk15_seteffectwithchancetarget(void);
-void atk16_seteffectprimary(void);
-void atk17_seteffectsecondary(void);
-void atk18_status_effect_clear(void);
-void atk19_faint_pokemon(void);
-void atk1A_faint_animation(void);
-void atk1B_faint_effects_clear(void);
-void atk1C_jumpifstatus(void);
-void atk1D_jumpifstatus2(void);
-void atk1E_jumpifability(void);
-void atk1F_jumpifsideaffecting(void);
-void atk20_jumpifstat(void);
-void atk21_jumpifstatus3(void);
-void atk22_jumpiftype(void);
-void atk23_getexp(void);
-void atk24(void);
-void atk25_move_values_cleanup(void);
-void atk26_set_multihit(void);
-void atk27_decrement_multihit(void);
-void atk28_goto(void);
-void atk29_jumpifbyte(void);
-void atk2A_jumpifhalfword(void);
-void atk2B_jumpifword(void);
-void atk2C_jumpifarrayequal(void);
-void atk2D_jumpifarraynotequal(void);
-void atk2E_setbyte(void);
-void atk2F_addbyte(void);
-void atk30_subbyte(void);
-void atk31_copyarray(void);
-void atk32_copyarray_withindex(void);
-void atk33_orbyte(void);
-void atk34_orhalfword(void);
-void atk35_orword(void);
-void atk36_bicbyte(void);
-void atk37_bichalfword(void);
-void atk38_bicword(void);
-void atk39_pause(void);
-void atk3A_waitstate(void);
-void atk3B_healthbar_update(void);
-void atk3C_return(void);
-void atk3D_end(void);
-void atk3E_end2(void);
-void atk3F_end3(void);
-void atk40_jump_if_move_affected_by_protect(void);
-void atk41_call(void);
-void atk42_jumpiftype2(void);
-void atk43_jumpifabilitypresent(void);
-void atk44(void);
-void atk45_playanimation(void);
-void atk46_playanimation2(void);
-void atk47_setgraphicalstatchangevalues(void);
-void atk48_playstatchangeanimation(void);
-void atk49_moveendturn(void);
-void atk4A_typecalc2(void);
-void atk4B_return_atk_to_ball(void);
-void atk4C_copy_poke_data(void);
-void atk4D_switch_data_update(void);
-void atk4E_switchin_anim(void);
-void atk4F_jump_if_cannot_switch(void);
-void atk50_openpartyscreen(void);
-void atk51_switch_handle_order(void);
-void atk52_switch_in_effects(void);
-void atk53_trainer_slide(void);
-void atk54_effectiveness_sound(void);
-void atk55_play_sound(void);
-void atk56_fainting_cry(void);
-void atk57(void);
-void atk58_return_to_ball(void);
-void atk59_learnmove_inbattle(void);
-void atk5A(void);
-void atk5B_80256E0(void);
-void atk5C_hitanimation(void);
-void atk5D_getmoneyreward(void);
-void atk5E_8025A70(void);
-void atk5F_8025B24(void);
-void atk60_increment_gamestat(void);
-void atk61_8025BA4(void);
-void atk62_08025C6C(void);
-void atk63_jumptorandomattack(void);
-void atk64_statusanimation(void);
-void atk65_status2animation(void);
-void atk66_chosenstatusanimation(void);
-void atk67_8025ECC(void);
-void atk68_80246A0(void);
-void atk69_dmg_adjustment2(void);
-void atk6A_removeitem(void);
-void atk6B_atknameinbuff1(void);
-void atk6C_lvlbox_display(void);
-void atk6D_set_sentpokes_values(void);
-void atk6E_set_atk_to_player0(void);
-void atk6F_set_visible(void);
-void atk70_record_ability(void);
-void atk71_buffer_move_to_learn(void);
-void atk72_jump_if_can_run_frombattle(void);
-void atk73_hp_thresholds(void);
-void atk74_hp_thresholds2(void);
-void atk75_8026A58(void);
-void atk76_various(void);
-void atk77_setprotect(void);
-void atk78_faintifabilitynotdamp(void);
-void atk79_setatkhptozero(void);
-void atk7A_jumpwhiletargetvalid(void);
-void atk7B_healhalfHP_if_possible(void);
-void atk7C_8025508(void);
-void atk7D_set_rain(void);
-void atk7E_setreflect(void);
-void atk7F_setseeded(void);
-void atk80_manipulatedamage(void);
-void atk81_setrest(void);
-void atk82_jumpifnotfirstturn(void);
-void atk83_nop(void);
-void atk84_jump_if_cant_sleep(void);
-void atk85_stockpile(void);
-void atk86_stockpiletobasedamage(void);
-void atk87_stockpiletohpheal(void);
-void atk88_negativedamage(void);
-void atk89_statbuffchange(void);
-void atk8A_normalisebuffs(void);
-void atk8B_setbide(void);
-void atk8C_confuseifrepeatingattackends(void);
-void atk8D_setmultihit_counter(void);
-void atk8E_prepare_multihit(void);
-void atk8F_forcerandomswitch(void);
-void atk90_conversion_type_change(void);
-void atk91_givepaydaymoney(void);
-void atk92_setlightscreen(void);
-void atk93_ko_move(void);
-void atk94_gethalfcurrentenemyhp(void);
-void atk95_setsandstorm(void);
-void atk96_weatherdamage(void);
-void atk97_try_infatuation(void);
-void atk98_status_icon_update(void);
-void atk99_setmist(void);
-void atk9A_set_focusenergy(void);
-void atk9B_transformdataexecution(void);
-void atk9C_set_substitute(void);
-void atk9D_copyattack(void);
-void atk9E_metronome(void);
-void atk9F_dmgtolevel(void);
-void atkA0_psywavedamageeffect(void);
-void atkA1_counterdamagecalculator(void);
-void atkA2_mirrorcoatdamagecalculator(void);
-void atkA3_disablelastusedattack(void);
-void atkA4_setencore(void);
-void atkA5_painsplitdmgcalc(void);
-void atkA6_settypetorandomresistance(void);
-void atkA7_setalwayshitflag(void);
-void atkA8_copymovepermanently(void);
-void atkA9_sleeptalk_choose_move(void);
-void atkAA_set_destinybond(void);
-void atkAB_DestinyBondFlagUpdate(void);
-void atkAC_remaininghptopower(void);
-void atkAD_spite_ppreduce(void);
-void atkAE_heal_party_status(void);
-void atkAF_cursetarget(void);
-void atkB0_set_spikes(void);
-void atkB1_set_foresight(void);
-void atkB2_setperishsong(void);
-void atkB3_rolloutdamagecalculation(void);
-void atkB4_jumpifconfusedandstatmaxed(void);
-void atkB5_furycuttercalc(void);
-void atkB6_happinesstodamagecalculation(void);
-void atkB7_presentdamagecalculation(void);
-void atkB8_set_safeguard(void);
-void atkB9_magnitudedamagecalculation(void);
-void atkBA_jumpifnopursuitswitchdmg(void);
-void atkBB_setsunny(void);
-void atkBC_maxattackhalvehp(void);
-void atkBD_copyfoestats(void);
-void atkBE_breakfree(void);
-void atkBF_set_defense_curl(void);
-void atkC0_recoverbasedonsunlight(void);
-void atkC1_hidden_power(void);
-void atkC2_selectnexttarget(void);
-void atkC3_setfutureattack(void);
-void atkC4_beat_up(void);
-void atkC5_hidepreattack(void);
-void atkC6_unhidepostattack(void);
-void atkC7_setminimize(void);
-void atkC8_sethail(void);
-void atkC9_jumpifattackandspecialattackcannotfall(void);
-void atkCA_setforcedtarget(void);
-void atkCB_setcharge(void);
-void atkCC_callterrainattack(void);
-void atkCD_cureifburnedparalysedorpoisoned(void);
-void atkCE_settorment(void);
-void atkCF_jumpifnodamage(void);
-void atkD0_settaunt(void);
-void atkD1_set_helpinghand(void);
-void atkD2_swap_items(void);
-void atkD3_copy_ability(void);
-void atkD4_wish_effect(void);
-void atkD5_setroots(void);
-void atkD6_doubledamagedealtifdamaged(void);
-void atkD7_setyawn(void);
-void atkD8_setdamagetohealthdifference(void);
-void atkD9_scaledamagebyhealthratio(void);
-void atkDA_abilityswap(void);
-void atkDB_imprisoneffect(void);
-void atkDC_setgrudge(void);
-void atkDD_weightdamagecalculation(void);
-void atkDE_asistattackselect(void);
-void atkDF_setmagiccoat(void);
-void atkE0_setstealstatchange(void);
-void atkE1_intimidate_string_loader(void);
-void atkE2_switchout_abilities(void);
-void atkE3_jumpiffainted(void);
-void atkE4_getsecretpowereffect(void);
-void atkE5_pickup(void);
-void atkE6_castform_change_animation(void);
-void atkE7_castform_data_change(void);
-void atkE8_settypebasedhalvers(void);
-void atkE9_setweatherballtype(void);
-void atkEA_recycleitem(void);
-void atkEB_settypetoterrain(void);
-void atkEC_pursuit_sth(void);
-void atkED_802B4B4(void);
-void atkEE_removelightscreenreflect(void);
-void atkEF_pokeball_catch_calculation(void);
-void atkF0_copy_caught_poke(void);
-void atkF1_setpoke_as_caught(void);
-void atkF2_display_dex_info(void);
-void atkF3_nickname_caught_poke(void);
-void atkF4_802BEF0(void);
-void atkF5_removeattackerstatus1(void);
-void atkF6_802BF48(void);
-void atkF7_802BF54(void);
-void sub_8056EF8(void);
-
-void (* const gBattleScriptingCommandsTable[])(void) =
-{
- atk00_attackcanceler,
- atk01_accuracycheck,
- atk02_attackstring,
- atk03_ppreduce,
- atk04_critcalc,
- atk05_damagecalc1,
- atk06_typecalc,
- atk07_dmg_adjustment,
- atk08_dmg_adjustment2,
- atk09_attackanimation,
- atk0A_waitanimation,
- atk0B_healthbarupdate,
- atk0C_datahpupdate,
- atk0D_critmessage,
- atk0E_effectiveness_sound,
- atk0F_resultmessage,
- atk10_printstring,
- atk11_printstring_playeronly,
- atk12_waitmessage,
- atk13_printfromtable,
- atk14_printfromtable_playeronly,
- atk15_seteffectwithchancetarget,
- atk16_seteffectprimary,
- atk17_seteffectsecondary,
- atk18_status_effect_clear,
- atk19_faint_pokemon,
- atk1A_faint_animation,
- atk1B_faint_effects_clear,
- atk1C_jumpifstatus,
- atk1D_jumpifstatus2,
- atk1E_jumpifability,
- atk1F_jumpifsideaffecting,
- atk20_jumpifstat,
- atk21_jumpifstatus3,
- atk22_jumpiftype,
- atk23_getexp,
- atk24,
- atk25_move_values_cleanup,
- atk26_set_multihit,
- atk27_decrement_multihit,
- atk28_goto,
- atk29_jumpifbyte,
- atk2A_jumpifhalfword,
- atk2B_jumpifword,
- atk2C_jumpifarrayequal,
- atk2D_jumpifarraynotequal,
- atk2E_setbyte,
- atk2F_addbyte,
- atk30_subbyte,
- atk31_copyarray,
- atk32_copyarray_withindex,
- atk33_orbyte,
- atk34_orhalfword,
- atk35_orword,
- atk36_bicbyte,
- atk37_bichalfword,
- atk38_bicword,
- atk39_pause,
- atk3A_waitstate,
- atk3B_healthbar_update,
- atk3C_return,
- atk3D_end,
- atk3E_end2,
- atk3F_end3,
- atk40_jump_if_move_affected_by_protect,
- atk41_call,
- atk42_jumpiftype2,
- atk43_jumpifabilitypresent,
- atk44,
- atk45_playanimation,
- atk46_playanimation2,
- atk47_setgraphicalstatchangevalues,
- atk48_playstatchangeanimation,
- atk49_moveendturn,
- atk4A_typecalc2,
- atk4B_return_atk_to_ball,
- atk4C_copy_poke_data,
- atk4D_switch_data_update,
- atk4E_switchin_anim,
- atk4F_jump_if_cannot_switch,
- atk50_openpartyscreen,
- atk51_switch_handle_order,
- atk52_switch_in_effects,
- atk53_trainer_slide,
- atk54_effectiveness_sound,
- atk55_play_sound,
- atk56_fainting_cry,
- atk57,
- atk58_return_to_ball,
- atk59_learnmove_inbattle,
- atk5A,
- atk5B_80256E0,
- atk5C_hitanimation,
- atk5D_getmoneyreward,
- atk5E_8025A70,
- atk5F_8025B24,
- atk60_increment_gamestat,
- atk61_8025BA4,
- atk62_08025C6C,
- atk63_jumptorandomattack,
- atk64_statusanimation,
- atk65_status2animation,
- atk66_chosenstatusanimation,
- atk67_8025ECC,
- atk68_80246A0,
- atk69_dmg_adjustment2,
- atk6A_removeitem,
- atk6B_atknameinbuff1,
- atk6C_lvlbox_display,
- atk6D_set_sentpokes_values,
- atk6E_set_atk_to_player0,
- atk6F_set_visible,
- atk70_record_ability,
- atk71_buffer_move_to_learn,
- atk72_jump_if_can_run_frombattle,
- atk73_hp_thresholds,
- atk74_hp_thresholds2,
- atk75_8026A58,
- atk76_various,
- atk77_setprotect,
- atk78_faintifabilitynotdamp,
- atk79_setatkhptozero,
- atk7A_jumpwhiletargetvalid,
- atk7B_healhalfHP_if_possible,
- atk7C_8025508,
- atk7D_set_rain,
- atk7E_setreflect,
- atk7F_setseeded,
- atk80_manipulatedamage,
- atk81_setrest,
- atk82_jumpifnotfirstturn,
- atk83_nop,
- atk84_jump_if_cant_sleep,
- atk85_stockpile,
- atk86_stockpiletobasedamage,
- atk87_stockpiletohpheal,
- atk88_negativedamage,
- atk89_statbuffchange,
- atk8A_normalisebuffs,
- atk8B_setbide,
- atk8C_confuseifrepeatingattackends,
- atk8D_setmultihit_counter,
- atk8E_prepare_multihit,
- atk8F_forcerandomswitch,
- atk90_conversion_type_change,
- atk91_givepaydaymoney,
- atk92_setlightscreen,
- atk93_ko_move,
- atk94_gethalfcurrentenemyhp,
- atk95_setsandstorm,
- atk96_weatherdamage,
- atk97_try_infatuation,
- atk98_status_icon_update,
- atk99_setmist,
- atk9A_set_focusenergy,
- atk9B_transformdataexecution,
- atk9C_set_substitute,
- atk9D_copyattack,
- atk9E_metronome,
- atk9F_dmgtolevel,
- atkA0_psywavedamageeffect,
- atkA1_counterdamagecalculator,
- atkA2_mirrorcoatdamagecalculator,
- atkA3_disablelastusedattack,
- atkA4_setencore,
- atkA5_painsplitdmgcalc,
- atkA6_settypetorandomresistance,
- atkA7_setalwayshitflag,
- atkA8_copymovepermanently,
- atkA9_sleeptalk_choose_move,
- atkAA_set_destinybond,
- atkAB_DestinyBondFlagUpdate,
- atkAC_remaininghptopower,
- atkAD_spite_ppreduce,
- atkAE_heal_party_status,
- atkAF_cursetarget,
- atkB0_set_spikes,
- atkB1_set_foresight,
- atkB2_setperishsong,
- atkB3_rolloutdamagecalculation,
- atkB4_jumpifconfusedandstatmaxed,
- atkB5_furycuttercalc,
- atkB6_happinesstodamagecalculation,
- atkB7_presentdamagecalculation,
- atkB8_set_safeguard,
- atkB9_magnitudedamagecalculation,
- atkBA_jumpifnopursuitswitchdmg,
- atkBB_setsunny,
- atkBC_maxattackhalvehp,
- atkBD_copyfoestats,
- atkBE_breakfree,
- atkBF_set_defense_curl,
- atkC0_recoverbasedonsunlight,
- atkC1_hidden_power,
- atkC2_selectnexttarget,
- atkC3_setfutureattack,
- atkC4_beat_up,
- atkC5_hidepreattack,
- atkC6_unhidepostattack,
- atkC7_setminimize,
- atkC8_sethail,
- atkC9_jumpifattackandspecialattackcannotfall,
- atkCA_setforcedtarget,
- atkCB_setcharge,
- atkCC_callterrainattack,
- atkCD_cureifburnedparalysedorpoisoned,
- atkCE_settorment,
- atkCF_jumpifnodamage,
- atkD0_settaunt,
- atkD1_set_helpinghand,
- atkD2_swap_items,
- atkD3_copy_ability,
- atkD4_wish_effect,
- atkD5_setroots,
- atkD6_doubledamagedealtifdamaged,
- atkD7_setyawn,
- atkD8_setdamagetohealthdifference,
- atkD9_scaledamagebyhealthratio,
- atkDA_abilityswap,
- atkDB_imprisoneffect,
- atkDC_setgrudge,
- atkDD_weightdamagecalculation,
- atkDE_asistattackselect,
- atkDF_setmagiccoat,
- atkE0_setstealstatchange,
- atkE1_intimidate_string_loader,
- atkE2_switchout_abilities,
- atkE3_jumpiffainted,
- atkE4_getsecretpowereffect,
- atkE5_pickup,
- atkE6_castform_change_animation,
- atkE7_castform_data_change,
- atkE8_settypebasedhalvers,
- atkE9_setweatherballtype,
- atkEA_recycleitem,
- atkEB_settypetoterrain,
- atkEC_pursuit_sth,
- atkED_802B4B4,
- atkEE_removelightscreenreflect,
- atkEF_pokeball_catch_calculation,
- atkF0_copy_caught_poke,
- atkF1_setpoke_as_caught,
- atkF2_display_dex_info,
- atkF3_nickname_caught_poke,
- atkF4_802BEF0,
- atkF5_removeattackerstatus1,
- atkF6_802BF48,
- atkF7_802BF54,
- sub_8056EF8
-};
-
-struct statFractions
-{
- u8 dividend;
- u8 divisor;
-};
-
-const struct statFractions gAccuracyStageRatios[] =
-{
- { 33, 100}, // -6
- { 36, 100}, // -5
- { 43, 100}, // -4
- { 50, 100}, // -3
- { 60, 100}, // -2
- { 75, 100}, // -1
- { 1, 1}, // 0
- {133, 100}, // +1
- {166, 100}, // +2
- { 2, 1}, // +3
- {233, 100}, // +4
- {133, 50}, // +5
- { 3, 1}, // +6
-};
-
-// The chance is 1/N for each stage.
-const u16 gCriticalHitChance[] = {16, 8, 4, 3, 2};
-
-const u32 gStatusFlagsForMoveEffects[] =
-{
- 0x00000000,
- 0x00000007,
- 0x00000008,
- 0x00000010,
- 0x00000020,
- 0x00000040,
- 0x00000080,
- 0x00000007,
- 0x00000008,
- 0x00000000,
- 0x00000070,
- 0x00000000,
- 0x00001000,
- 0x0000E000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00400000,
- 0x00000000,
- 0x00000000,
- 0x04000000,
- 0x08000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000C00,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000,
- 0x00000000
-};
diff --git a/src/battle_ai.c b/src/battle_ai_script_commands.c
index 76bf4156d..dae43f13c 100644
--- a/src/battle_ai.c
+++ b/src/battle_ai_script_commands.c
@@ -1,5 +1,5 @@
#include "global.h"
-#include "battle_ai.h"
+#include "battle_ai_script_commands.h"
#include "pokemon.h"
#include "battle.h"
#include "species.h"
@@ -73,10 +73,7 @@ extern const struct BaseStats gBaseStats[];
extern const u32 gBitTable[];
extern u8 * const gBattleAI_ScriptsTable[];
-extern u8 GetBankIdentity(u8);
extern u8 b_first_side(u8, u8, u8);
-extern u8 GetBankByPlayerAI(u8);
-extern void TypeCalc(u16 move, u8 bankAtk, u8 bankDef);
extern void AI_CalcDmg(u8, u8);
extern u8 CheckMoveLimitations();
@@ -87,7 +84,7 @@ static u8 BattleAI_ChooseMoveOrAction_Singles(void);
static u8 BattleAI_ChooseMoveOrAction_Doubles(void);
static void RecordLastUsedMoveByTarget(void);
static void BattleAI_DoAIProcessing(void);
-static void AIStackPushVar(u8 *);
+static void AIStackPushVar(const u8 *);
static bool8 AIStackPop(void);
static void BattleAICmd_if_random_less_than(void);
@@ -192,7 +189,7 @@ static void BattleAICmd_if_holds_item(void);
// ewram
-EWRAM_DATA u8 *gAIScriptPtr = NULL;
+EWRAM_DATA const u8 *gAIScriptPtr = NULL;
EWRAM_DATA static u8 sBank_AI = 0;
// const rom data
@@ -1805,7 +1802,7 @@ static void BattleAICmd_count_alive_pokemon(void)
u32 status;
bankOnField1 = gBattlePartyID[index];
status = GetBankIdentity(index) ^ 2;
- bankOnField2 = gBattlePartyID[GetBankByPlayerAI(status)];
+ bankOnField2 = gBattlePartyID[GetBankByIdentity(status)];
}
else // in singles there's only one bank by side
{
@@ -2902,7 +2899,7 @@ static void BattleAICmd_if_flash_fired(void)
gAIScriptPtr += 6;
}
-static void AIStackPushVar(u8 *var)
+static void AIStackPushVar(const u8 *var)
{
gBattleResources->AI_ScriptsStack->ptr[gBattleResources->AI_ScriptsStack->size++] = var;
}
diff --git a/src/battle_dome_cards.c b/src/battle_dome_cards.c
new file mode 100644
index 000000000..c0557ac70
--- /dev/null
+++ b/src/battle_dome_cards.c
@@ -0,0 +1,430 @@
+
+// Includes
+#include "global.h"
+#include "sprite.h"
+#include "window.h"
+#include "malloc.h"
+#include "species.h"
+#include "palette.h"
+#include "decompress.h"
+#include "battle_dome_cards.h"
+
+extern const struct CompressedSpriteSheet gMonFrontPicTable[NUM_SPECIES];
+extern const struct CompressedSpriteSheet gMonBackPicTable[NUM_SPECIES];
+extern const struct CompressedSpriteSheet gTrainerFrontPicTable[];
+extern const struct CompressedSpriteSheet gTrainerBackPicTable[];
+extern const struct CompressedSpritePalette gTrainerFrontPicPaletteTable[];
+extern const union AffineAnimCmd *const gUnknown_082FF618[];
+extern const union AffineAnimCmd *const gUnknown_082FF694[];
+extern const union AnimCmd *const gUnknown_082FF70C[];
+extern const union AnimCmd *const *const gUnknown_08309AAC[NUM_SPECIES];
+extern const union AnimCmd *const *const gUnknown_0830536C[];
+extern const u8 gUnknown_0831F578[];
+
+// Static type declarations
+
+struct BattleDomeCard {
+ u8 *frames;
+ struct SpriteFrameImage *images;
+ u16 paletteTag;
+ u8 spriteId;
+ u8 active;
+};
+
+// Static RAM declarations
+
+static EWRAM_DATA struct SpriteTemplate gUnknown_0203CCEC = {};
+static EWRAM_DATA struct BattleDomeCard gUnknown_0203CD04[8] = {};
+
+// Static ROM declarations
+
+// .rodata
+
+static const struct BattleDomeCard gUnknown_0860B058 = {};
+static const struct OamData gUnknown_0860B064 = {
+ .size = 3
+};
+static const struct OamData gUnknown_0860B06C = {
+ .affineMode = 1, .size = 3
+};
+
+// .text
+
+static void nullsub_122(struct Sprite *sprite)
+{
+
+}
+
+bool16 dp13_810BB8C(void)
+{
+ int i;
+
+ for (i = 0; i < 8; i ++)
+ {
+ gUnknown_0203CD04[i] = gUnknown_0860B058;
+ }
+ return FALSE;
+}
+
+static bool16 load_pokemon_image_TODO(u16 species, u32 personality, bool8 isFrontPic, u8 *dest, bool8 isTrainer, bool8 ignoreDeoxys)
+{
+ if (!isTrainer)
+ {
+ if (isFrontPic)
+ {
+ if (!ignoreDeoxys)
+ {
+ LoadSpecialPokePic(&gMonFrontPicTable[species], dest, species, personality, isFrontPic);
+ }
+ else
+ {
+ LoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species], dest, species, personality, isFrontPic);
+ }
+ }
+ else
+ {
+ if (!ignoreDeoxys)
+ {
+ LoadSpecialPokePic(&gMonBackPicTable[species], dest, species, personality, isFrontPic);
+ }
+ else
+ {
+ LoadSpecialPokePic_DontHandleDeoxys(&gMonBackPicTable[species], dest, species, personality, isFrontPic);
+ }
+ }
+ }
+ else
+ {
+ if (isFrontPic)
+ {
+ DecompressPicFromTable(&gTrainerFrontPicTable[species], dest, species);
+ }
+ else
+ {
+ DecompressPicFromTable(&gTrainerBackPicTable[species], dest, species);
+ }
+ }
+ return FALSE;
+}
+
+static bool16 sub_818D09C(u16 species, u32 personality, bool8 isFrontPic, u8 *dest, bool8 isTrainer)
+{
+ return load_pokemon_image_TODO(species, personality, isFrontPic, dest, isTrainer, FALSE);
+}
+
+static void sub_818D0C4(u16 species, u32 otId, u32 personality, u8 paletteSlot, u16 paletteTag, bool8 isTrainer)
+{
+ if (!isTrainer)
+ {
+ if (paletteTag == 0xFFFF)
+ {
+ gUnknown_0203CCEC.paletteTag |= 0xFFFF;
+ LoadCompressedPalette(species_and_otid_get_pal(species, otId, personality), 0x100 + paletteSlot * 0x10, 0x20);
+ }
+ else
+ {
+ gUnknown_0203CCEC.paletteTag = paletteTag;
+ LoadCompressedObjectPalette(sub_806E7CC(species, otId, personality));
+ }
+ }
+ else
+ {
+ if (paletteTag == 0xFFFF)
+ {
+ gUnknown_0203CCEC.paletteTag |= 0xFFFF;
+ LoadCompressedPalette(gTrainerFrontPicPaletteTable[species].data, 0x100 + paletteSlot * 0x10, 0x20);
+ }
+ else
+ {
+ gUnknown_0203CCEC.paletteTag = paletteTag;
+ LoadCompressedObjectPalette(&gTrainerFrontPicPaletteTable[species]);
+ }
+ }
+}
+
+static void sub_818D180(u16 species, u32 otId, u32 personality, u8 paletteSlot, bool8 isTrainer)
+{
+ if (!isTrainer)
+ {
+ LoadCompressedPalette(species_and_otid_get_pal(species, otId, personality), paletteSlot * 0x10, 0x20);
+ }
+ else
+ {
+ LoadCompressedPalette(gTrainerFrontPicPaletteTable[species].data, paletteSlot * 0x10, 0x20);
+ }
+}
+
+static void uns_builder_assign_animtable1(bool8 isTrainer)
+{
+ if (!isTrainer)
+ {
+ gUnknown_0203CCEC.anims = gUnknown_082FF70C;
+ }
+ else
+ {
+ gUnknown_0203CCEC.anims = gUnknown_0830536C[0];
+ }
+}
+
+static u16 oamt_spawn_poke_or_trainer_picture(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag, bool8 isTrainer, bool8 ignoreDeoxys)
+{
+ u8 i;
+ u8 *framePics;
+ struct SpriteFrameImage *images;
+ int j;
+ u8 spriteId;
+
+ for (i = 0; i < 8; i ++)
+ {
+ if (!gUnknown_0203CD04[i].active)
+ {
+ break;
+ }
+ }
+ if (i == 8)
+ {
+ return 0xFFFF;
+ }
+ framePics = Alloc(4 * 0x800);
+ if (!framePics)
+ {
+ return 0xFFFF;
+ }
+ images = Alloc(4 * sizeof(struct SpriteFrameImage));
+ if (!images)
+ {
+ Free(framePics);
+ return 0xFFFF;
+ }
+ if (load_pokemon_image_TODO(species, personality, isFrontPic, framePics, isTrainer, ignoreDeoxys))
+ {
+ // debug trap?
+ return 0xFFFF;
+ }
+ for (j = 0; j < 4; j ++)
+ {
+ images[j].data = framePics + 0x800 * j;
+ images[j].size = 0x800;
+ }
+ gUnknown_0203CCEC.tileTag = 0xFFFF;
+ gUnknown_0203CCEC.oam = &gUnknown_0860B064;
+ uns_builder_assign_animtable1(isTrainer);
+ gUnknown_0203CCEC.images = images;
+ gUnknown_0203CCEC.affineAnims = gDummySpriteAffineAnimTable;
+ gUnknown_0203CCEC.callback = nullsub_122;
+ sub_818D0C4(species, otId, personality, paletteSlot, paletteTag, isTrainer);
+ spriteId = CreateSprite(&gUnknown_0203CCEC, x, y, 0);
+ if (paletteTag == 0xFFFF)
+ {
+ gSprites[spriteId].oam.paletteNum = paletteSlot;
+ }
+ gUnknown_0203CD04[i].frames = framePics;
+ gUnknown_0203CD04[i].images = images;
+ gUnknown_0203CD04[i].paletteTag = paletteTag;
+ gUnknown_0203CD04[i].spriteId = spriteId;
+ gUnknown_0203CD04[i].active = TRUE;
+ return spriteId;
+}
+
+static u16 sub_818D384(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag, bool8 isTrainer)
+{
+ return oamt_spawn_poke_or_trainer_picture(species, otId, personality, isFrontPic, x, y, paletteSlot, paletteTag, isTrainer, FALSE);
+}
+
+u16 sub_818D3E4(u16 species, u32 otId, u32 personality, u8 flags, s16 x, s16 y, u8 paletteSlot, u16 paletteTag)
+{
+ u8 *framePics;
+ struct SpriteFrameImage *images;
+ int j;
+ u8 i;
+ u8 spriteId;
+ u8 flags2;
+
+ for (i = 0; i < 8; i ++)
+ {
+ if (!gUnknown_0203CD04[i].active)
+ {
+ break;
+ }
+ }
+ if (i == 8)
+ {
+ return 0xFFFF;
+ }
+ framePics = Alloc(4 * 0x800);
+ if (!framePics)
+ {
+ return 0xFFFF;
+ }
+ if (flags & 0x80)
+ {
+ flags &= 0x7F;
+ flags2 = 3;
+ }
+ else
+ {
+ flags2 = flags;
+ }
+ images = Alloc(4 * sizeof(struct SpriteFrameImage));
+ if (!images)
+ {
+ Free(framePics);
+ return 0xFFFF;
+ }
+ if (load_pokemon_image_TODO(species, personality, flags, framePics, FALSE, FALSE))
+ {
+ // debug trap?
+ return 0xFFFF;
+ }
+ for (j = 0; j < 4; j ++)
+ {
+ images[j].data = framePics + 0x800 * j;
+ images[j].size = 0x800;
+ }
+ gUnknown_0203CCEC.tileTag = 0xFFFF;
+ gUnknown_0203CCEC.anims = gUnknown_08309AAC[species];
+ gUnknown_0203CCEC.images = images;
+ if (flags2 == 0x01)
+ {
+ gUnknown_0203CCEC.affineAnims = gUnknown_082FF694;
+ gUnknown_0203CCEC.oam = &gUnknown_0860B06C;
+ }
+ else if (flags2 == 0x00)
+ {
+ gUnknown_0203CCEC.affineAnims = gUnknown_082FF618;
+ gUnknown_0203CCEC.oam = &gUnknown_0860B06C;
+ }
+ else
+ {
+ gUnknown_0203CCEC.oam = &gUnknown_0860B064;
+ gUnknown_0203CCEC.affineAnims = gDummySpriteAffineAnimTable;
+ }
+ gUnknown_0203CCEC.callback = nullsub_122;
+ sub_818D0C4(species, otId, personality, paletteSlot, paletteTag, FALSE);
+ spriteId = CreateSprite(&gUnknown_0203CCEC, x, y, 0);
+ if (paletteTag == 0xFFFF)
+ {
+ gSprites[spriteId].oam.paletteNum = paletteSlot;
+ }
+ gUnknown_0203CD04[i].frames = framePics;
+ gUnknown_0203CD04[i].images = images;
+ gUnknown_0203CD04[i].paletteTag = paletteTag;
+ gUnknown_0203CD04[i].spriteId = spriteId;
+ gUnknown_0203CD04[i].active = TRUE;
+ return spriteId;
+}
+
+static u16 sub_818D5B0(u16 spriteId)
+{
+ u8 i;
+ u8 *framePics;
+ struct SpriteFrameImage *images;
+
+ for (i = 0; i < 8; i ++)
+ {
+ if (gUnknown_0203CD04[i].spriteId == spriteId)
+ {
+ break;
+ }
+ }
+ if (i == 8)
+ {
+ return 0xFFFF;
+ }
+ framePics = gUnknown_0203CD04[i].frames;
+ images = gUnknown_0203CD04[i].images;
+ if (gUnknown_0203CD04[i].paletteTag != 0xFFFF)
+ {
+ FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(gSprites[spriteId].oam.paletteNum));
+ }
+ DestroySprite(&gSprites[spriteId]);
+ Free(framePics);
+ Free(images);
+ gUnknown_0203CD04[i] = gUnknown_0860B058;
+ return 0;
+}
+
+static u16 sub_818D65C(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId, bool8 isTrainer)
+{
+ if (sub_818D09C(species, personality, isFrontPic, (u8 *)GetWindowAttribute(windowId, WINDOW_TILE_DATA), FALSE))
+ {
+ return 0xFFFF;
+ }
+ sub_818D180(species, otId, personality, paletteSlot, isTrainer);
+ return 0;
+}
+
+static u16 sub_818D6CC(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId, bool8 isTrainer)
+{
+ u8 *framePics;
+
+ framePics = Alloc(4 * 0x800);
+ if (framePics && !sub_818D09C(species, personality, isFrontPic, framePics, isTrainer))
+ {
+ BlitBitmapRectToWindow(windowId, framePics, 0, 0, 0x40, 0x40, destX, destY, 0x40, 0x40);
+ sub_818D180(species, otId, personality, paletteSlot, isTrainer);
+ Free(framePics);
+ return 0;
+ }
+ return 0xFFFF;
+}
+
+static u16 sub_818D778(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag, bool8 ignoreDeoxys)
+{
+ return oamt_spawn_poke_or_trainer_picture(species, otId, personality, isFrontPic, x, y, paletteSlot, paletteTag, FALSE, ignoreDeoxys);
+}
+
+u16 sub_818D7D8(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag)
+{
+ return sub_818D778(species, otId, personality, isFrontPic, x, y, paletteSlot, paletteTag, FALSE);
+}
+
+u16 sub_818D820(u16 spriteId)
+{
+ return sub_818D5B0(spriteId);
+}
+
+u16 sub_818D834(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId)
+{
+ return sub_818D65C(species, otId, personality, isFrontPic, paletteSlot, windowId, FALSE);
+}
+
+u16 sub_818D864(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId)
+{
+ return sub_818D6CC(species, otId, personality, isFrontPic, destX, destY, paletteSlot, windowId, FALSE);
+}
+
+u16 sub_818D8AC(u16 species, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag)
+{
+ return sub_818D384(species, 0, 0, isFrontPic, x, y, paletteSlot, paletteTag, TRUE);
+}
+
+u16 sub_818D8F0(u16 spriteId)
+{
+ return sub_818D5B0(spriteId);
+}
+
+u16 sub_818D904(u16 species, bool8 isFrontPic, u8 paletteSlot, u8 windowId)
+{
+ return sub_818D65C(species, 0, 0, isFrontPic, paletteSlot, windowId, TRUE);
+}
+
+u16 sub_818D938(u16 species, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId)
+{
+ return sub_818D6CC(species, 0, 0, isFrontPic, destX, destY, paletteSlot, windowId, TRUE);
+}
+
+u8 sub_818D97C(u8 a0, u8 a1)
+{
+ if (a1 == 1)
+ {
+ switch (a0)
+ {
+ default:
+ return gUnknown_0831F578[0x3F];
+ case 0:
+ return gUnknown_0831F578[0x3C];
+ }
+ }
+ return a0;
+}
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
new file mode 100644
index 000000000..e0cb3e941
--- /dev/null
+++ b/src/battle_script_commands.c
@@ -0,0 +1,11415 @@
+#include "global.h"
+#include "battle.h"
+#include "battle_move_effects.h"
+#include "battle_message.h"
+#include "battle_ai_script_commands.h"
+#include "moves.h"
+#include "abilities.h"
+#include "item.h"
+#include "items.h"
+#include "hold_effects.h"
+#include "util.h"
+#include "pokemon.h"
+#include "calculate_base_damage.h"
+#include "rng.h"
+#include "battle_controllers.h"
+#include "species.h"
+#include "songs.h"
+#include "text.h"
+#include "sound.h"
+#include "pokedex.h"
+#include "recorded_battle.h"
+#include "window.h"
+#include "reshow_battle_screen.h"
+#include "main.h"
+#include "palette.h"
+#include "money.h"
+#include "bg.h"
+#include "string_util.h"
+#include "pokemon_icon.h"
+#include "pokemon_item_effects.h"
+#include "m4a.h"
+#include "mail.h"
+#include "event_data.h"
+#include "pokemon_storage_system.h"
+#include "task.h"
+#include "naming_screen.h"
+
+// variables
+
+extern u8 gCritMultiplier;
+extern s32 gBattleMoveDamage;
+extern u32 gStatuses3[BATTLE_BANKS_COUNT];
+extern u32 gBattleTypeFlags;
+extern struct BattleEnigmaBerry gEnigmaBerries[BATTLE_BANKS_COUNT];
+extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT];
+extern u8 gActiveBank;
+extern u32 gBattleExecBuffer;
+extern u8 gNoOfAllBanks;
+extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
+extern u8 gTurnOrder[BATTLE_BANKS_COUNT];
+extern u8 gUnknown_0202407A[BATTLE_BANKS_COUNT];
+extern u16 gCurrentMove;
+extern u8 gLastUsedAbility;
+extern u16 gBattleWeather;
+extern u8 gStringBank;
+extern u8 gEffectBank;
+extern u8 gAbsentBankFlags;
+extern u8 gMultiHitCounter;
+extern u16 gChosenMovesByBanks[BATTLE_BANKS_COUNT];
+extern u16 gSideAffecting[2];
+extern u16 gPauseCounterBattle;
+extern u16 gPaydayMoney;
+extern u16 gRandomTurnNumber;
+extern u8 gBattleOutcome;
+extern u8 gBattleTerrain;
+extern u8 gBankAttacker;
+extern u8 gBankTarget;
+extern const u8* gBattlescriptCurrInstr;
+extern u8 gCurrMovePos;
+extern u8 gFightStateTracker;
+extern u32 gHitMarker;
+extern u8 gBattleMoveFlags;
+extern u8 gBattleCommunication[];
+extern u16 gUnknown_02024250[4];
+extern u16 gUnknown_02024258[4];
+extern u16 gUnknown_02024260[4];
+extern u8 gUnknown_02024270[4];
+extern u8 gStringBank;
+extern u16 gDynamicBasePower;
+extern u16 gLastUsedItem;
+extern u16 gBattleMovePower;
+extern s32 gHpDealt;
+extern s32 gTakenDmg[BATTLE_BANKS_COUNT];
+extern u8 gTakenDmgBanks[BATTLE_BANKS_COUNT];
+extern u8 gSentPokesToOpponent[2];
+extern u8 gBank1;
+extern u16 gExpShareExp;
+extern u8 gLeveledUpInBattle;
+extern void (*gBattleMainFunc)(void);
+extern u8 gPlayerPartyCount;
+extern u16 gMoveToLearn;
+extern u16 gRandomMove;
+extern u8 gBankInMenu;
+extern u8 gActionForBanks[BATTLE_BANKS_COUNT];
+extern u8 gCurrentMoveTurn;
+extern u8 gBattleBufferB[BATTLE_BANKS_COUNT][0x200];
+extern u16 gLockedMoves[BATTLE_BANKS_COUNT];
+extern u16 gPartnerTrainerId;
+extern u16 gLastUsedMove;
+extern u16 gUnknownMovesUsedByBanks[BATTLE_BANKS_COUNT];
+extern u16 gLastUsedMovesByBanks[BATTLE_BANKS_COUNT];
+extern u16 gTrainerBattleOpponent_A;
+extern u16 gTrainerBattleOpponent_B;
+extern u8 gUnknown_020241E9;
+extern u16 gBattle_BG1_X;
+extern u16 gBattle_BG1_Y;
+extern u16 gBattle_BG2_X;
+extern u16 gBattle_BG2_Y;
+extern u16 gBattle_BG3_X;
+extern struct MusicPlayerInfo gMPlay_BGM;
+
+struct TrainerMoney
+{
+ u8 classId;
+ u8 value;
+};
+
+extern const struct BattleMove gBattleMoves[];
+extern const struct BaseStats gBaseStats[];
+extern const u8 gTypeEffectiveness[];
+extern const u16 gMissStringIds[];
+extern const u16 gTrappingMoves[];
+extern const struct TrainerMoney gTrainerMoneyTable[];
+extern const u8* const gBattleScriptsForMoveEffects[];
+
+// functions
+extern void sub_81A5718(u8 bank); // battle frontier 2
+extern void sub_81A56B4(void); // battle frontier 2
+extern void sub_81BFA38(struct Pokemon* party, u8 monPartyId, u8 monCount, void (*callback)(void), u16 move); // pokemon summary screen
+extern u8 sub_81C1B94(void); // pokemon summary screen
+extern void IncrementGameStat(u8 statId); // rom_4
+extern void sub_81D388C(struct Pokemon* mon, void* statStoreLocation); // pokenav.s
+extern void sub_81D3640(u8 arg0, void* statStoreLocation1, void* statStoreLocation2, u8 arg3, u8 arg4, u8 arg5); // pokenav.s
+extern void sub_81D3784(u8 arg0, void* statStoreLocation1, u8 arg2, u8 arg3, u8 arg4); // pokenav.s
+extern u8* GetMonNickname(struct Pokemon* mon, u8* dst); // party_menu
+extern u8 sub_81A5258(u8* arg0); // battle frontier 2
+extern void sub_81A5BF8(void); // battle frontier 2
+extern void sub_81A5D44(void); // battle frontier 2
+extern void sub_81B8E80(u8 bank, u8, u8); // party menu
+extern bool8 sub_81B1250(void); // ?
+extern u8 GetScaledHPFraction(s16 hp, s16 maxhp, u8 scale); // battle interface
+extern bool8 InBattlePike(void);
+extern bool8 InBattlePyramid(void);
+extern u16 GetBattlePyramidPickupItemId(void);
+extern u8 sav1_map_get_light_level(void);
+extern u8 sub_813B21C(void);
+extern u16 get_unknown_box_id(void);
+extern void c2_berry_program_update_menu(void);
+extern void sub_8035AA4(void);
+
+// BattleScripts
+extern const u8 BattleScript_MoveEnd[];
+extern const u8 BattleScript_NoPPForMove[];
+extern const u8 BattleScript_MagicCoatBounce[];
+extern const u8 BattleScript_TookAttack[];
+extern const u8 BattleScript_SnatchedMove[];
+extern const u8 BattleScript_Pausex20[];
+extern const u8 BattleScript_SubstituteFade[];
+extern const u8 BattleScript_HangedOnMsg[];
+extern const u8 BattleScript_OneHitKOMsg[];
+extern const u8 BattleScript_EnduredMsg[];
+extern const u8 BattleScript_PSNPrevention[];
+extern const u8 BattleScript_BRNPrevention[];
+extern const u8 BattleScript_PRLZPrevention[];
+extern const u8 BattleScript_FlinchPrevention[];
+extern const u8 BattleScript_StatUp[];
+extern const u8 BattleScript_StatDown[];
+extern const u8 BattleScript_NoItemSteal[];
+extern const u8 BattleScript_ItemSteal[];
+extern const u8 BattleScript_RapidSpinAway[];
+extern const u8 BattleScript_TargetPRLZHeal[];
+extern const u8 BattleScript_KnockedOff[];
+extern const u8 BattleScript_StickyHoldActivates[];
+extern const u8 BattleScript_AllStatsUp[];
+extern const u8 BattleScript_AtkDefDown[];
+extern const u8 BattleScript_SAtkDown2[];
+extern const u8 BattleScript_LevelUp[];
+extern const u8 BattleScript_WrapFree[];
+extern const u8 BattleScript_LeechSeedFree[];
+extern const u8 BattleScript_SpikesFree[];
+extern const u8 BattleScript_ButItFailed[];
+extern const u8 BattleScript_ObliviousPreventsAttraction[];
+extern const u8 BattleScript_MistProtected[];
+extern const u8 BattleScript_AbilityNoStatLoss[];
+extern const u8 BattleScript_AbilityNoSpecificStatLoss[];
+extern const u8 BattleScript_TrainerBallBlock[];
+extern const u8 BattleScript_WallyBallThrow[];
+extern const u8 BattleScript_SuccessBallThrow[];
+extern const u8 BattleScript_ShakeBallThrow[];
+extern const u8 BattleScript_FaintAttacker[];
+extern const u8 BattleScript_FaintTarget[];
+extern const u8 BattleScript_DestinyBondTakesLife[];
+extern const u8 BattleScript_GrudgeTakesPp[];
+extern const u8 BattleScript_RageIsBuilding[];
+extern const u8 BattleScript_DefrostedViaFireMove[];
+extern const u8 gUnknown_082DB87D[];
+extern const u8 gUnknown_082DAE90[];
+extern const u8 gUnknown_082DAE59[];
+extern const u8 gUnknown_082DAEC7[];
+extern const u8 BattleScript_MoveEffectSleep[];
+extern const u8 BattleScript_MoveEffectPoison[];
+extern const u8 BattleScript_MoveEffectBurn[];
+extern const u8 BattleScript_MoveEffectFreeze[];
+extern const u8 BattleScript_MoveEffectParalysis[];
+extern const u8 BattleScript_MoveEffectToxic[];
+extern const u8 BattleScript_MoveEffectConfusion[];
+extern const u8 BattleScript_MoveEffectUproar[];
+extern const u8 BattleScript_MoveEffectPayDay[];
+extern const u8 BattleScript_MoveEffectWrap[];
+extern const u8 BattleScript_MoveEffectRecoil33[];
+extern const u8 BattleScript_DampStopsExplosion[];
+extern const u8 BattleScript_MistProtected[];
+extern const u8 BattleScript_AbilityNoStatLoss[];
+extern const u8 BattleScript_AbilityNoSpecificStatLoss[];
+extern const u8 BattleScript_ButItFailed[];
+extern const u8 gUnknown_082DADD8[];
+extern const u8 BattleScript_PrintPayDayMoneyString[];
+extern const u8 BattleScript_SturdyPreventsOHKO[];
+extern const u8 BattleScript_ObliviousPreventsAttraction[];
+extern const u8 BattleScript_PauseEffectivenessSoundResultMsgEndMove[];
+extern const u8 BattleScript_CastformChange[];
+extern const u8 BattleScript_TrainerBallBlock[];
+extern const u8 BattleScript_WallyBallThrow[];
+extern const u8 BattleScript_SuccessBallThrow[];
+extern const u8 BattleScript_ShakeBallThrow[];
+extern const u8 BattleScript_PresentDamageTarget[];
+extern const u8 BattleScript_AlreadyAtFullHp[];
+extern const u8 BattleScript_PresentHealTarget[];
+extern const u8 BattleScript_WrapFree[];
+extern const u8 BattleScript_LeechSeedFree[];
+extern const u8 BattleScript_SpikesFree[];
+
+// strings
+extern const u8 gText_BattleYesNoChoice[];
+
+// read via orr
+#define BSScriptRead32(ptr) ((ptr)[0] | (ptr)[1] << 8 | (ptr)[2] << 16 | (ptr)[3] << 24)
+#define BSScriptRead16(ptr) ((ptr)[0] | ((ptr)[1] << 8))
+#define BSScriptReadPtr(ptr) ((void *)BSScriptRead32(ptr))
+
+// read via add
+#define BS2ScriptRead32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
+#define BS2ScriptRead16(ptr) ((ptr)[0] + ((ptr)[1] << 8))
+#define BS2ScriptReadPtr(ptr) ((void *)BS2ScriptRead32(ptr))
+
+#define TARGET_PROTECT_AFFECTED ((gProtectStructs[gBankTarget].protected && gBattleMoves[gCurrentMove].flags & FLAG_PROTECT_AFFECTED))
+
+#define TARGET_TURN_DAMAGED (((gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_special)))
+
+// this file's functions
+static bool8 IsTwoTurnsMove(u16 move);
+static void DestinyBondFlagUpdate(void);
+static u8 AttacksThisTurn(u8 bank, u16 move); // Note: returns 1 if it's a charging turn, otherwise 2.
+static void CheckWonderGuardAndLevitate(void);
+static u8 ChangeStatBuffs(s8 statValue, u8 statId, u8, const u8* BS_ptr);
+static bool32 IsMonGettingExpSentOut(void);
+static void sub_804F17C(void);
+static bool8 sub_804F1CC(void);
+static void sub_804F100(void);
+static void sub_804F144(void);
+static bool8 sub_804F344(void);
+static void PutMonIconOnLvlUpBox(void);
+static void PutLevelAndGenderOnLvlUpBox(void);
+
+static void SpriteCB_MonIconOnLvlUpBox(struct Sprite* sprite);
+
+static void atk00_attackcanceler(void);
+static void atk01_accuracycheck(void);
+static void atk02_attackstring(void);
+static void atk03_ppreduce(void);
+static void atk04_critcalc(void);
+static void atk05_damagecalc1(void);
+static void atk06_typecalc(void);
+static void atk07_dmg_adjustment(void);
+static void atk08_dmg_adjustment2(void);
+static void atk09_attackanimation(void);
+static void atk0A_waitanimation(void);
+static void atk0B_healthbarupdate(void);
+static void atk0C_datahpupdate(void);
+static void atk0D_critmessage(void);
+static void atk0E_effectiveness_sound(void);
+static void atk0F_resultmessage(void);
+static void atk10_printstring(void);
+static void atk11_printstring_playeronly(void);
+static void atk12_waitmessage(void);
+static void atk13_printfromtable(void);
+static void atk14_printfromtable_playeronly(void);
+static void atk15_seteffectwithchance(void);
+static void atk16_seteffectprimary(void);
+static void atk17_seteffectsecondary(void);
+static void atk18_status_effect_clear(void);
+static void atk19_faint_pokemon(void);
+static void atk1A_faint_animation(void);
+static void atk1B_faint_effects_clear(void);
+static void atk1C_jumpifstatus(void);
+static void atk1D_jumpifstatus2(void);
+static void atk1E_jumpifability(void);
+static void atk1F_jumpifsideaffecting(void);
+static void atk20_jumpifstat(void);
+static void atk21_jumpifstatus3(void);
+static void atk22_jumpiftype(void);
+static void atk23_getexp(void);
+static void atk24(void);
+static void atk25_move_values_cleanup(void);
+static void atk26_set_multihit(void);
+static void atk27_decrement_multihit(void);
+static void atk28_goto(void);
+static void atk29_jumpifbyte(void);
+static void atk2A_jumpifhalfword(void);
+static void atk2B_jumpifword(void);
+static void atk2C_jumpifarrayequal(void);
+static void atk2D_jumpifarraynotequal(void);
+static void atk2E_setbyte(void);
+static void atk2F_addbyte(void);
+static void atk30_subbyte(void);
+static void atk31_copyarray(void);
+static void atk32_copyarray_withindex(void);
+static void atk33_orbyte(void);
+static void atk34_orhalfword(void);
+static void atk35_orword(void);
+static void atk36_bicbyte(void);
+static void atk37_bichalfword(void);
+static void atk38_bicword(void);
+static void atk39_pause(void);
+static void atk3A_waitstate(void);
+static void atk3B_healthbar_update(void);
+static void atk3C_return(void);
+static void atk3D_end(void);
+static void atk3E_end2(void);
+static void atk3F_end3(void);
+static void atk40_jump_if_move_affected_by_protect(void);
+static void atk41_call(void);
+static void atk42_jumpiftype2(void);
+static void atk43_jumpifabilitypresent(void);
+static void atk44(void);
+static void atk45_playanimation(void);
+static void atk46_playanimation2(void);
+static void atk47_setgraphicalstatchangevalues(void);
+static void atk48_playstatchangeanimation(void);
+static void atk49_moveend(void);
+static void atk4A_typecalc2(void);
+static void atk4B_return_atk_to_ball(void);
+static void atk4C_copy_poke_data(void);
+static void atk4D_switch_data_update(void);
+static void atk4E_switchin_anim(void);
+static void atk4F_jump_if_cannot_switch(void);
+static void atk50_openpartyscreen(void);
+static void atk51_switch_handle_order(void);
+static void atk52_switch_in_effects(void);
+static void atk53_trainer_slide(void);
+static void atk54_effectiveness_sound(void);
+static void atk55_play_sound(void);
+static void atk56_fainting_cry(void);
+static void atk57(void);
+static void atk58_return_to_ball(void);
+static void atk59_learnmove_inbattle(void);
+static void atk5A_yesnoboxlearnmove(void);
+static void atk5B_yesnoboxstoplearningmove(void);
+static void atk5C_hitanimation(void);
+static void atk5D_getmoneyreward(void);
+static void atk5E_8025A70(void);
+static void atk5F_8025B24(void);
+static void atk60_increment_gamestat(void);
+static void atk61_8025BA4(void);
+static void atk62_08025C6C(void);
+static void atk63_jumptorandomattack(void);
+static void atk64_statusanimation(void);
+static void atk65_status2animation(void);
+static void atk66_chosenstatusanimation(void);
+static void atk67_yesnobox(void);
+static void atk68_80246A0(void);
+static void atk69_dmg_adjustment3(void);
+static void atk6A_removeitem(void);
+static void atk6B_atknameinbuff1(void);
+static void atk6C_draw_lvlupbox(void);
+static void atk6D_reset_sentpokes_value(void);
+static void atk6E_set_atk_to_player0(void);
+static void atk6F_set_visible(void);
+static void atk70_record_last_used_ability(void);
+static void atk71_buffer_move_to_learn(void);
+static void atk72_jump_if_can_run_frombattle(void);
+static void atk73_hp_thresholds(void);
+static void atk74_hp_thresholds2(void);
+static void atk75_item_effect_on_opponent(void);
+static void atk76_various(void);
+static void atk77_set_protect_like(void);
+static void atk78_faintifabilitynotdamp(void);
+static void atk79_setatkhptozero(void);
+static void atk7A_jumpwhiletargetvalid(void);
+static void atk7B_healhalfHP_if_possible(void);
+static void atk7C_trymirrormove(void);
+static void atk7D_set_rain(void);
+static void atk7E_setreflect(void);
+static void atk7F_setseeded(void);
+static void atk80_manipulatedamage(void);
+static void atk81_setrest(void);
+static void atk82_jumpifnotfirstturn(void);
+static void atk83_nop(void);
+static void atk84_jump_if_cant_sleep(void);
+static void atk85_stockpile(void);
+static void atk86_stockpiletobasedamage(void);
+static void atk87_stockpiletohpheal(void);
+static void atk88_negativedamage(void);
+static void atk89_statbuffchange(void);
+static void atk8A_normalisebuffs(void);
+static void atk8B_setbide(void);
+static void atk8C_confuseifrepeatingattackends(void);
+static void atk8D_setmultihit_counter(void);
+static void atk8E_init_multihit_string(void);
+static void atk8F_forcerandomswitch(void);
+static void atk90_conversion_type_change(void);
+static void atk91_givepaydaymoney(void);
+static void atk92_setlightscreen(void);
+static void atk93_ko_move(void);
+static void atk94_damagetohalftargethp(void);
+static void atk95_setsandstorm(void);
+static void atk96_weatherdamage(void);
+static void atk97_try_infatuation(void);
+static void atk98_status_icon_update(void);
+static void atk99_setmist(void);
+static void atk9A_set_focusenergy(void);
+static void atk9B_transformdataexecution(void);
+static void atk9C_set_substitute(void);
+static void atk9D_mimicattackcopy(void);
+static void atk9E_metronome(void);
+static void atk9F_dmgtolevel(void);
+static void atkA0_psywavedamageeffect(void);
+static void atkA1_counterdamagecalculator(void);
+static void atkA2_mirrorcoatdamagecalculator(void);
+static void atkA3_disablelastusedattack(void);
+static void atkA4_setencore(void);
+static void atkA5_painsplitdmgcalc(void);
+static void atkA6_settypetorandomresistance(void);
+static void atkA7_setalwayshitflag(void);
+static void atkA8_copymovepermanently(void);
+static void atkA9_sleeptalk_choose_move(void);
+static void atkAA_set_destinybond(void);
+static void atkAB_DestinyBondFlagUpdate(void);
+static void atkAC_remaininghptopower(void);
+static void atkAD_spite_ppreduce(void);
+static void atkAE_heal_party_status(void);
+static void atkAF_cursetarget(void);
+static void atkB0_set_spikes(void);
+static void atkB1_set_foresight(void);
+static void atkB2_setperishsong(void);
+static void atkB3_rolloutdamagecalculation(void);
+static void atkB4_jumpifconfusedandstatmaxed(void);
+static void atkB5_furycuttercalc(void);
+static void atkB6_happinesstodamagecalculation(void);
+static void atkB7_presentdamagecalculation(void);
+static void atkB8_set_safeguard(void);
+static void atkB9_magnitudedamagecalculation(void);
+static void atkBA_jumpifnopursuitswitchdmg(void);
+static void atkBB_setsunny(void);
+static void atkBC_maxattackhalvehp(void);
+static void atkBD_copyfoestats(void);
+static void atkBE_rapidspinfree(void);
+static void atkBF_set_defense_curl(void);
+static void atkC0_recoverbasedonsunlight(void);
+static void atkC1_hidden_power(void);
+static void atkC2_selectnexttarget(void);
+static void atkC3_setfutureattack(void);
+static void atkC4_beat_up(void);
+static void atkC5_setsemiinvulnerablebit(void);
+static void atkC6_clearsemiinvulnerablebit(void);
+static void atkC7_setminimize(void);
+static void atkC8_sethail(void);
+static void atkC9_jumpifattackandspecialattackcannotfall(void);
+static void atkCA_setforcedtarget(void);
+static void atkCB_setcharge(void);
+static void atkCC_callterrainattack(void);
+static void atkCD_cureifburnedparalysedorpoisoned(void);
+static void atkCE_settorment(void);
+static void atkCF_jumpifnodamage(void);
+static void atkD0_settaunt(void);
+static void atkD1_set_helpinghand(void);
+static void atkD2_swap_items(void);
+static void atkD3_copy_ability(void);
+static void atkD4_wish_effect(void);
+static void atkD5_setroots(void);
+static void atkD6_doubledamagedealtifdamaged(void);
+static void atkD7_setyawn(void);
+static void atkD8_setdamagetohealthdifference(void);
+static void atkD9_scaledamagebyhealthratio(void);
+static void atkDA_abilityswap(void);
+static void atkDB_imprisoneffect(void);
+static void atkDC_setgrudge(void);
+static void atkDD_weightdamagecalculation(void);
+static void atkDE_asistattackselect(void);
+static void atkDF_setmagiccoat(void);
+static void atkE0_setstealstatchange(void);
+static void atkE1_intimidate_string_loader(void);
+static void atkE2_switchout_abilities(void);
+static void atkE3_jumpifhasnohp(void);
+static void atkE4_getsecretpowereffect(void);
+static void atkE5_pickup(void);
+static void atkE6_castform_change_animation(void);
+static void atkE7_castform_data_change(void);
+static void atkE8_settypebasedhalvers(void);
+static void atkE9_setweatherballtype(void);
+static void atkEA_recycleitem(void);
+static void atkEB_settypetoterrain(void);
+static void atkEC_pursuit_sth(void);
+static void atkED_802B4B4(void);
+static void atkEE_removelightscreenreflect(void);
+static void atkEF_pokeball_catch_calculation(void);
+static void atkF0_give_caught_mon(void);
+static void atkF1_set_caught_mon_dex_flags(void);
+static void atkF2_display_dex_info(void);
+static void atkF3_nickname_caught_poke(void);
+static void atkF4_subattackerhpbydmg(void);
+static void atkF5_removeattackerstatus1(void);
+static void atkF6_802BF48(void);
+static void atkF7_802BF54(void);
+static void atkF8_trainer_slide_back(void);
+
+void (* const gBattleScriptingCommandsTable[])(void) =
+{
+ atk00_attackcanceler,
+ atk01_accuracycheck,
+ atk02_attackstring,
+ atk03_ppreduce,
+ atk04_critcalc,
+ atk05_damagecalc1,
+ atk06_typecalc,
+ atk07_dmg_adjustment,
+ atk08_dmg_adjustment2,
+ atk09_attackanimation,
+ atk0A_waitanimation,
+ atk0B_healthbarupdate,
+ atk0C_datahpupdate,
+ atk0D_critmessage,
+ atk0E_effectiveness_sound,
+ atk0F_resultmessage,
+ atk10_printstring,
+ atk11_printstring_playeronly,
+ atk12_waitmessage,
+ atk13_printfromtable,
+ atk14_printfromtable_playeronly,
+ atk15_seteffectwithchance,
+ atk16_seteffectprimary,
+ atk17_seteffectsecondary,
+ atk18_status_effect_clear,
+ atk19_faint_pokemon,
+ atk1A_faint_animation,
+ atk1B_faint_effects_clear,
+ atk1C_jumpifstatus,
+ atk1D_jumpifstatus2,
+ atk1E_jumpifability,
+ atk1F_jumpifsideaffecting,
+ atk20_jumpifstat,
+ atk21_jumpifstatus3,
+ atk22_jumpiftype,
+ atk23_getexp,
+ atk24,
+ atk25_move_values_cleanup,
+ atk26_set_multihit,
+ atk27_decrement_multihit,
+ atk28_goto,
+ atk29_jumpifbyte,
+ atk2A_jumpifhalfword,
+ atk2B_jumpifword,
+ atk2C_jumpifarrayequal,
+ atk2D_jumpifarraynotequal,
+ atk2E_setbyte,
+ atk2F_addbyte,
+ atk30_subbyte,
+ atk31_copyarray,
+ atk32_copyarray_withindex,
+ atk33_orbyte,
+ atk34_orhalfword,
+ atk35_orword,
+ atk36_bicbyte,
+ atk37_bichalfword,
+ atk38_bicword,
+ atk39_pause,
+ atk3A_waitstate,
+ atk3B_healthbar_update,
+ atk3C_return,
+ atk3D_end,
+ atk3E_end2,
+ atk3F_end3,
+ atk40_jump_if_move_affected_by_protect,
+ atk41_call,
+ atk42_jumpiftype2,
+ atk43_jumpifabilitypresent,
+ atk44,
+ atk45_playanimation,
+ atk46_playanimation2,
+ atk47_setgraphicalstatchangevalues,
+ atk48_playstatchangeanimation,
+ atk49_moveend,
+ atk4A_typecalc2,
+ atk4B_return_atk_to_ball,
+ atk4C_copy_poke_data,
+ atk4D_switch_data_update,
+ atk4E_switchin_anim,
+ atk4F_jump_if_cannot_switch,
+ atk50_openpartyscreen,
+ atk51_switch_handle_order,
+ atk52_switch_in_effects,
+ atk53_trainer_slide,
+ atk54_effectiveness_sound,
+ atk55_play_sound,
+ atk56_fainting_cry,
+ atk57,
+ atk58_return_to_ball,
+ atk59_learnmove_inbattle,
+ atk5A_yesnoboxlearnmove,
+ atk5B_yesnoboxstoplearningmove,
+ atk5C_hitanimation,
+ atk5D_getmoneyreward,
+ atk5E_8025A70,
+ atk5F_8025B24,
+ atk60_increment_gamestat,
+ atk61_8025BA4,
+ atk62_08025C6C,
+ atk63_jumptorandomattack,
+ atk64_statusanimation,
+ atk65_status2animation,
+ atk66_chosenstatusanimation,
+ atk67_yesnobox,
+ atk68_80246A0,
+ atk69_dmg_adjustment3,
+ atk6A_removeitem,
+ atk6B_atknameinbuff1,
+ atk6C_draw_lvlupbox,
+ atk6D_reset_sentpokes_value,
+ atk6E_set_atk_to_player0,
+ atk6F_set_visible,
+ atk70_record_last_used_ability,
+ atk71_buffer_move_to_learn,
+ atk72_jump_if_can_run_frombattle,
+ atk73_hp_thresholds,
+ atk74_hp_thresholds2,
+ atk75_item_effect_on_opponent,
+ atk76_various,
+ atk77_set_protect_like,
+ atk78_faintifabilitynotdamp,
+ atk79_setatkhptozero,
+ atk7A_jumpwhiletargetvalid,
+ atk7B_healhalfHP_if_possible,
+ atk7C_trymirrormove,
+ atk7D_set_rain,
+ atk7E_setreflect,
+ atk7F_setseeded,
+ atk80_manipulatedamage,
+ atk81_setrest,
+ atk82_jumpifnotfirstturn,
+ atk83_nop,
+ atk84_jump_if_cant_sleep,
+ atk85_stockpile,
+ atk86_stockpiletobasedamage,
+ atk87_stockpiletohpheal,
+ atk88_negativedamage,
+ atk89_statbuffchange,
+ atk8A_normalisebuffs,
+ atk8B_setbide,
+ atk8C_confuseifrepeatingattackends,
+ atk8D_setmultihit_counter,
+ atk8E_init_multihit_string,
+ atk8F_forcerandomswitch,
+ atk90_conversion_type_change,
+ atk91_givepaydaymoney,
+ atk92_setlightscreen,
+ atk93_ko_move,
+ atk94_damagetohalftargethp,
+ atk95_setsandstorm,
+ atk96_weatherdamage,
+ atk97_try_infatuation,
+ atk98_status_icon_update,
+ atk99_setmist,
+ atk9A_set_focusenergy,
+ atk9B_transformdataexecution,
+ atk9C_set_substitute,
+ atk9D_mimicattackcopy,
+ atk9E_metronome,
+ atk9F_dmgtolevel,
+ atkA0_psywavedamageeffect,
+ atkA1_counterdamagecalculator,
+ atkA2_mirrorcoatdamagecalculator,
+ atkA3_disablelastusedattack,
+ atkA4_setencore,
+ atkA5_painsplitdmgcalc,
+ atkA6_settypetorandomresistance,
+ atkA7_setalwayshitflag,
+ atkA8_copymovepermanently,
+ atkA9_sleeptalk_choose_move,
+ atkAA_set_destinybond,
+ atkAB_DestinyBondFlagUpdate,
+ atkAC_remaininghptopower,
+ atkAD_spite_ppreduce,
+ atkAE_heal_party_status,
+ atkAF_cursetarget,
+ atkB0_set_spikes,
+ atkB1_set_foresight,
+ atkB2_setperishsong,
+ atkB3_rolloutdamagecalculation,
+ atkB4_jumpifconfusedandstatmaxed,
+ atkB5_furycuttercalc,
+ atkB6_happinesstodamagecalculation,
+ atkB7_presentdamagecalculation,
+ atkB8_set_safeguard,
+ atkB9_magnitudedamagecalculation,
+ atkBA_jumpifnopursuitswitchdmg,
+ atkBB_setsunny,
+ atkBC_maxattackhalvehp,
+ atkBD_copyfoestats,
+ atkBE_rapidspinfree,
+ atkBF_set_defense_curl,
+ atkC0_recoverbasedonsunlight,
+ atkC1_hidden_power,
+ atkC2_selectnexttarget,
+ atkC3_setfutureattack,
+ atkC4_beat_up,
+ atkC5_setsemiinvulnerablebit,
+ atkC6_clearsemiinvulnerablebit,
+ atkC7_setminimize,
+ atkC8_sethail,
+ atkC9_jumpifattackandspecialattackcannotfall,
+ atkCA_setforcedtarget,
+ atkCB_setcharge,
+ atkCC_callterrainattack,
+ atkCD_cureifburnedparalysedorpoisoned,
+ atkCE_settorment,
+ atkCF_jumpifnodamage,
+ atkD0_settaunt,
+ atkD1_set_helpinghand,
+ atkD2_swap_items,
+ atkD3_copy_ability,
+ atkD4_wish_effect,
+ atkD5_setroots,
+ atkD6_doubledamagedealtifdamaged,
+ atkD7_setyawn,
+ atkD8_setdamagetohealthdifference,
+ atkD9_scaledamagebyhealthratio,
+ atkDA_abilityswap,
+ atkDB_imprisoneffect,
+ atkDC_setgrudge,
+ atkDD_weightdamagecalculation,
+ atkDE_asistattackselect,
+ atkDF_setmagiccoat,
+ atkE0_setstealstatchange,
+ atkE1_intimidate_string_loader,
+ atkE2_switchout_abilities,
+ atkE3_jumpifhasnohp,
+ atkE4_getsecretpowereffect,
+ atkE5_pickup,
+ atkE6_castform_change_animation,
+ atkE7_castform_data_change,
+ atkE8_settypebasedhalvers,
+ atkE9_setweatherballtype,
+ atkEA_recycleitem,
+ atkEB_settypetoterrain,
+ atkEC_pursuit_sth,
+ atkED_802B4B4,
+ atkEE_removelightscreenreflect,
+ atkEF_pokeball_catch_calculation,
+ atkF0_give_caught_mon,
+ atkF1_set_caught_mon_dex_flags,
+ atkF2_display_dex_info,
+ atkF3_nickname_caught_poke,
+ atkF4_subattackerhpbydmg,
+ atkF5_removeattackerstatus1,
+ atkF6_802BF48,
+ atkF7_802BF54,
+ atkF8_trainer_slide_back
+};
+
+struct StatFractions
+{
+ u8 dividend;
+ u8 divisor;
+};
+
+static const struct StatFractions sAccuracyStageRatios[] =
+{
+ { 33, 100}, // -6
+ { 36, 100}, // -5
+ { 43, 100}, // -4
+ { 50, 100}, // -3
+ { 60, 100}, // -2
+ { 75, 100}, // -1
+ { 1, 1}, // 0
+ {133, 100}, // +1
+ {166, 100}, // +2
+ { 2, 1}, // +3
+ {233, 100}, // +4
+ {133, 50}, // +5
+ { 3, 1}, // +6
+};
+
+// The chance is 1/N for each stage.
+static const u16 sCriticalHitChance[] = {16, 8, 4, 3, 2};
+
+static const u32 sStatusFlagsForMoveEffects[] =
+{
+ 0x00000000,
+ STATUS_SLEEP,
+ STATUS_POISON,
+ STATUS_BURN,
+ STATUS_FREEZE,
+ STATUS_PARALYSIS,
+ STATUS_TOXIC_POISON,
+ STATUS2_CONFUSION,
+ STATUS2_FLINCHED,
+ 0x00000000,
+ STATUS2_UPROAR,
+ 0x00000000,
+ STATUS2_MULTIPLETURNS,
+ STATUS2_WRAPPED,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ STATUS2_RECHARGE,
+ 0x00000000,
+ 0x00000000,
+ STATUS2_ESCAPE_PREVENTION,
+ 0x08000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ STATUS2_LOCK_CONFUSE,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000
+};
+
+static const u8* const sMoveEffectBS_Ptrs[] =
+{
+ BattleScript_MoveEffectSleep, // 0
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_SLEEP
+ BattleScript_MoveEffectPoison, // MOVE_EFFECT_POISON
+ BattleScript_MoveEffectBurn, // MOVE_EFFECT_BURN
+ BattleScript_MoveEffectFreeze, // MOVE_EFFECT_FREEZE
+ BattleScript_MoveEffectParalysis, // MOVE_EFFECT_PARALYSIS
+ BattleScript_MoveEffectToxic, // MOVE_EFFECT_TOXIC
+ BattleScript_MoveEffectConfusion, // MOVE_EFFECT_CONFUSION
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_FLINCH
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_TRI_ATTACK
+ BattleScript_MoveEffectUproar, // MOVE_EFFECT_UPROAR
+ BattleScript_MoveEffectPayDay, // MOVE_EFFECT_PAYDAY
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_CHARGING
+ BattleScript_MoveEffectWrap, // MOVE_EFFECT_WRAP
+ BattleScript_MoveEffectRecoil33, // MOVE_EFFECT_RECOIL_25
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_ATK_PLUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_DEF_PLUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_SPD_PLUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_SP_ATK_PLUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_SP_DEF_PLUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_ACC_PLUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_EVS_PLUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_ATK_MINUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_DEF_MINUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_SPD_MINUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_SP_ATK_MINUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_SP_DEF_MINUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_ACC_MINUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_EVS_MINUS_1
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_RECHARGE
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_RAGE
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_STEAL_ITEM
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_PREVENT_ESCAPE
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_NIGHTMARE
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_ALL_STATS_UP
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_RAPIDSPIN
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_REMOVE_PARALYSIS
+ BattleScript_MoveEffectSleep, // MOVE_EFFECT_ATK_DEF_DOWN
+ BattleScript_MoveEffectRecoil33, // MOVE_EFFECT_RECOIL_33_PARALYSIS
+};
+
+static const struct WindowTemplate sUnusedWinTemplate = {0, 1, 3, 7, 0xF, 0x1F, 0x3F};
+
+static const u16 sUnknown_0831C2C8[] = INCBIN_U16("graphics/battle_interface/unk_battlebox.gbapal");
+static const u8 sUnknown_0831C2E8[] = INCBIN_U8("graphics/battle_interface/unk_battlebox.4bpp.lz");
+
+// unused
+static const u8 sRubyLevelUpStatBoxStats[] =
+{
+ MON_DATA_MAX_HP, MON_DATA_SPATK, MON_DATA_ATK,
+ MON_DATA_SPDEF, MON_DATA_DEF, MON_DATA_SPD
+};
+
+#define MON_ICON_LVLUP_BOX_TAG 0xD75A
+
+static const struct OamData sOamData_MonIconOnLvlUpBox =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 2,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const struct SpriteTemplate sSpriteTemplate_MonIconOnLvlUpBox =
+{
+ .tileTag = MON_ICON_LVLUP_BOX_TAG,
+ .paletteTag = MON_ICON_LVLUP_BOX_TAG,
+ .oam = &sOamData_MonIconOnLvlUpBox,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_MonIconOnLvlUpBox
+};
+
+static const u16 sProtectSuccessRates[] = {USHRT_MAX, USHRT_MAX / 2, USHRT_MAX / 4, USHRT_MAX / 8};
+
+#define MIMIC_FORBIDDEN_END 0xFFFE
+#define METRONOME_FORBIDDEN_END 0xFFFF
+#define ASSIST_FORBIDDEN_END 0xFFFF
+
+static const u16 sMovesForbiddenToCopy[] =
+{
+ MOVE_METRONOME,
+ MOVE_STRUGGLE,
+ MOVE_SKETCH,
+ MOVE_MIMIC,
+ MIMIC_FORBIDDEN_END,
+ MOVE_COUNTER,
+ MOVE_MIRROR_COAT,
+ MOVE_PROTECT,
+ MOVE_DETECT,
+ MOVE_ENDURE,
+ MOVE_DESTINY_BOND,
+ MOVE_SLEEP_TALK,
+ MOVE_THIEF,
+ MOVE_FOLLOW_ME,
+ MOVE_SNATCH,
+ MOVE_HELPING_HAND,
+ MOVE_COVET,
+ MOVE_TRICK,
+ MOVE_FOCUS_PUNCH,
+ METRONOME_FORBIDDEN_END
+};
+
+static const u8 sFlailHpScaleToPowerTable[] =
+{
+ 1, 200,
+ 4, 150,
+ 9, 100,
+ 16, 80,
+ 32, 40,
+ 48, 20
+};
+
+static const u16 sNaturePowerMoves[] =
+{
+ MOVE_STUN_SPORE,
+ MOVE_RAZOR_LEAF,
+ MOVE_EARTHQUAKE,
+ MOVE_HYDRO_PUMP,
+ MOVE_SURF,
+ MOVE_BUBBLE_BEAM,
+ MOVE_ROCK_SLIDE,
+ MOVE_SHADOW_BALL,
+ MOVE_SWIFT,
+ MOVE_SWIFT
+};
+
+// format: min. weight (hectograms), base power
+static const u16 sWeightToDamageTable[] =
+{
+ 100, 20,
+ 250, 40,
+ 500, 60,
+ 1000, 80,
+ 2000, 100,
+ 0xFFFF, 0xFFFF
+};
+
+static const u16 sPickupItems[] =
+{
+ ITEM_POTION,
+ ITEM_ANTIDOTE,
+ ITEM_SUPER_POTION,
+ ITEM_GREAT_BALL,
+ ITEM_REPEL,
+ ITEM_ESCAPE_ROPE,
+ ITEM_X_ATTACK,
+ ITEM_FULL_HEAL,
+ ITEM_ULTRA_BALL,
+ ITEM_HYPER_POTION,
+ ITEM_RARE_CANDY,
+ ITEM_PROTEIN,
+ ITEM_REVIVE,
+ ITEM_HP_UP,
+ ITEM_FULL_RESTORE,
+ ITEM_MAX_REVIVE,
+ ITEM_PP_UP,
+ ITEM_MAX_ELIXIR,
+};
+
+static const u16 sRarePickupItems[] =
+{
+ ITEM_HYPER_POTION,
+ ITEM_NUGGET,
+ ITEM_KINGS_ROCK,
+ ITEM_FULL_RESTORE,
+ ITEM_ETHER,
+ ITEM_WHITE_HERB,
+ ITEM_TM44,
+ ITEM_ELIXIR,
+ ITEM_TM01,
+ ITEM_LEFTOVERS,
+ ITEM_TM26,
+};
+
+static const u8 sPickupProbabilities[] =
+{
+ 30, 40, 50, 60, 70, 80, 90, 94, 98
+};
+
+static const u8 sTerrainToType[] =
+{
+ TYPE_GRASS, // tall grass
+ TYPE_GRASS, // long grass
+ TYPE_GROUND, // sand
+ TYPE_WATER, // underwater
+ TYPE_WATER, // water
+ TYPE_WATER, // pond water
+ TYPE_ROCK, // rock
+ TYPE_ROCK, // cave
+ TYPE_NORMAL, // building
+ TYPE_NORMAL, // plain
+};
+
+static const u8 sBallCatchBonuses[] =
+{
+ 20, 15, 10, 15 // Ultra, Great, Poke, Safari
+};
+
+// could be a 2d array or a struct
+const ALIGNED(4) u8 gUnknown_0831C494[] =
+{
+ 0x3d, 0x44, 0x3d, 0x44, 0x14, 0x2d, 0x54, 0x5c,
+ 0x46, 0x55, 0x20, 0x5c, 0x26, 0x45, 0x46, 0x55,
+ 0x14, 0x5a, 0x46, 0x5c, 0x1e, 0x32, 0x20, 0x5a,
+ 0x38, 0x4e, 0x38, 0x4e, 0x19, 0x28, 0x4b, 0x5a,
+ 0x45, 0x4b, 0x1c, 0x53, 0x23, 0x2d, 0x1d, 0x23,
+ 0x3e, 0x48, 0x1e, 0x32, 0x3a, 0x5f, 0x58, 0x5e,
+ 0x22, 0x2d, 0x1d, 0x28, 0x23, 0x28, 0x23, 0x5f,
+ 0x38, 0x4e, 0x38, 0x4e, 0x23, 0x50, 0x22, 0x5e,
+ 0x2c, 0x5e, 0x22, 0x28, 0x38, 0x4e, 0x38, 0x4e,
+ 0x1e, 0x58, 0x1e, 0x58, 0x1e, 0x2b, 0x1b, 0x21,
+ 0x28, 0x5a, 0x19, 0x57, 0x12, 0x58, 0x5a, 0x5f,
+ 0x58, 0x5e, 0x16, 0x2a, 0x2a, 0x5c, 0x2a, 0x2f,
+ 0x38, 0x4e, 0x38, 0x4e
+};
+
+static const u8 sUnknown_0831C4F8[] =
+{
+ 0x03, 0x00, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00,
+ 0x01, 0x02, 0x02, 0x00, 0x03, 0x01, 0x03, 0x01,
+ 0x02, 0x03, 0x03, 0x02, 0x01, 0x00, 0x02, 0x02,
+ 0x03, 0x00, 0x00, 0x00
+};
+
+static void atk00_attackcanceler(void)
+{
+ s32 i;
+
+ if (gBattleOutcome)
+ {
+ gFightStateTracker = 0xC;
+ return;
+ }
+ if (gBattleMons[gBankAttacker].hp == 0 && !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
+ {
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ gBattlescriptCurrInstr = BattleScript_MoveEnd;
+ return;
+ }
+ if (AtkCanceller_UnableToUseMove())
+ return;
+ if (AbilityBattleEffects(ABILITYEFFECT_MOVES_BLOCK, gBankTarget, 0, 0, 0))
+ return;
+ if (!gBattleMons[gBankAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE && !(gHitMarker & 0x800200)
+ && !(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS))
+ {
+ gBattlescriptCurrInstr = BattleScript_NoPPForMove;
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ return;
+ }
+
+ gHitMarker &= ~(HITMARKER_x800000);
+
+ if (!(gHitMarker & HITMARKER_OBEYS) && !(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS))
+ {
+ i = IsPokeDisobedient(); // why use the 'i' variable...?
+ switch (i)
+ {
+ case 0:
+ break;
+ case 2:
+ gHitMarker |= HITMARKER_OBEYS;
+ return;
+ default:
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ return;
+ }
+ }
+
+ gHitMarker |= HITMARKER_OBEYS;
+
+ if (gProtectStructs[gBankTarget].bounceMove && gBattleMoves[gCurrentMove].flags & FLAG_MAGICCOAT_AFFECTED)
+ {
+ PressurePPLose(gBankAttacker, gBankTarget, MOVE_MAGIC_COAT);
+ gProtectStructs[gBankTarget].bounceMove = 0;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_MagicCoatBounce;
+ return;
+ }
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if ((gProtectStructs[gTurnOrder[i]].stealMove) && gBattleMoves[gCurrentMove].flags & FLAG_SNATCH_AFFECTED)
+ {
+ PressurePPLose(gBankAttacker, gTurnOrder[i], MOVE_SNATCH);
+ gProtectStructs[gTurnOrder[i]].stealMove = 0;
+ gBattleScripting.bank = gTurnOrder[i];
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_SnatchedMove;
+ return;
+ }
+ }
+
+ if (gSpecialStatuses[gBankTarget].lightningRodRedirected)
+ {
+ gSpecialStatuses[gBankTarget].lightningRodRedirected = 0;
+ gLastUsedAbility = ABILITY_LIGHTNING_ROD;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_TookAttack;
+ RecordAbilityBattle(gBankTarget, gLastUsedAbility);
+ }
+ else if (TARGET_PROTECT_AFFECTED
+ && (gCurrentMove != MOVE_CURSE || (gBattleMons[gBankAttacker].type1 == TYPE_GHOST || gBattleMons[gBankAttacker].type2 == TYPE_GHOST))
+ && ((!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS))))
+ {
+ CancelMultiTurnMoves(gBankAttacker);
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gUnknown_02024250[gBankTarget] = 0;
+ gUnknown_02024258[gBankTarget] = 0;
+ gBattleCommunication[6] = 1;
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gBattlescriptCurrInstr++;
+ }
+}
+
+static void JumpIfMoveFailed(u8 adder, u16 move)
+{
+ const void* BS_ptr = gBattlescriptCurrInstr + adder;
+ if (gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ {
+ gUnknown_02024250[gBankTarget] = 0;
+ gUnknown_02024258[gBankTarget] = 0;
+ BS_ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ DestinyBondFlagUpdate();
+ if (AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBankTarget, 0, 0, move))
+ return;
+ }
+ gBattlescriptCurrInstr = BS_ptr;
+}
+
+static void atk40_jump_if_move_affected_by_protect(void)
+{
+ if (TARGET_PROTECT_AFFECTED)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ JumpIfMoveFailed(5, 0);
+ gBattleCommunication[6] = 1;
+ }
+ else
+ {
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+bool8 JumpIfMoveAffectedByProtect(u16 move)
+{
+ bool8 affected = FALSE;
+ if (TARGET_PROTECT_AFFECTED)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ JumpIfMoveFailed(7, move);
+ gBattleCommunication[6] = 1;
+ affected = TRUE;
+ }
+ return affected;
+}
+
+bool8 AccuracyCalcHelper(u16 move)
+{
+ if (gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBankTarget].bankWithSureHit == gBankAttacker)
+ {
+ JumpIfMoveFailed(7, move);
+ return TRUE;
+ }
+
+ if (!(gHitMarker & HITMARKER_IGNORE_ON_AIR) && gStatuses3[gBankTarget] & STATUS3_ON_AIR)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ JumpIfMoveFailed(7, move);
+ return TRUE;
+ }
+
+ gHitMarker &= ~HITMARKER_IGNORE_ON_AIR;
+
+ if (!(gHitMarker & HITMARKER_IGNORE_UNDERGROUND) && gStatuses3[gBankTarget] & STATUS3_UNDERGROUND)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ JumpIfMoveFailed(7, move);
+ return TRUE;
+ }
+
+ gHitMarker &= ~HITMARKER_IGNORE_UNDERGROUND;
+
+ if (!(gHitMarker & HITMARKER_IGNORE_UNDERWATER) && gStatuses3[gBankTarget] & STATUS3_UNDERWATER)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ JumpIfMoveFailed(7, move);
+ return TRUE;
+ }
+
+ gHitMarker &= ~HITMARKER_IGNORE_UNDERWATER;
+
+ if ((WEATHER_HAS_EFFECT && (gBattleWeather & WEATHER_RAIN_ANY) && gBattleMoves[move].effect == EFFECT_THUNDER)
+ || (gBattleMoves[move].effect == EFFECT_ALWAYS_HIT || gBattleMoves[move].effect == EFFECT_VITAL_THROW))
+ {
+ JumpIfMoveFailed(7, move);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void atk01_accuracycheck(void)
+{
+ u16 move = BS2ScriptRead16(gBattlescriptCurrInstr + 5);
+
+ if (move == 0xFFFE || move == 0xFFFF)
+ {
+ if (gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS && move == 0xFFFF && gDisableStructs[gBankTarget].bankWithSureHit == gBankAttacker)
+ gBattlescriptCurrInstr += 7;
+ else if (gStatuses3[gBankTarget] & (STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ else if (!JumpIfMoveAffectedByProtect(0))
+ gBattlescriptCurrInstr += 7;
+ }
+ else
+ {
+ u8 type, moveAcc, holdEffect, quality;
+ s8 buff;
+ u16 calc;
+
+ if (move == 0)
+ move = gCurrentMove;
+
+ GET_MOVE_TYPE(move, type);
+
+ if (JumpIfMoveAffectedByProtect(move))
+ return;
+ if (AccuracyCalcHelper(move))
+ return;
+
+ if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT)
+ {
+ u8 acc = gBattleMons[gBankAttacker].statStages[STAT_STAGE_ACC];
+ buff = acc;
+ }
+ else
+ {
+ u8 acc = gBattleMons[gBankAttacker].statStages[STAT_STAGE_ACC];
+ buff = acc + 6 - gBattleMons[gBankTarget].statStages[STAT_STAGE_EVASION];
+ }
+
+ if (buff < 0)
+ buff = 0;
+ if (buff > 0xC)
+ buff = 0xC;
+
+ moveAcc = gBattleMoves[move].accuracy;
+ // check Thunder on sunny weather
+ if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY && gBattleMoves[move].effect == EFFECT_THUNDER)
+ moveAcc = 50;
+
+ calc = sAccuracyStageRatios[buff].dividend * moveAcc;
+ calc /= sAccuracyStageRatios[buff].divisor;
+
+ if (gBattleMons[gBankAttacker].ability == ABILITY_COMPOUND_EYES)
+ calc = (calc * 130) / 100; // 1.3 compound eyes boost
+ if (WEATHER_HAS_EFFECT && gBattleMons[gBankTarget].ability == ABILITY_SAND_VEIL && gBattleWeather & WEATHER_SANDSTORM_ANY)
+ calc = (calc * 80) / 100; // 1.2 sand veil loss
+ if (gBattleMons[gBankAttacker].ability == ABILITY_HUSTLE && type < 9)
+ calc = (calc * 80) / 100; // 1.2 hustle loss
+
+ if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[gBankTarget].holdEffect;
+ quality = gEnigmaBerries[gBankTarget].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
+ quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
+ }
+
+ gStringBank = gBankTarget;
+
+ if (holdEffect == HOLD_EFFECT_EVASION_UP)
+ calc = (calc * (100 - quality)) / 100;
+
+ // final calculation
+ if ((Random() % 100 + 1) > calc)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE &&
+ (gBattleMoves[move].target == MOVE_TARGET_BOTH || gBattleMoves[move].target == MOVE_TARGET_FOES_AND_ALLY))
+ gBattleCommunication[6] = 2;
+ else
+ gBattleCommunication[6] = 0;
+
+ CheckWonderGuardAndLevitate();
+ }
+ JumpIfMoveFailed(7, move);
+ }
+}
+
+static void atk02_attackstring(void)
+{
+ if (gBattleExecBuffer)
+ return;
+ if (!(gHitMarker & (HITMARKER_NO_ATTACKSTRING | HITMARKER_ATTACKSTRING_PRINTED)))
+ {
+ PrepareStringBattle(4, gBankAttacker);
+ gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED;
+ }
+ gBattlescriptCurrInstr++;
+ gBattleCommunication[MSG_DISPLAY] = 0;
+}
+
+static void atk03_ppreduce(void)
+{
+ s32 ppToDeduct = 1;
+
+ if (gBattleExecBuffer)
+ return;
+
+ if (!gSpecialStatuses[gBankAttacker].flag20)
+ {
+ switch (gBattleMoves[gCurrentMove].target)
+ {
+ case MOVE_TARGET_FOES_AND_ALLY:
+ ppToDeduct += AbilityBattleEffects(ABILITYEFFECT_COUNT_ON_FIELD, gBankAttacker, ABILITY_PRESSURE, 0, 0);
+ break;
+ case MOVE_TARGET_BOTH:
+ case MOVE_TARGET_OPPONENTS_FIELD:
+ ppToDeduct += AbilityBattleEffects(ABILITYEFFECT_COUNT_OTHER_SIDE, gBankAttacker, ABILITY_PRESSURE, 0, 0);
+ break;
+ default:
+ if (gBankAttacker != gBankTarget && gBattleMons[gBankTarget].ability == ABILITY_PRESSURE)
+ ppToDeduct++;
+ break;
+ }
+ }
+
+ if (!(gHitMarker & (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING)) && gBattleMons[gBankAttacker].pp[gCurrMovePos])
+ {
+ gProtectStructs[gBankAttacker].notFirstStrike = 1;
+
+ if (gBattleMons[gBankAttacker].pp[gCurrMovePos] > ppToDeduct)
+ gBattleMons[gBankAttacker].pp[gCurrMovePos] -= ppToDeduct;
+ else
+ gBattleMons[gBankAttacker].pp[gCurrMovePos] = 0;
+
+ if (!(gBattleMons[gBankAttacker].status2 & STATUS2_TRANSFORMED)
+ && !((gDisableStructs[gBankAttacker].unk18_b) & gBitTable[gCurrMovePos]))
+ {
+ gActiveBank = gBankAttacker;
+ EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + gCurrMovePos, 0, 1, &gBattleMons[gBankAttacker].pp[gCurrMovePos]);
+ MarkBufferBankForExecution(gBankAttacker);
+ }
+ }
+
+ gHitMarker &= ~(HITMARKER_NO_PPDEDUCT);
+ gBattlescriptCurrInstr++;
+}
+
+static void atk04_critcalc(void)
+{
+ u8 holdEffect;
+ u16 item, critChance;
+
+ item = gBattleMons[gBankAttacker].item;
+
+ if (item == ITEM_ENIGMA_BERRY)
+ holdEffect = gEnigmaBerries[gBankAttacker].holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(item);
+
+ gStringBank = gBankAttacker;
+
+ critChance = 2 * ((gBattleMons[gBankAttacker].status2 & STATUS2_FOCUS_ENERGY) != 0)
+ + (gBattleMoves[gCurrentMove].effect == EFFECT_HIGH_CRITICAL)
+ + (gBattleMoves[gCurrentMove].effect == EFFECT_SKY_ATTACK)
+ + (gBattleMoves[gCurrentMove].effect == EFFECT_BLAZE_KICK)
+ + (gBattleMoves[gCurrentMove].effect == EFFECT_POISON_TAIL)
+ + (holdEffect == HOLD_EFFECT_SCOPE_LENS)
+ + 2 * (holdEffect == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBankAttacker].species == SPECIES_CHANSEY)
+ + 2 * (holdEffect == HOLD_EFFECT_STICK && gBattleMons[gBankAttacker].species == SPECIES_FARFETCHD);
+
+ if (critChance > 4)
+ critChance = 4;
+
+ if ((gBattleMons[gBankTarget].ability != ABILITY_BATTLE_ARMOR && gBattleMons[gBankTarget].ability != ABILITY_SHELL_ARMOR)
+ && !(gStatuses3[gBankAttacker] & STATUS3_CANT_SCORE_A_CRIT)
+ && !(gBattleTypeFlags & (BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_FIRST_BATTLE))
+ && !(Random() % sCriticalHitChance[critChance]))
+ gCritMultiplier = 2;
+ else
+ gCritMultiplier = 1;
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk05_damagecalc1(void)
+{
+ u16 sideStatus = gSideAffecting[GET_BANK_SIDE(gBankTarget)];
+ gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankTarget], gCurrentMove,
+ sideStatus, gDynamicBasePower,
+ gBattleStruct->dynamicMoveType, gBankAttacker, gBankTarget);
+ gBattleMoveDamage = gBattleMoveDamage * gCritMultiplier * gBattleScripting.dmgMultiplier;
+
+ if (gStatuses3[gBankAttacker] & STATUS3_CHARGED_UP && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC)
+ gBattleMoveDamage *= 2;
+ if (gProtectStructs[gBankAttacker].helpingHand)
+ gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
+
+ gBattlescriptCurrInstr++;
+}
+
+void AI_CalcDmg(u8 bankAtk, u8 bankDef)
+{
+ u16 sideStatus = gSideAffecting[GET_BANK_SIDE(bankDef)];
+ gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[bankAtk], &gBattleMons[bankDef], gCurrentMove,
+ sideStatus, gDynamicBasePower,
+ gBattleStruct->dynamicMoveType, bankAtk, bankDef);
+ gDynamicBasePower = 0;
+ gBattleMoveDamage = gBattleMoveDamage * gCritMultiplier * gBattleScripting.dmgMultiplier;
+
+ if (gStatuses3[bankAtk] & STATUS3_CHARGED_UP && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC)
+ gBattleMoveDamage *= 2;
+ if (gProtectStructs[bankAtk].helpingHand)
+ gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
+}
+
+static void ModulateDmgByType(u8 multiplier)
+{
+ gBattleMoveDamage = gBattleMoveDamage * multiplier / 10;
+ if (gBattleMoveDamage == 0 && multiplier != 0)
+ gBattleMoveDamage = 1;
+
+ switch (multiplier)
+ {
+ case TYPE_MUL_NO_EFFECT:
+ gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
+ gBattleMoveFlags &= ~MOVESTATUS_NOTVERYEFFECTIVE;
+ gBattleMoveFlags &= ~MOVESTATUS_SUPEREFFECTIVE;
+ break;
+ case TYPE_MUL_NOT_EFFECTIVE:
+ if (gBattleMoves[gCurrentMove].power && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
+ {
+ if (gBattleMoveFlags & MOVESTATUS_SUPEREFFECTIVE)
+ gBattleMoveFlags &= ~MOVESTATUS_SUPEREFFECTIVE;
+ else
+ gBattleMoveFlags |= MOVESTATUS_NOTVERYEFFECTIVE;
+ }
+ break;
+ case TYPE_MUL_SUPER_EFFECTIVE:
+ if (gBattleMoves[gCurrentMove].power && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
+ {
+ if (gBattleMoveFlags & MOVESTATUS_NOTVERYEFFECTIVE)
+ gBattleMoveFlags &= ~MOVESTATUS_NOTVERYEFFECTIVE;
+ else
+ gBattleMoveFlags |= MOVESTATUS_SUPEREFFECTIVE;
+ }
+ break;
+ }
+}
+
+#define TYPE_FORESIGHT 0xFE
+#define TYPE_ENDTABLE 0xFF
+
+static void atk06_typecalc(void)
+{
+ s32 i = 0;
+ u8 moveType;
+
+ if (gCurrentMove == MOVE_STRUGGLE)
+ {
+ gBattlescriptCurrInstr++;
+ return;
+ }
+
+ GET_MOVE_TYPE(gCurrentMove, moveType);
+
+ // check stab
+ if (gBattleMons[gBankAttacker].type1 == moveType || gBattleMons[gBankAttacker].type2 == moveType)
+ {
+ gBattleMoveDamage = gBattleMoveDamage * 15;
+ gBattleMoveDamage = gBattleMoveDamage / 10;
+ }
+
+ if (gBattleMons[gBankTarget].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
+ {
+ gLastUsedAbility = gBattleMons[gBankTarget].ability;
+ gBattleMoveFlags |= (MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED);
+ gUnknown_02024250[gBankTarget] = 0;
+ gUnknown_02024258[gBankTarget] = 0;
+ gBattleCommunication[6] = moveType;
+ RecordAbilityBattle(gBankTarget, gLastUsedAbility);
+ }
+ else
+ {
+ while (gTypeEffectiveness[i] != TYPE_ENDTABLE)
+ {
+ if (gTypeEffectiveness[i] == TYPE_FORESIGHT)
+ {
+ if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT)
+ break;
+ i += 3;
+ continue;
+ }
+ else if (gTypeEffectiveness[i] == moveType)
+ {
+ // check type1
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1)
+ ModulateDmgByType(gTypeEffectiveness[i + 2]);
+ // check type2
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 &&
+ gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2)
+ ModulateDmgByType(gTypeEffectiveness[i + 2]);
+ }
+ i += 3;
+ }
+ }
+
+ if (gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD && AttacksThisTurn(gBankAttacker, gCurrentMove) == 2
+ && (!(gBattleMoveFlags & MOVESTATUS_SUPEREFFECTIVE) || ((gBattleMoveFlags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)))
+ && gBattleMoves[gCurrentMove].power)
+ {
+ gLastUsedAbility = ABILITY_WONDER_GUARD;
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gUnknown_02024250[gBankTarget] = 0;
+ gUnknown_02024258[gBankTarget] = 0;
+ gBattleCommunication[6] = 3;
+ RecordAbilityBattle(gBankTarget, gLastUsedAbility);
+ }
+ if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED)
+ gProtectStructs[gBankAttacker].notEffective = 1;
+
+ gBattlescriptCurrInstr++;
+}
+
+static void CheckWonderGuardAndLevitate(void)
+{
+ u8 flags = 0;
+ s32 i = 0;
+ u8 moveType;
+
+ if (gCurrentMove == MOVE_STRUGGLE || !gBattleMoves[gCurrentMove].power)
+ return;
+
+ GET_MOVE_TYPE(gCurrentMove, moveType);
+
+ if (gBattleMons[gBankTarget].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
+ {
+ gLastUsedAbility = ABILITY_LEVITATE;
+ gBattleCommunication[6] = moveType;
+ RecordAbilityBattle(gBankTarget, ABILITY_LEVITATE);
+ return;
+ }
+
+ while (gTypeEffectiveness[i] != TYPE_ENDTABLE)
+ {
+ if (gTypeEffectiveness[i] == TYPE_FORESIGHT)
+ {
+ if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT)
+ break;
+ i += 3;
+ continue;
+ }
+ if (gTypeEffectiveness[i] == moveType)
+ {
+ // check no effect
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1 && gTypeEffectiveness[i + 2] == 0)
+ {
+ gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
+ gProtectStructs[gBankAttacker].notEffective = 1;
+ }
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2 &&
+ gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2 &&
+ gTypeEffectiveness[i + 2] == TYPE_MUL_NO_EFFECT)
+ {
+ gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
+ gProtectStructs[gBankAttacker].notEffective = 1;
+ }
+
+ // check super effective
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1 && gTypeEffectiveness[i + 2] == 20)
+ flags |= 1;
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2
+ && gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2
+ && gTypeEffectiveness[i + 2] == TYPE_MUL_SUPER_EFFECTIVE)
+ flags |= 1;
+
+ // check not very effective
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1 && gTypeEffectiveness[i + 2] == 5)
+ flags |= 2;
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2
+ && gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2
+ && gTypeEffectiveness[i + 2] == TYPE_MUL_NOT_EFFECTIVE)
+ flags |= 2;
+ }
+ i += 3;
+ }
+
+ if (gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD && AttacksThisTurn(gBankAttacker, gCurrentMove) == 2)
+ {
+ if (((flags & 2) || !(flags & 1)) && gBattleMoves[gCurrentMove].power)
+ {
+ gLastUsedAbility = ABILITY_WONDER_GUARD;
+ gBattleCommunication[6] = 3;
+ RecordAbilityBattle(gBankTarget, ABILITY_WONDER_GUARD);
+ }
+ }
+}
+
+static void ModulateDmgByType2(u8 multiplier, u16 move, u8* flags) // same as ModulateDmgByType except different arguments
+{
+ gBattleMoveDamage = gBattleMoveDamage * multiplier / 10;
+ if (gBattleMoveDamage == 0 && multiplier != 0)
+ gBattleMoveDamage = 1;
+
+ switch (multiplier)
+ {
+ case TYPE_MUL_NO_EFFECT:
+ *flags |= MOVESTATUS_NOTAFFECTED;
+ *flags &= ~MOVESTATUS_NOTVERYEFFECTIVE;
+ *flags &= ~MOVESTATUS_SUPEREFFECTIVE;
+ break;
+ case TYPE_MUL_NOT_EFFECTIVE:
+ if (gBattleMoves[move].power && !(*flags & MOVESTATUS_NOEFFECT))
+ {
+ if (*flags & MOVESTATUS_SUPEREFFECTIVE)
+ *flags &= ~MOVESTATUS_SUPEREFFECTIVE;
+ else
+ *flags |= MOVESTATUS_NOTVERYEFFECTIVE;
+ }
+ break;
+ case TYPE_MUL_SUPER_EFFECTIVE:
+ if (gBattleMoves[move].power && !(*flags & MOVESTATUS_NOEFFECT))
+ {
+ if (*flags & MOVESTATUS_NOTVERYEFFECTIVE)
+ *flags &= ~MOVESTATUS_NOTVERYEFFECTIVE;
+ else
+ *flags |= MOVESTATUS_SUPEREFFECTIVE;
+ }
+ break;
+ }
+}
+
+u8 TypeCalc(u16 move, u8 bankAtk, u8 bankDef)
+{
+ s32 i = 0;
+ u8 flags = 0;
+ u8 moveType;
+
+ if (move == MOVE_STRUGGLE)
+ return 0;
+
+ moveType = gBattleMoves[move].type;
+
+ // check stab
+ if (gBattleMons[bankAtk].type1 == moveType || gBattleMons[bankAtk].type2 == moveType)
+ {
+ gBattleMoveDamage = gBattleMoveDamage * 15;
+ gBattleMoveDamage = gBattleMoveDamage / 10;
+ }
+
+ if (gBattleMons[bankDef].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
+ {
+ flags |= (MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED);
+ }
+ else
+ {
+ while (gTypeEffectiveness[i]!= TYPE_ENDTABLE)
+ {
+ if (gTypeEffectiveness[i] == TYPE_FORESIGHT)
+ {
+ if (gBattleMons[bankDef].status2 & STATUS2_FORESIGHT)
+ break;
+ i += 3;
+ continue;
+ }
+
+ else if (gTypeEffectiveness[i] == moveType)
+ {
+ // check type1
+ if (gTypeEffectiveness[i + 1] == gBattleMons[bankDef].type1)
+ ModulateDmgByType2(gTypeEffectiveness[i + 2], move, &flags);
+ // check type2
+ if (gTypeEffectiveness[i + 1] == gBattleMons[bankDef].type2 &&
+ gBattleMons[bankDef].type1 != gBattleMons[bankDef].type2)
+ ModulateDmgByType2(gTypeEffectiveness[i + 2], move, &flags);
+ }
+ i += 3;
+ }
+ }
+
+ if (gBattleMons[bankDef].ability == ABILITY_WONDER_GUARD && !(flags & MOVESTATUS_MISSED)
+ && AttacksThisTurn(bankAtk, move) == 2
+ && (!(flags & MOVESTATUS_SUPEREFFECTIVE) || ((flags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)))
+ && gBattleMoves[move].power)
+ {
+ flags |= MOVESTATUS_MISSED;
+ }
+ return flags;
+}
+
+u8 AI_TypeCalc(u16 move, u16 species, u8 ability)
+{
+ s32 i = 0;
+ u8 flags = 0;
+ u8 type1 = gBaseStats[species].type1, type2 = gBaseStats[species].type2;
+ u8 moveType;
+
+ if (move == MOVE_STRUGGLE)
+ return 0;
+
+ moveType = gBattleMoves[move].type;
+
+ if (ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
+ {
+ flags = MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED;
+ }
+ else
+ {
+ while (gTypeEffectiveness[i] != TYPE_ENDTABLE)
+ {
+ if (gTypeEffectiveness[i] == TYPE_FORESIGHT)
+ {
+ i += 3;
+ continue;
+ }
+ if (gTypeEffectiveness[i] == moveType)
+ {
+ // check type1
+ if (gTypeEffectiveness[i + 1] == type1)
+ ModulateDmgByType2(gTypeEffectiveness[i + 2], move, &flags);
+ // check type2
+ if (gTypeEffectiveness[i + 1] == type2 && type1 != type2)
+ ModulateDmgByType2(gTypeEffectiveness[i + 2], move, &flags);
+ }
+ i += 3;
+ }
+ }
+ if (ability == ABILITY_WONDER_GUARD
+ && (!(flags & MOVESTATUS_SUPEREFFECTIVE) || ((flags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)))
+ && gBattleMoves[move].power)
+ flags |= MOVESTATUS_NOTAFFECTED;
+ return flags;
+}
+
+// Multiplies the damage by a random factor between 85% to 100% inclusive
+static inline void ApplyRandomDmgMultiplier(void)
+{
+ u16 rand = Random();
+ u16 randPercent = 100 - (rand % 16);
+
+ if (gBattleMoveDamage != 0)
+ {
+ gBattleMoveDamage *= randPercent;
+ gBattleMoveDamage /= 100;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ }
+}
+
+static void Unused_ApplyRandomDmgMultiplier(void)
+{
+ ApplyRandomDmgMultiplier();
+}
+
+static void atk07_dmg_adjustment(void)
+{
+ u8 holdEffect, quality;
+
+ ApplyRandomDmgMultiplier();
+
+ if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
+ quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
+ }
+
+ gStringBank = gBankTarget;
+
+ if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < quality)
+ {
+ RecordItemEffectBattle(gBankTarget, holdEffect);
+ gSpecialStatuses[gBankTarget].focusBanded = 1;
+ }
+ if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE)
+ goto END;
+ if (gBattleMoves[gCurrentMove].effect != EFFECT_FALSE_SWIPE && !gProtectStructs[gBankTarget].endured
+ && !gSpecialStatuses[gBankTarget].focusBanded)
+ goto END;
+
+ if (gBattleMons[gBankTarget].hp > gBattleMoveDamage)
+ goto END;
+
+ gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1;
+
+ if (gProtectStructs[gBankTarget].endured)
+ {
+ gBattleMoveFlags |= MOVESTATUS_ENDURED;
+ }
+ else if (gSpecialStatuses[gBankTarget].focusBanded)
+ {
+ gBattleMoveFlags |= MOVESTATUS_HUNGON;
+ gLastUsedItem = gBattleMons[gBankTarget].item;
+ }
+
+ END:
+ gBattlescriptCurrInstr++;
+}
+
+static void atk08_dmg_adjustment2(void) // The same as 0x7 except it doesn't check for false swipe move effect.
+{
+ u8 holdEffect, quality;
+
+ ApplyRandomDmgMultiplier();
+
+ if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
+ quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
+ }
+
+ gStringBank = gBankTarget;
+
+ if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < quality)
+ {
+ RecordItemEffectBattle(gBankTarget, holdEffect);
+ gSpecialStatuses[gBankTarget].focusBanded = 1;
+ }
+ if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE)
+ goto END;
+ if (!gProtectStructs[gBankTarget].endured && !gSpecialStatuses[gBankTarget].focusBanded)
+ goto END;
+ if (gBattleMons[gBankTarget].hp > gBattleMoveDamage)
+ goto END;
+
+ gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1;
+
+ if (gProtectStructs[gBankTarget].endured)
+ {
+ gBattleMoveFlags |= MOVESTATUS_ENDURED;
+ }
+ else if (gSpecialStatuses[gBankTarget].focusBanded)
+ {
+ gBattleMoveFlags |= MOVESTATUS_HUNGON;
+ gLastUsedItem = gBattleMons[gBankTarget].item;
+ }
+
+ END:
+ gBattlescriptCurrInstr++;
+}
+
+static void atk09_attackanimation(void)
+{
+ if (gBattleExecBuffer)
+ return;
+
+ if ((gHitMarker & HITMARKER_NO_ANIMATIONS) && (gCurrentMove != MOVE_TRANSFORM && gCurrentMove != MOVE_SUBSTITUTE))
+ {
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_Pausex20;
+ gBattleScripting.animTurn++;
+ gBattleScripting.animTargetsHit++;
+ }
+ else
+ {
+ if ((gBattleMoves[gCurrentMove].target & MOVE_TARGET_BOTH
+ || gBattleMoves[gCurrentMove].target & MOVE_TARGET_FOES_AND_ALLY
+ || gBattleMoves[gCurrentMove].target & MOVE_TARGET_DEPENDS)
+ && gBattleScripting.animTargetsHit)
+ {
+ gBattlescriptCurrInstr++;
+ return;
+ }
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
+ {
+ u8 multihit;
+
+ gActiveBank = gBankAttacker;
+
+ if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE)
+ multihit = gMultiHitCounter;
+ else if (gMultiHitCounter != 0 && gMultiHitCounter != 1)
+ {
+ if (gBattleMons[gBankTarget].hp <= gBattleMoveDamage)
+ multihit = 1;
+ else
+ multihit = gMultiHitCounter;
+ }
+ else
+ multihit = gMultiHitCounter;
+
+ EmitMoveAnimation(0, gCurrentMove, gBattleScripting.animTurn, gBattleMovePower, gBattleMoveDamage, gBattleMons[gBankAttacker].friendship, &gDisableStructs[gBankAttacker], multihit);
+ gBattleScripting.animTurn += 1;
+ gBattleScripting.animTargetsHit += 1;
+ MarkBufferBankForExecution(gBankAttacker);
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_Pausex20;
+ }
+ }
+}
+
+static void atk0A_waitanimation(void)
+{
+ if (gBattleExecBuffer == 0)
+ gBattlescriptCurrInstr++;
+}
+
+static void atk0B_healthbarupdate(void)
+{
+ if (gBattleExecBuffer)
+ return;
+
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ if (gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE && gDisableStructs[gActiveBank].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE))
+ {
+ PrepareStringBattle(0x80, gActiveBank);
+ }
+ else
+ {
+ s16 healthValue;
+
+ s32 currDmg = gBattleMoveDamage;
+ s32 maxPossibleDmgValue = 10000; // not present in R/S, ensures that huge damage values don't change sign
+
+ if (currDmg <= maxPossibleDmgValue)
+ healthValue = currDmg;
+ else
+ healthValue = maxPossibleDmgValue;
+
+ EmitHealthBarUpdate(0, healthValue);
+ MarkBufferBankForExecution(gActiveBank);
+
+ if (GetBankSide(gActiveBank) == SIDE_PLAYER && gBattleMoveDamage > 0)
+ gBattleResults.unk5_0 = 1;
+ }
+ }
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk0C_datahpupdate(void)
+{
+ u32 moveType;
+
+ if (gBattleExecBuffer)
+ return;
+
+ if (gBattleStruct->dynamicMoveType == 0)
+ moveType = gBattleMoves[gCurrentMove].type;
+ else if (!(gBattleStruct->dynamicMoveType & 0x40))
+ moveType = gBattleStruct->dynamicMoveType & 0x3F;
+ else
+ moveType = gBattleMoves[gCurrentMove].type;
+
+ if (!(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ if (gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE && gDisableStructs[gActiveBank].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE))
+ {
+ if (gDisableStructs[gActiveBank].substituteHP >= gBattleMoveDamage)
+ {
+ if (gSpecialStatuses[gActiveBank].moveturnLostHP == 0)
+ gSpecialStatuses[gActiveBank].moveturnLostHP = gBattleMoveDamage;
+ gDisableStructs[gActiveBank].substituteHP -= gBattleMoveDamage;
+ gHpDealt = gBattleMoveDamage;
+ }
+ else
+ {
+ if (gSpecialStatuses[gActiveBank].moveturnLostHP == 0)
+ gSpecialStatuses[gActiveBank].moveturnLostHP = gDisableStructs[gActiveBank].substituteHP;
+ gHpDealt = gDisableStructs[gActiveBank].substituteHP;
+ gDisableStructs[gActiveBank].substituteHP = 0;
+ }
+ // check substitute fading
+ if (gDisableStructs[gActiveBank].substituteHP == 0)
+ {
+ gBattlescriptCurrInstr += 2;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_SubstituteFade;
+ return;
+ }
+ }
+ else
+ {
+ gHitMarker &= ~(HITMARKER_IGNORE_SUBSTITUTE);
+ if (gBattleMoveDamage < 0) // hp goes up
+ {
+ gBattleMons[gActiveBank].hp -= gBattleMoveDamage;
+ if (gBattleMons[gActiveBank].hp > gBattleMons[gActiveBank].maxHP)
+ gBattleMons[gActiveBank].hp = gBattleMons[gActiveBank].maxHP;
+
+ }
+ else // hp goes down
+ {
+ if (gHitMarker & HITMARKER_x20)
+ {
+ gHitMarker &= ~(HITMARKER_x20);
+ }
+ else
+ {
+ gTakenDmg[gActiveBank] += gBattleMoveDamage;
+ if (gBattlescriptCurrInstr[1] == BS_GET_TARGET)
+ gTakenDmgBanks[gActiveBank] = gBankAttacker;
+ else
+ gTakenDmgBanks[gActiveBank] = gBankTarget;
+ }
+
+ if (gBattleMons[gActiveBank].hp > gBattleMoveDamage)
+ {
+ gBattleMons[gActiveBank].hp -= gBattleMoveDamage;
+ gHpDealt = gBattleMoveDamage;
+ }
+ else
+ {
+ gHpDealt = gBattleMons[gActiveBank].hp;
+ gBattleMons[gActiveBank].hp = 0;
+ }
+
+ if (!gSpecialStatuses[gActiveBank].moveturnLostHP && !(gHitMarker & HITMARKER_x100000))
+ gSpecialStatuses[gActiveBank].moveturnLostHP = gHpDealt;
+
+ if (moveType <= 8 && !(gHitMarker & HITMARKER_x100000) && gCurrentMove != MOVE_PAIN_SPLIT)
+ {
+ gProtectStructs[gActiveBank].physicalDmg = gHpDealt;
+ gSpecialStatuses[gActiveBank].moveturnLostHP_physical = gHpDealt;
+ if (gBattlescriptCurrInstr[1] == BS_GET_TARGET)
+ {
+ gProtectStructs[gActiveBank].physicalBank = gBankAttacker;
+ gSpecialStatuses[gActiveBank].moveturnPhysicalBank = gBankAttacker;
+ }
+ else
+ {
+ gProtectStructs[gActiveBank].physicalBank = gBankTarget;
+ gSpecialStatuses[gActiveBank].moveturnPhysicalBank = gBankTarget;
+ }
+ }
+ else if (moveType > 8 && !(gHitMarker & HITMARKER_x100000))
+ {
+ gProtectStructs[gActiveBank].specialDmg = gHpDealt;
+ gSpecialStatuses[gActiveBank].moveturnLostHP_special = gHpDealt;
+ if (gBattlescriptCurrInstr[1] == BS_GET_TARGET)
+ {
+ gProtectStructs[gActiveBank].specialBank = gBankAttacker;
+ gSpecialStatuses[gActiveBank].moveturnSpecialBank = gBankAttacker;
+ }
+ else
+ {
+ gProtectStructs[gActiveBank].specialBank = gBankTarget;
+ gSpecialStatuses[gActiveBank].moveturnSpecialBank = gBankTarget;
+ }
+ }
+ }
+ gHitMarker &= ~(HITMARKER_x100000);
+ EmitSetMonData(0, REQUEST_HP_BATTLE, 0, 2, &gBattleMons[gActiveBank].hp);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+ else
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ if (gSpecialStatuses[gActiveBank].moveturnLostHP == 0)
+ gSpecialStatuses[gActiveBank].moveturnLostHP = 0xFFFF;
+ }
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk0D_critmessage(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ if (gCritMultiplier == 2 && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
+ {
+ PrepareStringBattle(0xD9, gBankAttacker);
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ }
+ gBattlescriptCurrInstr++;
+ }
+}
+
+static void atk0E_effectiveness_sound(void)
+{
+ if (gBattleExecBuffer)
+ return;
+
+ gActiveBank = gBankTarget;
+ if (!(gBattleMoveFlags & MOVESTATUS_MISSED))
+ {
+ switch (gBattleMoveFlags & (u8)(~(MOVESTATUS_MISSED)))
+ {
+ case MOVESTATUS_SUPEREFFECTIVE:
+ EmitEffectivenessSound(0, SE_KOUKA_H);
+ MarkBufferBankForExecution(gActiveBank);
+ break;
+ case MOVESTATUS_NOTVERYEFFECTIVE:
+ EmitEffectivenessSound(0, SE_KOUKA_L);
+ MarkBufferBankForExecution(gActiveBank);
+ break;
+ case MOVESTATUS_NOTAFFECTED:
+ case MOVESTATUS_FAILED:
+ // no sound
+ break;
+ case MOVESTATUS_ENDURED:
+ case MOVESTATUS_ONEHITKO:
+ case MOVESTATUS_HUNGON:
+ default:
+ if (gBattleMoveFlags & MOVESTATUS_SUPEREFFECTIVE)
+ {
+ EmitEffectivenessSound(0, SE_KOUKA_H);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ else if (gBattleMoveFlags & MOVESTATUS_NOTVERYEFFECTIVE)
+ {
+ EmitEffectivenessSound(0, SE_KOUKA_L);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ else if (!(gBattleMoveFlags & (MOVESTATUS_NOTAFFECTED | MOVESTATUS_FAILED)))
+ {
+ EmitEffectivenessSound(0, SE_KOUKA_M);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ break;
+ }
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atk0F_resultmessage(void)
+{
+ u32 stringId = 0;
+
+ if (gBattleExecBuffer)
+ return;
+
+ if (gBattleMoveFlags & MOVESTATUS_MISSED && (!(gBattleMoveFlags & MOVESTATUS_NOTAFFECTED) || gBattleCommunication[6] > 2))
+ {
+ stringId = gMissStringIds[gBattleCommunication[6]];
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ }
+ else
+ {
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ switch (gBattleMoveFlags & (u8)(~(MOVESTATUS_MISSED)))
+ {
+ case MOVESTATUS_SUPEREFFECTIVE:
+ stringId = 0xDE;
+ break;
+ case MOVESTATUS_NOTVERYEFFECTIVE:
+ stringId = 0xDD;
+ break;
+ case MOVESTATUS_ONEHITKO:
+ stringId = 0xDA;
+ break;
+ case MOVESTATUS_ENDURED:
+ stringId = 0x99;
+ break;
+ case MOVESTATUS_FAILED:
+ stringId = 0xE5;
+ break;
+ case MOVESTATUS_NOTAFFECTED:
+ stringId = 0x1B;
+ break;
+ case MOVESTATUS_HUNGON:
+ gLastUsedItem = gBattleMons[gBankTarget].item;
+ gStringBank = gBankTarget;
+ gBattleMoveFlags &= ~(MOVESTATUS_ENDURED | MOVESTATUS_HUNGON);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_HangedOnMsg;
+ return;
+ default:
+ if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED)
+ {
+ stringId = 0x1B;
+ }
+ else if (gBattleMoveFlags & MOVESTATUS_ONEHITKO)
+ {
+ gBattleMoveFlags &= ~(MOVESTATUS_ONEHITKO);
+ gBattleMoveFlags &= ~(MOVESTATUS_SUPEREFFECTIVE);
+ gBattleMoveFlags &= ~(MOVESTATUS_NOTVERYEFFECTIVE);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_OneHitKOMsg;
+ return;
+ }
+ else if (gBattleMoveFlags & MOVESTATUS_ENDURED)
+ {
+ gBattleMoveFlags &= ~(MOVESTATUS_ENDURED | MOVESTATUS_HUNGON);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_EnduredMsg;
+ return;
+ }
+ else if (gBattleMoveFlags & MOVESTATUS_HUNGON)
+ {
+ gLastUsedItem = gBattleMons[gBankTarget].item;
+ gStringBank = gBankTarget;
+ gBattleMoveFlags &= ~(MOVESTATUS_ENDURED | MOVESTATUS_HUNGON);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_HangedOnMsg;
+ return;
+ }
+ else if (gBattleMoveFlags & MOVESTATUS_FAILED)
+ {
+ stringId = 0xE5;
+ }
+ else
+ {
+ gBattleCommunication[MSG_DISPLAY] = 0;
+ }
+ }
+ }
+
+ if (stringId)
+ PrepareStringBattle(stringId, gBankAttacker);
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk10_printstring(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ u16 var = BS2ScriptRead16(gBattlescriptCurrInstr + 1);
+ PrepareStringBattle(var, gBankAttacker);
+ gBattlescriptCurrInstr += 3;
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ }
+}
+
+static void atk11_printstring_playeronly(void)
+{
+ gActiveBank = gBankAttacker;
+
+ EmitPrintStringPlayerOnly(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1));
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 3;
+ gBattleCommunication[MSG_DISPLAY] = 1;
+}
+
+static void atk12_waitmessage(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ if (!gBattleCommunication[MSG_DISPLAY])
+ {
+ gBattlescriptCurrInstr += 3;
+ }
+ else
+ {
+ u16 toWait = BS2ScriptRead16(gBattlescriptCurrInstr + 1);
+ if (++gPauseCounterBattle >= toWait)
+ {
+ gPauseCounterBattle = 0;
+ gBattlescriptCurrInstr += 3;
+ gBattleCommunication[MSG_DISPLAY] = 0;
+ }
+ }
+ }
+}
+
+static void atk13_printfromtable(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ const u16 *ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ ptr += gBattleCommunication[MULTISTRING_CHOOSER];
+
+ PrepareStringBattle(*ptr, gBankAttacker);
+
+ gBattlescriptCurrInstr += 5;
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ }
+}
+
+static void atk14_printfromtable_playeronly(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ const u16 *ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ ptr += gBattleCommunication[MULTISTRING_CHOOSER];
+
+ gActiveBank = gBankAttacker;
+ EmitPrintStringPlayerOnly(0, *ptr);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 5;
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ }
+}
+
+u8 BankGetTurnOrder(u8 bank)
+{
+ s32 i;
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gTurnOrder[i] == bank)
+ break;
+ }
+ return i;
+}
+
+#define INCREMENT_RESET_RETURN \
+{ \
+ gBattlescriptCurrInstr++; \
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0; \
+ return; \
+}
+
+#define RESET_RETURN \
+{ \
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0; \
+ return; \
+}
+
+void SetMoveEffect(bool8 primary, u8 certain)
+{
+ bool32 statusChanged = FALSE;
+ u8 affectsUser = 0; // 0x40 otherwise
+ bool32 noSunCanFreeze = TRUE;
+
+ if (gBattleCommunication[MOVE_EFFECT_BYTE] & MOVE_EFFECT_AFFECTS_USER)
+ {
+ gEffectBank = gBankAttacker; // bank that effects get applied on
+ gBattleCommunication[MOVE_EFFECT_BYTE] &= ~(MOVE_EFFECT_AFFECTS_USER);
+ affectsUser = MOVE_EFFECT_AFFECTS_USER;
+ gBattleScripting.bank = gBankTarget; // theoretically the attacker
+ }
+ else
+ {
+ gEffectBank = gBankTarget;
+ gBattleScripting.bank = gBankAttacker;
+ }
+
+ if (gBattleMons[gEffectBank].ability == ABILITY_SHIELD_DUST && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
+ && !primary && gBattleCommunication[MOVE_EFFECT_BYTE] <= 9)
+ INCREMENT_RESET_RETURN
+
+ if (gSideAffecting[GET_BANK_SIDE(gEffectBank)] & SIDE_STATUS_SAFEGUARD && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
+ && !primary && gBattleCommunication[MOVE_EFFECT_BYTE] <= 7)
+ INCREMENT_RESET_RETURN
+
+ if (gBattleMons[gEffectBank].hp == 0
+ && gBattleCommunication[MOVE_EFFECT_BYTE] != MOVE_EFFECT_PAYDAY
+ && gBattleCommunication[MOVE_EFFECT_BYTE] != MOVE_EFFECT_STEAL_ITEM)
+ INCREMENT_RESET_RETURN
+
+ if (gBattleMons[gEffectBank].status2 & STATUS2_SUBSTITUTE && affectsUser != MOVE_EFFECT_AFFECTS_USER)
+ INCREMENT_RESET_RETURN
+
+ if (gBattleCommunication[MOVE_EFFECT_BYTE] <= 6) // status change
+ {
+ switch (sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]])
+ {
+ case STATUS_SLEEP:
+ // check active uproar
+ if (gBattleMons[gEffectBank].ability != ABILITY_SOUNDPROOF)
+ {
+ for (gActiveBank = 0;
+ gActiveBank < gNoOfAllBanks && !(gBattleMons[gActiveBank].status2 & STATUS2_UPROAR);
+ gActiveBank++)
+ {}
+ }
+ else
+ gActiveBank = gNoOfAllBanks;
+
+ if (gBattleMons[gEffectBank].status1)
+ break;
+ if (gActiveBank != gNoOfAllBanks)
+ break;
+ if (gBattleMons[gEffectBank].ability == ABILITY_VITAL_SPIRIT)
+ break;
+ if (gBattleMons[gEffectBank].ability == ABILITY_INSOMNIA)
+ break;
+
+ CancelMultiTurnMoves(gEffectBank);
+ statusChanged = TRUE;
+ break;
+ case STATUS_POISON:
+ if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY
+ && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
+ {
+ gLastUsedAbility = ABILITY_IMMUNITY;
+ RecordAbilityBattle(gEffectBank, ABILITY_IMMUNITY);
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_PSNPrevention;
+
+ if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD);
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ RESET_RETURN
+ }
+ if ((gBattleMons[gEffectBank].type1 == TYPE_POISON || gBattleMons[gEffectBank].type2 == TYPE_POISON
+ || gBattleMons[gEffectBank].type1 == TYPE_STEEL || gBattleMons[gEffectBank].type2 == TYPE_STEEL)
+ && (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
+ && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
+ {
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_PSNPrevention;
+
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ RESET_RETURN
+ }
+ if (gBattleMons[gEffectBank].type1 == TYPE_POISON)
+ break;
+ if (gBattleMons[gEffectBank].type2 == TYPE_POISON)
+ break;
+ if (gBattleMons[gEffectBank].type1 == TYPE_STEEL)
+ break;
+ if (gBattleMons[gEffectBank].type2 == TYPE_STEEL)
+ break;
+ if (gBattleMons[gEffectBank].status1)
+ break;
+ if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY)
+ break;
+
+ statusChanged = TRUE;
+ break;
+ case STATUS_BURN:
+ if (gBattleMons[gEffectBank].ability == ABILITY_WATER_VEIL
+ && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
+ {
+ gLastUsedAbility = ABILITY_WATER_VEIL;
+ RecordAbilityBattle(gEffectBank, ABILITY_WATER_VEIL);
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_BRNPrevention;
+ if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD);
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ RESET_RETURN
+ }
+ if ((gBattleMons[gEffectBank].type1 == TYPE_FIRE
+ || gBattleMons[gEffectBank].type2 == TYPE_FIRE)
+ && (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
+ && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
+ {
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_BRNPrevention;
+
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ RESET_RETURN
+ }
+ if (gBattleMons[gEffectBank].type1 == TYPE_FIRE)
+ break;
+ if (gBattleMons[gEffectBank].type2 == TYPE_FIRE)
+ break;
+ if (gBattleMons[gEffectBank].ability == ABILITY_WATER_VEIL)
+ break;
+ if (gBattleMons[gEffectBank].status1)
+ break;
+
+ statusChanged = TRUE;
+ break;
+ case STATUS_FREEZE:
+ if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY)
+ noSunCanFreeze = FALSE;
+ if (gBattleMons[gEffectBank].type1 == TYPE_ICE)
+ break;
+ if (gBattleMons[gEffectBank].type2 == TYPE_ICE)
+ break;
+ if (gBattleMons[gEffectBank].status1)
+ break;
+ if (noSunCanFreeze == 0)
+ break;
+ if (gBattleMons[gEffectBank].ability == ABILITY_MAGMA_ARMOR)
+ break;
+
+ CancelMultiTurnMoves(gEffectBank);
+ statusChanged = TRUE;
+ break;
+ case STATUS_PARALYSIS:
+ if (gBattleMons[gEffectBank].ability == ABILITY_LIMBER)
+ {
+ if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)
+ {
+ gLastUsedAbility = ABILITY_LIMBER;
+ RecordAbilityBattle(gEffectBank, ABILITY_LIMBER);
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_PRLZPrevention;
+
+ if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD);
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ RESET_RETURN
+ }
+ else
+ break;
+ }
+ if (gBattleMons[gEffectBank].status1)
+ break;
+
+ statusChanged = TRUE;
+ break;
+ case STATUS_TOXIC_POISON:
+ if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
+ {
+ gLastUsedAbility = ABILITY_IMMUNITY;
+ RecordAbilityBattle(gEffectBank, ABILITY_IMMUNITY);
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_PSNPrevention;
+
+ if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD);
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ RESET_RETURN
+ }
+ if ((gBattleMons[gEffectBank].type1 == TYPE_POISON || gBattleMons[gEffectBank].type2 == TYPE_POISON
+ || gBattleMons[gEffectBank].type1 == TYPE_STEEL || gBattleMons[gEffectBank].type2 == TYPE_STEEL)
+ && (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
+ && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
+ {
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_PSNPrevention;
+
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ RESET_RETURN
+ }
+ if (gBattleMons[gEffectBank].status1)
+ break;
+ if (gBattleMons[gEffectBank].type1 != TYPE_POISON
+ && gBattleMons[gEffectBank].type2 != TYPE_POISON
+ && gBattleMons[gEffectBank].type1 != TYPE_STEEL
+ && gBattleMons[gEffectBank].type2 != TYPE_STEEL)
+ {
+ if (gBattleMons[gEffectBank].ability == ABILITY_IMMUNITY)
+ break;
+
+ // It's redundant, because at this point we know the status1 value is 0.
+ gBattleMons[gEffectBank].status1 &= ~(STATUS_TOXIC_POISON);
+ gBattleMons[gEffectBank].status1 &= ~(STATUS_POISON);
+ statusChanged = TRUE;
+ break;
+ }
+ else
+ {
+ gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
+ }
+ break;
+ }
+ if (statusChanged == TRUE)
+ {
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+
+ if (sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]] == STATUS_SLEEP)
+ gBattleMons[gEffectBank].status1 |= ((Random() & 3) + 2);
+ else
+ gBattleMons[gEffectBank].status1 |= sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]];
+
+ gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
+
+ gActiveBank = gEffectBank;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gEffectBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+
+ if (gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ gHitMarker &= ~(HITMARKER_IGNORE_SAFEGUARD);
+ }
+ else
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+
+ // for synchronize
+
+ if (gBattleCommunication[MOVE_EFFECT_BYTE] == MOVE_EFFECT_POISON
+ || gBattleCommunication[MOVE_EFFECT_BYTE] == MOVE_EFFECT_TOXIC
+ || gBattleCommunication[MOVE_EFFECT_BYTE] == MOVE_EFFECT_PARALYSIS
+ || gBattleCommunication[MOVE_EFFECT_BYTE] == MOVE_EFFECT_BURN)
+ {
+ u8* synchronizeEffect = &gBattleStruct->synchronizeMoveEffect;
+ *synchronizeEffect = gBattleCommunication[MOVE_EFFECT_BYTE];
+ gHitMarker |= HITMARKER_SYNCHRONISE_EFFECT;
+ }
+ return;
+ }
+ else if (statusChanged == FALSE)
+ {
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
+ gBattlescriptCurrInstr++;
+ return;
+ }
+ return;
+ }
+ else
+ {
+ if (gBattleMons[gEffectBank].status2 & sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]])
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ u8 side;
+ switch (gBattleCommunication[MOVE_EFFECT_BYTE])
+ {
+ case MOVE_EFFECT_CONFUSION:
+ if (gBattleMons[gEffectBank].ability == ABILITY_OWN_TEMPO
+ || gBattleMons[gEffectBank].status2 & STATUS2_CONFUSION)
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gBattleMons[gEffectBank].status2 |= (((Random()) % 0x4)) + 2;
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
+ }
+ break;
+ case MOVE_EFFECT_FLINCH:
+ if (gBattleMons[gEffectBank].ability == ABILITY_INNER_FOCUS)
+ {
+ if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)
+ {
+ gLastUsedAbility = ABILITY_INNER_FOCUS;
+ RecordAbilityBattle(gEffectBank, ABILITY_INNER_FOCUS);
+ gBattlescriptCurrInstr = BattleScript_FlinchPrevention;
+ }
+ else
+ {
+ gBattlescriptCurrInstr++;
+ }
+ }
+ else
+ {
+ if (BankGetTurnOrder(gEffectBank) > gCurrentMoveTurn)
+ gBattleMons[gEffectBank].status2 |= sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]];
+ gBattlescriptCurrInstr++;
+ }
+ break;
+ case MOVE_EFFECT_UPROAR:
+ if (!(gBattleMons[gEffectBank].status2 & STATUS2_UPROAR))
+ {
+
+ gBattleMons[gEffectBank].status2 |= STATUS2_MULTIPLETURNS;
+ gLockedMoves[gEffectBank] = gCurrentMove;
+ gBattleMons[gEffectBank].status2 |= ((Random() & 3) + 2) << 4;
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
+ }
+ else
+ {
+ gBattlescriptCurrInstr++;
+ }
+ break;
+ case MOVE_EFFECT_PAYDAY:
+ if (GET_BANK_SIDE(gBankAttacker) == SIDE_PLAYER)
+ {
+ u16 PayDay = gPaydayMoney;
+ gPaydayMoney += (gBattleMons[gBankAttacker].level * 5);
+ if (PayDay > gPaydayMoney)
+ gPaydayMoney = 0xFFFF;
+ }
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
+ break;
+ case MOVE_EFFECT_TRI_ATTACK:
+ if (gBattleMons[gEffectBank].status1)
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gBattleCommunication[MOVE_EFFECT_BYTE] = Random() % 3 + 3;
+ SetMoveEffect(FALSE, 0);
+ }
+ break;
+ case MOVE_EFFECT_CHARGING:
+ gBattleMons[gEffectBank].status2 |= STATUS2_MULTIPLETURNS;
+ gLockedMoves[gEffectBank] = gCurrentMove;
+ gProtectStructs[gEffectBank].chargingTurn = 1;
+ gBattlescriptCurrInstr++;
+ break;
+ case MOVE_EFFECT_WRAP:
+ if (gBattleMons[gEffectBank].status2 & STATUS2_WRAPPED)
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gBattleMons[gEffectBank].status2 |= ((Random() & 3) + 3) << 0xD;
+
+ *(gBattleStruct->wrappedMove + gEffectBank * 2 + 0) = gCurrentMove;
+ *(gBattleStruct->wrappedMove + gEffectBank * 2 + 1) = gCurrentMove >> 8;
+ *(gBattleStruct->wrappedBy + gEffectBank) = gBankAttacker;
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
+
+ for (gBattleCommunication[MULTISTRING_CHOOSER] = 0; ; gBattleCommunication[MULTISTRING_CHOOSER]++)
+ {
+ if (gBattleCommunication[MULTISTRING_CHOOSER] > 4)
+ break;
+ if (gTrappingMoves[gBattleCommunication[MULTISTRING_CHOOSER]] == gCurrentMove)
+ break;
+ }
+ }
+ break;
+ case MOVE_EFFECT_RECOIL_25: // 25% recoil
+ gBattleMoveDamage = (gHpDealt) / 4;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
+ break;
+ case MOVE_EFFECT_ATK_PLUS_1:
+ case MOVE_EFFECT_DEF_PLUS_1:
+ case MOVE_EFFECT_SPD_PLUS_1:
+ case MOVE_EFFECT_SP_ATK_PLUS_1:
+ case MOVE_EFFECT_SP_DEF_PLUS_1:
+ case MOVE_EFFECT_ACC_PLUS_1:
+ case MOVE_EFFECT_EVS_PLUS_1:
+ if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1),
+ gBattleCommunication[MOVE_EFFECT_BYTE] - MOVE_EFFECT_ATK_PLUS_1 + 1,
+ affectsUser, 0))
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gBattleScripting.animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
+ gBattleScripting.animArg2 = 0;
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_StatUp;
+ }
+ break;
+ case MOVE_EFFECT_ATK_MINUS_1:
+ case MOVE_EFFECT_DEF_MINUS_1:
+ case MOVE_EFFECT_SPD_MINUS_1:
+ case MOVE_EFFECT_SP_ATK_MINUS_1:
+ case MOVE_EFFECT_SP_DEF_MINUS_1:
+ case MOVE_EFFECT_ACC_MINUS_1:
+ case MOVE_EFFECT_EVS_MINUS_1:
+ if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE,
+ gBattleCommunication[MOVE_EFFECT_BYTE] - MOVE_EFFECT_ATK_MINUS_1 + 1,
+ affectsUser, 0))
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gBattleScripting.animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
+ gBattleScripting.animArg2 = 0;
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_StatDown;
+ }
+ break;
+ case MOVE_EFFECT_ATK_PLUS_2:
+ case MOVE_EFFECT_DEF_PLUS_2:
+ case MOVE_EFFECT_SPD_PLUS_2:
+ case MOVE_EFFECT_SP_ATK_PLUS_2:
+ case MOVE_EFFECT_SP_DEF_PLUS_2:
+ case MOVE_EFFECT_ACC_PLUS_2:
+ case MOVE_EFFECT_EVS_PLUS_2:
+ if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2),
+ gBattleCommunication[MOVE_EFFECT_BYTE] - MOVE_EFFECT_ATK_PLUS_2 + 1,
+ affectsUser, 0))
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gBattleScripting.animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
+ gBattleScripting.animArg2 = 0;
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_StatUp;
+ }
+ break;
+ case MOVE_EFFECT_ATK_MINUS_2:
+ case MOVE_EFFECT_DEF_MINUS_2:
+ case MOVE_EFFECT_SPD_MINUS_2:
+ case MOVE_EFFECT_SP_ATK_MINUS_2:
+ case MOVE_EFFECT_SP_DEF_MINUS_2:
+ case MOVE_EFFECT_ACC_MINUS_2:
+ case MOVE_EFFECT_EVS_MINUS_2:
+ if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE,
+ gBattleCommunication[MOVE_EFFECT_BYTE] - MOVE_EFFECT_ATK_MINUS_2 + 1,
+ affectsUser, 0))
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gBattleScripting.animArg1 = gBattleCommunication[MOVE_EFFECT_BYTE] & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
+ gBattleScripting.animArg2 = 0;
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_StatDown;
+ }
+ break;
+ case MOVE_EFFECT_RECHARGE:
+ gBattleMons[gEffectBank].status2 |= STATUS2_RECHARGE;
+ gDisableStructs[gEffectBank].rechargeCounter = 2;
+ gLockedMoves[gEffectBank] = gCurrentMove;
+ gBattlescriptCurrInstr++;
+ break;
+ case MOVE_EFFECT_RAGE:
+ gBattleMons[gBankAttacker].status2 |= STATUS2_RAGE;
+ gBattlescriptCurrInstr++;
+ break;
+ case MOVE_EFFECT_STEAL_ITEM:
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x4000000)
+ {
+ gBattlescriptCurrInstr++;
+ break;
+ }
+
+ side = GetBankSide(gBankAttacker);
+ if (GetBankSide(gBankAttacker) == SIDE_OPPONENT
+ && !(gBattleTypeFlags &
+ (BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_FRONTIER
+ | BATTLE_TYPE_LINK
+ | BATTLE_TYPE_x2000000
+ | BATTLE_TYPE_SECRET_BASE)))
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else if (!(gBattleTypeFlags &
+ (BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_FRONTIER
+ | BATTLE_TYPE_LINK
+ | BATTLE_TYPE_x2000000
+ | BATTLE_TYPE_SECRET_BASE))
+ && (gWishFutureKnock.knockedOffPokes[side] & gBitTable[gBattlePartyID[gBankAttacker]]))
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else if (gBattleMons[gBankTarget].item
+ && gBattleMons[gBankTarget].ability == ABILITY_STICKY_HOLD)
+ {
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_NoItemSteal;
+
+ gLastUsedAbility = gBattleMons[gBankTarget].ability;
+ RecordAbilityBattle(gBankTarget, gLastUsedAbility);
+ }
+ else if (gBattleMons[gBankAttacker].item != 0
+ || gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY
+ || IS_ITEM_MAIL(gBattleMons[gBankTarget].item)
+ || gBattleMons[gBankTarget].item == 0)
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ u16* changedItem = &gBattleStruct->changedItems[gBankAttacker];
+ gLastUsedItem = *changedItem = gBattleMons[gBankTarget].item;
+ gBattleMons[gBankTarget].item = 0;
+
+ gActiveBank = gBankAttacker;
+ EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gLastUsedItem);
+ MarkBufferBankForExecution(gBankAttacker);
+
+ gActiveBank = gBankTarget;
+ EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gBankTarget].item);
+ MarkBufferBankForExecution(gBankTarget);
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_ItemSteal;
+
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gBankTarget]) + 0) = 0;
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gBankTarget]) + 1) = 0;
+ }
+
+ }
+ break;
+ case MOVE_EFFECT_PREVENT_ESCAPE:
+ gBattleMons[gBankTarget].status2 |= STATUS2_ESCAPE_PREVENTION;
+ gDisableStructs[gBankTarget].bankPreventingEscape = gBankAttacker;
+ gBattlescriptCurrInstr++;
+ break;
+ case MOVE_EFFECT_NIGHTMARE:
+ gBattleMons[gBankTarget].status2 |= STATUS2_NIGHTMARE;
+ gBattlescriptCurrInstr++;
+ break;
+ case MOVE_EFFECT_ALL_STATS_UP:
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_AllStatsUp;
+ break;
+ case MOVE_EFFECT_RAPIDSPIN:
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_RapidSpinAway;
+ break;
+ case MOVE_EFFECT_REMOVE_PARALYSIS: // Smelling salts
+ if (!(gBattleMons[gBankTarget].status1 & STATUS_PARALYSIS))
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gBattleMons[gBankTarget].status1 &= ~(STATUS_PARALYSIS);
+
+ gActiveBank = gBankTarget;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_TargetPRLZHeal;
+ }
+ break;
+ case MOVE_EFFECT_ATK_DEF_DOWN: // SuperPower
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_AtkDefDown;
+ break;
+ case MOVE_EFFECT_RECOIL_33_PARALYSIS: // Volt Tackle
+ gBattleMoveDamage = gHpDealt / 3;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleCommunication[MOVE_EFFECT_BYTE]];
+ break;
+ case MOVE_EFFECT_THRASH:
+ if (gBattleMons[gEffectBank].status2 & STATUS2_LOCK_CONFUSE)
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gBattleMons[gEffectBank].status2 |= STATUS2_MULTIPLETURNS;
+ gLockedMoves[gEffectBank] = gCurrentMove;
+ gBattleMons[gEffectBank].status2 |= (((Random() & 1) + 2) << 0xA);
+ }
+ break;
+ case MOVE_EFFECT_KNOCK_OFF:
+ if (gBattleMons[gEffectBank].ability == ABILITY_STICKY_HOLD)
+ {
+ if (gBattleMons[gEffectBank].item == 0)
+ {
+ gBattlescriptCurrInstr++;
+ }
+ else
+ {
+ gLastUsedAbility = ABILITY_STICKY_HOLD;
+ gBattlescriptCurrInstr = BattleScript_StickyHoldActivates;
+ RecordAbilityBattle(gEffectBank, ABILITY_STICKY_HOLD);
+ }
+ break;
+ }
+ if (gBattleMons[gEffectBank].item)
+ {
+ side = GetBankSide(gEffectBank);
+
+ gLastUsedItem = gBattleMons[gEffectBank].item;
+ gBattleMons[gEffectBank].item = 0;
+ gWishFutureKnock.knockedOffPokes[side] |= gBitTable[gBattlePartyID[gEffectBank]];
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_KnockedOff;
+
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gEffectBank]) + 0) = 0;
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gEffectBank]) + 1) = 0;
+ }
+ else
+ {
+ gBattlescriptCurrInstr++;
+ }
+ break;
+ case MOVE_EFFECT_SP_ATK_TWO_DOWN: // Overheat
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_SAtkDown2;
+ break;
+ }
+ }
+ }
+
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
+}
+
+static void atk15_seteffectwithchance(void)
+{
+ u32 percentChance;
+
+ if (gBattleMons[gBankAttacker].ability == ABILITY_SERENE_GRACE)
+ percentChance = gBattleMoves[gCurrentMove].secondaryEffectChance * 2;
+ else
+ percentChance = gBattleMoves[gCurrentMove].secondaryEffectChance;
+
+ if (gBattleCommunication[MOVE_EFFECT_BYTE] & MOVE_EFFECT_CERTAIN
+ && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
+ {
+ gBattleCommunication[MOVE_EFFECT_BYTE] &= ~(MOVE_EFFECT_CERTAIN);
+ SetMoveEffect(0, MOVE_EFFECT_CERTAIN);
+ }
+ else if (Random() % 100 < percentChance
+ && gBattleCommunication[MOVE_EFFECT_BYTE]
+ && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
+ {
+ if (percentChance >= 100)
+ SetMoveEffect(0, MOVE_EFFECT_CERTAIN);
+ else
+ SetMoveEffect(0, 0);
+ }
+ else
+ {
+ gBattlescriptCurrInstr++;
+ }
+
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
+ gBattleScripting.field_16 = 0;
+}
+
+static void atk16_seteffectprimary(void)
+{
+ SetMoveEffect(TRUE, 0);
+}
+
+static void atk17_seteffectsecondary(void)
+{
+ SetMoveEffect(FALSE, 0);
+}
+
+static void atk18_status_effect_clear(void)
+{
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ if (gBattleCommunication[MOVE_EFFECT_BYTE] <= MOVE_EFFECT_TOXIC)
+ gBattleMons[gActiveBank].status1 &= (~sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]);
+ else
+ gBattleMons[gActiveBank].status2 &= (~sStatusFlagsForMoveEffects[gBattleCommunication[MOVE_EFFECT_BYTE]]);
+
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
+ gBattlescriptCurrInstr += 2;
+ gBattleScripting.field_16 = 0;
+}
+
+static void atk19_faint_pokemon(void)
+{
+ const u8 *BS_ptr;
+
+ if (gBattlescriptCurrInstr[2] != 0)
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ if (gHitMarker & HITMARKER_FAINTED(gActiveBank))
+ {
+ BS_ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 3);
+
+ BattleScriptPop();
+ gBattlescriptCurrInstr = BS_ptr;
+ gSideAffecting[GetBankSide(gActiveBank)] &= ~(SIDE_STATUS_SPIKES_DAMAGED);
+ }
+ else
+ {
+ gBattlescriptCurrInstr += 7;
+ }
+ }
+ else
+ {
+ u8 bank;
+
+ if (gBattlescriptCurrInstr[1] == BS_GET_ATTACKER)
+ {
+ gActiveBank = gBankAttacker;
+ bank = gBankTarget;
+ BS_ptr = BattleScript_FaintAttacker;
+ }
+ else
+ {
+ gActiveBank = gBankTarget;
+ bank = gBankAttacker;
+ BS_ptr = BattleScript_FaintTarget;
+ }
+ if (!(gAbsentBankFlags & gBitTable[gActiveBank])
+ && gBattleMons[gActiveBank].hp == 0)
+ {
+ gHitMarker |= HITMARKER_FAINTED(gActiveBank);
+ BattleScriptPush(gBattlescriptCurrInstr + 7);
+ gBattlescriptCurrInstr = BS_ptr;
+ if (GetBankSide(gActiveBank) == SIDE_PLAYER)
+ {
+ gHitMarker |= HITMARKER_x400000;
+ if (gBattleResults.playerFaintCounter < 0xFF)
+ gBattleResults.playerFaintCounter++;
+ AdjustFriendshipOnBattleFaint(gActiveBank);
+ }
+ else
+ {
+ if (gBattleResults.opponentFaintCounter < 0xFF)
+ gBattleResults.opponentFaintCounter++;
+ gBattleResults.lastOpponentSpecies = GetMonData(&gEnemyParty[gBattlePartyID[gActiveBank]], MON_DATA_SPECIES, NULL);
+ }
+ if ((gHitMarker & HITMARKER_DESTINYBOND) && gBattleMons[gBankAttacker].hp != 0)
+ {
+ gHitMarker &= ~(HITMARKER_DESTINYBOND);
+ BattleScriptPush(gBattlescriptCurrInstr);
+ gBattleMoveDamage = gBattleMons[bank].hp;
+ gBattlescriptCurrInstr = BattleScript_DestinyBondTakesLife;
+ }
+ if ((gStatuses3[gBankTarget] & STATUS3_GRUDGE)
+ && !(gHitMarker & HITMARKER_GRUDGE)
+ && GetBankSide(gBankAttacker) != GetBankSide(gBankTarget)
+ && gBattleMons[gBankAttacker].hp != 0
+ && gCurrentMove != MOVE_STRUGGLE)
+ {
+ u8 moveIndex = *(gBattleStruct->chosenMovesIds + gBankAttacker);
+
+ gBattleMons[gBankAttacker].pp[moveIndex] = 0;
+ BattleScriptPush(gBattlescriptCurrInstr);
+ gBattlescriptCurrInstr = BattleScript_GrudgeTakesPp;
+ gActiveBank = gBankAttacker;
+ EmitSetMonData(0, moveIndex + REQUEST_PPMOVE1_BATTLE, 0, 1, &gBattleMons[gActiveBank].pp[moveIndex]);
+ MarkBufferBankForExecution(gActiveBank);
+
+ PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBankAttacker].moves[moveIndex])
+ }
+ }
+ else
+ {
+ gBattlescriptCurrInstr += 7;
+ }
+ }
+}
+
+static void atk1A_faint_animation(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ EmitFaintAnimation(0);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 2;
+ }
+}
+
+static void atk1B_faint_effects_clear(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_ARENA) || gBattleMons[gActiveBank].hp == 0)
+ {
+ gBattleMons[gActiveBank].status1 = 0;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 0x4, &gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+
+ UndoEffectsAfterFainting(); // Effects like attractions, trapping, etc.
+ gBattlescriptCurrInstr += 2;
+ }
+}
+
+static void atk1C_jumpifstatus(void)
+{
+ u8 bank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ u32 flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2);
+ const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6);
+
+ if (gBattleMons[bank].status1 & flags && gBattleMons[bank].hp)
+ gBattlescriptCurrInstr = jumpPtr;
+ else
+ gBattlescriptCurrInstr += 10;
+}
+
+static void atk1D_jumpifstatus2(void)
+{
+ u8 bank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ u32 flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2);
+ const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6);
+
+ if (gBattleMons[bank].status2 & flags && gBattleMons[bank].hp)
+ gBattlescriptCurrInstr = jumpPtr;
+ else
+ gBattlescriptCurrInstr += 10;
+}
+
+static void atk1E_jumpifability(void)
+{
+ u8 bank;
+ u8 ability = gBattlescriptCurrInstr[2];
+ const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3);
+
+ if (gBattlescriptCurrInstr[1] == BS_GET_ATTACKER_SIDE)
+ {
+ bank = AbilityBattleEffects(ABILITYEFFECT_CHECK_BANK_SIDE, gBankAttacker, ability, 0, 0);
+ if (bank)
+ {
+ gLastUsedAbility = ability;
+ gBattlescriptCurrInstr = jumpPtr;
+ RecordAbilityBattle(bank - 1, gLastUsedAbility);
+ gBattleScripting.field_15 = bank - 1;
+ }
+ else
+ gBattlescriptCurrInstr += 7;
+ }
+ else if (gBattlescriptCurrInstr[1] == BS_GET_NOT_ATTACKER_SIDE)
+ {
+ bank = AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gBankAttacker, ability, 0, 0);
+ if (bank)
+ {
+ gLastUsedAbility = ability;
+ gBattlescriptCurrInstr = jumpPtr;
+ RecordAbilityBattle(bank - 1, gLastUsedAbility);
+ gBattleScripting.field_15 = bank - 1;
+ }
+ else
+ gBattlescriptCurrInstr += 7;
+ }
+ else
+ {
+ bank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ if (gBattleMons[bank].ability == ability)
+ {
+ gLastUsedAbility = ability;
+ gBattlescriptCurrInstr = jumpPtr;
+ RecordAbilityBattle(bank, gLastUsedAbility);
+ gBattleScripting.field_15 = bank;
+ }
+ else
+ gBattlescriptCurrInstr += 7;
+ }
+}
+
+static void atk1F_jumpifsideaffecting(void)
+{
+ u8 side;
+ u16 flags;
+ const u8* jumpPtr;
+
+ if (gBattlescriptCurrInstr[1] == BS_GET_ATTACKER)
+ side = GET_BANK_SIDE(gBankAttacker);
+ else
+ side = GET_BANK_SIDE(gBankTarget);
+
+ flags = BS2ScriptRead16(gBattlescriptCurrInstr + 2);
+ jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 4);
+
+ if (gSideAffecting[side] & flags)
+ gBattlescriptCurrInstr = jumpPtr;
+ else
+ gBattlescriptCurrInstr += 8;
+}
+
+static void atk20_jumpifstat(void)
+{
+ u8 ret = 0;
+ u8 bank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ u8 value = gBattleMons[bank].statStages[gBattlescriptCurrInstr[3]];
+
+ switch (gBattlescriptCurrInstr[2])
+ {
+ case CMP_EQUAL:
+ if (value == gBattlescriptCurrInstr[4])
+ ret++;
+ break;
+ case CMP_NOT_EQUAL:
+ if (value != gBattlescriptCurrInstr[4])
+ ret++;
+ break;
+ case CMP_GREATER_THAN:
+ if (value > gBattlescriptCurrInstr[4])
+ ret++;
+ break;
+ case CMP_LESS_THAN:
+ if (value < gBattlescriptCurrInstr[4])
+ ret++;
+ break;
+ case CMP_COMMON_BITS:
+ if (value & gBattlescriptCurrInstr[4])
+ ret++;
+ break;
+ case CMP_NO_COMMON_BITS:
+ if (!(value & gBattlescriptCurrInstr[4]))
+ ret++;
+ break;
+ }
+
+ if (ret)
+ gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5);
+ else
+ gBattlescriptCurrInstr += 9;
+}
+
+static void atk21_jumpifstatus3(void)
+{
+ u32 flags;
+ const u8* jumpPtr;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ flags = BS2ScriptRead32(gBattlescriptCurrInstr + 2);
+ jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 7);
+
+ if (gBattlescriptCurrInstr[6])
+ {
+ if ((gStatuses3[gActiveBank] & flags) != 0)
+ gBattlescriptCurrInstr += 11;
+ else
+ gBattlescriptCurrInstr = jumpPtr;
+ }
+ else
+ {
+ if ((gStatuses3[gActiveBank] & flags) != 0)
+ gBattlescriptCurrInstr = jumpPtr;
+ else
+ gBattlescriptCurrInstr += 11;
+ }
+}
+
+static void atk22_jumpiftype(void)
+{
+ u8 bank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ u8 type = gBattlescriptCurrInstr[2];
+ const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3);
+
+ if (gBattleMons[bank].type1 == type || gBattleMons[bank].type2 == type)
+ gBattlescriptCurrInstr = jumpPtr;
+ else
+ gBattlescriptCurrInstr += 7;
+}
+
+static void atk23_getexp(void)
+{
+ u16 item;
+ s32 i; // also used as stringId
+ u8 holdEffect;
+ s32 sentIn;
+
+ s32 viaExpShare = 0;
+ u16* exp = &gBattleStruct->expValue;
+
+ gBank1 = GetBattleBank(gBattlescriptCurrInstr[1]);
+ sentIn = gSentPokesToOpponent[(gBank1 & 2) >> 1];
+
+ switch (gBattleScripting.atk23_state)
+ {
+ case 0: // check if should receive exp at all
+ if (GetBankSide(gBank1) != SIDE_OPPONENT || (gBattleTypeFlags &
+ (BATTLE_TYPE_LINK
+ | BATTLE_TYPE_x2000000
+ | BATTLE_TYPE_x4000000
+ | BATTLE_TYPE_FRONTIER
+ | BATTLE_TYPE_SAFARI
+ | BATTLE_TYPE_BATTLE_TOWER
+ | BATTLE_TYPE_EREADER_TRAINER)))
+ {
+ gBattleScripting.atk23_state = 6; // goto last case
+ }
+ else
+ {
+ gBattleScripting.atk23_state++;
+ gBattleStruct->field_DF |= gBitTable[gBattlePartyID[gBank1]];
+ }
+ break;
+ case 1: // calculate experience points to redistribute
+ {
+ u16 calculatedExp;
+ s32 viaSentIn;
+
+ for (viaSentIn = 0, i = 0; i < 6; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) == SPECIES_NONE || GetMonData(&gPlayerParty[i], MON_DATA_HP) == 0)
+ continue;
+ if (gBitTable[i] & sentIn)
+ viaSentIn++;
+
+ item = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
+
+ if (item == ITEM_ENIGMA_BERRY)
+ holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(item);
+
+ if (holdEffect == HOLD_EFFECT_EXP_SHARE)
+ viaExpShare++;
+ }
+
+ calculatedExp = gBaseStats[gBattleMons[gBank1].species].expYield * gBattleMons[gBank1].level / 7;
+
+ if (viaExpShare) // at least one mon is getting exp via exp share
+ {
+ *exp = calculatedExp / 2 / viaSentIn;
+ if (*exp == 0)
+ *exp = 1;
+
+ gExpShareExp = calculatedExp / 2 / viaExpShare;
+ if (gExpShareExp == 0)
+ gExpShareExp = 1;
+ }
+ else
+ {
+ *exp = calculatedExp / viaSentIn;
+ if (*exp == 0)
+ *exp = 1;
+ gExpShareExp = 0;
+ }
+
+ gBattleScripting.atk23_state++;
+ gBattleStruct->expGetterId = 0;
+ gBattleStruct->sentInPokes = sentIn;
+ }
+ // fall through
+ case 2: // set exp value to the poke in expgetter_id and print message
+ if (gBattleExecBuffer == 0)
+ {
+ item = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_HELD_ITEM);
+
+ if (item == ITEM_ENIGMA_BERRY)
+ holdEffect = gSaveBlock1Ptr->enigmaBerry.holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(item);
+
+ if (holdEffect != HOLD_EFFECT_EXP_SHARE && !(gBattleStruct->sentInPokes & 1))
+ {
+ *(&gBattleStruct->sentInPokes) >>= 1;
+ gBattleScripting.atk23_state = 5;
+ gBattleMoveDamage = 0; // used for exp
+ }
+ else if (GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL) == MAX_MON_LEVEL)
+ {
+ *(&gBattleStruct->sentInPokes) >>= 1;
+ gBattleScripting.atk23_state = 5;
+ gBattleMoveDamage = 0; // used for exp
+ }
+ else
+ {
+ // music change in wild battle after fainting a poke
+ if (!(gBattleTypeFlags & BATTLE_TYPE_TRAINER) && gBattleMons[0].hp && !gBattleStruct->wildVictorySong)
+ {
+ BattleMusicStop();
+ PlayBGM(0x161);
+ gBattleStruct->wildVictorySong++;
+ }
+
+ if (GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_HP))
+ {
+ if (gBattleStruct->sentInPokes & 1)
+ gBattleMoveDamage = *exp;
+ else
+ gBattleMoveDamage = 0;
+
+ if (holdEffect == HOLD_EFFECT_EXP_SHARE)
+ gBattleMoveDamage += gExpShareExp;
+ if (holdEffect == HOLD_EFFECT_LUCKY_EGG)
+ gBattleMoveDamage = (gBattleMoveDamage * 150) / 100;
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ gBattleMoveDamage = (gBattleMoveDamage * 150) / 100;
+
+ if (IsTradedMon(&gPlayerParty[gBattleStruct->expGetterId]))
+ {
+ // check if the pokemon doesn't belong to the player
+ if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gBattleStruct->expGetterId >= 3)
+ {
+ i = 0x149;
+ }
+ else
+ {
+ gBattleMoveDamage = (gBattleMoveDamage * 150) / 100;
+ i = 0x14A;
+ }
+ }
+ else
+ {
+ i = 0x149;
+ }
+
+ // get exp getter bank
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ {
+ if (!(gBattlePartyID[2] != gBattleStruct->expGetterId) && !(gAbsentBankFlags & gBitTable[2]))
+ gBattleStruct->expGetterBank = 2;
+ else
+ {
+ if (!(gAbsentBankFlags & gBitTable[0]))
+ gBattleStruct->expGetterBank = 0;
+ else
+ gBattleStruct->expGetterBank = 2;
+ }
+ }
+ else
+ gBattleStruct->expGetterBank = 0;
+
+ PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBattleStruct->expGetterBank, gBattleStruct->expGetterId)
+
+ // buffer 'gained' or 'gained a boosted'
+ PREPARE_STRING_BUFFER(gBattleTextBuff2, i)
+
+ PREPARE_WORD_NUMBER_BUFFER(gBattleTextBuff3, 5, gBattleMoveDamage)
+
+ PrepareStringBattle(0xD, gBattleStruct->expGetterBank);
+ MonGainEVs(&gPlayerParty[gBattleStruct->expGetterId], gBattleMons[gBank1].species);
+ }
+ gBattleStruct->sentInPokes >>= 1;
+ gBattleScripting.atk23_state++;
+ }
+ }
+ break;
+ case 3: // Set stats and give exp
+ if (gBattleExecBuffer == 0)
+ {
+ gBattleBufferB[gBattleStruct->expGetterBank][0] = 0;
+ if (GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_HP) && GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL) != MAX_MON_LEVEL)
+ {
+ BATTLE_LVLUP_STATS->hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_MAX_HP);
+ BATTLE_LVLUP_STATS->atk = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_ATK);
+ BATTLE_LVLUP_STATS->def = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_DEF);
+ BATTLE_LVLUP_STATS->spd = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPD);
+ BATTLE_LVLUP_STATS->spAtk = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPATK);
+ BATTLE_LVLUP_STATS->spDef = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPDEF);
+
+ gActiveBank = gBattleStruct->expGetterBank;
+ EmitExpUpdate(0, gBattleStruct->expGetterId, gBattleMoveDamage);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ gBattleScripting.atk23_state++;
+ }
+ break;
+ case 4: // lvl up if necessary
+ if (gBattleExecBuffer == 0)
+ {
+ gActiveBank = gBattleStruct->expGetterBank;
+ if (gBattleBufferB[gActiveBank][0] == 0x21 && gBattleBufferB[gActiveBank][1] == 0xB)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER && gBattlePartyID[gActiveBank] == gBattleStruct->expGetterId)
+ sub_805E990(&gPlayerParty[gBattlePartyID[gActiveBank]], gActiveBank);
+
+ PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gActiveBank, gBattleStruct->expGetterId)
+
+ PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 3, GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL))
+
+ BattleScriptPushCursor();
+ gLeveledUpInBattle |= gBitTable[gBattleStruct->expGetterId];
+ gBattlescriptCurrInstr = BattleScript_LevelUp;
+ gBattleMoveDamage = (gBattleBufferB[gActiveBank][2] | (gBattleBufferB[gActiveBank][3] << 8));
+ AdjustFriendship(&gPlayerParty[gBattleStruct->expGetterId], 0);
+
+ // update battle mon structure after level up
+ if (gBattlePartyID[0] == gBattleStruct->expGetterId && gBattleMons[0].hp)
+ {
+ gBattleMons[0].level = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL);
+ gBattleMons[0].hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_HP);
+ gBattleMons[0].maxHP = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_MAX_HP);
+ gBattleMons[0].attack = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_ATK);
+ gBattleMons[0].defense = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_DEF);
+ // Why is this duplicated?
+ gBattleMons[0].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPD);
+ gBattleMons[0].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPD);
+
+ gBattleMons[0].spAttack = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPATK);
+ gBattleMons[0].spDefense = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPDEF);
+ }
+ // What is else if?
+ if (gBattlePartyID[2] == gBattleStruct->expGetterId && gBattleMons[2].hp && (gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ {
+ gBattleMons[2].level = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL);
+ gBattleMons[2].hp = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_HP);
+ gBattleMons[2].maxHP = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_MAX_HP);
+ gBattleMons[2].attack = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_ATK);
+ gBattleMons[2].defense = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_DEF);
+ // Duplicated again, but this time there's no Sp Defense
+ gBattleMons[2].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPD);
+ gBattleMons[2].speed = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPD);
+
+ gBattleMons[2].spAttack = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPATK);
+ }
+ gBattleScripting.atk23_state = 5;
+ }
+ else
+ {
+ gBattleMoveDamage = 0;
+ gBattleScripting.atk23_state = 5;
+ }
+ }
+ break;
+ case 5: // looper increment
+ if (gBattleMoveDamage) // there is exp to give, goto case 3 that gives exp
+ gBattleScripting.atk23_state = 3;
+ else
+ {
+ gBattleStruct->expGetterId++;
+ if (gBattleStruct->expGetterId <= 5)
+ gBattleScripting.atk23_state = 2; // loop again
+ else
+ gBattleScripting.atk23_state = 6; // we're done
+ }
+ break;
+ case 6: // increment instruction
+ if (gBattleExecBuffer == 0)
+ {
+ // not sure why gf clears the item and ability here
+ gBattleMons[gBank1].item = 0;
+ gBattleMons[gBank1].ability = 0;
+ gBattlescriptCurrInstr += 2;
+ }
+ break;
+ }
+}
+
+#ifdef NONMATCHING
+static void atk24(void)
+{
+ u16 HP_count = 0;
+ s32 i;
+
+ if (gBattleExecBuffer)
+ return;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && gPartnerTrainerId == STEVEN_PARTNER_ID)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG))
+ HP_count += GetMonData(&gPlayerParty[i], MON_DATA_HP);
+ }
+ }
+ else
+ {
+ for (i = 0; i < 6; i++)
+ {
+ if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)
+ && (!(gBattleTypeFlags & BATTLE_TYPE_ARENA) || !(gBattleStruct->field_2A0 & gBitTable[i])))
+ {
+ HP_count += GetMonData(&gPlayerParty[i], MON_DATA_HP);
+ }
+ }
+ }
+
+ if (HP_count == 0)
+ gBattleOutcome |= BATTLE_LOST;
+
+ for (HP_count = 0, i = 0; i < 6; i++)
+ {
+ if (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES) && !GetMonData(&gEnemyParty[i], MON_DATA_IS_EGG)
+ && (!(gBattleTypeFlags & BATTLE_TYPE_ARENA) || !(gBattleStruct->field_2A1 & gBitTable[i])))
+ {
+ HP_count += GetMonData(&gEnemyParty[i], MON_DATA_HP);
+ }
+ }
+
+ if (HP_count == 0)
+ gBattleOutcome |= BATTLE_WON;
+
+ if (gBattleOutcome == 0 && (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
+ {
+ s32 foundPlayer;
+ s32 foundOpponent;
+
+ // Impossible to decompile loops.
+ for (foundPlayer = 0, i = 0; i < gNoOfAllBanks; i += 2)
+ {
+ if (HITMARKER_UNK(i) & gHitMarker && !gSpecialStatuses[i].flag40)
+ foundPlayer++;
+ }
+
+ for (foundOpponent = 0, i = 1; i < gNoOfAllBanks; i += 2)
+ {
+ if (HITMARKER_UNK(i) & gHitMarker && !gSpecialStatuses[i].flag40)
+ foundOpponent++;
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ if (foundOpponent + foundPlayer > 1)
+ gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ else
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ if (foundOpponent != 0 && foundPlayer != 0)
+ gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ else
+ gBattlescriptCurrInstr += 5;
+ }
+ }
+ else
+ {
+ gBattlescriptCurrInstr += 5;
+ }
+}
+#else
+__attribute__((naked))
+static void atk24(void)
+{
+ asm("\n\
+ .syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r8\n\
+ push {r7}\n\
+ movs r6, 0\n\
+ ldr r0, =gBattleExecBuffer\n\
+ ldr r0, [r0]\n\
+ cmp r0, 0\n\
+ beq _0804ACE2\n\
+ b _0804AF22\n\
+ _0804ACE2:\n\
+ ldr r0, =gBattleTypeFlags\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x80\n\
+ lsls r1, 15\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0804AD48\n\
+ ldr r0, =gPartnerTrainerId\n\
+ ldrh r1, [r0]\n\
+ ldr r0, =0x00000c03\n\
+ cmp r1, r0\n\
+ bne _0804AD48\n\
+ movs r5, 0\n\
+ _0804ACFC:\n\
+ movs r0, 0x64\n\
+ adds r1, r5, 0\n\
+ muls r1, r0\n\
+ ldr r0, =gPlayerParty\n\
+ adds r4, r1, r0\n\
+ adds r0, r4, 0\n\
+ movs r1, 0xB\n\
+ bl GetMonData\n\
+ cmp r0, 0\n\
+ beq _0804AD2C\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x2D\n\
+ bl GetMonData\n\
+ cmp r0, 0\n\
+ bne _0804AD2C\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x39\n\
+ bl GetMonData\n\
+ adds r0, r6, r0\n\
+ lsls r0, 16\n\
+ lsrs r6, r0, 16\n\
+ _0804AD2C:\n\
+ adds r5, 0x1\n\
+ cmp r5, 0x2\n\
+ ble _0804ACFC\n\
+ b _0804ADA8\n\
+ .pool\n\
+ _0804AD48:\n\
+ movs r5, 0\n\
+ _0804AD4A:\n\
+ movs r0, 0x64\n\
+ adds r1, r5, 0\n\
+ muls r1, r0\n\
+ ldr r0, =gPlayerParty\n\
+ adds r4, r1, r0\n\
+ adds r0, r4, 0\n\
+ movs r1, 0xB\n\
+ bl GetMonData\n\
+ cmp r0, 0\n\
+ beq _0804ADA2\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x2D\n\
+ bl GetMonData\n\
+ cmp r0, 0\n\
+ bne _0804ADA2\n\
+ ldr r0, =gBattleTypeFlags\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x80\n\
+ lsls r1, 11\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0804AD94\n\
+ ldr r0, =gBattleStruct\n\
+ ldr r0, [r0]\n\
+ movs r1, 0xA8\n\
+ lsls r1, 2\n\
+ adds r0, r1\n\
+ ldrb r1, [r0]\n\
+ ldr r2, =gBitTable\n\
+ lsls r0, r5, 2\n\
+ adds r0, r2\n\
+ ldr r0, [r0]\n\
+ ands r1, r0\n\
+ cmp r1, 0\n\
+ bne _0804ADA2\n\
+ _0804AD94:\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x39\n\
+ bl GetMonData\n\
+ adds r0, r6, r0\n\
+ lsls r0, 16\n\
+ lsrs r6, r0, 16\n\
+ _0804ADA2:\n\
+ adds r5, 0x1\n\
+ cmp r5, 0x5\n\
+ ble _0804AD4A\n\
+ _0804ADA8:\n\
+ cmp r6, 0\n\
+ bne _0804ADB6\n\
+ ldr r0, =gBattleOutcome\n\
+ ldrb r1, [r0]\n\
+ movs r2, 0x2\n\
+ orrs r1, r2\n\
+ strb r1, [r0]\n\
+ _0804ADB6:\n\
+ movs r6, 0\n\
+ movs r5, 0\n\
+ _0804ADBA:\n\
+ movs r0, 0x64\n\
+ adds r1, r5, 0\n\
+ muls r1, r0\n\
+ ldr r0, =gEnemyParty\n\
+ adds r4, r1, r0\n\
+ adds r0, r4, 0\n\
+ movs r1, 0xB\n\
+ bl GetMonData\n\
+ cmp r0, 0\n\
+ beq _0804AE10\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x2D\n\
+ bl GetMonData\n\
+ cmp r0, 0\n\
+ bne _0804AE10\n\
+ ldr r0, =gBattleTypeFlags\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x80\n\
+ lsls r1, 11\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0804AE02\n\
+ ldr r0, =gBattleStruct\n\
+ ldr r0, [r0]\n\
+ ldr r1, =0x000002a1\n\
+ adds r0, r1\n\
+ ldrb r1, [r0]\n\
+ ldr r2, =gBitTable\n\
+ lsls r0, r5, 2\n\
+ adds r0, r2\n\
+ ldr r0, [r0]\n\
+ ands r1, r0\n\
+ cmp r1, 0\n\
+ bne _0804AE10\n\
+ _0804AE02:\n\
+ adds r0, r4, 0\n\
+ movs r1, 0x39\n\
+ bl GetMonData\n\
+ adds r0, r6, r0\n\
+ lsls r0, 16\n\
+ lsrs r6, r0, 16\n\
+ _0804AE10:\n\
+ adds r5, 0x1\n\
+ cmp r5, 0x5\n\
+ ble _0804ADBA\n\
+ ldr r2, =gBattleOutcome\n\
+ cmp r6, 0\n\
+ bne _0804AE24\n\
+ ldrb r0, [r2]\n\
+ movs r1, 0x1\n\
+ orrs r0, r1\n\
+ strb r0, [r2]\n\
+ _0804AE24:\n\
+ ldrb r0, [r2]\n\
+ cmp r0, 0\n\
+ bne _0804AF1A\n\
+ ldr r0, =gBattleTypeFlags\n\
+ ldr r1, [r0]\n\
+ ldr r2, =0x02000002\n\
+ ands r1, r2\n\
+ mov r8, r0\n\
+ cmp r1, 0\n\
+ beq _0804AF1A\n\
+ movs r3, 0\n\
+ movs r5, 0\n\
+ ldr r0, =gNoOfAllBanks\n\
+ ldrb r1, [r0]\n\
+ mov r12, r0\n\
+ ldr r7, =gBattlescriptCurrInstr\n\
+ cmp r3, r1\n\
+ bge _0804AE70\n\
+ ldr r0, =gHitMarker\n\
+ movs r6, 0x80\n\
+ lsls r6, 21\n\
+ ldr r4, [r0]\n\
+ adds r2, r1, 0\n\
+ ldr r1, =gSpecialStatuses\n\
+ _0804AE54:\n\
+ adds r0, r6, 0\n\
+ lsls r0, r5\n\
+ ands r0, r4\n\
+ cmp r0, 0\n\
+ beq _0804AE68\n\
+ ldrb r0, [r1]\n\
+ lsls r0, 25\n\
+ cmp r0, 0\n\
+ blt _0804AE68\n\
+ adds r3, 0x1\n\
+ _0804AE68:\n\
+ adds r1, 0x28\n\
+ adds r5, 0x2\n\
+ cmp r5, r2\n\
+ blt _0804AE54\n\
+ _0804AE70:\n\
+ movs r2, 0\n\
+ movs r5, 0x1\n\
+ mov r4, r12\n\
+ ldrb r1, [r4]\n\
+ cmp r5, r1\n\
+ bge _0804AEAA\n\
+ ldr r0, =gHitMarker\n\
+ movs r4, 0x80\n\
+ lsls r4, 21\n\
+ mov r12, r4\n\
+ ldr r6, [r0]\n\
+ ldr r0, =gSpecialStatuses\n\
+ adds r4, r1, 0\n\
+ adds r1, r0, 0\n\
+ adds r1, 0x14\n\
+ _0804AE8E:\n\
+ mov r0, r12\n\
+ lsls r0, r5\n\
+ ands r0, r6\n\
+ cmp r0, 0\n\
+ beq _0804AEA2\n\
+ ldrb r0, [r1]\n\
+ lsls r0, 25\n\
+ cmp r0, 0\n\
+ blt _0804AEA2\n\
+ adds r2, 0x1\n\
+ _0804AEA2:\n\
+ adds r1, 0x28\n\
+ adds r5, 0x2\n\
+ cmp r5, r4\n\
+ blt _0804AE8E\n\
+ _0804AEAA:\n\
+ mov r1, r8\n\
+ ldr r0, [r1]\n\
+ movs r1, 0x40\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0804AEF0\n\
+ adds r0, r2, r3\n\
+ cmp r0, 0x1\n\
+ bgt _0804AEF8\n\
+ b _0804AF12\n\
+ .pool\n\
+ _0804AEF0:\n\
+ cmp r2, 0\n\
+ beq _0804AF12\n\
+ cmp r3, 0\n\
+ beq _0804AF12\n\
+ _0804AEF8:\n\
+ ldr r2, [r7]\n\
+ ldrb r1, [r2, 0x1]\n\
+ ldrb r0, [r2, 0x2]\n\
+ lsls r0, 8\n\
+ adds r1, r0\n\
+ ldrb r0, [r2, 0x3]\n\
+ lsls r0, 16\n\
+ adds r1, r0\n\
+ ldrb r0, [r2, 0x4]\n\
+ lsls r0, 24\n\
+ adds r1, r0\n\
+ str r1, [r7]\n\
+ b _0804AF22\n\
+ _0804AF12:\n\
+ ldr r0, [r7]\n\
+ adds r0, 0x5\n\
+ str r0, [r7]\n\
+ b _0804AF22\n\
+ _0804AF1A:\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, [r1]\n\
+ adds r0, 0x5\n\
+ str r0, [r1]\n\
+ _0804AF22:\n\
+ pop {r3}\n\
+ mov r8, r3\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .pool\n\
+ .syntax divided");
+}
+
+#endif // NONMATCHING
+
+static void MoveValuesCleanUp(void)
+{
+ gBattleMoveFlags = 0;
+ gBattleScripting.dmgMultiplier = 1;
+ gCritMultiplier = 1;
+ gBattleCommunication[MOVE_EFFECT_BYTE] = 0;
+ gBattleCommunication[6] = 0;
+ gHitMarker &= ~(HITMARKER_DESTINYBOND);
+ gHitMarker &= ~(HITMARKER_SYNCHRONISE_EFFECT);
+}
+
+static void atk25_move_values_cleanup(void)
+{
+ MoveValuesCleanUp();
+ gBattlescriptCurrInstr += 1;
+}
+
+static void atk26_set_multihit(void)
+{
+ gMultiHitCounter = gBattlescriptCurrInstr[1];
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk27_decrement_multihit(void)
+{
+ if (--gMultiHitCounter == 0)
+ gBattlescriptCurrInstr += 5;
+ else
+ gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+}
+
+static void atk28_goto(void)
+{
+ gBattlescriptCurrInstr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+}
+
+static void atk29_jumpifbyte(void)
+{
+ u8 caseID = gBattlescriptCurrInstr[1];
+ const u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2);
+ u8 value = gBattlescriptCurrInstr[6];
+ const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 7);
+
+ gBattlescriptCurrInstr += 11;
+
+ switch (caseID)
+ {
+ case CMP_EQUAL:
+ if (*memByte == value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_NOT_EQUAL:
+ if (*memByte != value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_GREATER_THAN:
+ if (*memByte > value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_LESS_THAN:
+ if (*memByte < value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_COMMON_BITS:
+ if (*memByte & value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_NO_COMMON_BITS:
+ if (!(*memByte & value))
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ }
+}
+
+static void atk2A_jumpifhalfword(void)
+{
+ u8 caseID = gBattlescriptCurrInstr[1];
+ const u16* memHword = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2);
+ u16 value = BS2ScriptRead16(gBattlescriptCurrInstr + 6);
+ const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 8);
+
+ gBattlescriptCurrInstr += 12;
+
+ switch (caseID)
+ {
+ case CMP_EQUAL:
+ if (*memHword == value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_NOT_EQUAL:
+ if (*memHword != value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_GREATER_THAN:
+ if (*memHword > value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_LESS_THAN:
+ if (*memHword < value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_COMMON_BITS:
+ if (*memHword & value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_NO_COMMON_BITS:
+ if (!(*memHword & value))
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ }
+}
+
+static void atk2B_jumpifword(void)
+{
+ u8 caseID = gBattlescriptCurrInstr[1];
+ const u32* memWord = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2);
+ u32 value = BSScriptRead32(gBattlescriptCurrInstr + 6);
+ const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10);
+
+ gBattlescriptCurrInstr += 14;
+
+ switch (caseID)
+ {
+ case CMP_EQUAL:
+ if (*memWord == value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_NOT_EQUAL:
+ if (*memWord != value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_GREATER_THAN:
+ if (*memWord > value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_LESS_THAN:
+ if (*memWord < value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_COMMON_BITS:
+ if (*memWord & value)
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ case CMP_NO_COMMON_BITS:
+ if (!(*memWord & value))
+ gBattlescriptCurrInstr = jumpPtr;
+ break;
+ }
+}
+
+static void atk2C_jumpifarrayequal(void)
+{
+ const u8* mem1 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ const u8* mem2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5);
+ u32 size = gBattlescriptCurrInstr[9];
+ const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10);
+
+ u8 i;
+ for (i = 0; i < size; i++)
+ {
+ if (*mem1 != *mem2)
+ {
+ gBattlescriptCurrInstr += 14;
+ break;
+ }
+ mem1++, mem2++;
+ }
+
+ if (i == size)
+ gBattlescriptCurrInstr = jumpPtr;
+}
+
+static void atk2D_jumpifarraynotequal(void)
+{
+ u8 equalBytes = 0;
+ const u8* mem1 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ const u8* mem2 = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5);
+ u32 size = gBattlescriptCurrInstr[9];
+ const u8* jumpPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 10);
+
+ u8 i;
+ for (i = 0; i < size; i++)
+ {
+ if (*mem1 == *mem2)
+ {
+ equalBytes++;
+ }
+ mem1++, mem2++;
+ }
+
+ if (equalBytes != size)
+ gBattlescriptCurrInstr = jumpPtr;
+ else
+ gBattlescriptCurrInstr += 14;
+}
+
+static void atk2E_setbyte(void)
+{
+ u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ *memByte = gBattlescriptCurrInstr[5];
+
+ gBattlescriptCurrInstr += 6;
+}
+
+static void atk2F_addbyte(void)
+{
+ u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ *memByte += gBattlescriptCurrInstr[5];
+ gBattlescriptCurrInstr += 6;
+}
+
+static void atk30_subbyte(void)
+{
+ u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ *memByte -= gBattlescriptCurrInstr[5];
+ gBattlescriptCurrInstr += 6;
+}
+
+static void atk31_copyarray(void)
+{
+ u8* dest = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ const u8* src = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5);
+ s32 size = gBattlescriptCurrInstr[9];
+
+ s32 i;
+ for (i = 0; i < size; i++)
+ {
+ dest[i] = src[i];
+ }
+
+ gBattlescriptCurrInstr += 10;
+}
+
+static void atk32_copyarray_withindex(void)
+{
+ u8* dest = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ const u8* src = BS2ScriptReadPtr(gBattlescriptCurrInstr + 5);
+ const u8* index = BS2ScriptReadPtr(gBattlescriptCurrInstr + 9);
+ s32 size = gBattlescriptCurrInstr[13];
+
+ s32 i;
+ for (i = 0; i < size; i++)
+ {
+ dest[i] = src[i + *index];
+ }
+
+ gBattlescriptCurrInstr += 14;
+}
+
+static void atk33_orbyte(void)
+{
+ u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ *memByte |= gBattlescriptCurrInstr[5];
+ gBattlescriptCurrInstr += 6;
+}
+
+static void atk34_orhalfword(void)
+{
+ u16* memHword = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ u16 val = BS2ScriptRead16(gBattlescriptCurrInstr + 5);
+
+ *memHword |= val;
+ gBattlescriptCurrInstr += 7;
+}
+
+static void atk35_orword(void)
+{
+ u32* memWord = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ u32 val = BS2ScriptRead32(gBattlescriptCurrInstr + 5);
+
+ *memWord |= val;
+ gBattlescriptCurrInstr += 9;
+}
+
+static void atk36_bicbyte(void)
+{
+ u8* memByte = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ *memByte &= ~(gBattlescriptCurrInstr[5]);
+ gBattlescriptCurrInstr += 6;
+}
+
+static void atk37_bichalfword(void)
+{
+ u16* memHword = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ u16 val = BS2ScriptRead16(gBattlescriptCurrInstr + 5);
+
+ *memHword &= ~val;
+ gBattlescriptCurrInstr += 7;
+}
+
+static void atk38_bicword(void)
+{
+ u32* memWord = BS2ScriptReadPtr(gBattlescriptCurrInstr + 1);
+ u32 val = BS2ScriptRead32(gBattlescriptCurrInstr + 5);
+
+ *memWord &= ~val;
+ gBattlescriptCurrInstr += 9;
+}
+
+static void atk39_pause(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ u16 value = BS2ScriptRead16(gBattlescriptCurrInstr + 1);
+ if (++gPauseCounterBattle >= value)
+ {
+ gPauseCounterBattle = 0;
+ gBattlescriptCurrInstr += 3;
+ }
+ }
+}
+
+static void atk3A_waitstate(void)
+{
+ if (gBattleExecBuffer == 0)
+ gBattlescriptCurrInstr++;
+}
+
+static void atk3B_healthbar_update(void)
+{
+ if (gBattlescriptCurrInstr[1] == BS_GET_TARGET)
+ gActiveBank = gBankTarget;
+ else
+ gActiveBank = gBankAttacker;
+
+ EmitHealthBarUpdate(0, gBattleMoveDamage);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk3C_return(void)
+{
+ BattleScriptPop();
+}
+
+static void atk3D_end(void)
+{
+ if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
+ sub_81A5718(gBankAttacker);
+
+ gBattleMoveFlags = 0;
+ gActiveBank = 0;
+ gFightStateTracker = 0xB;
+}
+
+static void atk3E_end2(void)
+{
+ gActiveBank = 0;
+ gFightStateTracker = 0xB;
+}
+
+static void atk3F_end3(void) // pops the main function stack
+{
+ BattleScriptPop();
+ if (BATTLE_CALLBACKS_STACK->size)
+ BATTLE_CALLBACKS_STACK->size--;
+ gBattleMainFunc = BATTLE_CALLBACKS_STACK->function[BATTLE_CALLBACKS_STACK->size];
+}
+
+static void atk41_call(void)
+{
+ BattleScriptPush(gBattlescriptCurrInstr + 5);
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+}
+
+static void atk42_jumpiftype2(void)
+{
+ u8 bank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ if (gBattlescriptCurrInstr[2] == gBattleMons[bank].type1 || gBattlescriptCurrInstr[2] == gBattleMons[bank].type2)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 3);
+ else
+ gBattlescriptCurrInstr += 7;
+}
+
+static void atk43_jumpifabilitypresent(void)
+{
+ if (AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, gBattlescriptCurrInstr[1], 0, 0))
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ else
+ gBattlescriptCurrInstr += 6;
+}
+
+static void atk44(void)
+{
+ *(gBankAttacker + gBattleStruct->field_54) = 1;
+}
+
+static void atk45_playanimation(void)
+{
+ const u16* argumentPtr;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ argumentPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 3);
+
+ if (gBattlescriptCurrInstr[2] == B_ANIM_STATS_CHANGE
+ || gBattlescriptCurrInstr[2] == B_ANIM_SNATCH_MOVE
+ || gBattlescriptCurrInstr[2] == B_ANIM_SUBSTITUTE_FADE)
+ {
+ EmitBattleAnimation(0, gBattlescriptCurrInstr[2], *argumentPtr);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 7;
+ }
+ else if (gHitMarker & HITMARKER_NO_ANIMATIONS)
+ {
+ BattleScriptPush(gBattlescriptCurrInstr + 7);
+ gBattlescriptCurrInstr = BattleScript_Pausex20;
+ }
+ else if (gBattlescriptCurrInstr[2] == B_ANIM_RAIN_CONTINUES
+ || gBattlescriptCurrInstr[2] == B_ANIM_SUN_CONTINUES
+ || gBattlescriptCurrInstr[2] == B_ANIM_SANDSTORM_CONTINUES
+ || gBattlescriptCurrInstr[2] == B_ANIM_HAIL_CONTINUES)
+ {
+ EmitBattleAnimation(0, gBattlescriptCurrInstr[2], *argumentPtr);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 7;
+ }
+ else if (gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE)
+ {
+ gBattlescriptCurrInstr += 7;
+ }
+ else
+ {
+ EmitBattleAnimation(0, gBattlescriptCurrInstr[2], *argumentPtr);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 7;
+ }
+}
+
+static void atk46_playanimation2(void) // animation Id is stored in the first pointer
+{
+ const u16* argumentPtr;
+ const u8* animationIdPtr;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ animationIdPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 2);
+ argumentPtr = BS2ScriptReadPtr(gBattlescriptCurrInstr + 6);
+
+ if (*animationIdPtr == B_ANIM_STATS_CHANGE
+ || *animationIdPtr == B_ANIM_SNATCH_MOVE
+ || *animationIdPtr == B_ANIM_SUBSTITUTE_FADE)
+ {
+ EmitBattleAnimation(0, *animationIdPtr, *argumentPtr);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 10;
+ }
+ else if (gHitMarker & HITMARKER_NO_ANIMATIONS)
+ {
+ gBattlescriptCurrInstr += 10;
+ }
+ else if (*animationIdPtr == B_ANIM_RAIN_CONTINUES
+ || *animationIdPtr == B_ANIM_SUN_CONTINUES
+ || *animationIdPtr == B_ANIM_SANDSTORM_CONTINUES
+ || *animationIdPtr == B_ANIM_HAIL_CONTINUES)
+ {
+ EmitBattleAnimation(0, *animationIdPtr, *argumentPtr);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 10;
+ }
+ else if (gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE)
+ {
+ gBattlescriptCurrInstr += 10;
+ }
+ else
+ {
+ EmitBattleAnimation(0, *animationIdPtr, *argumentPtr);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 10;
+ }
+}
+
+static void atk47_setgraphicalstatchangevalues(void)
+{
+ u8 value = 0;
+ switch (gBattleScripting.statChanger & 0xF0)
+ {
+ case 0x10: // +1
+ value = 0xF;
+ break;
+ case 0x20: // +2
+ value = 0x27;
+ break;
+ case 0x90: // -1
+ value = 0x16;
+ break;
+ case 0xA0: // -2
+ value = 0x2E;
+ break;
+ }
+ gBattleScripting.animArg1 = (gBattleScripting.statChanger & 0xF) + value - 1;
+ gBattleScripting.animArg2 = 0;
+ gBattlescriptCurrInstr++;
+}
+
+#ifdef NONMATCHING
+static void atk48_playstatchangeanimation(void)
+{
+ u32 currStat = 0;
+ s16 statAnimId = 0;
+ s16 checkingStatAnimId = 0;
+ s32 changeableStats = 0;
+ u32 statsToCheck = 0;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ statsToCheck = gBattlescriptCurrInstr[2];
+
+ if (gBattlescriptCurrInstr[3] & ATK48_STAT_NEGATIVE) // goes down
+ {
+ checkingStatAnimId = (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO) ? 0x2D : 0x15;
+ while (statsToCheck != 0)
+ {
+ if (statsToCheck & 1)
+ {
+ if (!(gBattlescriptCurrInstr[3] & ATK48_LOWER_FAIL_CHECK))
+ {
+ if (gBattleMons[gActiveBank].statStages[currStat] > 0)
+ {
+ statAnimId = checkingStatAnimId;
+ changeableStats++;
+ }
+ }
+ else if (!gSideTimers[GET_BANK_SIDE(gActiveBank)].mistTimer
+ && gBattleMons[gActiveBank].ability != ABILITY_CLEAR_BODY
+ && gBattleMons[gActiveBank].ability != ABILITY_WHITE_SMOKE
+ && !(gBattleMons[gActiveBank].ability == ABILITY_KEEN_EYE && currStat == STAT_STAGE_ACC)
+ && !(gBattleMons[gActiveBank].ability == ABILITY_HYPER_CUTTER && currStat == STAT_STAGE_ATK))
+ {
+ if (gBattleMons[gActiveBank].statStages[currStat] > 0)
+ {
+ statAnimId = checkingStatAnimId;
+ changeableStats++;
+ }
+ }
+ }
+ statsToCheck >>= 1, checkingStatAnimId++, currStat++;
+ }
+
+ if (changeableStats > 1) // more than one stat, so the color is gray
+ {
+ if (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO)
+ statAnimId = 0x3A;
+ else
+ statAnimId = 0x39;
+ }
+ }
+ else // goes up
+ {
+ checkingStatAnimId = (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO) ? 0x26 : 0xE;
+ while (statsToCheck != 0)
+ {
+ if (statsToCheck & 1 && gBattleMons[gActiveBank].statStages[currStat] < 0xC)
+ {
+ statAnimId = checkingStatAnimId;
+ changeableStats++;
+ }
+ statsToCheck >>= 1, checkingStatAnimId += 1, currStat++;
+ }
+
+ if (changeableStats > 1) // more than one stat, so the color is gray
+ {
+ if (gBattlescriptCurrInstr[3] & ATK48_STAT_BY_TWO)
+ statAnimId = 0x38;
+ else
+ statAnimId = 0x37;
+ }
+ }
+
+ if (gBattlescriptCurrInstr[3] & ATK48_BIT_x4 && changeableStats < 2)
+ {
+ gBattlescriptCurrInstr += 4;
+ }
+ else if (changeableStats != 0 && gBattleScripting.field_1B == 0)
+ {
+ EmitBattleAnimation(0, B_ANIM_STATS_CHANGE, statAnimId);
+ MarkBufferBankForExecution(gActiveBank);
+ if (gBattlescriptCurrInstr[3] & ATK48_BIT_x4 && changeableStats > 1)
+ gBattleScripting.field_1B = 1;
+ gBattlescriptCurrInstr += 4;
+ }
+ else
+ {
+ gBattlescriptCurrInstr += 4;
+ }
+}
+#else
+__attribute__((naked))
+static void atk48_playstatchangeanimation(void)
+{
+ asm("\n\
+ .syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ sub sp, 0x4\n\
+ movs r7, 0\n\
+ movs r0, 0\n\
+ mov r8, r0\n\
+ movs r3, 0\n\
+ ldr r5, =gBattlescriptCurrInstr\n\
+ ldr r0, [r5]\n\
+ ldrb r0, [r0, 0x1]\n\
+ str r3, [sp]\n\
+ bl GetBattleBank\n\
+ ldr r2, =gActiveBank\n\
+ strb r0, [r2]\n\
+ ldr r0, [r5]\n\
+ ldrb r4, [r0, 0x2]\n\
+ ldrb r1, [r0, 0x3]\n\
+ movs r0, 0x1\n\
+ ands r0, r1\n\
+ ldr r3, [sp]\n\
+ cmp r0, 0\n\
+ beq _0804BAEC\n\
+ movs r0, 0x2\n\
+ ands r0, r1\n\
+ movs r1, 0x15\n\
+ cmp r0, 0\n\
+ beq _0804BA18\n\
+ movs r1, 0x2D\n\
+_0804BA18:\n\
+ cmp r4, 0\n\
+ beq _0804BAC0\n\
+ movs r0, 0x1\n\
+ mov r10, r0\n\
+ ldr r0, =gBattleMons + 0x18\n\
+ mov r9, r0\n\
+ lsls r5, r1, 16\n\
+_0804BA26:\n\
+ adds r0, r4, 0\n\
+ mov r1, r10\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0804BAB2\n\
+ ldr r0, =gBattlescriptCurrInstr\n\
+ ldr r0, [r0]\n\
+ ldrb r1, [r0, 0x3]\n\
+ movs r0, 0x8\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0804BA58\n\
+ ldr r0, =gActiveBank\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x58\n\
+ muls r0, r1\n\
+ adds r0, r7, r0\n\
+ b _0804BAA0\n\
+ .pool\n\
+_0804BA58:\n\
+ ldr r6, =gActiveBank\n\
+ ldrb r0, [r6]\n\
+ str r3, [sp]\n\
+ bl GetBankIdentity\n\
+ mov r1, r10\n\
+ ands r1, r0\n\
+ lsls r0, r1, 1\n\
+ adds r0, r1\n\
+ lsls r0, 2\n\
+ ldr r1, =gSideTimers\n\
+ adds r0, r1\n\
+ ldrb r0, [r0, 0x4]\n\
+ ldr r3, [sp]\n\
+ cmp r0, 0\n\
+ bne _0804BAB2\n\
+ ldr r0, =gBattleMons\n\
+ ldrb r2, [r6]\n\
+ movs r1, 0x58\n\
+ muls r2, r1\n\
+ adds r0, r2, r0\n\
+ adds r0, 0x20\n\
+ ldrb r0, [r0]\n\
+ cmp r0, 0x1D\n\
+ beq _0804BAB2\n\
+ cmp r0, 0x49\n\
+ beq _0804BAB2\n\
+ cmp r0, 0x33\n\
+ bne _0804BA96\n\
+ cmp r7, 0x6\n\
+ beq _0804BAB2\n\
+_0804BA96:\n\
+ cmp r0, 0x34\n\
+ bne _0804BA9E\n\
+ cmp r7, 0x1\n\
+ beq _0804BAB2\n\
+_0804BA9E:\n\
+ adds r0, r7, r2\n\
+_0804BAA0:\n\
+ add r0, r9\n\
+ ldrb r0, [r0]\n\
+ lsls r0, 24\n\
+ asrs r0, 24\n\
+ cmp r0, 0\n\
+ ble _0804BAB2\n\
+ lsrs r0, r5, 16\n\
+ mov r8, r0\n\
+ adds r3, 0x1\n\
+_0804BAB2:\n\
+ lsrs r4, 1\n\
+ movs r1, 0x80\n\
+ lsls r1, 9\n\
+ adds r5, r1\n\
+ adds r7, 0x1\n\
+ cmp r4, 0\n\
+ bne _0804BA26\n\
+_0804BAC0:\n\
+ ldr r0, =gBattlescriptCurrInstr\n\
+ mov r9, r0\n\
+ cmp r3, 0x1\n\
+ ble _0804BB4E\n\
+ ldr r0, [r0]\n\
+ ldrb r1, [r0, 0x3]\n\
+ movs r0, 0x2\n\
+ ands r0, r1\n\
+ movs r1, 0x39\n\
+ mov r8, r1\n\
+ cmp r0, 0\n\
+ beq _0804BB4E\n\
+ movs r0, 0x3A\n\
+ b _0804BB4C\n\
+ .pool\n\
+_0804BAEC:\n\
+ movs r0, 0x2\n\
+ ands r0, r1\n\
+ movs r1, 0xE\n\
+ cmp r0, 0\n\
+ beq _0804BAF8\n\
+ movs r1, 0x26\n\
+_0804BAF8:\n\
+ mov r9, r5\n\
+ cmp r4, 0\n\
+ beq _0804BB34\n\
+ ldr r6, =gBattleMons + 0x18\n\
+ adds r5, r2, 0\n\
+ lsls r2, r1, 16\n\
+_0804BB04:\n\
+ movs r0, 0x1\n\
+ ands r0, r4\n\
+ cmp r0, 0\n\
+ beq _0804BB26\n\
+ ldrb r1, [r5]\n\
+ movs r0, 0x58\n\
+ muls r0, r1\n\
+ adds r0, r7, r0\n\
+ adds r0, r6\n\
+ ldrb r0, [r0]\n\
+ lsls r0, 24\n\
+ asrs r0, 24\n\
+ cmp r0, 0xB\n\
+ bgt _0804BB26\n\
+ lsrs r1, r2, 16\n\
+ mov r8, r1\n\
+ adds r3, 0x1\n\
+_0804BB26:\n\
+ lsrs r4, 1\n\
+ movs r0, 0x80\n\
+ lsls r0, 9\n\
+ adds r2, r0\n\
+ adds r7, 0x1\n\
+ cmp r4, 0\n\
+ bne _0804BB04\n\
+_0804BB34:\n\
+ cmp r3, 0x1\n\
+ ble _0804BB4E\n\
+ mov r1, r9\n\
+ ldr r0, [r1]\n\
+ ldrb r1, [r0, 0x3]\n\
+ movs r0, 0x2\n\
+ ands r0, r1\n\
+ movs r1, 0x37\n\
+ mov r8, r1\n\
+ cmp r0, 0\n\
+ beq _0804BB4E\n\
+ movs r0, 0x38\n\
+_0804BB4C:\n\
+ mov r8, r0\n\
+_0804BB4E:\n\
+ mov r1, r9\n\
+ ldr r2, [r1]\n\
+ ldrb r1, [r2, 0x3]\n\
+ movs r0, 0x4\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _0804BB6C\n\
+ cmp r3, 0x1\n\
+ bgt _0804BB6C\n\
+ adds r0, r2, 0x4\n\
+ mov r1, r9\n\
+ b _0804BBBA\n\
+ .pool\n\
+_0804BB6C:\n\
+ cmp r3, 0\n\
+ beq _0804BBB4\n\
+ ldr r4, =gBattleScripting\n\
+ ldrb r0, [r4, 0x1B]\n\
+ cmp r0, 0\n\
+ bne _0804BBB4\n\
+ movs r0, 0\n\
+ movs r1, 0x1\n\
+ mov r2, r8\n\
+ str r3, [sp]\n\
+ bl EmitBattleAnimation\n\
+ ldr r0, =gActiveBank\n\
+ ldrb r0, [r0]\n\
+ bl MarkBufferBankForExecution\n\
+ ldr r0, =gBattlescriptCurrInstr\n\
+ ldr r0, [r0]\n\
+ ldrb r1, [r0, 0x3]\n\
+ movs r0, 0x4\n\
+ ands r0, r1\n\
+ ldr r3, [sp]\n\
+ cmp r0, 0\n\
+ beq _0804BBA4\n\
+ cmp r3, 0x1\n\
+ ble _0804BBA4\n\
+ movs r0, 0x1\n\
+ strb r0, [r4, 0x1B]\n\
+_0804BBA4:\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ b _0804BBB6\n\
+ .pool\n\
+_0804BBB4:\n\
+ mov r1, r9\n\
+_0804BBB6:\n\
+ ldr r0, [r1]\n\
+ adds r0, 0x4\n\
+_0804BBBA:\n\
+ str r0, [r1]\n\
+ add sp, 0x4\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .syntax divided");
+}
+#endif // NONMATCHING
+
+#define ATK49_LAST_CASE 17
+
+static void atk49_moveend(void)
+{
+ s32 i;
+ bool32 effect;
+ u8 moveType;
+ u8 holdEffectAtk;
+ u16 *choicedMoveAtk;
+ u8 arg1, arg2;
+ u16 lastMove;
+
+ effect = FALSE;
+
+ if (gLastUsedMove == 0xFFFF)
+ lastMove = 0;
+ else
+ lastMove = gLastUsedMove;
+
+ arg1 = gBattlescriptCurrInstr[1];
+ arg2 = gBattlescriptCurrInstr[2];
+
+ if (gBattleMons[gBankAttacker].item == ITEM_ENIGMA_BERRY)
+ holdEffectAtk = gEnigmaBerries[gBankAttacker].holdEffect;
+ else
+ holdEffectAtk = ItemId_GetHoldEffect(gBattleMons[gBankAttacker].item);
+
+ choicedMoveAtk = &gBattleStruct->choicedMove[gBankAttacker];
+
+ GET_MOVE_TYPE(gCurrentMove, moveType);
+
+ do
+ {
+ switch (gBattleScripting.atk49_state)
+ {
+ case 0: // rage check
+ if (gBattleMons[gBankTarget].status2 & STATUS2_RAGE
+ && gBattleMons[gBankTarget].hp != 0 && gBankAttacker != gBankTarget
+ && GetBankSide(gBankAttacker) != GetBankSide(gBankTarget)
+ && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT) && TARGET_TURN_DAMAGED
+ && gBattleMoves[gCurrentMove].power && gBattleMons[gBankTarget].statStages[STAT_STAGE_ATK] <= 0xB)
+ {
+ gBattleMons[gBankTarget].statStages[STAT_STAGE_ATK]++;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_RageIsBuilding;
+ effect = TRUE;
+ }
+ gBattleScripting.atk49_state++;
+ break;
+ case 1: // defrosting check
+ if (gBattleMons[gBankTarget].status1 & STATUS_FREEZE
+ && gBattleMons[gBankTarget].hp != 0 && gBankAttacker != gBankTarget
+ && gSpecialStatuses[gBankTarget].moveturnLostHP_special
+ && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT) && moveType == TYPE_FIRE)
+ {
+ gBattleMons[gBankTarget].status1 &= ~(STATUS_FREEZE);
+ gActiveBank = gBankTarget;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBankTarget].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_DefrostedViaFireMove;
+ effect = TRUE;
+ }
+ gBattleScripting.atk49_state++;
+ break;
+ case 2: // target synchronize
+ if (AbilityBattleEffects(ABILITYEFFECT_SYNCHRONIZE, gBankTarget, 0, 0, 0))
+ effect = TRUE;
+ gBattleScripting.atk49_state++;
+ break;
+ case 3: // contact abilities
+ if (AbilityBattleEffects(ABILITYEFFECT_CONTACT, gBankTarget, 0, 0, 0))
+ effect = TRUE;
+ gBattleScripting.atk49_state++;
+ break;
+ case 4: // status immunities
+ if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, 0, 0, 0, 0))
+ effect = TRUE; // it loops through all banks, so we increment after its done with all banks
+ else
+ gBattleScripting.atk49_state++;
+ break;
+ case 5: // attacker synchronize
+ if (AbilityBattleEffects(ABILITYEFFECT_ATK_SYNCHRONIZE, gBankAttacker, 0, 0, 0))
+ effect = TRUE;
+ gBattleScripting.atk49_state++;
+ break;
+ case 6: // update choice band move
+ if (!(gHitMarker & HITMARKER_OBEYS) || holdEffectAtk != HOLD_EFFECT_CHOICE_BAND
+ || gLastUsedMove == MOVE_STRUGGLE || (*choicedMoveAtk != 0 && *choicedMoveAtk != 0xFFFF))
+ goto LOOP;
+ if (gLastUsedMove == MOVE_BATON_PASS && !(gBattleMoveFlags & MOVESTATUS_FAILED))
+ {
+ gBattleScripting.atk49_state++;
+ break;
+ }
+ *choicedMoveAtk = gLastUsedMove;
+ LOOP:
+ {
+ for (i = 0; i < 4; i++)
+ {
+ if (gBattleMons[gBankAttacker].moves[i] == *choicedMoveAtk)
+ break;
+ }
+ if (i == 4)
+ *choicedMoveAtk = 0;
+
+ gBattleScripting.atk49_state++;
+ }
+ break;
+ case 7: // changed held items
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ u16* changedItem = &gBattleStruct->changedItems[i];
+ if (*changedItem != 0)
+ {
+ gBattleMons[i].item = *changedItem;
+ *changedItem = 0;
+ }
+ }
+ gBattleScripting.atk49_state++;
+ break;
+ case 11: // item effects for all banks
+ if (ItemBattleEffects(3, 0, FALSE))
+ effect = TRUE;
+ else
+ gBattleScripting.atk49_state++;
+ break;
+ case 12: // king's rock and shell bell
+ if (ItemBattleEffects(4, 0, FALSE))
+ effect = TRUE;
+ gBattleScripting.atk49_state++;
+ break;
+ case 8: // make attacker sprite invisible
+ if (gStatuses3[gBankAttacker] & (STATUS3_SEMI_INVULNERABLE)
+ && gHitMarker & HITMARKER_NO_ANIMATIONS)
+ {
+ gActiveBank = gBankAttacker;
+ EmitSpriteInvisibility(0, TRUE);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattleScripting.atk49_state++;
+ return;
+ }
+ gBattleScripting.atk49_state++;
+ break;
+ case 9: // make attacker sprite visible
+ if (gBattleMoveFlags & MOVESTATUS_NOEFFECT
+ || !(gStatuses3[gBankAttacker] & (STATUS3_SEMI_INVULNERABLE))
+ || HasMoveFailed(gBankAttacker))
+ {
+ gActiveBank = gBankAttacker;
+ EmitSpriteInvisibility(0, FALSE);
+ MarkBufferBankForExecution(gActiveBank);
+ gStatuses3[gBankAttacker] &= ~(STATUS3_SEMI_INVULNERABLE);
+ gSpecialStatuses[gBankAttacker].restoredBankSprite = 1;
+ gBattleScripting.atk49_state++;
+ return;
+ }
+ gBattleScripting.atk49_state++;
+ break;
+ case 10: // make target sprite visible
+ if (!gSpecialStatuses[gBankTarget].restoredBankSprite && gBankTarget < gNoOfAllBanks
+ && !(gStatuses3[gBankTarget] & STATUS3_SEMI_INVULNERABLE))
+ {
+ gActiveBank = gBankTarget;
+ EmitSpriteInvisibility(0, FALSE);
+ MarkBufferBankForExecution(gActiveBank);
+ gStatuses3[gBankTarget] &= ~(STATUS3_SEMI_INVULNERABLE);
+ gBattleScripting.atk49_state++;
+ return;
+ }
+ gBattleScripting.atk49_state++;
+ break;
+ case 13: // update substitute
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gDisableStructs[i].substituteHP == 0)
+ gBattleMons[i].status2 &= ~(STATUS2_SUBSTITUTE);
+ }
+ gBattleScripting.atk49_state++;
+ break;
+ case 14: // This case looks interesting, although I am not certain what it does. Probably fine tunes edge cases.
+ if (gHitMarker & HITMARKER_PURSUIT_TRAP)
+ {
+ gActiveBank = gBankAttacker;
+ gBankAttacker = gBankTarget;
+ gBankTarget = gActiveBank;
+ gHitMarker &= ~(HITMARKER_PURSUIT_TRAP);
+ }
+ if (gHitMarker & HITMARKER_ATTACKSTRING_PRINTED)
+ {
+ gUnknownMovesUsedByBanks[gBankAttacker] = gLastUsedMove;
+ }
+ if (!(gAbsentBankFlags & gBitTable[gBankAttacker])
+ && !(gBattleStruct->field_91 & gBitTable[gBankAttacker])
+ && gBattleMoves[lastMove].effect != EFFECT_BATON_PASS)
+ {
+ if (gHitMarker & HITMARKER_OBEYS)
+ {
+ gLastUsedMovesByBanks[gBankAttacker] = gLastUsedMove;
+ gUnknown_02024260[gBankAttacker] = gCurrentMove;
+ }
+ else
+ {
+ gLastUsedMovesByBanks[gBankAttacker] = 0xFFFF;
+ gUnknown_02024260[gBankAttacker] = 0xFFFF;
+ }
+
+ if (!(gHitMarker & HITMARKER_FAINTED(gBankTarget)))
+ gUnknown_02024270[gBankTarget] = gBankAttacker;
+
+ if (gHitMarker & HITMARKER_OBEYS && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
+ {
+ if (gLastUsedMove == 0xFFFF)
+ {
+ gUnknown_02024250[gBankTarget] = gLastUsedMove;
+ }
+ else
+ {
+ gUnknown_02024250[gBankTarget] = gCurrentMove;
+ GET_MOVE_TYPE(gCurrentMove, gUnknown_02024258[gBankTarget]);
+ }
+ }
+ else
+ {
+ gUnknown_02024250[gBankTarget] = 0xFFFF;
+ }
+ }
+ gBattleScripting.atk49_state++;
+ break;
+ case 15: // mirror move
+ if (!(gAbsentBankFlags & gBitTable[gBankAttacker]) && !(gBattleStruct->field_91 & gBitTable[gBankAttacker])
+ && gBattleMoves[lastMove].flags & FLAG_MIRROR_MOVE_AFFECTED && gHitMarker & HITMARKER_OBEYS
+ && gBankAttacker != gBankTarget && !(gHitMarker & HITMARKER_FAINTED(gBankTarget))
+ && !(gBattleMoveFlags & MOVESTATUS_NOEFFECT))
+ {
+ u8 target, attacker;
+
+ *(gBattleStruct->mirrorMoves + gBankTarget * 2 + 0) = gLastUsedMove;
+ *(gBattleStruct->mirrorMoves + gBankTarget * 2 + 1) = gLastUsedMove >> 8;
+
+ target = gBankTarget;
+ attacker = gBankAttacker;
+ *(attacker * 2 + target * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0) = gLastUsedMove;
+
+ target = gBankTarget;
+ attacker = gBankAttacker;
+ *(attacker * 2 + target * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) = gLastUsedMove >> 8;
+ }
+ gBattleScripting.atk49_state++;
+ break;
+ case 16: //
+ if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && gBattleTypeFlags & BATTLE_TYPE_DOUBLE
+ && !gProtectStructs[gBankAttacker].chargingTurn && gBattleMoves[gCurrentMove].target == MOVE_TARGET_BOTH
+ && !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
+ {
+ u8 bank = GetBankByIdentity(GetBankIdentity(gBankTarget) ^ BIT_MON);
+ if (gBattleMons[bank].hp != 0)
+ {
+ gBankTarget = bank;
+ gHitMarker |= HITMARKER_NO_ATTACKSTRING;
+ gBattleScripting.atk49_state = 0;
+ MoveValuesCleanUp();
+ BattleScriptPush(gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]);
+ gBattlescriptCurrInstr = gUnknown_082DB87D;
+ return;
+ }
+ else
+ {
+ gHitMarker |= HITMARKER_NO_ATTACKSTRING;
+ }
+ }
+ gBattleScripting.atk49_state++;
+ break;
+ case ATK49_LAST_CASE:
+ break;
+ }
+
+ if (arg1 == 1 && effect == FALSE)
+ gBattleScripting.atk49_state = ATK49_LAST_CASE;
+ if (arg1 == 2 && arg2 == gBattleScripting.atk49_state)
+ gBattleScripting.atk49_state = ATK49_LAST_CASE;
+
+ } while (gBattleScripting.atk49_state != ATK49_LAST_CASE && effect == FALSE);
+
+ if (gBattleScripting.atk49_state == ATK49_LAST_CASE && effect == FALSE)
+ gBattlescriptCurrInstr += 3;
+}
+
+static void atk4A_typecalc2(void)
+{
+ u8 flags = 0;
+ s32 i = 0;
+ u8 moveType = gBattleMoves[gCurrentMove].type;
+
+ if (gBattleMons[gBankTarget].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
+ {
+ gLastUsedAbility = gBattleMons[gBankTarget].ability;
+ gBattleMoveFlags |= (MOVESTATUS_MISSED | MOVESTATUS_NOTAFFECTED);
+ gUnknown_02024250[gBankTarget] = 0;
+ gBattleCommunication[6] = moveType;
+ RecordAbilityBattle(gBankTarget, gLastUsedAbility);
+ }
+ else
+ {
+ while (gTypeEffectiveness[i]!= TYPE_ENDTABLE)
+ {
+ if (gTypeEffectiveness[i] == TYPE_FORESIGHT)
+ {
+ if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT)
+ {
+ break;
+ }
+ else
+ {
+ i += 3;
+ continue;
+ }
+ }
+
+ if (gTypeEffectiveness[i] == moveType)
+ {
+ // check type1
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type1)
+ {
+ if (gTypeEffectiveness[i + 2] == 0)
+ {
+ gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
+ break;
+ }
+ if (gTypeEffectiveness[i + 2] == 5)
+ {
+ flags |= MOVESTATUS_NOTVERYEFFECTIVE;
+ }
+ if (gTypeEffectiveness[i + 2] == 20)
+ {
+ flags |= MOVESTATUS_SUPEREFFECTIVE;
+ }
+ }
+ // check type2
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2)
+ {
+ if (gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2
+ && gTypeEffectiveness[i + 2] == 0)
+ {
+ gBattleMoveFlags |= MOVESTATUS_NOTAFFECTED;
+ break;
+ }
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2
+ && gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2
+ && gTypeEffectiveness[i + 2] == 5)
+ {
+ flags |= MOVESTATUS_NOTVERYEFFECTIVE;
+ }
+ if (gTypeEffectiveness[i + 1] == gBattleMons[gBankTarget].type2
+ && gBattleMons[gBankTarget].type1 != gBattleMons[gBankTarget].type2
+ && gTypeEffectiveness[i + 2] == 20)
+ {
+ flags |= MOVESTATUS_SUPEREFFECTIVE;
+ }
+ }
+ }
+ i += 3;
+ }
+ }
+
+ if (gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD
+ && !(flags & MOVESTATUS_NOEFFECT)
+ && AttacksThisTurn(gBankAttacker, gCurrentMove) == 2
+ && (!(flags & MOVESTATUS_SUPEREFFECTIVE) || ((flags & (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)) == (MOVESTATUS_SUPEREFFECTIVE | MOVESTATUS_NOTVERYEFFECTIVE)))
+ && gBattleMoves[gCurrentMove].power)
+ {
+ gLastUsedAbility = ABILITY_WONDER_GUARD;
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gUnknown_02024250[gBankTarget] = 0;
+ gBattleCommunication[6] = 3;
+ RecordAbilityBattle(gBankTarget, gLastUsedAbility);
+ }
+ if (gBattleMoveFlags & MOVESTATUS_NOTAFFECTED)
+ gProtectStructs[gBankAttacker].notEffective = 1;
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk4B_return_atk_to_ball(void)
+{
+ gActiveBank = gBankAttacker;
+ if (!(gHitMarker & HITMARKER_FAINTED(gActiveBank)))
+ {
+ EmitReturnPokeToBall(0, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atk4C_copy_poke_data(void)
+{
+ if (gBattleExecBuffer)
+ return;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ gBattlePartyID[gActiveBank] = *(gBattleStruct->field_5C + gActiveBank);
+
+ EmitGetMonData(0, 0, gBitTable[gBattlePartyID[gActiveBank]]);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk4D_switch_data_update(void)
+{
+ struct BattlePokemon oldData;
+ s32 i;
+ u8 *monData;
+
+ if (gBattleExecBuffer)
+ return;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ oldData = gBattleMons[gActiveBank];
+ monData = (u8*)(&gBattleMons[gActiveBank]);
+
+ for (i = 0; i < sizeof(struct BattlePokemon); i++)
+ {
+ monData[i] = gBattleBufferB[gActiveBank][4 + i];
+ }
+
+ gBattleMons[gActiveBank].type1 = gBaseStats[gBattleMons[gActiveBank].species].type1;
+ gBattleMons[gActiveBank].type2 = gBaseStats[gBattleMons[gActiveBank].species].type2;
+ gBattleMons[gActiveBank].ability = GetAbilityBySpecies(gBattleMons[gActiveBank].species, gBattleMons[gActiveBank].altAbility);
+
+ // check knocked off item
+ i = GetBankSide(gActiveBank);
+ if (gWishFutureKnock.knockedOffPokes[i] & gBitTable[gBattlePartyID[gActiveBank]])
+ {
+ gBattleMons[gActiveBank].item = 0;
+ }
+
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_BATON_PASS)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ gBattleMons[gActiveBank].statStages[i] = oldData.statStages[i];
+ }
+ gBattleMons[gActiveBank].status2 = oldData.status2;
+ }
+
+ SwitchInClearStructs();
+
+ if (gBattleTypeFlags & BATTLE_TYPE_PALACE && gBattleMons[gActiveBank].maxHP / 2 >= gBattleMons[gActiveBank].hp
+ && gBattleMons[gActiveBank].hp != 0 && !(gBattleMons[gActiveBank].status1 & STATUS_SLEEP))
+ {
+ gBattleStruct->field_92 |= gBitTable[gActiveBank];
+ }
+
+ gBattleScripting.bank = gActiveBank;
+ gBattleTextBuff1[0] = PLACEHOLDER_BEGIN;
+ gBattleTextBuff1[1] = 7;
+ gBattleTextBuff1[2] = gActiveBank;
+ gBattleTextBuff1[3] = gBattlePartyID[gActiveBank];
+ gBattleTextBuff1[4] = EOS;
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk4E_switchin_anim(void)
+{
+ if (gBattleExecBuffer)
+ return;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ if (GetBankSide(gActiveBank) == SIDE_OPPONENT
+ && !(gBattleTypeFlags & (BATTLE_TYPE_LINK
+ | BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_x2000000
+ | BATTLE_TYPE_x4000000
+ | BATTLE_TYPE_FRONTIER)))
+ HandleSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gActiveBank].species), FLAG_SET_SEEN, gBattleMons[gActiveBank].personality);
+
+ gAbsentBankFlags &= ~(gBitTable[gActiveBank]);
+
+ EmitSwitchInAnim(0, gBattlePartyID[gActiveBank], gBattlescriptCurrInstr[2]);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 3;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
+ sub_81A56B4();
+}
+
+static void atk4F_jump_if_cannot_switch(void)
+{
+ s32 val = 0;
+ s32 compareVar = 0;
+ struct Pokemon *party = NULL;
+ s32 r7 = 0;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1] & ~(ATK4F_DONT_CHECK_STATUSES));
+
+ if (!(gBattlescriptCurrInstr[1] & ATK4F_DONT_CHECK_STATUSES)
+ && ((gBattleMons[gActiveBank].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
+ || (gStatuses3[gActiveBank] & STATUS3_ROOTED)))
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
+ {
+ #ifndef NONMATCHING
+ asm("":::"r5");
+ #endif // NONMATCHING
+ if (GetBankSide(gActiveBank) == SIDE_OPPONENT)
+ party = gEnemyParty;
+ else
+ party = gPlayerParty;
+
+ val = 0;
+ if (2 & gActiveBank)
+ val = 3;
+
+ for (compareVar = val + 3; val < compareVar; val++)
+ {
+ if (GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE
+ && !GetMonData(&party[val], MON_DATA_IS_EGG)
+ && GetMonData(&party[val], MON_DATA_HP) != 0
+ && gBattlePartyID[gActiveBank] != val)
+ break;
+ }
+
+ if (val == compareVar)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ else
+ gBattlescriptCurrInstr += 6;
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_x800000)
+ {
+ if (GetBankSide(gActiveBank) == SIDE_PLAYER)
+ {
+ party = gPlayerParty;
+
+ val = 0;
+ if (sub_806D82C(sub_806D864(gActiveBank)) == TRUE)
+ val = 3;
+ }
+ else
+ {
+ party = gEnemyParty;
+
+ if (gActiveBank == 1)
+ val = 0;
+ else
+ val = 3;
+ }
+ }
+ else
+ {
+ if (GetBankSide(gActiveBank) == SIDE_OPPONENT)
+ party = gEnemyParty;
+ else
+ party = gPlayerParty;
+
+
+ val = 0;
+ if (sub_806D82C(sub_806D864(gActiveBank)) == TRUE)
+ val = 3;
+ }
+
+ for (compareVar = val + 3; val < compareVar; val++)
+ {
+ if (GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE
+ && !GetMonData(&party[val], MON_DATA_IS_EGG)
+ && GetMonData(&party[val], MON_DATA_HP) != 0
+ && gBattlePartyID[gActiveBank] != val)
+ break;
+ }
+
+ if (val == compareVar)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ else
+ gBattlescriptCurrInstr += 6;
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS && GetBankSide(gActiveBank) == SIDE_OPPONENT)
+ {
+ party = gEnemyParty;
+
+ val = 0;
+ if (gActiveBank == 3)
+ val = 3;
+
+ for (compareVar = val + 3; val < compareVar; val++)
+ {
+ if (GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE
+ && !GetMonData(&party[val], MON_DATA_IS_EGG)
+ && GetMonData(&party[val], MON_DATA_HP) != 0
+ && gBattlePartyID[gActiveBank] != val)
+ break;
+ }
+
+ if (val == compareVar)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ else
+ gBattlescriptCurrInstr += 6;
+ }
+ else
+ {
+ if (GetBankSide(gActiveBank) == SIDE_OPPONENT)
+ {
+ r7 = GetBankByIdentity(1);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ compareVar = GetBankByIdentity(3);
+ else
+ compareVar = r7;
+
+ party = gEnemyParty;
+ }
+ else
+ {
+ r7 = GetBankByIdentity(0);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ compareVar = GetBankByIdentity(2);
+ else
+ compareVar = r7;
+
+ party = gPlayerParty;
+ }
+ for (val = 0; val < 6; val++)
+ {
+ if (GetMonData(&party[val], MON_DATA_HP) != 0
+ && GetMonData(&party[val], MON_DATA_SPECIES) != SPECIES_NONE
+ && !GetMonData(&party[val], MON_DATA_IS_EGG)
+ && val != gBattlePartyID[r7] && val != gBattlePartyID[compareVar])
+ break;
+ }
+
+ if (val == 6)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ else
+ gBattlescriptCurrInstr += 6;
+ }
+}
+
+static void sub_804CF10(u8 arg0)
+{
+ *(gBattleStruct->field_58 + gActiveBank) = gBattlePartyID[gActiveBank];
+ *(gBattleStruct->field_5C + gActiveBank) = 6;
+ gBattleStruct->field_93 &= ~(gBitTable[gActiveBank]);
+
+ EmitChoosePokemon(0, 1, arg0, 0, gBattleStruct->field_60[gActiveBank]);
+ MarkBufferBankForExecution(gActiveBank);
+}
+
+static void atk50_openpartyscreen(void)
+{
+ u32 flags;
+ u8 hitmarkerFaintBits;
+ u8 bank;
+ const u8 *jumpPtr;
+
+ bank = 0;
+ flags = 0;
+ jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+
+ if (gBattlescriptCurrInstr[1] == 5)
+ {
+ if ((gBattleTypeFlags & (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_MULTI)) != BATTLE_TYPE_DOUBLE)
+ {
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (gHitMarker & HITMARKER_FAINTED(gActiveBank))
+ {
+ if (sub_80423F4(gActiveBank, 6, 6))
+ {
+ gAbsentBankFlags |= gBitTable[gActiveBank];
+ gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
+ EmitLinkStandbyMsg(0, 2, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ else if (!gSpecialStatuses[gActiveBank].flag40)
+ {
+ sub_804CF10(6);
+ gSpecialStatuses[gActiveBank].flag40 = 1;
+ }
+ }
+ else
+ {
+ EmitLinkStandbyMsg(0, 2, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ {
+ u8 flag40_0, flag40_1, flag40_2, flag40_3;
+
+ hitmarkerFaintBits = gHitMarker >> 0x1C;
+
+ if (gBitTable[0] & hitmarkerFaintBits)
+ {
+ gActiveBank = 0;
+ if (sub_80423F4(0, 6, 6))
+ {
+ gAbsentBankFlags |= gBitTable[gActiveBank];
+ gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
+ Emit_x2A(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ else if (!gSpecialStatuses[gActiveBank].flag40)
+ {
+ sub_804CF10(gBattleStruct->field_5C[2]);
+ gSpecialStatuses[gActiveBank].flag40 = 1;
+ }
+ else
+ {
+ EmitLinkStandbyMsg(0, 2, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ flags |= 1;
+ }
+ }
+ if (gBitTable[2] & hitmarkerFaintBits && !(gBitTable[0] & hitmarkerFaintBits))
+ {
+ gActiveBank = 2;
+ if (sub_80423F4(2, 6, 6))
+ {
+ gAbsentBankFlags |= gBitTable[gActiveBank];
+ gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
+ Emit_x2A(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ else if (!gSpecialStatuses[gActiveBank].flag40)
+ {
+ sub_804CF10(gBattleStruct->field_5C[0]);
+ gSpecialStatuses[gActiveBank].flag40 = 1;
+ }
+ else if (!(flags & 1))
+ {
+ EmitLinkStandbyMsg(0, 2, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+ if (gBitTable[1] & hitmarkerFaintBits)
+ {
+ gActiveBank = 1;
+ if (sub_80423F4(1, 6, 6))
+ {
+ gAbsentBankFlags |= gBitTable[gActiveBank];
+ gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
+ Emit_x2A(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ else if (!gSpecialStatuses[gActiveBank].flag40)
+ {
+ sub_804CF10(gBattleStruct->field_5C[3]);
+ gSpecialStatuses[gActiveBank].flag40 = 1;
+ }
+ else
+ {
+ EmitLinkStandbyMsg(0, 2, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ flags |= 2;
+ }
+ }
+ if (gBitTable[3] & hitmarkerFaintBits && !(gBitTable[1] & hitmarkerFaintBits))
+ {
+ gActiveBank = 3;
+ if (sub_80423F4(3, 6, 6))
+ {
+ gAbsentBankFlags |= gBitTable[gActiveBank];
+ gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
+ Emit_x2A(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ else if (!gSpecialStatuses[gActiveBank].flag40)
+ {
+ sub_804CF10(gBattleStruct->field_5C[1]);
+ gSpecialStatuses[gActiveBank].flag40 = 1;
+ }
+ else if (!(flags & 2))
+ {
+ EmitLinkStandbyMsg(0, 2, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+
+ flag40_0 = gSpecialStatuses[0].flag40;
+ if (!flag40_0)
+ {
+ flag40_2 = gSpecialStatuses[2].flag40;
+ if (!flag40_2 && hitmarkerFaintBits != 0)
+ {
+ if (gAbsentBankFlags & gBitTable[0])
+ gActiveBank = 2;
+ else
+ gActiveBank = 0;
+
+ EmitLinkStandbyMsg(0, 2, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+
+ }
+ flag40_1 = gSpecialStatuses[1].flag40;
+ if (!flag40_1)
+ {
+ flag40_3 = gSpecialStatuses[3].flag40;
+ if (!flag40_3 && hitmarkerFaintBits != 0)
+ {
+ if (gAbsentBankFlags & gBitTable[1])
+ gActiveBank = 3;
+ else
+ gActiveBank = 1;
+
+ EmitLinkStandbyMsg(0, 2, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+ }
+ gBattlescriptCurrInstr += 6;
+ }
+ else if (gBattlescriptCurrInstr[1] == 6)
+ {
+ if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ {
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ {
+ hitmarkerFaintBits = gHitMarker >> 0x1C;
+ if (gBitTable[2] & hitmarkerFaintBits && gBitTable[0] & hitmarkerFaintBits)
+ {
+ gActiveBank = 2;
+ if (sub_80423F4(2, gBattleBufferB[0][1], 6))
+ {
+ gAbsentBankFlags |= gBitTable[gActiveBank];
+ gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
+ Emit_x2A(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ else if (!gSpecialStatuses[gActiveBank].flag40)
+ {
+ sub_804CF10(gBattleStruct->field_5C[0]);
+ gSpecialStatuses[gActiveBank].flag40 = 1;
+ }
+ }
+ if (gBitTable[3] & hitmarkerFaintBits && hitmarkerFaintBits & gBitTable[1])
+ {
+ gActiveBank = 3;
+ if (sub_80423F4(3, gBattleBufferB[1][1], 6))
+ {
+ gAbsentBankFlags |= gBitTable[gActiveBank];
+ gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
+ Emit_x2A(0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ else if (!gSpecialStatuses[gActiveBank].flag40)
+ {
+ sub_804CF10(gBattleStruct->field_5C[1]);
+ gSpecialStatuses[gActiveBank].flag40 = 1;
+ }
+ }
+ gBattlescriptCurrInstr += 6;
+ }
+ else
+ {
+ gBattlescriptCurrInstr += 6;
+ }
+ }
+ else
+ {
+ gBattlescriptCurrInstr += 6;
+ }
+
+ hitmarkerFaintBits = gHitMarker >> 0x1C;
+
+ gBank1 = 0;
+ while (1)
+ {
+ if (gBitTable[gBank1] & hitmarkerFaintBits)
+ break;
+ if (gBank1 >= gNoOfAllBanks)
+ break;
+ gBank1++;
+ }
+
+ if (gBank1 == gNoOfAllBanks)
+ gBattlescriptCurrInstr = jumpPtr;
+ }
+ else
+ {
+ if (gBattlescriptCurrInstr[1] & 0x80)
+ hitmarkerFaintBits = 0; // used here as the caseId for the EmitChoose function
+ else
+ hitmarkerFaintBits = 1;
+
+ bank = GetBattleBank(gBattlescriptCurrInstr[1] & ~(0x80));
+ if (gSpecialStatuses[bank].flag40)
+ {
+ gBattlescriptCurrInstr += 6;
+ }
+ else if (sub_80423F4(bank, 6, 6))
+ {
+ gActiveBank = bank;
+ gAbsentBankFlags |= gBitTable[gActiveBank];
+ gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
+ gBattlescriptCurrInstr = jumpPtr;
+ }
+ else
+ {
+ gActiveBank = bank;
+ *(gBattleStruct->field_58 + gActiveBank) = gBattlePartyID[gActiveBank];
+ *(gBattleStruct->field_5C + gActiveBank) = 6;
+ gBattleStruct->field_93 &= ~(gBitTable[gActiveBank]);
+
+ EmitChoosePokemon(0, hitmarkerFaintBits, *(gBattleStruct->field_5C + (gActiveBank ^ 2)), 0, gBattleStruct->field_60[gActiveBank]);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 6;
+
+ if (GetBankIdentity(gActiveBank) == 0 && gBattleResults.playerSwitchesCounter < 0xFF)
+ gBattleResults.playerSwitchesCounter++;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ {
+ for (gActiveBank = 0; gActiveBank < gNoOfAllBanks; gActiveBank++)
+ {
+ if (gActiveBank != bank)
+ {
+ EmitLinkStandbyMsg(0, 2, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+ }
+ else
+ {
+ gActiveBank = GetBankByIdentity(GetBankIdentity(bank) ^ BIT_SIDE);
+ if (gAbsentBankFlags & gBitTable[gActiveBank])
+ gActiveBank ^= BIT_MON;
+
+ EmitLinkStandbyMsg(0, 2, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+ }
+}
+
+static void atk51_switch_handle_order(void)
+{
+ s32 i;
+ if (gBattleExecBuffer)
+ return;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ switch (gBattlescriptCurrInstr[2])
+ {
+ case 0:
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gBattleBufferB[i][0] == 0x22)
+ {
+ *(gBattleStruct->field_5C + i) = gBattleBufferB[i][1];
+ if (!(gBattleStruct->field_93 & gBitTable[i]))
+ {
+ RecordedBattle_SetBankAction(i, gBattleBufferB[i][1]);
+ gBattleStruct->field_93 |= gBitTable[i];
+ }
+ }
+ }
+ break;
+ case 1:
+ if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ sub_803BDA0(gActiveBank);
+ break;
+ case 2:
+ if (!(gBattleStruct->field_93 & gBitTable[gActiveBank]))
+ {
+ RecordedBattle_SetBankAction(gActiveBank, gBattleBufferB[gActiveBank][1]);
+ gBattleStruct->field_93 |= gBitTable[gActiveBank];
+ }
+ // fall through
+ case 3:
+ gBattleCommunication[0] = gBattleBufferB[gActiveBank][1];
+ *(gBattleStruct->field_5C + gActiveBank) = gBattleBufferB[gActiveBank][1];
+
+ if ((gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_LINK)) == (BATTLE_TYPE_MULTI | BATTLE_TYPE_LINK))
+ {
+ *(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 0) &= 0xF;
+ *(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBank][2] & 0xF0);
+ *(gActiveBank * 3 + (u8*)(gBattleStruct->field_60) + 1) = gBattleBufferB[gActiveBank][3];
+
+ *((gActiveBank ^ 2) * 3 + (u8*)(gBattleStruct->field_60) + 0) &= (0xF0);
+ *((gActiveBank ^ 2) * 3 + (u8*)(gBattleStruct->field_60) + 0) |= (gBattleBufferB[gActiveBank][2] & 0xF0) >> 4;
+ *((gActiveBank ^ 2) * 3 + (u8*)(gBattleStruct->field_60) + 2) = gBattleBufferB[gActiveBank][3];
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
+ {
+ sub_80571DC(gActiveBank, *(gBattleStruct->field_5C + gActiveBank));
+ }
+ else
+ {
+ sub_803BDA0(gActiveBank);
+ }
+
+ PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBankAttacker].species)
+ PREPARE_MON_NICK_BUFFER(gBattleTextBuff2, gActiveBank, gBattleBufferB[gActiveBank][1])
+
+ break;
+ }
+
+ gBattlescriptCurrInstr += 3;
+}
+
+static void atk52_switch_in_effects(void)
+{
+ s32 i;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ sub_803FA70(gActiveBank);
+
+ gHitMarker &= ~(HITMARKER_FAINTED(gActiveBank));
+ gSpecialStatuses[gActiveBank].flag40 = 0;
+
+ if (!(gSideAffecting[GetBankSide(gActiveBank)] & SIDE_STATUS_SPIKES_DAMAGED)
+ && (gSideAffecting[GetBankSide(gActiveBank)] & SIDE_STATUS_SPIKES)
+ && gBattleMons[gActiveBank].type1 != TYPE_FLYING
+ && gBattleMons[gActiveBank].type2 != TYPE_FLYING
+ && gBattleMons[gActiveBank].ability != ABILITY_LEVITATE)
+ {
+ u8 spikesDmg;
+
+ gSideAffecting[GetBankSide(gActiveBank)] |= SIDE_STATUS_SPIKES_DAMAGED;
+
+ gBattleMons[gActiveBank].status2 &= ~(STATUS2_DESTINY_BOND);
+ gHitMarker &= ~(HITMARKER_DESTINYBOND);
+
+ spikesDmg = (5 - gSideTimers[GetBankSide(gActiveBank)].spikesAmount) * 2;
+ gBattleMoveDamage = gBattleMons[gActiveBank].maxHP / (spikesDmg);
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+
+ gBattleScripting.bank = gActiveBank;
+ BattleScriptPushCursor();
+
+ if (gBattlescriptCurrInstr[1] == 0)
+ gBattlescriptCurrInstr = gUnknown_082DAE90;
+ else if (gBattlescriptCurrInstr[1] == 1)
+ gBattlescriptCurrInstr = gUnknown_082DAE59;
+ else
+ gBattlescriptCurrInstr = gUnknown_082DAEC7;
+ }
+ else
+ {
+ if (gBattleMons[gActiveBank].ability == ABILITY_TRUANT && !gDisableStructs[gActiveBank].truantUnknownBit)
+ gDisableStructs[gActiveBank].truantCounter = 1;
+
+ gDisableStructs[gActiveBank].truantUnknownBit = 0;
+
+ if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gActiveBank, 0, 0, 0) == 0 &&
+ ItemBattleEffects(0, gActiveBank, 0) == 0)
+ {
+ gSideAffecting[GetBankSide(gActiveBank)] &= ~(SIDE_STATUS_SPIKES_DAMAGED);
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gTurnOrder[i] == gActiveBank)
+ gUnknown_0202407A[i] = 0xC;
+ }
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ u16* hpOnSwitchout = &gBattleStruct->hpOnSwitchout[GetBankSide(i)];
+ *hpOnSwitchout = gBattleMons[i].hp;
+ }
+
+ if (gBattlescriptCurrInstr[1] == 5)
+ {
+ u32 hitmarkerFaintBits = gHitMarker >> 0x1C;
+
+ gBank1++;
+ while (1)
+ {
+ if (hitmarkerFaintBits & gBitTable[gBank1] && !(gAbsentBankFlags & gBitTable[gBank1]))
+ break;
+ if (gBank1 >= gNoOfAllBanks)
+ break;
+ gBank1++;
+ }
+ }
+ gBattlescriptCurrInstr += 2;
+ }
+ }
+}
+
+static void atk53_trainer_slide(void)
+{
+ gActiveBank = GetBankByIdentity(gBattlescriptCurrInstr[1]);
+ EmitTrainerSlide(0);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk54_effectiveness_sound(void)
+{
+ gActiveBank = gBankAttacker;
+ EmitEffectivenessSound(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1));
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 3;
+}
+
+static void atk55_play_sound(void)
+{
+ gActiveBank = gBankAttacker;
+ EmitPlaySound(0, BS2ScriptRead16(gBattlescriptCurrInstr + 1), 0);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 3;
+}
+
+static void atk56_fainting_cry(void)
+{
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ EmitFaintingCry(0);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk57(void)
+{
+ gActiveBank = GetBankByIdentity(0);
+ Emit_x37(0, gBattleOutcome);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 1;
+}
+
+static void atk58_return_to_ball(void)
+{
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ EmitReturnPokeToBall(0, 1);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk59_learnmove_inbattle(void)
+{
+ const u8* jumpPtr1 = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ const u8* jumpPtr2 = BSScriptReadPtr(gBattlescriptCurrInstr + 5);
+
+ u16 ret = MonTryLearningNewMove(&gPlayerParty[gBattleStruct->expGetterId], gBattlescriptCurrInstr[9]);
+ while (ret == 0xFFFE)
+ ret = MonTryLearningNewMove(&gPlayerParty[gBattleStruct->expGetterId], 0);
+
+ if (ret == 0)
+ {
+ gBattlescriptCurrInstr = jumpPtr2;
+ }
+ else if (ret == 0xFFFF)
+ {
+ gBattlescriptCurrInstr += 10;
+ }
+ else
+ {
+ gActiveBank = GetBankByIdentity(0);
+
+ if (gBattlePartyID[gActiveBank] == gBattleStruct->expGetterId
+ && !(gBattleMons[gActiveBank].status2 & STATUS2_TRANSFORMED))
+ {
+ GiveMoveToBattleMon(&gBattleMons[gActiveBank], ret);
+ }
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ {
+ gActiveBank = GetBankByIdentity(2);
+ if (gBattlePartyID[gActiveBank] == gBattleStruct->expGetterId
+ && !(gBattleMons[gActiveBank].status2 & STATUS2_TRANSFORMED))
+ {
+ GiveMoveToBattleMon(&gBattleMons[gActiveBank], ret);
+ }
+ }
+
+ gBattlescriptCurrInstr = jumpPtr1;
+ }
+}
+
+static void atk5A_yesnoboxlearnmove(void)
+{
+ gActiveBank = 0;
+
+ switch (gBattleScripting.learnMoveState)
+ {
+ case 0:
+ sub_8056A3C(0x18, 8, 0x1D, 0xD, 0);
+ sub_814F9EC(gText_BattleYesNoChoice, 0xC);
+ gBattleScripting.learnMoveState++;
+ gBattleCommunication[CURSOR_POSITION] = 0;
+ BattleCreateCursorAt(0);
+ break;
+ case 1:
+ if (gMain.newKeys & DPAD_UP && gBattleCommunication[CURSOR_POSITION] != 0)
+ {
+ PlaySE(SE_SELECT);
+ BattleDestroyCursorAt(gBattleCommunication[CURSOR_POSITION]);
+ gBattleCommunication[CURSOR_POSITION] = 0;
+ BattleCreateCursorAt(0);
+ }
+ if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[CURSOR_POSITION] == 0)
+ {
+ PlaySE(SE_SELECT);
+ BattleDestroyCursorAt(gBattleCommunication[CURSOR_POSITION]);
+ gBattleCommunication[CURSOR_POSITION] = 1;
+ BattleCreateCursorAt(1);
+ }
+ if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ if (gBattleCommunication[1] == 0)
+ {
+ sub_8056A3C(0x18, 0x8, 0x1D, 0xD, 1);
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gBattleScripting.learnMoveState++;
+ }
+ else
+ {
+ gBattleScripting.learnMoveState = 5;
+ }
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ gBattleScripting.learnMoveState = 5;
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ FreeAllWindowBuffers();
+ sub_81BFA38(gPlayerParty, gBattleStruct->expGetterId, gPlayerPartyCount - 1, ReshowBattleScreenAfterMenu, gMoveToLearn);
+ gBattleScripting.learnMoveState++;
+ }
+ break;
+ case 3:
+ if (!gPaletteFade.active && gMain.callback2 == BattleMainCB2)
+ {
+ gBattleScripting.learnMoveState++;
+ }
+ break;
+ case 4:
+ if (!gPaletteFade.active && gMain.callback2 == BattleMainCB2)
+ {
+ u8 movePosition = sub_81C1B94();
+ if (movePosition == 4)
+ {
+ gBattleScripting.learnMoveState = 5;
+ }
+ else
+ {
+ u16 moveId = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_MOVE1 + movePosition);
+ if (IsHMMove2(moveId))
+ {
+ PrepareStringBattle(0x13F, gActiveBank);
+ gBattleScripting.learnMoveState = 6;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+
+ PREPARE_MOVE_BUFFER(gBattleTextBuff2, moveId)
+
+ RemoveMonPPBonus(&gPlayerParty[gBattleStruct->expGetterId], movePosition);
+ SetMonMoveSlot(&gPlayerParty[gBattleStruct->expGetterId], gMoveToLearn, movePosition);
+
+ if (gBattlePartyID[0] == gBattleStruct->expGetterId
+ && !(gBattleMons[0].status2 & STATUS2_TRANSFORMED)
+ && !(gDisableStructs[0].unk18_b & gBitTable[movePosition]))
+ {
+ RemoveBattleMonPPBonus(&gBattleMons[0], movePosition);
+ SetBattleMonMoveSlot(&gBattleMons[0], gMoveToLearn, movePosition);
+ }
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
+ && gBattlePartyID[2] == gBattleStruct->expGetterId
+ && !(gBattleMons[2].status2 & STATUS2_TRANSFORMED)
+ && !(gDisableStructs[2].unk18_b & gBitTable[movePosition]))
+ {
+ RemoveBattleMonPPBonus(&gBattleMons[2], movePosition);
+ SetBattleMonMoveSlot(&gBattleMons[2], gMoveToLearn, movePosition);
+ }
+ }
+ }
+ }
+ break;
+ case 5:
+ sub_8056A3C(0x18, 8, 0x1D, 0xD, 1);
+ gBattlescriptCurrInstr += 5;
+ break;
+ case 6:
+ if (gBattleExecBuffer == 0)
+ {
+ gBattleScripting.learnMoveState = 2;
+ }
+ break;
+ }
+}
+
+static void atk5B_yesnoboxstoplearningmove(void)
+{
+ switch (gBattleScripting.learnMoveState)
+ {
+ case 0:
+ sub_8056A3C(0x18, 8, 0x1D, 0xD, 0);
+ sub_814F9EC(gText_BattleYesNoChoice, 0xC);
+ gBattleScripting.learnMoveState++;
+ gBattleCommunication[CURSOR_POSITION] = 0;
+ BattleCreateCursorAt(0);
+ break;
+ case 1:
+ if (gMain.newKeys & DPAD_UP && gBattleCommunication[CURSOR_POSITION] != 0)
+ {
+ PlaySE(SE_SELECT);
+ BattleDestroyCursorAt(gBattleCommunication[CURSOR_POSITION]);
+ gBattleCommunication[CURSOR_POSITION] = 0;
+ BattleCreateCursorAt(0);
+ }
+ if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[CURSOR_POSITION] == 0)
+ {
+ PlaySE(SE_SELECT);
+ BattleDestroyCursorAt(gBattleCommunication[CURSOR_POSITION]);
+ gBattleCommunication[CURSOR_POSITION] = 1;
+ BattleCreateCursorAt(1);
+ }
+ if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+
+ if (gBattleCommunication[1] != 0)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ else
+ gBattlescriptCurrInstr += 5;
+
+ sub_8056A3C(0x18, 0x8, 0x1D, 0xD, 1);
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ sub_8056A3C(0x18, 0x8, 0x1D, 0xD, 1);
+ }
+ break;
+ }
+}
+
+static void atk5C_hitanimation(void)
+{
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ if (gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ {
+ gBattlescriptCurrInstr += 2;
+ }
+ else if (!(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE) || !(gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE) || gDisableStructs[gActiveBank].substituteHP == 0)
+ {
+ EmitHitAnimation(0);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 2;
+ }
+ else
+ {
+ gBattlescriptCurrInstr += 2;
+ }
+}
+
+static u32 GetTrainerMoneyToGive(u16 trainerId)
+{
+ u32 i = 0;
+ u32 lastMonLevel = 0;
+ u32 moneyReward = 0;
+
+ if (trainerId == SECRET_BASE_OPPONENT)
+ {
+ moneyReward = 20 * gBattleResources->secretBase->partyLevels[0] * gBattleStruct->moneyMultiplier;
+ }
+ else
+ {
+ switch (gTrainers[trainerId].partyFlags)
+ {
+ case 0:
+ {
+ const struct TrainerMonNoItemDefaultMoves *party = gTrainers[trainerId].party.NoItemDefaultMoves;
+ lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
+ }
+ break;
+ case PARTY_FLAG_CUSTOM_MOVES:
+ {
+ const struct TrainerMonNoItemCustomMoves *party = gTrainers[trainerId].party.NoItemCustomMoves;
+ lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
+ }
+ break;
+ case PARTY_FLAG_HAS_ITEM:
+ {
+ const struct TrainerMonItemDefaultMoves *party = gTrainers[trainerId].party.ItemDefaultMoves;
+ lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
+ }
+ break;
+ case PARTY_FLAG_CUSTOM_MOVES | PARTY_FLAG_HAS_ITEM:
+ {
+ const struct TrainerMonItemCustomMoves *party = gTrainers[trainerId].party.ItemCustomMoves;
+ lastMonLevel = party[gTrainers[trainerId].partySize - 1].lvl;
+ }
+ break;
+ }
+
+ for (; gTrainerMoneyTable[i].classId != 0xFF; i++)
+ {
+ if (gTrainerMoneyTable[i].classId == gTrainers[trainerId].trainerClass)
+ break;
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
+ moneyReward = 4 * lastMonLevel * gBattleStruct->moneyMultiplier * gTrainerMoneyTable[i].value;
+ else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ moneyReward = 4 * lastMonLevel * gBattleStruct->moneyMultiplier * 2 * gTrainerMoneyTable[i].value;
+ else
+ moneyReward = 4 * lastMonLevel * gBattleStruct->moneyMultiplier * gTrainerMoneyTable[i].value;
+ }
+
+ return moneyReward;
+}
+
+static void atk5D_getmoneyreward(void)
+{
+ u32 moneyReward = GetTrainerMoneyToGive(gTrainerBattleOpponent_A);
+ if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
+ moneyReward += GetTrainerMoneyToGive(gTrainerBattleOpponent_B);
+
+ AddMoney(&gSaveBlock1Ptr->money, moneyReward);
+
+ PREPARE_WORD_NUMBER_BUFFER(gBattleTextBuff1, 5, moneyReward)
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk5E_8025A70(void)
+{
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ switch (gBattleCommunication[0])
+ {
+ case 0:
+ EmitGetMonData(0, REQUEST_ALL_BATTLE, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattleCommunication[0]++;
+ break;
+ case 1:
+ if (gBattleExecBuffer == 0)
+ {
+ s32 i;
+ struct BattlePokemon* bufferPoke = (struct BattlePokemon*) &gBattleBufferB[gActiveBank][4];
+ for (i = 0; i < 4; i++)
+ {
+ gBattleMons[gActiveBank].moves[i] = bufferPoke->moves[i];
+ gBattleMons[gActiveBank].pp[i] = bufferPoke->pp[i];
+ }
+ gBattlescriptCurrInstr += 2;
+ }
+ break;
+ }
+}
+
+static void atk5F_8025B24(void)
+{
+ gActiveBank = gBankAttacker;
+ gBankAttacker = gBankTarget;
+ gBankTarget = gActiveBank;
+
+ if (gHitMarker & HITMARKER_PURSUIT_TRAP)
+ gHitMarker &= ~(HITMARKER_PURSUIT_TRAP);
+ else
+ gHitMarker |= HITMARKER_PURSUIT_TRAP;
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk60_increment_gamestat(void)
+{
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ IncrementGameStat(gBattlescriptCurrInstr[1]);
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk61_8025BA4(void)
+{
+ s32 i;
+ struct Pokemon* party;
+ struct HpAndStatus hpStatuses[6];
+
+ if (gBattleExecBuffer)
+ return;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ if (GetBankSide(gActiveBank) == SIDE_PLAYER)
+ party = gPlayerParty;
+ else
+ party = gEnemyParty;
+
+ for (i = 0; i < 6; i++)
+ {
+ if (GetMonData(&party[i], MON_DATA_SPECIES2) == SPECIES_NONE
+ || GetMonData(&party[i], MON_DATA_SPECIES2) == SPECIES_EGG)
+ {
+ hpStatuses[i].hp = 0xFFFF;
+ hpStatuses[i].status = 0;
+ }
+ else
+ {
+ hpStatuses[i].hp = GetMonData(&party[i], MON_DATA_HP);
+ hpStatuses[i].status = GetMonData(&party[i], MON_DATA_STATUS);
+ }
+ }
+
+ EmitCmd48(0, hpStatuses, 1);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk62_08025C6C(void)
+{
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ EmitCmd49(0);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk63_jumptorandomattack(void)
+{
+ if (gBattlescriptCurrInstr[1] != 0)
+ gCurrentMove = gRandomMove;
+ else
+ gLastUsedMove = gCurrentMove = gRandomMove;
+
+ gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
+}
+
+static void atk64_statusanimation(void)
+{
+ if (gBattleExecBuffer == 0)
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ if (!(gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE)
+ && gDisableStructs[gActiveBank].substituteHP == 0
+ && !(gHitMarker & HITMARKER_NO_ANIMATIONS))
+ {
+ EmitStatusAnimation(0, FALSE, gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ gBattlescriptCurrInstr += 2;
+ }
+}
+
+static void atk65_status2animation(void)
+{
+ u32 wantedToAnimate;
+
+ if (gBattleExecBuffer == 0)
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ wantedToAnimate = BSScriptRead32(gBattlescriptCurrInstr + 2);
+ if (!(gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE)
+ && gDisableStructs[gActiveBank].substituteHP == 0
+ && !(gHitMarker & HITMARKER_NO_ANIMATIONS))
+ {
+ EmitStatusAnimation(0, TRUE, gBattleMons[gActiveBank].status2 & wantedToAnimate);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ gBattlescriptCurrInstr += 6;
+ }
+}
+
+static void atk66_chosenstatusanimation(void)
+{
+ u32 wantedStatus;
+
+ if (gBattleExecBuffer == 0)
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ wantedStatus = BSScriptRead32(gBattlescriptCurrInstr + 3);
+ if (!(gStatuses3[gActiveBank] & STATUS3_SEMI_INVULNERABLE)
+ && gDisableStructs[gActiveBank].substituteHP == 0
+ && !(gHitMarker & HITMARKER_NO_ANIMATIONS))
+ {
+ EmitStatusAnimation(0, gBattlescriptCurrInstr[2], wantedStatus);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ gBattlescriptCurrInstr += 7;
+ }
+}
+
+static void atk67_yesnobox(void)
+{
+ switch (gBattleCommunication[0])
+ {
+ case 0:
+ sub_8056A3C(0x18, 8, 0x1D, 0xD, 0);
+ sub_814F9EC(gText_BattleYesNoChoice, 0xC);
+ gBattleCommunication[0]++;
+ gBattleCommunication[CURSOR_POSITION] = 0;
+ BattleCreateCursorAt(0);
+ break;
+ case 1:
+ if (gMain.newKeys & DPAD_UP && gBattleCommunication[CURSOR_POSITION] != 0)
+ {
+ PlaySE(SE_SELECT);
+ BattleDestroyCursorAt(gBattleCommunication[CURSOR_POSITION]);
+ gBattleCommunication[CURSOR_POSITION] = 0;
+ BattleCreateCursorAt(0);
+ }
+ if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[CURSOR_POSITION] == 0)
+ {
+ PlaySE(SE_SELECT);
+ BattleDestroyCursorAt(gBattleCommunication[CURSOR_POSITION]);
+ gBattleCommunication[CURSOR_POSITION] = 1;
+ BattleCreateCursorAt(1);
+ }
+ if (gMain.newKeys & B_BUTTON)
+ {
+ gBattleCommunication[CURSOR_POSITION] = 1;
+ PlaySE(SE_SELECT);
+ sub_8056A3C(0x18, 8, 0x1D, 0xD, 1);
+ gBattlescriptCurrInstr++;
+ }
+ else if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ sub_8056A3C(0x18, 8, 0x1D, 0xD, 1);
+ gBattlescriptCurrInstr++;
+ }
+ break;
+ }
+}
+
+static void atk68_80246A0(void)
+{
+ s32 i;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ gUnknown_0202407A[i] = 0xC;
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk69_dmg_adjustment3(void) // The same as 0x7, except there's no random damage multiplier.
+{
+ u8 holdEffect, quality;
+
+ if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[gBankTarget].holdEffect, quality = gEnigmaBerries[gBankTarget].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
+ quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
+ }
+
+ gStringBank = gBankTarget;
+
+ if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < quality)
+ {
+ RecordItemEffectBattle(gBankTarget, holdEffect);
+ gSpecialStatuses[gBankTarget].focusBanded = 1;
+ }
+ if (gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE)
+ goto END;
+ if (gBattleMoves[gCurrentMove].effect != EFFECT_FALSE_SWIPE && !gProtectStructs[gBankTarget].endured
+ && !gSpecialStatuses[gBankTarget].focusBanded)
+ goto END;
+
+ if (gBattleMons[gBankTarget].hp > gBattleMoveDamage)
+ goto END;
+
+ gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1;
+
+ if (gProtectStructs[gBankTarget].endured)
+ {
+ gBattleMoveFlags |= MOVESTATUS_ENDURED;
+ }
+ else if (gSpecialStatuses[gBankTarget].focusBanded)
+ {
+ gBattleMoveFlags |= MOVESTATUS_HUNGON;
+ gLastUsedItem = gBattleMons[gBankTarget].item;
+ }
+
+ END:
+ gBattlescriptCurrInstr++;
+}
+
+static void atk6A_removeitem(void)
+{
+ u16* usedHeldItem;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ usedHeldItem = &gBattleStruct->usedHeldItems[gActiveBank];
+ *usedHeldItem = gBattleMons[gActiveBank].item;
+ gBattleMons[gActiveBank].item = 0;
+
+ EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gActiveBank].item);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk6B_atknameinbuff1(void)
+{
+ PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, gBankAttacker, gBattlePartyID[gBankAttacker])
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk6C_draw_lvlupbox(void)
+{
+ if (gBattleScripting.atk6C_state == 0)
+ {
+ if (IsMonGettingExpSentOut())
+ gBattleScripting.atk6C_state = 3;
+ else
+ gBattleScripting.atk6C_state = 1;
+ }
+
+ switch (gBattleScripting.atk6C_state)
+ {
+ case 1:
+ gBattle_BG2_Y = 0x60;
+ SetBgAttribute(2, BG_CTRL_ATTR_MOSAIC, 0);
+ ShowBg(2);
+ sub_804F17C();
+ gBattleScripting.atk6C_state = 2;
+ break;
+ case 2:
+ if (!sub_804F1CC())
+ gBattleScripting.atk6C_state = 3;
+ break;
+ case 3:
+ gBattle_BG1_X = 0;
+ gBattle_BG1_Y = 0x100;
+ SetBgAttribute(0, BG_CTRL_ATTR_MOSAIC, 1);
+ SetBgAttribute(1, BG_CTRL_ATTR_MOSAIC, 0);
+ ShowBg(0);
+ ShowBg(1);
+ sub_8056A3C(0x12, 7, 0x1D, 0x13, 0x80);
+ gBattleScripting.atk6C_state = 4;
+ break;
+ case 4:
+ sub_804F100();
+ PutWindowTilemap(13);
+ CopyWindowToVram(13, 3);
+ gBattleScripting.atk6C_state++;
+ break;
+ case 5:
+ case 7:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ gBattle_BG1_Y = 0;
+ gBattleScripting.atk6C_state++;
+ }
+ break;
+ case 6:
+ if (gMain.newKeys != 0)
+ {
+ PlaySE(SE_SELECT);
+ sub_804F144();
+ CopyWindowToVram(13, 2);
+ gBattleScripting.atk6C_state++;
+ }
+ break;
+ case 8:
+ if (gMain.newKeys != 0)
+ {
+ PlaySE(SE_SELECT);
+ sub_8056A3C(0x12, 7, 0x1D, 0x13, 0x81);
+ gBattleScripting.atk6C_state++;
+ }
+ break;
+ case 9:
+ if (!sub_804F344())
+ {
+ ClearWindowTilemap(14);
+ CopyWindowToVram(14, 1);
+
+ ClearWindowTilemap(13);
+ CopyWindowToVram(13, 1);
+
+ SetBgAttribute(2, BG_CTRL_ATTR_MOSAIC, 2);
+ ShowBg(2);
+
+ gBattleScripting.atk6C_state = 10;
+ }
+ break;
+ case 10:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ SetBgAttribute(0, BG_CTRL_ATTR_MOSAIC, 0);
+ SetBgAttribute(1, BG_CTRL_ATTR_MOSAIC, 1);
+ ShowBg(0);
+ ShowBg(1);
+ gBattlescriptCurrInstr++;
+ }
+ break;
+ }
+}
+
+static void sub_804F100(void)
+{
+ struct StatsArray currentStats;
+
+ sub_81D388C(&gPlayerParty[gBattleStruct->expGetterId], &currentStats);
+ sub_81D3640(0xD, gBattleResources->statsBeforeLvlUp, &currentStats, 0xE, 0xD, 0xF);
+}
+
+static void sub_804F144(void)
+{
+ struct StatsArray currentStats;
+
+ sub_81D388C(&gPlayerParty[gBattleStruct->expGetterId], &currentStats);
+ sub_81D3784(0xD, &currentStats, 0xE, 0xD, 0xF);
+}
+
+static void sub_804F17C(void)
+{
+ gBattle_BG2_Y = 0;
+ gBattle_BG2_X = 0x1A0;
+
+ LoadPalette(sUnknown_0831C2C8, 0x60, 0x20);
+ CopyToWindowPixelBuffer(14, sUnknown_0831C2E8, 0, 0);
+ PutWindowTilemap(14);
+ CopyWindowToVram(14, 3);
+
+ PutMonIconOnLvlUpBox();
+}
+
+static bool8 sub_804F1CC(void)
+{
+ if (IsDma3ManagerBusyWithBgCopy())
+ return TRUE;
+
+ if (gBattle_BG2_X == 0x200)
+ return FALSE;
+
+ if (gBattle_BG2_X == 0x1A0)
+ PutLevelAndGenderOnLvlUpBox();
+
+ gBattle_BG2_X += 8;
+ if (gBattle_BG2_X >= 0x200)
+ gBattle_BG2_X = 0x200;
+
+ return (gBattle_BG2_X != 0x200);
+}
+
+static void PutLevelAndGenderOnLvlUpBox(void)
+{
+ u16 monLevel;
+ u8 monGender;
+ struct TextSubPrinter subPrinter;
+ u8 *txtPtr;
+ u32 var;
+
+ monLevel = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_LEVEL);
+ monGender = GetMonGender(&gPlayerParty[gBattleStruct->expGetterId]);
+ GetMonNickname(&gPlayerParty[gBattleStruct->expGetterId], gStringVar4);
+
+ subPrinter.current_text_offset = gStringVar4;
+ subPrinter.windowId = 14;
+ subPrinter.fontId = 0;
+ subPrinter.x = 32;
+ subPrinter.y = 0;
+ subPrinter.currentX = 32;
+ subPrinter.currentY = 0;
+ subPrinter.letterSpacing = 0;
+ subPrinter.lineSpacing = 0;
+ subPrinter.fontColor_l = TEXT_COLOR_TRANSPARENT;
+ subPrinter.fontColor_h = TEXT_COLOR_WHITE;
+ subPrinter.bgColor = TEXT_COLOR_TRANSPARENT;
+ subPrinter.shadowColor = TEXT_COLOR_DARK_GREY;
+
+ AddTextPrinter(&subPrinter, 0xFF, NULL);
+
+ txtPtr = gStringVar4;
+ gStringVar4[0] = CHAR_SPECIAL_F9;
+ txtPtr++;
+ txtPtr[0] = 5;
+ txtPtr++;
+
+ var = (u32)(txtPtr);
+ txtPtr = ConvertIntToDecimalStringN(txtPtr, monLevel, STR_CONV_MODE_LEFT_ALIGN, 3);
+ var = (u32)(txtPtr) - var;
+ txtPtr = StringFill(txtPtr, 0x77, 4 - var);
+
+ if (monGender != MON_GENDERLESS)
+ {
+ if (monGender == MON_MALE)
+ {
+ txtPtr = WriteColorChangeControlCode(txtPtr, 0, 0xC);
+ txtPtr = WriteColorChangeControlCode(txtPtr, 1, 0xD);
+ *(txtPtr++) = CHAR_MALE;
+ }
+ else
+ {
+ txtPtr = WriteColorChangeControlCode(txtPtr, 0, 0xE);
+ txtPtr = WriteColorChangeControlCode(txtPtr, 1, 0xF);
+ *(txtPtr++) = CHAR_FEMALE;
+ }
+ *(txtPtr++) = EOS;
+ }
+
+ subPrinter.y = 10;
+ subPrinter.currentY = 10;
+ AddTextPrinter(&subPrinter, 0xFF, NULL);
+
+ CopyWindowToVram(14, 2);
+}
+
+static bool8 sub_804F344(void)
+{
+ if (gBattle_BG2_X == 0x1A0)
+ return FALSE;
+
+ if (gBattle_BG2_X - 16 < 0x1A0)
+ gBattle_BG2_X = 0x1A0;
+ else
+ gBattle_BG2_X -= 16;
+
+ return (gBattle_BG2_X != 0x1A0);
+}
+
+#define sDestroy data0
+#define sSavedLvlUpBoxXPosition data1
+
+static void PutMonIconOnLvlUpBox(void)
+{
+ u8 spriteId;
+ const u16* iconPal;
+ struct SpriteSheet iconSheet;
+ struct SpritePalette iconPalSheet;
+
+ u16 species = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_SPECIES);
+ u32 personality = GetMonData(&gPlayerParty[gBattleStruct->expGetterId], MON_DATA_PERSONALITY);
+
+ const u8* iconPtr = GetMonIconPtr(species, personality, 1);
+ iconSheet.data = iconPtr;
+ iconSheet.size = 0x200;
+ iconSheet.tag = MON_ICON_LVLUP_BOX_TAG;
+
+ iconPal = GetValidMonIconPalettePtr(species);
+ iconPalSheet.data = iconPal;
+ iconPalSheet.tag = MON_ICON_LVLUP_BOX_TAG;
+
+ LoadSpriteSheet(&iconSheet);
+ LoadSpritePalette(&iconPalSheet);
+
+ spriteId = CreateSprite(&sSpriteTemplate_MonIconOnLvlUpBox, 256, 10, 0);
+ gSprites[spriteId].sDestroy = FALSE;
+ gSprites[spriteId].sSavedLvlUpBoxXPosition = gBattle_BG2_X;
+}
+
+static void SpriteCB_MonIconOnLvlUpBox(struct Sprite* sprite)
+{
+ sprite->pos2.x = sprite->sSavedLvlUpBoxXPosition - gBattle_BG2_X;
+
+ if (sprite->pos2.x != 0)
+ {
+ sprite->sDestroy = TRUE;
+ }
+ else if (sprite->sDestroy)
+ {
+ DestroySprite(sprite);
+ FreeSpriteTilesByTag(MON_ICON_LVLUP_BOX_TAG);
+ FreeSpritePaletteByTag(MON_ICON_LVLUP_BOX_TAG);
+ }
+}
+
+#undef sDestroy
+#undef sSavedLvlUpBoxXPosition
+
+static bool32 IsMonGettingExpSentOut(void)
+{
+ if (gBattlePartyID[0] == gBattleStruct->expGetterId)
+ return TRUE;
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && gBattlePartyID[2] == gBattleStruct->expGetterId)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void atk6D_reset_sentpokes_value(void)
+{
+ ResetSentPokesToOpponentValue();
+ gBattlescriptCurrInstr++;
+}
+
+static void atk6E_set_atk_to_player0(void)
+{
+ gBankAttacker = GetBankByIdentity(0);
+ gBattlescriptCurrInstr++;
+}
+
+static void atk6F_set_visible(void)
+{
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ EmitSpriteInvisibility(0, FALSE);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk70_record_last_used_ability(void)
+{
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ RecordAbilityBattle(gActiveBank, gLastUsedAbility);
+ gBattlescriptCurrInstr += 1; // UB: Should be + 2, one byte for command and one byte for bank argument.
+}
+
+void BufferMoveToLearnIntoBattleTextBuff2(void)
+{
+ PREPARE_MOVE_BUFFER(gBattleTextBuff2, gMoveToLearn);
+}
+
+static void atk71_buffer_move_to_learn(void)
+{
+ BufferMoveToLearnIntoBattleTextBuff2();
+ gBattlescriptCurrInstr++;
+}
+
+static void atk72_jump_if_can_run_frombattle(void)
+{
+ if (CanRunFromBattle(gBank1))
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ else
+ gBattlescriptCurrInstr += 5;
+}
+
+static void atk73_hp_thresholds(void)
+{
+ u8 opposingBank;
+ s32 result;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ opposingBank = gActiveBank ^ BIT_SIDE;
+
+ result = gBattleMons[opposingBank].hp * 100 / gBattleMons[opposingBank].maxHP;
+ if (result == 0)
+ result = 1;
+
+ if (result > 69 || !gBattleMons[opposingBank].hp)
+ gBattleStruct->hpScale = 0;
+ else if (result > 39)
+ gBattleStruct->hpScale = 1;
+ else if (result > 9)
+ gBattleStruct->hpScale = 2;
+ else
+ gBattleStruct->hpScale = 3;
+ }
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk74_hp_thresholds2(void)
+{
+ u8 opposingBank;
+ s32 result;
+ u8 hpSwitchout;
+
+ if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ opposingBank = gActiveBank ^ BIT_SIDE;
+ hpSwitchout = *(gBattleStruct->hpOnSwitchout + GetBankSide(opposingBank));
+ result = (hpSwitchout - gBattleMons[opposingBank].hp) * 100 / hpSwitchout;
+
+ if (gBattleMons[opposingBank].hp >= hpSwitchout)
+ gBattleStruct->hpScale = 0;
+ else if (result <= 29)
+ gBattleStruct->hpScale = 1;
+ else if (result <= 69)
+ gBattleStruct->hpScale = 2;
+ else
+ gBattleStruct->hpScale = 3;
+ }
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk75_item_effect_on_opponent(void)
+{
+ gBankInMenu = gBankAttacker;
+ ExecuteTableBasedItemEffect(&gEnemyParty[gBattlePartyID[gBankAttacker]], gLastUsedItem, gBattlePartyID[gBankAttacker], 0, 1);
+
+ gBattlescriptCurrInstr += 1;
+}
+
+static void atk76_various(void)
+{
+ u8 side;
+ s32 i;
+
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ switch (gBattlescriptCurrInstr[2])
+ {
+ case VARIOUS_CANCEL_MULTI_TURN_MOVES:
+ CancelMultiTurnMoves(gActiveBank);
+ break;
+ case VARIOUS_SET_MAGIC_COAT_TARGET:
+ gBankAttacker = gBankTarget;
+ side = GetBankSide(gBankAttacker) ^ 1;
+ if (gSideTimers[side].followmeTimer != 0 && gBattleMons[gSideTimers[side].followmeTarget].hp != 0)
+ gBankTarget = gSideTimers[side].followmeTarget;
+ else
+ gBankTarget = gActiveBank;
+ break;
+ case 2:
+ gBattleCommunication[0] = IsRunningFromBattleImpossible();
+ break;
+ case VARIOUS_GET_MOVE_TARGET:
+ gBankTarget = GetMoveTarget(gCurrentMove, 0);
+ break;
+ case 4:
+ if (gHitMarker & HITMARKER_FAINTED(gActiveBank))
+ gBattleCommunication[0] = 1;
+ else
+ gBattleCommunication[0] = 0;
+ break;
+ case VARIOUS_RESET_INTIMIDATE_TRACE_BITS:
+ gSpecialStatuses[gActiveBank].intimidatedPoke = 0;
+ gSpecialStatuses[gActiveBank].traced = 0;
+ break;
+ case VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP:
+ if (gBattlePartyID[0] == gBattleStruct->expGetterId || gBattlePartyID[2] == gBattleStruct->expGetterId)
+ {
+ u16 *choicedMove;
+
+ if (gBattlePartyID[0] == gBattleStruct->expGetterId)
+ gActiveBank = 0;
+ else
+ gActiveBank = 2;
+
+ choicedMove = &gBattleStruct->choicedMove[gActiveBank];
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gBattleMons[gActiveBank].moves[i] == *choicedMove)
+ break;
+ }
+ if (i == 4)
+ *choicedMove = 0;
+ }
+ break;
+ case 7:
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_DOUBLE))
+ && gBattleTypeFlags & BATTLE_TYPE_TRAINER
+ && gBattleMons[0].hp != 0
+ && gBattleMons[1].hp != 0)
+ {
+ gHitMarker &= ~(HITMARKER_x400000);
+ }
+ break;
+ case 8:
+ gBattleCommunication[0] = 0;
+ gBattleScripting.bank = gActiveBank = gBattleCommunication[1];
+ if (!(gBattleStruct->field_92 & gBitTable[gActiveBank])
+ && gBattleMons[gActiveBank].maxHP / 2 >= gBattleMons[gActiveBank].hp
+ && gBattleMons[gActiveBank].hp != 0
+ && !(gBattleMons[gActiveBank].status1 & STATUS_SLEEP))
+ {
+ gBattleStruct->field_92 |= gBitTable[gActiveBank];
+ gBattleCommunication[0] = 1;
+ gBattleCommunication[MULTISTRING_CHOOSER] = sUnknown_0831C4F8[GetNatureFromPersonality(gBattleMons[gActiveBank].personality)];
+ }
+ break;
+ case 9:
+ i = sub_81A5258(gBattleCommunication);
+ if (i == 0)
+ return;
+
+ gBattleCommunication[1] = i;
+ break;
+ case 10:
+ gBattleMons[1].hp = 0;
+ gHitMarker |= HITMARKER_FAINTED(1);
+ gBattleStruct->field_2A1 |= gBitTable[gBattlePartyID[1]];
+ gDisableStructs[1].truantUnknownBit = 1;
+ break;
+ case 11:
+ gBattleMons[0].hp = 0;
+ gHitMarker |= HITMARKER_FAINTED(0);
+ gHitMarker |= HITMARKER_x400000;
+ gBattleStruct->field_2A0 |= gBitTable[gBattlePartyID[0]];
+ gDisableStructs[0].truantUnknownBit = 1;
+ break;
+ case 12:
+ gBattleMons[0].hp = 0;
+ gBattleMons[1].hp = 0;
+ gHitMarker |= HITMARKER_FAINTED(0);
+ gHitMarker |= HITMARKER_FAINTED(1);
+ gHitMarker |= HITMARKER_x400000;
+ gBattleStruct->field_2A0 |= gBitTable[gBattlePartyID[0]];
+ gBattleStruct->field_2A1 |= gBitTable[gBattlePartyID[1]];
+ gDisableStructs[0].truantUnknownBit = 1;
+ gDisableStructs[1].truantUnknownBit = 1;
+ break;
+ case 13:
+ EmitCmd13(0);
+ MarkBufferBankForExecution(gActiveBank);
+ break;
+ case 14:
+ sub_81A5BF8();
+ break;
+ case 15:
+ sub_81A5D44();
+ break;
+ case 16:
+ BattleStringExpandPlaceholdersToDisplayedString(gRefereeStringsTable[gBattlescriptCurrInstr[1]]);
+ sub_814F9EC(gDisplayedStringBattle, 0x16);
+ break;
+ case 17:
+ if (IsTextPrinterActive(0x16))
+ return;
+ break;
+ case VARIOUS_WAIT_CRY:
+ if (!IsCryFinished())
+ return;
+ break;
+ case VARIOUS_RETURN_OPPONENT_MON1:
+ gActiveBank = 1;
+ if (gBattleMons[gActiveBank].hp != 0)
+ {
+ EmitReturnPokeToBall(0, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ break;
+ case VARIOUS_RETURN_OPPONENT_MON2:
+ if (gNoOfAllBanks > 3)
+ {
+ gActiveBank = 3;
+ if (gBattleMons[gActiveBank].hp != 0)
+ {
+ EmitReturnPokeToBall(0, 0);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+ break;
+ case 21:
+ m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x55);
+ break;
+ case 22:
+ m4aMPlayVolumeControl(&gMPlay_BGM, 0xFFFF, 0x100);
+ break;
+ case 23:
+ gBattleStruct->field_2A2 |= gBitTable[gActiveBank];
+ break;
+ case 24:
+ if (sub_805725C(gActiveBank))
+ return;
+ break;
+ case VARIOUS_SET_TELEPORT_OUTCOME:
+ if (GetBankSide(gActiveBank) == SIDE_PLAYER)
+ gBattleOutcome = BATTLE_PLAYER_TELEPORTED;
+ else
+ gBattleOutcome = BATTLE_OPPONENT_TELEPORTED;
+ break;
+ case VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC:
+ EmitPlaySound(0, 0x19C, 1);
+ MarkBufferBankForExecution(gActiveBank);
+ break;
+ }
+
+ gBattlescriptCurrInstr += 3;
+}
+
+static void atk77_set_protect_like(void) // protect and endure
+{
+ bool8 notLastTurn = TRUE;
+ u16 lastMove = gUnknown_02024260[gBankAttacker];
+
+ if (lastMove != MOVE_PROTECT && lastMove != MOVE_DETECT && lastMove != MOVE_ENDURE)
+ gDisableStructs[gBankAttacker].protectUses = 0;
+
+ if (gCurrentMoveTurn == (gNoOfAllBanks - 1))
+ notLastTurn = FALSE;
+
+ if (sProtectSuccessRates[gDisableStructs[gBankAttacker].protectUses] >= Random() && notLastTurn)
+ {
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_PROTECT)
+ {
+ gProtectStructs[gBankAttacker].protected = 1;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_ENDURE)
+ {
+ gProtectStructs[gBankAttacker].endured = 1;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ gDisableStructs[gBankAttacker].protectUses++;
+ }
+ else
+ {
+ gDisableStructs[gBankAttacker].protectUses = 0;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk78_faintifabilitynotdamp(void)
+{
+ if (gBattleExecBuffer)
+ return;
+
+ for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++)
+ {
+ if (gBattleMons[gBankTarget].ability == ABILITY_DAMP)
+ break;
+ }
+
+ if (gBankTarget == gNoOfAllBanks)
+ {
+ gActiveBank = gBankAttacker;
+ gBattleMoveDamage = gBattleMons[gActiveBank].hp;
+ EmitHealthBarUpdate(0, 0x7FFF);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr++;
+
+ for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++)
+ {
+ if (gBankTarget == gBankAttacker)
+ continue;
+ if (!(gAbsentBankFlags & gBitTable[gBankTarget]))
+ break;
+ }
+ }
+ else
+ {
+ gLastUsedAbility = ABILITY_DAMP;
+ RecordAbilityBattle(gBankTarget, gBattleMons[gBankTarget].ability);
+ gBattlescriptCurrInstr = BattleScript_DampStopsExplosion;
+ }
+}
+
+static void atk79_setatkhptozero(void)
+{
+ if (gBattleExecBuffer)
+ return;
+
+ gActiveBank = gBankAttacker;
+ gBattleMons[gActiveBank].hp = 0;
+ EmitSetMonData(0, REQUEST_HP_BATTLE, 0, 2, &gBattleMons[gActiveBank].hp);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk7A_jumpwhiletargetvalid(void) // Used by intimidate to loop through all targets.
+{
+ const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ {
+ for (gBankTarget++; ; gBankTarget++)
+ {
+ if (gBankTarget == gBankAttacker)
+ continue;
+ if (!(gAbsentBankFlags & gBitTable[gBankTarget]))
+ break;
+ }
+
+ if (gBankTarget >= gNoOfAllBanks)
+ gBattlescriptCurrInstr += 5;
+ else
+ gBattlescriptCurrInstr = jumpPtr;
+ }
+ else
+ gBattlescriptCurrInstr += 5;
+}
+
+static void atk7B_healhalfHP_if_possible(void)
+{
+ const u8* failPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+
+ if (gBattlescriptCurrInstr[5] == BS_GET_ATTACKER)
+ gBankTarget = gBankAttacker;
+
+ gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 2;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ gBattleMoveDamage *= -1;
+
+ if (gBattleMons[gBankTarget].hp == gBattleMons[gBankTarget].maxHP)
+ gBattlescriptCurrInstr = failPtr;
+ else
+ gBattlescriptCurrInstr += 6;
+}
+
+static void atk7C_trymirrormove(void)
+{
+ s32 validMovesCount;
+ s32 i;
+ u16 move;
+ u16 movesArray[4];
+
+ for (i = 0; i < 3; i++)
+ movesArray[i] = 0;
+
+ for (validMovesCount = 0, i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (i != gBankAttacker)
+ {
+ move = *(i * 2 + gBankAttacker * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 0)
+ | (*(i * 2 + gBankAttacker * 8 + (u8*)(gBattleStruct->mirrorMoveArrays) + 1) << 8);
+
+ if (move != 0 && move != 0xFFFF)
+ {
+ movesArray[validMovesCount] = move;
+ validMovesCount++;
+ }
+ }
+ }
+
+ move = *(gBattleStruct->mirrorMoves + gBankAttacker * 2 + 0)
+ | (*(gBattleStruct->mirrorMoves + gBankAttacker * 2 + 1) << 8);
+
+ if (move != 0 && move != 0xFFFF)
+ {
+ gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
+ gCurrentMove = move;
+ gBankTarget = GetMoveTarget(gCurrentMove, 0);
+ gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
+ }
+ else if (validMovesCount)
+ {
+ gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
+ i = Random() % validMovesCount;
+ gCurrentMove = movesArray[i];
+ gBankTarget = GetMoveTarget(gCurrentMove, 0);
+ gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
+ }
+ else
+ {
+ gSpecialStatuses[gBankAttacker].flag20 = 1;
+ gBattlescriptCurrInstr++;
+ }
+}
+
+static void atk7D_set_rain(void)
+{
+ if (gBattleWeather & WEATHER_RAIN_ANY)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ }
+ else
+ {
+ gBattleWeather = WEATHER_RAIN_TEMPORARY;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ gWishFutureKnock.weatherDuration = 5;
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atk7E_setreflect(void)
+{
+ if (gSideAffecting[GET_BANK_SIDE(gBankAttacker)] & SIDE_STATUS_REFLECT)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ else
+ {
+ gSideAffecting[GET_BANK_SIDE(gBankAttacker)] |= SIDE_STATUS_REFLECT;
+ gSideTimers[GET_BANK_SIDE(gBankAttacker)].reflectTimer = 5;
+ gSideTimers[GET_BANK_SIDE(gBankAttacker)].reflectBank = gBankAttacker;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && CountAliveMonsInBattle(BATTLE_ALIVE_ATK_SIDE) == 2)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atk7F_setseeded(void)
+{
+ if (gBattleMoveFlags & MOVESTATUS_NOEFFECT || gStatuses3[gBankTarget] & STATUS3_LEECHSEED)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ else if (gBattleMons[gBankTarget].type1 == TYPE_GRASS || gBattleMons[gBankTarget].type2 == TYPE_GRASS)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ }
+ else
+ {
+ gStatuses3[gBankTarget] |= gBankAttacker;
+ gStatuses3[gBankTarget] |= STATUS3_LEECHSEED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk80_manipulatedamage(void)
+{
+ switch (gBattlescriptCurrInstr[1])
+ {
+ case ATK80_DMG_CHANGE_SIGN:
+ gBattleMoveDamage *= -1;
+ break;
+ case ATK80_DMG_HALF_BY_TWO_NOT_MORE_THAN_HALF_MAX_HP:
+ gBattleMoveDamage /= 2;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ if ((gBattleMons[gBankTarget].maxHP / 2) < gBattleMoveDamage)
+ gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 2;
+ break;
+ case ATK80_DMG_DOUBLED:
+ gBattleMoveDamage *= 2;
+ break;
+ }
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk81_setrest(void)
+{
+ const u8* failJump = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ gActiveBank = gBankTarget = gBankAttacker;
+ gBattleMoveDamage = gBattleMons[gBankTarget].maxHP * (-1);
+
+ if (gBattleMons[gBankTarget].hp == gBattleMons[gBankTarget].maxHP)
+ {
+ gBattlescriptCurrInstr = failJump;
+ }
+ else
+ {
+ if (gBattleMons[gBankTarget].status1 & ((u8)(~STATUS_SLEEP)))
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+
+ gBattleMons[gBankTarget].status1 = 3;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atk82_jumpifnotfirstturn(void)
+{
+ const u8* failJump = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+
+ if (gDisableStructs[gBankAttacker].isFirstTurn)
+ gBattlescriptCurrInstr += 5;
+ else
+ gBattlescriptCurrInstr = failJump;
+}
+
+static void atk83_nop(void)
+{
+ gBattlescriptCurrInstr++;
+}
+
+bool8 UproarWakeUpCheck(u8 bank)
+{
+ s32 i;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || gBattleMons[bank].ability == ABILITY_SOUNDPROOF)
+ continue;
+
+ gBattleScripting.bank = i;
+
+ if (gBankTarget == 0xFF)
+ gBankTarget = i;
+ else if (gBankTarget == i)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+
+ break;
+ }
+
+ if (i == gNoOfAllBanks)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static void atk84_jump_if_cant_sleep(void)
+{
+ const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+
+ if (UproarWakeUpCheck(gBankTarget))
+ {
+ gBattlescriptCurrInstr = jumpPtr;
+ }
+ else if (gBattleMons[gBankTarget].ability == ABILITY_INSOMNIA
+ || gBattleMons[gBankTarget].ability == ABILITY_VITAL_SPIRIT)
+ {
+ gLastUsedAbility = gBattleMons[gBankTarget].ability;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ gBattlescriptCurrInstr = jumpPtr;
+ RecordAbilityBattle(gBankTarget, gLastUsedAbility);
+ }
+ else
+ {
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atk85_stockpile(void)
+{
+ if (gDisableStructs[gBankAttacker].stockpileCounter == 3)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ else
+ {
+ gDisableStructs[gBankAttacker].stockpileCounter++;
+
+ PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 1, gDisableStructs[gBankAttacker].stockpileCounter)
+
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atk86_stockpiletobasedamage(void)
+{
+ const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ if (gDisableStructs[gBankAttacker].stockpileCounter == 0)
+ {
+ gBattlescriptCurrInstr = jumpPtr;
+ }
+ else
+ {
+ if (gBattleCommunication[6] != 1)
+ {
+ gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankTarget], gCurrentMove,
+ gSideAffecting[GET_BANK_SIDE(gBankTarget)], 0,
+ 0, gBankAttacker, gBankTarget)
+ * gDisableStructs[gBankAttacker].stockpileCounter;
+ gBattleScripting.animTurn = gDisableStructs[gBankAttacker].stockpileCounter;
+
+ if (gProtectStructs[gBankAttacker].helpingHand)
+ gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
+ }
+
+ gDisableStructs[gBankAttacker].stockpileCounter = 0;
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atk87_stockpiletohpheal(void)
+{
+ const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+
+ if (gDisableStructs[gBankAttacker].stockpileCounter == 0)
+ {
+ gBattlescriptCurrInstr = jumpPtr;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ else if (gBattleMons[gBankAttacker].maxHP == gBattleMons[gBankAttacker].hp)
+ {
+ gDisableStructs[gBankAttacker].stockpileCounter = 0;
+ gBattlescriptCurrInstr = jumpPtr;
+ gBankTarget = gBankAttacker;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ else
+ {
+ gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / (1 << (3 - gDisableStructs[gBankAttacker].stockpileCounter));
+
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ gBattleMoveDamage *= -1;
+
+ gBattleScripting.animTurn = gDisableStructs[gBankAttacker].stockpileCounter;
+ gDisableStructs[gBankAttacker].stockpileCounter = 0;
+ gBattlescriptCurrInstr += 5;
+ gBankTarget = gBankAttacker;
+ }
+}
+
+static void atk88_negativedamage(void)
+{
+ gBattleMoveDamage = -(gHpDealt / 2);
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = -1;
+
+ gBattlescriptCurrInstr++;
+}
+
+static u8 ChangeStatBuffs(s8 statValue, u8 statId, u8 flags, const u8* BS_ptr)
+{
+ bool8 certain = 0;
+ bool8 notProtectAffected = FALSE;
+ u32 index;
+
+ if (flags & MOVE_EFFECT_AFFECTS_USER)
+ gActiveBank = gBankAttacker;
+ else
+ gActiveBank = gBankTarget;
+
+ flags &= ~(MOVE_EFFECT_AFFECTS_USER);
+
+ if (flags & MOVE_EFFECT_CERTAIN)
+ certain++;
+ flags &= ~(MOVE_EFFECT_CERTAIN);
+
+ if (flags & STAT_CHANGE_NOT_PROTECT_AFFECTED)
+ notProtectAffected++;
+ flags &= ~(STAT_CHANGE_NOT_PROTECT_AFFECTED);
+
+ PREPARE_STAT_BUFFER(gBattleTextBuff1, statId)
+
+ if ((statValue << 0x18) < 0) // stat decrease
+ {
+ if (gSideTimers[GET_BANK_SIDE(gActiveBank)].mistTimer
+ && !certain && gCurrentMove != MOVE_CURSE)
+ {
+ if (flags == STAT_CHANGE_BS_PTR)
+ {
+ if (gSpecialStatuses[gActiveBank].statLowered)
+ {
+ gBattlescriptCurrInstr = BS_ptr;
+ }
+ else
+ {
+ BattleScriptPush(BS_ptr);
+ gBattleScripting.bank = gActiveBank;
+ gBattlescriptCurrInstr = BattleScript_MistProtected;
+ gSpecialStatuses[gActiveBank].statLowered = 1;
+ }
+ }
+ return STAT_CHANGE_DIDNT_WORK;
+ }
+ else if (gCurrentMove != MOVE_CURSE
+ && notProtectAffected != TRUE && JumpIfMoveAffectedByProtect(0))
+ {
+ gBattlescriptCurrInstr = BattleScript_ButItFailed;
+ return STAT_CHANGE_DIDNT_WORK;
+ }
+ else if ((gBattleMons[gActiveBank].ability == ABILITY_CLEAR_BODY
+ || gBattleMons[gActiveBank].ability == ABILITY_WHITE_SMOKE)
+ && !certain && gCurrentMove != MOVE_CURSE)
+ {
+ if (flags == STAT_CHANGE_BS_PTR)
+ {
+ if (gSpecialStatuses[gActiveBank].statLowered)
+ {
+ gBattlescriptCurrInstr = BS_ptr;
+ }
+ else
+ {
+ BattleScriptPush(BS_ptr);
+ gBattleScripting.bank = gActiveBank;
+ gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss;
+ gLastUsedAbility = gBattleMons[gActiveBank].ability;
+ RecordAbilityBattle(gActiveBank, gLastUsedAbility);
+ gSpecialStatuses[gActiveBank].statLowered = 1;
+ }
+ }
+ return STAT_CHANGE_DIDNT_WORK;
+ }
+ else if (gBattleMons[gActiveBank].ability == ABILITY_KEEN_EYE
+ && !certain && statId == STAT_STAGE_ACC)
+ {
+ if (flags == STAT_CHANGE_BS_PTR)
+ {
+ BattleScriptPush(BS_ptr);
+ gBattleScripting.bank = gActiveBank;
+ gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss;
+ gLastUsedAbility = gBattleMons[gActiveBank].ability;
+ RecordAbilityBattle(gActiveBank, gLastUsedAbility);
+ }
+ return STAT_CHANGE_DIDNT_WORK;
+ }
+ else if (gBattleMons[gActiveBank].ability == ABILITY_HYPER_CUTTER
+ && !certain && statId == STAT_STAGE_ATK)
+ {
+ if (flags == STAT_CHANGE_BS_PTR)
+ {
+ BattleScriptPush(BS_ptr);
+ gBattleScripting.bank = gActiveBank;
+ gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss;
+ gLastUsedAbility = gBattleMons[gActiveBank].ability;
+ RecordAbilityBattle(gActiveBank, gLastUsedAbility);
+ }
+ return STAT_CHANGE_DIDNT_WORK;
+ }
+ else if (gBattleMons[gActiveBank].ability == ABILITY_SHIELD_DUST && flags == 0)
+ {
+ return STAT_CHANGE_DIDNT_WORK;
+ }
+ else // try to decrease
+ {
+ statValue = -GET_STAT_BUFF_VALUE(statValue);
+ gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN;
+ index = 1;
+ if (statValue == -2)
+ {
+ gBattleTextBuff2[1] = B_BUFF_STRING;
+ gBattleTextBuff2[2] = 0xD3; // harshly
+ gBattleTextBuff2[3] = 0xD3 >> 8;
+ index = 4;
+ }
+ gBattleTextBuff2[index] = B_BUFF_STRING;
+ index++;
+ gBattleTextBuff2[index] = 0xD4; // fell
+ index++;
+ gBattleTextBuff2[index] = 0xD4 >> 8;
+ index++;
+ gBattleTextBuff2[index] = B_BUFF_EOS;
+
+ if (gBattleMons[gActiveBank].statStages[statId] == 0)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = (gBankTarget == gActiveBank);
+
+ }
+ }
+ else // stat increase
+ {
+ statValue = GET_STAT_BUFF_VALUE(statValue);
+ gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN;
+ index = 1;
+ if (statValue == 2)
+ {
+ gBattleTextBuff2[1] = B_BUFF_STRING;
+ gBattleTextBuff2[2] = 0xD1; // sharply
+ gBattleTextBuff2[3] = 0xD1 >> 8;
+ index = 4;
+ }
+ gBattleTextBuff2[index] = B_BUFF_STRING;
+ index++;
+ gBattleTextBuff2[index] = 0xD2; // rose
+ index++;
+ gBattleTextBuff2[index] = 0xD2 >> 8;
+ index++;
+ gBattleTextBuff2[index] = B_BUFF_EOS;
+
+ if (gBattleMons[gActiveBank].statStages[statId] == 0xC)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = (gBankTarget == gActiveBank);
+ }
+
+ gBattleMons[gActiveBank].statStages[statId] += statValue;
+ if (gBattleMons[gActiveBank].statStages[statId] < 0)
+ gBattleMons[gActiveBank].statStages[statId] = 0;
+ if (gBattleMons[gActiveBank].statStages[statId] > 0xC)
+ gBattleMons[gActiveBank].statStages[statId] = 0xC;
+
+ if (gBattleCommunication[MULTISTRING_CHOOSER] == 2 && flags & STAT_CHANGE_BS_PTR)
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+
+ if (gBattleCommunication[MULTISTRING_CHOOSER] == 2 && !(flags & STAT_CHANGE_BS_PTR))
+ return STAT_CHANGE_DIDNT_WORK;
+
+ return STAT_CHANGE_WORKED;
+}
+
+static void atk89_statbuffchange(void)
+{
+ const u8* jumpPtr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ if (ChangeStatBuffs(gBattleScripting.statChanger & 0xF0, GET_STAT_BUFF_ID(gBattleScripting.statChanger), gBattlescriptCurrInstr[1], jumpPtr) == STAT_CHANGE_WORKED)
+ gBattlescriptCurrInstr += 6;
+}
+
+static void atk8A_normalisebuffs(void) // haze
+{
+ s32 i, j;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ for (j = 0; j < BATTLE_STATS_NO; j++)
+ gBattleMons[i].statStages[j] = 6;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk8B_setbide(void)
+{
+ gBattleMons[gBankAttacker].status2 |= STATUS2_MULTIPLETURNS;
+ gLockedMoves[gBankAttacker] = gCurrentMove;
+ gTakenDmg[gBankAttacker] = 0;
+ gBattleMons[gBankAttacker].status2 |= (STATUS2_BIDE - 0x100); // 2 turns
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk8C_confuseifrepeatingattackends(void)
+{
+ if (!(gBattleMons[gBankAttacker].status2 & STATUS2_LOCK_CONFUSE))
+ gBattleCommunication[MOVE_EFFECT_BYTE] = (MOVE_EFFECT_THRASH | MOVE_EFFECT_AFFECTS_USER);
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk8D_setmultihit_counter(void)
+{
+ if (gBattlescriptCurrInstr[1])
+ {
+ gMultiHitCounter = gBattlescriptCurrInstr[1];
+ }
+ else
+ {
+ gMultiHitCounter = Random() & 3;
+ if (gMultiHitCounter > 1)
+ gMultiHitCounter = (Random() & 3) + 2;
+ else
+ gMultiHitCounter += 2;
+ }
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atk8E_init_multihit_string(void)
+{
+ PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0)
+
+ gBattlescriptCurrInstr++;
+}
+
+static bool8 sub_8051064(void)
+{
+ if (gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level)
+ {
+ *(gBattleStruct->field_58 + gBankTarget) = gBattlePartyID[gBankTarget];
+ }
+ else
+ {
+ u16 random = Random() & 0xFF;
+ if ((u32)((random * (gBattleMons[gBankAttacker].level + gBattleMons[gBankTarget].level) >> 8) + 1) <= (gBattleMons[gBankTarget].level / 4))
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ return FALSE;
+ }
+ *(gBattleStruct->field_58 + gBankTarget) = gBattlePartyID[gBankTarget];
+ }
+
+ gBattlescriptCurrInstr = gUnknown_082DADD8;
+ return TRUE;
+}
+
+static void atk8F_forcerandomswitch(void)
+{
+ s32 i;
+ s32 bank1PartyId = 0;
+ s32 bank2PartyId = 0;
+
+ #ifdef NONMATCHING
+ s32 lastMonId = 0; // + 1
+ #else
+ register s32 lastMonId asm("r8") = 0; // + 1
+ #endif // NONMATCHING
+
+ s32 firstMonId = 0;
+ s32 monsCount = 0;
+ struct Pokemon* party = NULL;
+ s32 validMons = 0;
+ s32 minNeeded = 0;
+
+ if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER))
+ {
+ if (GetBankSide(gBankTarget) == SIDE_PLAYER)
+ party = gPlayerParty;
+ else
+ party = gEnemyParty;
+
+ if ((gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER && gBattleTypeFlags & BATTLE_TYPE_LINK)
+ || (gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER && gBattleTypeFlags & BATTLE_TYPE_x2000000)
+ || (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER))
+ {
+ if ((gBankTarget & BIT_MON) != 0)
+ {
+ firstMonId = 3;
+ lastMonId = 6;
+ }
+ else
+ {
+ firstMonId = 0;
+ lastMonId = 3;
+ }
+ monsCount = 3;
+ minNeeded = 1;
+ bank2PartyId = gBattlePartyID[gBankTarget];
+ bank1PartyId = gBattlePartyID[gBankTarget ^ BIT_MON];
+ }
+ else if ((gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_LINK)
+ || (gBattleTypeFlags & BATTLE_TYPE_MULTI && gBattleTypeFlags & BATTLE_TYPE_x2000000))
+ {
+ if (sub_806D82C(sub_806D864(gBankTarget)) == 1)
+ {
+ firstMonId = 3;
+ lastMonId = 6;
+ }
+ else
+ {
+ firstMonId = 0;
+ lastMonId = 3;
+ }
+ monsCount = 3;
+ minNeeded = 1;
+ bank2PartyId = gBattlePartyID[gBankTarget];
+ bank1PartyId = gBattlePartyID[gBankTarget ^ BIT_MON];
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
+ {
+ if (GetBankSide(gBankTarget) == SIDE_PLAYER)
+ {
+ firstMonId = 0;
+ lastMonId = 6;
+ monsCount = 6;
+ minNeeded = 2; // since there are two opponents, it has to be a double battle
+ }
+ else
+ {
+ if ((gBankTarget & BIT_MON) != 0)
+ {
+ firstMonId = 3;
+ lastMonId = 6;
+ }
+ else
+ {
+ firstMonId = 0;
+ lastMonId = 3;
+ }
+ monsCount = 3;
+ minNeeded = 1;
+ }
+ bank2PartyId = gBattlePartyID[gBankTarget];
+ bank1PartyId = gBattlePartyID[gBankTarget ^ BIT_MON];
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
+ {
+ firstMonId = 0;
+ lastMonId = 6;
+ monsCount = 6;
+ minNeeded = 2;
+ bank2PartyId = gBattlePartyID[gBankTarget];
+ bank1PartyId = gBattlePartyID[gBankTarget ^ BIT_MON];
+ }
+ else
+ {
+ firstMonId = 0;
+ lastMonId = 6;
+ monsCount = 6;
+ minNeeded = 1;
+ bank2PartyId = gBattlePartyID[gBankTarget]; // there is only one pokemon out in single battles
+ bank1PartyId = gBattlePartyID[gBankTarget];
+ }
+
+ for (i = firstMonId; i < lastMonId; i++)
+ {
+ if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE
+ && !GetMonData(&party[i], MON_DATA_IS_EGG)
+ && GetMonData(&party[i], MON_DATA_HP) != 0)
+ {
+ validMons++;
+ }
+ }
+
+ if (validMons <= minNeeded)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ if (sub_8051064())
+ {
+ do
+ {
+ i = Random() % monsCount;
+ i += firstMonId;
+ }
+ while (i == bank2PartyId
+ || i == bank1PartyId
+ || GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_NONE
+ || GetMonData(&party[i], MON_DATA_IS_EGG) == TRUE
+ || GetMonData(&party[i], MON_DATA_HP) == 0);
+ }
+ *(gBattleStruct->field_5C + gBankTarget) = i;
+
+ if (!sub_81B1250())
+ sub_803BDA0(gBankTarget);
+
+ if ((gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
+ || (gBattleTypeFlags & BATTLE_TYPE_LINK && gBattleTypeFlags & BATTLE_TYPE_MULTI)
+ || (gBattleTypeFlags & BATTLE_TYPE_x2000000 && gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER)
+ || (gBattleTypeFlags & BATTLE_TYPE_x2000000 && gBattleTypeFlags & BATTLE_TYPE_MULTI))
+ {
+ sub_81B8E80(gBankTarget, i, 0);
+ sub_81B8E80(gBankTarget ^ BIT_MON, i, 1);
+ }
+
+ if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER)
+ sub_80571DC(gBankTarget, i);
+ }
+ }
+ else
+ {
+ sub_8051064();
+ }
+}
+
+static void atk90_conversion_type_change(void) // randomly changes user's type to one of its moves' type
+{
+ u8 validMoves = 0;
+ u8 moveChecked;
+ u8 moveType;
+
+ while (validMoves < 4)
+ {
+ if (gBattleMons[gBankAttacker].moves[validMoves] == 0)
+ break;
+
+ validMoves++;
+ }
+
+ for (moveChecked = 0; moveChecked < validMoves; moveChecked++)
+ {
+ moveType = gBattleMoves[gBattleMons[gBankAttacker].moves[moveChecked]].type;
+
+ if (moveType == TYPE_MYSTERY)
+ {
+ if (gBattleMons[gBankAttacker].type1 == TYPE_GHOST || gBattleMons[gBankAttacker].type2 == TYPE_GHOST)
+ moveType = TYPE_GHOST;
+ else
+ moveType = TYPE_NORMAL;
+ }
+ if (moveType != gBattleMons[gBankAttacker].type1
+ && moveType != gBattleMons[gBankAttacker].type2)
+ {
+ break;
+ }
+ }
+
+ if (moveChecked == validMoves)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ do
+ {
+
+ while ((moveChecked = Random() & 3) >= validMoves);
+
+ moveType = gBattleMoves[gBattleMons[gBankAttacker].moves[moveChecked]].type;
+
+ if (moveType == TYPE_MYSTERY)
+ {
+ if (gBattleMons[gBankAttacker].type1 == TYPE_GHOST || gBattleMons[gBankAttacker].type2 == TYPE_GHOST)
+ moveType = TYPE_GHOST;
+ else
+ moveType = TYPE_NORMAL;
+ }
+ }
+ while (moveType == gBattleMons[gBankAttacker].type1 || moveType == gBattleMons[gBankAttacker].type2);
+
+ gBattleMons[gBankAttacker].type1 = moveType;
+ gBattleMons[gBankAttacker].type2 = moveType;
+
+ PREPARE_TYPE_BUFFER(gBattleTextBuff1, moveType)
+
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atk91_givepaydaymoney(void)
+{
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)) && gPaydayMoney != 0)
+ {
+ u32 bonusMoney = gPaydayMoney * gBattleStruct->moneyMultiplier;
+ AddMoney(&gSaveBlock1Ptr->money, bonusMoney);
+
+ PREPARE_HWORD_NUMBER_BUFFER(gBattleTextBuff1, 5, bonusMoney)
+
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_PrintPayDayMoneyString;
+ }
+ else
+ {
+ gBattlescriptCurrInstr++;
+ }
+}
+
+static void atk92_setlightscreen(void)
+{
+ if (gSideAffecting[GET_BANK_SIDE(gBankAttacker)] & SIDE_STATUS_LIGHTSCREEN)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ else
+ {
+ gSideAffecting[GET_BANK_SIDE(gBankAttacker)] |= SIDE_STATUS_LIGHTSCREEN;
+ gSideTimers[GET_BANK_SIDE(gBankAttacker)].lightscreenTimer = 5;
+ gSideTimers[GET_BANK_SIDE(gBankAttacker)].lightscreenBank = gBankAttacker;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && CountAliveMonsInBattle(BATTLE_ALIVE_ATK_SIDE) == 2)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 4;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 3;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk93_ko_move(void)
+{
+ u8 holdEffect, param;
+
+ if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[gBankTarget].holdEffect;
+ param = gEnigmaBerries[gBankTarget].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
+ param = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
+ }
+
+ gStringBank = gBankTarget;
+
+ if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < param)
+ {
+ RecordItemEffectBattle(gBankTarget, HOLD_EFFECT_FOCUS_BAND);
+ gSpecialStatuses[gBankTarget].focusBanded = 1;
+ }
+
+ if (gBattleMons[gBankTarget].ability == ABILITY_STURDY)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gLastUsedAbility = ABILITY_STURDY;
+ gBattlescriptCurrInstr = BattleScript_SturdyPreventsOHKO;
+ RecordAbilityBattle(gBankTarget, ABILITY_STURDY);
+ }
+ else
+ {
+ u16 chance;
+ if (!(gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS))
+ {
+ chance = gBattleMoves[gCurrentMove].accuracy + (gBattleMons[gBankAttacker].level - gBattleMons[gBankTarget].level);
+ if (Random() % 100 + 1 < chance && gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level)
+ chance = TRUE;
+ else
+ chance = FALSE;
+ }
+ else if (gDisableStructs[gBankTarget].bankWithSureHit == gBankAttacker
+ && gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level)
+ {
+ chance = TRUE;
+ }
+ else
+ {
+ chance = gBattleMoves[gCurrentMove].accuracy + (gBattleMons[gBankAttacker].level - gBattleMons[gBankTarget].level);
+ if (Random() % 100 + 1 < chance && gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level)
+ chance = TRUE;
+ else
+ chance = FALSE;
+ }
+ if (chance)
+ {
+ if (gProtectStructs[gBankTarget].endured)
+ {
+ gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1;
+ gBattleMoveFlags |= MOVESTATUS_ENDURED;
+ }
+ else if (gSpecialStatuses[gBankTarget].focusBanded)
+ {
+ gBattleMoveDamage = gBattleMons[gBankTarget].hp - 1;
+ gBattleMoveFlags |= MOVESTATUS_HUNGON;
+ gLastUsedItem = gBattleMons[gBankTarget].item;
+ }
+ else
+ {
+ gBattleMoveDamage = gBattleMons[gBankTarget].hp;
+ gBattleMoveFlags |= MOVESTATUS_ONEHITKO;
+ }
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ if (gBattleMons[gBankAttacker].level >= gBattleMons[gBankTarget].level)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ }
+}
+
+static void atk94_damagetohalftargethp(void) // super fang
+{
+ gBattleMoveDamage = gBattleMons[gBankTarget].hp / 2;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk95_setsandstorm(void)
+{
+ if (gBattleWeather & WEATHER_SANDSTORM_ANY)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ }
+ else
+ {
+ gBattleWeather = WEATHER_SANDSTORM_TEMPORARY;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 3;
+ gWishFutureKnock.weatherDuration = 5;
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atk96_weatherdamage(void)
+{
+ if (WEATHER_HAS_EFFECT)
+ {
+ if (gBattleWeather & WEATHER_SANDSTORM_ANY)
+ {
+ if (gBattleMons[gBankAttacker].type1 != TYPE_ROCK
+ && gBattleMons[gBankAttacker].type1 != TYPE_STEEL
+ && gBattleMons[gBankAttacker].type1 != TYPE_GROUND
+ && gBattleMons[gBankAttacker].type2 != TYPE_ROCK
+ && gBattleMons[gBankAttacker].type2 != TYPE_STEEL
+ && gBattleMons[gBankAttacker].type2 != TYPE_GROUND
+ && gBattleMons[gBankAttacker].ability != ABILITY_SAND_VEIL
+ && !(gStatuses3[gBankAttacker] & STATUS3_UNDERGROUND)
+ && !(gStatuses3[gBankAttacker] & STATUS3_UNDERWATER))
+ {
+ gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 16;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ }
+ else
+ {
+ gBattleMoveDamage = 0;
+ }
+ }
+ if (gBattleWeather & WEATHER_HAIL)
+ {
+ if (gBattleMons[gBankAttacker].type1 != TYPE_ICE
+ && gBattleMons[gBankAttacker].type2 != TYPE_ICE
+ && !(gStatuses3[gBankAttacker] & STATUS3_UNDERGROUND)
+ && !(gStatuses3[gBankAttacker] & STATUS3_UNDERWATER))
+ {
+ gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 16;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ }
+ else
+ {
+ gBattleMoveDamage = 0;
+ }
+ }
+ }
+ else
+ {
+ gBattleMoveDamage = 0;
+ }
+
+ if (gAbsentBankFlags & gBitTable[gBankAttacker])
+ gBattleMoveDamage = 0;
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atk97_try_infatuation(void)
+{
+ struct Pokemon *monAttacker, *monTarget;
+ u16 speciesAttacker, speciesTarget;
+ u32 personalityAttacker, personalityTarget;
+
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ monAttacker = &gPlayerParty[gBattlePartyID[gBankAttacker]];
+ else
+ monAttacker = &gEnemyParty[gBattlePartyID[gBankAttacker]];
+
+ if (GetBankSide(gBankTarget) == SIDE_PLAYER)
+ monTarget = &gPlayerParty[gBattlePartyID[gBankTarget]];
+ else
+ monTarget = &gEnemyParty[gBattlePartyID[gBankTarget]];
+
+ speciesAttacker = GetMonData(monAttacker, MON_DATA_SPECIES);
+ personalityAttacker = GetMonData(monAttacker, MON_DATA_PERSONALITY);
+
+ speciesTarget = GetMonData(monTarget, MON_DATA_SPECIES);
+ personalityTarget = GetMonData(monTarget, MON_DATA_PERSONALITY);
+
+ if (gBattleMons[gBankTarget].ability == ABILITY_OBLIVIOUS)
+ {
+ gBattlescriptCurrInstr = BattleScript_ObliviousPreventsAttraction;
+ gLastUsedAbility = ABILITY_OBLIVIOUS;
+ RecordAbilityBattle(gBankTarget, ABILITY_OBLIVIOUS);
+ }
+ else
+ {
+ if (GetGenderFromSpeciesAndPersonality(speciesAttacker, personalityAttacker) == GetGenderFromSpeciesAndPersonality(speciesTarget, personalityTarget)
+ || gBattleMons[gBankTarget].status2 & STATUS2_INFATUATION
+ || GetGenderFromSpeciesAndPersonality(speciesAttacker, personalityAttacker) == MON_GENDERLESS
+ || GetGenderFromSpeciesAndPersonality(speciesTarget, personalityTarget) == MON_GENDERLESS)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gBattleMons[gBankTarget].status2 |= STATUS2_INFATUATED_WITH(gBankAttacker);
+ gBattlescriptCurrInstr += 5;
+ }
+ }
+}
+
+static void atk98_status_icon_update(void)
+{
+ if (gBattleExecBuffer)
+ return;
+
+ if (gBattlescriptCurrInstr[1] != BS_ATTACKER_WITH_PARTNER)
+ {
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+ EmitStatusIconUpdate(0, gBattleMons[gActiveBank].status1, gBattleMons[gActiveBank].status2);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 2;
+ }
+ else
+ {
+ gActiveBank = gBankAttacker;
+ if (!(gAbsentBankFlags & gBitTable[gActiveBank]))
+ {
+ EmitStatusIconUpdate(0, gBattleMons[gActiveBank].status1, gBattleMons[gActiveBank].status2);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ if ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
+ {
+ gActiveBank = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ BIT_MON);
+ if (!(gAbsentBankFlags & gBitTable[gActiveBank]))
+ {
+ EmitStatusIconUpdate(0, gBattleMons[gActiveBank].status1, gBattleMons[gActiveBank].status2);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ }
+ gBattlescriptCurrInstr += 2;
+ }
+}
+
+static void atk99_setmist(void)
+{
+ if (gSideTimers[GET_BANK_SIDE(gBankAttacker)].mistTimer)
+ {
+ gBattleMoveFlags |= MOVESTATUS_FAILED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ else
+ {
+ gSideTimers[GET_BANK_SIDE(gBankAttacker)].mistTimer = 5;
+ gSideTimers[GET_BANK_SIDE(gBankAttacker)].mistBank = gBankAttacker;
+ gSideAffecting[GET_BANK_SIDE(gBankAttacker)] |= SIDE_STATUS_MIST;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atk9A_set_focusenergy(void)
+{
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_FOCUS_ENERGY)
+ {
+ gBattleMoveFlags |= MOVESTATUS_FAILED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ else
+ {
+ gBattleMons[gBankAttacker].status2 |= STATUS2_FOCUS_ENERGY;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atk9B_transformdataexecution(void)
+{
+ gLastUsedMove = 0xFFFF;
+ gBattlescriptCurrInstr++;
+ if (gBattleMons[gBankTarget].status2 & STATUS2_TRANSFORMED
+ || gStatuses3[gBankTarget] & STATUS3_SEMI_INVULNERABLE)
+ {
+ gBattleMoveFlags |= MOVESTATUS_FAILED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ else
+ {
+ s32 i;
+ u8 *battleMonAttacker, *battleMonTarget;
+
+ gBattleMons[gBankAttacker].status2 |= STATUS2_TRANSFORMED;
+ gDisableStructs[gBankAttacker].disabledMove = 0;
+ gDisableStructs[gBankAttacker].disableTimer1 = 0;
+ gDisableStructs[gBankAttacker].unk0 = gBattleMons[gBankTarget].personality;
+ gDisableStructs[gBankAttacker].unk18_b = 0;
+
+ PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBankTarget].species)
+
+ battleMonAttacker = (u8*)(&gBattleMons[gBankAttacker]);
+ battleMonTarget = (u8*)(&gBattleMons[gBankTarget]);
+
+ for (i = 0; i < offsetof(struct BattlePokemon, pp); i++)
+ battleMonAttacker[i] = battleMonTarget[i];
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gBattleMoves[gBattleMons[gBankAttacker].moves[i]].pp < 5)
+ gBattleMons[gBankAttacker].pp[i] = gBattleMoves[gBattleMons[gBankAttacker].moves[i]].pp;
+ else
+ gBattleMons[gBankAttacker].pp[i] = 5;
+ }
+
+ gActiveBank = gBankAttacker;
+ EmitResetActionMoveSelection(0, RESET_MOVE_SELECTION);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+}
+
+static void atk9C_set_substitute(void)
+{
+ u32 hp = gBattleMons[gBankAttacker].maxHP / 4;
+ if (gBattleMons[gBankAttacker].maxHP / 4 == 0)
+ hp = 1;
+
+ if (gBattleMons[gBankAttacker].hp <= hp)
+ {
+ gBattleMoveDamage = 0;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ else
+ {
+ gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 4; // one bit value will only work for pokemon which max hp can go to 1020(which is more than possible in games)
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+
+ gBattleMons[gBankAttacker].status2 |= STATUS2_SUBSTITUTE;
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_WRAPPED);
+ gDisableStructs[gBankAttacker].substituteHP = gBattleMoveDamage;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ gHitMarker |= HITMARKER_IGNORE_SUBSTITUTE;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static bool8 IsMoveUncopyableByMimic(u16 move)
+{
+ s32 i;
+ for (i = 0; sMovesForbiddenToCopy[i] != MIMIC_FORBIDDEN_END
+ && sMovesForbiddenToCopy[i] != move; i++);
+
+ return (sMovesForbiddenToCopy[i] != MIMIC_FORBIDDEN_END);
+}
+
+static void atk9D_mimicattackcopy(void)
+{
+ gLastUsedMove = 0xFFFF;
+
+ if (IsMoveUncopyableByMimic(gLastUsedMovesByBanks[gBankTarget])
+ || gBattleMons[gBankAttacker].status2 & STATUS2_TRANSFORMED
+ || gLastUsedMovesByBanks[gBankTarget] == 0
+ || gLastUsedMovesByBanks[gBankTarget] == 0xFFFF)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gBattleMons[gBankAttacker].moves[i] == gLastUsedMovesByBanks[gBankTarget])
+ break;
+ }
+
+ if (i == 4)
+ {
+ gBattleMons[gBankAttacker].moves[gCurrMovePos] = gLastUsedMovesByBanks[gBankTarget];
+ if (gBattleMoves[gLastUsedMovesByBanks[gBankTarget]].pp < 5)
+ gBattleMons[gBankAttacker].pp[gCurrMovePos] = gBattleMoves[gLastUsedMovesByBanks[gBankTarget]].pp;
+ else
+ gBattleMons[gBankAttacker].pp[gCurrMovePos] = 5;
+
+
+ PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastUsedMovesByBanks[gBankTarget])
+
+ gDisableStructs[gBankAttacker].unk18_b |= gBitTable[gCurrMovePos];
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ }
+}
+
+#ifdef NONMATCHING
+static void atk9E_metronome(void)
+{
+ while (1)
+ {
+ const u16 *move;
+ s32 i, j;
+
+ gCurrentMove = (Random() & 0x1FF) + 1;
+ if (gCurrentMove > LAST_MOVE_INDEX)
+ continue;
+
+ for (i = 0; i < 4; i++); // ?
+
+ for (move = sMovesForbiddenToCopy; ; move++)
+ {
+ if (*move == gCurrentMove)
+ break;
+ if (*move == METRONOME_FORBIDDEN_END)
+ break;
+ }
+
+ if (*move == METRONOME_FORBIDDEN_END)
+ break;
+ }
+
+ gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
+ gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
+ gBankTarget = GetMoveTarget(gCurrentMove, 0);
+}
+
+#else
+__attribute__((naked))
+static void atk9E_metronome(void)
+{
+ asm(
+ "\n\
+ .syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r8\n\
+ push {r7}\n\
+ ldr r7, =gCurrentMove\n\
+ movs r6, 0xB1\n\
+ lsls r6, 1\n\
+ ldr r5, =sMovesForbiddenToCopy\n\
+ ldr r0, =gBattlescriptCurrInstr\n\
+ mov r8, r0\n\
+_080524EE:\n\
+ bl Random\n\
+ ldr r2, =0x000001ff\n\
+ adds r1, r2, 0\n\
+ ands r0, r1\n\
+ adds r0, 0x1\n\
+ strh r0, [r7]\n\
+ cmp r0, r6\n\
+ bhi _080524EE\n\
+ movs r0, 0x3\n\
+_08052502:\n\
+ subs r0, 0x1\n\
+ cmp r0, 0\n\
+ bge _08052502\n\
+ ldr r4, =gCurrentMove\n\
+ ldrh r2, [r4]\n\
+ ldr r3, =0x0000ffff\n\
+ subs r0, r5, 0x2\n\
+_08052510:\n\
+ adds r0, 0x2\n\
+ ldrh r1, [r0]\n\
+ cmp r1, r2\n\
+ beq _0805251C\n\
+ cmp r1, r3\n\
+ bne _08052510\n\
+_0805251C:\n\
+ ldr r0, =0x0000ffff\n\
+ cmp r1, r0\n\
+ bne _080524EE\n\
+ ldr r2, =gHitMarker\n\
+ ldr r0, [r2]\n\
+ ldr r1, =0xfffffbff\n\
+ ands r0, r1\n\
+ str r0, [r2]\n\
+ ldr r3, =gBattleScriptsForMoveEffects\n\
+ ldr r2, =gBattleMoves\n\
+ ldrh r1, [r4]\n\
+ lsls r0, r1, 1\n\
+ adds r0, r1\n\
+ lsls r0, 2\n\
+ adds r0, r2\n\
+ ldrb r0, [r0]\n\
+ lsls r0, 2\n\
+ adds r0, r3\n\
+ ldr r0, [r0]\n\
+ mov r1, r8\n\
+ str r0, [r1]\n\
+ ldrh r0, [r4]\n\
+ movs r1, 0\n\
+ bl GetMoveTarget\n\
+ ldr r1, =gBankTarget\n\
+ strb r0, [r1]\n\
+ pop {r3}\n\
+ mov r8, r3\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .pool\n\
+ .syntax divided");
+}
+
+#endif // NONMATCHING
+
+static void atk9F_dmgtolevel(void)
+{
+ gBattleMoveDamage = gBattleMons[gBankAttacker].level;
+ gBattlescriptCurrInstr++;
+}
+
+static void atkA0_psywavedamageeffect(void)
+{
+ s32 randDamage;
+
+ while ((randDamage = (Random() & 0xF)) > 10);
+
+ randDamage *= 10;
+ gBattleMoveDamage = gBattleMons[gBankAttacker].level * (randDamage + 50) / 100;
+ gBattlescriptCurrInstr++;
+}
+
+static void atkA1_counterdamagecalculator(void)
+{
+ u8 sideAttacker = GetBankSide(gBankAttacker);
+ u8 sideTarget = GetBankSide(gProtectStructs[gBankAttacker].physicalBank);
+
+ if (gProtectStructs[gBankAttacker].physicalDmg
+ && sideAttacker != sideTarget
+ && gBattleMons[gProtectStructs[gBankAttacker].physicalBank].hp)
+ {
+ gBattleMoveDamage = gProtectStructs[gBankAttacker].physicalDmg * 2;
+
+ if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp)
+ gBankTarget = gSideTimers[sideTarget].followmeTarget;
+ else
+ gBankTarget = gProtectStructs[gBankAttacker].physicalBank;
+
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gSpecialStatuses[gBankAttacker].flag20 = 1;
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkA2_mirrorcoatdamagecalculator(void) // a copy of atkA1 with the physical -> special field changes
+{
+ u8 sideAttacker = GetBankSide(gBankAttacker);
+ u8 sideTarget = GetBankSide(gProtectStructs[gBankAttacker].specialBank);
+
+ if (gProtectStructs[gBankAttacker].specialDmg && sideAttacker != sideTarget && gBattleMons[gProtectStructs[gBankAttacker].specialBank].hp)
+ {
+ gBattleMoveDamage = gProtectStructs[gBankAttacker].specialDmg * 2;
+
+ if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp)
+ gBankTarget = gSideTimers[sideTarget].followmeTarget;
+ else
+ gBankTarget = gProtectStructs[gBankAttacker].specialBank;
+
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gSpecialStatuses[gBankAttacker].flag20 = 1;
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkA3_disablelastusedattack(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gBattleMons[gBankTarget].moves[i] == gLastUsedMovesByBanks[gBankTarget])
+ break;
+ }
+ if (gDisableStructs[gBankTarget].disabledMove == 0
+ && i != 4 && gBattleMons[gBankTarget].pp[i] != 0)
+ {
+ PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBankTarget].moves[i])
+
+ gDisableStructs[gBankTarget].disabledMove = gBattleMons[gBankTarget].moves[i];
+ gDisableStructs[gBankTarget].disableTimer1 = (Random() & 3) + 2;
+ gDisableStructs[gBankTarget].disableTimer2 = gDisableStructs[gBankTarget].disableTimer1; // used to save the random amount of turns?
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkA4_setencore(void)
+{
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gBattleMons[gBankTarget].moves[i] == gLastUsedMovesByBanks[gBankTarget])
+ break;
+ }
+
+ if (gLastUsedMovesByBanks[gBankTarget] == MOVE_STRUGGLE
+ || gLastUsedMovesByBanks[gBankTarget] == MOVE_ENCORE
+ || gLastUsedMovesByBanks[gBankTarget] == MOVE_MIRROR_MOVE)
+ {
+ i = 4;
+ }
+
+ if (gDisableStructs[gBankTarget].encoredMove == 0
+ && i != 4 && gBattleMons[gBankTarget].pp[i] != 0)
+ {
+ gDisableStructs[gBankTarget].encoredMove = gBattleMons[gBankTarget].moves[i];
+ gDisableStructs[gBankTarget].encoredMovePos = i;
+ gDisableStructs[gBankTarget].encoreTimer1 = (Random() & 3) + 3;
+ gDisableStructs[gBankTarget].encoreTimer2 = gDisableStructs[gBankTarget].encoreTimer1;
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkA5_painsplitdmgcalc(void)
+{
+ if (!(gBattleMons[gBankTarget].status2 & STATUS2_SUBSTITUTE))
+ {
+ s32 hpDiff = (gBattleMons[gBankAttacker].hp + gBattleMons[gBankTarget].hp) / 2;
+ s32 painSplitHp = gBattleMoveDamage = gBattleMons[gBankTarget].hp - hpDiff;
+ u8* storeLoc = (void*)(&gBattleScripting.painSplitHp);
+
+ storeLoc[0] = (painSplitHp);
+ storeLoc[1] = (painSplitHp & 0x0000FF00) >> 8;
+ storeLoc[2] = (painSplitHp & 0x00FF0000) >> 16;
+ storeLoc[3] = (painSplitHp & 0xFF000000) >> 24;
+
+ gBattleMoveDamage = gBattleMons[gBankAttacker].hp - hpDiff;
+ gSpecialStatuses[gBankTarget].moveturnLostHP = 0xFFFF;
+
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+#ifdef NONMATCHING
+static void atkA6_settypetorandomresistance(void) // conversion 2
+{
+ if (gUnknown_02024250[gBankAttacker] == 0
+ || gUnknown_02024250[gBankAttacker] == 0xFFFF)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else if (IsTwoTurnsMove(gUnknown_02024250[gBankAttacker])
+ && gBattleMons[gUnknown_02024270[gBankAttacker]].status2 & STATUS2_MULTIPLETURNS)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ s32 type = 0, rands = 0;
+ do
+ {
+ while (((type = (Random() & 0x7F)) > 0x70));
+
+ type *= 3;
+
+ if (gTypeEffectiveness[type] == gUnknown_02024258[gBankAttacker]
+ && gTypeEffectiveness[type + 2] <= 5
+ && gBattleMons[gBankAttacker].type1 != gTypeEffectiveness[type + 1]
+ && gBattleMons[gBankAttacker].type2 != gTypeEffectiveness[type + 1])
+ {
+ gBattleMons[gBankAttacker].type1 = type;
+ gBattleMons[gBankAttacker].type2 = type;
+
+ PREPARE_TYPE_BUFFER(gBattleTextBuff1, type)
+
+ gBattlescriptCurrInstr += 5;
+ return;
+ }
+
+ rands++;
+ } while (rands <= 999);
+
+ type = 0, rands = 0;
+ do
+ {
+ s8 var = (s8)(gTypeEffectiveness[type]);
+ if (var > -1 || var < -2)
+ {
+ if (gTypeEffectiveness[type] == gUnknown_02024258[gBankAttacker]
+ && gTypeEffectiveness[type + 2] <= 5
+ && gBattleMons[gBankAttacker].type1 != gTypeEffectiveness[type + 1]
+ && gBattleMons[gBankAttacker].type2 != gTypeEffectiveness[type + 1])
+ {
+ gBattleMons[gBankAttacker].type1 = gTypeEffectiveness[rands + 1];
+ gBattleMons[gBankAttacker].type2 = gTypeEffectiveness[rands + 1];
+
+ PREPARE_TYPE_BUFFER(gBattleTextBuff1, gTypeEffectiveness[rands + 1])
+
+ gBattlescriptCurrInstr += 5;
+ return;
+ }
+ }
+ type += 3, rands += 3;
+ } while (rands < 336);
+
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+#else
+__attribute__((naked))
+static void atkA6_settypetorandomresistance(void) // conversion 2
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ ldr r1, =gUnknown_02024250\n\
+ ldr r4, =gBankAttacker\n\
+ ldrb r0, [r4]\n\
+ lsls r0, 1\n\
+ adds r2, r0, r1\n\
+ ldrh r1, [r2]\n\
+ cmp r1, 0\n\
+ beq _08052B7E\n\
+ ldr r0, =0x0000ffff\n\
+ cmp r1, r0\n\
+ beq _08052B7E\n\
+ ldrh r0, [r2]\n\
+ bl IsTwoTurnsMove\n\
+ lsls r0, 24\n\
+ cmp r0, 0\n\
+ beq _08052C1C\n\
+ ldr r1, =gBattleMons\n\
+ ldr r2, =gUnknown_02024270\n\
+ ldrb r0, [r4]\n\
+ adds r0, r2\n\
+ ldrb r2, [r0]\n\
+ movs r0, 0x58\n\
+ muls r0, r2\n\
+ adds r1, 0x50\n\
+ adds r0, r1\n\
+ ldr r0, [r0]\n\
+ movs r1, 0x80\n\
+ lsls r1, 5\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ beq _08052C1C\n\
+_08052B7E:\n\
+ ldr r3, =gBattlescriptCurrInstr\n\
+ ldr r2, [r3]\n\
+ ldrb r1, [r2, 0x1]\n\
+ ldrb r0, [r2, 0x2]\n\
+ lsls r0, 8\n\
+ orrs r1, r0\n\
+ ldrb r0, [r2, 0x3]\n\
+ lsls r0, 16\n\
+ orrs r1, r0\n\
+ ldrb r0, [r2, 0x4]\n\
+ lsls r0, 24\n\
+ orrs r1, r0\n\
+ str r1, [r3]\n\
+ b _08052D08\n\
+ .pool\n\
+_08052BB4:\n\
+ mov r0, r12\n\
+ strb r5, [r0]\n\
+ mov r1, r10\n\
+ ldrb r0, [r1]\n\
+ muls r0, r2\n\
+ adds r0, r7\n\
+ adds r0, 0x22\n\
+ strb r5, [r0]\n\
+ ldr r1, =gBattleTextBuff1\n\
+ movs r0, 0xFD\n\
+ strb r0, [r1]\n\
+ movs r0, 0x3\n\
+ strb r0, [r1, 0x1]\n\
+ strb r5, [r1, 0x2]\n\
+ movs r0, 0xFF\n\
+ strb r0, [r1, 0x3]\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ b _08052C0A\n\
+ .pool\n\
+_08052BE0:\n\
+ mov r0, r8\n\
+ adds r0, 0x1\n\
+ adds r0, r3\n\
+ ldrb r2, [r0]\n\
+ strb r2, [r4]\n\
+ mov r4, r10\n\
+ ldrb r0, [r4]\n\
+ muls r0, r6\n\
+ ldr r7, =gBattleMons\n\
+ adds r0, r7\n\
+ adds r0, 0x22\n\
+ strb r2, [r0]\n\
+ ldr r1, =gBattleTextBuff1\n\
+ movs r0, 0xFD\n\
+ strb r0, [r1]\n\
+ movs r0, 0x3\n\
+ strb r0, [r1, 0x1]\n\
+ strb r2, [r1, 0x2]\n\
+ movs r0, 0xFF\n\
+ strb r0, [r1, 0x3]\n\
+ mov r1, r12\n\
+_08052C0A:\n\
+ ldr r0, [r1]\n\
+ adds r0, 0x5\n\
+ str r0, [r1]\n\
+ b _08052D08\n\
+ .pool\n\
+_08052C1C:\n\
+ movs r4, 0\n\
+ mov r8, r4\n\
+ movs r7, 0x7F\n\
+ mov r9, r7\n\
+_08052C24:\n\
+ bl Random\n\
+ mov r4, r9\n\
+ ands r4, r0\n\
+ cmp r4, 0x70\n\
+ bhi _08052C24\n\
+ lsls r0, r4, 1\n\
+ adds r4, r0, r4\n\
+ ldr r6, =gTypeEffectiveness\n\
+ adds r3, r4, r6\n\
+ ldr r1, =gUnknown_02024258\n\
+ ldr r2, =gBankAttacker\n\
+ ldrb r5, [r2]\n\
+ lsls r0, r5, 1\n\
+ adds r0, r1\n\
+ ldrb r1, [r3]\n\
+ mov r10, r2\n\
+ ldrh r0, [r0]\n\
+ cmp r1, r0\n\
+ bne _08052C80\n\
+ adds r0, r4, 0x2\n\
+ adds r0, r6\n\
+ ldrb r0, [r0]\n\
+ cmp r0, 0x5\n\
+ bhi _08052C80\n\
+ ldr r7, =gBattleMons\n\
+ movs r2, 0x58\n\
+ adds r0, r5, 0\n\
+ muls r0, r2\n\
+ adds r3, r0, r7\n\
+ movs r0, 0x21\n\
+ adds r0, r3\n\
+ mov r12, r0\n\
+ adds r0, r4, 0x1\n\
+ adds r0, r6\n\
+ ldrb r5, [r0]\n\
+ mov r1, r12\n\
+ ldrb r0, [r1]\n\
+ adds r1, r5, 0\n\
+ cmp r0, r1\n\
+ beq _08052C80\n\
+ adds r0, r3, 0\n\
+ adds r0, 0x22\n\
+ ldrb r0, [r0]\n\
+ cmp r0, r1\n\
+ bne _08052BB4\n\
+_08052C80:\n\
+ movs r7, 0x1\n\
+ add r8, r7\n\
+ ldr r0, =0x000003e7\n\
+ cmp r8, r0\n\
+ ble _08052C24\n\
+ movs r0, 0\n\
+ mov r8, r0\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ mov r12, r1\n\
+ ldr r3, =gTypeEffectiveness\n\
+ adds r0, r4, 0x1\n\
+ adds r0, r3\n\
+ mov r9, r0\n\
+ adds r5, r3, 0\n\
+_08052C9C:\n\
+ ldrb r1, [r5]\n\
+ cmp r1, 0xFF\n\
+ bgt _08052CA6\n\
+ cmp r1, 0xFE\n\
+ bge _08052CE0\n\
+_08052CA6:\n\
+ mov r4, r10\n\
+ ldrb r2, [r4]\n\
+ lsls r0, r2, 1\n\
+ ldr r7, =gUnknown_02024258\n\
+ adds r0, r7\n\
+ ldrh r0, [r0]\n\
+ cmp r1, r0\n\
+ bne _08052CE0\n\
+ ldrb r0, [r5, 0x2]\n\
+ cmp r0, 0x5\n\
+ bhi _08052CE0\n\
+ movs r6, 0x58\n\
+ adds r0, r2, 0\n\
+ muls r0, r6\n\
+ ldr r1, =gBattleMons\n\
+ adds r2, r0, r1\n\
+ adds r4, r2, 0\n\
+ adds r4, 0x21\n\
+ ldrb r0, [r4]\n\
+ mov r7, r9\n\
+ ldrb r1, [r7]\n\
+ cmp r0, r1\n\
+ beq _08052CE0\n\
+ adds r0, r2, 0\n\
+ adds r0, 0x22\n\
+ ldrb r0, [r0]\n\
+ cmp r0, r1\n\
+ beq _08052CE0\n\
+ b _08052BE0\n\
+_08052CE0:\n\
+ adds r5, 0x3\n\
+ movs r0, 0x3\n\
+ add r8, r0\n\
+ ldr r0, =0x0000014f\n\
+ cmp r8, r0\n\
+ bls _08052C9C\n\
+ mov r1, r12\n\
+ ldr r2, [r1]\n\
+ ldrb r1, [r2, 0x1]\n\
+ ldrb r0, [r2, 0x2]\n\
+ lsls r0, 8\n\
+ orrs r1, r0\n\
+ ldrb r0, [r2, 0x3]\n\
+ lsls r0, 16\n\
+ orrs r1, r0\n\
+ ldrb r0, [r2, 0x4]\n\
+ lsls r0, 24\n\
+ orrs r1, r0\n\
+ mov r4, r12\n\
+ str r1, [r4]\n\
+_08052D08:\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .pool\n\
+ .syntax divided");
+}
+#endif // NONMATCHING
+
+static void atkA7_setalwayshitflag(void)
+{
+ gStatuses3[gBankTarget] &= ~(STATUS3_ALWAYS_HITS);
+ gStatuses3[gBankTarget] |= 0x10;
+ gDisableStructs[gBankTarget].bankWithSureHit = gBankAttacker;
+ gBattlescriptCurrInstr++;
+}
+
+static void atkA8_copymovepermanently(void) // sketch
+{
+ gLastUsedMove = 0xFFFF;
+
+ if (!(gBattleMons[gBankAttacker].status2 & STATUS2_TRANSFORMED)
+ && gUnknownMovesUsedByBanks[gBankTarget] != MOVE_STRUGGLE
+ && gUnknownMovesUsedByBanks[gBankTarget] != 0
+ && gUnknownMovesUsedByBanks[gBankTarget] != 0xFFFF
+ && gUnknownMovesUsedByBanks[gBankTarget] != MOVE_SKETCH)
+ {
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gBattleMons[gBankAttacker].moves[i] == MOVE_SKETCH)
+ continue;
+ if (gBattleMons[gBankAttacker].moves[i] == gUnknownMovesUsedByBanks[gBankTarget])
+ break;
+ }
+
+ if (i != 4)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else // sketch worked
+ {
+ struct MovePpInfo movePpData;
+
+ gBattleMons[gBankAttacker].moves[gCurrMovePos] = gUnknownMovesUsedByBanks[gBankTarget];
+ gBattleMons[gBankAttacker].pp[gCurrMovePos] = gBattleMoves[gUnknownMovesUsedByBanks[gBankTarget]].pp;
+ gActiveBank = gBankAttacker;
+
+ for (i = 0; i < 4; i++)
+ {
+ movePpData.move[i] = gBattleMons[gBankAttacker].moves[i];
+ movePpData.pp[i] = gBattleMons[gBankAttacker].pp[i];
+ }
+ movePpData.ppBonuses = gBattleMons[gBankAttacker].ppBonuses;
+
+ EmitSetMonData(0, REQUEST_MOVES_PP_BATTLE, 0, sizeof(struct MovePpInfo), &movePpData);
+ MarkBufferBankForExecution(gActiveBank);
+
+ PREPARE_MOVE_BUFFER(gBattleTextBuff1, gUnknownMovesUsedByBanks[gBankTarget])
+
+ gBattlescriptCurrInstr += 5;
+ }
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static bool8 IsTwoTurnsMove(u16 move)
+{
+ if (gBattleMoves[move].effect == EFFECT_SKULL_BASH
+ || gBattleMoves[move].effect == EFFECT_RAZOR_WIND
+ || gBattleMoves[move].effect == EFFECT_SKY_ATTACK
+ || gBattleMoves[move].effect == EFFECT_SOLARBEAM
+ || gBattleMoves[move].effect == EFFECT_FLY
+ || gBattleMoves[move].effect == EFFECT_BIDE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static bool8 IsInvalidForSleepTalkOrAssist(u16 move)
+{
+ if (move == 0 || move == MOVE_SLEEP_TALK || move == MOVE_ASSIST
+ || move == MOVE_MIRROR_MOVE || move == MOVE_METRONOME)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static u8 AttacksThisTurn(u8 bank, u16 move) // Note: returns 1 if it's a charging turn, otherwise 2
+{
+ // first argument is unused
+ if (gBattleMoves[move].effect == EFFECT_SOLARBEAM
+ && (gBattleWeather & WEATHER_SUN_ANY))
+ return 2;
+
+ if (gBattleMoves[move].effect == EFFECT_SKULL_BASH
+ || gBattleMoves[move].effect == EFFECT_RAZOR_WIND
+ || gBattleMoves[move].effect == EFFECT_SKY_ATTACK
+ || gBattleMoves[move].effect == EFFECT_SOLARBEAM
+ || gBattleMoves[move].effect == EFFECT_FLY
+ || gBattleMoves[move].effect == EFFECT_BIDE)
+ {
+ if ((gHitMarker & HITMARKER_x8000000))
+ return 1;
+ }
+ return 2;
+}
+
+static void atkA9_sleeptalk_choose_move(void)
+{
+ s32 i;
+ u8 unusableMovesBits = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (IsInvalidForSleepTalkOrAssist(gBattleMons[gBankAttacker].moves[i])
+ || gBattleMons[gBankAttacker].moves[i] == MOVE_FOCUS_PUNCH
+ || gBattleMons[gBankAttacker].moves[i] == MOVE_UPROAR
+ || IsTwoTurnsMove(gBattleMons[gBankAttacker].moves[i]))
+ {
+ unusableMovesBits |= gBitTable[i];
+ }
+
+ }
+
+ unusableMovesBits = CheckMoveLimitations(gBankAttacker, unusableMovesBits, ~(MOVE_LIMITATION_PP));
+ if (unusableMovesBits == 0xF) // all 4 moves cannot be chosen
+ {
+ gBattlescriptCurrInstr += 5;
+ }
+ else // at least one move can be chosen
+ {
+ u32 movePosition;
+
+ do
+ {
+ movePosition = Random() & 3;
+ } while ((gBitTable[movePosition] & unusableMovesBits));
+
+ gRandomMove = gBattleMons[gBankAttacker].moves[movePosition];
+ gCurrMovePos = movePosition;
+ gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
+ gBankTarget = GetMoveTarget(gRandomMove, 0);
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkAA_set_destinybond(void)
+{
+ gBattleMons[gBankAttacker].status2 |= STATUS2_DESTINY_BOND;
+ gBattlescriptCurrInstr++;
+}
+
+static void DestinyBondFlagUpdate(void)
+{
+ u8 sideAttacker = GetBankSide(gBankAttacker);
+ u8 sideTarget = GetBankSide(gBankTarget);
+ if (gBattleMons[gBankTarget].status2 & STATUS2_DESTINY_BOND
+ && sideAttacker != sideTarget
+ && !(gHitMarker & HITMARKER_GRUDGE))
+ {
+ gHitMarker |= HITMARKER_DESTINYBOND;
+ }
+}
+
+static void atkAB_DestinyBondFlagUpdate(void)
+{
+ DestinyBondFlagUpdate();
+ gBattlescriptCurrInstr++;
+}
+
+static void atkAC_remaininghptopower(void)
+{
+ s32 i;
+ s32 hpFraction = GetScaledHPFraction(gBattleMons[gBankAttacker].hp, gBattleMons[gBankAttacker].maxHP, 48);
+
+ for (i = 0; i < (s32) sizeof(sFlailHpScaleToPowerTable); i += 2)
+ {
+ if (hpFraction <= sFlailHpScaleToPowerTable[i])
+ break;
+ }
+
+ gDynamicBasePower = sFlailHpScaleToPowerTable[i + 1];
+ gBattlescriptCurrInstr++;
+}
+
+static void atkAD_spite_ppreduce(void)
+{
+ if (gLastUsedMovesByBanks[gBankTarget] != 0
+ && gLastUsedMovesByBanks[gBankTarget] != 0xFFFF)
+ {
+ s32 i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (gLastUsedMovesByBanks[gBankTarget] == gBattleMons[gBankTarget].moves[i])
+ break;
+ }
+
+ if (i != 4 && gBattleMons[gBankTarget].pp[i] > 1)
+ {
+ s32 ppToDeduct = (Random() & 3) + 2;
+ if (gBattleMons[gBankTarget].pp[i] < ppToDeduct)
+ ppToDeduct = gBattleMons[gBankTarget].pp[i];
+
+ PREPARE_MOVE_BUFFER(gBattleTextBuff1, gLastUsedMovesByBanks[gBankTarget])
+
+ ConvertIntToDecimalStringN(gBattleTextBuff2, ppToDeduct, 0, 1);
+
+ PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff2, 1, ppToDeduct)
+
+ gBattleMons[gBankTarget].pp[i] -= ppToDeduct;
+ gActiveBank = gBankTarget;
+
+ if (!(gDisableStructs[gActiveBank].unk18_b & gBitTable[i])
+ && !(gBattleMons[gActiveBank].status2 & STATUS2_TRANSFORMED))
+ {
+ EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + i, 0, 1, &gBattleMons[gActiveBank].pp[i]);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+
+ gBattlescriptCurrInstr += 5;
+
+ if (gBattleMons[gBankTarget].pp[i] == 0)
+ CancelMultiTurnMoves(gBankTarget);
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkAE_heal_party_status(void)
+{
+ u32 zero = 0;
+ u8 toHeal = 0;
+
+ if (gCurrentMove == MOVE_HEAL_BELL)
+ {
+ struct Pokemon* party;
+ s32 i;
+
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ party = gPlayerParty;
+ else
+ party = gEnemyParty;
+
+ if (gBattleMons[gBankAttacker].ability != ABILITY_SOUNDPROOF)
+ {
+ gBattleMons[gBankAttacker].status1 = 0;
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE);
+ }
+ else
+ {
+ RecordAbilityBattle(gBankAttacker, gBattleMons[gBankAttacker].ability);
+ gBattleCommunication[MULTISTRING_CHOOSER] |= 1;
+ }
+
+ gActiveBank = gBattleScripting.bank = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ BIT_MON);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
+ && !(gAbsentBankFlags & gBitTable[gActiveBank]))
+ {
+ if (gBattleMons[gActiveBank].ability != ABILITY_SOUNDPROOF)
+ {
+ gBattleMons[gActiveBank].status1 = 0;
+ gBattleMons[gActiveBank].status2 &= ~(STATUS2_NIGHTMARE);
+ }
+ else
+ {
+ RecordAbilityBattle(gActiveBank, gBattleMons[gActiveBank].ability);
+ gBattleCommunication[MULTISTRING_CHOOSER] |= 2;
+ }
+ }
+
+ for (i = 0; i < 6; i++)
+ {
+ u16 species = GetMonData(&party[i], MON_DATA_SPECIES2);
+ u8 abilityBit = GetMonData(&party[i], MON_DATA_ALT_ABILITY);
+
+ if (species != 0 && species != SPECIES_EGG)
+ {
+ u8 ability;
+
+ if (gBattlePartyID[gBankAttacker] == i)
+ ability = gBattleMons[gBankAttacker].ability;
+ else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
+ && gBattlePartyID[gActiveBank] == i
+ && !(gAbsentBankFlags & gBitTable[gActiveBank]))
+ ability = gBattleMons[gActiveBank].ability;
+ else
+ ability = GetAbilityBySpecies(species, abilityBit);
+
+ if (ability != ABILITY_SOUNDPROOF)
+ toHeal |= (1 << i);
+ }
+ }
+ }
+ else // Aromatherapy
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 4;
+ toHeal = 0x3F;
+
+ gBattleMons[gBankAttacker].status1 = 0;
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_NIGHTMARE);
+
+ gActiveBank = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ 2);
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
+ && !(gAbsentBankFlags & gBitTable[gActiveBank]))
+ {
+ gBattleMons[gActiveBank].status1 = 0;
+ gBattleMons[gActiveBank].status2 &= ~(STATUS2_NIGHTMARE);
+ }
+
+ }
+
+ if (toHeal)
+ {
+ gActiveBank = gBankAttacker;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, toHeal, 4, &zero);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkAF_cursetarget(void)
+{
+ if (gBattleMons[gBankTarget].status2 & STATUS2_CURSED)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gBattleMons[gBankTarget].status2 |= STATUS2_CURSED;
+ gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 2;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkB0_set_spikes(void)
+{
+ u8 targetSide = GetBankSide(gBankAttacker) ^ BIT_SIDE;
+
+ if (gSideTimers[targetSide].spikesAmount == 3)
+ {
+ gSpecialStatuses[gBankAttacker].flag20 = 1;
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gSideAffecting[targetSide] |= SIDE_STATUS_SPIKES;
+ gSideTimers[targetSide].spikesAmount++;
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkB1_set_foresight(void)
+{
+ gBattleMons[gBankTarget].status2 |= STATUS2_FORESIGHT;
+ gBattlescriptCurrInstr++;
+}
+
+static void atkB2_setperishsong(void)
+{
+ s32 i;
+ s32 notAffectedCount = 0;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gStatuses3[i] & STATUS3_PERISH_SONG
+ || gBattleMons[i].ability == ABILITY_SOUNDPROOF)
+ {
+ notAffectedCount++;
+ }
+ else
+ {
+ gStatuses3[i] |= STATUS3_PERISH_SONG;
+ gDisableStructs[i].perishSong1 = 3;
+ gDisableStructs[i].perishSong2 = 3;
+ }
+ }
+
+ PressurePPLoseOnUsingPerishSong(gBankAttacker);
+
+ if (notAffectedCount == gNoOfAllBanks)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ else
+ gBattlescriptCurrInstr += 5;
+}
+
+static void atkB3_rolloutdamagecalculation(void)
+{
+ if (gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ {
+ CancelMultiTurnMoves(gBankAttacker);
+ gBattlescriptCurrInstr = BattleScript_PauseEffectivenessSoundResultMsgEndMove;
+ }
+ else
+ {
+ s32 i;
+
+ if (!(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS)) // first hit
+ {
+ gDisableStructs[gBankAttacker].rolloutTimer1 = 5;
+ gDisableStructs[gBankAttacker].rolloutTimer2 = 5;
+ gBattleMons[gBankAttacker].status2 |= STATUS2_MULTIPLETURNS;
+ gLockedMoves[gBankAttacker] = gCurrentMove;
+ }
+ if (--gDisableStructs[gBankAttacker].rolloutTimer1 == 0) // last hit
+ {
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_MULTIPLETURNS);
+ }
+
+ gDynamicBasePower = gBattleMoves[gCurrentMove].power;
+
+ for (i = 1; i < (5 - gDisableStructs[gBankAttacker].rolloutTimer1); i++)
+ gDynamicBasePower *= 2;
+
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_DEFENSE_CURL)
+ gDynamicBasePower *= 2;
+
+ gBattlescriptCurrInstr++;
+ }
+}
+
+static void atkB4_jumpifconfusedandstatmaxed(void)
+{
+ if (gBattleMons[gBankTarget].status2 & STATUS2_CONFUSION
+ && gBattleMons[gBankTarget].statStages[gBattlescriptCurrInstr[1]] == 0xC)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ else
+ gBattlescriptCurrInstr += 6;
+}
+
+static void atkB5_furycuttercalc(void)
+{
+ if (gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ {
+ gDisableStructs[gBankAttacker].furyCutterCounter = 0;
+ gBattlescriptCurrInstr = BattleScript_PauseEffectivenessSoundResultMsgEndMove;
+ }
+ else
+ {
+ s32 i;
+
+ if (gDisableStructs[gBankAttacker].furyCutterCounter != 5)
+ gDisableStructs[gBankAttacker].furyCutterCounter++;
+
+ gDynamicBasePower = gBattleMoves[gCurrentMove].power;
+
+ for (i = 1; i < gDisableStructs[gBankAttacker].furyCutterCounter; i++)
+ gDynamicBasePower *= 2;
+
+ gBattlescriptCurrInstr++;
+ }
+}
+
+static void atkB6_happinesstodamagecalculation(void)
+{
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_RETURN)
+ gDynamicBasePower = 10 * (gBattleMons[gBankAttacker].friendship) / 25;
+ else // EFFECT_FRUSTRATION
+ gDynamicBasePower = 10 * (255 - gBattleMons[gBankAttacker].friendship) / 25;
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkB7_presentdamagecalculation(void)
+{
+ s32 rand = Random() & 0xFF;
+
+ if (rand < 102)
+ gDynamicBasePower = 40;
+ else if (rand < 178)
+ gDynamicBasePower = 80;
+ else if (rand < 204)
+ gDynamicBasePower = 120;
+ else
+ {
+ gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 4;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ gBattleMoveDamage *= -1;
+ }
+ if (rand < 204)
+ gBattlescriptCurrInstr = BattleScript_PresentDamageTarget;
+ else if (gBattleMons[gBankTarget].maxHP == gBattleMons[gBankTarget].hp)
+ gBattlescriptCurrInstr = BattleScript_AlreadyAtFullHp;
+ else
+ {
+ gBattleMoveFlags &= ~(MOVESTATUS_NOTAFFECTED);
+ gBattlescriptCurrInstr = BattleScript_PresentHealTarget;
+ }
+}
+
+static void atkB8_set_safeguard(void)
+{
+ if (gSideAffecting[GET_BANK_SIDE(gBankAttacker)] & SIDE_STATUS_SAFEGUARD)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ }
+ else
+ {
+ gSideAffecting[GET_BANK_SIDE(gBankAttacker)] |= SIDE_STATUS_SAFEGUARD;
+ gSideTimers[GET_BANK_SIDE(gBankAttacker)].safeguardTimer = 5;
+ gSideTimers[GET_BANK_SIDE(gBankAttacker)].safeguardBank = gBankAttacker;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 5;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkB9_magnitudedamagecalculation(void)
+{
+ s32 magnitude = Random() % 100;
+
+ if (magnitude < 5)
+ {
+ gDynamicBasePower = 10;
+ magnitude = 4;
+ }
+ else if (magnitude < 15)
+ {
+ gDynamicBasePower = 30;
+ magnitude = 5;
+ }
+ else if (magnitude < 35)
+ {
+ gDynamicBasePower = 50;
+ magnitude = 6;
+ }
+ else if (magnitude < 65)
+ {
+ gDynamicBasePower = 70;
+ magnitude = 7;
+ }
+ else if (magnitude < 85)
+ {
+ gDynamicBasePower = 90;
+ magnitude = 8;
+ }
+ else if (magnitude < 95)
+ {
+ gDynamicBasePower = 110;
+ magnitude = 9;
+ }
+ else
+ {
+ gDynamicBasePower = 150;
+ magnitude = 10;
+ }
+
+
+ PREPARE_BYTE_NUMBER_BUFFER(gBattleTextBuff1, 2, magnitude)
+
+ for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++)
+ {
+ if (gBankTarget == gBankAttacker)
+ continue;
+ if (!(gAbsentBankFlags & gBitTable[gBankTarget])) // a valid target was found
+ break;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkBA_jumpifnopursuitswitchdmg(void)
+{
+ if (gMultiHitCounter == 1)
+ {
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ gBankTarget = GetBankByIdentity(IDENTITY_OPPONENT_MON1);
+ else
+ gBankTarget = GetBankByIdentity(IDENTITY_PLAYER_MON1);
+ }
+ else
+ {
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ gBankTarget = GetBankByIdentity(IDENTITY_OPPONENT_MON2);
+ else
+ gBankTarget = GetBankByIdentity(IDENTITY_PLAYER_MON2);
+ }
+
+ if (gActionForBanks[gBankTarget] == 0
+ && gBankAttacker == *(gBattleStruct->moveTarget + gBankTarget)
+ && !(gBattleMons[gBankTarget].status1 & (STATUS_SLEEP | STATUS_FREEZE))
+ && gBattleMons[gBankAttacker].hp
+ && !gDisableStructs[gBankTarget].truantCounter
+ && gChosenMovesByBanks[gBankTarget] == MOVE_PURSUIT)
+ {
+ s32 i;
+
+ for (i = 0; i < gNoOfAllBanks; i++)
+ {
+ if (gTurnOrder[i] == gBankTarget)
+ gUnknown_0202407A[i] = 11;
+ }
+
+ gCurrentMove = MOVE_PURSUIT;
+ gCurrMovePos = gUnknown_020241E9 = *(gBattleStruct->chosenMovesIds + gBankTarget);
+ gBattlescriptCurrInstr += 5;
+ gBattleScripting.animTurn = 1;
+ gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkBB_setsunny(void)
+{
+ if (gBattleWeather & WEATHER_SUN_ANY)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ }
+ else
+ {
+ gBattleWeather = WEATHER_SUN_TEMPORARY;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 4;
+ gWishFutureKnock.weatherDuration = 5;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkBC_maxattackhalvehp(void) // belly drum
+{
+ u32 halfHp = gBattleMons[gBankAttacker].maxHP / 2;
+
+ if (!(gBattleMons[gBankAttacker].maxHP / 2))
+ halfHp = 1;
+
+ if (gBattleMons[gBankAttacker].statStages[STAT_STAGE_ATK] < 12
+ && gBattleMons[gBankAttacker].hp > halfHp)
+ {
+ gBattleMons[gBankAttacker].statStages[STAT_STAGE_ATK] = 12;
+ gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 2;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkBD_copyfoestats(void) // psych up
+{
+ s32 i;
+
+ for (i = 0; i < BATTLE_STATS_NO; i++)
+ {
+ gBattleMons[gBankAttacker].statStages[i] = gBattleMons[gBankTarget].statStages[i];
+ }
+
+ gBattlescriptCurrInstr += 5; // Has an unused jump ptr(possibly for a failed attempt) parameter.
+}
+
+static void atkBE_rapidspinfree(void)
+{
+ if (gBattleMons[gBankAttacker].status2 & STATUS2_WRAPPED)
+ {
+ gBattleScripting.bank = gBankTarget;
+ gBattleMons[gBankAttacker].status2 &= ~(STATUS2_WRAPPED);
+ gBankTarget = *(gBattleStruct->wrappedBy + gBankAttacker);
+
+ gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN;
+ gBattleTextBuff1[1] = B_BUFF_MOVE;
+ gBattleTextBuff1[2] = *(gBattleStruct->wrappedMove + gBankAttacker * 2 + 0);
+ gBattleTextBuff1[3] = *(gBattleStruct->wrappedMove + gBankAttacker * 2 + 1);
+ gBattleTextBuff1[4] = B_BUFF_EOS;
+
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_WrapFree;
+ }
+ else if (gStatuses3[gBankAttacker] & STATUS3_LEECHSEED)
+ {
+ gStatuses3[gBankAttacker] &= ~(STATUS3_LEECHSEED);
+ gStatuses3[gBankAttacker] &= ~(STATUS3_LEECHSEED_BANK);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_LeechSeedFree;
+ }
+ else if (gSideAffecting[GetBankSide(gBankAttacker)] & SIDE_STATUS_SPIKES)
+ {
+ gSideAffecting[GetBankSide(gBankAttacker)] &= ~(SIDE_STATUS_SPIKES);
+ gSideTimers[GetBankSide(gBankAttacker)].spikesAmount = 0;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_SpikesFree;
+ }
+ else
+ {
+ gBattlescriptCurrInstr++;
+ }
+}
+
+static void atkBF_set_defense_curl(void)
+{
+ gBattleMons[gBankAttacker].status2 |= STATUS2_DEFENSE_CURL;
+ gBattlescriptCurrInstr++;
+}
+
+static void atkC0_recoverbasedonsunlight(void)
+{
+ gBankTarget = gBankAttacker;
+
+ if (gBattleMons[gBankAttacker].hp != gBattleMons[gBankAttacker].maxHP)
+ {
+ if (gBattleWeather == 0 || !WEATHER_HAS_EFFECT)
+ gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 2;
+ else if (gBattleWeather & WEATHER_SUN_ANY)
+ gBattleMoveDamage = 20 * gBattleMons[gBankAttacker].maxHP / 30;
+ else // not sunny weather
+ gBattleMoveDamage = gBattleMons[gBankAttacker].maxHP / 4;
+
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ gBattleMoveDamage *= -1;
+
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+#ifdef NONMATCHING
+static void atkC1_hidden_power(void)
+{
+ s32 powerBits;
+ s32 typeBits;
+
+ powerBits = ((gBattleMons[gBankAttacker].hpIV & 2) >> 1)
+ | ((gBattleMons[gBankAttacker].attackIV & 2) << 0)
+ | ((gBattleMons[gBankAttacker].defenseIV & 2) << 1)
+ | ((gBattleMons[gBankAttacker].speedIV & 2) << 2)
+ | ((gBattleMons[gBankAttacker].spAttackIV & 2) << 3)
+ | ((gBattleMons[gBankAttacker].spDefenseIV & 2) << 4);
+
+ typeBits = ((gBattleMons[gBankAttacker].hpIV & 1) << 0)
+ | ((gBattleMons[gBankAttacker].attackIV & 1) << 1)
+ | ((gBattleMons[gBankAttacker].defenseIV & 1) << 2)
+ | ((gBattleMons[gBankAttacker].speedIV & 1) << 3)
+ | ((gBattleMons[gBankAttacker].spAttackIV & 1) << 4)
+ | ((gBattleMons[gBankAttacker].spDefenseIV & 1) << 5);
+
+ gDynamicBasePower = (40 * powerBits) / 63 + 30;
+
+ gBattleStruct->dynamicMoveType = (15 * typeBits) / 63 + 1;
+ if (gBattleStruct->dynamicMoveType > 8)
+ gBattleStruct->dynamicMoveType++;
+ gBattleStruct->dynamicMoveType |= 0xC0;
+
+ gBattlescriptCurrInstr++;
+}
+
+#else
+__attribute__((naked))
+static void atkC1_hidden_power(void)
+{
+ asm(".syntax unified\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ ldr r2, =gBattleMons\n\
+ ldr r0, =gBankAttacker\n\
+ ldrb r1, [r0]\n\
+ movs r0, 0x58\n\
+ adds r4, r1, 0\n\
+ muls r4, r0\n\
+ adds r4, r2\n\
+ ldrb r0, [r4, 0x14]\n\
+ mov r10, r0\n\
+ mov r7, r10\n\
+ lsls r7, 27\n\
+ adds r0, r7, 0\n\
+ lsrs r0, 27\n\
+ mov r10, r0\n\
+ movs r1, 0x2\n\
+ mov r2, r10\n\
+ ands r2, r1\n\
+ asrs r2, 1\n\
+ ldrh r7, [r4, 0x14]\n\
+ mov r9, r7\n\
+ mov r0, r9\n\
+ lsls r0, 22\n\
+ mov r9, r0\n\
+ lsrs r3, r0, 27\n\
+ adds r0, r1, 0\n\
+ ands r0, r3\n\
+ orrs r2, r0\n\
+ ldrb r7, [r4, 0x15]\n\
+ mov r8, r7\n\
+ mov r0, r8\n\
+ lsls r0, 25\n\
+ mov r8, r0\n\
+ lsrs r3, r0, 27\n\
+ adds r0, r1, 0\n\
+ ands r0, r3\n\
+ lsls r0, 1\n\
+ orrs r2, r0\n\
+ ldr r6, [r4, 0x14]\n\
+ lsls r6, 12\n\
+ lsrs r3, r6, 27\n\
+ adds r0, r1, 0\n\
+ ands r0, r3\n\
+ lsls r0, 2\n\
+ orrs r2, r0\n\
+ ldrh r5, [r4, 0x16]\n\
+ lsls r5, 23\n\
+ lsrs r3, r5, 27\n\
+ adds r0, r1, 0\n\
+ ands r0, r3\n\
+ lsls r0, 3\n\
+ orrs r2, r0\n\
+ ldrb r3, [r4, 0x17]\n\
+ lsls r3, 26\n\
+ lsrs r0, r3, 27\n\
+ ands r1, r0\n\
+ lsls r1, 4\n\
+ orrs r2, r1\n\
+ movs r1, 0x1\n\
+ adds r4, r1, 0\n\
+ mov r7, r10\n\
+ ands r4, r7\n\
+ mov r0, r9\n\
+ lsrs r0, 27\n\
+ mov r9, r0\n\
+ adds r0, r1, 0\n\
+ mov r7, r9\n\
+ ands r0, r7\n\
+ lsls r0, 1\n\
+ orrs r4, r0\n\
+ mov r0, r8\n\
+ lsrs r0, 27\n\
+ mov r8, r0\n\
+ adds r0, r1, 0\n\
+ mov r7, r8\n\
+ ands r0, r7\n\
+ lsls r0, 2\n\
+ orrs r4, r0\n\
+ lsrs r6, 27\n\
+ adds r0, r1, 0\n\
+ ands r0, r6\n\
+ lsls r0, 3\n\
+ orrs r4, r0\n\
+ lsrs r5, 27\n\
+ adds r0, r1, 0\n\
+ ands r0, r5\n\
+ lsls r0, 4\n\
+ orrs r4, r0\n\
+ lsrs r3, 27\n\
+ ands r1, r3\n\
+ lsls r1, 5\n\
+ orrs r4, r1\n\
+ ldr r5, =gDynamicBasePower\n\
+ lsls r0, r2, 2\n\
+ adds r0, r2\n\
+ lsls r0, 3\n\
+ movs r1, 0x3F\n\
+ bl __divsi3\n\
+ adds r0, 0x1E\n\
+ strh r0, [r5]\n\
+ ldr r6, =gBattleStruct\n\
+ ldr r5, [r6]\n\
+ lsls r0, r4, 4\n\
+ subs r0, r4\n\
+ movs r1, 0x3F\n\
+ bl __divsi3\n\
+ adds r0, 0x1\n\
+ strb r0, [r5, 0x13]\n\
+ ldr r1, [r6]\n\
+ ldrb r0, [r1, 0x13]\n\
+ cmp r0, 0x8\n\
+ bls _080544F0\n\
+ adds r0, 0x1\n\
+ strb r0, [r1, 0x13]\n\
+_080544F0:\n\
+ ldr r2, [r6]\n\
+ ldrb r0, [r2, 0x13]\n\
+ movs r1, 0xC0\n\
+ orrs r0, r1\n\
+ strb r0, [r2, 0x13]\n\
+ ldr r1, =gBattlescriptCurrInstr\n\
+ ldr r0, [r1]\n\
+ adds r0, 0x1\n\
+ str r0, [r1]\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .pool\n\
+ .syntax divided");
+}
+#endif // NONMATCHING
+
+static void atkC2_selectnexttarget(void)
+{
+ for (gBankTarget = 0; gBankTarget < gNoOfAllBanks; gBankTarget++)
+ {
+ if (gBankTarget == gBankAttacker)
+ continue;
+ if (!(gAbsentBankFlags & gBitTable[gBankTarget]))
+ break;
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atkC3_setfutureattack(void)
+{
+ if (gWishFutureKnock.futureSightCounter[gBankTarget] != 0)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gSideAffecting[GET_BANK_SIDE(gBankTarget)] |= SIDE_STATUS_FUTUREATTACK;
+ gWishFutureKnock.futureSightMove[gBankTarget] = gCurrentMove;
+ gWishFutureKnock.futureSightAttacker[gBankTarget] = gBankAttacker;
+ gWishFutureKnock.futureSightCounter[gBankTarget] = 3;
+ gWishFutureKnock.futureSightDmg[gBankTarget] = CalculateBaseDamage(&gBattleMons[gBankAttacker], &gBattleMons[gBankTarget], gCurrentMove,
+ gSideAffecting[GET_BANK_SIDE(gBankTarget)], 0,
+ 0, gBankAttacker, gBankTarget);
+
+ if (gProtectStructs[gBankAttacker].helpingHand)
+ gWishFutureKnock.futureSightDmg[gBankTarget] = gWishFutureKnock.futureSightDmg[gBankTarget] * 15 / 10;
+
+ if (gCurrentMove == MOVE_DOOM_DESIRE)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkC4_beat_up(void)
+{
+ struct Pokemon* party;
+
+ if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
+ party = gPlayerParty;
+ else
+ party = gEnemyParty;
+
+ if (gBattleMons[gBankTarget].hp == 0)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ u8 beforeLoop = gBattleCommunication[0];
+ for (;gBattleCommunication[0] < 6; gBattleCommunication[0]++)
+ {
+ if (GetMonData(&party[gBattleCommunication[0]], MON_DATA_HP)
+ && GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES2)
+ && GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES2) != SPECIES_EGG
+ && !GetMonData(&party[gBattleCommunication[0]], MON_DATA_STATUS))
+ break;
+ }
+ if (gBattleCommunication[0] < 6)
+ {
+ PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBankAttacker, gBattleCommunication[0])
+
+ gBattlescriptCurrInstr += 9;
+
+ gBattleMoveDamage = gBaseStats[GetMonData(&party[gBattleCommunication[0]], MON_DATA_SPECIES)].baseAttack;
+ gBattleMoveDamage *= gBattleMoves[gCurrentMove].power;
+ gBattleMoveDamage *= (GetMonData(&party[gBattleCommunication[0]], MON_DATA_LEVEL) * 2 / 5 + 2);
+ gBattleMoveDamage /= gBaseStats[gBattleMons[gBankTarget].species].baseDefense;
+ gBattleMoveDamage = (gBattleMoveDamage / 50) + 2;
+ if (gProtectStructs[gBankAttacker].helpingHand)
+ gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
+
+ gBattleCommunication[0]++;
+ }
+ else if (beforeLoop != 0)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ else
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 5);
+ }
+}
+
+static void atkC5_setsemiinvulnerablebit(void)
+{
+ switch (gCurrentMove)
+ {
+ case MOVE_FLY:
+ case MOVE_BOUNCE:
+ gStatuses3[gBankAttacker] |= STATUS3_ON_AIR;
+ break;
+ case MOVE_DIG:
+ gStatuses3[gBankAttacker] |= STATUS3_UNDERGROUND;
+ break;
+ case MOVE_DIVE:
+ gStatuses3[gBankAttacker] |= STATUS3_UNDERWATER;
+ break;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkC6_clearsemiinvulnerablebit(void)
+{
+ switch (gCurrentMove)
+ {
+ case MOVE_FLY:
+ case MOVE_BOUNCE:
+ gStatuses3[gBankAttacker] &= ~STATUS3_ON_AIR;
+ break;
+ case MOVE_DIG:
+ gStatuses3[gBankAttacker] &= ~STATUS3_UNDERGROUND;
+ break;
+ case MOVE_DIVE:
+ gStatuses3[gBankAttacker] &= ~STATUS3_UNDERWATER;
+ break;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkC7_setminimize(void)
+{
+ if (gHitMarker & HITMARKER_OBEYS)
+ gStatuses3[gBankAttacker] |= STATUS3_MINIMIZED;
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkC8_sethail(void)
+{
+ if (gBattleWeather & WEATHER_HAIL_ANY)
+ {
+ gBattleMoveFlags |= MOVESTATUS_MISSED;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ }
+ else
+ {
+ gBattleWeather = WEATHER_HAIL;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 5;
+ gWishFutureKnock.weatherDuration = 5;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkC9_jumpifattackandspecialattackcannotfall(void) // memento
+{
+ if (gBattleMons[gBankTarget].statStages[STAT_STAGE_ATK] == 0
+ && gBattleMons[gBankTarget].statStages[STAT_STAGE_SPATK] == 0
+ && gBattleCommunication[6] != 1)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gActiveBank = gBankAttacker;
+ gBattleMoveDamage = gBattleMons[gActiveBank].hp;
+ EmitHealthBarUpdate(0, 0x7FFF);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkCA_setforcedtarget(void) // follow me
+{
+ gSideTimers[GetBankSide(gBankAttacker)].followmeTimer = 1;
+ gSideTimers[GetBankSide(gBankAttacker)].followmeTarget = gBankAttacker;
+ gBattlescriptCurrInstr++;
+}
+
+static void atkCB_setcharge(void)
+{
+ gStatuses3[gBankAttacker] |= STATUS3_CHARGED_UP;
+ gDisableStructs[gBankAttacker].chargeTimer1 = 2;
+ gDisableStructs[gBankAttacker].chargeTimer2 = 2;
+ gBattlescriptCurrInstr++;
+}
+
+static void atkCC_callterrainattack(void) // nature power
+{
+ gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
+ gCurrentMove = sNaturePowerMoves[gBattleTerrain];
+ gBankTarget = GetMoveTarget(gCurrentMove, 0);
+ BattleScriptPush(gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]);
+ gBattlescriptCurrInstr++;
+}
+
+static void atkCD_cureifburnedparalysedorpoisoned(void) // refresh
+{
+ if (gBattleMons[gBankAttacker].status1 & (STATUS_POISON | STATUS_BURN | STATUS_PARALYSIS | STATUS_TOXIC_POISON))
+ {
+ gBattleMons[gBankAttacker].status1 = 0;
+ gBattlescriptCurrInstr += 5;
+ gActiveBank = gBankAttacker;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkCE_settorment(void)
+{
+ if (gBattleMons[gBankTarget].status2 & STATUS2_TORMENT)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gBattleMons[gBankTarget].status2 |= STATUS2_TORMENT;
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkCF_jumpifnodamage(void)
+{
+ if (gProtectStructs[gBankAttacker].physicalDmg || gProtectStructs[gBankAttacker].specialDmg)
+ gBattlescriptCurrInstr += 5;
+ else
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+}
+
+static void atkD0_settaunt(void)
+{
+ if (gDisableStructs[gBankTarget].tauntTimer1 == 0)
+ {
+ gDisableStructs[gBankTarget].tauntTimer1 = 2;
+ gDisableStructs[gBankTarget].tauntTimer2 = 2;
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkD1_set_helpinghand(void)
+{
+ gBankTarget = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ BIT_MON);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
+ && !(gAbsentBankFlags & gBitTable[gBankTarget])
+ && !gProtectStructs[gBankAttacker].helpingHand
+ && !gProtectStructs[gBankTarget].helpingHand)
+ {
+ gProtectStructs[gBankTarget].helpingHand = 1;
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkD2_swap_items(void) // trick
+{
+ // opponent can't swap items with player in regular battles
+ if (gBattleTypeFlags & BATTLE_TYPE_x4000000
+ || (GetBankSide(gBankAttacker) == SIDE_OPPONENT
+ && !(gBattleTypeFlags & (BATTLE_TYPE_LINK
+ | BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_FRONTIER
+ | BATTLE_TYPE_SECRET_BASE
+ | BATTLE_TYPE_x2000000))))
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ u8 sideAttacker = GetBankSide(gBankAttacker);
+ u8 sideTarget = GetBankSide(gBankTarget);
+
+ // you can't swap items if they were knocked off in regular battles
+ if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK
+ | BATTLE_TYPE_EREADER_TRAINER
+ | BATTLE_TYPE_FRONTIER
+ | BATTLE_TYPE_SECRET_BASE
+ | BATTLE_TYPE_x2000000))
+ && (gWishFutureKnock.knockedOffPokes[sideAttacker] & gBitTable[gBattlePartyID[gBankAttacker]]
+ || gWishFutureKnock.knockedOffPokes[sideTarget] & gBitTable[gBattlePartyID[gBankTarget]]))
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ // can't swap if two pokemon don't have an item
+ // or if either of them is an enigma berry or a mail
+ else if ((gBattleMons[gBankAttacker].item == 0 && gBattleMons[gBankTarget].item == 0)
+ || gBattleMons[gBankAttacker].item == ITEM_ENIGMA_BERRY
+ || gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY
+ || IS_ITEM_MAIL(gBattleMons[gBankAttacker].item)
+ || IS_ITEM_MAIL(gBattleMons[gBankTarget].item))
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ // check if ability prevents swapping
+ else if (gBattleMons[gBankTarget].ability == ABILITY_STICKY_HOLD)
+ {
+ gBattlescriptCurrInstr = BattleScript_StickyHoldActivates;
+ gLastUsedAbility = gBattleMons[gBankTarget].ability;
+ RecordAbilityBattle(gBankTarget, gLastUsedAbility);
+ }
+ // took a while, but all checks passed and items can be safely swapped
+ else
+ {
+ u16 oldItemAtk, *newItemAtk;
+
+ newItemAtk = &gBattleStruct->changedItems[gBankAttacker];
+ oldItemAtk = gBattleMons[gBankAttacker].item;
+ *newItemAtk = gBattleMons[gBankTarget].item;
+
+ gBattleMons[gBankAttacker].item = 0;
+ gBattleMons[gBankTarget].item = oldItemAtk;
+
+ gActiveBank = gBankAttacker;
+ EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, newItemAtk);
+ MarkBufferBankForExecution(gBankAttacker);
+
+ gActiveBank = gBankTarget;
+ EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gBankTarget].item);
+ MarkBufferBankForExecution(gBankTarget);
+
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gBankTarget]) + 0) = 0;
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gBankTarget]) + 1) = 0;
+
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gBankAttacker]) + 0) = 0;
+ *(u8*)((u8*)(&gBattleStruct->choicedMove[gBankAttacker]) + 1) = 0;
+
+ gBattlescriptCurrInstr += 5;
+
+ PREPARE_ITEM_BUFFER(gBattleTextBuff1, *newItemAtk)
+ PREPARE_ITEM_BUFFER(gBattleTextBuff2, oldItemAtk)
+
+ if (oldItemAtk != 0 && *newItemAtk != 0)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2; // attacker's item -> <- target's item
+ else if (oldItemAtk == 0 && *newItemAtk != 0)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0; // nothing -> <- target's item
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1; // attacker's item -> <- nothing
+ }
+ }
+}
+
+static void atkD3_copy_ability(void) // role play
+{
+ if (gBattleMons[gBankTarget].ability != 0
+ && gBattleMons[gBankTarget].ability != ABILITY_WONDER_GUARD)
+ {
+ gBattleMons[gBankAttacker].ability = gBattleMons[gBankTarget].ability;
+ gLastUsedAbility = gBattleMons[gBankTarget].ability;
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkD4_wish_effect(void)
+{
+ switch (gBattlescriptCurrInstr[1])
+ {
+ case 0: // use wish
+ if (gWishFutureKnock.wishCounter[gBankAttacker] == 0)
+ {
+ gWishFutureKnock.wishCounter[gBankAttacker] = 2;
+ gWishFutureKnock.wishUserID[gBankAttacker] = gBattlePartyID[gBankAttacker];
+ gBattlescriptCurrInstr += 6;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ }
+ break;
+ case 1: // heal effect
+ PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff1, gBankTarget, gWishFutureKnock.wishUserID[gBankTarget])
+
+ gBattleMoveDamage = gBattleMons[gBankTarget].maxHP / 2;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ gBattleMoveDamage *= -1;
+
+ if (gBattleMons[gBankTarget].hp == gBattleMons[gBankTarget].maxHP)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ else
+ gBattlescriptCurrInstr += 6;
+
+ break;
+ }
+}
+
+static void atkD5_setroots(void) // ingrain
+{
+ if (gStatuses3[gBankAttacker] & STATUS3_ROOTED)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gStatuses3[gBankAttacker] |= STATUS3_ROOTED;
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkD6_doubledamagedealtifdamaged(void)
+{
+ if ((gProtectStructs[gBankAttacker].physicalDmg
+ && gProtectStructs[gBankAttacker].physicalBank == gBankTarget)
+ || (gProtectStructs[gBankAttacker].specialDmg
+ && gProtectStructs[gBankAttacker].specialBank == gBankTarget))
+ {
+ gBattleScripting.dmgMultiplier = 2;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkD7_setyawn(void)
+{
+ if (gStatuses3[gBankTarget] & STATUS3_YAWN
+ || gBattleMons[gBankTarget].status1 & STATUS_ANY)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gStatuses3[gBankTarget] |= 0x1000;
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkD8_setdamagetohealthdifference(void)
+{
+ if (gBattleMons[gBankTarget].hp <= gBattleMons[gBankAttacker].hp)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gBattleMoveDamage = gBattleMons[gBankTarget].hp - gBattleMons[gBankAttacker].hp;
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkD9_scaledamagebyhealthratio(void)
+{
+ if (gDynamicBasePower == 0)
+ {
+ u8 power = gBattleMoves[gCurrentMove].power;
+ gDynamicBasePower = gBattleMons[gBankAttacker].hp * power / gBattleMons[gBankAttacker].maxHP;
+ if (gDynamicBasePower == 0)
+ gDynamicBasePower = 1;
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atkDA_abilityswap(void) // skill swap
+{
+ if ((gBattleMons[gBankAttacker].ability == 0
+ && gBattleMons[gBankTarget].ability == 0)
+ || gBattleMons[gBankAttacker].ability == ABILITY_WONDER_GUARD
+ || gBattleMons[gBankTarget].ability == ABILITY_WONDER_GUARD
+ || gBattleMoveFlags & MOVESTATUS_NOEFFECT)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ u8 abilityAtk = gBattleMons[gBankAttacker].ability;
+ gBattleMons[gBankAttacker].ability = gBattleMons[gBankTarget].ability;
+ gBattleMons[gBankTarget].ability = abilityAtk;
+
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkDB_imprisoneffect(void)
+{
+ if ((gStatuses3[gBankAttacker] & STATUS3_IMPRISONED_OTHERS))
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ u8 bank, sideAttacker;
+
+ sideAttacker = GetBankSide(gBankAttacker);
+ PressurePPLoseOnUsingImprision(gBankAttacker);
+ for (bank = 0; bank < gNoOfAllBanks; bank++)
+ {
+ if (sideAttacker != GetBankSide(bank))
+ {
+ s32 attackerMoveId;
+ for (attackerMoveId = 0; attackerMoveId < 4; attackerMoveId++)
+ {
+ s32 i;
+ for (i = 0; i < 4; i++)
+ {
+ if (gBattleMons[gBankAttacker].moves[attackerMoveId] == gBattleMons[bank].moves[i]
+ && gBattleMons[gBankAttacker].moves[attackerMoveId] != MOVE_NONE)
+ break;
+ }
+ if (i != 4)
+ break;
+ }
+ if (attackerMoveId != 4)
+ {
+ gStatuses3[gBankAttacker] |= STATUS3_IMPRISONED_OTHERS;
+ gBattlescriptCurrInstr += 5;
+ break;
+ }
+ }
+ }
+ if (bank == gNoOfAllBanks) // In Generation 3 games, Imprison fails if the user doesn't share any moves with any of the foes
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkDC_setgrudge(void)
+{
+ if (gStatuses3[gBankAttacker] & STATUS3_GRUDGE)
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gStatuses3[gBankAttacker] |= STATUS3_GRUDGE;
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkDD_weightdamagecalculation(void)
+{
+ s32 i;
+ for (i = 0; sWeightToDamageTable[i] != 0xFFFF; i += 2)
+ {
+ if (sWeightToDamageTable[i] > GetPokedexHeightWeight(SpeciesToNationalPokedexNum(gBattleMons[gBankTarget].species), 1))
+ break;
+ }
+
+ if (sWeightToDamageTable[i] != 0xFFFF)
+ gDynamicBasePower = sWeightToDamageTable[i + 1];
+ else
+ gDynamicBasePower = 120;
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkDE_asistattackselect(void)
+{
+ s32 chooseableMovesNo = 0;
+ struct Pokemon* party;
+ s32 monId, moveId;
+ u16* movesArray = gBattleStruct->assistPossibleMoves;
+
+ if (GET_BANK_SIDE(gBankAttacker) != SIDE_PLAYER)
+ party = gEnemyParty;
+ else
+ party = gPlayerParty;
+
+ for (monId = 0; monId < 6; monId++)
+ {
+ if (monId == gBattlePartyID[gBankAttacker])
+ continue;
+ if (GetMonData(&party[monId], MON_DATA_SPECIES2) == SPECIES_NONE)
+ continue;
+ if (GetMonData(&party[monId], MON_DATA_SPECIES2) == SPECIES_EGG)
+ continue;
+
+ for (moveId = 0; moveId < 4; moveId++)
+ {
+ s32 i = 0;
+ u16 move = GetMonData(&party[monId], MON_DATA_MOVE1 + moveId);
+
+ if (IsInvalidForSleepTalkOrAssist(move))
+ continue;
+
+ for (; sMovesForbiddenToCopy[i] != ASSIST_FORBIDDEN_END && move != sMovesForbiddenToCopy[i]; i++);
+
+ if (sMovesForbiddenToCopy[i] != ASSIST_FORBIDDEN_END)
+ continue;
+ if (move == MOVE_NONE)
+ continue;
+
+ movesArray[chooseableMovesNo] = move;
+ chooseableMovesNo++;
+ }
+ }
+ if (chooseableMovesNo)
+ {
+ gHitMarker &= ~(HITMARKER_ATTACKSTRING_PRINTED);
+ gRandomMove = movesArray[((Random() & 0xFF) * chooseableMovesNo) >> 8];
+ gBankTarget = GetMoveTarget(gRandomMove, 0);
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkDF_setmagiccoat(void)
+{
+ gBankTarget = gBankAttacker;
+ gSpecialStatuses[gBankAttacker].flag20 = 1;
+ if (gCurrentMoveTurn == gNoOfAllBanks - 1) // moves last turn
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gProtectStructs[gBankAttacker].bounceMove = 1;
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkE0_setstealstatchange(void) // snatch
+{
+ gSpecialStatuses[gBankAttacker].flag20 = 1;
+ if (gCurrentMoveTurn == gNoOfAllBanks - 1) // moves last turn
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ gProtectStructs[gBankAttacker].stealMove = 1;
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkE1_intimidate_string_loader(void)
+{
+ u8 side;
+
+ gBattleScripting.bank = gBattleStruct->intimidateBank;
+ side = GetBankSide(gBattleScripting.bank);
+
+ PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gBattleMons[gBattleScripting.bank].ability)
+
+ for (;gBankTarget < gNoOfAllBanks; gBankTarget++)
+ {
+ if (GetBankSide(gBankTarget) == side)
+ continue;
+ if (!(gAbsentBankFlags & gBitTable[gBankTarget]))
+ break;
+ }
+
+ if (gBankTarget >= gNoOfAllBanks)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ else
+ gBattlescriptCurrInstr += 5;
+}
+
+static void atkE2_switchout_abilities(void)
+{
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ switch (gBattleMons[gActiveBank].ability)
+ {
+ case ABILITY_NATURAL_CURE:
+ gBattleMons[gActiveBank].status1 = 0;
+ EmitSetMonData(0, REQUEST_STATUS_BATTLE, gBitTable[*(gBattleStruct->field_58 + gActiveBank)], 4, &gBattleMons[gActiveBank].status1);
+ MarkBufferBankForExecution(gActiveBank);
+ break;
+ }
+
+ gBattlescriptCurrInstr += 2;
+}
+
+static void atkE3_jumpifhasnohp(void)
+{
+ gActiveBank = GetBattleBank(gBattlescriptCurrInstr[1]);
+
+ if (gBattleMons[gActiveBank].hp == 0)
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 2);
+ else
+ gBattlescriptCurrInstr += 6;
+}
+
+static void atkE4_getsecretpowereffect(void)
+{
+ switch (gBattleTerrain)
+ {
+ case BATTLE_TERRAIN_GRASS:
+ gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_POISON;
+ break;
+ case BATTLE_TERRAIN_LONG_GRASS:
+ gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_SLEEP;
+ break;
+ case BATTLE_TERRAIN_SAND:
+ gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_ACC_MINUS_1;
+ break;
+ case BATTLE_TERRAIN_UNDERWATER:
+ gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_DEF_MINUS_1;
+ break;
+ case BATTLE_TERRAIN_WATER:
+ gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_ATK_MINUS_1;
+ break;
+ case BATTLE_TERRAIN_POND:
+ gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_SPD_MINUS_1;
+ break;
+ case BATTLE_TERRAIN_ROCK:
+ gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_CONFUSION;
+ break;
+ case BATTLE_TERRAIN_CAVE:
+ gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_FLINCH;
+ break;
+ default:
+ gBattleCommunication[MOVE_EFFECT_BYTE] = MOVE_EFFECT_PARALYSIS;
+ break;
+ }
+ gBattlescriptCurrInstr++;
+}
+
+static void atkE5_pickup(void)
+{
+ if (!InBattlePike())
+ {
+ s32 i;
+ u16 species, heldItem;
+ u8 ability;
+
+ if (InBattlePyramid())
+ {
+ for (i = 0; i < 6; i++)
+ {
+ species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+ heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
+
+ if (GetMonData(&gPlayerParty[i], MON_DATA_ALT_ABILITY))
+ ability = gBaseStats[species].ability2;
+ else
+ ability = gBaseStats[species].ability1;
+
+ if (ability == ABILITY_PICKUP
+ && species != 0
+ && species != SPECIES_EGG
+ && heldItem == ITEM_NONE
+ && (Random() % 10) == 0)
+ {
+ heldItem = GetBattlePyramidPickupItemId();
+ SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &heldItem);
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < 6; i++)
+ {
+ species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+ heldItem = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM);
+
+ if (GetMonData(&gPlayerParty[i], MON_DATA_ALT_ABILITY))
+ ability = gBaseStats[species].ability2;
+ else
+ ability = gBaseStats[species].ability1;
+
+ if (ability == ABILITY_PICKUP
+ && species != 0
+ && species != SPECIES_EGG
+ && heldItem == ITEM_NONE
+ && (Random() % 10) == 0)
+ {
+ s32 j;
+ s32 rand = Random() % 100;
+ u8 lvlDivBy10 = (GetMonData(&gPlayerParty[i], MON_DATA_LEVEL) - 1) / 10;
+ if (lvlDivBy10 > 9)
+ lvlDivBy10 = 9;
+
+ for (j = 0; j < 9; j++)
+ {
+ if (sPickupProbabilities[j] > rand)
+ {
+ SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &sPickupItems[lvlDivBy10 + j]);
+ break;
+ }
+ else if (rand == 99 || rand == 98)
+ {
+ SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &sRarePickupItems[lvlDivBy10 + (99 - rand)]);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkE6_castform_change_animation(void)
+{
+ gActiveBank = gBattleScripting.bank;
+
+ if (gBattleMons[gActiveBank].status2 & STATUS2_SUBSTITUTE)
+ *(&gBattleStruct->formToChangeInto) |= 0x80;
+
+ EmitBattleAnimation(0, B_ANIM_CASTFORM_CHANGE, gBattleStruct->formToChangeInto);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkE7_castform_data_change(void)
+{
+ u8 form;
+
+ gBattlescriptCurrInstr++;
+ form = CastformDataTypeChange(gBattleScripting.bank);
+ if (form)
+ {
+ BattleScriptPushCursorAndCallback(BattleScript_CastformChange);
+ *(&gBattleStruct->formToChangeInto) = form - 1;
+ }
+}
+
+static void atkE8_settypebasedhalvers(void) // water and mud sport
+{
+ bool8 worked = FALSE;
+
+ if (gBattleMoves[gCurrentMove].effect == EFFECT_MUD_SPORT)
+ {
+ if (!(gStatuses3[gBankAttacker] & STATUS3_MUDSPORT))
+ {
+ gStatuses3[gBankAttacker] |= STATUS3_MUDSPORT;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ worked = TRUE;
+ }
+ }
+ else // water sport
+ {
+ if (!(gStatuses3[gBankAttacker] & STATUS3_WATERSPORT))
+ {
+ gStatuses3[gBankAttacker] |= STATUS3_WATERSPORT;
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ worked = TRUE;
+ }
+ }
+
+ if (worked)
+ gBattlescriptCurrInstr += 5;
+ else
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+}
+
+static void atkE9_setweatherballtype(void)
+{
+ if (WEATHER_HAS_EFFECT)
+ {
+ if (gBattleWeather & WEATHER_ANY)
+ gBattleScripting.dmgMultiplier = 2;
+ if (gBattleWeather & WEATHER_RAIN_ANY)
+ *(&gBattleStruct->dynamicMoveType) = TYPE_WATER | 0x80;
+ else if (gBattleWeather & WEATHER_SANDSTORM_ANY)
+ *(&gBattleStruct->dynamicMoveType) = TYPE_ROCK | 0x80;
+ else if (gBattleWeather & WEATHER_SUN_ANY)
+ *(&gBattleStruct->dynamicMoveType) = TYPE_FIRE | 0x80;
+ else if (gBattleWeather & WEATHER_HAIL_ANY)
+ *(&gBattleStruct->dynamicMoveType) = TYPE_ICE | 0x80;
+ else
+ *(&gBattleStruct->dynamicMoveType) = TYPE_NORMAL | 0x80;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkEA_recycleitem(void)
+{
+ u16 *usedHeldItem;
+
+ gActiveBank = gBankAttacker;
+ usedHeldItem = &gBattleStruct->usedHeldItems[gActiveBank];
+ if (*usedHeldItem != 0 && gBattleMons[gActiveBank].item == 0)
+ {
+ gLastUsedItem = *usedHeldItem;
+ *usedHeldItem = 0;
+ gBattleMons[gActiveBank].item = gLastUsedItem;
+
+ EmitSetMonData(0, REQUEST_HELDITEM_BATTLE, 0, 2, &gBattleMons[gActiveBank].item);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkEB_settypetoterrain(void)
+{
+ if (gBattleMons[gBankAttacker].type1 != sTerrainToType[gBattleTerrain]
+ && gBattleMons[gBankAttacker].type2 != sTerrainToType[gBattleTerrain])
+ {
+ gBattleMons[gBankAttacker].type1 = sTerrainToType[gBattleTerrain];
+ gBattleMons[gBankAttacker].type2 = sTerrainToType[gBattleTerrain];
+
+ PREPARE_TYPE_BUFFER(gBattleTextBuff1, sTerrainToType[gBattleTerrain])
+
+ gBattlescriptCurrInstr += 5;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkEC_pursuit_sth(void)
+{
+ gActiveBank = GetBankByIdentity(GetBankIdentity(gBankAttacker) ^ BIT_MON);
+
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
+ && !(gAbsentBankFlags & gBitTable[gActiveBank])
+ && gActionForBanks[gActiveBank] == 0
+ && gChosenMovesByBanks[gActiveBank] == MOVE_PURSUIT)
+ {
+ gUnknown_0202407A[gActiveBank] = 11;
+ gCurrentMove = MOVE_PURSUIT;
+ gBattlescriptCurrInstr += 5;
+ gBattleScripting.animTurn = 1;
+ gBattleScripting.field_20 = gBankAttacker;
+ gBankAttacker = gActiveBank;
+ }
+ else
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+}
+
+static void atkED_802B4B4(void)
+{
+ gEffectBank = gBankAttacker;
+
+ if (gBankAttacker == gBankTarget)
+ gBankAttacker = gBankTarget = gBattleScripting.bank;
+ else
+ gBankTarget = gBattleScripting.bank;
+
+ gBattleScripting.bank = gEffectBank;
+ gBattlescriptCurrInstr++;
+}
+
+static void atkEE_removelightscreenreflect(void) // brick break
+{
+ u8 opposingSide = GetBankSide(gBankAttacker) ^ BIT_SIDE;
+
+ if (gSideTimers[opposingSide].reflectTimer || gSideTimers[opposingSide].lightscreenTimer)
+ {
+ gSideAffecting[opposingSide] &= ~(SIDE_STATUS_REFLECT);
+ gSideAffecting[opposingSide] &= ~(SIDE_STATUS_LIGHTSCREEN);
+ gSideTimers[opposingSide].reflectTimer = 0;
+ gSideTimers[opposingSide].lightscreenTimer = 0;
+ gBattleScripting.animTurn = 1;
+ gBattleScripting.animTargetsHit = 1;
+ }
+ else
+ {
+ gBattleScripting.animTurn = 0;
+ gBattleScripting.animTargetsHit = 0;
+ }
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkEF_pokeball_catch_calculation(void)
+{
+ u8 ballMultiplier = 0;
+
+ if (gBattleExecBuffer)
+ return;
+
+ gActiveBank = gBankAttacker;
+ gBankTarget = gBankAttacker ^ BIT_SIDE;
+
+ if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
+ {
+ EmitBallThrow(0, BALL_TRAINER_BLOCK);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr = BattleScript_TrainerBallBlock;
+ }
+ else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL)
+ {
+ EmitBallThrow(0, BALL_3_SHAKES_SUCCESS);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr = BattleScript_WallyBallThrow;
+ }
+ else
+ {
+ u32 odds;
+ u8 catchRate;
+
+ if (gLastUsedItem == ITEM_SAFARI_BALL)
+ catchRate = gBattleStruct->field_7C * 1275 / 100;
+ else
+ catchRate = gBaseStats[gBattleMons[gBankTarget].species].catchRate;
+
+ if (gLastUsedItem > ITEM_SAFARI_BALL)
+ {
+ switch (gLastUsedItem)
+ {
+ case ITEM_NET_BALL:
+ if (gBattleMons[gBankTarget].type1 == TYPE_WATER
+ || gBattleMons[gBankTarget].type2 == TYPE_WATER
+ || gBattleMons[gBankTarget].type1 == TYPE_BUG
+ || gBattleMons[gBankTarget].type2 == TYPE_BUG)
+ ballMultiplier = 30;
+ else
+ ballMultiplier = 10;
+ break;
+ case ITEM_DIVE_BALL:
+ if (sav1_map_get_light_level() == 5)
+ ballMultiplier = 35;
+ else
+ ballMultiplier = 10;
+ break;
+ case ITEM_NEST_BALL:
+ if (gBattleMons[gBankTarget].level < 40)
+ {
+ ballMultiplier = 40 - gBattleMons[gBankTarget].level;
+ if (ballMultiplier <= 9)
+ ballMultiplier = 10;
+ }
+ else
+ {
+ ballMultiplier = 10;
+ }
+ break;
+ case ITEM_REPEAT_BALL:
+ if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(gBattleMons[gBankTarget].species), FLAG_GET_CAUGHT))
+ ballMultiplier = 30;
+ else
+ ballMultiplier = 10;
+ break;
+ case ITEM_TIMER_BALL:
+ ballMultiplier = gBattleResults.battleTurnCounter + 10;
+ if (ballMultiplier > 40)
+ ballMultiplier = 40;
+ break;
+ case ITEM_LUXURY_BALL:
+ case ITEM_PREMIER_BALL:
+ ballMultiplier = 10;
+ break;
+ }
+ }
+ else
+ ballMultiplier = sBallCatchBonuses[gLastUsedItem - 2];
+
+ odds = (catchRate * ballMultiplier / 10)
+ * (gBattleMons[gBankTarget].maxHP * 3 - gBattleMons[gBankTarget].hp * 2)
+ / (3 * gBattleMons[gBankTarget].maxHP);
+
+ if (gBattleMons[gBankTarget].status1 & (STATUS_SLEEP | STATUS_FREEZE))
+ odds *= 2;
+ if (gBattleMons[gBankTarget].status1 & (STATUS_POISON | STATUS_BURN | STATUS_PARALYSIS | STATUS_TOXIC_POISON))
+ odds = (odds * 15) / 10;
+
+ if (gLastUsedItem != ITEM_SAFARI_BALL)
+ {
+ if (gLastUsedItem == ITEM_MASTER_BALL)
+ {
+ gBattleResults.unk5_1 = 1;
+ }
+ else
+ {
+ if (gBattleResults.catchAttempts[gLastUsedItem - ITEM_ULTRA_BALL] < 0xFF)
+ gBattleResults.catchAttempts[gLastUsedItem - ITEM_ULTRA_BALL]++;
+ }
+ }
+
+ if (odds > 254) // mon caught
+ {
+ EmitBallThrow(0, BALL_3_SHAKES_SUCCESS);
+ MarkBufferBankForExecution(gActiveBank);
+ gBattlescriptCurrInstr = BattleScript_SuccessBallThrow;
+ SetMonData(&gEnemyParty[gBattlePartyID[gBankTarget]], MON_DATA_POKEBALL, &gLastUsedItem);
+
+ if (CalculatePlayerPartyCount() == 6)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ else // mon may be caught, calculate shakes
+ {
+ u8 shakes;
+
+ odds = Sqrt(Sqrt(16711680 / odds));
+ odds = 1048560 / odds;
+
+ for (shakes = 0; shakes < 4 && Random() < odds; shakes++);
+
+ if (gLastUsedItem == ITEM_MASTER_BALL)
+ shakes = BALL_3_SHAKES_SUCCESS; // why calculate the shakes before that check?
+
+ EmitBallThrow(0, shakes);
+ MarkBufferBankForExecution(gActiveBank);
+
+ if (shakes == BALL_3_SHAKES_SUCCESS) // mon caught, copy of the code above
+ {
+ gBattlescriptCurrInstr = BattleScript_SuccessBallThrow;
+ SetMonData(&gEnemyParty[gBattlePartyID[gBankTarget]], MON_DATA_POKEBALL, &gLastUsedItem);
+
+ if (CalculatePlayerPartyCount() == 6)
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ else
+ gBattleCommunication[MULTISTRING_CHOOSER] = 1;
+ }
+ else // not caught
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = shakes;
+ gBattlescriptCurrInstr = BattleScript_ShakeBallThrow;
+ }
+ }
+ }
+}
+
+static void atkF0_give_caught_mon(void)
+{
+ if (GiveMonToPlayer(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]]) != MON_GIVEN_TO_PARTY)
+ {
+ if (!sub_813B21C())
+ {
+ gBattleCommunication[MULTISTRING_CHOOSER] = 0;
+ StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_STORAGE_UNKNOWN)));
+ GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gStringVar2);
+ }
+ else
+ {
+ StringCopy(gStringVar1, GetBoxNamePtr(VarGet(VAR_STORAGE_UNKNOWN)));
+ GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gStringVar2);
+ StringCopy(gStringVar3, GetBoxNamePtr(get_unknown_box_id()));
+ gBattleCommunication[MULTISTRING_CHOOSER] = 2;
+ }
+
+ if (FlagGet(SYS_PC_LANETTE))
+ gBattleCommunication[MULTISTRING_CHOOSER]++;
+ }
+
+ gBattleResults.caughtMonSpecies = GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_SPECIES, NULL);
+ GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gBattleResults.caughtMonNick);
+ gBattleResults.caughtMonBall = GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_POKEBALL, NULL);
+
+ gBattlescriptCurrInstr++;
+}
+
+static void atkF1_set_caught_mon_dex_flags(void)
+{
+ u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL);
+ u32 personality = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY, NULL);
+
+ if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_GET_CAUGHT))
+ {
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ else
+ {
+ HandleSetPokedexFlag(SpeciesToNationalPokedexNum(species), FLAG_SET_CAUGHT, personality);
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+static void atkF2_display_dex_info(void)
+{
+ u16 species = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL);
+
+ switch (gBattleCommunication[0])
+ {
+ case 0:
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ gBattleCommunication[0]++;
+ break;
+ case 1:
+ if (!gPaletteFade.active)
+ {
+ FreeAllWindowBuffers();
+ gBattleCommunication[TASK_ID] = CreateDexDisplayMonDataTask(SpeciesToNationalPokedexNum(species),
+ gBattleMons[gBankTarget].otId,
+ gBattleMons[gBankTarget].personality);
+ gBattleCommunication[0]++;
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active
+ && gMain.callback2 == BattleMainCB2
+ && !gTasks[gBattleCommunication[TASK_ID]].isActive)
+ {
+ SetVBlankCallback(VBlankCB_Battle);
+ gBattleCommunication[0]++;
+ }
+ break;
+ case 3:
+ c2_berry_program_update_menu();
+ sub_8035AA4();
+ gBattle_BG3_X = 0x100;
+ gBattleCommunication[0]++;
+ break;
+ case 4:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ {
+ BeginNormalPaletteFade(0xFFFF, 0, 0x10, 0, 0);
+ ShowBg(0);
+ ShowBg(3);
+ gBattleCommunication[0]++;
+ }
+ break;
+ case 5:
+ if (!gPaletteFade.active)
+ gBattlescriptCurrInstr++;
+ break;
+ }
+}
+
+void sub_8056A3C(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags)
+{
+ s32 destY, destX;
+ u16 var = 0;
+
+ for (destY = yStart; destY <= yEnd; destY++)
+ {
+ for (destX = xStart; destX <= xEnd; destX++)
+ {
+ if (destY == yStart)
+ {
+ if (destX == xStart)
+ var = 0x1022;
+ else if (destX == xEnd)
+ var = 0x1024;
+ else
+ var = 0x1023;
+ }
+ else if (destY == yEnd)
+ {
+ if (destX == xStart)
+ var = 0x1028;
+ else if (destX == xEnd)
+ var = 0x102A;
+ else
+ var = 0x1029;
+ }
+ else
+ {
+ if (destX == xStart)
+ var = 0x1025;
+ else if (destX == xEnd)
+ var = 0x1027;
+ else
+ var = 0x1026;
+ }
+
+ if (flags & 1)
+ var = 0;
+
+ if (flags & 0x80)
+ CopyToBgTilemapBufferRect_ChangePalette(1, &var, destX, destY, 1, 1, 0x11);
+ else
+ CopyToBgTilemapBufferRect_ChangePalette(0, &var, destX, destY, 1, 1, 0x11);
+ }
+ }
+}
+
+void BattleCreateCursorAt(u8 cursorPosition)
+{
+ u16 src[2];
+ src[0] = 1;
+ src[1] = 2;
+
+ CopyToBgTilemapBufferRect_ChangePalette(0, src, 0x19, 9 + (2 * cursorPosition), 1, 2, 0x11);
+ CopyBgTilemapBufferToVram(0);
+}
+
+void BattleDestroyCursorAt(u8 cursorPosition)
+{
+ u16 src[2];
+ src[0] = 0x1016;
+ src[1] = 0x1016;
+
+ CopyToBgTilemapBufferRect_ChangePalette(0, src, 0x19, 9 + (2 * cursorPosition), 1, 2, 0x11);
+ CopyBgTilemapBufferToVram(0);
+}
+
+static void atkF3_nickname_caught_poke(void)
+{
+ switch (gBattleCommunication[MULTIUSE_STATE])
+ {
+ case 0:
+ sub_8056A3C(0x18, 8, 0x1D, 0xD, 0);
+ sub_814F9EC(gText_BattleYesNoChoice, 0xC);
+ gBattleCommunication[MULTIUSE_STATE]++;
+ gBattleCommunication[CURSOR_POSITION] = 0;
+ BattleCreateCursorAt(0);
+ break;
+ case 1:
+ if (gMain.newKeys & DPAD_UP && gBattleCommunication[CURSOR_POSITION] != 0)
+ {
+ PlaySE(SE_SELECT);
+ BattleDestroyCursorAt(gBattleCommunication[CURSOR_POSITION]);
+ gBattleCommunication[CURSOR_POSITION] = 0;
+ BattleCreateCursorAt(0);
+ }
+ if (gMain.newKeys & DPAD_DOWN && gBattleCommunication[CURSOR_POSITION] == 0)
+ {
+ PlaySE(SE_SELECT);
+ BattleDestroyCursorAt(gBattleCommunication[CURSOR_POSITION]);
+ gBattleCommunication[CURSOR_POSITION] = 1;
+ BattleCreateCursorAt(1);
+ }
+ if (gMain.newKeys & A_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ if (gBattleCommunication[CURSOR_POSITION] == 0)
+ {
+ gBattleCommunication[MULTIUSE_STATE]++;
+ BeginFastPaletteFade(3);
+ }
+ else
+ {
+ gBattleCommunication[MULTIUSE_STATE] = 4;
+ }
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ PlaySE(SE_SELECT);
+ gBattleCommunication[MULTIUSE_STATE] = 4;
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gBattleStruct->caughtMonNick);
+ FreeAllWindowBuffers();
+
+ DoNamingScreen(NAMING_SCREEN_CAUGHT_MON, gBattleStruct->caughtMonNick,
+ GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_SPECIES),
+ GetMonGender(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]]),
+ GetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_PERSONALITY, NULL),
+ BattleMainCB2);
+
+ gBattleCommunication[MULTIUSE_STATE]++;
+ }
+ break;
+ case 3:
+ if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active )
+ {
+ SetMonData(&gEnemyParty[gBattlePartyID[gBankAttacker ^ BIT_SIDE]], MON_DATA_NICKNAME, gBattleStruct->caughtMonNick);
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ }
+ break;
+ case 4:
+ if (CalculatePlayerPartyCount() == 6)
+ gBattlescriptCurrInstr += 5;
+ else
+ gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
+ break;
+ }
+}
+
+static void atkF4_subattackerhpbydmg(void)
+{
+ gBattleMons[gBankAttacker].hp -= gBattleMoveDamage;
+ gBattlescriptCurrInstr++;
+}
+
+static void atkF5_removeattackerstatus1(void)
+{
+ gBattleMons[gBankAttacker].status1 = 0;
+ gBattlescriptCurrInstr++;
+}
+
+static void atkF6_802BF48(void)
+{
+ gFightStateTracker = 0xC;
+}
+
+static void atkF7_802BF54(void)
+{
+ gFightStateTracker = 0xC;
+ gCurrentMoveTurn = gNoOfAllBanks;
+}
+
+static void atkF8_trainer_slide_back(void)
+{
+ gActiveBank = GetBankByIdentity(gBattlescriptCurrInstr[1]);
+ EmitTrainerSlideBack(0);
+ MarkBufferBankForExecution(gActiveBank);
+
+ gBattlescriptCurrInstr += 2;
+}
diff --git a/src/berry.c b/src/berry.c
index b6eaa14a0..98cf7d932 100644
--- a/src/berry.c
+++ b/src/berry.c
@@ -17,7 +17,6 @@ extern bool8 sub_8092E9C(u8, u8, u8);
extern u16 gScriptItemId;
extern const u8 BerryTreeScript[];
-extern const struct BerryTree gBlankBerryTree;
#define BERRY_NAME_LENGTH 6
@@ -804,10 +803,58 @@ const struct Berry gBerries[] =
},
};
+const struct UnkStruct_0858AB24 gUnknown_0858AB24[] = {
+ { 50, 20},
+ { 50, 20},
+ { 50, 20},
+ { 50, 20},
+ { 50, 20},
+ { 50, 30},
+ { 50, 30},
+ { 50, 30},
+ { 50, 30},
+ { 50, 30},
+ { 60, 50},
+ { 60, 50},
+ { 60, 50},
+ { 60, 50},
+ { 60, 50},
+ { 80, 70},
+ { 80, 70},
+ { 80, 70},
+ { 80, 70},
+ { 80, 70},
+ {100, 100},
+ {100, 100},
+ {100, 100},
+ {100, 100},
+ {100, 100},
+ {130, 150},
+ {130, 150},
+ {130, 150},
+ {130, 150},
+ {130, 150},
+ {160, 250},
+ {160, 250},
+ {160, 250},
+ {160, 250},
+ {160, 250},
+ {180, 500},
+ {180, 500},
+ {180, 500},
+ {180, 500},
+ {180, 500},
+ {200, 750},
+ {200, 750},
+ {150, 200}
+};
+
+const struct BerryTree gBlankBerryTree = {};
+
// unused
void ClearEnigmaBerries(void)
{
- CpuFill16(0, &gSaveBlock1Ptr->enigmaBerry, sizeof(gSaveBlock1Ptr->enigmaBerry));
+ CpuFill16(0, &gSaveBlock1Ptr->enigmaBerry, 52);
}
void SetEnigmaBerry(u8 *src)
@@ -815,7 +862,7 @@ void SetEnigmaBerry(u8 *src)
u32 i;
u8 *dest = (u8*)&gSaveBlock1Ptr->enigmaBerry;
- for (i = 0; i < sizeof(gSaveBlock1Ptr->enigmaBerry); i++)
+ for (i = 0; i < 52; i++)
dest[i] = src[i];
}
@@ -827,7 +874,7 @@ u32 GetEnigmaBerryChecksum(struct EnigmaBerry *enigmaBerry)
dest = (u8*)enigmaBerry;
checksum = 0;
- for (i = 0; i < sizeof(gSaveBlock1Ptr->enigmaBerry) - sizeof(gSaveBlock1Ptr->enigmaBerry.checksum); i++)
+ for (i = 0; i < 52 - sizeof(gSaveBlock1Ptr->enigmaBerry.checksum); i++)
{
checksum += dest[i];
}
diff --git a/src/berry_blender.c b/src/berry_blender.c
new file mode 100644
index 000000000..db50fe4c4
--- /dev/null
+++ b/src/berry_blender.c
@@ -0,0 +1,18 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+IWRAM_DATA void *berry_blender_c_unused_03000de4;
+IWRAM_DATA s16 gUnknown_03000DE8[8];
+IWRAM_DATA s16 gUnknown_03000DF8[6];
+IWRAM_DATA s16 gUnknown_03000E04;
+IWRAM_DATA s16 gUnknown_03000E06;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/berry_fix_program.c b/src/berry_fix_program.c
new file mode 100644
index 000000000..eca20af9d
--- /dev/null
+++ b/src/berry_fix_program.c
@@ -0,0 +1,530 @@
+
+// Includes
+#include "global.h"
+#include "gpu_regs.h"
+#include "multiboot.h"
+#include "malloc.h"
+#include "bg.h"
+#include "main.h"
+#include "sprite.h"
+#include "task.h"
+#include "unknown_task.h"
+#include "window.h"
+#include "menu.h"
+#include "m4a.h"
+
+// Static type declarations
+
+typedef struct {
+ u8 state;
+ u8 unk1;
+ u16 unk2;
+ struct MultiBootParam mb;
+} berryfix_t;
+
+// Static RAM declarations
+
+static berryfix_t *berry_fix_mb_manager;
+
+// Static ROM declarations
+
+static void berry_fix_main(void);
+static void berry_fix_gpu_set(void);
+static int berry_fix_text_update(int);
+static void berry_fix_text_print(int);
+static void berry_fix_bg_hide(void);
+
+// .rodata
+
+static const u8 gUnknown_08617E78[] = _("Berry Program Update");
+static const u8 gUnknown_08617E8D[] = _("Ruby/Sapphire");
+static const u8 gUnknown_08617E9B[] = _("Emerald");
+
+static const u8 Unknown_08617EA3[] = _("The Berry Program on your POKéMON\nRuby/Sapphire Game Pak will be updated.\n{COLOR RED}{SHADOW LIGHT_RED}Press the A Button.");
+static const u8 Unknown_08617F07[] = _("Please ensure the connection of your\nGame Boy Advance system matches this.\n{COLOR RED}{SHADOW LIGHT_RED}YES: Press the A Button.\nNO: Turn off the power and try again.");
+static const u8 Unknown_08617F97[] = _("Please turn on the power of POKéMON\nRuby/Sapphire while holding START and\nSELECT simultaneously. Then, ensure\nthe picture above appears.");
+static const u8 Unknown_08618020[] = _("Transmitting. Please wait.\n{COLOR RED}{SHADOW LIGHT_RED}Please do not turn off the power or\nunplug the Game Boy Advance Game\nLink Cable.");
+static const u8 Unknown_08618092[] = _("Please follow the instructions on your\nPOKéMON Ruby/Sapphire screen.");
+static const u8 Unknown_086180D7[] = _("Transmission failure.\n{COLOR RED}{SHADOW LIGHT_RED}Please try again.");
+
+static const struct BgTemplate gUnknown_08618108[] = {
+ {
+ 0, 0, 30, 0, 0, 0
+ }, {
+ 1, 1, 31, 0, 0, 1
+ }
+};
+
+static const struct WindowTemplate gUnknown_08618110[] = {
+ {0, 2, 4, 26, 2, 15, 0x001},
+ {0, 1, 11, 28, 8, 15, 0x035},
+ {0, 0, 8, 30, 2, 15, 0x115},
+ {0, 8, 0, 14, 2, 15, 0x151},
+ {-1}
+};
+
+static const u16 gUnknown_08618138[] = {
+ 0x7fff, 0x7fff, 0x318c, 0x675a,
+ 0x043c, 0x3aff, 0x0664, 0x4bd2,
+ 0x6546, 0x7b14, 0x7fff, 0x318c,
+ 0x675a, 0x0000, 0x0000, 0x0000
+};
+
+static const u8 gUnknown_08618158[] = {10, 11, 12};
+static const u8 gUnknown_0861815B[] = { 0, 10, 13};
+
+static const u8 *const gUnknown_08618160[] = {
+ Unknown_08617F07,
+ Unknown_08617F97,
+ Unknown_08618020,
+ Unknown_08618092,
+ Unknown_086180D7,
+ Unknown_08617EA3
+};
+
+extern const u8 gUnknown_08DD87C0[];
+extern const u8 gUnknown_08DD8EE0[];
+extern const u8 gUnknown_08DD8780[];
+extern const u8 gUnknown_08DD90E0[];
+extern const u8 gUnknown_08DD9718[];
+extern const u8 gUnknown_08DD9080[];
+extern const u8 gUnknown_08DD98B4[];
+extern const u8 gUnknown_08DD9E58[];
+extern const u8 gUnknown_08DD9874[];
+extern const u8 gUnknown_08DDA02C[];
+extern const u8 gUnknown_08DDA63C[];
+extern const u8 gUnknown_08DD9FEC[];
+extern const u8 gUnknown_08DDA840[];
+extern const u8 gUnknown_08DDAE40[];
+extern const u8 gUnknown_08DDA800[];
+extern const u8 gUnknown_08DDB020[];
+extern const u8 gUnknown_08DDB2C4[];
+extern const u8 gUnknown_08DDAFE0[];
+
+static const u8 *const gUnknown_08618178[][3] = {
+ {
+ gUnknown_08DD87C0,
+ gUnknown_08DD8EE0,
+ gUnknown_08DD8780
+ }, {
+ gUnknown_08DD90E0,
+ gUnknown_08DD9718,
+ gUnknown_08DD9080
+ }, {
+ gUnknown_08DD98B4,
+ gUnknown_08DD9E58,
+ gUnknown_08DD9874
+ }, {
+ gUnknown_08DDA02C,
+ gUnknown_08DDA63C,
+ gUnknown_08DD9FEC
+ }, {
+ gUnknown_08DDA840,
+ gUnknown_08DDAE40,
+ gUnknown_08DDA800
+ }, {
+ gUnknown_08DDB020,
+ gUnknown_08DDB2C4,
+ gUnknown_08DDAFE0
+ },
+};
+
+extern const u8 gMultiBootProgram_BerryGlitchFix_Start[0x3BF4];
+extern const u8 gMultiBootProgram_BerryGlitchFix_End[];
+
+// .text
+
+void InitBerryFixProgram(void)
+{
+ DisableInterrupts(0xFFFF);
+ EnableInterrupts(0x0001);
+ m4aSoundVSyncOff();
+ SetVBlankCallback(NULL);
+ ResetSpriteData();
+ ResetTasks();
+ remove_some_task();
+ SetGpuReg(REG_OFFSET_DISPCNT, 0x0000);
+ berry_fix_mb_manager = AllocZeroed(0x50);
+ berry_fix_mb_manager->state = 0;
+ berry_fix_mb_manager->unk1 = 6;
+ SetMainCallback2(berry_fix_main);
+}
+
+static void berry_fix_main(void)
+{
+ switch (berry_fix_mb_manager->state)
+ {
+ case 0:
+ berry_fix_gpu_set();
+ berry_fix_mb_manager->state = 1;
+ break;
+ case 1:
+ if (berry_fix_text_update(5) == 5 && (gMain.newKeys & A_BUTTON))
+ {
+ berry_fix_mb_manager->state = 2;
+ }
+ break;
+ case 2:
+ if (berry_fix_text_update(0) == 0 && (gMain.newKeys & A_BUTTON))
+ {
+ berry_fix_mb_manager->state = 3;
+ }
+ break;
+ case 3:
+ if (berry_fix_text_update(1) == 1)
+ {
+ berry_fix_mb_manager->mb.masterp = gMultiBootProgram_BerryGlitchFix_Start;
+ berry_fix_mb_manager->mb.server_type = 0;
+ MultiBootInit(&berry_fix_mb_manager->mb);
+ berry_fix_mb_manager->unk2 = 0;
+ berry_fix_mb_manager->state = 4;
+ }
+ break;
+ case 4:
+ MultiBootMain(&berry_fix_mb_manager->mb);
+ if (berry_fix_mb_manager->mb.probe_count != 0 || (!(berry_fix_mb_manager->mb.response_bit & 2) || !(berry_fix_mb_manager->mb.client_bit & 2)))
+ {
+ berry_fix_mb_manager->unk2 = 0;
+ }
+ else if (++ berry_fix_mb_manager->unk2 > 180)
+ {
+ MultiBootStartMaster(&berry_fix_mb_manager->mb, gMultiBootProgram_BerryGlitchFix_Start + ROM_HEADER_SIZE, (u32)(gMultiBootProgram_BerryGlitchFix_End - (gMultiBootProgram_BerryGlitchFix_Start + ROM_HEADER_SIZE)), 4, 1);
+ berry_fix_mb_manager->state = 5;
+ }
+ break;
+ case 5:
+ if (berry_fix_text_update(2) == 2) {
+ MultiBootMain(&berry_fix_mb_manager->mb);
+ if (MultiBootCheckComplete(&berry_fix_mb_manager->mb)) {
+ berry_fix_mb_manager->state = 6;
+ }
+ else if (!(berry_fix_mb_manager->mb.client_bit & 2)) {
+ berry_fix_mb_manager->state = 7;
+ }
+ }
+ break;
+ case 6:
+ if (berry_fix_text_update(3) == 3 && gMain.newKeys & A_BUTTON)
+ {
+ DoSoftReset();
+ }
+ break;
+ case 7:
+ if (berry_fix_text_update(4) == 4 && gMain.newKeys & A_BUTTON)
+ {
+ berry_fix_mb_manager->state = 1;
+ }
+ break;
+ }
+}
+
+#ifdef NONMATCHING
+static void berry_fix_gpu_set(void)
+{
+ s32 width;
+
+ SetGpuReg(REG_OFFSET_BG0CNT, 0x0000);
+ SetGpuReg(REG_OFFSET_BG1CNT, 0x0000);
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BG1VOFS, 0x0000);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0x0000);
+
+ DmaFill32(3, 0, VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, OAM, OAM_SIZE);
+ DmaFill32(3, 0, PLTT, PLTT_SIZE);
+ ResetBgsAndClearDma3BusyFlags(0);
+
+ InitBgsFromTemplates(0, gUnknown_08618108, ARRAY_COUNT(gUnknown_08618108));
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ InitWindows(gUnknown_08618110);
+ DeactivateAllTextPrinters();
+
+ DmaCopy32(3, gUnknown_08618138, BG_PLTT + 0x1E0, 0x20);
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP);
+ FillWindowPixelBuffer(2, 0);
+ FillWindowPixelBuffer(3, 0);
+ FillWindowPixelBuffer(0, 0xAA);
+
+// This block is a meme among memes
+ width = (0x78 - GetStringWidth(0, gUnknown_08617E9B, 0)) / 2;
+ box_print(2, 0, width, 3, gUnknown_0861815B, -1, gUnknown_08617E9B);
+ width = (s32)(0x78 - GetStringWidth(0, gUnknown_08617E9B, 0)) / 2 + 0x78;
+ box_print(2, 0, width, 3, gUnknown_0861815B, -1, gUnknown_08617E8D);
+ width = (0x70 - GetStringWidth(0, gUnknown_08617E8D, 0)) / 2;
+ box_print(3, 0, width, 0, gUnknown_0861815B, -1, gUnknown_08617E8D);
+ width = (0xd0 - GetStringWidth(1, gUnknown_08617E78, 0)) / 2;
+ box_print(0, 1, width, 2, gUnknown_08618158, -1, gUnknown_08617E78);
+
+ CopyWindowToVram(2, 2);
+ CopyWindowToVram(3, 2);
+ CopyWindowToVram(0, 2);
+}
+
+#else
+__attribute__((naked)) static void berry_fix_gpu_set(void)
+{
+ asm(".syntax unified\n"
+ "\tpush {r4-r6,lr}\n"
+ "\tmov r6, r8\n"
+ "\tpush {r6}\n"
+ "\tsub sp, 0x10\n"
+ "\tmovs r0, 0x8\n"
+ "\tmovs r1, 0\n"
+ "\tbl SetGpuReg\n"
+ "\tmovs r0, 0xA\n"
+ "\tmovs r1, 0\n"
+ "\tbl SetGpuReg\n"
+ "\tmovs r0, 0x10\n"
+ "\tmovs r1, 0\n"
+ "\tbl SetGpuReg\n"
+ "\tmovs r0, 0x12\n"
+ "\tmovs r1, 0\n"
+ "\tbl SetGpuReg\n"
+ "\tmovs r0, 0x14\n"
+ "\tmovs r1, 0\n"
+ "\tbl SetGpuReg\n"
+ "\tmovs r0, 0x16\n"
+ "\tmovs r1, 0\n"
+ "\tbl SetGpuReg\n"
+ "\tmovs r0, 0x50\n"
+ "\tmovs r1, 0\n"
+ "\tbl SetGpuReg\n"
+ "\tmovs r1, 0\n"
+ "\tstr r1, [sp, 0xC]\n"
+ "\tldr r4, =0x040000d4\n"
+ "\tadd r0, sp, 0xC\n"
+ "\tstr r0, [r4]\n"
+ "\tmovs r0, 0xC0\n"
+ "\tlsls r0, 19\n"
+ "\tstr r0, [r4, 0x4]\n"
+ "\tldr r0, =0x85006000\n"
+ "\tstr r0, [r4, 0x8]\n"
+ "\tldr r0, [r4, 0x8]\n"
+ "\tstr r1, [sp, 0xC]\n"
+ "\tadd r0, sp, 0xC\n"
+ "\tstr r0, [r4]\n"
+ "\tmovs r0, 0xE0\n"
+ "\tlsls r0, 19\n"
+ "\tstr r0, [r4, 0x4]\n"
+ "\tldr r2, =0x85000100\n"
+ "\tstr r2, [r4, 0x8]\n"
+ "\tldr r0, [r4, 0x8]\n"
+ "\tstr r1, [sp, 0xC]\n"
+ "\tadd r0, sp, 0xC\n"
+ "\tstr r0, [r4]\n"
+ "\tmovs r0, 0xA0\n"
+ "\tlsls r0, 19\n"
+ "\tstr r0, [r4, 0x4]\n"
+ "\tstr r2, [r4, 0x8]\n"
+ "\tldr r0, [r4, 0x8]\n"
+ "\tmovs r0, 0\n"
+ "\tbl ResetBgsAndClearDma3BusyFlags\n"
+ "\tldr r1, =gUnknown_08618108\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r2, 0x2\n"
+ "\tbl InitBgsFromTemplates\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r2, 0\n"
+ "\tbl ChangeBgX\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r2, 0\n"
+ "\tbl ChangeBgY\n"
+ "\tmovs r0, 0x1\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r2, 0\n"
+ "\tbl ChangeBgX\n"
+ "\tmovs r0, 0x1\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r2, 0\n"
+ "\tbl ChangeBgY\n"
+ "\tldr r0, =gUnknown_08618110\n"
+ "\tbl InitWindows\n"
+ "\tbl DeactivateAllTextPrinters\n"
+ "\tldr r0, =gUnknown_08618138\n"
+ "\tstr r0, [r4]\n"
+ "\tldr r0, =0x050001e0\n"
+ "\tstr r0, [r4, 0x4]\n"
+ "\tldr r0, =0x84000008\n"
+ "\tstr r0, [r4, 0x8]\n"
+ "\tldr r0, [r4, 0x8]\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r1, 0x40\n"
+ "\tbl SetGpuReg\n"
+ "\tmovs r0, 0x2\n"
+ "\tmovs r1, 0\n"
+ "\tbl FillWindowPixelBuffer\n"
+ "\tmovs r0, 0x3\n"
+ "\tmovs r1, 0\n"
+ "\tbl FillWindowPixelBuffer\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r1, 0xAA\n"
+ "\tbl FillWindowPixelBuffer\n"
+ "\tldr r5, =gUnknown_08617E9B\n"
+ "\tmovs r0, 0\n"
+ "\tadds r1, r5, 0\n"
+ "\tmovs r2, 0\n"
+ "\tbl GetStringWidth\n"
+ "\tadds r1, r0, 0\n"
+ "\tmovs r4, 0x78\n"
+ "\tsubs r0, r4, r1\n"
+ "\tlsrs r1, r0, 31\n"
+ "\tadds r0, r1\n"
+ "\tasrs r0, 1\n"
+ "\tlsls r2, r0, 24\n"
+ "\tlsrs r2, 24\n"
+ "\tldr r6, =gUnknown_0861815B\n"
+ "\tstr r6, [sp]\n"
+ "\tmovs r0, 0x1\n"
+ "\tnegs r0, r0\n"
+ "\tmov r8, r0\n"
+ "\tstr r0, [sp, 0x4]\n"
+ "\tstr r5, [sp, 0x8]\n"
+ "\tmovs r0, 0x2\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r3, 0x3\n"
+ "\tbl box_print\n"
+ "\tldr r5, =gUnknown_08617E8D\n"
+ "\tmovs r0, 0\n"
+ "\tadds r1, r5, 0\n"
+ "\tmovs r2, 0\n"
+ "\tbl GetStringWidth\n"
+ "\tadds r1, r0, 0\n"
+ "\tsubs r4, r1\n"
+ "\tlsrs r0, r4, 31\n"
+ "\tadds r4, r0\n"
+ "\tasrs r4, 1\n"
+ "\tadds r0, r4, 0\n"
+ "\tadds r0, 0x78\n"
+ "\tlsls r2, r0, 24\n"
+ "\tlsrs r2, 24\n"
+ "\tstr r6, [sp]\n"
+ "\tmov r0, r8\n"
+ "\tstr r0, [sp, 0x4]\n"
+ "\tstr r5, [sp, 0x8]\n"
+ "\tmovs r0, 0x2\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r3, 0x3\n"
+ "\tbl box_print\n"
+ "\tmovs r0, 0\n"
+ "\tadds r1, r5, 0\n"
+ "\tmovs r2, 0\n"
+ "\tbl GetStringWidth\n"
+ "\tadds r1, r0, 0\n"
+ "\tmovs r0, 0x70\n"
+ "\tsubs r0, r1\n"
+ "\tlsrs r1, r0, 31\n"
+ "\tadds r0, r1\n"
+ "\tasrs r0, 1\n"
+ "\tlsls r2, r0, 24\n"
+ "\tlsrs r2, 24\n"
+ "\tstr r6, [sp]\n"
+ "\tmov r0, r8\n"
+ "\tstr r0, [sp, 0x4]\n"
+ "\tstr r5, [sp, 0x8]\n"
+ "\tmovs r0, 0x3\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r3, 0\n"
+ "\tbl box_print\n"
+ "\tldr r4, =gUnknown_08617E78\n"
+ "\tmovs r0, 0x1\n"
+ "\tadds r1, r4, 0\n"
+ "\tmovs r2, 0\n"
+ "\tbl GetStringWidth\n"
+ "\tadds r1, r0, 0\n"
+ "\tmovs r0, 0xD0\n"
+ "\tsubs r0, r1\n"
+ "\tlsrs r1, r0, 31\n"
+ "\tadds r0, r1\n"
+ "\tasrs r0, 1\n"
+ "\tlsls r2, r0, 24\n"
+ "\tlsrs r2, 24\n"
+ "\tldr r0, =gUnknown_08618158\n"
+ "\tstr r0, [sp]\n"
+ "\tmov r0, r8\n"
+ "\tstr r0, [sp, 0x4]\n"
+ "\tstr r4, [sp, 0x8]\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r1, 0x1\n"
+ "\tmovs r3, 0x2\n"
+ "\tbl box_print\n"
+ "\tmovs r0, 0x2\n"
+ "\tmovs r1, 0x2\n"
+ "\tbl CopyWindowToVram\n"
+ "\tmovs r0, 0x3\n"
+ "\tmovs r1, 0x2\n"
+ "\tbl CopyWindowToVram\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r1, 0x2\n"
+ "\tbl CopyWindowToVram\n"
+ "\tadd sp, 0x10\n"
+ "\tpop {r3}\n"
+ "\tmov r8, r3\n"
+ "\tpop {r4-r6}\n"
+ "\tpop {r0}\n"
+ "\tbx r0\n"
+ "\t.pool\n"
+ ".syntax divided");
+}
+#endif
+
+static int berry_fix_text_update(int checkval)
+{
+ if (berry_fix_mb_manager->unk1 == checkval)
+ {
+ return checkval;
+ }
+ if (berry_fix_mb_manager->unk1 == 6)
+ {
+ berry_fix_text_print(checkval);
+ berry_fix_mb_manager->unk1 = checkval;
+ }
+ else
+ {
+ berry_fix_bg_hide();
+ berry_fix_mb_manager->unk1 = 6;
+ }
+ return berry_fix_mb_manager->unk1;
+}
+
+static void berry_fix_text_print(int scene)
+{
+ FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 32, 32);
+ FillWindowPixelBuffer(1, 0xAA);
+ box_print(1, 1, 0, 0, gUnknown_08618158, -1, gUnknown_08618160[scene]);
+ PutWindowTilemap(1);
+ CopyWindowToVram(1, 2);
+ switch (scene)
+ {
+ case 0:
+ case 2:
+ case 3:
+ case 4:
+ PutWindowTilemap(2);
+ break;
+ case 1:
+ PutWindowTilemap(3);
+ break;
+ case 5:
+ PutWindowTilemap(0);
+ break;
+ }
+ CopyBgTilemapBufferToVram(0);
+ LZ77UnCompVram(gUnknown_08618178[scene][0], (void *)BG_CHAR_ADDR(1));
+ LZ77UnCompVram(gUnknown_08618178[scene][1], (void *)BG_SCREEN_ADDR(31));
+ CpuCopy32(gUnknown_08618178[scene][2], (void *)BG_PLTT, 0x100);
+ ShowBg(0);
+ ShowBg(1);
+}
+
+static void berry_fix_bg_hide()
+{
+ HideBg(0);
+ HideBg(1);
+}
diff --git a/src/bg.c b/src/bg.c
index 8979eaecd..74e3ea830 100644
--- a/src/bg.c
+++ b/src/bg.c
@@ -1,20 +1,12 @@
#include "global.h"
+#include "bg.h"
#include "dma3.h"
+#include "gpu_regs.h"
-#define DISPCNT_ALL_BG_AND_MODE_BITS 0x0F07
-
-enum {
- BG_CTRL_ATTR_VISIBLE = 1,
- BG_CTRL_ATTR_CHARBASEINDEX = 2,
- BG_CTRL_ATTR_MAPBASEINDEX = 3,
- BG_CTRL_ATTR_SCREENSIZE = 4,
- BG_CTRL_ATTR_PALETTEMODE = 5,
- BG_CTRL_ATTR_PRIORITY = 6,
- BG_CTRL_ATTR_MOSAIC = 7,
- BG_CTRL_ATTR_WRAPAROUND = 8,
-};
+#define DISPCNT_ALL_BG_AND_MODE_BITS (DISPCNT_BG_ALL_ON | 0x7)
-struct BgControl {
+struct BgControl
+{
struct BgConfig {
u16 visible:1;
u16 unknown_1:1;
@@ -22,88 +14,61 @@ struct BgControl {
u16 priority:2;
u16 mosaic:1;
u16 wraparound:1;
-
+
u16 charBaseIndex:2;
u16 mapBaseIndex:5;
u16 paletteMode:1;
-
+
u8 unknown_2;
u8 unknown_3;
} configs[4];
-
- u16 bgVisibilityAndMode;
-};
-struct BgTemplate {
- u32 bg:2;
- u32 charBaseIndex:2;
- u32 mapBaseIndex:5;
- u32 screenSize:2;
- u32 paletteMode:1;
- u32 priority:2;
- u32 baseTile:10;
+ u16 bgVisibilityAndMode;
};
-struct BgConfig2 {
+struct BgConfig2
+{
u32 baseTile:10;
u32 basePalette:4;
u32 unk_3:18;
-
+
void* tilemap;
u32 bg_x;
u32 bg_y;
};
-static struct BgControl gGpuBgConfigs;
-static struct BgConfig2 gGpuBgConfigs2[4];
-static u32 gDmaBusyBitfield[4];
+static IWRAM_DATA struct BgControl sGpuBgConfigs;
+static IWRAM_DATA struct BgConfig2 sGpuBgConfigs2[4];
+static IWRAM_DATA u32 sDmaBusyBitfield[4];
u32 gUnneededFireRedVariable;
-static const struct BgConfig gZeroedBgControlStruct = { 0 };
-
-extern void SetGpuReg(u8 regOffset, u16 value);
-extern void SetGpuReg_ForcedBlank(u8 regOffset, u16 value);
-extern u16 GetGpuReg(u8 regOffset);
-extern int CheckForSpaceForDma3Request(s16 index);
-
-bool32 IsInvalidBg32(u8);
-void ResetBgControlStructs();
-u16 GetBgMetricTextMode(u8, u8);
-u32 GetBgMetricAffineMode(u8, u8);
-u32 GetBgType(u8);
-void SetTextModeAndHideBgs();
-bool8 IsInvalidBg(u8);
-bool32 IsTileMapOutsideWram(u8);
-void CopyRectToBgTilemapBufferRect(u8, void*, u8, u8, u8, u8, u8, u8, u8, u8, u8, u16, u16);
-void CopyTileMapEntry(u16*, u16*, s32, u32, u32);
-u32 GetTileMapIndexFromCoords(s32, s32, s32, u32, u32);
-void WriteSequenceToBgTilemapBuffer(u8, u16, u8, u8, u8, u8, u8, s16);
+static const struct BgConfig sZeroedBgControlStruct = { 0 };
void ResetBgs(void)
{
ResetBgControlStructs();
- gGpuBgConfigs.bgVisibilityAndMode = 0;
+ sGpuBgConfigs.bgVisibilityAndMode = 0;
SetTextModeAndHideBgs();
}
-void SetBgModeInternal(u8 bgMode)
+static void SetBgModeInternal(u8 bgMode)
{
- gGpuBgConfigs.bgVisibilityAndMode &= 0xFFF8;
- gGpuBgConfigs.bgVisibilityAndMode |= bgMode;
+ sGpuBgConfigs.bgVisibilityAndMode &= 0xFFF8;
+ sGpuBgConfigs.bgVisibilityAndMode |= bgMode;
}
u8 GetBgMode(void)
{
- return gGpuBgConfigs.bgVisibilityAndMode & 0x7;
+ return sGpuBgConfigs.bgVisibilityAndMode & 0x7;
}
void ResetBgControlStructs(void)
{
- struct BgConfig* bgConfigs = &gGpuBgConfigs.configs[0];
- struct BgConfig zeroedConfig = gZeroedBgControlStruct;
+ struct BgConfig* bgConfigs = &sGpuBgConfigs.configs[0];
+ struct BgConfig zeroedConfig = sZeroedBgControlStruct;
int i;
-
+
for (i = 0; i < 4; i++)
{
bgConfigs[i] = zeroedConfig;
@@ -114,7 +79,7 @@ void Unused_ResetBgControlStruct(u8 bg)
{
if (IsInvalidBg(bg) == FALSE)
{
- gGpuBgConfigs.configs[bg] = gZeroedBgControlStruct;
+ sGpuBgConfigs.configs[bg] = sZeroedBgControlStruct;
}
}
@@ -124,98 +89,98 @@ void SetBgControlAttributes(u8 bg, u8 charBaseIndex, u8 mapBaseIndex, u8 screenS
{
if (charBaseIndex != 0xFF)
{
- gGpuBgConfigs.configs[bg].charBaseIndex = charBaseIndex & 0x3;
+ sGpuBgConfigs.configs[bg].charBaseIndex = charBaseIndex & 0x3;
}
-
+
if (mapBaseIndex != 0xFF)
{
- gGpuBgConfigs.configs[bg].mapBaseIndex = mapBaseIndex & 0x1F;
+ sGpuBgConfigs.configs[bg].mapBaseIndex = mapBaseIndex & 0x1F;
}
-
+
if (screenSize != 0xFF)
{
- gGpuBgConfigs.configs[bg].screenSize = screenSize & 0x3;
+ sGpuBgConfigs.configs[bg].screenSize = screenSize & 0x3;
}
-
+
if (paletteMode != 0xFF)
{
- gGpuBgConfigs.configs[bg].paletteMode = paletteMode;
+ sGpuBgConfigs.configs[bg].paletteMode = paletteMode;
}
-
+
if (priority != 0xFF)
{
- gGpuBgConfigs.configs[bg].priority = priority & 0x3;
+ sGpuBgConfigs.configs[bg].priority = priority & 0x3;
}
-
+
if (mosaic != 0xFF)
{
- gGpuBgConfigs.configs[bg].mosaic = mosaic & 0x1;
+ sGpuBgConfigs.configs[bg].mosaic = mosaic & 0x1;
}
-
+
if (wraparound != 0xFF)
{
- gGpuBgConfigs.configs[bg].wraparound = wraparound;
+ sGpuBgConfigs.configs[bg].wraparound = wraparound;
}
-
- gGpuBgConfigs.configs[bg].unknown_2 = 0;
- gGpuBgConfigs.configs[bg].unknown_3 = 0;
-
- gGpuBgConfigs.configs[bg].visible = 1;
+
+ sGpuBgConfigs.configs[bg].unknown_2 = 0;
+ sGpuBgConfigs.configs[bg].unknown_3 = 0;
+
+ sGpuBgConfigs.configs[bg].visible = 1;
}
}
u16 GetBgControlAttribute(u8 bg, u8 attributeId)
{
- if (IsInvalidBg(bg) == FALSE && gGpuBgConfigs.configs[bg].visible != FALSE)
+ if (IsInvalidBg(bg) == FALSE && sGpuBgConfigs.configs[bg].visible != FALSE)
{
switch (attributeId)
{
case BG_CTRL_ATTR_VISIBLE:
- return gGpuBgConfigs.configs[bg].visible;
+ return sGpuBgConfigs.configs[bg].visible;
case BG_CTRL_ATTR_CHARBASEINDEX:
- return gGpuBgConfigs.configs[bg].charBaseIndex;
+ return sGpuBgConfigs.configs[bg].charBaseIndex;
case BG_CTRL_ATTR_MAPBASEINDEX:
- return gGpuBgConfigs.configs[bg].mapBaseIndex;
+ return sGpuBgConfigs.configs[bg].mapBaseIndex;
case BG_CTRL_ATTR_SCREENSIZE:
- return gGpuBgConfigs.configs[bg].screenSize;
+ return sGpuBgConfigs.configs[bg].screenSize;
case BG_CTRL_ATTR_PALETTEMODE:
- return gGpuBgConfigs.configs[bg].paletteMode;
+ return sGpuBgConfigs.configs[bg].paletteMode;
case BG_CTRL_ATTR_PRIORITY:
- return gGpuBgConfigs.configs[bg].priority;
+ return sGpuBgConfigs.configs[bg].priority;
case BG_CTRL_ATTR_MOSAIC:
- return gGpuBgConfigs.configs[bg].mosaic;
+ return sGpuBgConfigs.configs[bg].mosaic;
case BG_CTRL_ATTR_WRAPAROUND:
- return gGpuBgConfigs.configs[bg].wraparound;
+ return sGpuBgConfigs.configs[bg].wraparound;
}
}
-
+
return 0xFF;
}
-u8 LoadBgVram(u8 bg, void *src, u16 size, u16 destOffset, u8 mode)
+u8 LoadBgVram(u8 bg, const void *src, u16 size, u16 destOffset, u8 mode)
{
u16 offset;
s8 cursor;
-
- if (IsInvalidBg(bg) == FALSE && gGpuBgConfigs.configs[bg].visible != FALSE)
+
+ if (IsInvalidBg(bg) == FALSE && sGpuBgConfigs.configs[bg].visible != FALSE)
{
switch (mode)
{
case 0x1:
- offset = gGpuBgConfigs.configs[bg].charBaseIndex * BG_CHAR_SIZE;
+ offset = sGpuBgConfigs.configs[bg].charBaseIndex * BG_CHAR_SIZE;
break;
case 0x2:
- offset = gGpuBgConfigs.configs[bg].mapBaseIndex * BG_SCREEN_SIZE;
+ offset = sGpuBgConfigs.configs[bg].mapBaseIndex * BG_SCREEN_SIZE;
break;
default:
cursor = -1;
goto end;
}
-
+
offset = destOffset + offset;
-
+
cursor = RequestDma3Copy(src, (void*)(offset + BG_VRAM), size, 0);
-
+
if (cursor == -1)
{
return -1;
@@ -225,56 +190,56 @@ u8 LoadBgVram(u8 bg, void *src, u16 size, u16 destOffset, u8 mode)
{
return -1;
}
-
+
end:
return cursor;
}
-void ShowBgInternal(u8 bg)
+static void ShowBgInternal(u8 bg)
{
u16 value;
- if (IsInvalidBg(bg) == FALSE && gGpuBgConfigs.configs[bg].visible != FALSE)
+ if (IsInvalidBg(bg) == FALSE && sGpuBgConfigs.configs[bg].visible != FALSE)
{
- value = gGpuBgConfigs.configs[bg].priority |
- (gGpuBgConfigs.configs[bg].charBaseIndex << 2) |
- (gGpuBgConfigs.configs[bg].mosaic << 6) |
- (gGpuBgConfigs.configs[bg].paletteMode << 7) |
- (gGpuBgConfigs.configs[bg].mapBaseIndex << 8) |
- (gGpuBgConfigs.configs[bg].wraparound << 13) |
- (gGpuBgConfigs.configs[bg].screenSize << 14);
-
+ value = sGpuBgConfigs.configs[bg].priority |
+ (sGpuBgConfigs.configs[bg].charBaseIndex << 2) |
+ (sGpuBgConfigs.configs[bg].mosaic << 6) |
+ (sGpuBgConfigs.configs[bg].paletteMode << 7) |
+ (sGpuBgConfigs.configs[bg].mapBaseIndex << 8) |
+ (sGpuBgConfigs.configs[bg].wraparound << 13) |
+ (sGpuBgConfigs.configs[bg].screenSize << 14);
+
SetGpuReg((bg << 1) + 0x8, value);
-
- gGpuBgConfigs.bgVisibilityAndMode |= 1 << (bg + 8);
- gGpuBgConfigs.bgVisibilityAndMode &= DISPCNT_ALL_BG_AND_MODE_BITS;
+
+ sGpuBgConfigs.bgVisibilityAndMode |= 1 << (bg + 8);
+ sGpuBgConfigs.bgVisibilityAndMode &= DISPCNT_ALL_BG_AND_MODE_BITS;
}
}
-void HideBgInternal(u8 bg)
+static void HideBgInternal(u8 bg)
{
if (IsInvalidBg(bg) == FALSE)
{
- gGpuBgConfigs.bgVisibilityAndMode &= ~(1 << (bg + 8));
- gGpuBgConfigs.bgVisibilityAndMode &= DISPCNT_ALL_BG_AND_MODE_BITS;
+ sGpuBgConfigs.bgVisibilityAndMode &= ~(1 << (bg + 8));
+ sGpuBgConfigs.bgVisibilityAndMode &= DISPCNT_ALL_BG_AND_MODE_BITS;
}
}
-void SyncBgVisibilityAndMode()
+static void SyncBgVisibilityAndMode(void)
{
- SetGpuReg(0, (GetGpuReg(0) & ~DISPCNT_ALL_BG_AND_MODE_BITS) | gGpuBgConfigs.bgVisibilityAndMode);
+ SetGpuReg(0, (GetGpuReg(0) & ~DISPCNT_ALL_BG_AND_MODE_BITS) | sGpuBgConfigs.bgVisibilityAndMode);
}
-void SetTextModeAndHideBgs()
+void SetTextModeAndHideBgs(void)
{
SetGpuReg(0, GetGpuReg(0) & ~DISPCNT_ALL_BG_AND_MODE_BITS);
}
-void SetBgAffineInternal(u8 bg, u32 srcCenterX, u32 srcCenterY, s16 dispCenterX, s16 dispCenterY, s16 scaleX, s16 scaleY, u16 rotationAngle)
+static void SetBgAffineInternal(u8 bg, u32 srcCenterX, u32 srcCenterY, s16 dispCenterX, s16 dispCenterY, s16 scaleX, s16 scaleY, u16 rotationAngle)
{
struct BgAffineSrcData src;
struct BgAffineDstData dest;
-
- switch (gGpuBgConfigs.bgVisibilityAndMode & 0x7)
+
+ switch (sGpuBgConfigs.bgVisibilityAndMode & 0x7)
{
case 1:
if (bg != 2)
@@ -288,7 +253,7 @@ void SetBgAffineInternal(u8 bg, u32 srcCenterX, u32 srcCenterY, s16 dispCenterX,
default:
return;
}
-
+
src.texX = srcCenterX;
src.texY = srcCenterY;
src.scrX = dispCenterX;
@@ -296,7 +261,7 @@ void SetBgAffineInternal(u8 bg, u32 srcCenterX, u32 srcCenterY, s16 dispCenterX,
src.sx = scaleX;
src.sy = scaleY;
src.alpha = rotationAngle;
-
+
BgAffineSet(&src, &dest, 1);
SetGpuReg(REG_OFFSET_BG2PA, dest.pa);
@@ -326,20 +291,20 @@ void ResetBgsAndClearDma3BusyFlags(u32 leftoverFireRedLeafGreenVariable)
{
int i;
ResetBgs();
-
+
for (i = 0; i < 4; i++)
{
- gDmaBusyBitfield[i] = 0;
+ sDmaBusyBitfield[i] = 0;
}
-
+
gUnneededFireRedVariable = leftoverFireRedLeafGreenVariable;
}
-void InitBgsFromTemplates(u8 bgMode, struct BgTemplate *templates, u8 numTemplates)
+void InitBgsFromTemplates(u8 bgMode, const struct BgTemplate *templates, u8 numTemplates)
{
int i;
u8 bg;
-
+
SetBgModeInternal(bgMode);
ResetBgControlStructs();
@@ -355,22 +320,22 @@ void InitBgsFromTemplates(u8 bgMode, struct BgTemplate *templates, u8 numTemplat
templates[i].priority,
0,
0);
-
- gGpuBgConfigs2[bg].baseTile = templates[i].baseTile;
- gGpuBgConfigs2[bg].basePalette = 0;
- gGpuBgConfigs2[bg].unk_3 = 0;
-
- gGpuBgConfigs2[bg].tilemap = NULL;
- gGpuBgConfigs2[bg].bg_x = 0;
- gGpuBgConfigs2[bg].bg_y = 0;
+
+ sGpuBgConfigs2[bg].baseTile = templates[i].baseTile;
+ sGpuBgConfigs2[bg].basePalette = 0;
+ sGpuBgConfigs2[bg].unk_3 = 0;
+
+ sGpuBgConfigs2[bg].tilemap = NULL;
+ sGpuBgConfigs2[bg].bg_x = 0;
+ sGpuBgConfigs2[bg].bg_y = 0;
}
}
}
-void InitBgFromTemplate(struct BgTemplate *template)
+void InitBgFromTemplate(const struct BgTemplate *template)
{
u8 bg = template->bg;
-
+
if (bg < 4)
{
SetBgControlAttributes(bg,
@@ -381,14 +346,14 @@ void InitBgFromTemplate(struct BgTemplate *template)
template->priority,
0,
0);
-
- gGpuBgConfigs2[bg].baseTile = template->baseTile;
- gGpuBgConfigs2[bg].basePalette = 0;
- gGpuBgConfigs2[bg].unk_3 = 0;
-
- gGpuBgConfigs2[bg].tilemap = NULL;
- gGpuBgConfigs2[bg].bg_x = 0;
- gGpuBgConfigs2[bg].bg_y = 0;
+
+ sGpuBgConfigs2[bg].baseTile = template->baseTile;
+ sGpuBgConfigs2[bg].basePalette = 0;
+ sGpuBgConfigs2[bg].unk_3 = 0;
+
+ sGpuBgConfigs2[bg].tilemap = NULL;
+ sGpuBgConfigs2[bg].bg_x = 0;
+ sGpuBgConfigs2[bg].bg_y = 0;
}
}
@@ -397,63 +362,63 @@ void SetBgMode(u8 bgMode)
SetBgModeInternal(bgMode);
}
-u16 LoadBgTiles(u8 bg, void* src, u16 size, u16 destOffset)
+u16 LoadBgTiles(u8 bg, const void* src, u16 size, u16 destOffset)
{
u16 tileOffset;
u8 cursor;
-
+
if (GetBgControlAttribute(bg, BG_CTRL_ATTR_PALETTEMODE) == 0)
{
- tileOffset = (gGpuBgConfigs2[bg].baseTile + destOffset) * 0x20;
+ tileOffset = (sGpuBgConfigs2[bg].baseTile + destOffset) * 0x20;
}
else
{
- tileOffset = (gGpuBgConfigs2[bg].baseTile + destOffset) * 0x40;
+ tileOffset = (sGpuBgConfigs2[bg].baseTile + destOffset) * 0x40;
}
-
+
cursor = LoadBgVram(bg, src, size, tileOffset, DISPCNT_MODE_1);
-
+
if (cursor == 0xFF)
{
return -1;
}
-
- gDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
-
+
+ sDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
+
if (gUnneededFireRedVariable == 1)
{
DummiedOutFireRedLeafGreenTileAllocFunc(bg, tileOffset / 0x20, size / 0x20, 1);
}
-
+
return cursor;
}
-u16 LoadBgTilemap(u8 bg, void *src, u16 size, u16 destOffset)
+u16 LoadBgTilemap(u8 bg, const void *src, u16 size, u16 destOffset)
{
u8 cursor;
-
+
cursor = LoadBgVram(bg, src, size, destOffset * 2, DISPCNT_MODE_2);
-
+
if (cursor == 0xFF)
{
return -1;
}
-
- gDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
-
+
+ sDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
+
return cursor;
}
-u16 Unused_LoadBgPalette(u8 bg, void *src, u16 size, u16 destOffset)
+u16 Unused_LoadBgPalette(u8 bg, const void *src, u16 size, u16 destOffset)
{
u16 paletteOffset;
s8 cursor;
-
+
if (IsInvalidBg32(bg) == FALSE)
{
- paletteOffset = (gGpuBgConfigs2[bg].basePalette * 0x20) + (destOffset * 2);
+ paletteOffset = (sGpuBgConfigs2[bg].basePalette * 0x20) + (destOffset * 2);
cursor = RequestDma3Copy(src, (void*)(paletteOffset + BG_PLTT), size, 0);
-
+
if (cursor == -1)
{
return -1;
@@ -464,7 +429,7 @@ u16 Unused_LoadBgPalette(u8 bg, void *src, u16 size, u16 destOffset)
return -1;
}
- gDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
+ sDmaBusyBitfield[cursor / 0x20] |= (1 << (cursor % 0x20));
return (u8)cursor;
}
@@ -475,23 +440,23 @@ bool8 IsDma3ManagerBusyWithBgCopy(void)
u8 mod;
u8 div;
s8 reqSpace;
-
+
int i;
-
+
for (i = 0; i < 0x80; i++)
{
div = i / 0x20;
mod = i % 0x20;
-
- if ((gDmaBusyBitfield[div] & (1 << mod)) != FALSE)
+
+ if ((sDmaBusyBitfield[div] & (1 << mod)) != FALSE)
{
reqSpace = CheckForSpaceForDma3Request(i);
if (reqSpace == -1)
{
return TRUE;
}
-
- gDmaBusyBitfield[div] &= ~(1 << mod);
+
+ sDmaBusyBitfield[div] &= ~(1 << mod);
}
}
@@ -517,7 +482,7 @@ _08001AE4:\n\
sub r0, r5, r0\n\
lsl r0, #24\n\
lsr r0, #24\n\
- ldr r1, =gDmaBusyBitfield\n\
+ ldr r1, =sDmaBusyBitfield\n\
lsr r2, #22\n\
add r4, r2, r1\n\
mov r6, #0x1\n\
@@ -623,7 +588,7 @@ u16 GetBgAttribute(u8 bg, u8 attributeId)
case 9:
return GetBgType(bg);
case 10:
- return gGpuBgConfigs2[bg].baseTile;
+ return sGpuBgConfigs2[bg].baseTile;
default:
return -1;
}
@@ -634,48 +599,48 @@ u32 ChangeBgX(u8 bg, u32 value, u8 op)
u8 mode;
u16 temp1;
u16 temp2;
-
+
if (IsInvalidBg32(bg) != FALSE || GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) == 0)
{
return -1;
}
-
+
switch (op)
{
case 0:
default:
- gGpuBgConfigs2[bg].bg_x = value;
+ sGpuBgConfigs2[bg].bg_x = value;
break;
case 1:
- gGpuBgConfigs2[bg].bg_x += value;
+ sGpuBgConfigs2[bg].bg_x += value;
break;
case 2:
- gGpuBgConfigs2[bg].bg_x -= value;
+ sGpuBgConfigs2[bg].bg_x -= value;
break;
}
-
+
mode = GetBgMode();
-
+
switch (bg)
{
case 0:
- temp1 = gGpuBgConfigs2[0].bg_x >> 0x8;
+ temp1 = sGpuBgConfigs2[0].bg_x >> 0x8;
SetGpuReg(REG_OFFSET_BG0HOFS, temp1);
break;
case 1:
- temp1 = gGpuBgConfigs2[1].bg_x >> 0x8;
+ temp1 = sGpuBgConfigs2[1].bg_x >> 0x8;
SetGpuReg(REG_OFFSET_BG1HOFS, temp1);
break;
case 2:
if (mode == 0)
{
- temp1 = gGpuBgConfigs2[2].bg_x >> 0x8;
+ temp1 = sGpuBgConfigs2[2].bg_x >> 0x8;
SetGpuReg(REG_OFFSET_BG2HOFS, temp1);
}
else
{
- temp1 = gGpuBgConfigs2[2].bg_x >> 0x10;
- temp2 = gGpuBgConfigs2[2].bg_x & 0xFFFF;
+ temp1 = sGpuBgConfigs2[2].bg_x >> 0x10;
+ temp2 = sGpuBgConfigs2[2].bg_x & 0xFFFF;
SetGpuReg(REG_OFFSET_BG2X_H, temp1);
SetGpuReg(REG_OFFSET_BG2X_L, temp2);
}
@@ -683,20 +648,20 @@ u32 ChangeBgX(u8 bg, u32 value, u8 op)
case 3:
if (mode == 0)
{
- temp1 = gGpuBgConfigs2[3].bg_x >> 0x8;
+ temp1 = sGpuBgConfigs2[3].bg_x >> 0x8;
SetGpuReg(REG_OFFSET_BG3HOFS, temp1);
}
else if (mode == 2)
{
- temp1 = gGpuBgConfigs2[3].bg_x >> 0x10;
- temp2 = gGpuBgConfigs2[3].bg_x & 0xFFFF;
+ temp1 = sGpuBgConfigs2[3].bg_x >> 0x10;
+ temp2 = sGpuBgConfigs2[3].bg_x & 0xFFFF;
SetGpuReg(REG_OFFSET_BG3X_H, temp1);
SetGpuReg(REG_OFFSET_BG3X_L, temp2);
}
break;
}
-
- return gGpuBgConfigs2[bg].bg_x;
+
+ return sGpuBgConfigs2[bg].bg_x;
}
u32 GetBgX(u8 bg)
@@ -705,7 +670,7 @@ u32 GetBgX(u8 bg)
return -1;
if (GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) == 0)
return -1;
- return gGpuBgConfigs2[bg].bg_x;
+ return sGpuBgConfigs2[bg].bg_x;
}
u32 ChangeBgY(u8 bg, u32 value, u8 op)
@@ -713,48 +678,48 @@ u32 ChangeBgY(u8 bg, u32 value, u8 op)
u8 mode;
u16 temp1;
u16 temp2;
-
+
if (IsInvalidBg32(bg) != FALSE || GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) == 0)
{
return -1;
}
-
+
switch (op)
{
case 0:
default:
- gGpuBgConfigs2[bg].bg_y = value;
+ sGpuBgConfigs2[bg].bg_y = value;
break;
case 1:
- gGpuBgConfigs2[bg].bg_y += value;
+ sGpuBgConfigs2[bg].bg_y += value;
break;
case 2:
- gGpuBgConfigs2[bg].bg_y -= value;
+ sGpuBgConfigs2[bg].bg_y -= value;
break;
}
-
+
mode = GetBgMode();
-
+
switch (bg)
{
case 0:
- temp1 = gGpuBgConfigs2[0].bg_y >> 0x8;
+ temp1 = sGpuBgConfigs2[0].bg_y >> 0x8;
SetGpuReg(REG_OFFSET_BG0VOFS, temp1);
break;
case 1:
- temp1 = gGpuBgConfigs2[1].bg_y >> 0x8;
+ temp1 = sGpuBgConfigs2[1].bg_y >> 0x8;
SetGpuReg(REG_OFFSET_BG1VOFS, temp1);
break;
case 2:
if (mode == 0)
{
- temp1 = gGpuBgConfigs2[2].bg_y >> 0x8;
+ temp1 = sGpuBgConfigs2[2].bg_y >> 0x8;
SetGpuReg(REG_OFFSET_BG2VOFS, temp1);
}
else
{
- temp1 = gGpuBgConfigs2[2].bg_y >> 0x10;
- temp2 = gGpuBgConfigs2[2].bg_y & 0xFFFF;
+ temp1 = sGpuBgConfigs2[2].bg_y >> 0x10;
+ temp2 = sGpuBgConfigs2[2].bg_y & 0xFFFF;
SetGpuReg(REG_OFFSET_BG2Y_H, temp1);
SetGpuReg(REG_OFFSET_BG2Y_L, temp2);
}
@@ -762,20 +727,20 @@ u32 ChangeBgY(u8 bg, u32 value, u8 op)
case 3:
if (mode == 0)
{
- temp1 = gGpuBgConfigs2[3].bg_y >> 0x8;
+ temp1 = sGpuBgConfigs2[3].bg_y >> 0x8;
SetGpuReg(REG_OFFSET_BG3VOFS, temp1);
}
else if (mode == 2)
{
- temp1 = gGpuBgConfigs2[3].bg_y >> 0x10;
- temp2 = gGpuBgConfigs2[3].bg_y & 0xFFFF;
+ temp1 = sGpuBgConfigs2[3].bg_y >> 0x10;
+ temp2 = sGpuBgConfigs2[3].bg_y & 0xFFFF;
SetGpuReg(REG_OFFSET_BG3Y_H, temp1);
SetGpuReg(REG_OFFSET_BG3Y_L, temp2);
}
break;
}
-
- return gGpuBgConfigs2[bg].bg_y;
+
+ return sGpuBgConfigs2[bg].bg_y;
}
u32 ChangeBgY_ScreenOff(u8 bg, u32 value, u8 op)
@@ -783,49 +748,49 @@ u32 ChangeBgY_ScreenOff(u8 bg, u32 value, u8 op)
u8 mode;
u16 temp1;
u16 temp2;
-
+
if (IsInvalidBg32(bg) != FALSE || GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) == 0)
{
return -1;
}
-
+
switch (op)
{
case 0:
default:
- gGpuBgConfigs2[bg].bg_y = value;
+ sGpuBgConfigs2[bg].bg_y = value;
break;
case 1:
- gGpuBgConfigs2[bg].bg_y += value;
+ sGpuBgConfigs2[bg].bg_y += value;
break;
case 2:
- gGpuBgConfigs2[bg].bg_y -= value;
+ sGpuBgConfigs2[bg].bg_y -= value;
break;
}
-
+
mode = GetBgMode();
-
+
switch (bg)
{
case 0:
- temp1 = gGpuBgConfigs2[0].bg_y >> 0x8;
+ temp1 = sGpuBgConfigs2[0].bg_y >> 0x8;
SetGpuReg_ForcedBlank(REG_OFFSET_BG0VOFS, temp1);
break;
case 1:
- temp1 = gGpuBgConfigs2[1].bg_y >> 0x8;
+ temp1 = sGpuBgConfigs2[1].bg_y >> 0x8;
SetGpuReg_ForcedBlank(REG_OFFSET_BG1VOFS, temp1);
break;
case 2:
if (mode == 0)
{
- temp1 = gGpuBgConfigs2[2].bg_y >> 0x8;
+ temp1 = sGpuBgConfigs2[2].bg_y >> 0x8;
SetGpuReg_ForcedBlank(REG_OFFSET_BG2VOFS, temp1);
-
+
}
else
{
- temp1 = gGpuBgConfigs2[2].bg_y >> 0x10;
- temp2 = gGpuBgConfigs2[2].bg_y & 0xFFFF;
+ temp1 = sGpuBgConfigs2[2].bg_y >> 0x10;
+ temp2 = sGpuBgConfigs2[2].bg_y & 0xFFFF;
SetGpuReg_ForcedBlank(REG_OFFSET_BG2Y_H, temp1);
SetGpuReg_ForcedBlank(REG_OFFSET_BG2Y_L, temp2);
}
@@ -833,20 +798,20 @@ u32 ChangeBgY_ScreenOff(u8 bg, u32 value, u8 op)
case 3:
if (mode == 0)
{
- temp1 = gGpuBgConfigs2[3].bg_y >> 0x8;
+ temp1 = sGpuBgConfigs2[3].bg_y >> 0x8;
SetGpuReg_ForcedBlank(REG_OFFSET_BG3VOFS, temp1);
}
else if (mode == 2)
{
- temp1 = gGpuBgConfigs2[3].bg_y >> 0x10;
- temp2 = gGpuBgConfigs2[3].bg_y & 0xFFFF;
+ temp1 = sGpuBgConfigs2[3].bg_y >> 0x10;
+ temp2 = sGpuBgConfigs2[3].bg_y & 0xFFFF;
SetGpuReg_ForcedBlank(REG_OFFSET_BG3Y_H, temp1);
SetGpuReg_ForcedBlank(REG_OFFSET_BG3Y_L, temp2);
}
break;
}
-
- return gGpuBgConfigs2[bg].bg_y;
+
+ return sGpuBgConfigs2[bg].bg_y;
}
u32 GetBgY(u8 bg)
@@ -855,7 +820,7 @@ u32 GetBgY(u8 bg)
return -1;
if (GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) == 0)
return -1;
- return gGpuBgConfigs2[bg].bg_y;
+ return sGpuBgConfigs2[bg].bg_y;
}
void SetBgAffine(u8 bg, u32 srcCenterX, u32 srcCenterY, s16 dispCenterX, s16 dispCenterY, s16 scaleX, s16 scaleY, u16 rotationAngle)
@@ -868,13 +833,13 @@ u8 Unused_AdjustBgMosaic(u8 a1, u8 a2)
u16 result;
s16 test1;
s16 test2;
-
+
result = GetGpuReg(REG_OFFSET_MOSAIC);
-
+
test1 = result & 0xF;
test2 = (result >> 4) & 0xF;
result &= 0xFF00;
-
+
switch (a2)
{
case 0:
@@ -929,12 +894,12 @@ u8 Unused_AdjustBgMosaic(u8 a1, u8 a2)
}
break;
}
-
+
result |= ((test2 << 0x4) & 0xF0);
result |= (test1 & 0xF);
-
+
SetGpuReg(REG_OFFSET_MOSAIC, result);
-
+
return result;
}
@@ -942,7 +907,7 @@ void SetBgTilemapBuffer(u8 bg, void *tilemap)
{
if (IsInvalidBg32(bg) == FALSE && GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) != 0x0)
{
- gGpuBgConfigs2[bg].tilemap = tilemap;
+ sGpuBgConfigs2[bg].tilemap = tilemap;
}
}
@@ -950,7 +915,7 @@ void UnsetBgTilemapBuffer(u8 bg)
{
if (IsInvalidBg32(bg) == FALSE && GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) != 0x0)
{
- gGpuBgConfigs2[bg].tilemap = NULL;
+ sGpuBgConfigs2[bg].tilemap = NULL;
}
}
@@ -960,20 +925,20 @@ void* GetBgTilemapBuffer(u8 bg)
return NULL;
if (GetBgControlAttribute(bg, BG_CTRL_ATTR_VISIBLE) == 0)
return NULL;
- return gGpuBgConfigs2[bg].tilemap;
+ return sGpuBgConfigs2[bg].tilemap;
}
-void CopyToBgTilemapBuffer(u8 bg, void *src, u16 mode, u16 destOffset)
+void CopyToBgTilemapBuffer(u8 bg, const void *src, u16 mode, u16 destOffset)
{
if (IsInvalidBg32(bg) == FALSE && IsTileMapOutsideWram(bg) == FALSE)
{
if (mode != 0)
{
- CpuCopy16(src, (void *)(gGpuBgConfigs2[bg].tilemap + (destOffset * 2)), mode);
+ CpuCopy16(src, (void *)(sGpuBgConfigs2[bg].tilemap + (destOffset * 2)), mode);
}
else
{
- LZ77UnCompWram(src, (void *)(gGpuBgConfigs2[bg].tilemap + (destOffset * 2)));
+ LZ77UnCompWram(src, (void *)(sGpuBgConfigs2[bg].tilemap + (destOffset * 2)));
}
}
}
@@ -981,7 +946,7 @@ void CopyToBgTilemapBuffer(u8 bg, void *src, u16 mode, u16 destOffset)
void CopyBgTilemapBufferToVram(u8 bg)
{
u16 sizeToLoad;
-
+
if (IsInvalidBg32(bg) == FALSE && IsTileMapOutsideWram(bg) == FALSE)
{
switch (GetBgType(bg))
@@ -996,7 +961,7 @@ void CopyBgTilemapBufferToVram(u8 bg)
sizeToLoad = 0;
break;
}
- LoadBgVram(bg, gGpuBgConfigs2[bg].tilemap, sizeToLoad, 0, 2);
+ LoadBgVram(bg, sGpuBgConfigs2[bg].tilemap, sizeToLoad, 0, 2);
}
}
@@ -1006,7 +971,7 @@ void CopyToBgTilemapBufferRect(u8 bg, void* src, u8 destX, u8 destY, u8 width, u
u16 destX16;
u16 destY16;
u16 mode;
-
+
if (IsInvalidBg32(bg) == FALSE && IsTileMapOutsideWram(bg) == FALSE)
{
switch (GetBgType(bg))
@@ -1017,7 +982,7 @@ void CopyToBgTilemapBufferRect(u8 bg, void* src, u8 destX, u8 destY, u8 width, u
{
for (destX16 = destX; destX16 < (destX + width); destX16++)
{
- ((u16*)gGpuBgConfigs2[bg].tilemap)[((destY16 * 0x20) + destX16)] = *((u16*)srcCopy)++;
+ ((u16*)sGpuBgConfigs2[bg].tilemap)[((destY16 * 0x20) + destX16)] = *((u16*)srcCopy)++;
}
}
break;
@@ -1028,7 +993,7 @@ void CopyToBgTilemapBufferRect(u8 bg, void* src, u8 destX, u8 destY, u8 width, u
{
for (destX16 = destX; destX16 < (destX + width); destX16++)
{
- ((u8*)gGpuBgConfigs2[bg].tilemap)[((destY16 * mode) + destX16)] = *((u8*)srcCopy)++;
+ ((u8*)sGpuBgConfigs2[bg].tilemap)[((destY16 * mode) + destX16)] = *((u8*)srcCopy)++;
}
}
break;
@@ -1047,11 +1012,11 @@ void CopyRectToBgTilemapBufferRect(u8 bg, void* src, u8 srcX, u8 srcY, u8 srcWid
u16 attribute;
u16 mode;
u16 mode2;
-
+
void* srcCopy;
u16 destX16;
u16 destY16;
-
+
if (IsInvalidBg32(bg) == FALSE && IsTileMapOutsideWram(bg) == FALSE)
{
attribute = GetBgControlAttribute(bg, BG_CTRL_ATTR_SCREENSIZE);
@@ -1065,7 +1030,7 @@ void CopyRectToBgTilemapBufferRect(u8 bg, void* src, u8 srcX, u8 srcY, u8 srcWid
{
for (destX16 = destX; destX16 < (destX + rectWidth); destX16++)
{
- CopyTileMapEntry(&((u16*)srcCopy)[(srcY * rectWidth) + srcX], &((u16*)gGpuBgConfigs2[bg].tilemap)[GetTileMapIndexFromCoords(destX16, destY16, attribute, mode, mode2)], palette1, tileOffset, palette2);
+ CopyTileMapEntry(&((u16*)srcCopy)[(srcY * rectWidth) + srcX], &((u16*)sGpuBgConfigs2[bg].tilemap)[GetTileMapIndexFromCoords(destX16, destY16, attribute, mode, mode2)], palette1, tileOffset, palette2);
}
}
break;
@@ -1076,7 +1041,7 @@ void CopyRectToBgTilemapBufferRect(u8 bg, void* src, u8 srcX, u8 srcY, u8 srcWid
{
for (destX16 = destX; destX16 < (destX + rectWidth); destX16++)
{
- CopyTileMapEntry(&((u16*)srcCopy)[(srcY * rectWidth) + srcX], &((u16*)gGpuBgConfigs2[bg].tilemap)[GetTileMapIndexFromCoords(destX16, destY16, attribute, mode, mode2)], palette1, tileOffset, palette2);
+ CopyTileMapEntry(&((u16*)srcCopy)[(srcY * rectWidth) + srcX], &((u16*)sGpuBgConfigs2[bg].tilemap)[GetTileMapIndexFromCoords(destX16, destY16, attribute, mode, mode2)], palette1, tileOffset, palette2);
}
}
break;
@@ -1204,7 +1169,7 @@ _080025F8:\n\
bge _0800265A\n\
ldr r2, [sp, #0x4]\n\
lsl r0, r2, #4\n\
- ldr r1, =gGpuBgConfigs2+4\n\
+ ldr r1, =sGpuBgConfigs2+4\n\
add r0, r1\n\
mov r10, r0\n\
ldr r7, [sp, #0x20]\n\
@@ -1276,7 +1241,7 @@ _08002674:\n\
sub r2, r7, r2\n\
str r2, [sp, #0x34]\n\
str r0, [sp, #0x38]\n\
- ldr r7, =gGpuBgConfigs2+4\n\
+ ldr r7, =sGpuBgConfigs2+4\n\
mov r10, r7\n\
ldr r0, [sp, #0x4]\n\
lsl r0, #4\n\
@@ -1336,7 +1301,7 @@ void FillBgTilemapBufferRect_Palette0(u8 bg, u16 tileNum, u8 x, u8 y, u8 width,
u16 x16;
u16 y16;
u16 mode;
-
+
if (IsInvalidBg32(bg) == FALSE && IsTileMapOutsideWram(bg) == FALSE)
{
switch (GetBgType(bg))
@@ -1346,7 +1311,7 @@ void FillBgTilemapBufferRect_Palette0(u8 bg, u16 tileNum, u8 x, u8 y, u8 width,
{
for (x16 = x; x16 < (x + width); x16++)
{
- ((u16*)gGpuBgConfigs2[bg].tilemap)[((y16 * 0x20) + x16)] = tileNum;
+ ((u16*)sGpuBgConfigs2[bg].tilemap)[((y16 * 0x20) + x16)] = tileNum;
}
}
break;
@@ -1356,7 +1321,7 @@ void FillBgTilemapBufferRect_Palette0(u8 bg, u16 tileNum, u8 x, u8 y, u8 width,
{
for (x16 = x; x16 < (x + width); x16++)
{
- ((u8*)gGpuBgConfigs2[bg].tilemap)[((y16 * mode) + x16)] = tileNum;
+ ((u8*)sGpuBgConfigs2[bg].tilemap)[((y16 * mode) + x16)] = tileNum;
}
}
break;
@@ -1375,10 +1340,10 @@ void WriteSequenceToBgTilemapBuffer(u8 bg, u16 firstTileNum, u8 x, u8 y, u8 widt
u16 mode2;
u16 attribute;
u16 mode3;
-
+
u16 x16;
u16 y16;
-
+
if (IsInvalidBg32(bg) == FALSE && IsTileMapOutsideWram(bg) == FALSE)
{
attribute = GetBgControlAttribute(bg, BG_CTRL_ATTR_SCREENSIZE);
@@ -1391,7 +1356,7 @@ void WriteSequenceToBgTilemapBuffer(u8 bg, u16 firstTileNum, u8 x, u8 y, u8 widt
{
for (x16 = x; x16 < (x + width); x16++)
{
- CopyTileMapEntry(&firstTileNum, &((u16*)gGpuBgConfigs2[bg].tilemap)[(u16)GetTileMapIndexFromCoords(x16, y16, attribute, mode, mode2)], paletteSlot, 0, 0);
+ CopyTileMapEntry(&firstTileNum, &((u16*)sGpuBgConfigs2[bg].tilemap)[(u16)GetTileMapIndexFromCoords(x16, y16, attribute, mode, mode2)], paletteSlot, 0, 0);
firstTileNum = (firstTileNum & 0xFC00) + ((firstTileNum + tileNumDelta) & 0x3FF);
}
}
@@ -1402,7 +1367,7 @@ void WriteSequenceToBgTilemapBuffer(u8 bg, u16 firstTileNum, u8 x, u8 y, u8 widt
{
for (x16 = x; x16 < (x + width); x16++)
{
- ((u8*)gGpuBgConfigs2[bg].tilemap)[(y16 * mode3) + x16] = firstTileNum;
+ ((u8*)sGpuBgConfigs2[bg].tilemap)[(y16 * mode3) + x16] = firstTileNum;
firstTileNum = (firstTileNum & 0xFC00) + ((firstTileNum + tileNumDelta) & 0x3FF);
}
}
@@ -1414,9 +1379,9 @@ void WriteSequenceToBgTilemapBuffer(u8 bg, u16 firstTileNum, u8 x, u8 y, u8 widt
u16 GetBgMetricTextMode(u8 bg, u8 whichMetric)
{
u8 attribute;
-
+
attribute = GetBgControlAttribute(bg, BG_CTRL_ATTR_SCREENSIZE);
-
+
switch (whichMetric)
{
case 0:
@@ -1462,9 +1427,9 @@ u16 GetBgMetricTextMode(u8 bg, u8 whichMetric)
u32 GetBgMetricAffineMode(u8 bg, u8 whichMetric)
{
u8 attribute;
-
+
attribute = GetBgControlAttribute(bg, BG_CTRL_ATTR_SCREENSIZE);
-
+
switch (whichMetric)
{
case 0:
@@ -1491,7 +1456,7 @@ u32 GetTileMapIndexFromCoords(s32 x, s32 y, s32 screenSize, u32 screenWidth, u32
{
x = x & (screenWidth - 1);
y = y & (screenHeight - 1);
-
+
switch (screenSize)
{
case 0:
@@ -1526,7 +1491,7 @@ void CopyTileMapEntry(u16 *src, u16 *dest, s32 palette1, u32 tileOffset, u32 pal
test = ((*dest & 0xFC00) + (palette2 << 12)) | ((*src + tileOffset) & 0x3FF);
break;
}
-
+
*dest = test;
}
#else
@@ -1586,10 +1551,10 @@ _08002B3C:\n\
u32 GetBgType(u8 bg)
{
u8 mode;
-
+
mode = GetBgMode();
-
-
+
+
switch (bg)
{
case 0:
@@ -1621,7 +1586,7 @@ u32 GetBgType(u8 bg)
}
break;
}
-
+
return 0xFFFF;
}
@@ -1634,9 +1599,9 @@ bool32 IsInvalidBg32(u8 bg)
bool32 IsTileMapOutsideWram(u8 bg)
{
- if (gGpuBgConfigs2[bg].tilemap > (void*)IWRAM_END)
+ if (sGpuBgConfigs2[bg].tilemap > (void*)IWRAM_END)
return TRUE;
- if (gGpuBgConfigs2[bg].tilemap == 0x0)
+ if (sGpuBgConfigs2[bg].tilemap == 0x0)
return TRUE;
return FALSE;
}
diff --git a/src/calculate_base_damage.c b/src/calculate_base_damage.c
index 105b334f2..8996059f9 100644
--- a/src/calculate_base_damage.c
+++ b/src/calculate_base_damage.c
@@ -19,7 +19,6 @@ extern struct BattleEnigmaBerry gEnigmaBerries[];
extern u16 gBattleMovePower;
extern u16 gTrainerBattleOpponent_A;
-u8 CountAliveMonsInBattle(u8);
bool8 ShouldGetStatBadgeBoost(u16 flagId, u8 bank);
extern const struct BattleMove gBattleMoves[];
diff --git a/src/coins.c b/src/coins.c
index 84a79f5f2..4ee601b22 100644
--- a/src/coins.c
+++ b/src/coins.c
@@ -4,14 +4,13 @@
#include "window.h"
#include "text_window.h"
#include "string_util.h"
+#include "menu.h"
#define MAX_COINS 9999
EWRAM_DATA u8 sCoinsWindowId = 0;
extern s32 GetStringRightAlignXOffset(u8 fontId, u8 *str, s32 totalWidth);
-extern void SetWindowTemplateFields(struct WindowTemplate* template, u8 priority, u8 tilemapLeft, u8 tilemapTop, u8 width, u8 height, u8 palNum, u16 baseBlock);
-extern void SetWindowBorderStyle(u8 windowId, bool8 copyToVram, s16 tileStart, s8 palette);
extern void sub_819746C(u8 windowId, bool8 copyToVram);
extern const u8 gText_Coins[];
diff --git a/src/dma3_manager.c b/src/dma3_manager.c
index 6d12dec05..bb015c5cf 100644
--- a/src/dma3_manager.c
+++ b/src/dma3_manager.c
@@ -1,12 +1,23 @@
#include "global.h"
#include "dma3.h"
+IWRAM_DATA struct {
+ /* 0x00 */ const u8 *src;
+ /* 0x04 */ u8 *dest;
+ /* 0x08 */ u16 size;
+ /* 0x0A */ u16 mode;
+ /* 0x0C */ u32 value;
+} gDma3Requests[128];
+
+static bool8 gDma3ManagerLocked;
+static u8 gDma3RequestCursor;
+
void ClearDma3Requests(void)
{
int i;
gDma3ManagerLocked = TRUE;
- gDma3RequestCursor = FALSE;
+ gDma3RequestCursor = 0;
for(i = 0; i < (u8)ARRAY_COUNT(gDma3Requests); i++)
{
@@ -14,7 +25,7 @@ void ClearDma3Requests(void)
gDma3Requests[i].src = 0;
gDma3Requests[i].dest = 0;
}
-
+
gDma3ManagerLocked = FALSE;
}
@@ -22,9 +33,8 @@ void ClearDma3Requests(void)
void ProcessDma3Requests(void)
{
// NOTE: the fillerA member of the DMA struct is actually u32 value;
- // NOTE: gUnknown_0300001C is just a pointer inside the gDma3Requests structure, not a true symbol; feel free to remove
u16 total_size;
-
+
if (gDma3ManagerLocked)
return;
@@ -34,7 +44,7 @@ void ProcessDma3Requests(void)
while (gDma3Requests[gDma3RequestCursor].size)
{
total_size += gDma3Requests[gDma3RequestCursor].size;
-
+
if (total_size > 0xA000)
return; // don't do too much at once
@@ -90,14 +100,14 @@ void ProcessDma3Requests(void)
}
DmaFill16(3, gDma3Requests[gDma3RequestCursor].value, gDma3Requests[gDma3RequestCursor].dest, gDma3Requests[gDma3RequestCursor].size);
break;
- }
- gDma3Requests[gDma3RequestCursor].src = 0;
- gDma3Requests[gDma3RequestCursor].dest = 0;
+ }
+ gDma3Requests[gDma3RequestCursor].src = NULL;
+ gDma3Requests[gDma3RequestCursor].dest = NULL;
gDma3Requests[gDma3RequestCursor].size = 0;
gDma3Requests[gDma3RequestCursor].mode = 0;
gDma3Requests[gDma3RequestCursor].value = 0;
gDma3RequestCursor++;
-
+
if (gDma3RequestCursor >= 128) // loop back to the first DMA request
gDma3RequestCursor = 0;
}
@@ -331,7 +341,7 @@ _08000DB2:\n\
mov r5, r12\n\
ldrb r0, [r5]\n\
lsls r0, 4\n\
- ldr r3, =gUnknown_0300001C\n\
+ ldr r3, =gDma3Requests + 0x0C\n\
adds r0, r3\n\
ldr r0, [r0]\n\
strh r0, [r1]\n\
@@ -347,7 +357,7 @@ _08000DB2:\n\
bhi _08000DB2\n\
ldrb r0, [r5]\n\
lsls r0, 4\n\
- ldr r5, =gUnknown_0300001C\n\
+ ldr r5, =gDma3Requests + 0x0C\n\
adds r0, r5\n\
ldr r0, [r0]\n\
strh r0, [r1]\n\
@@ -419,13 +429,13 @@ _08000E46:\n\
}
#endif
-int RequestDma3Copy(void *src, void *dest, u16 size, u8 mode)
+int RequestDma3Copy(const void *src, void *dest, u16 size, u8 mode)
{
int cursor;
int var = 0;
-
+
gDma3ManagerLocked = 1;
-
+
cursor = gDma3RequestCursor;
while(1)
{
@@ -434,12 +444,12 @@ int RequestDma3Copy(void *src, void *dest, u16 size, u8 mode)
gDma3Requests[cursor].src = src;
gDma3Requests[cursor].dest = dest;
gDma3Requests[cursor].size = size;
-
+
if(mode == 1)
gDma3Requests[cursor].mode = mode;
else
gDma3Requests[cursor].mode = 3;
-
+
gDma3ManagerLocked = FALSE;
return (s16)cursor;
}
@@ -460,10 +470,10 @@ int RequestDma3Fill(s32 value, void *dest, u16 size, u8 mode)
{
int cursor;
int var = 0;
-
+
cursor = gDma3RequestCursor;
gDma3ManagerLocked = 1;
-
+
while(1)
{
if(!gDma3Requests[cursor].size)
@@ -477,7 +487,7 @@ int RequestDma3Fill(s32 value, void *dest, u16 size, u8 mode)
gDma3Requests[cursor].mode = 2;
else
gDma3Requests[cursor].mode = 4;
-
+
gDma3ManagerLocked = FALSE;
return (s16)cursor;
}
@@ -503,9 +513,9 @@ int CheckForSpaceForDma3Request(s16 index)
for (; current < 0x80; current ++)
if (gDma3Requests[current].size)
return -1;
-
+
return 0;
- }
+ }
if (gDma3Requests[index].size)
return -1;
diff --git a/src/egg_hatch.c b/src/egg_hatch.c
new file mode 100644
index 000000000..6d14e92f0
--- /dev/null
+++ b/src/egg_hatch.c
@@ -0,0 +1,893 @@
+#include "global.h"
+#include "pokemon.h"
+#include "pokedex.h"
+#include "items.h"
+#include "script.h"
+#include "decompress.h"
+#include "task.h"
+#include "palette.h"
+#include "main.h"
+#include "event_data.h"
+#include "sound.h"
+#include "songs.h"
+#include "text.h"
+#include "text_window.h"
+#include "string_util.h"
+#include "menu.h"
+#include "trig.h"
+#include "rng.h"
+#include "malloc.h"
+#include "dma3.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "m4a.h"
+#include "window.h"
+#include "abilities.h"
+#include "battle.h" // to get rid of later
+
+struct EggHatchData
+{
+ u8 eggSpriteID;
+ u8 pokeSpriteID;
+ u8 CB2_state;
+ u8 CB2_PalCounter;
+ u8 eggPartyID;
+ u8 unused_5;
+ u8 unused_6;
+ u8 eggShardVelocityID;
+ u8 windowId;
+ u8 unused_9;
+ u8 unused_A;
+ u16 species;
+ struct TextColor textColor;
+};
+
+extern struct SpriteTemplate gUnknown_0202499C;
+extern void (*gFieldCallback)(void);
+
+extern const struct CompressedSpriteSheet gMonFrontPicTable[];
+extern const u8 gUnknown_08C00000[];
+extern const u8 gUnknown_08C00524[];
+extern const u8 gUnknown_08C004E0[];
+extern const u16 gUnknown_08DD7300[]; // palette, gameboy advance
+extern const u32 gUnknown_08DD7360[]; // tileset gameboy advance
+extern const u32 gUnknown_08331F60[]; // tilemap gameboy circle
+extern const u8 gText_HatchedFromEgg[];
+extern const u8 gText_NickHatchPrompt[];
+
+extern u8* GetMonNick(struct Pokemon* mon, u8* dst);
+extern u8* GetBoxMonNick(struct BoxPokemon* boxMon, u8* dst);
+extern u8 sav1_map_get_name(void);
+extern s8 sub_8198C58(void);
+extern void sub_81DB5E8(u8* str1, u8* str2, u8);
+extern void sub_806A068(u16, u8);
+extern void fade_screen(u8, u8);
+extern void overworld_free_bg_tilemaps(void);
+extern void sub_80AF168(void);
+extern void init_uns_table_pokemon_copy(void);
+extern void sub_805F094(void);
+extern void remove_some_task(void);
+extern void reset_temp_tile_data_buffers(void);
+extern void c2_exit_to_overworld_2_switch(void);
+extern void play_some_sound(void);
+extern void copy_decompressed_tile_data_to_vram_autofree(u8 bg_id, const void* src, u16 size, u16 offset, u8 mode);
+extern void CreateYesNoMenu(const struct WindowTemplate*, u16, u8, u8);
+extern void DoNamingScreen(u8, const u8*, u16, u8, u32, MainCallback);
+extern void AddTextPrinterParametrized2(u8 windowId, u8 fontId, u8 x, u8 y, u8 letterSpacing, u8 lineSpacing, struct TextColor* colors, s8 speed, u8 *str);
+extern u16 sub_80D22D0(void);
+extern u8 sub_80C7050(u8);
+
+static void Task_EggHatch(u8 taskID);
+static void CB2_EggHatch_0(void);
+static void CB2_EggHatch_1(void);
+static void SpriteCB_Egg_0(struct Sprite* sprite);
+static void SpriteCB_Egg_1(struct Sprite* sprite);
+static void SpriteCB_Egg_2(struct Sprite* sprite);
+static void SpriteCB_Egg_3(struct Sprite* sprite);
+static void SpriteCB_Egg_4(struct Sprite* sprite);
+static void SpriteCB_Egg_5(struct Sprite* sprite);
+static void SpriteCB_EggShard(struct Sprite* sprite);
+static void EggHatchPrintMessage(u8 windowId, u8* string, u8 x, u8 y, u8 speed);
+static void CreateRandomEggShardSprite(void);
+static void CreateEggShardSprite(u8 x, u8 y, s16 data1, s16 data2, s16 data3, u8 spriteAnimIndex);
+
+// IWRAM bss
+static IWRAM_DATA struct EggHatchData* sEggHatchData;
+
+// rom data
+static const u16 sEggPalette[] = INCBIN_U16("graphics/pokemon/palettes/egg_palette.gbapal");
+static const u8 sEggHatchTiles[] = INCBIN_U8("graphics/misc/egg_hatch.4bpp");
+static const u8 sEggShardTiles[] = INCBIN_U8("graphics/misc/egg_shard.4bpp");
+
+static const struct OamData sOamData_EggHatch =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 2,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd sSpriteAnim_EggHatch0[] =
+{
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_EggHatch1[] =
+{
+ ANIMCMD_FRAME(16, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_EggHatch2[] =
+{
+ ANIMCMD_FRAME(32, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_EggHatch3[] =
+{
+ ANIMCMD_FRAME(48, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteAnimTable_EggHatch[] =
+{
+ sSpriteAnim_EggHatch0,
+ sSpriteAnim_EggHatch1,
+ sSpriteAnim_EggHatch2,
+ sSpriteAnim_EggHatch3,
+};
+
+static const struct SpriteSheet sEggHatch_Sheet =
+{
+ .data = sEggHatchTiles,
+ .size = 2048,
+ .tag = 12345,
+};
+
+static const struct SpriteSheet sEggShards_Sheet =
+{
+ .data = sEggShardTiles,
+ .size = 128,
+ .tag = 23456,
+};
+
+static const struct SpritePalette sEgg_SpritePalette =
+{
+ .data = sEggPalette,
+ .tag = 54321
+};
+
+static const struct SpriteTemplate sSpriteTemplate_EggHatch =
+{
+ .tileTag = 12345,
+ .paletteTag = 54321,
+ .oam = &sOamData_EggHatch,
+ .anims = sSpriteAnimTable_EggHatch,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct OamData sOamData_EggShard =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 0,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 0,
+ .tileNum = 0,
+ .priority = 2,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd sSpriteAnim_EggShard0[] =
+{
+ ANIMCMD_FRAME(0, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_EggShard1[] =
+{
+ ANIMCMD_FRAME(1, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_EggShard2[] =
+{
+ ANIMCMD_FRAME(2, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnim_EggShard3[] =
+{
+ ANIMCMD_FRAME(3, 5),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteAnimTable_EggShard[] =
+{
+ sSpriteAnim_EggShard0,
+ sSpriteAnim_EggShard1,
+ sSpriteAnim_EggShard2,
+ sSpriteAnim_EggShard3,
+};
+
+static const struct SpriteTemplate sSpriteTemplate_EggShard =
+{
+ .tileTag = 23456,
+ .paletteTag = 54321,
+ .oam = &sOamData_EggShard,
+ .anims = sSpriteAnimTable_EggShard,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_EggShard
+};
+
+static const struct BgTemplate sBgTemplates_EggHatch[2] =
+{
+ {
+ .bg = 0,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 24,
+ .screenSize = 3,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0
+ },
+
+ {
+ .bg = 1,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 8,
+ .screenSize = 1,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0
+ },
+};
+
+static const struct WindowTemplate sWinTemplates_EggHatch[2] =
+{
+ {0, 2, 0xF, 0x1A, 4, 0, 0x40},
+ DUMMY_WIN_TEMPLATE
+};
+
+static const struct WindowTemplate sYesNoWinTemplate =
+{
+ 0, 0x15, 9, 5, 4, 0xF, 0x1A8
+};
+
+static const s16 sEggShardVelocities[][2] =
+{
+ {Q_8_8(-1.5), Q_8_8(-3.75)},
+ {Q_8_8(-5), Q_8_8(-3)},
+ {Q_8_8(3.5), Q_8_8(-3)},
+ {Q_8_8(-4), Q_8_8(-3.75)},
+ {Q_8_8(2), Q_8_8(-1.5)},
+ {Q_8_8(-0.5), Q_8_8(-6.75)},
+ {Q_8_8(5), Q_8_8(-2.25)},
+ {Q_8_8(-1.5), Q_8_8(-3.75)},
+ {Q_8_8(4.5), Q_8_8(-1.5)},
+ {Q_8_8(-1), Q_8_8(-6.75)},
+ {Q_8_8(4), Q_8_8(-2.25)},
+ {Q_8_8(-3.5), Q_8_8(-3.75)},
+ {Q_8_8(1), Q_8_8(-1.5)},
+ {Q_8_8(-3.515625), Q_8_8(-6.75)},
+ {Q_8_8(4.5), Q_8_8(-2.25)},
+ {Q_8_8(-0.5), Q_8_8(-7.5)},
+ {Q_8_8(1), Q_8_8(-4.5)},
+ {Q_8_8(-2.5), Q_8_8(-2.25)},
+ {Q_8_8(2.5), Q_8_8(-7.5)},
+};
+
+// code
+
+static void CreatedHatchedMon(struct Pokemon *egg, struct Pokemon *temp)
+{
+ u16 species;
+ u32 personality, pokerus;
+ u8 i, friendship, language, gameMet, markings, obedience;
+ u16 moves[4];
+ u32 ivs[6];
+
+
+ species = GetMonData(egg, MON_DATA_SPECIES);
+
+ for (i = 0; i < 4; i++)
+ {
+ moves[i] = GetMonData(egg, MON_DATA_MOVE1 + i);
+ }
+
+ personality = GetMonData(egg, MON_DATA_PERSONALITY);
+
+ for (i = 0; i < 6; i++)
+ {
+ ivs[i] = GetMonData(egg, MON_DATA_HP_IV + i);
+ }
+
+ language = GetMonData(egg, MON_DATA_LANGUAGE);
+ gameMet = GetMonData(egg, MON_DATA_MET_GAME);
+ markings = GetMonData(egg, MON_DATA_MARKINGS);
+ pokerus = GetMonData(egg, MON_DATA_POKERUS);
+ obedience = GetMonData(egg, MON_DATA_OBEDIENCE);
+
+ CreateMon(temp, species, 5, 32, TRUE, personality, 0, 0);
+
+ for (i = 0; i < 4; i++)
+ {
+ SetMonData(temp, MON_DATA_MOVE1 + i, &moves[i]);
+ }
+
+ for (i = 0; i < 6; i++)
+ {
+ SetMonData(temp, MON_DATA_HP_IV + i, &ivs[i]);
+ }
+
+ language = GAME_LANGUAGE;
+ SetMonData(temp, MON_DATA_LANGUAGE, &language);
+ SetMonData(temp, MON_DATA_MET_GAME, &gameMet);
+ SetMonData(temp, MON_DATA_MARKINGS, &markings);
+
+ friendship = 120;
+ SetMonData(temp, MON_DATA_FRIENDSHIP, &friendship);
+ SetMonData(temp, MON_DATA_POKERUS, &pokerus);
+ SetMonData(temp, MON_DATA_OBEDIENCE, &obedience);
+
+ *egg = *temp;
+}
+
+static void AddHatchedMonToParty(u8 id)
+{
+ u8 isEgg = 0x46; // ?
+ u16 pokeNum;
+ u8 name[12];
+ u16 ball;
+ u16 caughtLvl;
+ u8 mapNameID;
+ struct Pokemon* mon = &gPlayerParty[id];
+
+ CreatedHatchedMon(mon, &gEnemyParty[0]);
+ SetMonData(mon, MON_DATA_IS_EGG, &isEgg);
+
+ pokeNum = GetMonData(mon, MON_DATA_SPECIES);
+ GetSpeciesName(name, pokeNum);
+ SetMonData(mon, MON_DATA_NICKNAME, name);
+
+ pokeNum = SpeciesToNationalPokedexNum(pokeNum);
+ GetSetPokedexFlag(pokeNum, FLAG_SET_SEEN);
+ GetSetPokedexFlag(pokeNum, FLAG_SET_CAUGHT);
+
+ GetMonNick(mon, gStringVar1);
+
+ ball = ITEM_POKE_BALL;
+ SetMonData(mon, MON_DATA_POKEBALL, &ball);
+
+ caughtLvl = 0;
+ SetMonData(mon, MON_DATA_MET_LEVEL, &caughtLvl);
+
+ mapNameID = sav1_map_get_name();
+ SetMonData(mon, MON_DATA_MET_LOCATION, &mapNameID);
+
+ MonRestorePP(mon);
+ CalculateMonStats(mon);
+}
+
+void ScriptHatchMon(void)
+{
+ AddHatchedMonToParty(gSpecialVar_0x8004);
+}
+
+static bool8 sub_807158C(struct DaycareData* daycare, u8 daycareId)
+{
+ u8 nick[0x20];
+ struct DaycareMon* daycareMon = &daycare->mons[daycareId];
+
+ GetBoxMonNick(&daycareMon->mon, nick);
+ if (daycareMon->mail.itemId != 0
+ && (StringCompareWithoutExtCtrlCodes(nick, daycareMon->monName) != 0
+ || StringCompareWithoutExtCtrlCodes(gSaveBlock2Ptr->playerName, daycareMon->OT_name) != 0))
+ {
+ StringCopy(gStringVar1, nick);
+ sub_81DB5E8(gStringVar2, daycareMon->OT_name, daycareMon->language_maybe);
+ sub_81DB5E8(gStringVar3, daycareMon->monName, daycareMon->unknown);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8071614(void)
+{
+ return sub_807158C(&gSaveBlock1Ptr->daycare, gSpecialVar_0x8004);
+}
+
+static u8 EggHatchCreateMonSprite(u8 a0, u8 switchID, u8 pokeID, u16* speciesLoc)
+{
+ u8 r5 = 0;
+ u8 spriteID = 0;
+ struct Pokemon* mon = NULL;
+
+ if (a0 == 0)
+ {
+ mon = &gPlayerParty[pokeID];
+ r5 = 1;
+ }
+ if (a0 == 1)
+ {
+ mon = &gPlayerParty[pokeID];
+ r5 = 3;
+ }
+ switch (switchID)
+ {
+ case 0:
+ {
+ u16 species = GetMonData(mon, MON_DATA_SPECIES);
+ u32 pid = GetMonData(mon, MON_DATA_PERSONALITY);
+ HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[species],
+ gBattleSpritesGfx->sprites[(a0 * 2) + 1],
+ species, pid);
+ LoadCompressedObjectPalette(sub_806E794(mon));
+ *speciesLoc = species;
+ }
+ break;
+ case 1:
+ sub_806A068(sub_806E794(mon)->tag, r5);
+ spriteID = CreateSprite(&gUnknown_0202499C, 120, 75, 6);
+ gSprites[spriteID].invisible = 1;
+ gSprites[spriteID].callback = SpriteCallbackDummy;
+ break;
+ }
+ return spriteID;
+}
+
+static void VBlankCB_EggHatch(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void EggHatch(void)
+{
+ ScriptContext2_Enable();
+ CreateTask(Task_EggHatch, 10);
+ fade_screen(1, 0);
+}
+
+static void Task_EggHatch(u8 taskID)
+{
+ if (!gPaletteFade.active)
+ {
+ overworld_free_bg_tilemaps();
+ SetMainCallback2(CB2_EggHatch_0);
+ gFieldCallback = sub_80AF168;
+ DestroyTask(taskID);
+ }
+}
+
+static void CB2_EggHatch_0(void)
+{
+ switch (gMain.state)
+ {
+ case 0:
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+
+ sEggHatchData = Alloc(sizeof(struct EggHatchData));
+ init_uns_table_pokemon_copy();
+ sEggHatchData->eggPartyID = gSpecialVar_0x8004;
+ sEggHatchData->eggShardVelocityID = 0;
+
+ SetVBlankCallback(VBlankCB_EggHatch);
+ gSpecialVar_0x8005 = GetCurrentMapMusic();
+
+ reset_temp_tile_data_buffers();
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, sBgTemplates_EggHatch, ARRAY_COUNT(sBgTemplates_EggHatch));
+
+ ChangeBgX(1, 0, 0);
+ ChangeBgY(1, 0, 0);
+ ChangeBgX(0, 0, 0);
+ ChangeBgY(0, 0, 0);
+
+ SetBgAttribute(1, BG_CTRL_ATTR_MOSAIC, 2);
+ SetBgTilemapBuffer(1, Alloc(0x1000));
+ SetBgTilemapBuffer(0, Alloc(0x2000));
+
+ DeactivateAllTextPrinters();
+ ResetPaletteFade();
+ FreeAllSpritePalettes();
+ ResetSpriteData();
+ ResetTasks();
+ remove_some_task();
+ m4aSoundVSyncOn();
+ gMain.state++;
+ break;
+ case 1:
+ InitWindows(sWinTemplates_EggHatch);
+ sEggHatchData->windowId = 0;
+ gMain.state++;
+ break;
+ case 2:
+ copy_decompressed_tile_data_to_vram_autofree(0, gUnknown_08C00000, 0, 0, 0);
+ CopyToBgTilemapBuffer(0, gUnknown_08C00524, 0, 0);
+ LoadCompressedPalette(gUnknown_08C004E0, 0, 0x20);
+ gMain.state++;
+ break;
+ case 3:
+ LoadSpriteSheet(&sEggHatch_Sheet);
+ LoadSpriteSheet(&sEggShards_Sheet);
+ LoadSpritePalette(&sEgg_SpritePalette);
+ gMain.state++;
+ break;
+ case 4:
+ CopyBgTilemapBufferToVram(0);
+ AddHatchedMonToParty(sEggHatchData->eggPartyID);
+ gMain.state++;
+ break;
+ case 5:
+ EggHatchCreateMonSprite(0, 0, sEggHatchData->eggPartyID, &sEggHatchData->species);
+ gMain.state++;
+ break;
+ case 6:
+ sEggHatchData->pokeSpriteID = EggHatchCreateMonSprite(0, 1, sEggHatchData->eggPartyID, &sEggHatchData->species);
+ gMain.state++;
+ break;
+ case 7:
+ SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
+ LoadPalette(gUnknown_08DD7300, 0x10, 0xA0);
+ LoadBgTiles(1, gUnknown_08DD7360, 0x1420, 0);
+ CopyToBgTilemapBuffer(1, gUnknown_08331F60, 0x1000, 0);
+ CopyBgTilemapBufferToVram(1);
+ gMain.state++;
+ break;
+ case 8:
+ SetMainCallback2(CB2_EggHatch_1);
+ sEggHatchData->CB2_state = 0;
+ break;
+ }
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void EggHatchSetMonNickname(void)
+{
+ SetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar3);
+ sub_805F094();
+ Free(sEggHatchData);
+ SetMainCallback2(c2_exit_to_overworld_2_switch);
+}
+
+static void Task_EggHatchPlayBGM(u8 taskID)
+{
+ if (gTasks[taskID].data[0] == 0)
+ {
+ StopMapMusic();
+ play_some_sound();
+ }
+ if (gTasks[taskID].data[0] == 1)
+ PlayBGM(376);
+ if (gTasks[taskID].data[0] > 60)
+ {
+ PlayBGM(377);
+ DestroyTask(taskID);
+ // UB: task is destroyed, yet the value is incremented
+ }
+ gTasks[taskID].data[0]++;
+}
+
+static void CB2_EggHatch_1(void)
+{
+ u16 species;
+ u8 gender;
+ u32 personality;
+
+ switch (sEggHatchData->CB2_state)
+ {
+ case 0:
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
+ sEggHatchData->eggSpriteID = CreateSprite(&sSpriteTemplate_EggHatch, 120, 75, 5);
+ ShowBg(0);
+ ShowBg(1);
+ sEggHatchData->CB2_state++;
+ CreateTask(Task_EggHatchPlayBGM, 5);
+ break;
+ case 1:
+ if (!gPaletteFade.active)
+ {
+ FillWindowPixelBuffer(sEggHatchData->windowId, 0);
+ sEggHatchData->CB2_PalCounter = 0;
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 2:
+ if (++sEggHatchData->CB2_PalCounter > 30)
+ {
+ sEggHatchData->CB2_state++;
+ gSprites[sEggHatchData->eggSpriteID].callback = SpriteCB_Egg_0;
+ }
+ break;
+ case 3:
+ if (gSprites[sEggHatchData->eggSpriteID].callback == SpriteCallbackDummy)
+ {
+ species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES);
+ DoMonFrontSpriteAnimation(&gSprites[sEggHatchData->pokeSpriteID], species, FALSE, 1);
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 4:
+ if (gSprites[sEggHatchData->pokeSpriteID].callback == SpriteCallbackDummy)
+ {
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 5:
+ GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_HatchedFromEgg);
+ EggHatchPrintMessage(sEggHatchData->windowId, gStringVar4, 0, 3, 0xFF);
+ PlayFanfare(371);
+ sEggHatchData->CB2_state++;
+ PutWindowTilemap(sEggHatchData->windowId);
+ CopyWindowToVram(sEggHatchData->windowId, 3);
+ break;
+ case 6:
+ if (IsFanfareTaskInactive())
+ sEggHatchData->CB2_state++;
+ break;
+ case 7:
+ if (IsFanfareTaskInactive())
+ sEggHatchData->CB2_state++;
+ break;
+ case 8:
+ GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar1);
+ StringExpandPlaceholders(gStringVar4, gText_NickHatchPrompt);
+ EggHatchPrintMessage(sEggHatchData->windowId, gStringVar4, 0, 2, 1);
+ sEggHatchData->CB2_state++;
+ break;
+ case 9:
+ if (!IsTextPrinterActive(sEggHatchData->windowId))
+ {
+ sub_809882C(sEggHatchData->windowId, 0x140, 0xE0);
+ CreateYesNoMenu(&sYesNoWinTemplate, 0x140, 0xE, 0);
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 10:
+ switch (sub_8198C58())
+ {
+ case 0:
+ GetMonNick(&gPlayerParty[sEggHatchData->eggPartyID], gStringVar3);
+ species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES);
+ gender = GetMonGender(&gPlayerParty[sEggHatchData->eggPartyID]);
+ personality = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_PERSONALITY, 0);
+ DoNamingScreen(3, gStringVar3, species, gender, personality, EggHatchSetMonNickname);
+ break;
+ case 1:
+ case -1:
+ sEggHatchData->CB2_state++;
+ }
+ break;
+ case 11:
+ BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
+ sEggHatchData->CB2_state++;
+ break;
+ case 12:
+ if (!gPaletteFade.active)
+ {
+ sub_805F094();
+ RemoveWindow(sEggHatchData->windowId);
+ UnsetBgTilemapBuffer(0);
+ UnsetBgTilemapBuffer(1);
+ Free(sEggHatchData);
+ SetMainCallback2(c2_exit_to_overworld_2_switch);
+ }
+ break;
+ }
+
+ RunTasks();
+ RunTextPrinters();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void SpriteCB_Egg_0(struct Sprite* sprite)
+{
+ if (++sprite->data0 > 20)
+ {
+ sprite->callback = SpriteCB_Egg_1;
+ sprite->data0 = 0;
+ }
+ else
+ {
+ sprite->data1 = (sprite->data1 + 20) & 0xFF;
+ sprite->pos2.x = Sin(sprite->data1, 1);
+ if (sprite->data0 == 15)
+ {
+ PlaySE(SE_BOWA);
+ StartSpriteAnim(sprite, 1);
+ CreateRandomEggShardSprite();
+ }
+ }
+}
+
+static void SpriteCB_Egg_1(struct Sprite* sprite)
+{
+ if (++sprite->data2 > 30)
+ {
+ if (++sprite->data0 > 20)
+ {
+ sprite->callback = SpriteCB_Egg_2;
+ sprite->data0 = 0;
+ sprite->data2 = 0;
+ }
+ else
+ {
+ sprite->data1 = (sprite->data1 + 20) & 0xFF;
+ sprite->pos2.x = Sin(sprite->data1, 2);
+ if (sprite->data0 == 15)
+ {
+ PlaySE(SE_BOWA);
+ StartSpriteAnim(sprite, 2);
+ }
+ }
+ }
+}
+
+static void SpriteCB_Egg_2(struct Sprite* sprite)
+{
+ if (++sprite->data2 > 30)
+ {
+ if (++sprite->data0 > 38)
+ {
+ u16 species;
+
+ sprite->callback = SpriteCB_Egg_3;
+ sprite->data0 = 0;
+ species = GetMonData(&gPlayerParty[sEggHatchData->eggPartyID], MON_DATA_SPECIES);
+ gSprites[sEggHatchData->pokeSpriteID].pos2.x = 0;
+ gSprites[sEggHatchData->pokeSpriteID].pos2.y = 0;
+ }
+ else
+ {
+ sprite->data1 = (sprite->data1 + 20) & 0xFF;
+ sprite->pos2.x = Sin(sprite->data1, 2);
+ if (sprite->data0 == 15)
+ {
+ PlaySE(SE_BOWA);
+ StartSpriteAnim(sprite, 2);
+ CreateRandomEggShardSprite();
+ CreateRandomEggShardSprite();
+ }
+ if (sprite->data0 == 30)
+ PlaySE(SE_BOWA);
+ }
+ }
+}
+
+static void SpriteCB_Egg_3(struct Sprite* sprite)
+{
+ if (++sprite->data0 > 50)
+ {
+ sprite->callback = SpriteCB_Egg_4;
+ sprite->data0 = 0;
+ }
+}
+
+static void SpriteCB_Egg_4(struct Sprite* sprite)
+{
+ s16 i;
+ if (sprite->data0 == 0)
+ BeginNormalPaletteFade(-1, -1, 0, 0x10, 0xFFFF);
+ if (sprite->data0 < 4u)
+ {
+ for (i = 0; i <= 3; i++)
+ CreateRandomEggShardSprite();
+ }
+ sprite->data0++;
+ if (!gPaletteFade.active)
+ {
+ PlaySE(SE_TAMAGO);
+ sprite->invisible = 1;
+ sprite->callback = SpriteCB_Egg_5;
+ sprite->data0 = 0;
+ }
+}
+
+static void SpriteCB_Egg_5(struct Sprite* sprite)
+{
+ if (sprite->data0 == 0)
+ {
+ gSprites[sEggHatchData->pokeSpriteID].invisible = 0;
+ StartSpriteAffineAnim(&gSprites[sEggHatchData->pokeSpriteID], 1);
+ }
+ if (sprite->data0 == 8)
+ BeginNormalPaletteFade(-1, -1, 0x10, 0, 0xFFFF);
+ if (sprite->data0 <= 9)
+ gSprites[sEggHatchData->pokeSpriteID].pos1.y -= 1;
+ if (sprite->data0 > 40)
+ sprite->callback = SpriteCallbackDummy;
+ sprite->data0++;
+}
+
+static void SpriteCB_EggShard(struct Sprite* sprite)
+{
+ sprite->data4 += sprite->data1;
+ sprite->data5 += sprite->data2;
+
+ sprite->pos2.x = sprite->data4 / 256;
+ sprite->pos2.y = sprite->data5 / 256;
+
+ sprite->data2 += sprite->data3;
+
+ if (sprite->pos1.y + sprite->pos2.y > sprite->pos1.y + 20 && sprite->data2 > 0)
+ DestroySprite(sprite);
+}
+
+static void CreateRandomEggShardSprite(void)
+{
+ u16 spriteAnimIndex;
+
+ s16 velocity1 = sEggShardVelocities[sEggHatchData->eggShardVelocityID][0];
+ s16 velocity2 = sEggShardVelocities[sEggHatchData->eggShardVelocityID][1];
+ sEggHatchData->eggShardVelocityID++;
+ spriteAnimIndex = Random() % 4;
+ CreateEggShardSprite(120, 60, velocity1, velocity2, 100, spriteAnimIndex);
+}
+
+static void CreateEggShardSprite(u8 x, u8 y, s16 data1, s16 data2, s16 data3, u8 spriteAnimIndex)
+{
+ u8 spriteID = CreateSprite(&sSpriteTemplate_EggShard, x, y, 4);
+ gSprites[spriteID].data1 = data1;
+ gSprites[spriteID].data2 = data2;
+ gSprites[spriteID].data3 = data3;
+ StartSpriteAnim(&gSprites[spriteID], spriteAnimIndex);
+}
+
+static void EggHatchPrintMessage(u8 windowId, u8* string, u8 x, u8 y, u8 speed)
+{
+ FillWindowPixelBuffer(windowId, 0xFF);
+ sEggHatchData->textColor.fgColor = 0;
+ sEggHatchData->textColor.bgColor = 5;
+ sEggHatchData->textColor.shadowColor = 6;
+ AddTextPrinterParametrized2(windowId, 1, x, y, 0, 0, &sEggHatchData->textColor, speed, string);
+}
+
+u8 GetEggStepsToSubtract(void)
+{
+ u8 count, i;
+ for (count = CalculatePlayerPartyCount(), i = 0; i < count; i++)
+ {
+ if (!GetMonData(&gPlayerParty[i], MON_DATA_SANITY_BIT3))
+ {
+ u8 ability = GetMonAbility(&gPlayerParty[i]);
+ if (ability == ABILITY_MAGMA_ARMOR || ability == ABILITY_FLAME_BODY)
+ return 2;
+ }
+ }
+ return 1;
+}
+
+u16 sub_80722E0(void)
+{
+ u16 value = sub_80D22D0();
+ value += sub_80C7050(6);
+ return value;
+}
diff --git a/src/field_camera.c b/src/field_camera.c
new file mode 100644
index 000000000..17ced6aa5
--- /dev/null
+++ b/src/field_camera.c
@@ -0,0 +1,28 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+struct FieldCameraUnknownStruct
+{
+ u8 unk0;
+ u8 unk1;
+ u8 unk2;
+ u8 unk3;
+ bool8 unk4;
+};
+
+// Static RAM declarations
+
+IWRAM_DATA struct FieldCameraUnknownStruct gUnknown_03000E20;
+IWRAM_DATA s16 gUnknown_03000E28;
+IWRAM_DATA s16 gUnknown_03000E2A;
+IWRAM_DATA u8 gUnknown_03000E2C;
+IWRAM_DATA void (*gUnknown_03000E30)(void);
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/field_effect.c b/src/field_effect.c
new file mode 100644
index 000000000..628dc776a
--- /dev/null
+++ b/src/field_effect.c
@@ -0,0 +1,15 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03000F58[32];
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/field_map_obj.c b/src/field_map_obj.c
new file mode 100755
index 000000000..e80e402c8
--- /dev/null
+++ b/src/field_map_obj.c
@@ -0,0 +1,5118 @@
+// Includes
+
+#include "global.h"
+#include "malloc.h"
+#include "sprite.h"
+#include "rom4.h"
+#include "rng.h"
+#include "event_scripts.h"
+#include "berry.h"
+#include "palette.h"
+#include "field_player_avatar.h"
+#include "fieldmap.h"
+#include "event_data.h"
+#include "rom_818CFC8.h"
+#include "rom_81BE66C.h"
+#include "field_ground_effect.h"
+#include "map_obj_8097404.h"
+#include "mauville_old_man.h"
+#include "metatile_behavior.h"
+#include "field_effect.h"
+#include "field_effect_helpers.h"
+#include "field_camera.h"
+#include "trainer_see.h"
+#include "field_map_obj.h"
+
+#define NUM_FIELD_MAP_OBJECT_TEMPLATES 0x51
+
+#define null_object_step(name, retval) \
+bool8 FieldObjectCB2_##name(struct MapObject *, struct Sprite *);\
+void FieldObjectCB_##name(struct Sprite *sprite)\
+{\
+ FieldObjectStep(&gMapObjects[sprite->data0], sprite, FieldObjectCB2_##name);\
+}\
+bool8 FieldObjectCB2_##name(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ return (retval);\
+}
+
+#define field_object_step(name, table) \
+extern bool8 (*const (table)[])(struct MapObject *, struct Sprite *);\
+bool8 FieldObjectCB2_##name(struct MapObject *, struct Sprite *);\
+void FieldObjectCB_##name(struct Sprite *sprite)\
+{\
+ FieldObjectStep(&gMapObjects[sprite->data0], sprite, FieldObjectCB2_##name);\
+}\
+bool8 FieldObjectCB2_##name(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ return (table)[sprite->data1](mapObject, sprite);\
+}
+
+#define field_object_path(idx, table, sub, path, catch, coord)\
+field_object_step(GoInDirectionSequence##idx, table)\
+extern const u8 path[4];\
+bool8 sub(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ u8 route[sizeof(path)];\
+ memcpy(route, path, sizeof(path));\
+ if (mapObject->mapobj_unk_21 == (catch) && mapObject->coords1.coord == mapObject->coords2.coord)\
+ {\
+ mapObject->mapobj_unk_21 = (catch) + 1;\
+ }\
+ return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, route);\
+}\
+
+// Static struct declarations
+
+// Static RAM declarations
+
+extern u8 gUnknown_020375B4;
+extern u16 gUnknown_020375B6;
+
+// Static ROM declarations
+
+static void sub_808D450(void);
+static u8 GetFieldObjectIdByLocalId(u8);
+static u8 GetFieldObjectIdByLocalIdAndMapInternal(u8, u8, u8);
+static bool8 GetAvailableFieldObjectSlot(u16, u8, u8, u8 *);
+static void FieldObjectHandleDynamicGraphicsId(struct MapObject *);
+static void RemoveFieldObjectInternal (struct MapObject *);
+/*static*/ u16 GetFieldObjectFlagIdByFieldObjectId(u8);
+void sub_8096518(struct MapObject *, struct Sprite *);
+static void MakeObjectTemplateFromFieldObjectTemplate(struct MapObjectTemplate *, struct SpriteTemplate *, const struct SubspriteTable **);
+/*static*/ void GetFieldObjectMovingCameraOffset(s16 *, s16 *);
+/*static*/ struct MapObjectTemplate *GetFieldObjectTemplateByLocalIdAndMap(u8, u8, u8);
+static void sub_808E894(u16);
+static void RemoveFieldObjectIfOutsideView(struct MapObject *);
+static void sub_808E1B8(u8, s16, s16);
+static void SetPlayerAvatarFieldObjectIdAndObjectId(u8, u8);
+/*static*/ void sub_808E38C(struct MapObject *);
+static u8 sub_808E8F4(const struct SpritePalette *);
+static u8 FindFieldObjectPaletteIndexByTag(u16);
+static void sub_808EAB0(u16, u8);
+static bool8 FieldObjectDoesZCoordMatch(struct MapObject *, u8);
+//static void CameraObject_0(struct Sprite *);
+/*static*/ void CameraObject_1(struct Sprite *);
+//static void CameraObject_2(struct Sprite *);
+/*static*/ struct MapObjectTemplate *FindFieldObjectTemplateInArrayByLocalId(u8 localId, struct MapObjectTemplate *templates, u8 count);
+void npc_reset(struct MapObject *, struct Sprite *);
+void FieldObjectSetRegularAnim(struct MapObject *, struct Sprite *, u8);
+
+u8 GetFaceDirectionAnimId(u32);
+u8 GetGoSpeed0AnimId(u32);
+u8 GetGoSpeed1AnimId(u32);
+u8 GetGoSpeed3AnimId(u32);
+u8 sub_8093438(u32);
+u8 sub_80934BC(u32);
+u8 sub_8093514(u32);
+u8 GetJumpLedgeAnimId(u32);
+void sub_8092F88(u32, s16 *, s16 *, s16, s16);
+
+bool8 FieldObjectExecRegularAnim(struct MapObject *, struct Sprite *);
+void SetFieldObjectStepTimer(struct Sprite *, s16);
+bool8 RunFieldObjectStepTimer(struct Sprite *);
+bool8 npc_block_way__next_tile(struct MapObject *, u8);
+static u32 state_to_direction(u8, u32, u32);
+/*static*/ void sub_80964E8(struct MapObject *, struct Sprite *);
+static void FieldObjectExecSpecialAnim(struct MapObject *, struct Sprite *);
+/*static*/ void npc_obj_transfer_image_anim_pause_flag(struct MapObject *, struct Sprite *);
+
+static bool8 IsCoordOutsideFieldObjectMovementRect(struct MapObject *, s16, s16);
+static bool8 IsMetatileDirectionallyImpassable(struct MapObject *, s16, s16, u8);
+static bool8 CheckForCollisionBetweenFieldObjects(struct MapObject *, s16, s16);
+bool8 sub_809558C(struct MapObject *, struct Sprite *);
+bool8 sub_8095B64(struct MapObject *, struct Sprite *);
+static void sub_8096530(struct MapObject *, struct Sprite *);
+static void npc_update_obj_anim_flag(struct MapObject *, struct Sprite *);
+
+// ROM data
+
+extern void (*const gUnknown_08505438[NUM_FIELD_MAP_OBJECT_TEMPLATES])(struct Sprite *);
+extern const u8 gUnknown_0850557C[NUM_FIELD_MAP_OBJECT_TEMPLATES];
+extern const u8 gUnknown_085055CD[NUM_FIELD_MAP_OBJECT_TEMPLATES];
+extern const struct MapObjectGraphicsInfo *const gMauvilleOldManGraphicsInfoPointers[7];
+extern const struct MapObjectGraphicsInfo *const gFieldObjectGraphicsInfoPointers[0xEF];
+extern u8 (*const gUnknown_0850D714[11])(s16, s16, s16, s16);
+
+struct PairedPalettes {
+ u16 tag;
+ const u16 *data;
+};
+
+extern const u8 gUnknown_084975C4[0x10];
+extern const struct SpriteTemplate gUnknown_084975D4;
+extern void (*const gUnknown_084975EC[3])(struct Sprite *);
+extern const struct SpritePalette gUnknown_0850BBC8[39];
+extern const struct PairedPalettes gUnknown_0850BD00[4];
+extern const struct PairedPalettes gUnknown_0850BD78[14];
+extern const u16 *const gUnknown_0850BE38[2];
+extern const s16 gUnknown_0850D6DC[4]; // {0x20, 0x40, 0x60, 0x80}
+extern const s16 gUnknown_0850D6EC[4];
+extern const u8 gUnknown_0850D710[4]; // {DIR_SOUTH, DIR_NORTH, DIR_WEST, DIR_EAST}
+extern const u8 gUnknown_0850D770[2]; // {DIR_SOUTH, DIR_NORTH}
+extern const u8 gUnknown_0850D790[2]; // {DIR_WEST, DIR_EAST}
+extern const u8 gUnknown_0850D7F0[2]; // {DIR_NORTH, DIR_WEST}
+extern const u8 gUnknown_0850D808[2]; // {DIR_NORTH, DIR_EAST}
+extern const u8 gUnknown_0850D820[2]; // {DIR_SOUTH, DIR_WEST}
+extern const u8 gUnknown_0850D838[2]; // {DIR_SOUTH, DIR_EAST}
+extern const u8 gUnknown_0850D850[4];
+extern const u8 gUnknown_0850D868[4];
+extern const u8 gUnknown_0850D880[4];
+extern const u8 gUnknown_0850D898[4];
+extern const u8 gUnknown_0850D8AC[5];
+extern const u8 gUnknown_0850D8C4[5];
+extern const u8 gUnknown_0850D8E8[4];
+extern bool8 (*const gUnknown_0850DA64[11])(struct MapObject *, struct Sprite *, u8, bool8(u8));
+extern bool8 (*const gUnknown_0850DB5C[4])(u8);
+extern bool8 (*const gUnknown_0850DB6C[4])(u8);
+extern const struct Coords16 gUnknown_0850DB7C[4];
+extern const u8 gUnknown_0850DC2F[4][4];
+extern const u8 gUnknown_0850DC3F[4][4];
+extern const u8 gUnknown_0850DBA0[5];
+extern bool8 (*const *const gUnknown_0850DC50[166])(struct MapObject *, struct Sprite *);
+extern u8 (*const gUnknown_0850DEE8[5])(u8);
+extern const s16 gUnknown_0850DFBC[3];
+extern const s16 gUnknown_0850DFC2[3];
+
+// Code
+
+static void npc_clear_ids_and_state(struct MapObject *mapObject)
+{
+ *mapObject = (struct MapObject){};
+ mapObject->localId = 0xFF;
+ mapObject->mapNum = -1;
+ mapObject->mapGroup = -1;
+ mapObject->mapobj_unk_1C = -1;
+}
+
+static void npcs_clear_ids_and_state(void)
+{
+ u8 i;
+
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ npc_clear_ids_and_state(&gMapObjects[i]);
+ }
+}
+
+void sub_808D438(void)
+{
+ strange_npc_table_clear();
+ npcs_clear_ids_and_state();
+ ClearPlayerAvatarInfo();
+ sub_808D450();
+}
+
+static void sub_808D450(void)
+{
+ u8 spriteIdx;
+
+ spriteIdx = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[21], 0, 0, 31);
+ gSprites[spriteIdx].oam.affineMode = 1;
+ InitSpriteAffineAnim(&gSprites[spriteIdx]);
+ StartSpriteAffineAnim(&gSprites[spriteIdx], 0);
+ gSprites[spriteIdx].invisible = TRUE;
+
+ spriteIdx = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[21], 0, 0, 31);
+ gSprites[spriteIdx].oam.affineMode = 1;
+ InitSpriteAffineAnim(&gSprites[spriteIdx]);
+ StartSpriteAffineAnim(&gSprites[spriteIdx], 1);
+ gSprites[spriteIdx].invisible = TRUE;
+}
+
+u8 sub_808D4F4(void)
+{
+ u8 i;
+
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ if (!gMapObjects[i].active)
+ {
+ break;
+ }
+ }
+ return i;
+}
+
+u8 GetFieldObjectIdByLocalIdAndMap(u8 localId, u8 mapId, u8 mapGroupId)
+{
+ if (localId < 0xff)
+ {
+ return GetFieldObjectIdByLocalIdAndMapInternal(localId, mapId, mapGroupId);
+ }
+ return GetFieldObjectIdByLocalId(localId);
+}
+
+bool8 TryGetFieldObjectIdByLocalIdAndMap(u8 localId, u8 mapId, u8 mapGroupId, u8 *fieldObjectId)
+{
+ *fieldObjectId = GetFieldObjectIdByLocalIdAndMap(localId, mapId, mapGroupId);
+ if (*fieldObjectId == NUM_FIELD_OBJECTS)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+u8 GetFieldObjectIdByXY(s16 x, s16 y)
+{
+ u8 i;
+
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ if (gMapObjects[i].active && gMapObjects[i].coords2.x == x && gMapObjects[i].coords2.y == y)
+ {
+ break;
+ }
+ }
+ return i;
+}
+
+static u8 GetFieldObjectIdByLocalIdAndMapInternal(u8 localId, u8 mapId, u8 mapGroupId)
+{
+ u8 i;
+
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ if (gMapObjects[i].active && gMapObjects[i].localId == localId && gMapObjects[i].mapNum == mapId && gMapObjects[i].mapGroup == mapGroupId)
+ {
+ return i;
+ }
+ }
+ return NUM_FIELD_OBJECTS;
+}
+
+static u8 GetFieldObjectIdByLocalId(u8 localId)
+{
+ u8 i;
+
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ if (gMapObjects[i].active && gMapObjects[i].localId == localId)
+ {
+ return i;
+ }
+ }
+ return NUM_FIELD_OBJECTS;
+}
+
+// This function has the same nonmatching quirk as in Ruby/Sapphire.
+#ifdef NONMATCHING
+static u8 InitFieldObjectStateFromTemplate(struct MapObjectTemplate *template, u8 mapNum, u8 mapGroup)
+{
+ struct MapObject *mapObject;
+ s16 x;
+ s16 y;
+ u8 slot;
+
+ // mapNum and mapGroup are in the wrong registers (r7/r6 instead of r6/r7)
+ if (GetAvailableFieldObjectSlot(template->localId, mapNum, mapGroup, &slot))
+ {
+ return NUM_FIELD_OBJECTS;
+ }
+ mapObject = &gMapObjects[slot];
+ npc_clear_ids_and_state(mapObject);
+ x = template->x + 7;
+ y = template->y + 7;
+ mapObject->active = TRUE;
+ mapObject->mapobj_bit_2 = TRUE;
+ mapObject->graphicsId = template->graphicsId;
+ mapObject->animPattern = template->movementType;
+ mapObject->localId = template->localId;
+ mapObject->mapNum = mapNum;
+ mapObject->mapGroup = mapGroup;
+ mapObject->coords1.x = x;
+ mapObject->coords1.y = y;
+ mapObject->coords2.x = x;
+ mapObject->coords2.y = y;
+ mapObject->coords3.x = x;
+ mapObject->coords3.y = y;
+ mapObject->mapobj_unk_0B_0 = template->elevation;
+ mapObject->elevation = template->elevation;
+ // For some reason, 0x0F is placed in r9, to be used later
+ mapObject->range.as_nybbles.x = template->unkA_0;
+ mapObject->range.as_nybbles.y = template->unkA_4;
+ mapObject->trainerType = template->unkC;
+ mapObject->trainerRange_berryTreeId = template->unkE;
+ mapObject->mapobj_unk_20 = gUnknown_085055CD[template->movementType];
+ FieldObjectSetDirection(mapObject, mapObject->mapobj_unk_20);
+ FieldObjectHandleDynamicGraphicsId(mapObject);
+
+ if (gUnknown_0850557C[mapObject->animPattern])
+ {
+ if ((mapObject->range.as_nybbles.x) == 0)
+ {
+ // r9 is invoked here
+ mapObject->range.as_nybbles.x ++;
+ }
+ if ((mapObject->range.as_nybbles.y) == 0)
+ {
+ mapObject->range.as_nybbles.y ++;
+ }
+ }
+ return slot;
+}
+#else
+static __attribute__((naked)) u8 InitFieldObjectStateFromTemplate(struct MapObjectTemplate *template, u8 mapId, u8 mapGroupId)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmov r7, r9\n"
+ "\tmov r6, r8\n"
+ "\tpush {r6,r7}\n"
+ "\tsub sp, 0x4\n"
+ "\tadds r5, r0, 0\n"
+ "\tlsls r1, 24\n"
+ "\tlsrs r6, r1, 24\n"
+ "\tlsls r2, 24\n"
+ "\tlsrs r7, r2, 24\n"
+ "\tldrb r0, [r5]\n"
+ "\tadds r1, r6, 0\n"
+ "\tadds r2, r7, 0\n"
+ "\tmov r3, sp\n"
+ "\tbl GetAvailableFieldObjectSlot\n"
+ "\tlsls r0, 24\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0808D66E\n"
+ "\tmovs r0, 0x10\n"
+ "\tb _0808D762\n"
+ "_0808D66E:\n"
+ "\tmov r0, sp\n"
+ "\tldrb r1, [r0]\n"
+ "\tlsls r0, r1, 3\n"
+ "\tadds r0, r1\n"
+ "\tlsls r0, 2\n"
+ "\tldr r1, =gMapObjects\n"
+ "\tadds r4, r0, r1\n"
+ "\tadds r0, r4, 0\n"
+ "\tbl npc_clear_ids_and_state\n"
+ "\tldrh r3, [r5, 0x4]\n"
+ "\tadds r3, 0x7\n"
+ "\tlsls r3, 16\n"
+ "\tlsrs r3, 16\n"
+ "\tldrh r2, [r5, 0x6]\n"
+ "\tadds r2, 0x7\n"
+ "\tlsls r2, 16\n"
+ "\tlsrs r2, 16\n"
+ "\tldrb r0, [r4]\n"
+ "\tmovs r1, 0x1\n"
+ "\torrs r0, r1\n"
+ "\tmovs r1, 0x4\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r4]\n"
+ "\tldrb r0, [r5, 0x1]\n"
+ "\tstrb r0, [r4, 0x5]\n"
+ "\tldrb r0, [r5, 0x9]\n"
+ "\tstrb r0, [r4, 0x6]\n"
+ "\tldrb r0, [r5]\n"
+ "\tstrb r0, [r4, 0x8]\n"
+ "\tstrb r6, [r4, 0x9]\n"
+ "\tstrb r7, [r4, 0xA]\n"
+ "\tstrh r3, [r4, 0xC]\n"
+ "\tstrh r2, [r4, 0xE]\n"
+ "\tstrh r3, [r4, 0x10]\n"
+ "\tstrh r2, [r4, 0x12]\n"
+ "\tstrh r3, [r4, 0x14]\n"
+ "\tstrh r2, [r4, 0x16]\n"
+ "\tldrb r0, [r5, 0x8]\n"
+ "\tmovs r7, 0xF\n"
+ "\tadds r1, r7, 0\n"
+ "\tands r1, r0\n"
+ "\tldrb r2, [r4, 0xB]\n"
+ "\tmovs r0, 0x10\n"
+ "\tnegs r0, r0\n"
+ "\tmov r8, r0\n"
+ "\tands r0, r2\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r4, 0xB]\n"
+ "\tldrb r1, [r5, 0x8]\n"
+ "\tlsls r1, 4\n"
+ "\tands r0, r7\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r4, 0xB]\n"
+ "\tldrb r1, [r5, 0xA]\n"
+ "\tlsls r1, 28\n"
+ "\tmovs r0, 0xF\n"
+ "\tmov r9, r0\n"
+ "\tlsrs r1, 28\n"
+ "\tldrb r2, [r4, 0x19]\n"
+ "\tmov r0, r8\n"
+ "\tands r0, r2\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r4, 0x19]\n"
+ "\tldrb r1, [r5, 0xA]\n"
+ "\tlsrs r1, 4\n"
+ "\tlsls r1, 4\n"
+ "\tands r0, r7\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r4, 0x19]\n"
+ "\tldrh r0, [r5, 0xC]\n"
+ "\tstrb r0, [r4, 0x7]\n"
+ "\tldrh r0, [r5, 0xE]\n"
+ "\tstrb r0, [r4, 0x1D]\n"
+ "\tldr r1, =gUnknown_085055CD\n"
+ "\tldrb r0, [r5, 0x9]\n"
+ "\tadds r0, r1\n"
+ "\tldrb r1, [r0]\n"
+ "\tadds r0, r4, 0\n"
+ "\tadds r0, 0x20\n"
+ "\tstrb r1, [r0]\n"
+ "\tldrb r1, [r0]\n"
+ "\tadds r0, r4, 0\n"
+ "\tbl FieldObjectSetDirection\n"
+ "\tadds r0, r4, 0\n"
+ "\tbl FieldObjectHandleDynamicGraphicsId\n"
+ "\tldr r1, =gUnknown_0850557C\n"
+ "\tldrb r0, [r4, 0x6]\n"
+ "\tadds r0, r1\n"
+ "\tldrb r0, [r0]\n"
+ "\tcmp r0, 0\n"
+ "\tbeq _0808D75E\n"
+ "\tldrb r2, [r4, 0x19]\n"
+ "\tadds r0, r7, 0\n"
+ "\tands r0, r2\n"
+ "\tcmp r0, 0\n"
+ "\tbne _0808D746\n"
+ "\tlsls r0, r2, 28\n"
+ "\tlsrs r0, 28\n"
+ "\tadds r0, 0x1\n"
+ "\tmov r1, r9\n"
+ "\tands r0, r1\n"
+ "\tmov r1, r8\n"
+ "\tands r1, r2\n"
+ "\torrs r1, r0\n"
+ "\tstrb r1, [r4, 0x19]\n"
+ "_0808D746:\n"
+ "\tldrb r2, [r4, 0x19]\n"
+ "\tmovs r0, 0xF0\n"
+ "\tands r0, r2\n"
+ "\tcmp r0, 0\n"
+ "\tbne _0808D75E\n"
+ "\tlsrs r1, r2, 4\n"
+ "\tadds r1, 0x1\n"
+ "\tlsls r1, 4\n"
+ "\tadds r0, r7, 0\n"
+ "\tands r0, r2\n"
+ "\torrs r0, r1\n"
+ "\tstrb r0, [r4, 0x19]\n"
+ "_0808D75E:\n"
+ "\tmov r0, sp\n"
+ "\tldrb r0, [r0]\n"
+ "_0808D762:\n"
+ "\tadd sp, 0x4\n"
+ "\tpop {r3,r4}\n"
+ "\tmov r8, r3\n"
+ "\tmov r9, r4\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r1}\n"
+ "\tbx r1\n"
+ ".pool");
+}
+#endif
+
+u8 unref_sub_808D77C(u8 localId)
+{
+ u8 i;
+ u8 nObjects;
+ struct MapObjectTemplate *template;
+
+ if (gMapHeader.events != NULL)
+ {
+ if (InBattlePyramid())
+ {
+ nObjects = sub_81AAA40();
+ }
+ else if (InTrainerHill())
+ {
+ nObjects = 2;
+ }
+ else
+ {
+ nObjects = gMapHeader.events->mapObjectCount;
+ }
+ for (i = 0; i < nObjects; i ++)
+ {
+ template = &gSaveBlock1Ptr->mapObjectTemplates[i];
+ if (template->localId == localId && !FlagGet(template->flagId))
+ {
+ return InitFieldObjectStateFromTemplate(template, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup);
+ }
+ }
+ }
+ return NUM_FIELD_OBJECTS;
+}
+
+static bool8 GetAvailableFieldObjectSlot(u16 localId, u8 mapNum, u8 mapGroup, u8 *result)
+// Looks for an empty slot.
+// Returns FALSE and the location of the available slot
+// in *result.
+// If no slots are available, or if the object is already
+// loaded, returns TRUE.
+{
+ u8 i = 0;
+
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ if (!gMapObjects[i].active)
+ break;
+ if (gMapObjects[i].localId == localId && gMapObjects[i].mapNum == mapNum && gMapObjects[i].mapGroup == mapGroup)
+ return TRUE;
+ }
+ if (i >= NUM_FIELD_OBJECTS)
+ return TRUE;
+ *result = i;
+ do
+ {
+ if (gMapObjects[i].active && gMapObjects[i].localId == localId && gMapObjects[i].mapNum == mapNum && gMapObjects[i].mapGroup == mapGroup)
+ return TRUE;
+ i ++;
+ } while (i < NUM_FIELD_OBJECTS);
+ return FALSE;
+}
+
+static void RemoveFieldObject(struct MapObject *mapObject)
+{
+ mapObject->active = FALSE;
+ RemoveFieldObjectInternal(mapObject);
+}
+
+void RemoveFieldObjectByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ u8 index;
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &index))
+ {
+ FlagSet(GetFieldObjectFlagIdByFieldObjectId(index));
+ RemoveFieldObject(&gMapObjects[index]);
+ }
+}
+
+static void RemoveFieldObjectInternal(struct MapObject *mapObject)
+{
+ struct SpriteFrameImage image;
+ image.size = GetFieldObjectGraphicsInfo(mapObject->graphicsId)->size;
+ gSprites[mapObject->spriteId].images = &image;
+ DestroySprite(&gSprites[mapObject->spriteId]);
+}
+
+void unref_sub_808D958(void)
+{
+ u8 i;
+
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ if (i != gPlayerAvatar.mapObjectId)
+ {
+ RemoveFieldObject(&gMapObjects[i]);
+ }
+ }
+}
+
+static u8 SpawnFieldObjectInternal(struct MapObjectTemplate *mapObjectTemplate, struct SpriteTemplate *spriteTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY)
+{
+ struct MapObject *mapObject;
+ const struct MapObjectGraphicsInfo *graphicsInfo;
+ struct Sprite *sprite;
+ u8 mapObjectId;
+ u8 paletteSlot;
+ u8 spriteId;
+
+ mapObjectId = InitFieldObjectStateFromTemplate(mapObjectTemplate, mapNum, mapGroup);
+ if (mapObjectId == NUM_FIELD_OBJECTS)
+ {
+ return NUM_FIELD_OBJECTS;
+ }
+ mapObject = &gMapObjects[mapObjectId];
+ graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId);
+ paletteSlot = graphicsInfo->paletteSlot;
+ if (paletteSlot == 0)
+ {
+ npc_load_two_palettes__no_record(graphicsInfo->paletteTag1, 0);
+ }
+ else if (paletteSlot == 10)
+ {
+ npc_load_two_palettes__and_record(graphicsInfo->paletteTag1, 10);
+ }
+ else if (paletteSlot >= 16)
+ {
+ paletteSlot -= 16;
+ sub_808EAB0(graphicsInfo->paletteTag1, paletteSlot);
+ }
+ if (mapObject->animPattern == 0x4c)
+ {
+ mapObject->mapobj_bit_13 = TRUE;
+ }
+ *(u16 *)&spriteTemplate->paletteTag = 0xFFFF;
+ spriteId = CreateSprite(spriteTemplate, 0, 0, 0);
+ if (spriteId == MAX_SPRITES)
+ {
+ gMapObjects[mapObjectId].active = FALSE;
+ return NUM_FIELD_OBJECTS;
+ }
+ sprite = &gSprites[spriteId];
+ sub_8092FF0(mapObject->coords2.x + cameraX, mapObject->coords2.y + cameraY, &sprite->pos1.x, &sprite->pos1.y);
+ sprite->centerToCornerVecX = -(graphicsInfo->width >> 1);
+ sprite->centerToCornerVecY = -(graphicsInfo->height >> 1);
+ sprite->pos1.x += 8;
+ sprite->pos1.y += 16 + sprite->centerToCornerVecY;
+ sprite->oam.paletteNum = paletteSlot;
+ sprite->coordOffsetEnabled = TRUE;
+ sprite->data0 = mapObjectId;
+ mapObject->spriteId = spriteId;
+ mapObject->mapobj_bit_12 = graphicsInfo->inanimate;
+ if (!mapObject->mapobj_bit_12)
+ {
+ StartSpriteAnim(sprite, FieldObjectDirectionToImageAnimId(mapObject->mapobj_unk_18));
+ }
+ SetObjectSubpriorityByZCoord(mapObject->elevation, sprite, 1);
+ sub_8096518(mapObject, sprite);
+ return mapObjectId;
+}
+
+static u8 SpawnFieldObject(struct MapObjectTemplate *mapObjectTemplate, u8 mapNum, u8 mapGroup, s16 cameraX, s16 cameraY)
+{
+ const struct MapObjectGraphicsInfo *graphicsInfo;
+ struct SpriteTemplate spriteTemplate;
+ const struct SubspriteTable *subspriteTables;
+ struct SpriteFrameImage spriteFrameImage;
+ u8 mapObjectId;
+
+ subspriteTables = NULL;
+ graphicsInfo = GetFieldObjectGraphicsInfo(mapObjectTemplate->graphicsId);
+ MakeObjectTemplateFromFieldObjectTemplate(mapObjectTemplate, &spriteTemplate, &subspriteTables);
+ spriteFrameImage.size = graphicsInfo->size;
+ spriteTemplate.images = &spriteFrameImage;
+ mapObjectId = SpawnFieldObjectInternal(mapObjectTemplate, &spriteTemplate, mapNum, mapGroup, cameraX, cameraY);
+ if (mapObjectId == NUM_FIELD_OBJECTS)
+ {
+ return NUM_FIELD_OBJECTS;
+ }
+ gSprites[gMapObjects[mapObjectId].spriteId].images = graphicsInfo->images;
+ if (subspriteTables != NULL)
+ {
+ SetSubspriteTables(&gSprites[gMapObjects[mapObjectId].spriteId], subspriteTables);
+ }
+ return mapObjectId;
+}
+
+u8 SpawnSpecialFieldObject(struct MapObjectTemplate *mapObjectTemplate)
+{
+ s16 cameraX;
+ s16 cameraY;
+
+ GetFieldObjectMovingCameraOffset(&cameraX, &cameraY);
+ return SpawnFieldObject(mapObjectTemplate, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, cameraX, cameraY);
+}
+
+u8 SpawnSpecialFieldObjectParametrized(u8 graphicsId, u8 movementBehavior, u8 localId, s16 x, s16 y, u8 z)
+{
+ struct MapObjectTemplate mapObjectTemplate;
+
+ x -= 7;
+ y -= 7;
+ mapObjectTemplate.localId = localId;
+ mapObjectTemplate.graphicsId = graphicsId;
+ mapObjectTemplate.unk2 = 0;
+ mapObjectTemplate.x = x;
+ mapObjectTemplate.y = y;
+ mapObjectTemplate.elevation = z;
+ mapObjectTemplate.movementType = movementBehavior;
+ mapObjectTemplate.unkA_0 = 0;
+ mapObjectTemplate.unkA_4 = 0;
+ mapObjectTemplate.unkC = 0;
+ mapObjectTemplate.unkE = 0;
+ return SpawnSpecialFieldObject(&mapObjectTemplate);
+}
+
+u8 show_sprite(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ struct MapObjectTemplate *mapObjectTemplate;
+ s16 cameraX;
+ s16 cameraY;
+
+ mapObjectTemplate = GetFieldObjectTemplateByLocalIdAndMap(localId, mapNum, mapGroup);
+ if (mapObjectTemplate == NULL)
+ {
+ return NUM_FIELD_OBJECTS;
+ }
+ GetFieldObjectMovingCameraOffset(&cameraX, &cameraY);
+ return SpawnFieldObject(mapObjectTemplate, mapNum, mapGroup, cameraX, cameraY);
+}
+
+static void MakeObjectTemplateFromFieldObjectGraphicsInfo(u16 graphicsId, void (*callback)(struct Sprite *), struct SpriteTemplate *sprTemplate, const struct SubspriteTable **subspriteTables)
+{
+ const struct MapObjectGraphicsInfo *gfxInfo = GetFieldObjectGraphicsInfo(graphicsId);
+
+ sprTemplate->tileTag = gfxInfo->tileTag;
+ sprTemplate->paletteTag = gfxInfo->paletteTag1;
+ sprTemplate->oam = gfxInfo->oam;
+ sprTemplate->anims = gfxInfo->anims;
+ sprTemplate->images = gfxInfo->images;
+ sprTemplate->affineAnims = gfxInfo->affineAnims;
+ sprTemplate->callback = callback;
+ *subspriteTables = gfxInfo->subspriteTables;
+}
+
+static void MakeObjectTemplateFromFieldObjectGraphicsInfoWithCallbackIndex(u16 graphicsId, u16 callbackIndex, struct SpriteTemplate *sprTemplate, const struct SubspriteTable **subspriteTables)
+{
+ MakeObjectTemplateFromFieldObjectGraphicsInfo(graphicsId, gUnknown_08505438[callbackIndex], sprTemplate, subspriteTables);
+}
+
+static void MakeObjectTemplateFromFieldObjectTemplate(struct MapObjectTemplate *mapObjectTemplate, struct SpriteTemplate *spriteTemplate, const struct SubspriteTable **subspriteTables)
+{
+ MakeObjectTemplateFromFieldObjectGraphicsInfoWithCallbackIndex(mapObjectTemplate->graphicsId, mapObjectTemplate->movementType, spriteTemplate, subspriteTables);
+}
+
+u8 AddPseudoFieldObject(u16 graphicsId, void (*callback)(struct Sprite *), s16 x, s16 y, u8 subpriority)
+{
+ struct SpriteTemplate *spriteTemplate;
+ const struct SubspriteTable *subspriteTables;
+ struct Sprite *sprite;
+ u8 spriteIdx;
+
+ spriteTemplate = malloc(sizeof(struct SpriteTemplate));
+ MakeObjectTemplateFromFieldObjectGraphicsInfo(graphicsId, callback, spriteTemplate, &subspriteTables);
+ if (spriteTemplate->paletteTag != 0xffff)
+ {
+ sub_808E894(spriteTemplate->paletteTag);
+ }
+ spriteIdx = CreateSprite(spriteTemplate, x, y, subpriority);
+ free(spriteTemplate);
+
+ if (spriteIdx != MAX_SPRITES && subspriteTables != NULL)
+ {
+ sprite = &gSprites[spriteIdx];
+ SetSubspriteTables(sprite, subspriteTables);
+ sprite->subspriteMode = 2;
+ }
+ return spriteIdx;
+}
+
+u8 sprite_new(u8 graphicsId, u8 a1, s16 x, s16 y, u8 z, u8 direction)
+{
+ const struct MapObjectGraphicsInfo *graphicsInfo;
+ struct SpriteTemplate spriteTemplate;
+ const struct SubspriteTable *subspriteTables;
+ u8 spriteId;
+ struct Sprite *sprite;
+
+ graphicsInfo = GetFieldObjectGraphicsInfo(graphicsId);
+ MakeObjectTemplateFromFieldObjectGraphicsInfo(graphicsId, sub_8097AC8, &spriteTemplate, &subspriteTables);
+ *(u16 *)&spriteTemplate.paletteTag = 0xffff;
+ x += 7;
+ y += 7;
+ sub_80930E0(&x, &y, 8, 16);
+ spriteId = CreateSpriteAtEnd(&spriteTemplate, x, y, 0);
+ if (spriteId != MAX_SPRITES)
+ {
+ sprite = &gSprites[spriteId];
+ sprite->centerToCornerVecX = -(graphicsInfo->width >> 1);
+ sprite->centerToCornerVecY = -(graphicsInfo->height >> 1);
+ sprite->pos1.y += sprite->centerToCornerVecY;
+ sprite->oam.paletteNum = graphicsInfo->paletteSlot;
+ if (sprite->oam.paletteNum >= 16)
+ {
+ sprite->oam.paletteNum -= 16;
+ }
+ sprite->coordOffsetEnabled = TRUE;
+ sprite->data0 = a1;
+ sprite->data1 = z;
+ if (graphicsInfo->paletteSlot == 10)
+ {
+ npc_load_two_palettes__and_record(graphicsInfo->paletteTag1, graphicsInfo->paletteSlot);
+ }
+ else if (graphicsInfo->paletteSlot >= 16)
+ {
+ sub_808EAB0(graphicsInfo->paletteTag1, graphicsInfo->paletteSlot | 0xf0);
+ }
+ if (subspriteTables != NULL)
+ {
+ SetSubspriteTables(sprite, subspriteTables);
+ sprite->subspriteMode = 2;
+ }
+ InitObjectPriorityByZCoord(sprite, z);
+ SetObjectSubpriorityByZCoord(z, sprite, 1);
+ StartSpriteAnim(sprite, FieldObjectDirectionToImageAnimId(direction));
+ }
+ return spriteId;
+}
+
+void SpawnFieldObjectsInView(s16 cameraX, s16 cameraY)
+{
+ u8 i;
+ s16 left;
+ s16 right;
+ s16 top;
+ s16 bottom;
+ u8 objectCount;
+ s16 npcX;
+ s16 npcY;
+
+ if (gMapHeader.events != NULL)
+ {
+ left = gSaveBlock1Ptr->pos.x - 2;
+ right = gSaveBlock1Ptr->pos.x + 17;
+ top = gSaveBlock1Ptr->pos.y;
+ bottom = gSaveBlock1Ptr->pos.y + 16;
+
+ if (InBattlePyramid())
+ {
+ objectCount = sub_81AAA40();
+ }
+ else if (InTrainerHill())
+ {
+ objectCount = 2;
+ }
+ else
+ {
+ objectCount = gMapHeader.events->mapObjectCount;
+ }
+
+ for (i = 0; i < objectCount; i++)
+ {
+ struct MapObjectTemplate *template = &gSaveBlock1Ptr->mapObjectTemplates[i];
+ npcX = template->x + 7;
+ npcY = template->y + 7;
+
+ if (top <= npcY && bottom >= npcY && left <= npcX && right >= npcX
+ && !FlagGet(template->flagId))
+ SpawnFieldObject(template, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, cameraX, cameraY);
+ }
+ }
+}
+
+/*static*/ void RemoveFieldObjectsOutsideView(void)
+{
+ u8 i;
+ u8 j;
+ bool8 isActiveLinkPlayer;
+ struct MapObject *mapObject;
+
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ for (j = 0, isActiveLinkPlayer = FALSE; j < ARRAY_COUNT(gLinkPlayerMapObjects); j ++)
+ {
+ if (gLinkPlayerMapObjects[j].active && i == gLinkPlayerMapObjects[j].mapObjId)
+ isActiveLinkPlayer = TRUE;
+ }
+ if (!isActiveLinkPlayer)
+ {
+ mapObject = &gMapObjects[i];
+
+ if (mapObject->active && !mapObject->mapobj_bit_16)
+ RemoveFieldObjectIfOutsideView(mapObject);
+ }
+ }
+}
+
+static void RemoveFieldObjectIfOutsideView(struct MapObject *mapObject)
+{
+ s16 left;
+ s16 right;
+ s16 top;
+ s16 bottom;
+
+ left = gSaveBlock1Ptr->pos.x - 2;
+ right = gSaveBlock1Ptr->pos.x + 17;
+ top = gSaveBlock1Ptr->pos.y;
+ bottom = gSaveBlock1Ptr->pos.y + 16;
+
+ if (mapObject->coords2.x >= left && mapObject->coords2.x <= right
+ && mapObject->coords2.y >= top && mapObject->coords2.y <= bottom)
+ return;
+ if (mapObject->coords1.x >= left && mapObject->coords1.x <= right
+ && mapObject->coords1.y >= top && mapObject->coords1.y <= bottom)
+ return;
+ RemoveFieldObject(mapObject);
+}
+
+void sub_808E16C(s16 x, s16 y)
+{
+ u8 i;
+
+ ClearPlayerAvatarInfo();
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ if (gMapObjects[i].active)
+ {
+ sub_808E1B8(i, x, y);
+ }
+ }
+ sub_808D450();
+}
+
+static void sub_808E1B8(u8 mapObjectId, s16 x, s16 y)
+{
+ u8 spriteId;
+ u8 paletteSlot;
+ struct MapObject *mapObject;
+ const struct SubspriteTable *subspriteTables;
+ const struct MapObjectGraphicsInfo *graphicsInfo;
+ struct SpriteFrameImage spriteFrameImage;
+ struct SpriteTemplate spriteTemplate;
+ struct Sprite *sprite;
+
+#define i spriteId
+ for (i = 0; i < ARRAY_COUNT(gLinkPlayerMapObjects); i ++)
+ {
+ if (gLinkPlayerMapObjects[i].active && mapObjectId == gLinkPlayerMapObjects[i].mapObjId)
+ {
+ return;
+ }
+ }
+#undef i
+
+ mapObject = &gMapObjects[mapObjectId];
+ subspriteTables = NULL;
+ graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId);
+ spriteFrameImage.size = graphicsInfo->size;
+ MakeObjectTemplateFromFieldObjectGraphicsInfoWithCallbackIndex(mapObject->graphicsId, mapObject->animPattern, &spriteTemplate, &subspriteTables);
+ spriteTemplate.images = &spriteFrameImage;
+ *(u16 *)&spriteTemplate.paletteTag = 0xffff;
+ paletteSlot = graphicsInfo->paletteSlot;
+ if (paletteSlot == 0)
+ {
+ npc_load_two_palettes__no_record(graphicsInfo->paletteTag1, graphicsInfo->paletteSlot);
+ }
+ else if (paletteSlot == 10)
+ {
+ npc_load_two_palettes__and_record(graphicsInfo->paletteTag1, graphicsInfo->paletteSlot);
+ }
+ else if (paletteSlot >= 16)
+ {
+ paletteSlot -= 16;
+ sub_808EAB0(graphicsInfo->paletteTag1, paletteSlot);
+ }
+ *(u16 *)&spriteTemplate.paletteTag = 0xffff;
+ spriteId = CreateSprite(&spriteTemplate, 0, 0, 0);
+ if (spriteId != MAX_SPRITES)
+ {
+ sprite = &gSprites[spriteId];
+ sub_8092FF0(x + mapObject->coords2.x, y + mapObject->coords2.y, &sprite->pos1.x, &sprite->pos1.y);
+ sprite->centerToCornerVecX = -(graphicsInfo->width >> 1);
+ sprite->centerToCornerVecY = -(graphicsInfo->height >> 1);
+ sprite->pos1.x += 8;
+ sprite->pos1.y += 16 + sprite->centerToCornerVecY;
+ sprite->images = graphicsInfo->images;
+ if (mapObject->animPattern == 0x0b)
+ {
+ SetPlayerAvatarFieldObjectIdAndObjectId(mapObjectId, spriteId);
+ mapObject->mapobj_unk_1B = sub_8154228();
+ }
+ if (subspriteTables != NULL)
+ {
+ SetSubspriteTables(sprite, subspriteTables);
+ }
+ sprite->oam.paletteNum = paletteSlot;
+ sprite->coordOffsetEnabled = TRUE;
+ sprite->data0 = mapObjectId;
+ mapObject->spriteId = spriteId;
+ if (!mapObject->mapobj_bit_12 && mapObject->animPattern != 0x0b)
+ {
+ StartSpriteAnim(sprite, FieldObjectDirectionToImageAnimId(mapObject->mapobj_unk_18));
+ }
+ sub_808E38C(mapObject);
+ SetObjectSubpriorityByZCoord(mapObject->elevation, sprite, 1);
+ }
+}
+
+/*static*/ void sub_808E38C(struct MapObject *mapObject)
+{
+ mapObject->mapobj_bit_1 = FALSE;
+ mapObject->mapobj_bit_2 = TRUE;
+ mapObject->mapobj_bit_22 = FALSE;
+ mapObject->mapobj_bit_17 = FALSE;
+ mapObject->mapobj_bit_18 = FALSE;
+ mapObject->mapobj_bit_19 = FALSE;
+ mapObject->mapobj_bit_20 = FALSE;
+ mapObject->mapobj_bit_21 = FALSE;
+ FieldObjectClearAnim(mapObject);
+}
+
+static void SetPlayerAvatarFieldObjectIdAndObjectId(u8 mapObjectId, u8 spriteId)
+{
+ gPlayerAvatar.mapObjectId = mapObjectId;
+ gPlayerAvatar.spriteId = spriteId;
+ gPlayerAvatar.gender = GetPlayerAvatarGenderByGraphicsId(gMapObjects[mapObjectId].graphicsId);
+ SetPlayerAvatarExtraStateTransition(gMapObjects[mapObjectId].graphicsId, 0x20);
+}
+
+void FieldObjectSetGraphicsId(struct MapObject *mapObject, u8 graphicsId)
+{
+ const struct MapObjectGraphicsInfo *graphicsInfo;
+ struct Sprite *sprite;
+ u8 paletteSlot;
+
+ graphicsInfo = GetFieldObjectGraphicsInfo(graphicsId);
+ sprite = &gSprites[mapObject->spriteId];
+ paletteSlot = graphicsInfo->paletteSlot;
+ if (paletteSlot == 0)
+ {
+ pal_patch_for_npc(graphicsInfo->paletteTag1, graphicsInfo->paletteSlot);
+ }
+ else if (paletteSlot == 10)
+ {
+ npc_load_two_palettes__and_record(graphicsInfo->paletteTag1, graphicsInfo->paletteSlot);
+ }
+ else if (paletteSlot >= 16)
+ {
+ paletteSlot -= 16;
+ sub_808EAB0(graphicsInfo->paletteTag1, paletteSlot);
+ }
+ sprite->oam.shape = graphicsInfo->oam->shape;
+ sprite->oam.size = graphicsInfo->oam->size;
+ sprite->images = graphicsInfo->images;
+ sprite->anims = graphicsInfo->anims;
+ sprite->subspriteTables = graphicsInfo->subspriteTables;
+ sprite->oam.paletteNum = paletteSlot;
+ mapObject->mapobj_bit_12 = graphicsInfo->inanimate;
+ mapObject->graphicsId = graphicsId;
+ sub_8093038(mapObject->coords2.x, mapObject->coords2.y, &sprite->pos1.x, &sprite->pos1.y);
+ sprite->centerToCornerVecX = -(graphicsInfo->width >> 1);
+ sprite->centerToCornerVecY = -(graphicsInfo->height >> 1);
+ sprite->pos1.x += 8;
+ sprite->pos1.y += 16 + sprite->centerToCornerVecY;
+ if (mapObject->mapobj_bit_15)
+ {
+ CameraObjectReset1();
+ }
+}
+
+void FieldObjectSetGraphicsIdByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup, u8 graphicsId)
+{
+ u8 mapObjectId;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ FieldObjectSetGraphicsId(&gMapObjects[mapObjectId], graphicsId);
+ }
+}
+
+void FieldObjectTurn(struct MapObject *mapObject, u8 direction)
+{
+ FieldObjectSetDirection(mapObject, direction);
+ if (!mapObject->mapobj_bit_12)
+ {
+ StartSpriteAnim(&gSprites[mapObject->spriteId], FieldObjectDirectionToImageAnimId(mapObject->mapobj_unk_18));
+ SeekSpriteAnim(&gSprites[mapObject->spriteId], 0);
+ }
+}
+
+void FieldObjectTurnByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup, u8 direction)
+{
+ u8 mapObjectId;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ FieldObjectTurn(&gMapObjects[mapObjectId], direction);
+ }
+}
+
+void PlayerObjectTurn(struct PlayerAvatar *playerAvatar, u8 direction)
+{
+ FieldObjectTurn(&gMapObjects[playerAvatar->mapObjectId], direction);
+}
+
+/*static*/ void get_berry_tree_graphics(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 berryStage;
+ u8 berryId;
+
+ mapObject->mapobj_bit_13 = TRUE;
+ sprite->invisible = TRUE;
+ berryStage = GetStageByBerryTreeId(mapObject->trainerRange_berryTreeId);
+ if (berryStage != 0)
+ {
+ mapObject->mapobj_bit_13 = FALSE;
+ sprite->invisible = FALSE;
+ berryId = GetBerryTypeByBerryTreeId(mapObject->trainerRange_berryTreeId) - 1;
+ berryStage -= 1;
+ if (berryId >= NUM_BERRIES)
+ {
+ berryId = 0;
+ }
+ FieldObjectSetGraphicsId(mapObject, gBerryTreeFieldObjectGraphicsIdTablePointers[berryId][berryStage]);
+ sprite->images = gBerryTreePicTablePointers[berryId];
+ sprite->oam.paletteNum = gBerryTreePaletteSlotTablePointers[berryId][berryStage];
+ StartSpriteAnim(sprite, berryStage);
+ }
+}
+
+const struct MapObjectGraphicsInfo *GetFieldObjectGraphicsInfo(u8 graphicsId)
+{
+ u8 bard;
+
+ if (graphicsId >= SPRITE_VAR)
+ {
+ graphicsId = VarGetFieldObjectGraphicsId(graphicsId - SPRITE_VAR);
+ }
+ if (graphicsId == 0x45)
+ {
+ bard = sub_81201C8();
+ return gMauvilleOldManGraphicsInfoPointers[bard];
+ }
+ if (graphicsId >= NUM_OBJECT_GRAPHICS_INFO)
+ {
+ graphicsId = 0x05; // LittleBoy1
+ }
+ return gFieldObjectGraphicsInfoPointers[graphicsId];
+}
+
+static void FieldObjectHandleDynamicGraphicsId(struct MapObject *mapObject)
+{
+ if (mapObject->graphicsId >= SPRITE_VAR)
+ {
+ mapObject->graphicsId = VarGetFieldObjectGraphicsId(mapObject->graphicsId - SPRITE_VAR);
+ }
+}
+
+void npc_by_local_id_and_map_set_field_1_bit_x20(u8 localId, u8 mapNum, u8 mapGroup, u8 state)
+{
+ u8 mapObjectId;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ gMapObjects[mapObjectId].mapobj_bit_13 = state;
+ }
+}
+
+void FieldObjectGetLocalIdAndMap(struct MapObject *mapObject, u8 *localId, u8 *mapNum, u8 *mapGroup)
+{
+ *localId = mapObject->localId;
+ *mapNum = mapObject->mapNum;
+ *mapGroup = mapObject->mapGroup;
+}
+
+void sub_808E75C(s16 x, s16 y)
+{
+ u8 mapObjectId;
+ struct MapObject *mapObject;
+
+ mapObjectId = GetFieldObjectIdByXY(x, y);
+ if (mapObjectId != NUM_FIELD_OBJECTS)
+ {
+ mapObject = &gMapObjects[mapObjectId];
+ mapObject->mapobj_bit_2 = TRUE;
+ }
+}
+
+void sub_808E78C(u8 localId, u8 mapNum, u8 mapGroup, u8 subpriority)
+{
+ u8 mapObjectId;
+ struct MapObject *mapObject;
+ struct Sprite *sprite;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ mapObject = &gMapObjects[mapObjectId];
+ sprite = &gSprites[mapObject->spriteId];
+ mapObject->mapobj_bit_26 = TRUE;
+ sprite->subpriority = subpriority;
+ }
+}
+
+void sub_808E7E4(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ u8 mapObjectId;
+ struct MapObject *mapObject;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ mapObject = &gMapObjects[mapObjectId];
+ mapObject->mapobj_bit_26 = FALSE;
+ mapObject->mapobj_bit_2 = TRUE;
+ }
+}
+
+void sub_808E82C(u8 localId, u8 mapNum, u8 mapGroup, s16 x, s16 y)
+{
+ u8 mapObjectId;
+ struct Sprite *sprite;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ sprite = &gSprites[gMapObjects[mapObjectId].spriteId];
+ sprite->pos2.x = x;
+ sprite->pos2.y = y;
+ }
+}
+
+void gpu_pal_allocator_reset__manage_upper_four(void)
+{
+ FreeAllSpritePalettes();
+ gReservedSpritePaletteCount = 12;
+}
+
+static void sub_808E894(u16 paletteTag)
+{
+ u16 paletteSlot;
+
+ paletteSlot = FindFieldObjectPaletteIndexByTag(paletteTag);
+ if (paletteSlot != 0x11ff) // always true
+ {
+ sub_808E8F4(&gUnknown_0850BBC8[paletteSlot]);
+ }
+}
+
+void sub_808E8C0(u16 *paletteTags)
+{
+ u8 i;
+
+ for (i = 0; paletteTags[i] != 0x11ff; i ++)
+ {
+ sub_808E894(paletteTags[i]);
+ }
+}
+
+static u8 sub_808E8F4(const struct SpritePalette *spritePalette)
+{
+ if (IndexOfSpritePaletteTag(spritePalette->tag) != 0xff)
+ {
+ return 0xff;
+ }
+ return LoadSpritePalette(spritePalette);
+}
+
+void pal_patch_for_npc(u16 paletteTag, u8 paletteSlot)
+{
+ u16 paletteIdx;
+
+ paletteIdx = FindFieldObjectPaletteIndexByTag(paletteTag);
+ LoadPalette(gUnknown_0850BBC8[paletteIdx].data, 16 * paletteSlot + 256, 0x20);
+}
+
+void pal_patch_for_npc_range(const u16 *paletteTags, u8 minSlot, u8 maxSlot)
+{
+ while (minSlot < maxSlot)
+ {
+ pal_patch_for_npc(*paletteTags, minSlot);
+ paletteTags ++;
+ minSlot ++;
+ }
+}
+
+static u8 FindFieldObjectPaletteIndexByTag(u16 tag)
+{
+ u8 i;
+
+ for (i = 0; gUnknown_0850BBC8[i].tag != 0x11ff; i ++)
+ {
+ if (gUnknown_0850BBC8[i].tag == tag)
+ {
+ return i;
+ }
+ }
+ return 0xff;
+}
+
+void npc_load_two_palettes__no_record(u16 tag, u8 slot)
+{
+ u8 i;
+
+ pal_patch_for_npc(tag, slot);
+ for (i = 0; gUnknown_0850BD00[i].tag != 0x11ff; i ++)
+ {
+ if (gUnknown_0850BD00[i].tag == tag)
+ {
+ pal_patch_for_npc(gUnknown_0850BD00[i].data[gUnknown_020375B4], gUnknown_084975C4[slot]);
+ return;
+ }
+ }
+}
+
+void npc_load_two_palettes__and_record(u16 tag, u8 slot)
+{
+ u8 i;
+
+ gUnknown_020375B6 = tag;
+ pal_patch_for_npc(tag, slot);
+ for (i = 0; gUnknown_0850BD78[i].tag != 0x11ff; i ++)
+ {
+ if (gUnknown_0850BD78[i].tag == tag)
+ {
+ pal_patch_for_npc(gUnknown_0850BD78[i].data[gUnknown_020375B4], gUnknown_084975C4[slot]);
+ return;
+ }
+ }
+}
+
+static void sub_808EAB0(u16 tag, u8 slot)
+{
+ pal_patch_for_npc(tag, slot);
+}
+
+void unref_sub_808EAC4(struct MapObject *mapObject, s16 x, s16 y)
+{
+ mapObject->coords3.x = mapObject->coords2.x;
+ mapObject->coords3.y = mapObject->coords2.y;
+ mapObject->coords2.x += x;
+ mapObject->coords2.y += y;
+}
+
+void npc_coords_shift(struct MapObject *mapObject, s16 x, s16 y)
+{
+ mapObject->coords3.x = mapObject->coords2.x;
+ mapObject->coords3.y = mapObject->coords2.y;
+ mapObject->coords2.x = x;
+ mapObject->coords2.y = y;
+}
+
+/*static*/ void npc_coords_set(struct MapObject *mapObject, s16 x, s16 y)
+{
+ mapObject->coords3.x = x;
+ mapObject->coords3.y = y;
+ mapObject->coords2.x = x;
+ mapObject->coords2.y = y;
+}
+
+void sub_808EB08(struct MapObject *mapObject, s16 x, s16 y)
+{
+ struct Sprite *sprite;
+ const struct MapObjectGraphicsInfo *graphicsInfo;
+
+ sprite = &gSprites[mapObject->spriteId];
+ graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId);
+ npc_coords_set(mapObject, x, y);
+ sub_8093038(mapObject->coords2.x, mapObject->coords2.y, &sprite->pos1.x, &sprite->pos1.y);
+ sprite->centerToCornerVecX = -(graphicsInfo->width >> 1);
+ sprite->centerToCornerVecY = -(graphicsInfo->height >> 1);
+ sprite->pos1.x += 8;
+ sprite->pos1.y += 16 + sprite->centerToCornerVecY;
+ sub_808E38C(mapObject);
+ if (mapObject->mapobj_bit_15)
+ {
+ CameraObjectReset1();
+ }
+}
+
+void sub_808EBA8(u8 localId, u8 mapNum, u8 mapGroup, s16 x, s16 y)
+{
+ u8 mapObjectId;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ x += 7;
+ y += 7;
+ sub_808EB08(&gMapObjects[mapObjectId], x, y);
+ }
+}
+
+void npc_coords_shift_still(struct MapObject *mapObject)
+{
+ npc_coords_shift(mapObject, mapObject->coords2.x, mapObject->coords2.y);
+}
+
+void UpdateFieldObjectCoordsForCameraUpdate(void)
+{
+ u8 i;
+ s16 dx;
+ s16 dy;
+
+ if (gCamera.active)
+ {
+ dx = gCamera.x;
+ dy = gCamera.y;
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ if (gMapObjects[i].active)
+ {
+ gMapObjects[i].coords1.x -= dx;
+ gMapObjects[i].coords1.y -= dy;
+ gMapObjects[i].coords2.x -= dx;
+ gMapObjects[i].coords2.y -= dy;
+ gMapObjects[i].coords3.x -= dx;
+ gMapObjects[i].coords3.y -= dy;
+ }
+ }
+ }
+}
+
+u8 GetFieldObjectIdByXYZ(u16 x, u16 y, u8 z)
+{
+ u8 i;
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ if (gMapObjects[i].active)
+ {
+ if (gMapObjects[i].coords2.x == x && gMapObjects[i].coords2.y == y && FieldObjectDoesZCoordMatch(&gMapObjects[i], z))
+ {
+ return i;
+ }
+ }
+ }
+ return NUM_FIELD_OBJECTS;
+}
+
+static bool8 FieldObjectDoesZCoordMatch(struct MapObject *mapObject, u8 z)
+{
+ if (mapObject->mapobj_unk_0B_0 != 0 && z != 0 && mapObject->mapobj_unk_0B_0 != z)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void UpdateFieldObjectsForCameraUpdate(s16 x, s16 y)
+{
+ UpdateFieldObjectCoordsForCameraUpdate();
+ SpawnFieldObjectsInView(x, y);
+ RemoveFieldObjectsOutsideView();
+}
+
+u8 AddCameraObject(u8 linkedSpriteId)
+{
+ u8 spriteId;
+
+ spriteId = CreateSprite(&gUnknown_084975D4, 0, 0, 4);
+ gSprites[spriteId].invisible = TRUE;
+ gSprites[spriteId].data0 = linkedSpriteId;
+ return spriteId;
+}
+
+void ObjectCB_CameraObject(struct Sprite *sprite)
+{
+ void (*callbacks[ARRAY_COUNT(gUnknown_084975EC)])(struct Sprite *);
+
+ memcpy(callbacks, gUnknown_084975EC, sizeof gUnknown_084975EC);
+ callbacks[sprite->data1](sprite);
+}
+
+/*static*/ void CameraObject_0(struct Sprite *sprite)
+{
+ sprite->pos1.x = gSprites[sprite->data0].pos1.x;
+ sprite->pos1.y = gSprites[sprite->data0].pos1.y;
+ sprite->invisible = TRUE;
+ sprite->data1 = 1;
+ CameraObject_1(sprite);
+}
+
+/*static*/ void CameraObject_1(struct Sprite *sprite)
+{
+ s16 x;
+ s16 y;
+
+ y = gSprites[sprite->data0].pos1.y;
+ x = gSprites[sprite->data0].pos1.x;
+ sprite->data2 = x - sprite->pos1.x;
+ sprite->data3 = y - sprite->pos1.y;
+ sprite->pos1.x = x;
+ sprite->pos1.y = y;
+}
+
+/*static*/ void CameraObject_2(struct Sprite *sprite)
+{
+ sprite->pos1.x = gSprites[sprite->data0].pos1.x;
+ sprite->pos1.y = gSprites[sprite->data0].pos1.y;
+ sprite->data2 = 0;
+ sprite->data3 = 0;
+}
+
+static struct Sprite *FindCameraObject(void)
+{
+ u8 spriteId;
+
+ for (spriteId = 0; spriteId < MAX_SPRITES; spriteId ++)
+ {
+ if (gSprites[spriteId].inUse && gSprites[spriteId].callback == ObjectCB_CameraObject)
+ {
+ return &gSprites[spriteId];
+ }
+ }
+ return NULL;
+}
+
+void CameraObjectReset1(void)
+{
+ struct Sprite *cameraObject;
+
+ cameraObject = FindCameraObject();
+ if (cameraObject != NULL)
+ {
+ cameraObject->data1 = 0;
+ cameraObject->callback(cameraObject);
+ }
+}
+
+void CameraObjectSetFollowedObjectId(u8 objectId)
+{
+ struct Sprite *cameraObject;
+
+ cameraObject = FindCameraObject();
+ if (cameraObject != NULL)
+ {
+ cameraObject->data0 = objectId;
+ CameraObjectReset1();
+ }
+}
+
+u8 CameraObjectGetFollowedObjectId(void)
+{
+ struct Sprite *cameraObject;
+
+ cameraObject = FindCameraObject();
+ if (cameraObject == NULL)
+ {
+ return MAX_SPRITES;
+ }
+ return cameraObject->data0;
+}
+
+void CameraObjectReset2(void)
+{
+ FindCameraObject()->data1 = 2;
+}
+
+u8 CopySprite(struct Sprite *sprite, s16 x, s16 y, u8 subpriority)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_SPRITES; i ++)
+ {
+ if (!gSprites[i].inUse)
+ {
+ gSprites[i] = *sprite;
+ gSprites[i].pos1.x = x;
+ gSprites[i].pos1.y = y;
+ gSprites[i].subpriority = subpriority;
+ break;
+ }
+ }
+ return i;
+}
+
+u8 obj_unfreeze(struct Sprite *sprite, s16 x, s16 y, u8 subpriority)
+{
+ s16 i;
+
+ for (i = MAX_SPRITES - 1; i > -1; i --)
+ {
+ if (!gSprites[i].inUse)
+ {
+ gSprites[i] = *sprite;
+ gSprites[i].pos1.x = x;
+ gSprites[i].pos1.y = y;
+ gSprites[i].subpriority = subpriority;
+ return i;
+ }
+ }
+ return MAX_SPRITES;
+}
+
+void FieldObjectSetDirection(struct MapObject *mapObject, u8 direction)
+{
+ s8 d2;
+ mapObject->mapobj_unk_20 = mapObject->mapobj_unk_18;
+ if (!mapObject->mapobj_bit_9)
+ {
+ d2 = direction;
+ mapObject->mapobj_unk_18 = d2;
+ }
+ mapObject->placeholder18 = direction;
+}
+
+static const u8 *GetFieldObjectScriptPointerByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ return GetFieldObjectTemplateByLocalIdAndMap(localId, mapNum, mapGroup)->script;
+}
+
+const u8 *GetFieldObjectScriptPointerByFieldObjectId(u8 mapObjectId)
+{
+ return GetFieldObjectScriptPointerByLocalIdAndMap(gMapObjects[mapObjectId].localId, gMapObjects[mapObjectId].mapNum, gMapObjects[mapObjectId].mapGroup);
+}
+
+static u16 GetFieldObjectFlagIdByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ return GetFieldObjectTemplateByLocalIdAndMap(localId, mapNum, mapGroup)->flagId;
+}
+
+u16 GetFieldObjectFlagIdByFieldObjectId(u8 mapObjectId)
+{
+ return GetFieldObjectFlagIdByLocalIdAndMap(gMapObjects[mapObjectId].localId, gMapObjects[mapObjectId].mapNum, gMapObjects[mapObjectId].mapGroup);
+}
+
+u8 sub_808F080(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ u8 mapObjectId;
+
+ if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ return 0xFF;
+ }
+ return gMapObjects[mapObjectId].trainerType;
+}
+
+u8 sub_808F0BC(u8 mapObjectId)
+{
+ return gMapObjects[mapObjectId].trainerType;
+}
+
+u8 sub_808F0D4(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ u8 mapObjectId;
+
+ if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ return 0xFF;
+ }
+ return gMapObjects[mapObjectId].trainerRange_berryTreeId;
+}
+
+u8 FieldObjectGetBerryTreeId(u8 mapObjectId)
+{
+ return gMapObjects[mapObjectId].trainerRange_berryTreeId;
+}
+
+struct MapObjectTemplate *GetFieldObjectTemplateByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ struct MapObjectTemplate *templates;
+ const struct MapHeader *mapHeader;
+ u8 count;
+
+ if (gSaveBlock1Ptr->location.mapNum == mapNum && gSaveBlock1Ptr->location.mapGroup == mapGroup)
+ {
+ templates = gSaveBlock1Ptr->mapObjectTemplates;
+ count = gMapHeader.events->mapObjectCount;
+ }
+ else
+ {
+ mapHeader = get_mapheader_by_bank_and_number(mapGroup, mapNum);
+ templates = mapHeader->events->mapObjects;
+ count = mapHeader->events->mapObjectCount;
+ }
+ return FindFieldObjectTemplateInArrayByLocalId(localId, templates, count);
+}
+
+struct MapObjectTemplate *FindFieldObjectTemplateInArrayByLocalId(u8 localId, struct MapObjectTemplate *templates, u8 count)
+{
+ u8 i;
+
+ for (i = 0; i < count; i ++)
+ {
+ if (templates[i].localId == localId)
+ {
+ return &templates[i];
+ }
+ }
+ return NULL;
+}
+
+struct MapObjectTemplate *sub_808F1B4(const struct MapObject *mapObject)
+{
+ int i;
+
+ if (mapObject->mapNum != gSaveBlock1Ptr->location.mapNum || mapObject->mapGroup != gSaveBlock1Ptr->location.mapGroup)
+ {
+ return NULL;
+ }
+ for (i = 0; i < 64; i ++) // Using ARRAY_COUNT here results in the wrong conditional branch instruction (bls instead of ble)
+ {
+ if (mapObject->localId == gSaveBlock1Ptr->mapObjectTemplates[i].localId)
+ {
+ return &gSaveBlock1Ptr->mapObjectTemplates[i];
+ }
+ }
+ return NULL;
+}
+
+void sub_808F208(const struct MapObject *mapObject)
+{
+ struct MapObjectTemplate *mapObjectTemplate;
+
+ mapObjectTemplate = sub_808F1B4(mapObject);
+ if (mapObjectTemplate != NULL)
+ {
+ mapObjectTemplate->x = mapObject->coords2.x - 7;
+ mapObjectTemplate->y = mapObject->coords2.y - 7;
+ }
+}
+
+void sub_808F228(const struct MapObject *mapObject, const u8 *script)
+{
+ struct MapObjectTemplate *mapObjectTemplate;
+
+ mapObjectTemplate = sub_808F1B4(mapObject);
+ if (mapObjectTemplate != NULL)
+ {
+ mapObjectTemplate->script = script;
+ }
+}
+
+void sub_808F23C(const struct MapObject *mapObject, u8 movementType)
+{
+ struct MapObjectTemplate *mapObjectTemplate;
+
+ mapObjectTemplate = sub_808F1B4(mapObject);
+ if (mapObjectTemplate != NULL)
+ {
+ mapObjectTemplate->movementType = movementType;
+ }
+}
+
+void sub_808F254(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ u8 mapObjectId;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ sub_808F208(&gMapObjects[mapObjectId]);
+ }
+}
+
+void sub_808F28C(u8 localId, u8 mapNum, u8 mapGroup, u8 action)
+{
+ u8 mapObjectId;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ switch (action)
+ {
+ case 6:
+ sub_808F228(&gMapObjects[mapObjectId], gUnknown_082766A2);
+ break;
+ case 7:
+ sub_808F228(&gMapObjects[mapObjectId], gUnknown_082766A6);
+ break;
+ }
+ }
+}
+
+void npc_paltag_set_load(u8 palSlot)
+{
+ gpu_pal_allocator_reset__manage_upper_four();
+ gUnknown_020375B6 = 0x11ff;
+ gUnknown_020375B4 = palSlot;
+ if (palSlot == 1)
+ {
+ pal_patch_for_npc_range(gUnknown_0850BE38[gUnknown_020375B4], 0, 6);
+ gReservedSpritePaletteCount = 8;
+ }
+ else
+ {
+ pal_patch_for_npc_range(gUnknown_0850BE38[gUnknown_020375B4], 0, 10);
+ }
+}
+
+u16 npc_paltag_by_palslot(u8 palSlot)
+{
+ u8 i;
+
+ if (palSlot < 10)
+ {
+ return gUnknown_0850BE38[gUnknown_020375B4][palSlot];
+ }
+ for (i = 0; gUnknown_0850BD78[i].tag != 0x11ff; i ++)
+ {
+ if (gUnknown_0850BD78[i].tag == gUnknown_020375B6)
+ {
+ return gUnknown_0850BD78[i].data[gUnknown_020375B4];
+ }
+ }
+ return 0x11ff;
+}
+
+// Map Object Step Callbacks
+// file boundary?
+
+null_object_step(NoMovement1, FALSE)
+
+field_object_step(GoRandomDirections, gUnknown_0850D6F4)
+
+bool8 sub_808F44C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_808F460(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_808F48C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (!FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ return FALSE;
+ }
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6DC[Random() & 0x03]);
+ sprite->data1 = 3;
+ return TRUE;
+}
+
+bool8 sub_808F4C8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_808F4E8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[4];
+ u8 chosenDirection;
+
+ memcpy(directions, gUnknown_0850D710, sizeof directions);
+ chosenDirection = directions[Random() & 0x03];
+ FieldObjectSetDirection(mapObject, chosenDirection);
+ sprite->data1 = 5;
+ if (npc_block_way__next_tile(mapObject, chosenDirection))
+ {
+ sprite->data1 = 1;
+ }
+ return TRUE;
+}
+
+bool8 sub_808F534(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetGoSpeed0AnimId(mapObject->placeholder18));
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 6;
+ return TRUE;
+}
+
+bool8 sub_808F564(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 1;
+ }
+ return FALSE;
+}
+
+bool8 FieldObjectIsTrainerAndCloseToPlayer(struct MapObject *mapObject)
+{
+ s16 playerX;
+ s16 playerY;
+ s16 objX;
+ s16 objY;
+ s16 minX;
+ s16 maxX;
+ s16 minY;
+ s16 maxY;
+
+ if (!TestPlayerAvatarFlags(0x80))
+ {
+ return FALSE;
+ }
+ if (mapObject->trainerType != 1 && mapObject->trainerType != 3)
+ {
+ return FALSE;
+ }
+ PlayerGetDestCoords(&playerX, &playerY);
+ objX = mapObject->coords2.x;
+ objY = mapObject->coords2.y;
+ minX = objX - mapObject->trainerRange_berryTreeId;
+ minY = objY - mapObject->trainerRange_berryTreeId;
+ maxX = objX + mapObject->trainerRange_berryTreeId;
+ maxY = objY + mapObject->trainerRange_berryTreeId;
+ if (minX > playerX || maxX < playerX || minY > playerY || maxY < playerY)
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+u8 GetRegularRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ if (absdx > absdy)
+ {
+ direction = DIR_EAST;
+ if (dx < 0)
+ {
+ direction = DIR_WEST;
+ }
+ }
+ else
+ {
+ direction = DIR_SOUTH;
+ if (dy < 0)
+ {
+ direction = DIR_NORTH;
+ }
+ }
+ return direction;
+}
+
+u8 GetNorthSouthRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ direction = DIR_SOUTH;
+ if (dy < 0)
+ {
+ direction = DIR_NORTH;
+ }
+ return direction;
+}
+
+u8 GetEastWestRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ direction = DIR_EAST;
+ if (dx < 0)
+ {
+ direction = DIR_WEST;
+ }
+ return direction;
+}
+
+u8 GetNorthEastRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ direction = GetRegularRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_SOUTH)
+ {
+ direction = GetEastWestRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_EAST)
+ {
+ direction = DIR_NORTH;
+ }
+ }
+ else if (direction == DIR_EAST)
+ {
+ direction = GetNorthSouthRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_SOUTH)
+ {
+ direction = DIR_NORTH;
+ }
+ }
+ return direction;
+}
+
+u8 GetNorthWestRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ direction = GetRegularRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_SOUTH)
+ {
+ direction = GetEastWestRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_WEST)
+ {
+ direction = DIR_NORTH;
+ }
+ }
+ else if (direction == DIR_WEST)
+ {
+ direction = GetNorthSouthRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_SOUTH)
+ {
+ direction = DIR_NORTH;
+ }
+ }
+ return direction;
+}
+
+u8 GetSouthEastRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ direction = GetRegularRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_NORTH)
+ {
+ direction = GetEastWestRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_EAST)
+ {
+ direction = DIR_SOUTH;
+ }
+ }
+ else if (direction == DIR_EAST)
+ {
+ direction = GetNorthSouthRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_NORTH)
+ {
+ direction = DIR_SOUTH;
+ }
+ }
+ return direction;
+}
+
+u8 GetSouthWestRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ direction = GetRegularRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_NORTH)
+ {
+ direction = GetEastWestRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_WEST)
+ {
+ direction = DIR_SOUTH;
+ }
+ }
+ else if (direction == DIR_WEST)
+ {
+ direction = GetNorthSouthRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_NORTH)
+ {
+ direction = DIR_SOUTH;
+ }
+ }
+ return direction;
+}
+
+u8 GetNonEastRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ direction = GetRegularRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_EAST)
+ {
+ direction = GetNorthSouthRunningPastFacingDirection(dx, dy, absdx, absdy);
+ }
+ return direction;
+}
+
+u8 GetNonWestRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ direction = GetRegularRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_WEST)
+ {
+ direction = GetNorthSouthRunningPastFacingDirection(dx, dy, absdx, absdy);
+ }
+ return direction;
+}
+
+u8 GetNonSouthRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ direction = GetRegularRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_SOUTH)
+ {
+ direction = GetEastWestRunningPastFacingDirection(dx, dy, absdx, absdy);
+ }
+ return direction;
+}
+
+u8 GetNonNorthRunningPastFacingDirection(s16 dx, s16 dy, s16 absdx, s16 absdy)
+{
+ u8 direction;
+
+ direction = GetRegularRunningPastFacingDirection(dx, dy, absdx, absdy);
+ if (direction == DIR_NORTH)
+ {
+ direction = GetEastWestRunningPastFacingDirection(dx, dy, absdx, absdy);
+ }
+ return direction;
+}
+
+u8 GetRunningPastFacingDirection(struct MapObject *mapObject, u8 movementType)
+{
+ s16 dx;
+ s16 dy;
+ s16 absdx;
+ s16 absdy;
+
+ if (!FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ return 0;
+ }
+ PlayerGetDestCoords(&dx, &dy);
+ dx -= mapObject->coords2.x;
+ dy -= mapObject->coords2.y;
+ absdx = dx;
+ absdy = dy;
+ if (absdx < 0)
+ {
+ absdx = -absdx;
+ }
+ if (absdy < 0)
+ {
+ absdy = -absdy;
+ }
+ return gUnknown_0850D714[movementType](dx, dy, absdx, absdy);
+}
+
+field_object_step(LookRandomDirections, gUnknown_0850D740)
+
+bool8 sub_808F988(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_808F99C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_808F9C8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6DC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_808FA0C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_808FA3C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[4];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D710, sizeof directions);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_ANY);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x03];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(RandomlyGoNorthOrSouth, gUnknown_0850D754)
+
+bool8 sub_808FAC8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_808FADC(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_808FB08(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (!FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ return FALSE;
+ }
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6DC[Random() & 0x03]);
+ sprite->data1 = 3;
+ return TRUE;
+}
+
+bool8 sub_808FB44(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_808FB64(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[2];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D770, sizeof directions);
+ direction = directions[Random() & 0x01];
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 5;
+ if (npc_block_way__next_tile(mapObject, direction))
+ {
+ sprite->data1 = 1;
+ }
+ return TRUE;
+}
+
+bool8 sub_808FBB0(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetGoSpeed0AnimId(mapObject->placeholder18));
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 6;
+ return TRUE;
+}
+
+bool8 sub_808FBE0(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 1;
+ }
+ return FALSE;
+}
+
+field_object_step(RandomlyGoEastOrWest, gUnknown_0850D774)
+
+bool8 sub_808FC4C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_808FC60(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_808FC8C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (!FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ return FALSE;
+ }
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6DC[Random() & 0x03]);
+ sprite->data1 = 3;
+ return TRUE;
+}
+
+bool8 sub_808FCC8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_808FCE8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[2];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D790, sizeof directions);
+ direction = directions[Random() & 0x01];
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 5;
+ if (npc_block_way__next_tile(mapObject, direction))
+ {
+ sprite->data1 = 1;
+ }
+ return TRUE;
+}
+
+bool8 sub_808FD34(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetGoSpeed0AnimId(mapObject->placeholder18));
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 6;
+ return TRUE;
+}
+
+bool8 sub_808FD64(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 1;
+ }
+ return FALSE;
+}
+
+field_object_step(FaceFixedDirection, gUnknown_0850D794)
+
+bool8 sub_808FDD0(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_808FDFC(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ sprite->data1 = 2;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_808FE1C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_1 = FALSE;
+ return FALSE;
+}
+
+static bool8 FieldObjectCB2_BerryTree(struct MapObject *mapObject, struct Sprite *sprite);
+extern bool8 (*const gUnknown_0850D7A0[])(struct MapObject *mapObject, struct Sprite *sprite);
+void FieldObjectCB_BerryTree(struct Sprite *sprite)
+{
+ struct MapObject *mapObject;
+
+ mapObject = &gMapObjects[sprite->data0];
+ if (!(sprite->data7 & 0x0001))
+ {
+ get_berry_tree_graphics(mapObject, sprite);
+ sprite->data7 |= 0x0001;
+ }
+ FieldObjectStep(mapObject, sprite, FieldObjectCB2_BerryTree);
+}
+static bool8 FieldObjectCB2_BerryTree(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ return gUnknown_0850D7A0[sprite->data1](mapObject, sprite);
+}
+
+bool8 do_berry_tree_growth_sparkle_1 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 berryStage;
+
+ npc_reset(mapObject, sprite);
+ mapObject->mapobj_bit_13 = TRUE;
+ sprite->invisible = TRUE;
+ berryStage = GetStageByBerryTreeId(mapObject->trainerRange_berryTreeId);
+ if (berryStage == 0)
+ {
+ if (!(sprite->data7 & 0x0004) && sprite->animNum == 4)
+ {
+ gFieldEffectSpawnParams[0] = mapObject->coords2.x;
+ gFieldEffectSpawnParams[1] = mapObject->coords2.y;
+ gFieldEffectSpawnParams[2] = sprite->subpriority - 1;
+ gFieldEffectSpawnParams[3] = sprite->oam.priority;
+ FieldEffectStart(FLDEFF_BERRY_TREE_GROWTH_SPARKLE);
+ sprite->animNum = berryStage;
+ }
+ return FALSE;
+ }
+ mapObject->mapobj_bit_13 = FALSE;
+ sprite->invisible = FALSE;
+ berryStage --;
+ if (sprite->animNum != berryStage)
+ {
+ sprite->data1 = 2;
+ return TRUE;
+ }
+ get_berry_tree_graphics(mapObject, sprite);
+ FieldObjectSetRegularAnim(mapObject, sprite, 0x39);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_808FF48 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ sprite->data1 = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 do_berry_tree_growth_sparkle_2 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 3;
+ sprite->data2 = 0;
+ sprite->data7 |= 0x0002;
+ gFieldEffectSpawnParams[0] = mapObject->coords2.x;
+ gFieldEffectSpawnParams[1] = mapObject->coords2.y;
+ gFieldEffectSpawnParams[2] = sprite->subpriority - 1;
+ gFieldEffectSpawnParams[3] = sprite->oam.priority;
+ FieldEffectStart(FLDEFF_BERRY_TREE_GROWTH_SPARKLE);
+ return TRUE;
+}
+
+bool8 sub_808FFB4 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sprite->data2 ++;
+ mapObject->mapobj_bit_13 = (sprite->data2 & 0x02) >> 1;
+ sprite->animPaused = TRUE;
+ if (sprite->data2 > 64)
+ {
+ get_berry_tree_graphics(mapObject, sprite);
+ sprite->data1 = 4;
+ sprite->data2 = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090004 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sprite->data2 ++;
+ mapObject->mapobj_bit_13 = (sprite->data2 & 0x02) >> 1;
+ sprite->animPaused = TRUE;
+ if (sprite->data2 > 64)
+ {
+ sprite->data1 = 0;
+ sprite->data7 &= ~0x0002;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+field_object_step(RandomlyLookNorthOrSouth, gUnknown_0850D7B4)
+
+bool8 sub_8090094 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_80900A8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_80900D4 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6DC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090118 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090148 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[2];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D770, sizeof gUnknown_0850D770);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_NORTH_SOUTH);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x01];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(RandomlyLookEastOrWest, gUnknown_0850D7C8)
+
+bool8 sub_80901D4 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_80901E8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8090214 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6DC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090258 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090288 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[2];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D790, sizeof gUnknown_0850D790);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_EAST_WEST);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x01];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(RandomlyLookNorthOrWest, gUnknown_0850D7DC)
+
+bool8 sub_8090314 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_8090328 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8090354 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6EC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090398 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_80903C8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[2];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D7F0, sizeof gUnknown_0850D7F0);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_NORTH_WEST);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x01];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(RandomlyLookNorthOrEast, gUnknown_0850D7F4)
+
+bool8 sub_8090454 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_8090468 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8090494 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6EC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_80904D8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090508 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[2];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D808, sizeof gUnknown_0850D808);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_NORTH_EAST);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x01];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(RandomlyLookSouthOrWest, gUnknown_0850D80C)
+
+bool8 sub_8090594 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_80905A8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_80905D4 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6EC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090618 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090648 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[2];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D820, sizeof gUnknown_0850D820);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_SOUTH_WEST);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x01];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(RandomlyLookSouthOrEast, gUnknown_0850D824)
+
+bool8 sub_80906D4 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_80906E8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8090714 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6EC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090758 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090788 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[2];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D838, sizeof gUnknown_0850D838);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_SOUTH_EAST);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x01];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(RandomlyLookNorthOrSouthOrWest, gUnknown_0850D83C)
+
+bool8 sub_8090814 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_8090828 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8090854 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6EC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090898 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_80908C8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[4];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D850, sizeof gUnknown_0850D850);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_NORTH_SOUTH_WEST);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x03];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(RandomlyLookNorthOrSouthOrEast, gUnknown_0850D854)
+
+bool8 sub_8090954 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_8090968 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8090994 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6EC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_80909D8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090A08 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[4];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D868, sizeof gUnknown_0850D868);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_NORTH_SOUTH_EAST);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x03];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(RandomlyLookNorthOrEastOrWest, gUnknown_0850D86C)
+
+bool8 sub_8090A94 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_8090AA8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8090AD4 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6EC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090B18 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090B48 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[4];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D880, sizeof gUnknown_0850D880);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_NORTH_EAST_WEST);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x03];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(RandomlyLookSouthOrEastOrWest, gUnknown_0850D884)
+
+bool8 sub_8090BD4 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_8090BE8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8090C14 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, gUnknown_0850D6EC[Random() & 0x03]);
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090C58 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 4;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090C88 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[4];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D898, sizeof gUnknown_0850D898);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_SOUTH_EAST_WEST);
+ if (direction == 0)
+ {
+ direction = directions[Random() & 0x03];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(LookAroundCounterclockwise, gUnknown_0850D89C)
+
+bool8 sub_8090D14 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_8090D40 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, 48);
+ sprite->data1 = 2;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090D64 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090D90 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[5];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D8AC, sizeof gUnknown_0850D8AC);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_ANY);
+ if (direction == 0)
+ {
+ direction = directions[mapObject->mapobj_unk_18];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 0;
+ return TRUE;
+}
+
+field_object_step(LookAroundClockwise, gUnknown_0850D8B4)
+
+bool8 sub_8090E18 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_8090E44 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ SetFieldObjectStepTimer(sprite, 48);
+ sprite->data1 = 2;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090E68 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (RunFieldObjectStepTimer(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject))
+ {
+ sprite->data1 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8090E94 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 directions[5];
+ u8 direction;
+
+ memcpy(directions, gUnknown_0850D8C4, sizeof gUnknown_0850D8C4);
+ direction = GetRunningPastFacingDirection(mapObject, RUNFOLLOW_ANY);
+ if (direction == 0)
+ {
+ direction = directions[mapObject->mapobj_unk_18];
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 0;
+ return TRUE;
+}
+
+field_object_step(AlternatelyGoInOppositeDirections, gUnknown_0850D8CC)
+
+bool8 sub_8090F1C (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_8090F30 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 direction;
+
+ direction = gUnknown_085055CD[mapObject->animPattern];
+ if (mapObject->mapobj_unk_21)
+ {
+ direction = GetOppositeDirection(direction);
+ }
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8090F68 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ bool8 blockingWay;
+ u8 animId;
+
+ if (mapObject->mapobj_unk_21 && mapObject->coords1.x == mapObject->coords2.x && mapObject->coords1.y == mapObject->coords2.y)
+ {
+ mapObject->mapobj_unk_21 = 0;
+ FieldObjectSetDirection(mapObject, GetOppositeDirection(mapObject->placeholder18));
+ }
+ blockingWay = npc_block_way__next_tile(mapObject, mapObject->placeholder18);
+ animId = GetGoSpeed0AnimId(mapObject->placeholder18);
+ if (blockingWay == TRUE)
+ {
+ mapObject->mapobj_unk_21 ++;
+ FieldObjectSetDirection(mapObject, GetOppositeDirection(mapObject->placeholder18));
+ animId = GetGoSpeed0AnimId(mapObject->placeholder18);
+ blockingWay = npc_block_way__next_tile(mapObject, mapObject->placeholder18);
+ }
+ if (blockingWay)
+ {
+ animId = GetStepInPlaceDelay16AnimId(mapObject->mapobj_unk_18);
+ }
+ FieldObjectSetRegularAnim(mapObject, sprite, animId);
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 3;
+ return TRUE;
+}
+
+bool8 sub_8091020 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 1;
+ }
+ return FALSE;
+}
+
+bool8 sub_8091048(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 MoveFieldObjectInNextDirectionInSequence(struct MapObject *mapObject, struct Sprite *sprite, u8 *route)
+{
+ u8 blockingWay;
+ u8 animId;
+
+ if (mapObject->mapobj_unk_21 == 3 && mapObject->coords1.x == mapObject->coords2.x && mapObject->coords1.y == mapObject->coords2.y)
+ {
+ mapObject->mapobj_unk_21 = 0;
+ }
+ FieldObjectSetDirection(mapObject, route[mapObject->mapobj_unk_21]);
+ animId = GetGoSpeed0AnimId(mapObject->placeholder18);
+ blockingWay = npc_block_way__next_tile(mapObject, mapObject->placeholder18);
+ if (blockingWay == TRUE)
+ {
+ mapObject->mapobj_unk_21 ++;
+ FieldObjectSetDirection(mapObject, route[mapObject->mapobj_unk_21]);
+ animId = GetGoSpeed0AnimId(mapObject->placeholder18);
+ blockingWay = npc_block_way__next_tile(mapObject, mapObject->placeholder18);
+ }
+ if (blockingWay)
+ {
+ animId = GetStepInPlaceDelay16AnimId(mapObject->mapobj_unk_18);
+ }
+ FieldObjectSetRegularAnim(mapObject, sprite, animId);
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8091110(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 1;
+ }
+ return FALSE;
+}
+
+field_object_path( 1, gUnknown_0850D8DC, sub_809117C, gUnknown_0850D8E8, 2, x)
+field_object_path( 2, gUnknown_0850D8EC, sub_8091208, gUnknown_0850D8F8, 1, x)
+field_object_path( 3, gUnknown_0850D8FC, sub_8091294, gUnknown_0850D908, 1, y)
+field_object_path( 4, gUnknown_0850D90C, sub_8091320, gUnknown_0850D918, 2, y)
+field_object_path( 5, gUnknown_0850D91C, sub_80913AC, gUnknown_0850D928, 2, x)
+field_object_path( 6, gUnknown_0850D92C, sub_8091438, gUnknown_0850D938, 1, x)
+field_object_path( 7, gUnknown_0850D93C, sub_80914C4, gUnknown_0850D710, 1, y)
+field_object_path( 8, gUnknown_0850D948, sub_8091550, gUnknown_0850D954, 2, y)
+field_object_path( 9, gUnknown_0850D958, sub_80915DC, gUnknown_0850D964, 2, y)
+field_object_path(10, gUnknown_0850D968, sub_8091668, gUnknown_0850D974, 1, y)
+field_object_path(11, gUnknown_0850D978, sub_80916F4, gUnknown_0850D984, 1, x)
+field_object_path(12, gUnknown_0850D988, sub_8091780, gUnknown_0850D994, 2, x)
+field_object_path(13, gUnknown_0850D998, sub_809180C, gUnknown_0850D9A4, 2, y)
+field_object_path(14, gUnknown_0850D9A8, sub_8091898, gUnknown_0850D9B4, 1, y)
+field_object_path(15, gUnknown_0850D9B8, sub_8091924, gUnknown_0850D9C4, 1, x)
+field_object_path(16, gUnknown_0850D9C8, sub_80919B0, gUnknown_0850D9D4, 2, x)
+field_object_path(17, gUnknown_0850D9D8, sub_8091A3C, gUnknown_0850D9E4, 2, y)
+field_object_path(18, gUnknown_0850D9E8, sub_8091AC8, gUnknown_0850D9F4, 2, y)
+field_object_path(19, gUnknown_0850D9F8, sub_8091B54, gUnknown_0850DA04, 2, x)
+field_object_path(20, gUnknown_0850DA08, sub_8091BE0, gUnknown_0850DA14, 2, x)
+field_object_path(21, gUnknown_0850DA18, sub_8091C6C, gUnknown_0850DA24, 2, y)
+field_object_path(22, gUnknown_0850DA28, sub_8091CF8, gUnknown_0850DA34, 2, y)
+field_object_path(23, gUnknown_0850DA38, sub_8091D84, gUnknown_0850DA44, 2, x)
+field_object_path(24, gUnknown_0850DA48, sub_8091E10, gUnknown_0850DA54, 2, x)
+
+field_object_step(CopyPlayer1, gUnknown_0850DA58)
+
+bool8 mss_npc_reset_oampriv3_1_unk2_unk3(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ if (mapObject->mapobj_unk_21 == 0)
+ {
+ mapObject->mapobj_unk_21 = player_get_direction_lower_nybble();
+ }
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+bool8 sub_8091EC0(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1C == 0xFF || gPlayerAvatar.running1 == 2)
+ {
+ return FALSE;
+ }
+ return gUnknown_0850DA64[player_get_x22()](mapObject, sprite, player_get_direction_upper_nybble(), NULL);
+}
+
+bool8 sub_8091F20(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ mapObject->mapobj_bit_1 = FALSE;
+ sprite->data1 = 1;
+ }
+ return FALSE;
+}
+
+bool8 sub_8091F48(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8))
+{
+ return FALSE;
+}
+
+bool8 sub_8091F4C(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8))
+{
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(state_to_direction(gUnknown_085055CD[mapObject->animPattern], mapObject->mapobj_unk_21, playerDirection)));
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8091F94(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8))
+{
+ u32 direction;
+ s16 x;
+ s16 y;
+
+ direction = playerDirection;
+ if (FieldObjectIsFarawayIslandMew(mapObject))
+ {
+ direction = sub_81D427C();
+ if (direction == 0)
+ {
+ direction = playerDirection;
+ direction = state_to_direction(gUnknown_085055CD[mapObject->animPattern], mapObject->mapobj_unk_21, direction);
+ FieldObjectMoveDestCoords(mapObject, direction, &x, &y);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction));
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 2;
+ return TRUE;
+ }
+ }
+ else
+ {
+ direction = state_to_direction(gUnknown_085055CD[mapObject->animPattern], mapObject->mapobj_unk_21, direction);
+ }
+ FieldObjectMoveDestCoords(mapObject, direction, &x, &y);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetGoSpeed0AnimId(direction));
+ if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y))))
+ {
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction));
+ }
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_80920A4(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8))
+{
+ u32 direction;
+ s16 x;
+ s16 y;
+
+ direction = playerDirection;
+ direction = state_to_direction(gUnknown_085055CD[mapObject->animPattern], mapObject->mapobj_unk_21, direction);
+ FieldObjectMoveDestCoords(mapObject, direction, &x, &y);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetGoSpeed1AnimId(direction));
+ if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y))))
+ {
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction));
+ }
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_809215C(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8))
+{
+ u32 direction;
+ s16 x;
+ s16 y;
+
+ direction = playerDirection;
+ direction = state_to_direction(gUnknown_085055CD[mapObject->animPattern], mapObject->mapobj_unk_21, direction);
+ FieldObjectMoveDestCoords(mapObject, direction, &x, &y);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetGoSpeed3AnimId(direction));
+ if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y))))
+ {
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction));
+ }
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8092214(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8))
+{
+ u32 direction;
+ s16 x;
+ s16 y;
+
+ direction = playerDirection;
+ direction = state_to_direction(gUnknown_085055CD[mapObject->animPattern], mapObject->mapobj_unk_21, direction);
+ FieldObjectMoveDestCoords(mapObject, direction, &x, &y);
+ FieldObjectSetRegularAnim(mapObject, sprite, sub_8093438(direction));
+ if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y))))
+ {
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction));
+ }
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 cph_IM_DIFFERENT(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8))
+{
+ u32 direction;
+
+ direction = playerDirection;
+ direction = state_to_direction(gUnknown_085055CD[mapObject->animPattern], mapObject->mapobj_unk_21, direction);
+ FieldObjectSetRegularAnim(mapObject, sprite, sub_80934BC(direction));
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 sub_8092314(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8))
+{
+ u32 direction;
+ s16 x;
+ s16 y;
+
+ direction = playerDirection;
+ direction = state_to_direction(gUnknown_085055CD[mapObject->animPattern], mapObject->mapobj_unk_21, direction);
+ FieldObjectMoveDestCoords(mapObject, direction, &x, &y);
+ FieldObjectSetRegularAnim(mapObject, sprite, sub_8093514(direction));
+ if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y))))
+ {
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction));
+ }
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+bool8 oac_hopping(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8))
+{
+ u32 direction;
+ s16 x;
+ s16 y;
+
+ direction = playerDirection;
+ direction = state_to_direction(gUnknown_085055CD[mapObject->animPattern], mapObject->mapobj_unk_21, direction);
+ x = mapObject->coords2.x;
+ y = mapObject->coords2.y;
+ sub_8092F88(direction, &x, &y, 2, 2);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetJumpLedgeAnimId(direction));
+ if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y))))
+ {
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction));
+ }
+ mapObject->mapobj_bit_1 = TRUE;
+ sprite->data1 = 2;
+ return TRUE;
+}
+
+field_object_step(CopyPlayer2, gUnknown_0850DA90)
+
+bool8 mss_08062EA4(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1C == 0xFF || gPlayerAvatar.running1 == 2)
+ {
+ return FALSE;
+ }
+ return gUnknown_0850DA64[player_get_x22()](mapObject, sprite, player_get_direction_upper_nybble(), MetatileBehavior_IsPokeGrass);
+}
+
+bool8 sub_80925AC(struct MapObject *, struct Sprite *);
+
+void FieldObjectCB_TreeDisguise(struct Sprite *sprite)
+{
+ struct MapObject *mapObject;
+
+ mapObject = &gMapObjects[sprite->data0];
+ if (mapObject->mapobj_unk_21 == 0 || (mapObject->mapobj_unk_21 == 1 && !sprite->data7))
+ {
+ FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectSpawnParams[0], (u8 *)&gFieldEffectSpawnParams[1], (u8 *)&gFieldEffectSpawnParams[2]);
+ mapObject->mapobj_unk_1A = FieldEffectStart(FLDEFF_TREE_DISGUISE);
+ mapObject->mapobj_unk_21 = 1;
+ sprite->data7 ++;
+ }
+ FieldObjectStep(&gMapObjects[sprite->data0], sprite, sub_80925AC);
+}
+
+bool8 sub_80925AC(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ return FALSE;
+}
+
+void FieldObjectCB_MountainDisguise(struct Sprite *sprite)
+{
+ struct MapObject *mapObject;
+
+ mapObject = &gMapObjects[sprite->data0];
+ if (mapObject->mapobj_unk_21 == 0 || (mapObject->mapobj_unk_21 == 1 && !sprite->data7))
+ {
+ FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectSpawnParams[0], (u8 *)&gFieldEffectSpawnParams[1], (u8 *)&gFieldEffectSpawnParams[2]);
+ mapObject->mapobj_unk_1A = FieldEffectStart(FLDEFF_MOUNTAIN_DISGUISE);
+ mapObject->mapobj_unk_21 = 1;
+ sprite->data7 ++;
+ }
+ FieldObjectStep(&gMapObjects[sprite->data0], sprite, sub_80925AC);
+}
+
+extern bool8 (*const gUnknown_0850DA9C[])(struct MapObject *, struct Sprite *);
+bool8 sub_809268C(struct MapObject *, struct Sprite *);
+
+void FieldObjectCB_Hidden1(struct Sprite *sprite)
+{
+ if (!sprite->data7)
+ {
+ gMapObjects[sprite->data0].mapobj_bit_26 = TRUE;
+ sprite->subspriteMode = 2;
+ sprite->oam.priority = 3;
+ sprite->data7 ++;
+ }
+ FieldObjectStep(&gMapObjects[sprite->data0], sprite, sub_809268C);
+}
+
+bool8 sub_809268C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ return gUnknown_0850DA9C[sprite->data1](mapObject, sprite);
+}
+
+bool8 sub_80926AC (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ return FALSE;
+}
+bool8 sub_80926B8 (struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ sprite->data1 = 0;
+ }
+ return FALSE;
+}
+
+field_object_step(WalkInPlace1, gUnknown_0850DAA0)
+
+bool8 sub_8092718(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetStepInPlaceDelay16AnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(WalkInPlace4, gUnknown_0850DAA8)
+
+bool8 sub_8092788(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetStepInPlaceDelay32AnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(WalkInPlace2, gUnknown_0850DAB0)
+
+bool8 sub_80927F8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetStepInPlaceDelay8AnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(WalkInPlace3, gUnknown_0850DAB8)
+
+bool8 sub_8092868(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetStepInPlaceDelay4AnimId(mapObject->mapobj_unk_18));
+ sprite->data1 = 1;
+ return TRUE;
+}
+
+field_object_step(Hidden2, gUnknown_0850DAC0)
+
+bool8 sub_80928D8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_reset(mapObject, sprite);
+ FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18));
+ mapObject->mapobj_bit_13 = TRUE;
+ sprite->data1 = 1;
+ return TRUE;
+}
+bool8 sub_809290C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (FieldObjectExecRegularAnim(mapObject, sprite))
+ {
+ sprite->data1 = 2;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_809292C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_1 = FALSE;
+ return FALSE;
+}
+
+void npc_reset(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_1 = FALSE;
+ mapObject->mapobj_bit_6 = FALSE;
+ mapObject->mapobj_bit_7 = FALSE;
+ mapObject->mapobj_unk_1C = 0xFF;
+ sprite->data1 = 0;
+}
+
+#define dirn2anim(name, table)\
+extern const u8 table[4];\
+u8 name(u8 direction)\
+{\
+ return table[direction];\
+}
+
+dirn2anim(FieldObjectDirectionToImageAnimId, gUnknown_0850DACC)
+dirn2anim(get_go_image_anim_num, gUnknown_0850DAD5)
+dirn2anim(get_go_fast_image_anim_num, gUnknown_0850DADE)
+dirn2anim(get_go_faster_image_anim_num, gUnknown_0850DAE7)
+dirn2anim(get_go_fastest_image_anim_num, gUnknown_0850DAF0)
+dirn2anim(sub_80929AC, gUnknown_0850DAF9)
+dirn2anim(sub_80929BC, gUnknown_0850DB02)
+dirn2anim(sub_80929CC, gUnknown_0850DB0B)
+dirn2anim(sub_80929DC, gUnknown_0850DB14)
+dirn2anim(sub_80929EC, gUnknown_0850DB1D)
+dirn2anim(sub_80929FC, gUnknown_0850DB26)
+dirn2anim(sub_8092A0C, gUnknown_0850DB2F)
+dirn2anim(sub_8092A1C, gUnknown_0850DB38)
+dirn2anim(sub_8092A2C, gUnknown_0850DB41)
+dirn2anim(get_run_image_anim_num, gUnknown_0850DB4A)
+
+// file boundary?
+
+struct UnkStruct_085094AC {
+ const union AnimCmd *const *anims;
+ u8 animPos[4];
+};
+
+extern const struct UnkStruct_085094AC gUnknown_085094AC[];
+
+static const struct UnkStruct_085094AC *sub_8092A4C(const union AnimCmd *const *anims)
+{
+ const struct UnkStruct_085094AC *retval;
+
+ for (retval = gUnknown_085094AC; retval->anims != NULL; retval ++)
+ {
+ if (retval->anims == anims)
+ {
+ return retval;
+ }
+ }
+ return NULL;
+}
+
+void npc_apply_anim_looping(struct MapObject *mapObject, struct Sprite *sprite, u8 animNum)
+{
+ const struct UnkStruct_085094AC *unk85094AC;
+
+ if (!mapObject->mapobj_bit_12)
+ {
+ sprite->animNum = animNum;
+ unk85094AC = sub_8092A4C(sprite->anims);
+ if (unk85094AC != NULL)
+ {
+ if (sprite->animCmdIndex == unk85094AC->animPos[0])
+ {
+ sprite->animCmdIndex = unk85094AC->animPos[3];
+ }
+ else if (sprite->animCmdIndex == unk85094AC->animPos[1])
+ {
+ sprite->animCmdIndex = unk85094AC->animPos[2];
+ }
+ }
+ SeekSpriteAnim(sprite, sprite->animCmdIndex);
+ }
+}
+
+void obj_npc_animation_step(struct MapObject *mapObject, struct Sprite *sprite, u8 animNum)
+{
+ const struct UnkStruct_085094AC *unk85094AC;
+
+ if (!mapObject->mapobj_bit_12)
+ {
+ u8 animPos;
+
+ sprite->animNum = animNum;
+ unk85094AC = sub_8092A4C(sprite->anims);
+ if (unk85094AC != NULL)
+ {
+ animPos = unk85094AC->animPos[1];
+ if (sprite->animCmdIndex <= unk85094AC->animPos[0])
+ {
+ animPos = unk85094AC->animPos[0];
+ }
+ SeekSpriteAnim(sprite, animPos);
+ }
+ }
+}
+
+// file boundary?
+
+u8 sub_8092AF8(s16 x1, s16 y1, s16 x2, s16 y2)
+{
+ if (x1 > x2)
+ {
+ return DIR_WEST;
+ }
+ if (x1 < x2)
+ {
+ return DIR_EAST;
+ }
+ if (y1 > y2)
+ {
+ return DIR_NORTH;
+ }
+ return DIR_SOUTH;
+}
+
+void npc_set_running_behaviour_etc(struct MapObject *mapObject, u8 animPattern)
+{
+ mapObject->animPattern = animPattern;
+ mapObject->mapobj_unk_21 = 0;
+ mapObject->animId = 0;
+ gSprites[mapObject->spriteId].callback = gUnknown_08505438[animPattern];
+ gSprites[mapObject->spriteId].data1 = 0;
+}
+
+dirn2anim(npc_running_behaviour_by_direction, gUnknown_0850DB53)
+
+u8 npc_block_way__next_tile(struct MapObject *mapObject, u8 direction)
+{
+ s16 x;
+ s16 y;
+
+ x = mapObject->coords2.x;
+ y = mapObject->coords2.y;
+ MoveCoords(direction, &x, &y);
+ return npc_block_way(mapObject, x, y, direction);
+}
+
+u8 npc_block_way(struct MapObject *mapObject, s16 x, s16 y, u32 dirn)
+{
+ u8 direction;
+
+ direction = dirn;
+ if (IsCoordOutsideFieldObjectMovementRect(mapObject, x, y))
+ {
+ return 1;
+ }
+ if (MapGridIsImpassableAt(x, y) || GetMapBorderIdAt(x, y) == -1 || IsMetatileDirectionallyImpassable(mapObject, x, y, direction))
+ {
+ return 2;
+ }
+ if (mapObject->mapobj_bit_15 && !CanCameraMoveInDirection(direction))
+ {
+ return 2;
+ }
+ if (IsZCoordMismatchAt(mapObject->mapobj_unk_0B_0, x, y))
+ {
+ return 3;
+ }
+ if (CheckForCollisionBetweenFieldObjects(mapObject, x, y))
+ {
+ return 4;
+ }
+ return 0;
+}
+
+u8 sub_8092C8C(struct MapObject *mapObject, s16 x, s16 y, u8 direction)
+{
+ u8 retval;
+
+ retval = 0x00;
+ if (IsCoordOutsideFieldObjectMovementRect(mapObject, x, y))
+ {
+ retval |= 1;
+ }
+ if (MapGridIsImpassableAt(x, y) || GetMapBorderIdAt(x, y) == -1 || IsMetatileDirectionallyImpassable(mapObject, x, y, direction) || (mapObject->mapobj_bit_15 && !CanCameraMoveInDirection(direction)))
+ {
+ retval |= 2;
+ }
+ if (IsZCoordMismatchAt(mapObject->mapobj_unk_0B_0, x, y))
+ {
+ retval |= 4;
+ }
+ if (CheckForCollisionBetweenFieldObjects(mapObject, x, y))
+ {
+ retval |= 8;
+ }
+ return retval;
+}
+
+static bool8 IsCoordOutsideFieldObjectMovementRect(struct MapObject *mapObject, s16 x, s16 y)
+{
+ s16 left;
+ s16 right;
+ s16 top;
+ s16 bottom;
+
+ if (mapObject->range.as_nybbles.x != 0)
+ {
+ left = mapObject->coords1.x - mapObject->range.as_nybbles.x;
+ right = mapObject->coords1.x + mapObject->range.as_nybbles.x;
+ if (left > x || right < x)
+ {
+ return TRUE;
+ }
+ }
+ if (mapObject->range.as_nybbles.y != 0)
+ {
+ top = mapObject->coords1.y - mapObject->range.as_nybbles.y;
+ bottom = mapObject->coords1.y + mapObject->range.as_nybbles.y;
+ if (top > y || bottom < y)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static bool8 IsMetatileDirectionallyImpassable(struct MapObject *mapObject, s16 x, s16 y, u8 direction)
+{
+ if (gUnknown_0850DB5C[direction - 1](mapObject->mapobj_unk_1E) || gUnknown_0850DB6C[direction - 1](MapGridGetMetatileBehaviorAt(x, y)))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static bool8 CheckForCollisionBetweenFieldObjects(struct MapObject *mapObject, s16 x, s16 y)
+{
+ u8 i;
+ struct MapObject *curObject;
+
+ for (i = 0; i < NUM_FIELD_OBJECTS; i ++)
+ {
+ curObject = &gMapObjects[i];
+ if (curObject->active && curObject != mapObject)
+ {
+ if ((curObject->coords2.x == x && curObject->coords2.y == y) || (curObject->coords3.x == x && curObject->coords3.y == y))
+ {
+ if (AreZCoordsCompatible(mapObject->mapobj_unk_0B_0, curObject->mapobj_unk_0B_0))
+ {
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+bool8 sub_8092E9C(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ u8 mapObjectId;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId) && gSprites[gMapObjects[mapObjectId].spriteId].data7 & 0x02)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void sub_8092EF0(u8 localId, u8 mapNum, u8 mapGroup)
+{
+ u8 mapObjectId;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId))
+ {
+ gSprites[gMapObjects[mapObjectId].spriteId].data7 |= 0x04;
+ }
+}
+
+void MoveCoords(u8 direction, s16 *x, s16 *y)
+{
+ *x += gUnknown_0850DB7C[direction].x;
+ *y += gUnknown_0850DB7C[direction].y;
+}
+
+void sub_8092F60(u8 direction, s16 *x, s16 *y)
+{
+ *x += gUnknown_0850DB7C[direction].x << 4;
+ *y += gUnknown_0850DB7C[direction].y << 4;
+}
+
+void sub_8092F88(u32 dirn, s16 *x, s16 *y, s16 dx, s16 dy)
+{
+ u8 direction;
+ s16 dx_2;
+ s16 dy_2;
+ s16 cur_x;
+ s16 cur_y;
+
+ direction = dirn;
+ dx_2 = dx;
+ dy_2 = dy;
+ cur_x = gUnknown_0850DB7C[direction].x;
+ if (cur_x > 0)
+ {
+ *x += dx_2;
+ }
+ if (cur_x < 0)
+ {
+ *x -= dx_2;
+ }
+ cur_y = gUnknown_0850DB7C[direction].y;
+ if (cur_y > 0)
+ {
+ *y += dy_2;
+ }
+ if (cur_y < 0)
+ {
+ *y -= dy_2;
+ }
+}
+
+void sub_8092FF0(s16 x, s16 y, s16 *dest_x, s16 *dest_y)
+{
+ *dest_x = (x - gSaveBlock1Ptr->pos.x) << 4;
+ *dest_y = (y - gSaveBlock1Ptr->pos.y) << 4;
+ *dest_x -= gUnknown_03005DEC;
+ *dest_y -= gUnknown_03005DE8;
+}
+
+void sub_8093038(s16 x, s16 y, s16 *dest_x, s16 *dest_y)
+{
+ s16 dx;
+ s16 dy;
+
+ dx = -gUnknown_03005DEC - gUnknown_03005DD0.x;
+ dy = -gUnknown_03005DE8 - gUnknown_03005DD0.y;
+ if (gUnknown_03005DD0.x > 0)
+ {
+ dx += 0x10;
+ }
+ if (gUnknown_03005DD0.x < 0)
+ {
+ dx -= 0x10;
+ }
+ if (gUnknown_03005DD0.y > 0)
+ {
+ dy += 0x10;
+ }
+ if (gUnknown_03005DD0.y < 0)
+ {
+ dy -= 0x10;
+ }
+ *dest_x = ((x - gSaveBlock1Ptr->pos.x) << 4) + dx;
+ *dest_y = ((y - gSaveBlock1Ptr->pos.y) << 4) + dy;
+}
+
+void sub_80930E0(s16 *x, s16 *y, s16 dx, s16 dy)
+{
+ sub_8093038(*x, *y, x, y);
+ *x += dx;
+ *y += dy;
+}
+
+void GetFieldObjectMovingCameraOffset(s16 *x, s16 *y)
+{
+ *x = 0;
+ *y = 0;
+ if (gUnknown_03005DD0.x > 0)
+ {
+ (*x) ++;
+ }
+ if (gUnknown_03005DD0.x < 0)
+ {
+ (*x) --;
+ }
+ if (gUnknown_03005DD0.y > 0)
+ {
+ (*y) ++;
+ }
+ if (gUnknown_03005DD0.y < 0)
+ {
+ (*y) --;
+ }
+}
+
+void FieldObjectMoveDestCoords(struct MapObject *mapObject, u32 dirn, s16 *x, s16 *y)
+{
+ u8 direction;
+
+ direction = dirn;
+ *x = mapObject->coords2.x;
+ *y = mapObject->coords2.y;
+ MoveCoords(direction, x, y);
+}
+
+// file boundary?
+
+bool8 FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(struct MapObject *mapObject)
+{
+ if (mapObject->mapobj_bit_1 || mapObject->mapobj_bit_6)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 FieldObjectIsSpecialAnimActive(struct MapObject *mapObject)
+{
+ if (mapObject->mapobj_bit_6 && mapObject->mapobj_unk_1C != 0xFF)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 FieldObjectSetSpecialAnim(struct MapObject *mapObject, u8 specialAnimId)
+{
+ if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject))
+ {
+ return TRUE;
+ }
+ npc_sync_anim_pause_bits(mapObject);
+ mapObject->mapobj_unk_1C = specialAnimId;
+ mapObject->mapobj_bit_6 = TRUE;
+ mapObject->mapobj_bit_7 = FALSE;
+ gSprites[mapObject->spriteId].data2 = 0;
+ return FALSE;
+}
+
+void FieldObjectForceSetSpecialAnim(struct MapObject *mapObject, u8 specialAnimId)
+{
+ FieldObjectClearAnimIfSpecialAnimActive(mapObject);
+ FieldObjectSetSpecialAnim(mapObject, specialAnimId);
+}
+
+void FieldObjectClearAnimIfSpecialAnimActive(struct MapObject *mapObject)
+{
+ if (mapObject->mapobj_bit_6)
+ {
+ FieldObjectClearAnim(mapObject);
+ }
+}
+
+void FieldObjectClearAnim(struct MapObject *mapObject)
+{
+ mapObject->mapobj_unk_1C = 0xFF;
+ mapObject->mapobj_bit_6 = FALSE;
+ mapObject->mapobj_bit_7 = FALSE;
+ gSprites[mapObject->spriteId].data1 = 0;
+ gSprites[mapObject->spriteId].data2 = 0;
+}
+
+u8 FieldObjectCheckIfSpecialAnimFinishedOrInactive(struct MapObject *mapObject)
+{
+ if (mapObject->mapobj_bit_6)
+ {
+ return mapObject->mapobj_bit_7;
+ }
+ return 0x10;
+}
+
+u8 FieldObjectClearAnimIfSpecialAnimFinished(struct MapObject *mapObject)
+{
+ u8 specialAnimState;
+
+ specialAnimState = FieldObjectCheckIfSpecialAnimFinishedOrInactive(mapObject);
+ if (specialAnimState != 0 && specialAnimState != 16)
+ {
+ FieldObjectClearAnimIfSpecialAnimActive(mapObject);
+ }
+ return specialAnimState;
+}
+
+u8 FieldObjectGetSpecialAnim(struct MapObject *mapObject)
+{
+ if (mapObject->mapobj_bit_6)
+ {
+ return mapObject->mapobj_unk_1C;
+ }
+ return 0xFF;
+}
+
+void FieldObjectStep(struct MapObject *mapObject, struct Sprite *sprite, bool8 (*callback)(struct MapObject *, struct Sprite *))
+{
+ DoGroundEffects_OnSpawn(mapObject, sprite);
+ sub_80964E8(mapObject, sprite);
+ if (FieldObjectIsSpecialAnimActive(mapObject))
+ {
+ FieldObjectExecSpecialAnim(mapObject, sprite);
+ }
+ else if (!mapObject->mapobj_bit_8)
+ {
+ while (callback(mapObject, sprite));
+ }
+ DoGroundEffects_OnBeginStep(mapObject, sprite);
+ DoGroundEffects_OnFinishStep(mapObject, sprite);
+ npc_obj_transfer_image_anim_pause_flag(mapObject, sprite);
+ sub_8096518(mapObject, sprite);
+ FieldObjectUpdateSubpriority(mapObject, sprite);
+}
+
+#define dirn2anim_2(name, table) \
+extern const u8 table[5]; \
+u8 name(u32 direction) \
+{ \
+ u8 dirn2; \
+ u8 animIds[5]; \
+ dirn2 = direction; \
+ memcpy(animIds, table, 5); \
+ if (dirn2 > DIR_EAST) \
+ { \
+ dirn2 = 0; \
+ } \
+ return animIds[dirn2]; \
+}
+
+dirn2anim_2(GetFaceDirectionAnimId, gUnknown_0850DBA0);
+dirn2anim_2(GetSimpleGoAnimId, gUnknown_0850DBA5);
+dirn2anim_2(GetGoSpeed0AnimId, gUnknown_0850DBAA);
+dirn2anim_2(GetGoSpeed1AnimId, gUnknown_0850DBAF);
+dirn2anim_2(GetGoSpeed2AnimId, gUnknown_0850DBB4);
+dirn2anim_2(GetGoSpeed3AnimId, gUnknown_0850DBB9);
+dirn2anim_2(sub_8093438, gUnknown_0850DBBE);
+dirn2anim_2(GetRunAnimId, gUnknown_0850DBC3);
+dirn2anim_2(GetJumpLedgeAnimId, gUnknown_0850DBC8);
+dirn2anim_2(sub_80934BC, gUnknown_0850DBCD);
+dirn2anim_2(sub_80934E8, gUnknown_0850DBD2);
+dirn2anim_2(sub_8093514, gUnknown_0850DBD7);
+dirn2anim_2(sub_8093540, gUnknown_0850DBDC);
+dirn2anim_2(GetStepInPlaceDelay32AnimId, gUnknown_0850DBE1);
+dirn2anim_2(GetStepInPlaceDelay16AnimId, gUnknown_0850DBE6);
+dirn2anim_2(GetStepInPlaceDelay8AnimId, gUnknown_0850DBEB);
+dirn2anim_2(GetStepInPlaceDelay4AnimId, gUnknown_0850DBF0);
+
+bool8 FieldObjectFaceOppositeDirection(struct MapObject *mapObject, u8 direction)
+{
+ return FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(GetOppositeDirection(direction)));
+}
+
+dirn2anim_2(sub_8093648, gUnknown_0850DBF5);
+dirn2anim_2(sub_8093674, gUnknown_0850DBFA);
+dirn2anim_2(sub_80936A0, gUnknown_0850DBFF);
+dirn2anim_2(sub_80936CC, gUnknown_0850DC04);
+dirn2anim_2(sub_80936F8, gUnknown_0850DC09);
+dirn2anim_2(sub_8093724, gUnknown_0850DC0E);
+dirn2anim_2(sub_8093750, gUnknown_0850DC13);
+dirn2anim_2(sub_809377C, gUnknown_0850DC18);
+dirn2anim_2(sub_80937A8, gUnknown_0850DC1D);
+dirn2anim_2(d2s_08064034, gUnknown_0850DC22);
+
+extern const u8 gUnknown_0850DC27[8];
+
+u8 GetOppositeDirection(u8 direction)
+{
+ u8 directions[sizeof gUnknown_0850DC27];
+
+ memcpy(directions, gUnknown_0850DC27, sizeof gUnknown_0850DC27);
+ if (direction < 1 || direction > (sizeof gUnknown_0850DC27))
+ {
+ return direction;
+ }
+ return directions[direction - 1];
+}
+
+static u32 zffu_offset_calc(u8 a0, u8 a1)
+{
+ return gUnknown_0850DC2F[a0 - 1][a1 - 1];
+}
+
+static u32 state_to_direction(u8 a0, u32 a1, u32 a2)
+{
+ u32 zffuOffset;
+ u8 a1_2;
+ u8 a2_2;
+
+ a1_2 = a1;
+ a2_2 = a2;
+ if (a1_2 == 0 || a2_2 == 0 || a1_2 > DIR_EAST || a2_2 > DIR_EAST)
+ {
+ return 0;
+ }
+ zffuOffset = zffu_offset_calc(a1_2, a2);
+ return gUnknown_0850DC3F[a0 - 1][zffuOffset - 1];
+}
+
+static void FieldObjectExecSpecialAnim(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (gUnknown_0850DC50[mapObject->mapobj_unk_1C][sprite->data2](mapObject, sprite))
+ {
+ mapObject->mapobj_bit_7 = TRUE;
+ }
+}
+
+bool8 FieldObjectExecRegularAnim(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (gUnknown_0850DC50[mapObject->mapobj_unk_1C][sprite->data2](mapObject, sprite))
+ {
+ mapObject->mapobj_unk_1C = 0xFF;
+ sprite->data2 = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void FieldObjectSetRegularAnim(struct MapObject *mapObject, struct Sprite *sprite, u8 animId)
+{
+ mapObject->mapobj_unk_1C = animId;
+ sprite->data2 = 0;
+}
+
+// file boundary?
+
+void an_look_any(struct MapObject *mapObject, struct Sprite *sprite, u8 direction)
+{
+ FieldObjectSetDirection(mapObject, direction);
+ npc_coords_shift_still(mapObject);
+ obj_npc_animation_step(mapObject, sprite, get_go_image_anim_num(mapObject->mapobj_unk_18));
+ sprite->animPaused = TRUE;
+ sprite->data2 = 1;
+}
+
+bool8 sub_8093950(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ an_look_any(mapObject, sprite, DIR_SOUTH);
+ return TRUE;
+}
+
+bool8 sub_8093960(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ an_look_any(mapObject, sprite, DIR_NORTH);
+ return TRUE;
+}
+
+bool8 sub_8093970(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ an_look_any(mapObject, sprite, DIR_WEST);
+ return TRUE;
+}
+
+bool8 sub_8093980(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ an_look_any(mapObject, sprite, DIR_EAST);
+ return TRUE;
+}
+
+void npc_apply_direction(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 speed)
+{
+ s16 x;
+ s16 y;
+
+ x = mapObject->coords2.x;
+ y = mapObject->coords2.y;
+ FieldObjectSetDirection(mapObject, direction);
+ MoveCoords(direction, &x, &y);
+ npc_coords_shift(mapObject, x, y);
+ oamt_npc_ministep_reset(sprite, direction, speed);
+ sprite->animPaused = FALSE;
+ if (gUnknown_020375B8 != NULL && sub_8097F78(mapObject) != 0x10)
+ {
+ sprite->animPaused = TRUE;
+ }
+ mapObject->mapobj_bit_2 = TRUE;
+ sprite->data2 = 1;
+}
+
+void do_go_anim(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 speed)
+{
+ u8 (*functions[ARRAY_COUNT(gUnknown_0850DEE8)])(u8);
+
+ memcpy(functions, gUnknown_0850DEE8, sizeof gUnknown_0850DEE8);
+ npc_apply_direction(mapObject, sprite, direction, speed);
+ npc_apply_anim_looping(mapObject, sprite, functions[speed](mapObject->mapobj_unk_18));
+}
+
+void do_run_anim(struct MapObject *mapObject, struct Sprite *sprite, u8 direction)
+{
+ npc_apply_direction(mapObject, sprite, direction, 1);
+ npc_apply_anim_looping(mapObject, sprite, get_run_image_anim_num(mapObject->mapobj_unk_18));
+}
+
+bool8 npc_obj_ministep_stop_on_arrival(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (obj_npc_ministep(sprite))
+ {
+ npc_coords_shift_still(mapObject);
+ mapObject->mapobj_bit_3 = TRUE;
+ sprite->animPaused = TRUE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void sub_8093AF0(struct MapObject *mapObject, struct Sprite *sprite, u8 direction)
+{
+ s16 x;
+ s16 y;
+
+ x = mapObject->coords2.x;
+ y = mapObject->coords2.y;
+ FieldObjectSetDirection(mapObject, direction);
+ MoveCoords(direction, &x, &y);
+ npc_coords_shift(mapObject, x, y);
+ sub_80976DC(sprite, direction);
+ sprite->animPaused = FALSE;
+ mapObject->mapobj_bit_2 = TRUE;
+ sprite->data2 = 1;
+}
+
+void sub_8093B60(struct MapObject *mapObject, struct Sprite *sprite, u8 direction)
+{
+ sub_8093AF0(mapObject, sprite, direction);
+ npc_apply_anim_looping(mapObject, sprite, get_go_image_anim_num(mapObject->mapobj_unk_18));
+}
+
+bool8 an_walk_any_2(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sub_80976EC(sprite))
+ {
+ npc_coords_shift_still(mapObject);
+ mapObject->mapobj_bit_3 = TRUE;
+ sprite->animPaused = TRUE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#define an_walk_any_2_macro(name, fn1, fn2, ...) \
+bool8 name##_2(struct MapObject *, struct Sprite *);\
+bool8 name(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ fn1(mapObject, sprite, __VA_ARGS__);\
+ return name##_2(mapObject, sprite);\
+}\
+bool8 name##_2(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ if (fn2(mapObject, sprite))\
+ {\
+ sprite->data2 = 2;\
+ return TRUE;\
+ }\
+ return FALSE;\
+}
+
+an_walk_any_2_macro(sub_8093BC4, sub_8093B60, an_walk_any_2, 7)
+an_walk_any_2_macro(sub_8093C04, sub_8093B60, an_walk_any_2, 8)
+an_walk_any_2_macro(sub_8093C44, sub_8093B60, an_walk_any_2, 5)
+an_walk_any_2_macro(sub_8093C84, sub_8093B60, an_walk_any_2, 6)
+an_walk_any_2_macro(sub_8093CC4, sub_8093B60, an_walk_any_2, 1)
+an_walk_any_2_macro(sub_8093D04, sub_8093B60, an_walk_any_2, 2)
+an_walk_any_2_macro(sub_8093D44, sub_8093B60, an_walk_any_2, 3)
+an_walk_any_2_macro(sub_8093D84, sub_8093B60, an_walk_any_2, 4)
+an_walk_any_2_macro(sub_8093DC4, do_go_anim, npc_obj_ministep_stop_on_arrival, 7, 0)
+an_walk_any_2_macro(sub_8093E04, do_go_anim, npc_obj_ministep_stop_on_arrival, 8, 0)
+an_walk_any_2_macro(sub_8093E44, do_go_anim, npc_obj_ministep_stop_on_arrival, 5, 0)
+an_walk_any_2_macro(sub_8093E84, do_go_anim, npc_obj_ministep_stop_on_arrival, 6, 0)
+an_walk_any_2_macro(sub_8093EC4, do_go_anim, npc_obj_ministep_stop_on_arrival, 1, 0)
+an_walk_any_2_macro(sub_8093F04, do_go_anim, npc_obj_ministep_stop_on_arrival, 2, 0)
+an_walk_any_2_macro(sub_8093F44, do_go_anim, npc_obj_ministep_stop_on_arrival, 3, 0)
+an_walk_any_2_macro(sub_8093F84, do_go_anim, npc_obj_ministep_stop_on_arrival, 4, 0)
+
+void sub_8093FC4(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 speed, u8 a5)
+{
+ s16 displacements[ARRAY_COUNT(gUnknown_0850DFBC)];
+ s16 x;
+ s16 y;
+
+ memcpy(displacements, gUnknown_0850DFBC, sizeof gUnknown_0850DFBC);
+ x = 0;
+ y = 0;
+ FieldObjectSetDirection(mapObject, direction);
+ sub_8092F88(direction, &x, &y, displacements[speed], displacements[speed]);
+ npc_coords_shift(mapObject, mapObject->coords2.x + x, mapObject->coords2.y + y);
+ sub_809783C(sprite, direction, speed, a5);
+ sprite->data2 = 1;
+ sprite->animPaused = 0;
+ mapObject->mapobj_bit_2 = 1;
+ mapObject->mapobj_bit_4 = 1;
+}
+
+void maybe_shadow_1(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 speed, u8 a4)
+{
+ sub_8093FC4(mapObject, sprite, direction, speed, a4);
+ npc_apply_anim_looping(mapObject, sprite, get_go_image_anim_num(mapObject->mapobj_unk_18));
+ DoShadowFieldEffect(mapObject);
+}
+
+u8 sub_80940C4(struct MapObject *mapObject, struct Sprite *sprite, u8 callback(struct Sprite *))
+{
+ s16 displacements[ARRAY_COUNT(gUnknown_0850DFC2)];
+ s16 x;
+ s16 y;
+ u8 result;
+
+ memcpy(displacements, gUnknown_0850DFC2, sizeof gUnknown_0850DFC2);
+ result = callback(sprite);
+ if (result == 1 && displacements[sprite->data4] != 0)
+ {
+ x = 0;
+ y = 0;
+ sub_8092F88(mapObject->placeholder18, &x, &y, displacements[sprite->data4], displacements[sprite->data4]);
+ npc_coords_shift(mapObject, mapObject->coords2.x + x, mapObject->coords2.y + y);
+ mapObject->mapobj_bit_2 = TRUE;
+ mapObject->mapobj_bit_4 = TRUE;
+ }
+ else if (result == 0xFF)
+ {
+ npc_coords_shift_still(mapObject);
+ mapObject->mapobj_bit_3 = TRUE;
+ mapObject->mapobj_bit_5 = TRUE;
+ sprite->animPaused = TRUE;
+ }
+ return result;
+}
+
+u8 sub_8094188(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ return sub_80940C4(mapObject, sprite, sub_809785C);
+}
+
+u8 sub_809419C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ return sub_80940C4(mapObject, sprite, sub_80978E4);
+}
+
+bool8 sub_80941B0(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sub_8094188(mapObject, sprite) == 0xFF)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_80941C8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sub_809419C(mapObject, sprite) == 0xFF)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_80941E0(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ switch (sub_8094188(mapObject, sprite))
+ {
+ case 255:
+ return TRUE;
+ case 1:
+ FieldObjectSetDirection(mapObject, GetOppositeDirection(mapObject->placeholder18));
+ obj_npc_animation_step(mapObject, sprite, get_go_image_anim_num(mapObject->mapobj_unk_18));
+ default:
+ return FALSE;
+ }
+}
+
+#define maybe_shadow_1_macro(name, fn1, fn2, ...) \
+bool8 name##_2(struct MapObject *, struct Sprite *);\
+bool8 name(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ fn1(mapObject, sprite, __VA_ARGS__);\
+ return name##_2(mapObject, sprite);\
+}\
+bool8 name##_2(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ if (fn2(mapObject, sprite))\
+ {\
+ mapObject->mapobj_bit_22 = FALSE;\
+ sprite->data2 = 2;\
+ return TRUE;\
+ }\
+ return FALSE;\
+}
+
+maybe_shadow_1_macro(sub_8094230, maybe_shadow_1, sub_80941B0, DIR_SOUTH, 2, 0)
+maybe_shadow_1_macro(sub_8094288, maybe_shadow_1, sub_80941B0, DIR_NORTH, 2, 0)
+maybe_shadow_1_macro(sub_80942E0, maybe_shadow_1, sub_80941B0, DIR_WEST, 2, 0)
+maybe_shadow_1_macro(sub_8094338, maybe_shadow_1, sub_80941B0, DIR_EAST, 2, 0)
+
+void sub_8094390(struct Sprite *sprite, u16 duration)
+{
+ sprite->data2 = 1;
+ sprite->data3 = duration;
+}
+
+bool8 sub_8094398(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (-- sprite->data3 == 0)
+ {
+ sprite->data2 = 2;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+#define special_anim_with_timer(name, duration)\
+bool8 name(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ sub_8094390(sprite, duration);\
+ return sub_8094398(mapObject, sprite);\
+}
+
+special_anim_with_timer(sub_80943B4, 1)
+special_anim_with_timer(sub_80943D4, 2)
+special_anim_with_timer(sub_80943F4, 4)
+special_anim_with_timer(sub_8094414, 8)
+special_anim_with_timer(sub_8094434, 16)
+
+an_walk_any_2_macro(sub_8094454, do_go_anim, npc_obj_ministep_stop_on_arrival, 1, 1)
+an_walk_any_2_macro(sub_8094494, do_go_anim, npc_obj_ministep_stop_on_arrival, 2, 1)
+an_walk_any_2_macro(sub_80944D4, do_go_anim, npc_obj_ministep_stop_on_arrival, 3, 1)
+an_walk_any_2_macro(sub_8094514, do_go_anim, npc_obj_ministep_stop_on_arrival, 4, 1)
+
+void sub_8094554(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 animNum, u16 duration)
+{
+ FieldObjectSetDirection(mapObject, direction);
+ npc_apply_anim_looping(mapObject, sprite, animNum);
+ sprite->animPaused = FALSE;
+ sprite->data2 = 1;
+ sprite->data3 = duration;
+}
+
+bool8 sub_809459C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (-- sprite->data3 == 0)
+ {
+ sprite->data2 = 2;
+ sprite->animPaused = TRUE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_80945C4(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sprite->data3 & 1)
+ {
+ sprite->animDelayCounter ++;
+ }
+ return sub_809459C(mapObject, sprite);
+}
+
+#define special_anim_with_timer_2(name, direction, images, duration, timer) \
+bool8 name(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ u8 animId;\
+ animId = images(DIR_##direction);\
+ sub_8094554(mapObject, sprite, DIR_##direction, animId, duration);\
+ return timer(mapObject, sprite);\
+}
+
+special_anim_with_timer_2(sub_8094600, SOUTH, get_go_image_anim_num, 32, sub_80945C4)
+special_anim_with_timer_2(sub_8094638, NORTH, get_go_image_anim_num, 32, sub_80945C4)
+special_anim_with_timer_2(sub_8094670, WEST, get_go_image_anim_num, 32, sub_80945C4)
+special_anim_with_timer_2(sub_80946A8, EAST, get_go_image_anim_num, 32, sub_80945C4)
+special_anim_with_timer_2(sub_80946E0, SOUTH, get_go_image_anim_num, 16, sub_809459C)
+special_anim_with_timer_2(sub_8094718, NORTH, get_go_image_anim_num, 16, sub_809459C)
+special_anim_with_timer_2(sub_8094750, WEST, get_go_image_anim_num, 16, sub_809459C)
+special_anim_with_timer_2(sub_8094788, EAST, get_go_image_anim_num, 16, sub_809459C)
+special_anim_with_timer_2(sub_80947C0, SOUTH, get_go_fast_image_anim_num, 8, sub_809459C)
+special_anim_with_timer_2(sub_80947F8, NORTH, get_go_fast_image_anim_num, 8, sub_809459C)
+special_anim_with_timer_2(sub_8094830, WEST, get_go_fast_image_anim_num, 8, sub_809459C)
+special_anim_with_timer_2(sub_8094868, EAST, get_go_fast_image_anim_num, 8, sub_809459C)
+special_anim_with_timer_2(sub_80948A0, SOUTH, get_go_faster_image_anim_num, 4, sub_809459C)
+special_anim_with_timer_2(sub_80948D8, NORTH, get_go_faster_image_anim_num, 4, sub_809459C)
+special_anim_with_timer_2(sub_8094910, WEST, get_go_faster_image_anim_num, 4, sub_809459C)
+special_anim_with_timer_2(sub_8094948, EAST, get_go_faster_image_anim_num, 4, sub_809459C)
+
+an_walk_any_2_macro(sub_8094980, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_SOUTH, 2)
+an_walk_any_2_macro(sub_80949C0, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_NORTH, 2)
+an_walk_any_2_macro(sub_8094A00, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_WEST, 2)
+an_walk_any_2_macro(sub_8094A40, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_EAST, 2)
+an_walk_any_2_macro(sub_8094A80, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_SOUTH, 3)
+an_walk_any_2_macro(sub_8094AC0, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_NORTH, 3)
+an_walk_any_2_macro(sub_8094B00, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_WEST, 3)
+an_walk_any_2_macro(sub_8094B40, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_EAST, 3)
+an_walk_any_2_macro(sub_8094B80, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_SOUTH, 4)
+an_walk_any_2_macro(sub_8094BC0, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_NORTH, 4)
+an_walk_any_2_macro(sub_8094C00, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_WEST, 4)
+an_walk_any_2_macro(sub_8094C40, do_go_anim, npc_obj_ministep_stop_on_arrival, DIR_EAST, 4)
+an_walk_any_2_macro(sub_8094C80, do_run_anim, npc_obj_ministep_stop_on_arrival, DIR_SOUTH)
+an_walk_any_2_macro(sub_8094CC0, do_run_anim, npc_obj_ministep_stop_on_arrival, DIR_NORTH)
+an_walk_any_2_macro(sub_8094D00, do_run_anim, npc_obj_ministep_stop_on_arrival, DIR_WEST)
+an_walk_any_2_macro(sub_8094D40, do_run_anim, npc_obj_ministep_stop_on_arrival, DIR_EAST)
+
+void npc_set_direction_and_anim__an_proceed(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 animNum)
+{
+ obj_anim_image_set_and_seek(sprite, animNum, 0);
+ FieldObjectSetDirection(mapObject, direction);
+ sprite->data2 = 1;
+}
+
+bool8 sub_8094DAC(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_set_direction_and_anim__an_proceed(mapObject, sprite, mapObject->placeholder18, sprite->animNum);
+ return FALSE;
+}
+
+bool8 sub_8094DC4(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sub_80979BC(sprite))
+ {
+ sprite->data2 = 2;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void sub_8094DE4(struct MapObject *mapObject, struct Sprite *sprite, u8 direction)
+{
+ sub_8093FC4(mapObject, sprite, direction, 1, 0);
+ StartSpriteAnim(sprite, sub_80929AC(direction));
+}
+
+#define unk_macro_8094E18(name, direction)\
+bool8 name##_2(struct MapObject *, struct Sprite *);\
+bool8 name(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ sub_8094DE4(mapObject, sprite, direction);\
+ return name##_2(mapObject, sprite);\
+}\
+bool8 name##_2(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ if (sub_80941C8(mapObject, sprite))\
+ {\
+ sprite->data2 = 2;\
+ mapObject->mapobj_bit_5 = FALSE;\
+ return TRUE;\
+ }\
+ return FALSE;\
+}
+
+unk_macro_8094E18(sub_8094E18, DIR_SOUTH)
+unk_macro_8094E18(sub_8094E60, DIR_NORTH)
+unk_macro_8094E18(sub_8094EB8, DIR_WEST)
+unk_macro_8094E18(sub_8094710, DIR_EAST)
+
+bool8 sub_8094F38(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 mapObjectId;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0, &mapObjectId))
+ {
+ an_look_any(mapObject, sprite, sub_8092AF8(mapObject->coords2.x, mapObject->coords2.y, gMapObjects[mapObjectId].coords2.x, gMapObjects[mapObjectId].coords2.y));
+ }
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_8094F94(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u8 mapObjectId;
+
+ if (!TryGetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0, &mapObjectId))
+ {
+ an_look_any(mapObject, sprite, GetOppositeDirection(sub_8092AF8(mapObject->coords2.x, mapObject->coords2.y, gMapObjects[mapObjectId].coords2.x, gMapObjects[mapObjectId].coords2.y)));
+ }
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_8094FF8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_9 = TRUE;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_8095008(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_9 = FALSE;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+maybe_shadow_1_macro(sub_8095018, maybe_shadow_1, sub_80941B0, DIR_SOUTH, 1, 2)
+maybe_shadow_1_macro(sub_8095070, maybe_shadow_1, sub_80941B0, DIR_NORTH, 1, 2)
+maybe_shadow_1_macro(sub_80950C8, maybe_shadow_1, sub_80941B0, DIR_WEST, 1, 2)
+maybe_shadow_1_macro(sub_8095120, maybe_shadow_1, sub_80941B0, DIR_EAST, 1, 2)
+maybe_shadow_1_macro(sub_8095178, maybe_shadow_1, sub_80941B0, DIR_SOUTH, 0, 0)
+maybe_shadow_1_macro(sub_80951D0, maybe_shadow_1, sub_80941B0, DIR_NORTH, 0, 0)
+maybe_shadow_1_macro(sub_8095228, maybe_shadow_1, sub_80941B0, DIR_WEST, 0, 0)
+maybe_shadow_1_macro(sub_8095280, maybe_shadow_1, sub_80941B0, DIR_EAST, 0, 0)
+maybe_shadow_1_macro(sub_80952D8, maybe_shadow_1, sub_80941E0, DIR_SOUTH, 0, 2)
+maybe_shadow_1_macro(sub_8095330, maybe_shadow_1, sub_80941E0, DIR_NORTH, 0, 2)
+maybe_shadow_1_macro(sub_8095388, maybe_shadow_1, sub_80941E0, DIR_WEST, 0, 2)
+maybe_shadow_1_macro(sub_80953E0, maybe_shadow_1, sub_80941E0, DIR_EAST, 0, 2)
+
+bool8 sub_8095438(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ an_look_any(mapObject, sprite, gUnknown_085055CD[mapObject->animPattern]);
+ return TRUE;
+}
+
+bool8 sub_8095450(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_SOUTH, 0x14);
+ return FALSE;
+}
+
+bool8 sub_8095460(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_25 = FALSE;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_8095470(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_25 = TRUE;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_8095480(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_12 = TRUE;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_8095490(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_12 = GetFieldObjectGraphicsInfo(mapObject->graphicsId)->inanimate;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_80954BC(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_13 = TRUE;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_80954CC(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_13 = FALSE;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 do_exclamation_mark_bubble_1(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectSpawnParams[0], (u8 *)&gFieldEffectSpawnParams[1], (u8 *)&gFieldEffectSpawnParams[2]);
+ FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON_1);
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 do_exclamation_mark_bubble_2(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectSpawnParams[0], (u8 *)&gFieldEffectSpawnParams[1], (u8 *)&gFieldEffectSpawnParams[2]);
+ FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON_2);
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 do_heart_bubble(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectSpawnParams[0], (u8 *)&gFieldEffectSpawnParams[1], (u8 *)&gFieldEffectSpawnParams[2]);
+ FieldEffectStart(FLDEFF_HEART_ICON);
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_8095548(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (mapObject->animPattern == 0x3F)
+ {
+ sub_80B4578(mapObject);
+ return FALSE;
+ }
+ if (mapObject->animPattern != 0x39 && mapObject->animPattern != 0x3A)
+ {
+ sprite->data2 = 2;
+ return TRUE;
+ }
+ sub_8155D78(mapObject);
+ sprite->data2 = 1;
+ return sub_809558C(mapObject, sprite);
+}
+
+bool8 sub_809558C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sub_8155DA0(mapObject))
+ {
+ sprite->data2 = 2;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_80955AC(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ obj_anim_image_set_and_seek(sprite, 1, 0);
+ sprite->data2 = 1;
+ return FALSE;
+}
+
+bool8 sub_80955C8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sub_80979BC(sprite))
+ {
+ SetFieldObjectStepTimer(sprite, 32);
+ sprite->data2 = 2;
+ }
+ return FALSE;
+}
+
+bool8 sub_80955EC(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_13 ^= TRUE;
+ if (RunFieldObjectStepTimer(sprite))
+ {
+ mapObject->mapobj_bit_13 = TRUE;
+ sprite->data2 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_8095628(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ obj_anim_image_set_and_seek(sprite, 1, 0);
+ sprite->data2 = 1;
+ return FALSE;
+}
+
+bool8 sub_8095644(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sub_80979BC(sprite))
+ {
+ SetFieldObjectStepTimer(sprite, 32);
+ sprite->data2 = 2;
+ }
+ return FALSE;
+}
+
+bool8 sub_8095668(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_13 ^= TRUE;
+ if (RunFieldObjectStepTimer(sprite))
+ {
+ mapObject->mapobj_bit_13 = TRUE;
+ sprite->data2 = 3;
+ }
+ return FALSE;
+}
+
+bool8 sub_80956A4(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_26 = TRUE;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_80956B4(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_26 = FALSE;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_80956C4(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sprite->oam.affineMode = 3;
+ InitSpriteAffineAnim(sprite);
+ sprite->affineAnimPaused = TRUE;
+ sprite->subspriteMode = 0;
+ return TRUE;
+}
+
+bool8 sub_80956F4(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ FreeOamMatrix(sprite->oam.matrixNum);
+ sprite->oam.affineMode = 0;
+ CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, sprite->oam.affineMode);
+ return TRUE;
+}
+
+bool8 sub_8095724(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_27 = TRUE;
+ return TRUE;
+}
+
+bool8 sub_8095730(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ mapObject->mapobj_bit_27 = FALSE;
+ return TRUE;
+}
+
+#define affine_an_walk_any_2_macro(name, fn, fn2, action, anim, ...)\
+bool8 name##_2(struct MapObject *, struct Sprite *);\
+bool8 name(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ fn(mapObject, sprite, __VA_ARGS__);\
+ sprite->affineAnimPaused = FALSE;\
+ action(sprite, anim);\
+ return name##_2(mapObject, sprite);\
+}\
+bool8 name##_2(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ if (fn2(mapObject, sprite))\
+ {\
+ sprite->affineAnimPaused = TRUE;\
+ sprite->data2 = 2;\
+ return TRUE;\
+ }\
+ return FALSE;\
+}\
+
+affine_an_walk_any_2_macro(sub_8095740, sub_8093B60, an_walk_any_2, StartSpriteAffineAnimIfDifferent, 0, DIR_SOUTH)
+affine_an_walk_any_2_macro(sub_80957A0, sub_8093B60, an_walk_any_2, ChangeSpriteAffineAnimIfDifferent, 1, DIR_SOUTH)
+affine_an_walk_any_2_macro(sub_8095800, do_go_anim, npc_obj_ministep_stop_on_arrival, ChangeSpriteAffineAnimIfDifferent, 2, DIR_WEST, 1)
+affine_an_walk_any_2_macro(sub_8095860, do_go_anim, npc_obj_ministep_stop_on_arrival, ChangeSpriteAffineAnimIfDifferent, 3, DIR_EAST, 1)
+
+static void sub_80958C0(struct MapObject *mapObject, struct Sprite *sprite, u8 direction)
+{
+ FieldObjectSetDirection(mapObject, direction);
+ npc_coords_shift_still(mapObject);
+ obj_npc_animation_step(mapObject, sprite, sub_80929FC(direction));
+ sprite->animPaused = TRUE;
+ sprite->data2 = 1;
+}
+
+bool8 sub_8095900(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sub_80958C0(mapObject, sprite, DIR_SOUTH);
+ return TRUE;
+}
+
+bool8 sub_8095910(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sub_80958C0(mapObject, sprite, DIR_NORTH);
+ return TRUE;
+}
+
+bool8 sub_8095920(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sub_80958C0(mapObject, sprite, DIR_WEST);
+ return TRUE;
+}
+
+bool8 sub_8095930(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sub_80958C0(mapObject, sprite, DIR_EAST);
+ return TRUE;
+}
+
+#define set_dirn_and_anim__an_proceed(name, direction, anims)\
+bool8 name(struct MapObject *mapObject, struct Sprite *sprite)\
+{\
+ npc_set_direction_and_anim__an_proceed(mapObject, sprite, direction, anims(direction));\
+ return FALSE;\
+}
+
+set_dirn_and_anim__an_proceed(sub_8095940, DIR_SOUTH, sub_80929BC)
+set_dirn_and_anim__an_proceed(sub_8095964, DIR_NORTH, sub_80929BC)
+set_dirn_and_anim__an_proceed(sub_8095988, DIR_WEST, sub_80929BC)
+set_dirn_and_anim__an_proceed(sub_80959AC, DIR_EAST, sub_80929BC)
+set_dirn_and_anim__an_proceed(sub_80959D0, DIR_SOUTH, sub_80929DC)
+set_dirn_and_anim__an_proceed(sub_80959F4, DIR_NORTH, sub_80929DC)
+set_dirn_and_anim__an_proceed(sub_8095A18, DIR_WEST, sub_80929DC)
+set_dirn_and_anim__an_proceed(sub_8095A3C, DIR_EAST, sub_80929DC)
+set_dirn_and_anim__an_proceed(sub_8095A60, DIR_SOUTH, sub_80929EC)
+set_dirn_and_anim__an_proceed(sub_8095A84, DIR_NORTH, sub_80929EC)
+set_dirn_and_anim__an_proceed(sub_8095AA8, DIR_WEST, sub_80929EC)
+set_dirn_and_anim__an_proceed(sub_8095ACC, DIR_EAST, sub_80929EC)
+
+void sub_8095AF0(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sub_8097750(sprite);
+ sprite->animPaused = FALSE;
+}
+
+bool8 sub_8095B0C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sub_8097758(sprite))
+ {
+ npc_coords_shift_still(mapObject);
+ mapObject->mapobj_bit_3 = TRUE;
+ sprite->animPaused = TRUE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_8095B44(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sub_8095AF0(mapObject, sprite);
+ sprite->data2 = 1;
+ return sub_8095B64(mapObject, sprite);
+}
+
+bool8 sub_8095B64(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sub_8095B0C(mapObject, sprite))
+ {
+ sprite->data2 = 2;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void sub_8095B84(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 speed, u8 a4)
+{
+ sub_8093FC4(mapObject, sprite, direction, speed, a4);
+ StartSpriteAnimIfDifferent(sprite, sub_80929BC(direction));
+ DoShadowFieldEffect(mapObject);
+}
+
+maybe_shadow_1_macro(sub_8095BC8, sub_8095B84, sub_80941B0, DIR_SOUTH, 0, 1)
+maybe_shadow_1_macro(sub_8095C20, sub_8095B84, sub_80941B0, DIR_NORTH, 0, 1)
+maybe_shadow_1_macro(sub_8095C78, sub_8095B84, sub_80941B0, DIR_WEST, 0, 1)
+maybe_shadow_1_macro(sub_8095CD0, sub_8095B84, sub_80941B0, DIR_EAST, 0, 1)
+maybe_shadow_1_macro(sub_8095D28, sub_8095B84, sub_80941B0, DIR_SOUTH, 1, 1)
+maybe_shadow_1_macro(sub_8095D80, sub_8095B84, sub_80941B0, DIR_NORTH, 1, 1)
+maybe_shadow_1_macro(sub_8095DD8, sub_8095B84, sub_80941B0, DIR_WEST, 1, 1)
+maybe_shadow_1_macro(sub_8095E30, sub_8095B84, sub_80941B0, DIR_EAST, 1, 1)
+maybe_shadow_1_macro(sub_8095E88, sub_8095B84, sub_80941B0, DIR_SOUTH, 2, 0)
+maybe_shadow_1_macro(sub_8095EE0, sub_8095B84, sub_80941B0, DIR_NORTH, 2, 0)
+maybe_shadow_1_macro(sub_8095F38, sub_8095B84, sub_80941B0, DIR_WEST, 2, 0)
+maybe_shadow_1_macro(sub_8095F90, sub_8095B84, sub_80941B0, DIR_EAST, 2, 0)
+
+special_anim_with_timer_2(sub_8095FE8, SOUTH, sub_80929FC, 8, sub_809459C)
+special_anim_with_timer_2(sub_8096020, NORTH, sub_80929FC, 8, sub_809459C)
+special_anim_with_timer_2(sub_8096058, WEST, sub_80929FC, 8, sub_809459C)
+special_anim_with_timer_2(sub_8096090, EAST, sub_80929FC, 8, sub_809459C)
+
+void sub_80960C8(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 speed)
+{
+ npc_apply_direction(mapObject, sprite, direction, speed);
+ StartSpriteAnim(sprite, sub_80929BC(mapObject->mapobj_unk_18));
+ SeekSpriteAnim(sprite, 0);
+}
+
+an_walk_any_2_macro(sub_8096100, sub_80960C8, npc_obj_ministep_stop_on_arrival, DIR_SOUTH, 1)
+an_walk_any_2_macro(sub_8096140, sub_80960C8, npc_obj_ministep_stop_on_arrival, DIR_NORTH, 1)
+an_walk_any_2_macro(sub_8096180, sub_80960C8, npc_obj_ministep_stop_on_arrival, DIR_WEST, 1)
+an_walk_any_2_macro(sub_80961C0, sub_80960C8, npc_obj_ministep_stop_on_arrival, DIR_EAST, 1)
+
+void sub_8096200(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 speed)
+{
+ npc_apply_direction(mapObject, sprite, direction, speed);
+ npc_apply_anim_looping(mapObject, sprite, sub_80929FC(mapObject->mapobj_unk_18));
+}
+
+an_walk_any_2_macro(sub_8096230, sub_8096200, npc_obj_ministep_stop_on_arrival, DIR_SOUTH, 1)
+an_walk_any_2_macro(sub_8096270, sub_8096200, npc_obj_ministep_stop_on_arrival, DIR_NORTH, 1)
+an_walk_any_2_macro(sub_80962B0, sub_8096200, npc_obj_ministep_stop_on_arrival, DIR_WEST, 1)
+an_walk_any_2_macro(sub_80962F0, sub_8096200, npc_obj_ministep_stop_on_arrival, DIR_EAST, 1)
+
+void sub_8096330(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 speed)
+{
+ npc_apply_direction(mapObject, sprite, direction, speed);
+ StartSpriteAnim(sprite, sub_80929DC(mapObject->mapobj_unk_18));
+ SeekSpriteAnim(sprite, 0);
+}
+an_walk_any_2_macro(sub_8096368, sub_8096330, npc_obj_ministep_stop_on_arrival, DIR_SOUTH, 1)
+an_walk_any_2_macro(sub_80963A8, sub_8096330, npc_obj_ministep_stop_on_arrival, DIR_NORTH, 1)
+an_walk_any_2_macro(sub_80963E8, sub_8096330, npc_obj_ministep_stop_on_arrival, DIR_WEST, 1)
+an_walk_any_2_macro(sub_8096428, sub_8096330, npc_obj_ministep_stop_on_arrival, DIR_EAST, 1)
+
+bool8 sub_8096468(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sub_8097FA4(mapObject);
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_809647C(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sub_8098044(mapObject->mapobj_unk_1B);
+ sprite->pos2.y = 0;
+ sprite->data2 = 1;
+ return TRUE;
+}
+
+bool8 sub_8096494(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (sprite->pos2.y == 0)
+ {
+ sub_8098044(mapObject->mapobj_unk_1B);
+ sprite->data2 = 1;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_80964B8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ return TRUE;
+}
+
+bool8 sub_80964BC(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sprite->animPaused = TRUE;
+ return TRUE;
+}
+
+void npc_obj_transfer_image_anim_pause_flag(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (mapObject->mapobj_bit_10)
+ {
+ sprite->animPaused = TRUE;
+ }
+}
+
+void sub_80964E8(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ if (mapObject->mapobj_bit_11)
+ {
+ sprite->animPaused = FALSE;
+ mapObject->mapobj_bit_10 = FALSE;
+ mapObject->mapobj_bit_11 = FALSE;
+ }
+}
+
+void sub_8096518(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sub_8096530(mapObject, sprite);
+ npc_update_obj_anim_flag(mapObject, sprite);
+}
+
+static void sub_8096530(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ u16 x;
+ u16 y;
+ u16 x2;
+ u16 y2;
+ const struct MapObjectGraphicsInfo *graphicsInfo;
+
+ mapObject->mapobj_bit_14 = FALSE;
+ graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId);
+ if (sprite->coordOffsetEnabled)
+ {
+ x = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX + gSpriteCoordOffsetX;
+ y = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY;
+ }
+ else
+ {
+ x = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX;
+ y = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY;
+ }
+ x2 = graphicsInfo->width;
+ x2 += x;
+ y2 = y;
+ y2 += graphicsInfo->height;
+ if ((s16)x >= 0x100 || (s16)x2 < -0x10)
+ {
+ mapObject->mapobj_bit_14 = TRUE;
+ }
+ if ((s16)y >= 0xB0 || (s16)y2 < -0x10)
+ {
+ mapObject->mapobj_bit_14 = TRUE;
+ }
+}
+
+static void npc_update_obj_anim_flag(struct MapObject *mapObject, struct Sprite *sprite)
+{
+ sprite->invisible = FALSE;
+ if (mapObject->mapobj_bit_13 || mapObject->mapobj_bit_14)
+ {
+ sprite->invisible = TRUE;
+ }
+}
diff --git a/src/field_screen.c b/src/field_screen.c
new file mode 100644
index 000000000..2d33d237f
--- /dev/null
+++ b/src/field_screen.c
@@ -0,0 +1,15 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+IWRAM_DATA u8 *gUnknown_03000F50;
+IWRAM_DATA u32 filler_03000f54;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/field_special_scene.c b/src/field_special_scene.c
new file mode 100755
index 000000000..9c35a33da
--- /dev/null
+++ b/src/field_special_scene.c
@@ -0,0 +1,363 @@
+#include "global.h"
+#include "task.h"
+#include "sprite.h"
+#include "field_map_obj.h"
+#include "songs.h"
+#include "sound.h"
+#include "palette.h"
+#include "script.h"
+#include "vars.h"
+#include "event_data.h"
+#include "main.h"
+
+#define SECONDS(value) ((signed) (60.0 * value + 0.5))
+
+extern u8 GetSSTidalLocation(s8 *, s8 *, s16 *, s16 *); // should be in field_specials.h
+extern void warp1_set(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y);
+extern bool8 sub_80D3340(u8, u8, u8);
+extern bool32 CountSSTidalStep(u16);
+extern bool8 exec_movement(u8, u8, u8, u8 *);
+extern void copy_saved_warp2_bank_and_enter_x_to_warp1(u8 unused);
+extern void sp13E_warp_to_last_warp(void);
+extern void saved_warp2_set(int unused, s8 mapGroup, s8 mapNum, s8 warpId);
+extern void sub_80AF8B8(void);
+
+// porthole states
+enum
+{
+ INIT_PORTHOLE,
+ IDLE_CHECK,
+ EXECUTE_MOVEMENT,
+ EXIT_PORTHOLE,
+};
+
+extern void SetCameraPanning(s16 x, s16 y);
+extern void SetCameraPanningCallback(void ( *callback)());
+extern void InstallCameraPanAheadCallback();
+extern void pal_fill_black(void);
+extern void MapGridSetMetatileIdAt(s32 x, s32 y, u16 metatileId);
+extern void DrawWholeMapView();
+
+extern s8 gTruckCamera_HorizontalTable[];
+
+extern u8 gUnknown_0858E8AB[];
+extern u8 gUnknown_0858E8AD[];
+
+void Task_Truck3(u8);
+
+s16 GetTruckCameraBobbingY(int a1)
+{
+ if (!(a1 % 120))
+ return -1;
+ else if ((a1 % 10) <= 4)
+ return 1;
+
+ return 0;
+}
+
+s16 GetTruckBoxMovement(int a1) // for the box movement?
+{
+ if (!((a1 + 120) % 180))
+ return -1;
+
+ return 0;
+}
+
+// smh STILL BROKEN IN EMERALD
+void Task_Truck1(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ s16 cameraYpan;
+ s16 box1 = 0;
+ s16 box2 = 0;
+ s16 box3 = 0;
+ u8 mapNum, mapGroup;
+ register s16 zero asm("r4");
+
+ box1 = GetTruckBoxMovement(data[0] + 30) * 4; // top box.
+ sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3, box1 + 3);
+ box2 = GetTruckBoxMovement(data[0]) * 2; // bottom left box.
+ sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 0, box2 - 3);
+ box3 = GetTruckBoxMovement(data[0]) * 4; // bottom right box.
+ mapNum = gSaveBlock1Ptr->location.mapNum;
+ mapGroup = gSaveBlock1Ptr->location.mapGroup;
+ zero = 0;
+ sub_808E82C(3, mapNum, mapGroup, -3, box3);
+
+ if (++data[0] == SECONDS(500)) // this will never run
+ data[0] = zero; // reset the timer if it gets stuck.
+
+ cameraYpan = GetTruckCameraBobbingY(data[0]);
+ SetCameraPanning(0, cameraYpan);
+}
+
+void Task_Truck2(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ s16 cameraYpan;
+ s16 cameraXpan;
+ s16 box1;
+ s16 box2;
+ s16 box3;
+
+ data[0]++;
+ data[2]++;
+
+ if (data[0] > 5)
+ {
+ data[0] = 0;
+ data[1]++;
+ }
+ if ((u16)data[1] == 19)
+ {
+ DestroyTask(taskId);
+ }
+ else
+ {
+ if (gTruckCamera_HorizontalTable[data[1]] == 2)
+ gTasks[taskId].func = Task_Truck3;
+
+ cameraXpan = gTruckCamera_HorizontalTable[data[1]];
+ cameraYpan = GetTruckCameraBobbingY(data[2]);
+ SetCameraPanning(cameraXpan, cameraYpan);
+ box1 = GetTruckBoxMovement(data[2] + 30) * 4;
+ sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3 - cameraXpan, box1 + 3);
+ box2 = GetTruckBoxMovement(data[2]) * 2;
+ sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -cameraXpan, box2 - 3);
+ box3 = GetTruckBoxMovement(data[2]) * 4;
+ sub_808E82C(3, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -3 - cameraXpan, box3);
+ }
+}
+
+void Task_Truck3(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ s16 cameraXpan;
+ s16 cameraYpan;
+
+ data[0]++;
+
+ if (data[0] > 5)
+ {
+ data[0] = 0;
+ data[1]++;
+ }
+
+ if ((u16)data[1] == 19)
+ {
+ DestroyTask(taskId);
+ }
+ else
+ {
+ cameraXpan = gTruckCamera_HorizontalTable[data[1]];
+ cameraYpan = 0;
+ SetCameraPanning(cameraXpan, 0);
+ sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3 - cameraXpan, cameraYpan + 3);
+ sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -cameraXpan, cameraYpan - 3);
+ sub_808E82C(3, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -3 - cameraXpan, cameraYpan);
+ }
+}
+
+void Task_HandleTruckSequence(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ /*
+ Each case has a timer which is handled with data[1], incrementing
+ until it reaches the if function's condition, which sets the next task up.
+ */
+ case 0:
+ data[1]++;
+ if (data[1] == SECONDS(1.5))
+ {
+ SetCameraPanningCallback(NULL);
+ data[1] = 0; // reset the timer.
+ data[2] = CreateTask(Task_Truck1, 0xA);
+ data[0] = 1; // run the next case.
+ PlaySE(SE_TRACK_MOVE);
+ }
+ break;
+ case 1:
+ data[1]++;
+ if (data[1] == SECONDS(2.5))
+ {
+ pal_fill_black();
+ data[1] = 0;
+ data[0] = 2;
+ }
+ break;
+ case 2:
+ data[1]++;
+ if (!gPaletteFade.active && data[1] > SECONDS(5))
+ {
+ data[1] = 0;
+ DestroyTask(data[2]);
+ data[3] = CreateTask(Task_Truck2, 0xA);
+ data[0] = 3;
+ PlaySE(SE_TRACK_STOP);
+ }
+ break;
+ case 3:
+ if (!gTasks[data[3]].isActive) // is Truck2 no longer active (is Truck3 active?)
+ {
+ InstallCameraPanAheadCallback();
+ data[1] = 0;
+ data[0] = 4;
+ }
+ break;
+ case 4:
+ data[1]++;
+ if (data[1] == 90)
+ {
+ PlaySE(SE_TRACK_HAIK);
+ data[1] = 0;
+ data[0] = 5;
+ }
+ break;
+ case 5:
+ data[1]++;
+ if (data[1] == 120)
+ {
+ MapGridSetMetatileIdAt(11, 8, 520);
+ MapGridSetMetatileIdAt(11, 9, 528);
+ MapGridSetMetatileIdAt(11, 10, 536);
+ DrawWholeMapView();
+ PlaySE(SE_TRACK_DOOR);
+ DestroyTask(taskId);
+ ScriptContext2_Disable();
+ }
+ break;
+ }
+}
+
+void ExecuteTruckSequence(void)
+{
+ MapGridSetMetatileIdAt(11, 8, 525);
+ MapGridSetMetatileIdAt(11, 9, 533);
+ MapGridSetMetatileIdAt(11, 10, 541);
+ DrawWholeMapView();
+ ScriptContext2_Enable();
+ CpuFastFill(0, gPlttBufferFaded, 0x400);
+ CreateTask(Task_HandleTruckSequence, 0xA);
+}
+
+void EndTruckSequence(u8 taskId)
+{
+ if (!FuncIsActiveTask(Task_HandleTruckSequence))
+ {
+ sub_808E82C(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 3, 3);
+ sub_808E82C(2, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, 0, -3);
+ sub_808E82C(3, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, -3, 0);
+ }
+}
+
+bool8 sub_80FB59C(void)
+{
+ s8 mapGroup, mapNum;
+ s16 x, y;
+
+ if (GetSSTidalLocation(&mapGroup, &mapNum, &x, &y))
+ {
+ return FALSE;
+ }
+ else
+ {
+ warp1_set(mapGroup, mapNum, -1, x, y);
+ return TRUE;
+ }
+}
+
+void Task_HandlePorthole(u8 taskId)
+{
+ s16 *data = gTasks[taskId].data;
+ u16 *var = GetVarPointer(VAR_PORTHOLE);
+ struct WarpData *location = &gSaveBlock1Ptr->location;
+
+ switch (data[0])
+ {
+ case INIT_PORTHOLE: // finish fading before making porthole finish.
+ if (!gPaletteFade.active)
+ {
+ data[1] = 0;
+ data[0] = EXECUTE_MOVEMENT; // execute movement before checking if should be exited. strange?
+ }
+ break;
+ case IDLE_CHECK: // idle and move.
+ if (gMain.newKeys & A_BUTTON)
+ data[1] = 1;
+ if (!sub_80D3340(0xFF, location->mapNum, location->mapGroup))
+ return;
+ if (CountSSTidalStep(1) == TRUE)
+ {
+ if (*var == 2)
+ *var = 9;
+ else
+ *var = 10;
+ data[0] = 3;
+ return;
+ }
+ data[0] = 2;
+ case EXECUTE_MOVEMENT: // execute movement.
+ if (data[1])
+ {
+ data[0] = EXIT_PORTHOLE; // exit porthole.
+ return;
+ }
+ // run this once.
+ if (*var == 2) // which direction?
+ {
+ exec_movement(0xFF, location->mapNum, location->mapGroup, gUnknown_0858E8AB);
+ data[0] = IDLE_CHECK; // run case 1.
+ }
+ else
+ {
+ exec_movement(0xFF, location->mapNum, location->mapGroup, gUnknown_0858E8AD);
+ data[0] = IDLE_CHECK; // run case 1.
+ }
+ break;
+ case EXIT_PORTHOLE: // exit porthole.
+ FlagReset(0x4001);
+ FlagReset(0x4000);
+ copy_saved_warp2_bank_and_enter_x_to_warp1(0);
+ sp13E_warp_to_last_warp();
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+void sub_80FB6EC(void)
+{
+ u8 spriteId = AddPseudoFieldObject(0x8C, SpriteCallbackDummy, 112, 80, 0);
+
+ gSprites[spriteId].coordOffsetEnabled = FALSE;
+
+ if (VarGet(0x40B4) == 2)
+ {
+ StartSpriteAnim(&gSprites[spriteId], FieldObjectDirectionToImageAnimId(4));
+ }
+ else
+ {
+ StartSpriteAnim(&gSprites[spriteId], FieldObjectDirectionToImageAnimId(3));
+ }
+}
+
+void sub_80FB768(void)
+{
+ sub_80FB6EC();
+ gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = TRUE;
+ pal_fill_black();
+ CreateTask(Task_HandlePorthole, 80);
+ ScriptContext2_Enable();
+}
+
+void sub_80FB7A4(void)
+{
+ FlagSet(SYS_CRUISE_MODE);
+ FlagSet(0x4001);
+ FlagSet(0x4000);
+ saved_warp2_set(0, gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum, -1);
+ sub_80FB59C();
+ sub_80AF8B8();
+}
diff --git a/src/fldeff_cut.c b/src/fldeff_cut.c
new file mode 100644
index 000000000..9929dd6f9
--- /dev/null
+++ b/src/fldeff_cut.c
@@ -0,0 +1,19 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03001100;
+IWRAM_DATA u8 gUnknown_03001101;
+IWRAM_DATA u8 gUnknown_03001102;
+IWRAM_DATA u32 fldeff_cut_unused_03001104;
+IWRAM_DATA u8 gUnknown_03001108[25];
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/gpu_regs.c b/src/gpu_regs.c
index be1f153d4..805f23b48 100644
--- a/src/gpu_regs.c
+++ b/src/gpu_regs.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "gpu_regs.h"
#define GPU_REG_BUF_SIZE 0x60
@@ -14,14 +15,15 @@ static bool8 sShouldSyncRegIE;
static u16 sRegIE;
static void CopyBufferedValueToGpuReg(u8 regOffset);
-static void SyncRegIE();
+static void SyncRegIE(void);
static void UpdateRegDispstatIntrBits(u16 regIE);
-void InitGpuRegManager()
+void InitGpuRegManager(void)
{
s32 i;
- for (i = 0; i < GPU_REG_BUF_SIZE; i++) {
+ for (i = 0; i < GPU_REG_BUF_SIZE; i++)
+ {
sGpuRegBuffer[i] = 0;
sGpuRegWaitingList[i] = EMPTY_SLOT;
}
@@ -33,20 +35,25 @@ void InitGpuRegManager()
static void CopyBufferedValueToGpuReg(u8 regOffset)
{
- if (regOffset == REG_OFFSET_DISPSTAT) {
+ if (regOffset == REG_OFFSET_DISPSTAT)
+ {
REG_DISPSTAT &= ~(DISPSTAT_HBLANK_INTR | DISPSTAT_VBLANK_INTR);
REG_DISPSTAT |= GPU_REG_BUF(REG_OFFSET_DISPSTAT);
- } else {
+ }
+ else
+ {
GPU_REG(regOffset) = GPU_REG_BUF(regOffset);
}
}
-void CopyBufferedValuesToGpuRegs()
+void CopyBufferedValuesToGpuRegs(void)
{
- if (!sGpuRegBufferLocked) {
+ if (!sGpuRegBufferLocked)
+ {
s32 i;
- for (i = 0; i < GPU_REG_BUF_SIZE; i++) {
+ for (i = 0; i < GPU_REG_BUF_SIZE; i++)
+ {
u8 regOffset = sGpuRegWaitingList[i];
if (regOffset == EMPTY_SLOT)
return;
@@ -135,7 +142,7 @@ void ClearGpuRegBits(u8 regOffset, u16 mask)
SetGpuReg(regOffset, regValue & ~mask);
}
-static void SyncRegIE()
+static void SyncRegIE(void)
{
if (sShouldSyncRegIE) {
u16 temp = REG_IME;
diff --git a/src/hall_of_fame.c b/src/hall_of_fame.c
new file mode 100644
index 000000000..d9fd40b84
--- /dev/null
+++ b/src/hall_of_fame.c
@@ -0,0 +1,4 @@
+#include "global.h"
+#include "hall_of_fame.h"
+
+
diff --git a/src/item.c b/src/item.c
index c85e2fe1f..0114676b6 100644
--- a/src/item.c
+++ b/src/item.c
@@ -8,9 +8,9 @@
extern void ApplyNewEncyprtionKeyToHword(u16* hword, u32 newKey);
extern bool8 InBattlePyramid(void);
-extern const u8 gOtherText_PokeBalls[];
-extern const u8 gOtherText_Berries[];
-extern const u8 gOtherText_Berry[];
+extern const u8 gText_PokeBalls[];
+extern const u8 gText_Berries[];
+extern const u8 gText_Berry[];
extern const u8 gUnknown_085897E4[][28]; // not sure what this one is
bool8 CheckPyramidBagHasItem(u16 itemId, u16 count);
@@ -92,7 +92,7 @@ void CopyItemNameHandlePlural(u16 itemId, u8 *string, u32 quantity)
if (quantity < 2)
StringCopy(string, ItemId_GetItem(ITEM_POKE_BALL)->name);
else
- StringCopy(string, gOtherText_PokeBalls);
+ StringCopy(string, gText_PokeBalls);
}
else
{
@@ -109,9 +109,9 @@ void GetBerryCountString(u8* dst, const u8* berryName, u32 quantity)
u8* txtPtr;
if (quantity < 2)
- berryString = gOtherText_Berry;
+ berryString = gText_Berry;
else
- berryString = gOtherText_Berries;
+ berryString = gText_Berries;
txtPtr = StringCopy(dst, berryName);
*txtPtr = CHAR_SPACE;
StringCopy(txtPtr + 1, berryString);
diff --git a/src/lilycove_lady.c b/src/lilycove_lady.c
new file mode 100644
index 000000000..9f38824f9
--- /dev/null
+++ b/src/lilycove_lady.c
@@ -0,0 +1,1101 @@
+//
+// Created by Scott Norton on 9/19/17.
+//
+
+#include "global.h"
+#include "main.h"
+#include "rom4.h"
+#include "rom6.h"
+#include "event_data.h"
+#include "script.h"
+#include "rng.h"
+#include "string_util.h"
+#include "item.h"
+#include "items.h"
+#include "item_menu.h"
+#include "text.h"
+#include "easy_chat.h"
+#include "lilycove_lady.h"
+
+static void SetLilycoveQuizLady(void);
+static void SetLilycoveFavourLady(void);
+static void SetLilycoveContestLady(void);
+static void sub_818E004(void);
+static void sub_818DBC4(void);
+static void sub_818E674(void);
+static u8 sub_818E13C(void);
+static bool8 sub_818E1F4(void);
+static u8 sub_818E258(const u8 *);
+
+extern const u8 gText_Lady2[];
+
+static const u16 gUnknown_0860B074[] = {
+ 0x62, 0xcb, 0xdc, 0xcc, 0xd1
+};
+static const u16 gUnknown_0860B07E[] = {
+ 0x1a, 0x14, 0x0a
+};
+
+static const u16 Unknown_0860B084[] = {
+ 0x101b, 0x1623, 0x1812, 0x102c, 0x020e, 0x0c03, 0x1a0b, 0x0210, 0x020d
+};
+
+static const u16 Unknown_0860B096[] = {
+ 0x101b, 0x1013, 0x1020, 0x1a0f, 0x020c, 0x0c03, 0x0211, 0x0203, 0x0400
+};
+
+static const u16 Unknown_0860B0A8[] = {
+ 0x0e0f, 0x1018, 0x020e, 0x0204, 0x0c03, 0xffff, 0x0212, 0x0451, 0x0463
+};
+
+static const u16 Unknown_0860B0BA[] = {
+ 0x101b, 0x100b, 0x0e0d, 0x141a, 0x181d, 0x0c03, 0x141e, 0x1a26, 0x1823
+};
+
+static const u16 Unknown_0860B0CC[] = {
+ 0x101b, 0x181d, 0x1018, 0x0a02, 0x2014, 0x0c03, 0x0208, 0x1824, 0x181c
+};
+
+static const u16 Unknown_0860B0DE[] = {
+ 0x101b, 0x1000, 0x1c19, 0x265d, 0x0c03, 0xffff, 0x0447, 0x045d, 0x042c
+};
+
+static const u16 Unknown_0860B0F0[] = {
+ 0x101b, 0x1034, 0x1e11, 0x100b, 0x1a08, 0x0c03, 0x044b, 0x0446, 0x040a
+};
+
+static const u16 Unknown_0860B102[] = {
+ 0x101b, 0x1000, 0x274f, 0x0626, 0x0c03, 0xffff, 0x0442, 0x0411, 0x0450
+};
+
+static const u16 Unknown_0860B114[] = {
+ 0x101b, 0x1000, 0x1c19, 0x043c, 0x0c03, 0xffff, 0x0421, 0x0464, 0x0435
+};
+
+static const u16 Unknown_0860B126[] = {
+ 0x101b, 0x1203, 0x1030, 0x0207, 0x0c03, 0xffff, 0x0210, 0x020e, 0x020d
+};
+
+static const u16 Unknown_0860B138[] = {
+ 0x101b, 0x1623, 0x0a05, 0x020e, 0x0c03, 0xffff, 0x1a25, 0x181a, 0x181b
+};
+
+static const u16 Unknown_0860B14A[] = {
+ 0x101b, 0x1823, 0x1603, 0x0a02, 0x1812, 0x0c03, 0x1a15, 0x1a23, 0x181b
+};
+
+static const u16 Unknown_0860B15C[] = {
+ 0x1020, 0x020e, 0x1010, 0x1043, 0x1e0f, 0x0c03, 0x181c, 0x1a24, 0x1816
+};
+
+static const u16 Unknown_0860B16E[] = {
+ 0x0446, 0x100b, 0x0620, 0x061c, 0x101b, 0x0c03, 0x0420, 0x0426, 0xffff
+};
+
+static const u16 Unknown_0860B180[] = {
+ 0x0400, 0x100b, 0x0639, 0x061c, 0x101b, 0x0c03, 0x040e, 0x0410, 0xffff
+};
+
+static const u16 Unknown_0860B192[] = {
+ 0x041f, 0x100b, 0x0639, 0x061c, 0x101b, 0x0c03, 0x0445, 0x0400, 0xffff
+};
+
+static const u16 *const gUnknown_0860B1A4[] = {
+ Unknown_0860B084,
+ Unknown_0860B096,
+ Unknown_0860B0A8,
+ Unknown_0860B0BA,
+ Unknown_0860B0CC,
+ Unknown_0860B0DE,
+ Unknown_0860B0F0,
+ Unknown_0860B102,
+ Unknown_0860B114,
+ Unknown_0860B126,
+ Unknown_0860B138,
+ Unknown_0860B14A,
+ Unknown_0860B15C,
+ Unknown_0860B16E,
+ Unknown_0860B180,
+ Unknown_0860B192
+};
+
+static const u16 gUnknown_0860B1E4[] = {
+ 0x0210, 0x0400, 0x0212, 0x1a26, 0x0208, 0x045d, 0x040a, 0x0411, 0x0464, 0x020e, 0x1a25, 0x181b, 0x1a24, 0x0420, 0x0410, 0x0400
+};
+
+static const u16 gUnknown_0860B204[] = {
+ 0x007b, 0x007f, 0x0081, 0x0023, 0x0023, 0x0023, 0x00a5, 0x00a7, 0x00a6, 0x000b, 0x012f, 0x006b, 0x006d, 0x0044, 0x0044, 0x000c
+};
+
+extern const u8 gUnknown_085EEB83[];
+extern const u8 gUnknown_085EEB8C[];
+extern const u8 gUnknown_085EEB95[];
+extern const u8 gUnknown_085EEB9E[];
+extern const u8 gUnknown_085EEBA4[];
+extern const u8 gUnknown_085EEBAB[];
+
+static const u8 *const gUnknown_0860B224[] = {
+ gUnknown_085EEB83,
+ gUnknown_085EEB8C,
+ gUnknown_085EEB95,
+ gUnknown_085EEB9E,
+ gUnknown_085EEBA4,
+ gUnknown_085EEBAB
+};
+
+static const u16 Unknown_0860B23C[] = {
+ 0x0056, 0x0053, 0x0054, 0x000e, 0x0012, 0x000f, 0x00a7, 0x0011, 0x0010, 0x0018, 0x0019, 0x001e, 0x0000
+};
+
+static const u16 Unknown_0860B256[] = {
+ 0x0051, 0x006a, 0x006b, 0x00cc, 0x00c2, 0x002f, 0x0067, 0x0068, 0x0087, 0x0089, 0x008b, 0x009d, 0x00a0, 0x00a5, 0x0004, 0x0002, 0x0000
+};
+
+static const u16 Unknown_0860B278[] = {
+ 0x0021, 0x000d, 0x001a, 0x001b, 0x001c, 0x00cc, 0x00ca, 0x0026, 0x0086, 0x0096, 0x0097, 0x009a, 0x00a2, 0x00a6, 0x0000
+};
+
+static const u16 Unknown_0860B296[] = {
+ 0x0020, 0x004d, 0x004b, 0x004c, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x006e, 0x005d, 0x006c, 0x006d, 0x006a, 0x006b, 0x00d6, 0x00bc, 0x00b3, 0x000b, 0x000c, 0x0000
+};
+
+static const u16 Unknown_0860B2C0[] = {
+ 0x001f, 0x0013, 0x0014, 0x004a, 0x004e, 0x0049, 0x00a5, 0x00c8, 0x0067, 0x006f, 0x0000
+};
+
+static const u16 Unknown_0860B2D6[] = {
+ 0x00b7, 0x00d3, 0x00d2, 0x00d8, 0x009e, 0x00a6, 0x00ab, 0x00aa, 0x006c, 0x006d, 0x0000
+};
+
+static const u16 *const gUnknown_0860B2EC[] = {
+ Unknown_0860B23C,
+ Unknown_0860B256,
+ Unknown_0860B278,
+ Unknown_0860B296,
+ Unknown_0860B2C0,
+ Unknown_0860B2D6
+};
+
+static const u16 gUnknown_0860B304[] = {
+ 0x0b, 0x6e, 0x40, 0x6f, 0x44, 0x47
+};
+
+extern const u8 gUnknown_085EEB2B[];
+extern const u8 gUnknown_085EEB34[];
+extern const u8 gUnknown_085EEB3A[];
+extern const u8 gUnknown_085EEB41[];
+extern const u8 gUnknown_085EEB4A[];
+extern const u8 gUnknown_085EEB51[];
+extern const u8 gUnknown_085EEB5A[];
+extern const u8 gUnknown_085EEB61[];
+extern const u8 gUnknown_085EEB6A[];
+extern const u8 gUnknown_085EEB74[];
+extern const u8 gUnknown_085EADA4[];
+extern const u8 gUnknown_085EADB5[];
+extern const u8 gUnknown_085EADC4[];
+extern const u8 gUnknown_085EADD5[];
+extern const u8 gUnknown_085EADE7[];
+
+static const u8 *const gUnknown_0860B310[] = {
+ gUnknown_085EEB2B,
+ gUnknown_085EEB34,
+ gUnknown_085EEB3A,
+ gUnknown_085EEB41,
+ gUnknown_085EEB4A
+};
+static const u8 *const gUnknown_0860B324[] = {
+ gUnknown_085EEB51,
+ gUnknown_085EEB5A,
+ gUnknown_085EEB61,
+ gUnknown_085EEB6A,
+ gUnknown_085EEB74
+};
+static const u8 *const gUnknown_0860B338[] = {
+ gUnknown_085EADA4,
+ gUnknown_085EADB5,
+ gUnknown_085EADC4,
+ gUnknown_085EADD5,
+ gUnknown_085EADE7
+};
+
+static const u16 gUnknown_0860B34C[] = {
+ 0x0120, 0x013b, 0x011e, 0x013d, 0x0019
+};
+
+static EWRAM_DATA struct LilycoveLadyFavour *gUnknown_0203CD64 = NULL;
+static EWRAM_DATA struct LilycoveLadyQuiz *gUnknown_0203CD68 = NULL;
+static EWRAM_DATA struct LilycoveLadyContest *gUnknown_0203CD6C = NULL;
+
+extern EWRAM_DATA u16 gScriptItemId;
+
+u8 GetLilycoveLadyId(void)
+{
+ return gSaveBlock1Ptr->lilycoveLady.id;
+}
+
+void sub_818D9C0(void)
+{
+ LilycoveLady *lilycoveLady;
+
+ VarSet(VAR_0x4010, gUnknown_0860B07E[GetLilycoveLadyId()]);
+ if (GetLilycoveLadyId() == LILYCOVE_LADY_CONTEST)
+ {
+ lilycoveLady = &gSaveBlock1Ptr->lilycoveLady;
+ VarSet(VAR_0x4011, gUnknown_0860B074[lilycoveLady->contest.category]);
+ gScriptResult = TRUE;
+ }
+ else
+ {
+ gScriptResult = FALSE;
+ }
+}
+
+void SetLilycoveLady(void)
+{
+ u16 id;
+
+ id = ((gSaveBlock2Ptr->playerTrainerId[1] << 8) | gSaveBlock2Ptr->playerTrainerId[0]);
+ id %= 6;
+ id >>= 1;
+ switch (id)
+ {
+ case LILYCOVE_LADY_QUIZ:
+ SetLilycoveQuizLady();
+ break;
+ case LILYCOVE_LADY_FAVOUR:
+ SetLilycoveFavourLady();
+ break;
+ case LILYCOVE_LADY_CONTEST:
+ SetLilycoveContestLady();
+ break;
+ }
+}
+
+void sub_818DA78(void)
+{
+ switch (GetLilycoveLadyId())
+ {
+ case LILYCOVE_LADY_QUIZ:
+ sub_818E004();
+ break;
+ case LILYCOVE_LADY_FAVOUR:
+ sub_818DBC4();
+ break;
+ case LILYCOVE_LADY_CONTEST:
+ sub_818E674();
+ break;
+ }
+}
+
+void SetLilycoveLadyRandomly(void)
+{
+ u8 id;
+
+ id = Random() % 3;
+ switch (id)
+ {
+ case LILYCOVE_LADY_QUIZ:
+ SetLilycoveQuizLady();
+ break;
+ case LILYCOVE_LADY_FAVOUR:
+ SetLilycoveFavourLady();
+ break;
+ case LILYCOVE_LADY_CONTEST:
+ SetLilycoveContestLady();
+ break;
+ }
+}
+
+void sub_818DAEC(void)
+{
+ gScriptResult = GetLilycoveLadyId();
+}
+
+static u8 sub_818DB04(const u16 *data)
+{
+ u8 len;
+
+ for (len = 0; *data != 0; len ++, data ++);
+ return len;
+}
+
+static void sub_818DB20(void)
+{
+ u8 size;
+ u8 idx;
+
+ gUnknown_0203CD64->unk_00c = Random() % 6;
+ size = sub_818DB04(gUnknown_0860B2EC[gUnknown_0203CD64->unk_00c]);
+ idx = Random() % size;
+ gUnknown_0203CD64->unk_010 = gUnknown_0860B2EC[gUnknown_0203CD64->unk_00c][idx];
+}
+
+static void SetLilycoveFavourLady(void)
+{
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ gUnknown_0203CD64->id = LILYCOVE_LADY_FAVOUR;
+ gUnknown_0203CD64->phase = 0;
+ gUnknown_0203CD64->playerName[0] = EOS;
+ gUnknown_0203CD64->unk_002 = 0;
+ gUnknown_0203CD64->unk_003= 0;
+ gUnknown_0203CD64->itemId = ITEM_NONE;
+ gUnknown_0203CD64->language = gGameLanguage;
+ sub_818DB20();
+}
+
+static void sub_818DBC4(void)
+{
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ gUnknown_0203CD64->id = LILYCOVE_LADY_FAVOUR;
+ gUnknown_0203CD64->phase = 0;
+}
+
+u8 sub_818DBE8(void)
+{
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ if (gUnknown_0203CD64->phase == 2)
+ {
+ return 2;
+ }
+ else if (gUnknown_0203CD64->phase == 1)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static const u8 *sub_818DC1C(u8 idx)
+{
+ return gUnknown_0860B224[idx];
+}
+
+void sub_818DC2C(void)
+{
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ StringCopy(gStringVar1, sub_818DC1C(gUnknown_0203CD64->unk_00c));
+}
+
+bool8 sub_818DC60(void)
+{
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ if (gUnknown_0203CD64->playerName[0] != EOS)
+ {
+ StringCopy7(gStringVar3, gUnknown_0203CD64->playerName);
+ ConvertInternationalString(gStringVar3, gUnknown_0203CD64->language);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void sub_818DCAC(u8 *dest, u16 itemId)
+{
+ StringCopy(dest, ItemId_GetItem(itemId)->name);
+}
+
+void sub_818DCC8(void)
+{
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ sub_818DCAC(gStringVar2, gUnknown_0203CD64->itemId);
+}
+
+static void sub_818DCF4(const u8 *src, u8 *dest)
+{
+ memset(dest, 0xFF, 8);
+ StringCopy7(dest, src);
+}
+
+void sub_818DD14(void)
+{
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ sub_818DCF4(gUnknown_0203CD64->playerName, gStringVar3);
+ ConvertInternationalString(gStringVar3, gUnknown_0203CD64->language);
+}
+
+bool8 sub_818DD54(void)
+{
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ return gUnknown_0203CD64->unk_002 ? TRUE : FALSE;
+}
+
+void sub_818DD78(void)
+{
+ sub_81AAC50();
+}
+
+static bool8 sub_818DD84(u16 itemId)
+{
+ u8 len;
+ u8 i;
+ bool8 response;
+
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ len = sub_818DB04(gUnknown_0860B2EC[gUnknown_0203CD64->unk_00c]);
+ gUnknown_0203CD64->phase = 1;
+ sub_818DCAC(gStringVar2, itemId);
+ gUnknown_0203CD64->itemId = itemId;
+ sub_818DCF4(gSaveBlock2Ptr->playerName, gUnknown_0203CD64->playerName);
+ gUnknown_0203CD64->language = gGameLanguage;
+ response = FALSE;
+ for (i = 0; i < len; i ++)
+ {
+ if (gUnknown_0860B2EC[gUnknown_0203CD64->unk_00c][i] == itemId)
+ {
+ response = TRUE;
+ gUnknown_0203CD64->unk_003 ++;
+ gUnknown_0203CD64->unk_002 = 1;
+ if (gUnknown_0203CD64->unk_010 == itemId)
+ {
+ gUnknown_0203CD64->unk_003 = 5;
+ }
+ break;
+ }
+ gUnknown_0203CD64->unk_002 = 0;
+ }
+ return response;
+}
+
+bool8 sub_818DE44(void)
+{
+ return sub_818DD84(gScriptItemId);
+}
+
+bool8 sub_818DE5C(void)
+{
+ u8 checkval;
+
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ checkval = gUnknown_0203CD64->unk_003;
+ return checkval < 5 ? FALSE : TRUE;
+}
+
+static void sub_818DE88(u16 itemId)
+{
+ sub_818DCAC(gStringVar2, itemId);
+}
+
+u16 sub_818DEA0(void)
+{
+ u16 itemId;
+
+ gUnknown_0203CD64 = &gSaveBlock1Ptr->lilycoveLady.favour;
+ itemId = gUnknown_0860B304[gUnknown_0203CD64->unk_00c];
+ sub_818DE88(itemId);
+ gUnknown_0203CD64->phase = 2;
+ return itemId;
+}
+
+void sub_818DEDC(void)
+{
+ SetLilycoveFavourLady();
+ gUnknown_0203CD64->phase = 1;
+}
+
+void sub_818DEF4(void)
+{
+ EnableBothScriptContexts();
+}
+
+static void sub_818DF00(void)
+{
+ u8 v0;
+ u8 i;
+
+ v0 = Random() % 16;
+ for (i = 0; i < 9; i ++)
+ {
+ gUnknown_0203CD68->unk_002[i] = gUnknown_0860B1A4[v0][i];
+ }
+ gUnknown_0203CD68->unk_014 = gUnknown_0860B1E4[v0];
+ gUnknown_0203CD68->itemId = gUnknown_0860B204[v0];
+ gUnknown_0203CD68->unk_02b = v0;
+ gUnknown_0203CD68->playerName[0] = EOS;
+}
+
+static void SetLilycoveQuizLady(void)
+{
+ u8 i;
+
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ gUnknown_0203CD68->id = LILYCOVE_LADY_QUIZ;
+ gUnknown_0203CD68->phase = 0;
+ for (i = 0; i < 9; i ++)
+ {
+ gUnknown_0203CD68->unk_002[i] = -1;
+ }
+ gUnknown_0203CD68->unk_014 = -1;
+ gUnknown_0203CD68->unk_016 = -1;
+ for (i = 0; i < 4; i ++)
+ {
+ gUnknown_0203CD68->playerTrainerId[i] = 0;
+ }
+ gUnknown_0203CD68->itemId = ITEM_NONE;
+ gUnknown_0203CD68->unk_02a = 0;
+ gUnknown_0203CD68->unk_02c = 0x10;
+ gUnknown_0203CD68->language = gGameLanguage;
+ sub_818DF00();
+}
+
+static void sub_818E004(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ gUnknown_0203CD68->id = LILYCOVE_LADY_QUIZ;
+ gUnknown_0203CD68->phase = 0;
+ gUnknown_0203CD68->unk_02a = 0;
+ gUnknown_0203CD68->unk_016 = -1;
+}
+
+u8 sub_818E038(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ if (gUnknown_0203CD68->phase == 2)
+ {
+ return 2;
+ }
+ else if (gUnknown_0203CD68->phase == 1)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+u8 sub_818E06C(void)
+{
+ int i;
+ int j;
+ u8 rv;
+ struct LilycoveLadyQuiz *quiz;
+
+ quiz = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ if (sub_811F8D8(quiz->unk_014) == 0)
+ {
+ i = quiz->unk_02b;
+ do
+ {
+ if (++ i >= 16)
+ {
+ i = 0;
+ }
+ } while (sub_811F8D8(gUnknown_0860B1E4[i]) == 0);
+ for (j = 0; j < 9; j ++)
+ {
+ quiz->unk_002[j] = gUnknown_0860B1A4[i][j];
+ }
+ quiz->unk_014 = gUnknown_0860B1E4[i];
+ quiz->itemId = gUnknown_0860B204[i];
+ quiz->unk_02b = i;
+ quiz->playerName[0] = EOS;
+ }
+ rv = sub_818E13C();
+ if (rv == 0)
+ {
+ return 2;
+ }
+ else if (rv == 2 || sub_818E1F4())
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+#ifdef NONMATCHING
+static u8 sub_818E13C(void)
+{
+ u8 retval;
+ u8 len;
+ u8 i;
+
+ retval = 1;
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ if (gUnknown_0203CD68->playerName[0] == EOS)
+ {
+ StringCopy7(gStringVar1, gText_Lady2);
+ retval = 0;
+ }
+ else
+ {
+ StringCopy7(gStringVar1, gUnknown_0203CD68->playerName);
+ ConvertInternationalString(gStringVar1, gUnknown_0203CD68->language);
+ len = sub_818E258(gUnknown_0203CD68->playerName);
+ if (len == sub_818E258(gSaveBlock2Ptr->playerName))
+ {
+ for (i = 0; i < len; i ++)
+ {
+ if (gUnknown_0203CD68->playerName[i] != gSaveBlock2Ptr->playerName[i])
+ {
+ retval = 2;
+ break;
+ }
+ }
+ }
+
+ }
+ return retval;
+}
+#else
+__attribute__((naked)) static u8 sub_818E13C(void)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmovs r7, 0x1\n"
+ "\tldr r5, =gUnknown_0203CD68\n"
+ "\tldr r0, =gSaveBlock1Ptr\n"
+ "\tldr r1, [r0]\n"
+ "\tldr r2, =0x00003b58\n"
+ "\tadds r0, r1, r2\n"
+ "\tstr r0, [r5]\n"
+ "\tldrb r0, [r0, 0x18]\n"
+ "\tcmp r0, 0xFF\n"
+ "\tbne _0818E174\n"
+ "\tldr r0, =gStringVar1\n"
+ "\tldr r1, =gText_Lady2\n"
+ "\tbl StringCopy7\n"
+ "\tmovs r7, 0\n"
+ "\tb _0818E1DC\n"
+ "\t.pool\n"
+ "_0818E174:\n"
+ "\tldr r4, =gStringVar1\n"
+ "\tldr r0, =0x00003b70\n"
+ "\tadds r1, r0\n"
+ "\tadds r0, r4, 0\n"
+ "\tbl StringCopy7\n"
+ "\tldr r0, [r5]\n"
+ "\tadds r0, 0x2D\n"
+ "\tldrb r1, [r0]\n"
+ "\tadds r0, r4, 0\n"
+ "\tbl ConvertInternationalString\n"
+ "\tldr r0, [r5]\n"
+ "\tadds r0, 0x18\n"
+ "\tbl sub_818E258\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r4, r0, 24\n"
+ "\tldr r6, =gSaveBlock2Ptr\n"
+ "\tldr r0, [r6]\n"
+ "\tbl sub_818E258\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r0, 24\n"
+ "\tcmp r4, r0\n"
+ "\tbne _0818E1DC\n"
+ "\tldr r0, [r5]\n"
+ "\tmovs r2, 0\n"
+ "\tcmp r2, r4\n"
+ "\tbcs _0818E1DC\n"
+ "\tldr r1, [r6]\n"
+ "\tldrb r0, [r0, 0x18]\n"
+ "\tldrb r1, [r1]\n"
+ "\tcmp r0, r1\n"
+ "\tbne _0818E1DA\n"
+ "_0818E1BA:\n"
+ "\tadds r0, r2, 0x1\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r2, r0, 24\n"
+ "\tcmp r2, r4\n"
+ "\tbcs _0818E1DC\n"
+ "\tldr r0, =gUnknown_0203CD68\n"
+ "\tldr r1, [r0]\n"
+ "\tadds r1, 0x18\n"
+ "\tadds r1, r2\n"
+ "\tldr r0, =gSaveBlock2Ptr\n"
+ "\tldr r0, [r0]\n"
+ "\tadds r0, r2\n"
+ "\tldrb r1, [r1]\n"
+ "\tldrb r0, [r0]\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _0818E1BA\n"
+ "_0818E1DA:\n"
+ "\tmovs r7, 0x2\n"
+ "_0818E1DC:\n"
+ "\tadds r0, r7, 0\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r1}\n"
+ "\tbx r1\n"
+ "\t.pool");
+}
+#endif
+
+static u8 sub_818E1F4(void)
+{
+ bool8 response;
+ u8 i;
+
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ response = FALSE;
+ for (i = 0; i < 4; i ++)
+ {
+ if (gUnknown_0203CD68->playerTrainerId[i] != gSaveBlock2Ptr->playerTrainerId[i])
+ {
+ response = TRUE;
+ break;
+ }
+ }
+ return response;
+}
+
+static u8 sub_818E258(const u8 *str)
+{
+ u8 len;
+ const u8 *ptr;
+
+ for (len = 0, ptr = str; *ptr != EOS; len ++, ptr ++);
+ return len;
+}
+
+void sub_818E274(void)
+{
+ StringCopy(gStringVar1, ItemId_GetItem(gUnknown_0203CD68->itemId)->name);
+}
+
+bool8 sub_818E298(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ if (!sub_818E13C())
+ {
+ gUnknown_0203CD68->language = gGameLanguage;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+u8 sub_818E2D8(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ return gUnknown_0203CD68->unk_02a;
+}
+
+void sub_818E2FC(void)
+{
+ easy_chat_input_maybe();
+}
+
+bool8 sub_818E308(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ CopyEasyChatWord(gStringVar1, gUnknown_0203CD68->unk_014);
+ CopyEasyChatWord(gStringVar2, gUnknown_0203CD68->unk_016);
+ return StringCompare(gStringVar1, gStringVar2) ? FALSE : TRUE;
+}
+
+void sub_818E358(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ gSpecialVar_0x8005 = gUnknown_0203CD68->itemId;
+}
+
+void sub_818E37C(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ gUnknown_0203CD68->phase = 1;
+}
+
+void sub_818E39C(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ gUnknown_0203CD68->phase = 2;
+}
+
+void sub_818E3BC(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ gUnknown_0203CD68->unk_016 = -1;
+}
+
+void sub_818E3E0(void)
+{
+ sub_81AAC70();
+}
+
+void sub_818E3EC(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ if (sub_818E298())
+ {
+ gUnknown_0203CD68->unk_02c = gUnknown_0203CD68->unk_02b;
+ }
+ else
+ {
+ gUnknown_0203CD68->unk_02c = 0x10;
+ }
+ sub_818DF00();
+}
+
+void sub_818E430(void)
+{
+ u8 i;
+
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ for (i = 0; i < 9; i ++)
+ {
+ gUnknown_0203CD68->unk_002[i] = -1;
+ }
+ gUnknown_0203CD68->unk_014 = -1;
+}
+
+void sub_818E47C(void)
+{
+ gSpecialVar_0x8004 = 0x11;
+ easy_chat_input_maybe();
+}
+
+void sub_818E490(void)
+{
+ RemoveBagItem(gScriptItemId, 1);
+}
+
+void sub_818E4A4(void)
+{
+ u8 i;
+
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ gUnknown_0203CD68->itemId = gScriptItemId;
+ for (i = 0; i < 4; i ++)
+ {
+ gUnknown_0203CD68->playerTrainerId[i] = gSaveBlock2Ptr->playerTrainerId[i];
+ }
+ StringCopy7(gUnknown_0203CD68->playerName, gSaveBlock2Ptr->playerName);
+ gUnknown_0203CD68->language = gGameLanguage;
+}
+
+void sub_818E510(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ gUnknown_0203CD68->unk_02a = 1;
+}
+
+void sub_818E538(void)
+{
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ CopyEasyChatWord(gStringVar3, gUnknown_0203CD68->unk_014);
+}
+
+void sub_818E564(void)
+{
+ EnableBothScriptContexts();
+}
+
+void sub_818E570(const struct LilycoveLadyQuiz *quiz)
+{
+ u8 i;
+
+ gUnknown_0203CD68 = &gSaveBlock1Ptr->lilycoveLady.quiz;
+ if (quiz->unk_02c < 16 && gUnknown_0203CD68->id == LILYCOVE_LADY_QUIZ)
+ {
+ for (i = 0; i < 4; i ++)
+ {
+ if (quiz->unk_02c != gUnknown_0203CD68->unk_02b)
+ {
+ break;
+ }
+ gUnknown_0203CD68->unk_02b = Random() % 16;
+ }
+ if (quiz->unk_02c == gUnknown_0203CD68->unk_02b)
+ {
+ gUnknown_0203CD68->unk_02b = (gUnknown_0203CD68->unk_02b + 1) % 16;
+ }
+ gUnknown_0203CD68->unk_02c = quiz->unk_02c;
+ }
+}
+
+static void sub_818E604(void)
+{
+ gUnknown_0203CD6C->playerName[0] = EOS;
+ gUnknown_0203CD6C->fave_pkblk = 0;
+ gUnknown_0203CD6C->other_pkblk = 0;
+ gUnknown_0203CD6C->max_sheen = 0;
+ gUnknown_0203CD6C->category = Random() % 5;
+}
+
+static void SetLilycoveContestLady(void)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ gUnknown_0203CD6C->id = LILYCOVE_LADY_CONTEST;
+ gUnknown_0203CD6C->phase = 0;
+ sub_818E604();
+ gUnknown_0203CD6C->language = gGameLanguage;
+}
+
+static void sub_818E674(void)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ gUnknown_0203CD6C->id = LILYCOVE_LADY_CONTEST;
+ gUnknown_0203CD6C->phase = 0;
+ if (gUnknown_0203CD6C->fave_pkblk == 5 || gUnknown_0203CD6C->other_pkblk == 5)
+ {
+ sub_818E604();
+ }
+}
+
+static void sub_818E6B0(u8 sheen)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ if (gUnknown_0203CD6C->max_sheen <= sheen)
+ {
+ gUnknown_0203CD6C->max_sheen = sheen;
+ memset(gUnknown_0203CD6C->playerName, EOS, sizeof(gUnknown_0203CD6C->playerName));
+ memcpy(gUnknown_0203CD6C->playerName, gSaveBlock2Ptr->playerName, sizeof(gUnknown_0203CD6C->playerName));
+ gUnknown_0203CD6C->language = gGameLanguage;
+ }
+}
+
+bool8 sub_818E704(struct Pokeblock *pokeblock)
+{
+ u8 sheen;
+ bool8 response;
+
+ sheen = 0;
+ response = FALSE;
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ switch (gUnknown_0203CD6C->category)
+ {
+ case 0:
+ if (pokeblock->spicy != 0)
+ {
+ sheen = pokeblock->spicy;
+ response = TRUE;
+ }
+ break;
+ case 1:
+ if (pokeblock->dry != 0)
+ {
+ sheen = pokeblock->dry;
+ response = TRUE;
+ }
+ break;
+ case 2:
+ if (pokeblock->sweet != 0)
+ {
+ sheen = pokeblock->sweet;
+ response = TRUE;
+ }
+ break;
+ case 3:
+ if (pokeblock->bitter != 0)
+ {
+ sheen = pokeblock->bitter;
+ response = TRUE;
+ }
+ break;
+ case 4:
+ if (pokeblock->sour != 0)
+ {
+ sheen = pokeblock->sour;
+ response = TRUE;
+ }
+ break;
+ }
+ if (response == TRUE)
+ {
+ sub_818E6B0(sheen);
+ gUnknown_0203CD6C->fave_pkblk ++;
+ }
+ else
+ {
+ gUnknown_0203CD6C->other_pkblk ++;
+ }
+ return response;
+}
+
+static void sub_818E794(u8 *dest1, u8 *dest2)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ StringCopy(dest1, gUnknown_0860B324[gUnknown_0203CD6C->category]);
+ StringCopy10(dest2, gUnknown_0860B310[gUnknown_0203CD6C->category]);
+}
+
+void sub_818E7E0(u8 *dest1, u8 *dest2)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ *dest1 = gUnknown_0203CD6C->category;
+ StringCopy(dest2, gUnknown_0860B310[gUnknown_0203CD6C->category]);
+}
+
+void sub_818E81C(u8 *dest)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ StringCopy(dest, gUnknown_0203CD6C->playerName);
+}
+
+void sub_818E848(u8 *dest)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ *dest = gUnknown_0203CD6C->language;
+}
+
+void sub_818E868(u8 *dest, u8 category)
+{
+ StringCopy(dest, gUnknown_0860B338[category]);
+}
+
+u8 sub_818E880(void)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ if (gUnknown_0203CD6C->fave_pkblk >= 5)
+ {
+ return 1;
+ }
+ else if (gUnknown_0203CD6C->fave_pkblk == 0)
+ {
+ return 2;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+bool8 sub_818E8B4(void)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ if (gUnknown_0203CD6C->phase == 1)
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 sub_818E8E0(void)
+{
+ bool8 response;
+
+ response = FALSE;
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ if (gUnknown_0203CD6C->fave_pkblk >= 5 || gUnknown_0203CD6C->other_pkblk >= 5)
+ {
+ response = TRUE;
+ }
+ return response;
+}
+
+void sub_818E914(void)
+{
+ sub_818E794(gStringVar2, gStringVar1);
+}
+
+void sub_818E92C(void)
+{
+ sub_81357FC(3, c2_exit_to_overworld_2_switch);
+}
+
+void sub_818E940(void)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ gUnknown_0203CD6C->phase = 1;
+}
+
+void sub_818E960(void)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ gSpecialVar_0x8005 = gUnknown_0860B34C[gUnknown_0203CD6C->category];
+}
+
+u8 sub_818E990(void)
+{
+ gUnknown_0203CD6C = &gSaveBlock1Ptr->lilycoveLady.contest;
+ return gUnknown_0203CD6C->category;
+}
diff --git a/src/link.c b/src/link.c
new file mode 100644
index 000000000..ae2cd1992
--- /dev/null
+++ b/src/link.c
@@ -0,0 +1,56 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+struct BlockTransfer
+{
+ u16 pos;
+ u16 size;
+ void *src;
+ bool8 active;
+ u8 multiplayerId;
+};
+
+struct LinkTestBGInfo
+{
+ u32 screenBaseBlock;
+ u32 paletteNum;
+ u32 dummy_8;
+ u32 dummy_C;
+};
+
+// Static RAM declarations
+
+IWRAM_DATA struct BlockTransfer gUnknown_03000D10;
+IWRAM_DATA u32 link_c_unused_03000d1c;
+IWRAM_DATA struct BlockTransfer gUnknown_03000D20[4];
+IWRAM_DATA u32 gUnknown_03000D50;
+IWRAM_DATA u32 gUnknown_03000D54;
+IWRAM_DATA u8 gUnknown_03000D58;
+IWRAM_DATA u32 gUnknown_03000D5C;
+IWRAM_DATA u32 gUnknown_03000D60;
+IWRAM_DATA u8 gUnknown_03000D64[4]; // not really, but won't match otherwise
+IWRAM_DATA u8 gUnknown_03000D68[4];
+IWRAM_DATA u8 gUnknown_03000D6C;
+IWRAM_DATA bool8 gUnknown_03000D6D;
+IWRAM_DATA u16 gUnknown_03000D6E;
+IWRAM_DATA u16 gUnknown_03000D70;
+IWRAM_DATA u8 gUnknown_03000D72;
+IWRAM_DATA u8 gUnknown_03000D73;
+IWRAM_DATA u8 gUnknown_03000D74[4]; // not really, but won't match otherwise
+IWRAM_DATA u8 gUnknown_03000D78[8]; // not really, but won't match otherwise
+IWRAM_DATA u8 gUnknown_03000D80[16];
+IWRAM_DATA u16 gUnknown_03000D90[8];
+IWRAM_DATA u32 gUnknown_03000DA0;
+IWRAM_DATA u32 gUnknown_03000DA4;
+IWRAM_DATA void *gUnknown_03000DA8;
+IWRAM_DATA void *gUnknown_03000DAC;
+IWRAM_DATA bool32 gUnknown_03000DB0;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/load_save.c b/src/load_save.c
index 588387186..68d978e3d 100644
--- a/src/load_save.c
+++ b/src/load_save.c
@@ -6,15 +6,11 @@
#include "rng.h"
#include "malloc.h"
-extern u8 gPlayerPartyCount;
-extern struct PokemonStorage* gPokemonStoragePtr;
extern void* gUnknown_0203CF5C;
-extern u8 gHeap[0x1C000];
extern bool16 IdentifyFlash(void);
extern void SetBagItemsPointers(void);
extern void SetDecorationInventoriesPointers(void);
-extern void InitHeap(void *heapStart, u32 heapSize);
void ApplyNewEncyprtionKeyToAllEncryptedData(u32 encryptionKey);
diff --git a/src/main.c b/src/main.c
index 5707e18af..665a4dd84 100644
--- a/src/main.c
+++ b/src/main.c
@@ -77,7 +77,7 @@ const IntrFunc gIntrTableTemplate[] =
#define INTR_COUNT ((int)(sizeof(gIntrTableTemplate)/sizeof(IntrFunc)))
-extern u16 gUnknown_03000000;
+static u16 gUnknown_03000000;
extern u16 gKeyRepeatStartDelay;
extern u8 gUnknown_030022B4;
diff --git a/src/main_menu.c b/src/main_menu.c
new file mode 100644
index 000000000..8608159c2
--- /dev/null
+++ b/src/main_menu.c
@@ -0,0 +1,15 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03000DD0;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/malloc.c b/src/malloc.c
index 3901c5a35..1d64351c3 100644
--- a/src/malloc.c
+++ b/src/malloc.c
@@ -2,6 +2,7 @@
static void *sHeapStart;
static u32 sHeapSize;
+static u32 malloc_c_unused_0300000c; // needed to align dma3_manager.o(.bss)
#define MALLOC_SYSTEM_ID 0xA3A3
@@ -38,7 +39,7 @@ void PutMemBlockHeader(void *block, struct MemBlock *prev, struct MemBlock *next
void PutFirstMemBlockHeader(void *block, u32 size)
{
- PutMemBlockHeader(block, (struct MemBlock *)block, (struct MemBlock *)block, size - 16);
+ PutMemBlockHeader(block, (struct MemBlock *)block, (struct MemBlock *)block, size - sizeof(struct MemBlock));
}
void *AllocInternal(void *heapStart, u32 size)
@@ -48,6 +49,7 @@ void *AllocInternal(void *heapStart, u32 size)
struct MemBlock *splitBlock;
u32 foundBlockSize;
+ // Alignment
if (size & 3)
size = 4 * ((size / 4) + 1);
@@ -58,7 +60,7 @@ void *AllocInternal(void *heapStart, u32 size)
foundBlockSize = pos->size;
if (foundBlockSize >= size) {
- if (foundBlockSize - size <= 31) {
+ if (foundBlockSize - size < 2 * sizeof(struct MemBlock)) {
// The block isn't much bigger than the requested size,
// so just use it.
pos->flag = TRUE;
diff --git a/src/metatile_behavior.c b/src/metatile_behavior.c
new file mode 100644
index 000000000..b9760f522
--- /dev/null
+++ b/src/metatile_behavior.c
@@ -0,0 +1,1436 @@
+#include "global.h"
+#include "metatile_behavior.h"
+#include "metatile_behaviors.h"
+
+#define TILE_FLAG_ENCOUNTER_TILE 1
+#define TILE_FLAG_SURFABLE 2
+
+#define TILE_ATTRIBUTES(three, two, one) (((one) ? 1 : 0) | ((two) ? 2 : 0) | ((three) ? 4 : 0))
+
+// wonder what the third flag is supposed to do
+static const u8 sTileBitAttributes[] =
+{
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_NORMAL 0x00
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x01
+ TILE_ATTRIBUTES(TRUE, FALSE, TRUE), // MB_TALL_GRASS 0x02
+ TILE_ATTRIBUTES(TRUE, FALSE, TRUE), // MB_LONG_GRASS 0x03
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_04 0x04
+ TILE_ATTRIBUTES(FALSE, FALSE, TRUE), // MB_05 0x05
+ TILE_ATTRIBUTES(TRUE, FALSE, TRUE), // MB_DEEP_SAND 0x06
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SHORT_GRASS 0x07
+ TILE_ATTRIBUTES(TRUE, FALSE, TRUE), // MB_CAVE 0x08
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_LONG_GRASS_SOUTH_EDGE 0x09
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_NO_RUNNING 0x0A
+ TILE_ATTRIBUTES(TRUE, FALSE, TRUE), // MB_0B 0x0B
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_MOUNTAIN_TOP 0x0C
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_BATTLE_PYRAMID_WARP 0x0D
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_MOSSDEEP_GYM_WARP 0x0E
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_MT_PYRE_HOLE 0x0F
+ TILE_ATTRIBUTES(TRUE, TRUE, TRUE), // MB_POND_WATER 0x10
+ TILE_ATTRIBUTES(TRUE, TRUE, TRUE), // MB_SEMI_DEEP_WATER 0x11
+ TILE_ATTRIBUTES(TRUE, TRUE, TRUE), // MB_DEEP_WATER 0x12
+ TILE_ATTRIBUTES(TRUE, TRUE, FALSE), // MB_WATERFALL 0x13
+ TILE_ATTRIBUTES(TRUE, TRUE, FALSE), // MB_SOOTOPOLIS_DEEP_WATER 0x14
+ TILE_ATTRIBUTES(TRUE, TRUE, TRUE), // MB_OCEAN_WATER 0x15
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_PUDDLE 0x16
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SHALLOW_WATER 0x17
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_18 0x18
+ TILE_ATTRIBUTES(TRUE, TRUE, FALSE), // MB_NO_SURFACING 0x19
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_1A 0x1A
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_STAIRS_OUTSIDE_ABANDONED_SHIP 0x1B
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SHOAL_CAVE_ENTRANCE 0x1C
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x1D
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x1E
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x1F
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ICE 0x20
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SAND 0x21
+ TILE_ATTRIBUTES(TRUE, TRUE, TRUE), // MB_SEAWEED 0x22
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // ? 0x23
+ TILE_ATTRIBUTES(TRUE, FALSE, TRUE), // MB_ASHGRASS 0x24
+ TILE_ATTRIBUTES(TRUE, FALSE, TRUE), // MB_25 0x25
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_THIN_ICE 0x26
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_CRACKED_ICE 0x27
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_HOT_SPRINGS 0x28
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_LAVARIDGE_GYM_B1F_WARP 0x29
+ TILE_ATTRIBUTES(TRUE, TRUE, TRUE), // MB_SEAWEED_NO_SURFACING 0x2A
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_REFLECTION_UNDER_BRIDGE 0x2B
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x2C
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x2D
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x2E
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x2F
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_IMPASSABLE_EAST 0x30
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_IMPASSABLE_WEST 0x31
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_IMPASSABLE_NORTH 0x32
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_IMPASSABLE_SOUTH 0x33
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_IMPASSABLE_NORTHEAST 0x34
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_IMPASSABLE_NORTHWEST 0x35
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_IMPASSABLE_SOUTHEAST 0x36
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_IMPASSABLE_SOUTHWEST 0x37
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_JUMP_EAST 0x38
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_JUMP_WEST 0x39
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_JUMP_NORTH 0x3A
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_JUMP_SOUTH 0x3B
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // ? 0x3C
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // ? 0x3D
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_JUMP_SOUTHEAST 0x3E
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_JUMP_SOUTHWEST 0x3F
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_WALK_EAST 0x40
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_WALK_WEST 0x41
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_WALK_NORTH 0x42
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_WALK_SOUTH 0x43
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SLIDE_EAST 0x44
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SLIDE_WEST 0x45
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SLIDE_NORTH 0x46
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SLIDE_SOUTH 0x47
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_TRICK_HOUSE_PUZZLE_8_FLOOR 0x48
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // ? 0x49
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // ? 0x4A
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x4B
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x4C
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x4D
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x4E
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x4F
+ TILE_ATTRIBUTES(TRUE, TRUE, FALSE), // MB_EASTWARD_CURRENT 0x50
+ TILE_ATTRIBUTES(TRUE, TRUE, FALSE), // MB_WESTWARD_CURRENT 0x51
+ TILE_ATTRIBUTES(TRUE, TRUE, FALSE), // MB_NORTHWARD_CURRENT 0x52
+ TILE_ATTRIBUTES(TRUE, TRUE, FALSE), // MB_SOUTHWARD_CURRENT 0x53
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x54
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x55
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x56
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x57
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x58
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x59
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x5A
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x5B
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x5C
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x5D
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x5E
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x5F
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_NON_ANIMATED_DOOR 0x60
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_LADDER 0x61
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_EAST_ARROW_WARP 0x62
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_WEST_ARROW_WARP 0x63
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_NORTH_ARROW_WARP 0x64
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SOUTH_ARROW_WARP 0x65
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_CRACKED_FLOOR_HOLE 0x66
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_AQUA_HIDEOUT_WARP 0x67
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_LAVARIDGE_GYM_1F_WARP 0x68
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ANIMATED_DOOR 0x69
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_UP_ESCALATOR 0x6A
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_DOWN_ESCALATOR 0x6B
+ TILE_ATTRIBUTES(TRUE, TRUE, FALSE), // MB_WATER_DOOR 0x6C
+ TILE_ATTRIBUTES(TRUE, TRUE, FALSE), // MB_WATER_SOUTH_ARROW_WARP 0x6D
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_DEEP_SOUTH_WARP 0x6E
+ TILE_ATTRIBUTES(TRUE, TRUE, FALSE), // ? 0x6F
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_WARP_OR_BRIDGE 0x70
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_71 0x71
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ROUTE120_NORTH_BRIDGE_1 0x72
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ROUTE120_NORTH_BRIDGE_2 0x73
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_PACIFIDLOG_VERTICAL_LOG_1 0x74
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_PACIFIDLOG_VERTICAL_LOG_2 0x75
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_PACIFIDLOG_HORIZONTAL_LOG_1 0x76
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_PACIFIDLOG_HORIZONTAL_LOG_2 0x77
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_FORTREE_BRIDGE 0x78
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x79
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ROUTE120_SOUTH_BRIDGE_1 0x7A
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ROUTE120_SOUTH_BRIDGE_2 0x7B
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ROUTE120_NORTH_BRIDGE_3 0x7C
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ROUTE120_NORTH_BRIDGE_4 0x7D
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_7E 0x7E
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ROUTE110_BRIDGE 0x7F
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_COUNTER 0x80
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x81
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x82
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_PC 0x83
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_CABLE_BOX_RESULTS_1 0x84
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_REGION_MAP 0x85
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_TELEVISION 0x86
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_POKEBLOCK_FEEDER 0x87
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x88
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SLOT_MACHINE 0x89
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_ROULETTE 0x8A
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_CLOSED_SOOTOPOLIS_GYM_DOOR 0x8B
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_TRICK_HOUSE_PUZZLE_DOOR 0x8C
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_8D 0x8D
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_RUNNING_SHOES_INSTRUCTION 0x8E
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_QUESTIONNAIRE 0x8F
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_RED_CAVE 0x90
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_RED_CAVE_OPEN 0x91
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_BROWN_CAVE 0x92
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_BROWN_CAVE_OPEN 0x93
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_YELLOW_CAVE 0x94
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_YELLOW_CAVE_OPEN 0x95
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_TREE_LEFT 0x96
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_TREE_LEFT_OPEN 0x97
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_SHRUB 0x98
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_SHRUB_OPEN 0x99
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_BLUE_CAVE 0x9A
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_BLUE_CAVE_OPEN 0x9B
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_TREE_RIGHT 0x9C
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_SPOT_TREE_RIGHT_OPEN 0x9D
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x9E
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0x9F
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_BERRY_TREE_SOIL 0xA0
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xA1
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xA2
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xA3
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xA4
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xA5
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xA6
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xA7
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xA8
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xA9
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xAA
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xAB
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xAC
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xAD
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xAE
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xAF A
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_PC 0xB0
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_REGISTER_PC 0xB1
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_B2 0xB2
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_B3 0xB3
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_B4 0xB4
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_B5 0xB5
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_B6 0xB6
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_B7 0xB7
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SECRET_BASE_BALLOON 0xB8
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_B9 0xB9
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SECRET_BASE_GLITTER_MAT 0xBA
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SECRET_BASE_JUMP_MAT 0xBB
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SECRET_BASE_SPIN_MAT 0xBC
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SECRET_BASE_SOUND_MAT 0xBD
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_BE 0xBE
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_BF 0xBF
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_BED 0xC0
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_C1 0xC1
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_C2 0xC2
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_C3 0xC3
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_SECRET_BASE_TV_SHIELD 0xC4
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_C5 0xC5
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_C6 0xC6
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SECRET_BASE_POSTER 0xC7
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_C8 0xC8
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_C9 0xC9
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_CA 0xCA
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_CB 0xCB
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_CC 0xCC
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_CD 0xCD
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_CE 0xCE
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_CF 0xCF
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_MUDDY_SLOPE 0xD0
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_BUMPY_SLOPE 0xD1
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_CRACKED_FLOOR 0xD2
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ISOLATED_VERTICAL_RAIL 0xD3
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_ISOLATED_HORIZONTAL_RAIL 0xD4
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_VERTICAL_RAIL 0xD5
+ TILE_ATTRIBUTES(TRUE, FALSE, FALSE), // MB_HORIZONTAL_RAIL 0xD6
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xD7
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xD8
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xD9
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xDA
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xDB
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xDC
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xDD
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xDE
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xDF
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_PICTURE_BOOK_SHELF 0xE0
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_BOOKSHELF 0xE1
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_POKEMON_CENTER_BOOKSHELF 0xE2
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_VASE 0xE3
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_TRASH_CAN 0xE4
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_SHOP_SHELF 0xE5
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_BLUEPRINT 0xE6
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_CABLE_BOX_RESULTS_2 0xE7
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_WIRELESS_BOX_RESULTS 0xE8
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_TRAINER_HILL_TIMER 0xE9
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // MB_UNKNOWN_CLOSED_DOOR 0xEA
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xEB
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xEC
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xED
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xEE
+ TILE_ATTRIBUTES(FALSE, FALSE, FALSE), // ? 0xEF
+};
+
+// only used as default case for checking jump landing in field_ground_effect.
+bool8 ShouldDoJumpLandingDustEffect(u8 var)
+{
+ return TRUE;
+}
+
+bool8 MetatileBehavior_IsEncounterTile(u8 var)
+{
+ if ((sTileBitAttributes[var] & TILE_FLAG_ENCOUNTER_TILE) != 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsJumpEast(u8 var)
+{
+ if (var == MB_JUMP_EAST)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsJumpWest(u8 var)
+{
+ if (var == MB_JUMP_WEST)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsJumpNorth(u8 var)
+{
+ if (var == MB_JUMP_NORTH)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsJumpSouth(u8 var)
+{
+ if (var == MB_JUMP_SOUTH)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPokeGrass(u8 var)
+{
+ if (var == MB_TALL_GRASS || var == MB_LONG_GRASS)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSandOrDeepSand(u8 var)
+{
+ if (var == MB_SAND || var == MB_DEEP_SAND)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsDeepSand(u8 var)
+{
+ if (var == MB_DEEP_SAND)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsReflective(u8 var)
+{
+ if (var == MB_POND_WATER || var == MB_PUDDLE || var == MB_1A || var == MB_ICE || var == MB_SOOTOPOLIS_DEEP_WATER || var == MB_REFLECTION_UNDER_BRIDGE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsIce(u8 var)
+{
+ if (var == MB_ICE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWarpDoor(u8 var)
+{
+ if (var == MB_ANIMATED_DOOR)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsDoor(u8 var)
+{
+ if (var == MB_8D || var == MB_ANIMATED_DOOR)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsEscalator(u8 var)
+{
+ if (var == MB_UP_ESCALATOR || var == MB_DOWN_ESCALATOR)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_04(u8 var) // unused
+{
+ if (var == MB_04)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsLadder(u8 var)
+{
+ if (var == MB_LADDER)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsNonAnimDoor(u8 var)
+{
+ if (var == MB_NON_ANIMATED_DOOR || var == MB_WATER_DOOR || var == MB_DEEP_SOUTH_WARP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsDeepSouthWarp(u8 var)
+{
+ if (var == MB_DEEP_SOUTH_WARP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSurfableWaterOrUnderwater(u8 var)
+{
+ if ((sTileBitAttributes[var] & TILE_FLAG_SURFABLE) != 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsEastArrowWarp(u8 var)
+{
+ if (var == MB_EAST_ARROW_WARP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWestArrowWarp(u8 var)
+{
+ if (var == MB_WEST_ARROW_WARP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsNorthArrowWarp(u8 var)
+{
+ if (var == MB_NORTH_ARROW_WARP || var == MB_STAIRS_OUTSIDE_ABANDONED_SHIP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSouthArrowWarp(u8 var)
+{
+ if (var == MB_SOUTH_ARROW_WARP || var == MB_WATER_SOUTH_ARROW_WARP || var == MB_SHOAL_CAVE_ENTRANCE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsArrowWarp(u8 var) // unused
+{
+ u8 ret = FALSE;
+
+ if (MetatileBehavior_IsEastArrowWarp(var)
+ || MetatileBehavior_IsWestArrowWarp(var)
+ || MetatileBehavior_IsNorthArrowWarp(var)
+ || MetatileBehavior_IsSouthArrowWarp(var))
+ {
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+bool8 MetatileBehavior_IsMoveTile(u8 var)
+{
+ if ((var >= MB_WALK_EAST && var <= MB_TRICK_HOUSE_PUZZLE_8_FLOOR) || (var >= MB_EASTWARD_CURRENT && var <= MB_SOUTHWARD_CURRENT)
+ || var == MB_MUDDY_SLOPE || var == MB_CRACKED_FLOOR || var == MB_WATERFALL || var == MB_ICE || var == MB_SECRET_BASE_JUMP_MAT || var == MB_SECRET_BASE_SPIN_MAT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsIce_2(u8 var)
+{
+ if (var == MB_ICE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsTrickHouseSlipperyFloor(u8 var)
+{
+ if (var == MB_TRICK_HOUSE_PUZZLE_8_FLOOR)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_05(u8 var)
+{
+ if (var == MB_05)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWalkNorth(u8 var)
+{
+ if (var == MB_WALK_NORTH)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWalkSouth(u8 var)
+{
+ if (var == MB_WALK_SOUTH)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWalkWest(u8 var)
+{
+ if (var == MB_WALK_WEST)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWalkEast(u8 var)
+{
+ if (var == MB_WALK_EAST)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsNorthwardCurrent(u8 var)
+{
+ if (var == MB_NORTHWARD_CURRENT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSouthwardCurrent(u8 var)
+{
+ if (var == MB_SOUTHWARD_CURRENT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWestwardCurrent(u8 var)
+{
+ if (var == MB_WESTWARD_CURRENT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsEastwardCurrent(u8 var)
+{
+ if (var == MB_EASTWARD_CURRENT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSlideNorth(u8 var)
+{
+ if (var == MB_SLIDE_NORTH)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSlideSouth(u8 var)
+{
+ if (var == MB_SLIDE_SOUTH)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSlideWest(u8 var)
+{
+ if (var == MB_SLIDE_WEST)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSlideEast(u8 var)
+{
+ if (var == MB_SLIDE_EAST)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsCounter(u8 var)
+{
+ if (var == MB_COUNTER)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPlayerFacingTVScreen(u8 tile, u8 playerDir)
+{
+ if (playerDir != CONNECTION_NORTH) // if the player isn't facing north, forget about it.
+ return FALSE;
+ else if (tile == MB_TELEVISION) // is the player's north tile a TV?
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPC(u8 var)
+{
+ if (var == MB_PC)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsCableBoxResults1(u8 var)
+{
+ if (var == MB_CABLE_BOX_RESULTS_1)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseOpen(u8 var)
+{
+ if (var == MB_SECRET_BASE_SPOT_RED_CAVE_OPEN || var == MB_SECRET_BASE_SPOT_BROWN_CAVE_OPEN
+ || var == MB_SECRET_BASE_SPOT_YELLOW_CAVE_OPEN || var == MB_SECRET_BASE_SPOT_TREE_LEFT_OPEN
+ || var == MB_SECRET_BASE_SPOT_SHRUB_OPEN || var == MB_SECRET_BASE_SPOT_BLUE_CAVE_OPEN
+ || var == MB_SECRET_BASE_SPOT_TREE_RIGHT_OPEN)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseCave(u8 var)
+{
+ if (var == MB_SECRET_BASE_SPOT_RED_CAVE || var == MB_SECRET_BASE_SPOT_BROWN_CAVE || var == MB_SECRET_BASE_SPOT_YELLOW_CAVE || var == MB_SECRET_BASE_SPOT_BLUE_CAVE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseTree(u8 var)
+{
+ if (var == MB_SECRET_BASE_SPOT_TREE_LEFT || var == MB_SECRET_BASE_SPOT_TREE_RIGHT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseShrub(u8 var)
+{
+ if (var == MB_SECRET_BASE_SPOT_SHRUB)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBasePC(u8 var)
+{
+ if (var == MB_SECRET_BASE_PC)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseRegisterPC(u8 var)
+{
+ if (var == MB_SECRET_BASE_REGISTER_PC)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_B2(u8 var) // unused
+{
+ if (var == MB_B2)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_B3(u8 var)
+{
+ if (var == MB_B3)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_B9(u8 var)
+{
+ if (var == MB_B9)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_C6(u8 var)
+{
+ if (var == MB_C6)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBasePoster(u8 var)
+{
+ if (var == MB_SECRET_BASE_POSTER)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsNormal(u8 var)
+{
+ if (var == MB_NORMAL)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_B7(u8 var)
+{
+ if (var == MB_B7)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_B2_Duplicate(u8 var) // unused
+{
+ if (var == MB_B2)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_B5(u8 var)
+{
+ if (var == MB_B5)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_C3(u8 var)
+{
+ if (var == MB_C3)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_C2(u8 var)
+{
+ if (var == MB_C2)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseBalloon(u8 var)
+{
+ if (var == MB_SECRET_BASE_BALLOON)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_BE(u8 var)
+{
+ if (var == MB_BE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseSoundMat(u8 var)
+{
+ if (var == MB_SECRET_BASE_SOUND_MAT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseGlitterMat(u8 var)
+{
+ if (var == MB_SECRET_BASE_GLITTER_MAT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_BF(u8 var)
+{
+ if (var == MB_BF)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseTvOrShield(u8 var)
+{
+ if (var == MB_SECRET_BASE_TV_SHIELD)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_C5(u8 var)
+{
+ if (var == MB_C5)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_HasRipples(u8 var)
+{
+ if (var == MB_POND_WATER || var == MB_PUDDLE || var == MB_SOOTOPOLIS_DEEP_WATER)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPuddle(u8 var)
+{
+ if (var == MB_PUDDLE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsTallGrass(u8 var)
+{
+ if (var == MB_TALL_GRASS)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsLongGrass(u8 var)
+{
+ if (var == MB_LONG_GRASS)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsBerryTreeSoil(u8 var)
+{
+ if (var == MB_BERRY_TREE_SOIL)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsAsh(u8 var)
+{
+ if (var == MB_ASHGRASS)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsUnusedFootprintMetatile(u8 var)
+{
+ if (var == MB_25)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsBridge(u8 var)
+{
+ if ((var == MB_WARP_OR_BRIDGE || var == MB_71 || var == MB_ROUTE120_NORTH_BRIDGE_1 || var == MB_ROUTE120_NORTH_BRIDGE_2)
+ || (var == MB_ROUTE120_NORTH_BRIDGE_3 || var == MB_ROUTE120_NORTH_BRIDGE_4 || var == MB_7E || var == MB_ROUTE110_BRIDGE))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+u8 MetatileBehavior_GetBridgeSth(u8 var)
+{
+ u8 result = var - MB_WARP_OR_BRIDGE;
+ if (result < 4)
+ return result;
+
+ result = var - MB_ROUTE120_SOUTH_BRIDGE_1;
+ if (result < 2)
+ return 2;
+
+ result = var - MB_ROUTE120_NORTH_BRIDGE_3;
+ if (result < 2)
+ return 3;
+
+ return 0;
+}
+
+u8 MetatileBehavior_8089510(u8 var)
+{
+ u8 result = var - MB_WARP_OR_BRIDGE;
+
+ if (result < 4)
+ return 1;
+ else
+ return 0;
+}
+
+bool8 MetatileBehavior_IsLandWildEncounter(u8 var)
+{
+ if (MetatileBehavior_IsSurfableWaterOrUnderwater(var) == FALSE && MetatileBehavior_IsEncounterTile(var) == TRUE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWaterWildEncounter(u8 var)
+{
+ if (MetatileBehavior_IsSurfableWaterOrUnderwater(var) == TRUE && MetatileBehavior_IsEncounterTile(var) == TRUE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_0B(u8 var)
+{
+ if (var == MB_0B)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMountain(u8 var)
+{
+ if (var == MB_MOUNTAIN_TOP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsDiveable(u8 var)
+{
+ if (var == MB_SEMI_DEEP_WATER || var == MB_DEEP_WATER || var == MB_SOOTOPOLIS_DEEP_WATER)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsUnableToEmerge(u8 var)
+{
+ if (var == MB_NO_SURFACING || var == MB_SEAWEED_NO_SURFACING)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsShallowFlowingWater(u8 var)
+{
+ if (var == MB_SHALLOW_WATER || var == MB_STAIRS_OUTSIDE_ABANDONED_SHIP || var == MB_SHOAL_CAVE_ENTRANCE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsThinIce(u8 var)
+{
+ if (var == MB_THIN_ICE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsCrackedIce(u8 var)
+{
+ if (var == MB_CRACKED_ICE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsDeepOrOceanWater(u8 var)
+{
+ if (var == MB_OCEAN_WATER || var == MB_SEMI_DEEP_WATER || var == MB_DEEP_WATER)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMB_18_OrMB_1A(u8 var) // unused
+{
+ if (var == MB_18 || var == MB_1A)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSurfableAndNotWaterfall(u8 var)
+{
+ if (MetatileBehavior_IsSurfableWaterOrUnderwater(var) && MetatileBehavior_IsWaterfall(var) == FALSE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsEastBlocked(u8 var)
+{
+ if (var == MB_IMPASSABLE_EAST || var == MB_IMPASSABLE_NORTHEAST || var == MB_IMPASSABLE_SOUTHEAST || var == MB_C1 || var == MB_BE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWestBlocked(u8 var)
+{
+ if (var == MB_IMPASSABLE_WEST || var == MB_IMPASSABLE_NORTHWEST || var == MB_IMPASSABLE_SOUTHWEST || var == MB_C1 || var == MB_BE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsNorthBlocked(u8 var)
+{
+ if (var == MB_IMPASSABLE_NORTH || var == MB_IMPASSABLE_NORTHEAST || var == MB_IMPASSABLE_NORTHWEST || var == MB_BED)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSouthBlocked(u8 var)
+{
+ if (var == MB_IMPASSABLE_SOUTH || var == MB_IMPASSABLE_SOUTHEAST || var == MB_IMPASSABLE_SOUTHWEST || var == MB_BED)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsShortGrass(u8 var)
+{
+ if (var == MB_SHORT_GRASS)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsHotSprings(u8 var)
+{
+ if (var == MB_HOT_SPRINGS)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWaterfall(u8 var)
+{
+ if (var == MB_WATERFALL)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsFortreeBridge(u8 var)
+{
+ if (var == MB_FORTREE_BRIDGE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPacifilogVerticalLog1(u8 var)
+{
+ if (var == MB_PACIFIDLOG_VERTICAL_LOG_1)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPacifilogVerticalLog2(u8 var)
+{
+ if (var == MB_PACIFIDLOG_VERTICAL_LOG_2)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPacifilogHorizontalLog1(u8 var)
+{
+ if (var == MB_PACIFIDLOG_HORIZONTAL_LOG_1)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPacifilogHorizontalLog2(u8 var)
+{
+ if (var == MB_PACIFIDLOG_HORIZONTAL_LOG_2)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPacifidlogLog(u8 var)
+{
+ if (var == MB_PACIFIDLOG_VERTICAL_LOG_1 || var == MB_PACIFIDLOG_VERTICAL_LOG_2
+ || var == MB_PACIFIDLOG_HORIZONTAL_LOG_1 || var == MB_PACIFIDLOG_HORIZONTAL_LOG_2)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsTrickHousePuzzleDoor(u8 var)
+{
+ if (var == MB_TRICK_HOUSE_PUZZLE_DOOR)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsRegionMap(u8 var)
+{
+ if (var == MB_REGION_MAP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsClosedSootopolisGymDoor(u8 var)
+{
+ if (var == MB_CLOSED_SOOTOPOLIS_GYM_DOOR)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsUnknownClosedDoor(u8 var)
+{
+ if (var == MB_UNKNOWN_CLOSED_DOOR)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsRoulette(u8 var) // unused
+{
+ if (var == MB_ROULETTE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPokeblockFeeder(u8 var)
+{
+ if (var == MB_POKEBLOCK_FEEDER)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseJumpMat(u8 var)
+{
+ if (var == MB_SECRET_BASE_JUMP_MAT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSecretBaseSpinMat(u8 var)
+{
+ if (var == MB_SECRET_BASE_SPIN_MAT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsLavaridgeB1FWarp(u8 var)
+{
+ if (var == MB_LAVARIDGE_GYM_B1F_WARP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsLavaridge1FWarp(u8 var)
+{
+ if (var == MB_LAVARIDGE_GYM_1F_WARP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsAquaHideoutWarp(u8 var)
+{
+ if (var == MB_AQUA_HIDEOUT_WARP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsWarpOrBridge(u8 var)
+{
+ if (var == MB_WARP_OR_BRIDGE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMossdeepGymWarp(u8 var)
+{
+ if (var == MB_MOSSDEEP_GYM_WARP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+bool8 MetatileBehavior_IsSurfableFishableWater(u8 var)
+{
+ if (var == MB_POND_WATER || var == MB_OCEAN_WATER || var == MB_SEMI_DEEP_WATER || var == MB_DEEP_WATER
+ || var == MB_SOOTOPOLIS_DEEP_WATER || (var == MB_EASTWARD_CURRENT || var == MB_WESTWARD_CURRENT
+ || var == MB_NORTHWARD_CURRENT || var == MB_SOUTHWARD_CURRENT))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMtPyreHole(u8 var)
+{
+ if (var == MB_MT_PYRE_HOLE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsCrackedFloorHole(u8 var)
+{
+ if (var == MB_CRACKED_FLOOR_HOLE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsCrackedFloor(u8 var)
+{
+ if (var == MB_CRACKED_FLOOR)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsMuddySlope(u8 var)
+{
+ if (var == MB_MUDDY_SLOPE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsBumpySlope(u8 var)
+{
+ if (var == MB_BUMPY_SLOPE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsIsolatedVerticalRail(u8 var)
+{
+ if (var == MB_ISOLATED_VERTICAL_RAIL)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsIsolatedHorizontalRail(u8 var)
+{
+ if (var == MB_ISOLATED_HORIZONTAL_RAIL)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsVerticalRail(u8 var)
+{
+ if (var == MB_VERTICAL_RAIL)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsHorizontalRail(u8 var)
+{
+ if (var == MB_HORIZONTAL_RAIL)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsSeaweed(u8 var)
+{
+ if (var == MB_SEAWEED || var == MB_SEAWEED_NO_SURFACING)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsRunningDisallowed(u8 var)
+{
+ if (var == MB_NO_RUNNING || var == MB_LONG_GRASS || var == MB_HOT_SPRINGS || MetatileBehavior_IsPacifidlogLog(var) != FALSE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsCuttableGrass(u8 var)
+{
+ if (var == MB_TALL_GRASS || var == MB_LONG_GRASS || var == MB_ASHGRASS || var == MB_LONG_GRASS_SOUTH_EDGE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsRunningShoesInstruction(u8 var)
+{
+ if (var == MB_RUNNING_SHOES_INSTRUCTION)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPictureBookShelf(u8 var)
+{
+ if (var == MB_PICTURE_BOOK_SHELF)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsBookShelf(u8 var)
+{
+ if (var == MB_BOOKSHELF)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPokeCenterBookShelf(u8 var)
+{
+ if (var == MB_POKEMON_CENTER_BOOKSHELF)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsVase(u8 var)
+{
+ if (var == MB_VASE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsTrashCan(u8 var)
+{
+ if (var == MB_TRASH_CAN)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsShopShelf(u8 var)
+{
+ if (var == MB_SHOP_SHELF)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsBlueprint(u8 var)
+{
+ if (var == MB_BLUEPRINT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsBattlePyramidWarp(u8 var)
+{
+ if (var == MB_BATTLE_PYRAMID_WARP)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsPlayerFacingWirelessBoxResults(u8 tile, u8 playerDir)
+{
+ if (playerDir != CONNECTION_NORTH) // if the player isn't facing north, forget about it.
+ return FALSE;
+ else if (tile == MB_WIRELESS_BOX_RESULTS) // is the player's north tile the monitor with results?
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsCableBoxResults2(u8 tile, u8 playerDir)
+{
+ if (playerDir != CONNECTION_NORTH) // if the player isn't facing north, forget about it.
+ return FALSE;
+ else if (tile == MB_CABLE_BOX_RESULTS_2) // is the player's north tile the monitor with results?
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsQuestionnaire(u8 var)
+{
+ if (var == MB_QUESTIONNAIRE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsLongGrass_Duplicate(u8 var)
+{
+ if (var == MB_LONG_GRASS)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsLongGrassSouthEdge(u8 var)
+{
+ if (var == MB_LONG_GRASS_SOUTH_EDGE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+bool8 MetatileBehavior_IsTrainerHillTimer(u8 var)
+{
+ if (var == MB_TRAINER_HILL_TIMER)
+ return TRUE;
+ else
+ return FALSE;
+}
diff --git a/src/money.c b/src/money.c
index be64d9633..65a45b158 100644
--- a/src/money.c
+++ b/src/money.c
@@ -1,8 +1,77 @@
#include "global.h"
#include "money.h"
+#include "event_data.h"
+#include "string_util.h"
+#include "text.h"
+#include "menu.h"
+#include "window.h"
+#include "sprite.h"
+#include "decompress.h"
+
+extern const u8 gText_PokedollarVar1[];
+
+extern const u8 gMenuMoneyGfx[];
+extern const u8 gMenuMoneyPal[];
#define MAX_MONEY 999999
+EWRAM_DATA static u8 sMoneyBoxWindowId = 0;
+EWRAM_DATA static u8 sMoneyLabelSpriteId = 0;
+
+#define MONEY_LABEL_TAG 0x2722
+
+static const struct OamData sOamData_MoneyLabel =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = 1,
+ .x = 0,
+ .matrixNum = 0,
+ .size = 2,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const union AnimCmd sSpriteAnim_MoneyLabel[] =
+{
+ ANIMCMD_FRAME(0, 0),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteAnimTable_MoneyLabel[] =
+{
+ sSpriteAnim_MoneyLabel,
+};
+
+static const struct SpriteTemplate sSpriteTemplate_MoneyLabel =
+{
+ .tileTag = MONEY_LABEL_TAG,
+ .paletteTag = MONEY_LABEL_TAG,
+ .oam = &sOamData_MoneyLabel,
+ .anims = sSpriteAnimTable_MoneyLabel,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct CompressedSpriteSheet sSpriteSheet_MoneyLabel =
+{
+ .data = gMenuMoneyGfx,
+ .size = 256,
+ .tag = MONEY_LABEL_TAG,
+};
+
+static const struct CompressedSpritePalette sSpritePalette_MoneyLabel =
+{
+ .data = gMenuMoneyPal,
+ .tag = MONEY_LABEL_TAG
+};
+
u32 GetMoney(u32* moneyPtr)
{
return *moneyPtr ^ gSaveBlock2Ptr->encryptionKey;
@@ -53,3 +122,79 @@ void SubtractMoney(u32* moneyPtr, u32 toSub)
SetMoney(moneyPtr, toSet);
}
+
+bool8 IsEnoughForCostInVar0x8005(void)
+{
+ return IsEnoughMoney(&gSaveBlock1Ptr->money, gSpecialVar_0x8005);
+}
+
+void SubtractMoneyFromVar0x8005(void)
+{
+ SubtractMoney(&gSaveBlock1Ptr->money, gSpecialVar_0x8005);
+}
+
+void PrintMoneyAmountInMoneyBox(u8 windowId, int amount, u8 speed)
+{
+ PrintMoneyAmount(windowId, 0x26, 1, amount, speed);
+}
+
+void PrintMoneyAmount(u8 windowId, u8 x, u8 y, int amount, u8 speed)
+{
+ u8 *txtPtr;
+ s32 strLength;
+
+ ConvertIntToDecimalStringN(gStringVar1, amount, STR_CONV_MODE_LEFT_ALIGN, 6);
+
+ strLength = 6 - StringLength(gStringVar1);
+ txtPtr = gStringVar4;
+
+ while (strLength-- > 0)
+ *(txtPtr++) = 0x77;
+
+ StringExpandPlaceholders(txtPtr, gText_PokedollarVar1);
+ PrintTextOnWindow(windowId, 1, gStringVar4, x, y, speed, NULL);
+}
+
+void PrintMoneyAmountInMoneyBoxWithBorder(u8 windowId, u16 tileStart, u8 pallete, int amount)
+{
+ SetWindowBorderStyle(windowId, FALSE, tileStart, pallete);
+ PrintMoneyAmountInMoneyBox(windowId, amount, 0);
+}
+
+void ChangeAmountInMoneyBox(int amount)
+{
+ PrintMoneyAmountInMoneyBox(sMoneyBoxWindowId, amount, 0);
+}
+
+void DrawMoneyBox(int amount, u8 x, u8 y)
+{
+ struct WindowTemplate template;
+
+ SetWindowTemplateFields(&template, 0, x + 1, y + 1, 10, 2, 15, 8);
+ sMoneyBoxWindowId = AddWindow(&template);
+ FillWindowPixelBuffer(sMoneyBoxWindowId, 0);
+ PutWindowTilemap(sMoneyBoxWindowId);
+ CopyWindowToVram(sMoneyBoxWindowId, 1);
+ PrintMoneyAmountInMoneyBoxWithBorder(sMoneyBoxWindowId, 0x214, 14, amount);
+ AddMoneyLabelObject((8 * x) + 19, (8 * y) + 11);
+}
+
+void HideMoneyBox(void)
+{
+ RemoveMoneyLabelObject();
+ sub_8198070(sMoneyBoxWindowId, FALSE);
+ CopyWindowToVram(sMoneyBoxWindowId, 2);
+ RemoveWindow(sMoneyBoxWindowId);
+}
+
+void AddMoneyLabelObject(u16 x, u16 y)
+{
+ LoadCompressedObjectPic(&sSpriteSheet_MoneyLabel);
+ LoadCompressedObjectPalette(&sSpritePalette_MoneyLabel);
+ sMoneyLabelSpriteId = CreateSprite(&sSpriteTemplate_MoneyLabel, x, y, 0);
+}
+
+void RemoveMoneyLabelObject(void)
+{
+ DestroySpriteAndFreeResources(&gSprites[sMoneyLabelSpriteId]);
+}
diff --git a/src/multiboot.c b/src/multiboot.c
index 80291ff46..7fd6df2d0 100644
--- a/src/multiboot.c
+++ b/src/multiboot.c
@@ -316,7 +316,7 @@ void MultiBootStartProbe(struct MultiBootParam *mp)
mp->probe_count = 1;
}
-void MultiBootStartMaster(struct MultiBootParam *mp, u8 *srcp, int length, u8 palette_color, s8 palette_speed)
+void MultiBootStartMaster(struct MultiBootParam *mp, const u8 *srcp, int length, u8 palette_color, s8 palette_speed)
{
int i = 0;
diff --git a/src/new_game.c b/src/new_game.c
index 2bf774c69..5a482c593 100644
--- a/src/new_game.c
+++ b/src/new_game.c
@@ -18,6 +18,7 @@
#include "event_data.h"
#include "money.h"
#include "coins.h"
+#include "text.h"
extern u8 gPlayerPartyCount;
extern u8 gDifferentSaveFile;
@@ -104,7 +105,10 @@ void ClearPokedexFlags(void)
memset(&gSaveBlock2Ptr->pokedex.seen, 0, sizeof(gSaveBlock2Ptr->pokedex.seen));
}
-extern const struct ContestWinner gContestWinnerPicDummy;
+const struct ContestWinner gContestWinnerPicDummy = {
+ .monName = _(""),
+ .trainerName = _("")
+};
void ClearAllContestWinnerPics(void)
{
diff --git a/src/palette.c b/src/palette.c
index aa9a84e4c..d60efdbc5 100644
--- a/src/palette.c
+++ b/src/palette.c
@@ -1,5 +1,8 @@
#include "global.h"
+#include "blend_palette.h"
#include "palette.h"
+#include "decompress.h"
+#include "gpu_regs.h"
#include "task.h"
enum
@@ -28,7 +31,7 @@ struct PaletteStructTemplate
struct PaletteStruct
{
- struct PaletteStructTemplate *base;
+ const struct PaletteStructTemplate *base;
u32 ps_field_4_0:1;
u16 ps_field_4_1:1;
u32 baseDestOffset:9;
@@ -38,31 +41,6 @@ struct PaletteStruct
u8 ps_field_9;
};
-extern void LZDecompressWram(const void *src, void *dest);
-extern void SetGpuReg(u8 regOffset, u16 value);
-extern void sub_8149DFC(u8 a1);
-extern void sub_80A1670(u16 a1);
-extern void sub_80A2D54(u8 a1);
-extern void SetWordTaskArg(u8 taskId, u8 dataElem, u32 value);
-extern void _call_via_r1(u32 a1, void *a2);
-
-extern void BlendPalette(u16, u16, u8, u16);
-
-EWRAM_DATA u16 gPlttBufferUnfaded[0x200] = {0};
-EWRAM_DATA u16 gPlttBufferFaded[0x200] = {0};
-EWRAM_DATA struct PaletteStruct sPaletteStructs[0x10] = {0};
-EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0};
-EWRAM_DATA u32 gFiller_2037FE0 = 0;
-EWRAM_DATA u32 sPlttBufferTransferPending = 0;
-EWRAM_DATA u8 gPaletteDecompressionBuffer[0x400] = {0};
-
-extern struct PaletteStructTemplate gDummyPaletteStructTemplate;
-extern void *gUnknown_0852487C;
-extern u8 gUnknown_0852489C[];
-
-extern u16 gUnknown_03000F3C;
-extern void *gUnknown_03000F44;
-
static void unused_sub_80A1CDC(struct PaletteStruct *, u32 *);
static void unused_sub_80A1E40(struct PaletteStruct *, u32 *);
static void unused_sub_80A1F00(struct PaletteStruct *);
@@ -73,32 +51,29 @@ static u8 UpdateFastPaletteFade(void);
static u8 UpdateHardwarePaletteFade(void);
static void UpdateBlendRegisters(void);
static bool8 IsSoftwarePaletteFadeFinishing(void);
+static void sub_80A2D54(u8 taskId);
-void sub_80A1818(u16 a1)
-{
- void **v1 = &gUnknown_0852487C;
- CpuSet(v1[a1 & 0x3], gPlttBufferUnfaded + 0x80, 0x10);
- BlendPalette(0x80, 0x10, gPaletteFade.y, gPaletteFade.blendColor & 0x7FFF);
- if ((u8)FindTaskIdByFunc(sub_8149DFC) != 0xFF )
- {
- gUnknown_03000F44 = sub_80A1670;
- gUnknown_03000F3C = 0x20;
- }
- return;
-}
+EWRAM_DATA u16 gPlttBufferUnfaded[0x200] = {0};
+EWRAM_DATA u16 gPlttBufferFaded[0x200] = {0};
+EWRAM_DATA struct PaletteStruct sPaletteStructs[0x10] = {0};
+EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0};
+static EWRAM_DATA u32 gFiller_2037FE0 = 0;
+static EWRAM_DATA u32 sPlttBufferTransferPending = 0;
+EWRAM_DATA u8 gPaletteDecompressionBuffer[0x400] = {0};
-void sub_80A1884(u16 a1)
-{
- void **v1 = &gUnknown_0852487C;
- CpuSet(v1[a1 & 0x3], gPlttBufferUnfaded + 0x80, 0x10);
- if ((u8)FindTaskIdByFunc(sub_8149DFC) == 0xFF )
- {
- BlendPalette(0x80, 0x10, gPaletteFade.y, gPaletteFade.blendColor & 0x7FFF);
- if (!--gUnknown_03000F3C)
- gUnknown_03000F44 = 0;
- }
- return;
-}
+static const struct PaletteStructTemplate gDummyPaletteStructTemplate = {
+ .uid = 0xFFFF,
+ .pst_field_B_5 = 1
+};
+static const u8 gUnknown_0852489C[] = {
+ 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 5,
+ 11, 11, 11, 11, 11,
+ 16, 16, 16, 16, 16,
+ 21, 21, 21, 21, 21,
+ 27, 27, 27, 27, 27,
+ 31, 31
+};
void LoadCompressedPalette(const void *src, u16 offset, u16 size)
{
diff --git a/src/pokemon_2.c b/src/pokemon_2.c
index 30e788874..c5c36c793 100644
--- a/src/pokemon_2.c
+++ b/src/pokemon_2.c
@@ -31,11 +31,11 @@ extern const union AnimCmd* gUnknown_082FF70C[];
extern const union AnimCmd* const * const gUnknown_08309AAC[];
extern const union AnimCmd* const * const gUnknown_08305D0C[];
extern const union AnimCmd* const * const gUnknown_0830536C[];
-extern const u8 gBadEggNickname[];
+extern const u8 gText_BadEgg[];
extern const u8 gText_EggNickname[];
extern u8 GetBankSide(u8 bank);
-extern u8 GetBankByPlayerAI(u8 bank);
+extern u8 GetBankByIdentity(u8 bank);
extern u8 GetBankIdentity(u8 bank);
u8 CountAliveMonsInBattle(u8 caseId)
@@ -90,7 +90,7 @@ u8 sub_8069F34(u8 bank)
status ^= 1;
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
- return GetBankByPlayerAI(status);
+ return GetBankByIdentity(status);
if (CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_ACTIVE) > 1)
{
u8 val;
@@ -99,14 +99,14 @@ u8 sub_8069F34(u8 bank)
val = status ^ 2;
else
val = status;
- return GetBankByPlayerAI(val);
+ return GetBankByIdentity(val);
}
else
{
if ((gAbsentBankFlags & gBitTable[status]))
- return GetBankByPlayerAI(status ^ 2);
+ return GetBankByIdentity(status ^ 2);
else
- return GetBankByPlayerAI(status);
+ return GetBankByIdentity(status);
}
}
@@ -409,8 +409,8 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
if (boxMon->isBadEgg)
{
for (retVal = 0;
- retVal < POKEMON_NAME_LENGTH && gBadEggNickname[retVal] != EOS;
- data[retVal] = gBadEggNickname[retVal], retVal++) {}
+ retVal < POKEMON_NAME_LENGTH && gText_BadEgg[retVal] != EOS;
+ data[retVal] = gText_BadEgg[retVal], retVal++) {}
data[retVal] = EOS;
}
@@ -1308,10 +1308,9 @@ void sub_805EF84(u8 bank, bool8);
extern struct BattlePokemon gBattleMons[4];
-/*
-
void CopyPlayerPartyMonToBattleData(u8 bank, u8 partyIndex)
{
+ u16* hpSwitchout;
s32 i;
u8 nickname[POKEMON_NAME_LENGTH * 2];
@@ -1352,15 +1351,9 @@ void CopyPlayerPartyMonToBattleData(u8 bank, u8 partyIndex)
GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, nickname);
StringCopy10(gBattleMons[bank].nickname, nickname);
GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_NAME, gBattleMons[bank].otName);
- // ewram memes from Ruby return
- #ifdef NONMATCHING
- gBattleStruct->hpOnSwitchout[GetBankSide(bank)] = gBattleMons[bank].hp;
- #else
- {
- u32 side = GetBankSide(bank);
- *(u16*)((void*)(gBattleStruct) + side) = gBattleMons[bank].hp;
- }
- #endif // NONMATCHING
+
+ hpSwitchout = &gBattleStruct->hpOnSwitchout[GetBankSide(bank)];
+ *hpSwitchout = gBattleMons[bank].hp;
for (i = 0; i < 8; i++)
gBattleMons[bank].statStages[i] = 6;
@@ -1369,4 +1362,3 @@ void CopyPlayerPartyMonToBattleData(u8 bank, u8 partyIndex)
sub_803FA70(bank);
sub_805EF84(bank, FALSE);
}
-*/
diff --git a/src/pokemon_3.c b/src/pokemon_3.c
index 2d1dfb8b7..d44c0cb2f 100644
--- a/src/pokemon_3.c
+++ b/src/pokemon_3.c
@@ -46,16 +46,16 @@ extern const struct SpindaSpot gSpindaSpotGraphics[];
extern const u8* const gStatNamesTable[];
extern const u8 gSpeciesNames[][11];
extern const u8 gUnknown_08329EC8[];
-extern const u8 gUnknown_085CB38A[];
-extern const u8 gUnknown_085CB3AA[];
-extern const u8 gUnknown_085CA459[];
-extern const u8 gUnknown_085CA424[];
+extern const u8 gText_StatRose[];
+extern const u8 gText_PkmnsStatChanged2[];
+extern const u8 gText_PkmnGettingPumped[];
+extern const u8 gText_PkmnShroudedInMist[];
extern const s8 gNatureStatTable[][5];
extern const s8 gUnknown_08329ECE[][3];
extern const u32 gBitTable[];
extern const u32 gTMHMLearnsets[][2];
-extern const u8 BattleText_Wally[];
-extern const u8 BattleText_PreventedSwitch[];
+extern const u8 gText_BattleWallyName[];
+extern const u8 gText_PkmnsXPreventsSwitching[];
extern const struct CompressedSpritePalette gMonPaletteTable[];
extern const struct CompressedSpritePalette gMonShinyPaletteTable[];
extern const u16 gHMMoves[];
@@ -215,8 +215,8 @@ void sub_806CF24(s32 stat)
{
gBankTarget = gBankInMenu;
StringCopy(gBattleTextBuff1, gStatNamesTable[gUnknown_08329EC8[stat]]);
- StringCopy(gBattleTextBuff2, gUnknown_085CB38A);
- StrCpyDecodeToDisplayedStringBattle(gUnknown_085CB3AA);
+ StringCopy(gBattleTextBuff2, gText_StatRose);
+ BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnsStatChanged2);
}
u8 *sub_806CF78(u16 itemId)
@@ -251,7 +251,7 @@ u8 *sub_806CF78(u16 itemId)
else
{
gBankAttacker = gBankInMenu;
- StrCpyDecodeToDisplayedStringBattle(gUnknown_085CA459);
+ BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnGettingPumped);
}
}
}
@@ -259,7 +259,7 @@ u8 *sub_806CF78(u16 itemId)
if (itemEffect[3] & 0x80)
{
gBankAttacker = gBankInMenu;
- StrCpyDecodeToDisplayedStringBattle(gUnknown_085CA424);
+ BattleStringExpandPlaceholdersToDisplayedString(gText_PkmnShroudedInMist);
}
return gDisplayedStringBattle;
@@ -601,9 +601,9 @@ bool8 sub_806D7EC(void)
return retVal;
}
-bool8 sub_806D82C(u8 id)
+bool16 sub_806D82C(u8 id)
{
- bool8 retVal = FALSE;
+ bool16 retVal = FALSE;
switch (gLinkPlayers[id].lp_field_18)
{
case 0:
@@ -1177,7 +1177,7 @@ u16 GetBattleBGM(void)
case CLASS_PKMN_TRAINER_RIVAL:
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER)
return 0x1E1;
- if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, BattleText_Wally))
+ if (!StringCompare(gTrainers[gTrainerBattleOpponent_A].trainerName, gText_BattleWallyName))
return 0x1DC;
return 0x1E1;
case CLASS_ELITE_FOUR:
@@ -1361,20 +1361,20 @@ void BoxMonRestorePP(struct BoxPokemon *boxMon)
void sub_806E994(void)
{
gLastUsedAbility = gBattleStruct->field_B0;
- gBattleTextBuff1[0] = 0xFD;
- gBattleTextBuff1[1] = 4;
+
+ gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN;
+ gBattleTextBuff1[1] = B_BUFF_MON_NICK_WITH_PREFIX;
gBattleTextBuff1[2] = gBattleStruct->field_49;
- gBattleTextBuff1[4] = EOS;
+ gBattleTextBuff1[4] = B_BUFF_EOS;
+
if (!GetBankSide(gBattleStruct->field_49))
gBattleTextBuff1[3] = pokemon_order_func(gBattlePartyID[gBattleStruct->field_49]);
else
gBattleTextBuff1[3] = gBattlePartyID[gBattleStruct->field_49];
- gBattleTextBuff2[0] = 0xFD;
- gBattleTextBuff2[1] = 4;
- gBattleTextBuff2[2] = gBankInMenu;
- gBattleTextBuff2[3] = pokemon_order_func(gBattlePartyID[gBankInMenu]);
- gBattleTextBuff2[4] = EOS;
- StrCpyDecodeBattle(BattleText_PreventedSwitch, gStringVar4);
+
+ PREPARE_MON_NICK_WITH_PREFIX_BUFFER(gBattleTextBuff2, gBankInMenu, pokemon_order_func(gBattlePartyID[gBankInMenu]))
+
+ BattleStringExpandPlaceholders(gText_PkmnsXPreventsSwitching, gStringVar4);
}
struct PokeItem
@@ -1388,7 +1388,7 @@ extern const struct PokeItem gAlteringCaveWildMonHeldItems[9];
static s32 GetWildMonTableIdInAlteringCave(u16 species)
{
s32 i;
- for (i = 0; i < 9; i++)
+ for (i = 0; i < (s32) ARRAY_COUNT(gAlteringCaveWildMonHeldItems); i++)
if (gAlteringCaveWildMonHeldItems[i].species == species)
return i;
return 0;
@@ -1511,8 +1511,6 @@ static void Task_PokemonSummaryAnimateAfterDelay(u8 taskId)
}
}
-void DoMonFrontSpriteAnimation(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3);
-
void BattleAnimateFrontSprite(struct Sprite* sprite, u16 species, bool8 noCry, u8 arg3)
{
if (gHitMarker & HITMARKER_NO_ANIMATIONS && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000)))
diff --git a/src/pokemon_size_record.c b/src/pokemon_size_record.c
index 804dbda74..12d98bfd8 100644
--- a/src/pokemon_size_record.c
+++ b/src/pokemon_size_record.c
@@ -45,8 +45,8 @@ static const u8 sGiftRibbonsMonDataIds[] =
MON_DATA_GIFT_RIBBON_7
};
-extern const u8 gOtherText_DecimalPoint[];
-extern const u8 gOtherText_Marco[];
+extern const u8 gText_DecimalPoint[];
+extern const u8 gText_Marco[];
extern const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1];
#define CM_PER_INCH 2.54
@@ -103,7 +103,7 @@ static void FormatMonSizeRecord(u8 *string, u32 size)
#endif
string = ConvertIntToDecimalStringN(string, size / 10, 0, 8);
- string = StringAppend(string, gOtherText_DecimalPoint);
+ string = StringAppend(string, gText_DecimalPoint);
ConvertIntToDecimalStringN(string, size % 10, 0, 1);
}
@@ -152,7 +152,7 @@ static void GetMonSizeRecordInfo(u16 species, u16 *sizeRecord)
FormatMonSizeRecord(gStringVar3, size);
StringCopy(gStringVar1, gSpeciesNames[species]);
if (*sizeRecord == DEFAULT_MAX_SIZE)
- StringCopy(gStringVar2, gOtherText_Marco);
+ StringCopy(gStringVar2, gText_Marco);
else
StringCopy(gStringVar2, gSaveBlock2Ptr->playerName);
}
diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c
new file mode 100644
index 000000000..3e409244c
--- /dev/null
+++ b/src/pokemon_storage_system.c
@@ -0,0 +1,15 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03000F78[0x188];
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/record_mixing.c b/src/record_mixing.c
new file mode 100644
index 000000000..151835e5e
--- /dev/null
+++ b/src/record_mixing.c
@@ -0,0 +1,28 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA bool8 gUnknown_03001130;
+IWRAM_DATA struct SecretBaseRecord *gUnknown_03001134;
+IWRAM_DATA TVShow *gUnknown_03001138;
+IWRAM_DATA struct UnknownSaveStruct2ABC *gUnknown_0300113C;
+IWRAM_DATA OldMan *gUnknown_03001140;
+IWRAM_DATA struct EasyChatPair *gUnknown_03001144;
+IWRAM_DATA struct DaycareData *gUnknown_03001148;
+IWRAM_DATA void *gUnknown_0300114C; // gSaveBlock2Ptr->field_64C
+IWRAM_DATA LilycoveLady *gUnknown_03001150;
+IWRAM_DATA void *gUnknown_03001154; // gSaveBlock2Ptr->field_0DC;
+IWRAM_DATA void *gUnknown_03001158; // gSaveBlock2Ptr->field_64C
+IWRAM_DATA u32 gUnknown_0300115C;
+IWRAM_DATA u8 gUnknown_03001160[8];
+IWRAM_DATA u32 gUnknown_03001168[3];
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/reset_save_heap.c b/src/reset_save_heap.c
new file mode 100644
index 000000000..b786ff9f8
--- /dev/null
+++ b/src/reset_save_heap.c
@@ -0,0 +1,32 @@
+#include "global.h"
+#include "main.h"
+#include "gpu_regs.h"
+#include "m4a.h"
+#include "load_save.h"
+#include "save.h"
+#include "new_game.h"
+#include "rom4.h"
+#include "malloc.h"
+
+void sub_81700F8(void)
+{
+ u16 imeBackup;
+
+ imeBackup = REG_IME;
+ REG_IME = 0;
+ RegisterRamReset(0x00000001);
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, 0x80);
+ REG_IME = imeBackup;
+ gMain.inBattle = FALSE;
+ SetSaveBlocksPointers(sub_815355C());
+ sub_808447C();
+ ResetSaveCounters();
+ sub_81534D0(0);
+ if (gSaveFileStatus == 0 || gSaveFileStatus == 2)
+ {
+ Sav2_ClearSetDefault();
+ }
+ SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound);
+ InitHeap(gHeap, 0x1c000);
+ SetMainCallback2(sub_8086230);
+}
diff --git a/src/roamer.c b/src/roamer.c
new file mode 100644
index 000000000..cbe1b6312
--- /dev/null
+++ b/src/roamer.c
@@ -0,0 +1,218 @@
+#include "global.h"
+#include "roamer.h"
+#include "pokemon.h"
+#include "rng.h"
+#include "species.h"
+#include "event_data.h"
+
+enum
+{
+ MAP_GRP = 0, // map group
+ MAP_NUM = 1, // map number
+};
+
+EWRAM_DATA static u8 sLocationHistory[3][2] = {0};
+EWRAM_DATA static u8 sRoamerLocation[2] = {0};
+
+static const u8 sRoamerLocations[][6] =
+{
+ { 0x19, 0x1A, 0x20, 0x21, 0x31, 0xFF },
+ { 0x1A, 0x19, 0x20, 0x21, 0xFF, 0xFF },
+ { 0x20, 0x1A, 0x19, 0x21, 0xFF, 0xFF },
+ { 0x21, 0x20, 0x19, 0x1A, 0x22, 0x26 },
+ { 0x22, 0x21, 0x23, 0xFF, 0xFF, 0xFF },
+ { 0x23, 0x22, 0x24, 0xFF, 0xFF, 0xFF },
+ { 0x24, 0x23, 0x25, 0x26, 0xFF, 0xFF },
+ { 0x25, 0x24, 0x26, 0xFF, 0xFF, 0xFF },
+ { 0x26, 0x25, 0x21, 0xFF, 0xFF, 0xFF },
+ { 0x27, 0x24, 0x28, 0x29, 0xFF, 0xFF },
+ { 0x28, 0x27, 0x2A, 0xFF, 0xFF, 0xFF },
+ { 0x29, 0x27, 0x2A, 0xFF, 0xFF, 0xFF },
+ { 0x2A, 0x28, 0x29, 0x2B, 0xFF, 0xFF },
+ { 0x2B, 0x2A, 0x2C, 0xFF, 0xFF, 0xFF },
+ { 0x2C, 0x2B, 0x2D, 0xFF, 0xFF, 0xFF },
+ { 0x2D, 0x2C, 0x2E, 0xFF, 0xFF, 0xFF },
+ { 0x2E, 0x2D, 0x2F, 0xFF, 0xFF, 0xFF },
+ { 0x2F, 0x2E, 0x30, 0xFF, 0xFF, 0xFF },
+ { 0x30, 0x2F, 0x31, 0xFF, 0xFF, 0xFF },
+ { 0x31, 0x30, 0x19, 0xFF, 0xFF, 0xFF },
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
+};
+
+void ClearRoamerData(void)
+{
+ memset(&gSaveBlock1Ptr->roamer, 0, sizeof(struct Roamer));
+ (&gSaveBlock1Ptr->roamer)->species = SPECIES_LATIAS;
+}
+
+void ClearRoamerLocationData(void)
+{
+ u8 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ sLocationHistory[i][MAP_GRP] = 0;
+ sLocationHistory[i][MAP_NUM] = 0;
+ }
+
+ sRoamerLocation[MAP_GRP] = 0;
+ sRoamerLocation[MAP_NUM] = 0;
+}
+
+static void CreateInitialRoamerMon(bool16 createLatios)
+{
+ if (!createLatios)
+ (&gSaveBlock1Ptr->roamer)->species = SPECIES_LATIAS;
+ else
+ (&gSaveBlock1Ptr->roamer)->species = SPECIES_LATIOS;
+
+ CreateMon(&gEnemyParty[0], (&gSaveBlock1Ptr->roamer)->species, 40, 0x20, 0, 0, 0, 0);
+ (&gSaveBlock1Ptr->roamer)->level = 40;
+ (&gSaveBlock1Ptr->roamer)->status = 0;
+ (&gSaveBlock1Ptr->roamer)->active = TRUE;
+ (&gSaveBlock1Ptr->roamer)->ivs = GetMonData(&gEnemyParty[0], MON_DATA_IVS);
+ (&gSaveBlock1Ptr->roamer)->personality = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY);
+ (&gSaveBlock1Ptr->roamer)->hp = GetMonData(&gEnemyParty[0], MON_DATA_MAX_HP);
+ (&gSaveBlock1Ptr->roamer)->cool = GetMonData(&gEnemyParty[0], MON_DATA_COOL);
+ (&gSaveBlock1Ptr->roamer)->beauty = GetMonData(&gEnemyParty[0], MON_DATA_BEAUTY);
+ (&gSaveBlock1Ptr->roamer)->cute = GetMonData(&gEnemyParty[0], MON_DATA_CUTE);
+ (&gSaveBlock1Ptr->roamer)->smart = GetMonData(&gEnemyParty[0], MON_DATA_SMART);
+ (&gSaveBlock1Ptr->roamer)->tough = GetMonData(&gEnemyParty[0], MON_DATA_TOUGH);
+ sRoamerLocation[MAP_GRP] = 0;
+ sRoamerLocation[MAP_NUM] = sRoamerLocations[Random() % 20][0];
+}
+
+void InitRoamer(void)
+{
+ ClearRoamerData();
+ ClearRoamerLocationData();
+ CreateInitialRoamerMon(gSpecialVar_0x8004);
+}
+
+void UpdateLocationHistoryForRoamer(void)
+{
+ sLocationHistory[2][MAP_GRP] = sLocationHistory[1][MAP_GRP];
+ sLocationHistory[2][MAP_NUM] = sLocationHistory[1][MAP_NUM];
+
+ sLocationHistory[1][MAP_GRP] = sLocationHistory[0][MAP_GRP];
+ sLocationHistory[1][MAP_NUM] = sLocationHistory[0][MAP_NUM];
+
+ sLocationHistory[0][MAP_GRP] = gSaveBlock1Ptr->location.mapGroup;
+ sLocationHistory[0][MAP_NUM] = gSaveBlock1Ptr->location.mapNum;
+}
+
+void RoamerMoveToOtherLocationSet(void)
+{
+ u8 val = 0;
+ struct Roamer *roamer = &gSaveBlock1Ptr->roamer;
+
+ if (!roamer->active)
+ return;
+
+ sRoamerLocation[MAP_GRP] = val;
+
+ while (1)
+ {
+ val = sRoamerLocations[Random() % 20][0];
+ if (sRoamerLocation[MAP_NUM] != val)
+ {
+ sRoamerLocation[MAP_NUM] = val;
+ return;
+ }
+ }
+}
+
+void RoamerMove(void)
+{
+ u8 locSet = 0;
+
+ if ((Random() % 16) == 0)
+ {
+ RoamerMoveToOtherLocationSet();
+ }
+ else
+ {
+ struct Roamer *roamer = &gSaveBlock1Ptr->roamer;
+
+ if (!roamer->active)
+ return;
+
+ while (locSet < 20)
+ {
+ if (sRoamerLocation[MAP_NUM] == sRoamerLocations[locSet][0])
+ {
+ u8 mapNum;
+ while (1)
+ {
+ mapNum = sRoamerLocations[locSet][(Random() % 5) + 1];
+ if (!(sLocationHistory[2][MAP_GRP] == 0 && sLocationHistory[2][MAP_NUM] == mapNum) && mapNum != 0xFF)
+ break;
+ }
+ sRoamerLocation[MAP_NUM] = mapNum;
+ return;
+ }
+ locSet++;
+ }
+ }
+}
+
+bool8 IsRoamerAt(u8 mapGroup, u8 mapNum)
+{
+ struct Roamer *roamer = &gSaveBlock1Ptr->roamer;
+
+ if (roamer->active && mapGroup == sRoamerLocation[MAP_GRP] && mapNum == sRoamerLocation[MAP_NUM])
+ return TRUE;
+ else
+ return FALSE;
+}
+
+void CreateRoamerMonInstance(void)
+{
+ struct Pokemon *mon;
+ struct Roamer *roamer;
+
+ mon = &gEnemyParty[0];
+ ZeroEnemyPartyMons();
+ roamer = &gSaveBlock1Ptr->roamer;
+ CreateMonWithIVsPersonality(mon, roamer->species, roamer->level, roamer->ivs, roamer->personality);
+ SetMonData(mon, MON_DATA_STATUS, &gSaveBlock1Ptr->roamer.status);
+ SetMonData(mon, MON_DATA_HP, &gSaveBlock1Ptr->roamer.hp);
+ SetMonData(mon, MON_DATA_COOL, &gSaveBlock1Ptr->roamer.cool);
+ SetMonData(mon, MON_DATA_BEAUTY, &gSaveBlock1Ptr->roamer.beauty);
+ SetMonData(mon, MON_DATA_CUTE, &gSaveBlock1Ptr->roamer.cute);
+ SetMonData(mon, MON_DATA_SMART, &gSaveBlock1Ptr->roamer.smart);
+ SetMonData(mon, MON_DATA_TOUGH, &gSaveBlock1Ptr->roamer.tough);
+}
+
+bool8 TryStartRoamerEncounter(void)
+{
+ if (IsRoamerAt(gSaveBlock1Ptr->location.mapGroup, gSaveBlock1Ptr->location.mapNum) == TRUE && (Random() % 4) == 0)
+ {
+ CreateRoamerMonInstance();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void UpdateRoamerHPStatus(struct Pokemon *mon)
+{
+ (&gSaveBlock1Ptr->roamer)->hp = GetMonData(mon, MON_DATA_HP);
+ (&gSaveBlock1Ptr->roamer)->status = GetMonData(mon, MON_DATA_STATUS);
+
+ RoamerMoveToOtherLocationSet();
+}
+
+void SetRoamerInactive(void)
+{
+ struct Roamer *roamer = &gSaveBlock1Ptr->roamer;
+ roamer->active = FALSE;
+}
+
+void GetRoamerLocation(u8 *mapGroup, u8 *mapNum)
+{
+ *mapGroup = sRoamerLocation[MAP_GRP];
+ *mapNum = sRoamerLocation[MAP_NUM];
+}
diff --git a/src/rom4.c b/src/rom4.c
new file mode 100644
index 000000000..c538595f2
--- /dev/null
+++ b/src/rom4.c
@@ -0,0 +1,19 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+IWRAM_DATA void *gUnknown_03000E0C;
+IWRAM_DATA u8 gUnknown_03000E10[4];
+IWRAM_DATA u8 (*gUnknown_03000E14)(u32);
+IWRAM_DATA u8 gUnknown_03000E18;
+IWRAM_DATA u8 gUnknown_03000E19;
+IWRAM_DATA void *rom4_c_unused_03000e1c;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/safari_zone.c b/src/safari_zone.c
index fdfdd961a..3e25468bf 100644
--- a/src/safari_zone.c
+++ b/src/safari_zone.c
@@ -18,7 +18,7 @@ struct PokeblockFeeder
#define NUM_POKEBLOCK_FEEDERS 10
extern u8 gBattleOutcome;
-extern void* gUnknown_03005DAC;
+extern void* gFieldCallback;
extern u8 gUnknown_082A4B8A[];
extern u8 gUnknown_082A4B6F[];
@@ -118,7 +118,7 @@ void sub_80FC190(void)
{
ScriptContext2_RunNewScript(gUnknown_082A4B4C);
warp_in();
- gUnknown_03005DAC = sub_80AF6F0;
+ gFieldCallback = sub_80AF6F0;
SetMainCallback2(c2_load_new_map);
}
else if (gBattleOutcome == BATTLE_CAUGHT)
diff --git a/src/save.c b/src/save.c
index 5ca855247..aee20d451 100644
--- a/src/save.c
+++ b/src/save.c
@@ -2,12 +2,15 @@
#include "gba/flash_internal.h"
#include "save.h"
#include "game_stat.h"
+#include "task.h"
-extern struct SaveSectionOffsets gSaveSectionOffsets[0xE];
extern struct SaveSectionLocation gRamSaveSectionLocations[0xE];
extern u8 gDecompressionBuffer[];
extern u32 gFlashMemoryPresent;
extern u16 gUnknown_03006294;
+extern bool8 gSoftResetDisabled;
+
+extern const struct SaveSectionOffsets gSaveSectionOffsets[0xE];
extern void DoSaveFailedScreen(u8); // save_failed_screen
extern void LoadSerializedGame(void); // load_save
@@ -576,84 +579,27 @@ u16 CalculateChecksum(void *data, u16 size)
return ((checksum >> 16) + checksum);
}
-#ifdef NONMATCHING
-// the initial allocation of the pointer and toAdd variable doesnt match up with the original function. however, forcing it is impossible since gRamSaveSectionLocations is loaded first.
void UpdateSaveAddresses(void)
{
int i = 0;
- gRamSaveSectionLocations[i].data = gSaveBlock2Ptr + gSaveSectionOffsets[0].toAdd;
- gRamSaveSectionLocations[i].size = gSaveSectionOffsets[0].size;
- for(i = 1; i < 5; i++)
+ gRamSaveSectionLocations[i].data = (void*)(gSaveBlock2Ptr) + gSaveSectionOffsets[i].toAdd;
+ gRamSaveSectionLocations[i].size = gSaveSectionOffsets[i].size;
+
+ for (i = 1; i < 5; i++)
{
- gRamSaveSectionLocations[i].data = gSaveBlock1Ptr + gSaveSectionOffsets[i].toAdd;
+ gRamSaveSectionLocations[i].data = (void*)(gSaveBlock1Ptr) + gSaveSectionOffsets[i].toAdd;
gRamSaveSectionLocations[i].size = gSaveSectionOffsets[i].size;
}
- for(i = 5; i < 14; i++)
+ for (i = 5; i < 14; i++)
{
- gRamSaveSectionLocations[i].data = gPokemonStoragePtr + gSaveSectionOffsets[i].toAdd;
+ gRamSaveSectionLocations[i].data = (void*)(gPokemonStoragePtr) + gSaveSectionOffsets[i].toAdd;
gRamSaveSectionLocations[i].size = gSaveSectionOffsets[i].size;
+
+ i++;i--; // needed to match
}
}
-#else
-__attribute__((naked))
-void UpdateSaveAddresses(void)
-{
- asm(".syntax unified\n\
- push {r4,r5,lr}\n\
- ldr r3, =gRamSaveSectionLocations\n\
- ldr r0, =gSaveBlock2Ptr\n\
- ldr r2, =gSaveSectionOffsets\n\
- ldrh r1, [r2]\n\
- ldr r0, [r0]\n\
- adds r0, r1\n\
- str r0, [r3]\n\
- ldrh r0, [r2, 0x2]\n\
- strh r0, [r3, 0x4]\n\
- ldr r5, =gSaveBlock1Ptr\n\
- adds r3, 0x8\n\
- adds r2, 0x4\n\
- movs r4, 0x3\n\
-_081531AC:\n\
- ldrh r0, [r2]\n\
- ldr r1, [r5]\n\
- adds r1, r0\n\
- str r1, [r3]\n\
- ldrh r0, [r2, 0x2]\n\
- strh r0, [r3, 0x4]\n\
- adds r3, 0x8\n\
- adds r2, 0x4\n\
- subs r4, 0x1\n\
- cmp r4, 0\n\
- bge _081531AC\n\
- movs r4, 0x5\n\
- ldr r1, =gRamSaveSectionLocations\n\
- ldr r5, =gPokemonStoragePtr\n\
- ldr r0, =gSaveSectionOffsets\n\
- adds r3, r1, 0\n\
- adds r3, 0x28\n\
- adds r2, r0, 0\n\
- adds r2, 0x14\n\
-_081531D2:\n\
- ldrh r0, [r2]\n\
- ldr r1, [r5]\n\
- adds r1, r0\n\
- str r1, [r3]\n\
- ldrh r0, [r2, 0x2]\n\
- strh r0, [r3, 0x4]\n\
- adds r3, 0x8\n\
- adds r2, 0x4\n\
- adds r4, 0x1\n\
- cmp r4, 0xD\n\
- ble _081531D2\n\
- pop {r4,r5}\n\
- pop {r0}\n\
- bx r0\n\
- .pool\n\
- .syntax divided");
-}
-#endif
extern u32 GetGameStat(u8 index); // rom4
extern void IncrementGameStat(u8 index); // rom4
@@ -894,3 +840,85 @@ u32 sub_8153634(u8 sector, u8* src)
return 0xFF;
return 1;
}
+
+extern void save_serialize_map(void);
+extern void sub_8076D5C(void);
+extern void sav2_gender2_inplace_and_xFE(void);
+extern void sub_800ADF8(void);
+extern bool8 sub_800A520(void);
+
+void sub_8153688(u8 taskId)
+{
+ s16* taskData = gTasks[taskId].data;
+
+ switch (taskData[0])
+ {
+ case 0:
+ gSoftResetDisabled = TRUE;
+ taskData[0] = 1;
+ break;
+ case 1:
+ sub_800ADF8();
+ taskData[0] = 2;
+ break;
+ case 2:
+ if (sub_800A520())
+ {
+ if (taskData[2] == 0)
+ save_serialize_map();
+ taskData[0] = 3;
+ }
+ break;
+ case 3:
+ if (taskData[2] == 0)
+ sub_8076D5C();
+ sub_8153380();
+ taskData[0] = 4;
+ break;
+ case 4:
+ if (++taskData[1] == 5)
+ {
+ taskData[1] = 0;
+ taskData[0] = 5;
+ }
+ break;
+ case 5:
+ if (sub_81533AC())
+ taskData[0] = 6;
+ else
+ taskData[0] = 4;
+ break;
+ case 6:
+ sub_81533E0();
+ taskData[0] = 7;
+ break;
+ case 7:
+ if (taskData[2] == 0)
+ sav2_gender2_inplace_and_xFE();
+ sub_800ADF8();
+ taskData[0] = 8;
+ break;
+ case 8:
+ if (sub_800A520())
+ {
+ sub_8153408();
+ taskData[0] = 9;
+ }
+ break;
+ case 9:
+ sub_800ADF8();
+ taskData[0] = 10;
+ break;
+ case 10:
+ if (sub_800A520())
+ taskData[0]++;
+ break;
+ case 11:
+ if (++taskData[1] > 5)
+ {
+ gSoftResetDisabled = FALSE;
+ DestroyTask(taskId);
+ }
+ break;
+ }
+}
diff --git a/src/scrcmd.c b/src/scrcmd.c
new file mode 100644
index 000000000..b56a53caf
--- /dev/null
+++ b/src/scrcmd.c
@@ -0,0 +1,15 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03000F30;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/script_menu.c b/src/script_menu.c
new file mode 100644
index 000000000..04f1e82b7
--- /dev/null
+++ b/src/script_menu.c
@@ -0,0 +1,16 @@
+
+// Includes
+#include "global.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+IWRAM_DATA u8 gUnknown_03001124[6];
+IWRAM_DATA u32 filler_0300112c;
+
+// Static ROM declarations
+
+// .rodata
+
+// .text
diff --git a/src/start_menu.c b/src/start_menu.c
index ffcab5220..ac393ce2e 100644
--- a/src/start_menu.c
+++ b/src/start_menu.c
@@ -151,7 +151,7 @@ static void BuildStartMenuActions_MultiBattleRoom(void)
extern const struct WindowTemplate gSafariBallsWindowTemplate;
extern const struct WindowTemplate gPyramidFloorWindowTemplate_1;
extern const struct WindowTemplate gPyramidFloorWindowTemplate_2;
-extern const u8 gOtherText_SafariStock[];
+extern const u8 gText_SafariBallStock[];
void DisplaySafariBallsWindow(void)
{
@@ -159,13 +159,13 @@ void DisplaySafariBallsWindow(void)
PutWindowTilemap(sSafariBallsWindowId);
sub_81973FC(sSafariBallsWindowId, 0);
ConvertIntToDecimalStringN(gStringVar1, gNumSafariBalls, STR_CONV_MODE_RIGHT_ALIGN, 2);
- StringExpandPlaceholders(gStringVar4, gOtherText_SafariStock);
+ StringExpandPlaceholders(gStringVar4, gText_SafariBallStock);
PrintTextOnWindow(sSafariBallsWindowId, 1, gStringVar4, 0, 1, 0xFF, NULL);
CopyWindowToVram(sSafariBallsWindowId, 2);
}
extern const u8* const gUnknown_08510510[];
-extern const u8 gOtherText_BattlePyramid_X[];
+extern const u8 gText_BattlePyramidFloor[];
void DisplayPyramidFloorWindow(void)
{
@@ -177,7 +177,7 @@ void DisplayPyramidFloorWindow(void)
PutWindowTilemap(sBattlePyramidFloorWindowId);
sub_81973FC(sBattlePyramidFloorWindowId, 0);
StringCopy(gStringVar1, gUnknown_08510510[*(u16*)(&gSaveBlock2Ptr->field_CAA[8])]);
- StringExpandPlaceholders(gStringVar4, gOtherText_BattlePyramid_X);
+ StringExpandPlaceholders(gStringVar4, gText_BattlePyramidFloor);
PrintTextOnWindow(sBattlePyramidFloorWindowId, 1, gStringVar4, 0, 1, 0xFF, NULL);
CopyWindowToVram(sBattlePyramidFloorWindowId, 2);
}
diff --git a/src/text.c b/src/text.c
index cad8326e3..7cc46cd92 100644
--- a/src/text.c
+++ b/src/text.c
@@ -1,9 +1,9 @@
#include "global.h"
-#include "text.h"
#include "main.h"
#include "palette.h"
#include "string_util.h"
#include "window.h"
+#include "text.h"
extern void FillBitmapRect4Bit(struct Bitmap *surface, u16 x, u16 y, u16 width, u16 height, u8 fillValue);
extern void FillWindowPixelRect(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16 height);
@@ -32,11 +32,7 @@ u8 gUnknown_03002FB0[0x20];
u8 gUnknown_03002FD0[0x20];
u8 gUnknown_03002FF0[0x20];
u8 gGlyphDimensions[0x2];
-struct {
- u8 flag_0:1;
- u8 flag_1:1;
- u8 flag_2:1;
-} gTextFlags;
+TextFlags gTextFlags;
const u8 gFontHalfRowOffsets[] = {
0x00, 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x03, 0x06, 0x07, 0x08, 0x06, 0x00, 0x01, 0x02, 0x00,
@@ -244,12 +240,11 @@ void RunTextPrinters(void)
}
}
-bool8 IsTextPrinterActive(u8 id)
+bool16 IsTextPrinterActive(u8 id)
{
return gTextPrinters[id].sub_union.sub.active;
}
-
u32 RenderFont(struct TextPrinter *textPrinter)
{
u32 ret;
@@ -1973,7 +1968,7 @@ bool8 TextPrinterWaitAutoMode(struct TextPrinter *textPrinter)
}
}
-bool8 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter)
+bool16 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter)
{
bool8 result = FALSE;
if (gTextFlags.flag_2 != 0)
@@ -1992,9 +1987,9 @@ bool8 TextPrinterWaitWithDownArrow(struct TextPrinter *textPrinter)
return result;
}
-bool8 TextPrinterWait(struct TextPrinter *textPrinter)
+bool16 TextPrinterWait(struct TextPrinter *textPrinter)
{
- bool8 result = FALSE;
+ bool16 result = FALSE;
if (gTextFlags.flag_2 != 0)
{
result = TextPrinterWaitAutoMode(textPrinter);
@@ -2779,7 +2774,7 @@ _08005D6E:\n\
bx r1");
}
-u32 GetStringWidthFixedWidthFont(u8 *str, u8 fontId, u8 letterSpacing)
+u32 GetStringWidthFixedWidthFont(const u8 *str, u8 fontId, u8 letterSpacing)
{
int i;
u8 width;
@@ -2788,7 +2783,7 @@ u32 GetStringWidthFixedWidthFont(u8 *str, u8 fontId, u8 letterSpacing)
u8 line;
int strPos;
u8 lineWidths[8];
- u8 *strLocal;
+ const u8 *strLocal;
for (i = 0; i < 8; i++)
{
@@ -2883,7 +2878,7 @@ u32 (*GetFontWidthFunc(u8 glyphId))(u16, bool32)
return 0;
}
-s32 GetStringWidth(u8 fontId, u8 *str, s16 letterSpacing)
+u32 GetStringWidth(u8 fontId, const u8 *str, s16 letterSpacing)
{
bool8 isJapanese;
int minGlyphWidth;
diff --git a/src/tileset_anims.c b/src/tileset_anims.c
new file mode 100644
index 000000000..e53461e02
--- /dev/null
+++ b/src/tileset_anims.c
@@ -0,0 +1,1411 @@
+
+// Includes
+#include "global.h"
+#include "palette.h"
+#include "blend_palette.h"
+#include "battle.h"
+#include "task.h"
+
+// Static type declarations
+
+// Static RAM declarations
+
+static EWRAM_DATA struct {
+ const u16 *src;
+ u16 *dest;
+ u16 size;
+} sTilesetDMA3TransferBuffer[20] = {0};
+
+static u8 sTilesetDMA3TransferBufferSize;
+static u16 sPrimaryTilesetCBCounter;
+static u16 sPrimaryTilesetCBBufferSize;
+static u16 sSecondaryTilesetCBCounter;
+static u16 sSecondaryTilesetCBBufferSize;
+static void (*sPrimaryTilesetCB)(u16);
+static void (*sSecondaryTilesetCB)(u16);
+
+// Static ROM declarations
+
+static void cur_mapheader_run_tileset1_func(void);
+static void cur_mapheader_run_tileset2_func(void);
+
+// .rodata
+
+
+const u16 gUnknown_085105C4[] = INCBIN_U16("data/tilesets/primary/general/anim/0/1.4bpp");
+
+const u16 gUnknown_08510644[] = INCBIN_U16("data/tilesets/primary/general/anim/0/0.4bpp");
+
+const u16 gUnknown_085106C4[] = INCBIN_U16("data/tilesets/primary/general/anim/0/2.4bpp");
+
+const u16 tileset_anims_space_0[16] = {};
+
+const u16 *const gTilesetAnims_General0[] = {
+ gUnknown_08510644,
+ gUnknown_085105C4,
+ gUnknown_08510644,
+ gUnknown_085106C4
+};
+
+const u16 gUnknown_08510774[] = INCBIN_U16("data/tilesets/primary/general/anim/1/0.4bpp");
+
+const u16 gUnknown_08510B34[] = INCBIN_U16("data/tilesets/primary/general/anim/1/1.4bpp");
+
+const u16 gUnknown_08510EF4[] = INCBIN_U16("data/tilesets/primary/general/anim/1/2.4bpp");
+
+const u16 gUnknown_085112B4[] = INCBIN_U16("data/tilesets/primary/general/anim/1/3.4bpp");
+
+const u16 gUnknown_08511674[] = INCBIN_U16("data/tilesets/primary/general/anim/1/4.4bpp");
+
+const u16 gUnknown_08511A34[] = INCBIN_U16("data/tilesets/primary/general/anim/1/5.4bpp");
+
+const u16 gUnknown_08511DF4[] = INCBIN_U16("data/tilesets/primary/general/anim/1/6.4bpp");
+
+const u16 gUnknown_085121B4[] = INCBIN_U16("data/tilesets/primary/general/anim/1/7.4bpp");
+
+const u16 *const gTilesetAnims_General1[] = {
+ gUnknown_08510774,
+ gUnknown_08510B34,
+ gUnknown_08510EF4,
+ gUnknown_085112B4,
+ gUnknown_08511674,
+ gUnknown_08511A34,
+ gUnknown_08511DF4,
+ gUnknown_085121B4
+};
+
+const u16 gUnknown_08512594[] = INCBIN_U16("data/tilesets/primary/general/anim/2/0.4bpp");
+
+const u16 gUnknown_085126D4[] = INCBIN_U16("data/tilesets/primary/general/anim/2/1.4bpp");
+
+const u16 gUnknown_08512814[] = INCBIN_U16("data/tilesets/primary/general/anim/2/2.4bpp");
+
+const u16 gUnknown_08512954[] = INCBIN_U16("data/tilesets/primary/general/anim/2/3.4bpp");
+
+const u16 gUnknown_08512A94[] = INCBIN_U16("data/tilesets/primary/general/anim/2/4.4bpp");
+
+const u16 gUnknown_08512BD4[] = INCBIN_U16("data/tilesets/primary/general/anim/2/5.4bpp");
+
+const u16 gUnknown_08512D14[] = INCBIN_U16("data/tilesets/primary/general/anim/2/6.4bpp");
+
+const u16 *const gTilesetAnims_General2[] = {
+ gUnknown_08512594,
+ gUnknown_085126D4,
+ gUnknown_08512814,
+ gUnknown_08512954,
+ gUnknown_08512A94,
+ gUnknown_08512BD4,
+ gUnknown_08512D14,
+ gUnknown_08512594
+};
+
+const u16 gUnknown_08512E74[] = INCBIN_U16("data/tilesets/primary/general/anim/3/0.4bpp");
+
+const u16 gUnknown_08512F34[] = INCBIN_U16("data/tilesets/primary/general/anim/3/1.4bpp");
+
+const u16 gUnknown_08512FF4[] = INCBIN_U16("data/tilesets/primary/general/anim/3/2.4bpp");
+
+const u16 gUnknown_085130B4[] = INCBIN_U16("data/tilesets/primary/general/anim/3/3.4bpp");
+
+const u16 *const gTilesetAnims_General3[] = {
+ gUnknown_08512E74,
+ gUnknown_08512F34,
+ gUnknown_08512FF4,
+ gUnknown_085130B4
+};
+
+const u16 gUnknown_08513184[] = INCBIN_U16("data/tilesets/primary/general/anim/4/0.4bpp");
+
+const u16 gUnknown_085132C4[] = INCBIN_U16("data/tilesets/primary/general/anim/4/1.4bpp");
+
+const u16 gUnknown_08513404[] = INCBIN_U16("data/tilesets/primary/general/anim/4/2.4bpp");
+
+const u16 gUnknown_08513544[] = INCBIN_U16("data/tilesets/primary/general/anim/4/3.4bpp");
+
+const u16 *const gTilesetAnims_General4[] = {
+ gUnknown_08513184,
+ gUnknown_085132C4,
+ gUnknown_08513404,
+ gUnknown_08513544
+};
+
+const u16 gUnknown_08513694[] = INCBIN_U16("data/tilesets/secondary/lavaridge/anim/0.4bpp");
+
+const u16 gUnknown_08513714[] = INCBIN_U16("data/tilesets/secondary/lavaridge/anim/1.4bpp");
+
+const u16 gUnknown_08513794[] = INCBIN_U16("data/tilesets/secondary/lavaridge/anim/2.4bpp");
+
+const u16 gUnknown_08513814[] = INCBIN_U16("data/tilesets/secondary/lavaridge/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_Lavaridge0[] = {
+ gUnknown_08513694,
+ gUnknown_08513714,
+ gUnknown_08513794,
+ gUnknown_08513814
+};
+
+const u16 gUnknown_085138A4[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/0/0.4bpp");
+
+const u16 gUnknown_08513C64[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/0/1.4bpp");
+
+const u16 gUnknown_08514024[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/0/2.4bpp");
+
+const u16 *const gTilesetAnims_Pacifidlog0[] = {
+ gUnknown_085138A4,
+ gUnknown_08513C64,
+ gUnknown_08514024,
+ gUnknown_08513C64
+};
+
+const u16 gUnknown_085143F4[] = INCBIN_U16("data/tilesets/secondary/underwater/anim/0.4bpp");
+
+const u16 gUnknown_08514474[] = INCBIN_U16("data/tilesets/secondary/underwater/anim/1.4bpp");
+
+const u16 gUnknown_085144F4[] = INCBIN_U16("data/tilesets/secondary/underwater/anim/2.4bpp");
+
+const u16 gUnknown_08514574[] = INCBIN_U16("data/tilesets/secondary/underwater/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_Underwater0[] = {
+ gUnknown_085143F4,
+ gUnknown_08514474,
+ gUnknown_085144F4,
+ gUnknown_08514574
+};
+
+const u16 gUnknown_08514604[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/0.4bpp");
+
+const u16 gUnknown_08514704[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/1.4bpp");
+
+const u16 gUnknown_08514804[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/2.4bpp");
+
+const u16 gUnknown_08514904[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/3.4bpp");
+
+const u16 gUnknown_08514A04[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/4.4bpp");
+
+const u16 gUnknown_08514B04[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/5.4bpp");
+
+const u16 gUnknown_08514C04[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/6.4bpp");
+
+const u16 gUnknown_08514D04[] = INCBIN_U16("data/tilesets/secondary/pacifidlog/anim/1/7.4bpp");
+
+const u16 *const gTilesetAnims_Pacifidlog1[] = {
+ gUnknown_08514604,
+ gUnknown_08514704,
+ gUnknown_08514804,
+ gUnknown_08514904,
+ gUnknown_08514A04,
+ gUnknown_08514B04,
+ gUnknown_08514C04,
+ gUnknown_08514D04
+};
+
+const u16 gUnknown_08514E24[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/a/0.4bpp");
+
+const u16 gUnknown_08514EA4[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/a/1.4bpp");
+
+const u16 gUnknown_08514F24[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/a/2.4bpp");
+
+const u16 gUnknown_08514FA4[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/a/3.4bpp");
+
+const u16 gUnknown_08515024[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/1/a/1.4bpp");
+
+const u16 gUnknown_085150A4[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/b/0.4bpp");
+
+const u16 gUnknown_08515124[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/b/1.4bpp");
+
+const u16 gUnknown_085151A4[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/b/2.4bpp");
+
+const u16 gUnknown_08515224[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/0/b/3.4bpp");
+
+const u16 gUnknown_085152A4[] = INCBIN_U16("data/tilesets/secondary/mauville/anim/1/b/1.4bpp");
+
+const u16 tileset_anims_space_1[16] = {};
+
+u16 *const gTilesetAnims_MauvilleVDests0[] = {
+ (u16 *)(BG_VRAM + 0x4c00),
+ (u16 *)(BG_VRAM + 0x4c80),
+ (u16 *)(BG_VRAM + 0x4d00),
+ (u16 *)(BG_VRAM + 0x4d80),
+ (u16 *)(BG_VRAM + 0x4e00),
+ (u16 *)(BG_VRAM + 0x4e80),
+ (u16 *)(BG_VRAM + 0x4f00),
+ (u16 *)(BG_VRAM + 0x4f80)
+};
+
+u16 *const gTilesetAnims_MauvilleVDests1[] = {
+ (u16 *)(BG_VRAM + 0x5000),
+ (u16 *)(BG_VRAM + 0x5080),
+ (u16 *)(BG_VRAM + 0x5100),
+ (u16 *)(BG_VRAM + 0x5180),
+ (u16 *)(BG_VRAM + 0x5200),
+ (u16 *)(BG_VRAM + 0x5280),
+ (u16 *)(BG_VRAM + 0x5300),
+ (u16 *)(BG_VRAM + 0x5380)
+};
+
+const u16 *const gTilesetAnims_Mauville0a[] = {
+ gUnknown_08514E24,
+ gUnknown_08514E24,
+ gUnknown_08514EA4,
+ gUnknown_08514F24,
+ gUnknown_08514FA4,
+ gUnknown_08514FA4,
+ gUnknown_08514FA4,
+ gUnknown_08514FA4,
+ gUnknown_08514FA4,
+ gUnknown_08514FA4,
+ gUnknown_08514F24,
+ gUnknown_08514EA4
+};
+
+const u16 *const gTilesetAnims_Mauville0b[] = {
+ gUnknown_085150A4,
+ gUnknown_085150A4,
+ gUnknown_08515124,
+ gUnknown_085151A4,
+ gUnknown_08515224,
+ gUnknown_08515224,
+ gUnknown_08515224,
+ gUnknown_08515224,
+ gUnknown_08515224,
+ gUnknown_08515224,
+ gUnknown_085151A4,
+ gUnknown_08515124
+};
+
+const u16 *const gTilesetAnims_Mauville1a[] = {
+ gUnknown_08514E24,
+ gUnknown_08514E24,
+ gUnknown_08515024,
+ gUnknown_08515024
+};
+
+const u16 *const gTilesetAnims_Mauville1b[] = {
+ gUnknown_085150A4,
+ gUnknown_085150A4,
+ gUnknown_085152A4,
+ gUnknown_085152A4
+};
+
+const u16 gUnknown_08515404[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/0.4bpp");
+
+const u16 gUnknown_08515484[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/1.4bpp");
+
+const u16 gUnknown_08515504[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/2.4bpp");
+
+const u16 gUnknown_08515584[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/3.4bpp");
+
+const u16 gUnknown_08515604[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/4.4bpp");
+
+const u16 gUnknown_08515684[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/5.4bpp");
+
+const u16 gUnknown_08515704[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/6.4bpp");
+
+const u16 gUnknown_08515784[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/0/7.4bpp");
+
+u16 *const gTilesetAnims_RustboroVDests0[] = {
+ (u16 *)(BG_VRAM + 0x5000),
+ (u16 *)(BG_VRAM + 0x5080),
+ (u16 *)(BG_VRAM + 0x5100),
+ (u16 *)(BG_VRAM + 0x5180),
+ (u16 *)(BG_VRAM + 0x5200),
+ (u16 *)(BG_VRAM + 0x5280),
+ (u16 *)(BG_VRAM + 0x5300),
+ (u16 *)(BG_VRAM + 0x5380)
+};
+
+const u16 *const gTilesetAnims_Rustboro0[] = {
+ gUnknown_08515404,
+ gUnknown_08515484,
+ gUnknown_08515504,
+ gUnknown_08515584,
+ gUnknown_08515604,
+ gUnknown_08515684,
+ gUnknown_08515704,
+ gUnknown_08515784
+};
+
+const u16 gUnknown_08515844[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/1/0.4bpp");
+
+const u16 gUnknown_085158C4[] = INCBIN_U16("data/tilesets/secondary/rustboro/anim/1/1.4bpp");
+
+const u16 tileset_anims_space_2[16] = {};
+
+const u16 *const gTilesetAnims_Rustboro1[] = {
+ gUnknown_08515844,
+ gUnknown_085158C4
+};
+
+const u16 gUnknown_0851596C[] = INCBIN_U16("data/tilesets/secondary/cave/anim/0.4bpp");
+
+const u16 gUnknown_085159EC[] = INCBIN_U16("data/tilesets/secondary/cave/anim/1.4bpp");
+
+const u16 gUnknown_08515A6C[] = INCBIN_U16("data/tilesets/secondary/cave/anim/2.4bpp");
+
+const u16 gUnknown_08515AEC[] = INCBIN_U16("data/tilesets/secondary/cave/anim/3.4bpp");
+
+const u16 gUnknown_08515B6C[] = INCBIN_U16("data/tilesets/secondary/cave/anim/unused/0.4bpp");
+
+const u16 gUnknown_08515BEC[] = INCBIN_U16("data/tilesets/secondary/cave/anim/unused/1.4bpp");
+
+const u16 gUnknown_08515C6C[] = INCBIN_U16("data/tilesets/secondary/cave/anim/unused/2.4bpp");
+
+const u16 gUnknown_08515CEC[] = INCBIN_U16("data/tilesets/secondary/cave/anim/unused/3.4bpp");
+
+const u16 tileset_anims_space_3[16] = {};
+
+const u16 *const gTilesetAnims_Lavaridge1_Cave0[] = {
+ gUnknown_0851596C,
+ gUnknown_085159EC,
+ gUnknown_08515A6C,
+ gUnknown_08515AEC
+};
+
+const u16 gUnknown_08515D9C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/0.4bpp");
+
+const u16 gUnknown_08515E1C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/1.4bpp");
+
+const u16 gUnknown_08515E9C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/2.4bpp");
+
+const u16 gUnknown_08515F1C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/3.4bpp");
+
+const u16 gUnknown_08515F9C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/4.4bpp");
+
+const u16 gUnknown_0851601C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/5.4bpp");
+
+const u16 gUnknown_0851609C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/6.4bpp");
+
+const u16 gUnknown_0851611C[] = INCBIN_U16("data/tilesets/secondary/ever_grande/anim/7.4bpp");
+
+const u16 tileset_anims_space_4[16] = {};
+
+u16 *const gTilesetAnims_EverGrandeVDests0[] = {
+ (u16 *)(BG_VRAM + 0x5c00),
+ (u16 *)(BG_VRAM + 0x5c80),
+ (u16 *)(BG_VRAM + 0x5d00),
+ (u16 *)(BG_VRAM + 0x5d80),
+ (u16 *)(BG_VRAM + 0x5e00),
+ (u16 *)(BG_VRAM + 0x5e80),
+ (u16 *)(BG_VRAM + 0x5f00),
+ (u16 *)(BG_VRAM + 0x5f80)
+};
+
+const u16 *const gTilesetAnims_EverGrande0[] = {
+ gUnknown_08515D9C,
+ gUnknown_08515E1C,
+ gUnknown_08515E9C,
+ gUnknown_08515F1C,
+ gUnknown_08515F9C,
+ gUnknown_0851601C,
+ gUnknown_0851609C,
+ gUnknown_0851611C
+};
+
+const u16 gUnknown_085161FC[] = INCBIN_U16("data/tilesets/secondary/dewford/anim/0.4bpp");
+
+const u16 gUnknown_085162BC[] = INCBIN_U16("data/tilesets/secondary/dewford/anim/1.4bpp");
+
+const u16 gUnknown_0851637C[] = INCBIN_U16("data/tilesets/secondary/dewford/anim/2.4bpp");
+
+const u16 gUnknown_0851643C[] = INCBIN_U16("data/tilesets/secondary/dewford/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_Dewford0[] = {
+ gUnknown_085161FC,
+ gUnknown_085162BC,
+ gUnknown_0851637C,
+ gUnknown_0851643C
+};
+
+const u16 gUnknown_0851650C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_west/anim/0.4bpp");
+
+const u16 gUnknown_085165CC[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_west/anim/1.4bpp");
+
+const u16 gUnknown_0851668C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_west/anim/2.4bpp");
+
+const u16 gUnknown_0851674C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_west/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_BattleFrontierOutsideWest0[] = {
+ gUnknown_0851650C,
+ gUnknown_085165CC,
+ gUnknown_0851668C,
+ gUnknown_0851674C
+};
+
+const u16 gUnknown_0851681C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_east/anim/0.4bpp");
+
+const u16 gUnknown_085168DC[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_east/anim/1.4bpp");
+
+const u16 gUnknown_0851699C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_east/anim/2.4bpp");
+
+const u16 gUnknown_08516A5C[] = INCBIN_U16("data/tilesets/secondary/battle_frontier_outside_east/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_BattleFrontierOutsideEast0[] = {
+ gUnknown_0851681C,
+ gUnknown_085168DC,
+ gUnknown_0851699C,
+ gUnknown_08516A5C
+};
+
+const u16 gUnknown_08516B2C[] = INCBIN_U16("data/tilesets/secondary/slateport/anim/0.4bpp");
+
+const u16 gUnknown_08516BAC[] = INCBIN_U16("data/tilesets/secondary/slateport/anim/1.4bpp");
+
+const u16 gUnknown_08516C2C[] = INCBIN_U16("data/tilesets/secondary/slateport/anim/2.4bpp");
+
+const u16 gUnknown_08516CAC[] = INCBIN_U16("data/tilesets/secondary/slateport/anim/3.4bpp");
+
+const u16 *const gTilesetAnims_Slateport0[] = {
+ gUnknown_08516B2C,
+ gUnknown_08516BAC,
+ gUnknown_08516C2C,
+ gUnknown_08516CAC
+};
+
+const u16 gUnknown_08516D3C[] = INCBIN_U16("data/tilesets/primary/building/anim/0.4bpp");
+
+const u16 gUnknown_08516DBC[] = INCBIN_U16("data/tilesets/primary/building/anim/1.4bpp");
+
+const u16 *const gTilesetAnims_InsideBuilding0[] = {
+ gUnknown_08516D3C,
+ gUnknown_08516DBC
+};
+
+const u16 gUnknown_08516E44[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/0/0.4bpp");
+
+const u16 gUnknown_08516FC4[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/0/1.4bpp");
+
+const u16 gUnknown_08517144[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/0/2.4bpp");
+
+const u16 gUnknown_085172C4[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/1/0.4bpp");
+
+const u16 gUnknown_08517544[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/1/1.4bpp");
+
+const u16 gUnknown_085177C4[] = INCBIN_U16("data/tilesets/secondary/sootopolis_gym/anim/1/2.4bpp");
+
+const u16 *const gTilesetAnims_SootopolisGym0[] = {
+ gUnknown_08516E44,
+ gUnknown_08516FC4,
+ gUnknown_08517144
+};
+
+const u16 *const gTilesetAnims_SootopolisGym1[] = {
+ gUnknown_085172C4,
+ gUnknown_08517544,
+ gUnknown_085177C4
+};
+
+const u16 gUnknown_08517A5C[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/1/0.4bpp");
+
+const u16 gUnknown_08517ADC[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/1/1.4bpp");
+
+const u16 gUnknown_08517B5C[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/0/0.4bpp");
+
+const u16 gUnknown_08517B7C[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/0/1.4bpp");
+
+const u16 gUnknown_08517B9C[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/0/2.4bpp");
+
+const u16 gUnknown_08517BBC[] = INCBIN_U16("data/tilesets/secondary/elite_four/anim/0/3.4bpp");
+
+const u16 tileset_anims_space_5[16] = {};
+
+const u16 *const gTilesetAnims_EliteFour1[] = {
+ gUnknown_08517B5C,
+ gUnknown_08517B7C,
+ gUnknown_08517B9C,
+ gUnknown_08517BBC
+};
+
+const u16 *const gTilesetAnims_EliteFour0[] = {
+ gUnknown_08517A5C,
+ gUnknown_08517ADC
+};
+
+const u16 gUnknown_08517C14[] = INCBIN_U16("data/tilesets/secondary/mauville_gym/anim/0.4bpp");
+
+const u16 gUnknown_08517E14[] = INCBIN_U16("data/tilesets/secondary/mauville_gym/anim/1.4bpp");
+
+const u16 tileset_anims_space_6[16] = {};
+
+const u16 *const gTilesetAnims_MauvilleGym0[] = {
+ gUnknown_08517C14,
+ gUnknown_08517E14
+};
+
+const u16 gUnknown_0851803C[] = INCBIN_U16("data/tilesets/secondary/bike_shop/anim/0.4bpp");
+
+const u16 gUnknown_0851815C[] = INCBIN_U16("data/tilesets/secondary/bike_shop/anim/1.4bpp");
+
+const u16 tileset_anims_space_7[16] = {};
+
+const u16 *const gTilesetAnims_BikeShop0[] = {
+ gUnknown_0851803C,
+ gUnknown_0851815C
+};
+
+const u16 gUnknown_085182A4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/0.4bpp");
+
+const u16 gUnknown_08518EA4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/1.4bpp");
+
+const u16 gUnknown_08519AA4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/2.4bpp");
+
+const u16 gUnknown_0851A6A4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/3.4bpp");
+
+const u16 gUnknown_0851B2A4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/4.4bpp");
+
+const u16 gUnknown_0851BEA4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/5.4bpp");
+
+const u16 gUnknown_0851CAA4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/6.4bpp");
+
+const u16 gUnknown_0851D6A4[] = INCBIN_U16("data/tilesets/secondary/sootopolis/anim/7.4bpp");
+
+const u16 tileset_anims_space_8[16] = {};
+
+const u16 gUnknown_0851E2C4[] = INCBIN_U16("data/tilesets/secondary/unused_1/0.4bpp");
+
+const u16 gUnknown_0851EAC4[] = INCBIN_U16("data/tilesets/secondary/unused_1/1.4bpp");
+
+const u16 gUnknown_0851F2C4[] = INCBIN_U16("data/tilesets/secondary/unused_1/2.4bpp");
+
+const u16 gUnknown_0851FAC4[] = INCBIN_U16("data/tilesets/secondary/unused_1/3.4bpp");
+
+const u16 *const gTilesetAnims_Sootopolis0[] = {
+ gUnknown_085182A4,
+ gUnknown_08518EA4,
+ gUnknown_08519AA4,
+ gUnknown_0851A6A4,
+ gUnknown_0851B2A4,
+ gUnknown_0851BEA4,
+ gUnknown_0851CAA4,
+ gUnknown_0851D6A4
+};
+
+const u16 gUnknown_085202E4[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/0/0.4bpp");
+
+const u16 gUnknown_085203E4[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/0/1.4bpp");
+
+const u16 gUnknown_085204E4[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/0/2.4bpp");
+
+const u16 tileset_anims_space_9[16] = {};
+
+const u16 gUnknown_08520604[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/1/0.4bpp");
+
+const u16 gUnknown_08520704[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/1/1.4bpp");
+
+const u16 gUnknown_08520804[] = INCBIN_U16("data/tilesets/secondary/battle_pyramid/anim/1/2.4bpp");
+
+const u16 tileset_anims_space_10[7808] = {};
+
+const u16 gUnknown_08524604[] = INCBIN_U16("data/tilesets/secondary/unused_2/0.4bpp");
+
+const u16 tileset_anims_space_11[224] = {};
+
+const u16 gUnknown_08524804[] = INCBIN_U16("data/tilesets/secondary/unused_2/1.4bpp");
+
+const u16 *const gTilesetAnims_BattlePyramid0[] = {
+ gUnknown_085202E4,
+ gUnknown_085203E4,
+ gUnknown_085204E4
+};
+
+const u16 *const gTilesetAnims_BattlePyramid1[] = {
+ gUnknown_08520604,
+ gUnknown_08520704,
+ gUnknown_08520804
+};
+
+extern const u16 gUnknown_08D85640[];
+extern const u16 gUnknown_08D85660[];
+extern const u16 gUnknown_08D85680[];
+extern const u16 gUnknown_08D856A0[];
+
+static const u16 *const gTilesetAnims_BattleDomePals0[] = {
+ gUnknown_08D85640,
+ gUnknown_08D85660,
+ gUnknown_08D85680,
+ gUnknown_08D856A0,
+};
+
+// .text
+
+static void ResetTilesetAnimBuffer(void)
+{
+ sTilesetDMA3TransferBufferSize = 0;
+ CpuFill32(0, sTilesetDMA3TransferBuffer, sizeof sTilesetDMA3TransferBuffer);
+}
+
+static void AppendTilesetAnimToBuffer(const u16 *src, u16 *dest, u16 size)
+{
+ if (sTilesetDMA3TransferBufferSize < 20)
+ {
+ sTilesetDMA3TransferBuffer[sTilesetDMA3TransferBufferSize].src = src;
+ sTilesetDMA3TransferBuffer[sTilesetDMA3TransferBufferSize].dest = dest;
+ sTilesetDMA3TransferBuffer[sTilesetDMA3TransferBufferSize].size = size;
+ sTilesetDMA3TransferBufferSize ++;
+ }
+}
+
+void TransferTilesetAnimsBuffer(void)
+{
+ int i;
+
+ for (i = 0; i < sTilesetDMA3TransferBufferSize; i ++)
+ {
+ DmaCopy16(3, sTilesetDMA3TransferBuffer[i].src, sTilesetDMA3TransferBuffer[i].dest, sTilesetDMA3TransferBuffer[i].size);
+ }
+ sTilesetDMA3TransferBufferSize = 0;
+}
+
+void cur_mapheader_run_tileset_funcs_after_some_cpuset(void)
+{
+ ResetTilesetAnimBuffer();
+ cur_mapheader_run_tileset1_func();
+ cur_mapheader_run_tileset2_func();
+}
+
+void sub_80A0A2C(void)
+{
+ cur_mapheader_run_tileset2_func();
+}
+
+void sub_80A0A38(void)
+{
+ ResetTilesetAnimBuffer();
+ if (++sPrimaryTilesetCBCounter >= sPrimaryTilesetCBBufferSize)
+ sPrimaryTilesetCBCounter = 0;
+ if (++sSecondaryTilesetCBCounter >= sSecondaryTilesetCBBufferSize)
+ sSecondaryTilesetCBCounter = 0;
+ if (sPrimaryTilesetCB)
+ sPrimaryTilesetCB(sPrimaryTilesetCBCounter);
+ if (sSecondaryTilesetCB)
+ sSecondaryTilesetCB(sSecondaryTilesetCBCounter);
+}
+
+static void cur_mapheader_run_tileset1_func(void)
+{
+ sPrimaryTilesetCBCounter = 0;
+ sPrimaryTilesetCBBufferSize = 0;
+ sPrimaryTilesetCB = NULL;
+ if (gMapHeader.mapData->primaryTileset && gMapHeader.mapData->primaryTileset->callback)
+ gMapHeader.mapData->primaryTileset->callback();
+}
+
+static void cur_mapheader_run_tileset2_func(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = 0;
+ sSecondaryTilesetCB = NULL;
+ if (gMapHeader.mapData->secondaryTileset && gMapHeader.mapData->secondaryTileset->callback)
+ gMapHeader.mapData->secondaryTileset->callback();
+}
+
+void TilesetCb_General(void)
+{
+ static void sub_80A0B70(u16);
+
+ sPrimaryTilesetCBCounter = 0;
+ sPrimaryTilesetCBBufferSize = 0x100;
+ sPrimaryTilesetCB = sub_80A0B70;
+}
+
+void TilesetCb_InsideBuilding(void)
+{
+ static void sub_80A0BB4(u16);
+
+ sPrimaryTilesetCBCounter = 0;
+ sPrimaryTilesetCBBufferSize = 0x100;
+ sPrimaryTilesetCB = sub_80A0BB4;
+}
+
+static void sub_80A0B70(u16 timer)
+{
+ static void sub_80A0BCC(u16);
+ static void sub_80A0BF4(u16);
+ static void sub_80A0C1C(u16);
+ static void sub_80A0C44(u16);
+ static void sub_80A12AC(u16);
+
+ if ((timer & 0x0F) == 0)
+ sub_80A0BCC(timer >> 4);
+ if ((timer & 0x0F) == 1)
+ sub_80A0BF4(timer >> 4);
+ if ((timer & 0x0F) == 2)
+ sub_80A0C1C(timer >> 4);
+ if ((timer & 0x0F) == 3)
+ sub_80A0C44(timer >> 4);
+ if ((timer & 0x0F) == 4)
+ sub_80A12AC(timer >> 4);
+}
+
+static void sub_80A0BB4(u16 timer)
+{
+ static void sub_80A1688(u16);
+
+ if ((timer & 0x7) == 0)
+ sub_80A1688(timer >> 3);
+}
+
+static void sub_80A0BCC(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_General0[idx], (u16 *)(BG_VRAM + 0x3F80), 0x80);
+}
+
+static void sub_80A0BF4(u16 timer)
+{
+ u8 idx;
+
+ idx = timer % 8;
+ AppendTilesetAnimToBuffer(gTilesetAnims_General1[idx], (u16 *)(BG_VRAM + 0x3600), 0x3C0);
+}
+
+static void sub_80A0C1C(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 8;
+ AppendTilesetAnimToBuffer(gTilesetAnims_General2[idx], (u16 *)(BG_VRAM + 0x3a00), 0x140);
+}
+
+static void sub_80A0C44(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_General3[idx], (u16 *)(BG_VRAM + 0x3e00), 0xc0);
+}
+
+void TilesetCb_Petalburg(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = NULL;
+}
+
+void TilesetCb_Rustboro(void)
+{
+ static void sub_80A103C(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A103C;
+}
+
+void TilesetCb_Dewford(void)
+{
+ static void sub_80A10B8(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A10B8;
+}
+
+void TilesetCb_Slateport(void)
+{
+ static void sub_80A10D0(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A10D0;
+}
+
+void TilesetCb_Mauville(void)
+{
+ static void sub_80A10E8(u16);
+
+ sSecondaryTilesetCBCounter = sPrimaryTilesetCBCounter;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A10E8;
+}
+
+void TilesetCb_Lavaridge(void)
+{
+ static void sub_80A115C(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A115C;
+}
+
+void TilesetCb_Fallarbor(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = NULL;
+}
+
+void TilesetCb_Fortree(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = NULL;
+}
+
+void TilesetCb_Lilycove(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = NULL;
+}
+
+void TilesetCb_Mossdeep(void)
+{
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = NULL;
+}
+
+void TilesetCb_EverGrande(void)
+{
+ static void sub_80A1188(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A1188;
+}
+
+void TilesetCb_Pacifidlog(void)
+{
+ static void sub_80A11FC(u16);
+
+ sSecondaryTilesetCBCounter = sPrimaryTilesetCBCounter;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A11FC;
+}
+
+void TilesetCb_Sootopolis(void)
+{
+ static void sub_80A122C(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A122C;
+}
+
+void TilesetCb_BattleFrontierOutsideWest(void)
+{
+ static void sub_80A127C(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A127C;
+}
+
+void TilesetCb_BattleFrontierOutsideEast(void)
+{
+ static void sub_80A1294(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A1294;
+}
+
+void TilesetCb_Underwater(void)
+{
+ static void sub_80A1244(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = 128;
+ sSecondaryTilesetCB = sub_80A1244;
+}
+
+void TilesetCb_SootopolisGym(void)
+{
+ static void sub_80A15D8(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = 240;
+ sSecondaryTilesetCB = sub_80A15D8;
+}
+
+void TilesetCb_Cave(void)
+{
+ static void sub_80A1260(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A1260;
+}
+
+void TilesetCb_EliteFour(void)
+{
+ static void sub_80A15F0(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = 128;
+ sSecondaryTilesetCB = sub_80A15F0;
+}
+
+void TilesetCb_MauvilleGym(void)
+{
+ static void sub_80A15C0(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A15C0;
+}
+
+void TilesetCb_BikeShop(void)
+{
+ static void sub_80A161C(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A161C;
+}
+
+void TilesetCb_BattlePyramid(void)
+{
+ static void sub_80A1634(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A1634;
+}
+
+void TilesetCb_BattleDome(void)
+{
+ static void sub_80A1658(u16);
+
+ sSecondaryTilesetCBCounter = 0;
+ sSecondaryTilesetCBBufferSize = sPrimaryTilesetCBBufferSize;
+ sSecondaryTilesetCB = sub_80A1658;
+}
+
+static void sub_80A103C(u16 timer)
+{
+ static void sub_80A1434(u16, u8);
+ static void sub_80A1470(u16);
+
+ if ((timer & 0x07) == 0)
+ {
+ sub_80A1434(timer >> 3, 0);
+ sub_80A1470(timer >> 3);
+ }
+ if ((timer & 0x07) == 1)
+ sub_80A1434(timer >> 3, 1);
+ if ((timer & 0x07) == 2)
+ sub_80A1434(timer >> 3, 2);
+ if ((timer & 0x07) == 3)
+ sub_80A1434(timer >> 3, 3);
+ if ((timer & 0x07) == 4)
+ sub_80A1434(timer >> 3, 4);
+ if ((timer & 0x07) == 5)
+ sub_80A1434(timer >> 3, 5);
+ if ((timer & 0x07) == 6)
+ sub_80A1434(timer >> 3, 6);
+ if ((timer & 0x07) == 7)
+ sub_80A1434(timer >> 3, 7);
+}
+
+static void sub_80A10B8(u16 timer)
+{
+ static void sub_80A1520(u16);
+
+ if ((timer & 7) == 0)
+ sub_80A1520(timer >> 3);
+}
+
+static void sub_80A10D0(u16 timer)
+{
+ static void sub_80A1598(u16);
+
+ if ((timer & 15) == 0)
+ sub_80A1598(timer >> 4);
+}
+
+static void sub_80A10E8(u16 timer)
+{
+ static void sub_80A1394(u16, u8);
+
+ if ((timer & 0x07) == 0)
+ sub_80A1394(timer >> 3, 0);
+ if ((timer & 0x07) == 1)
+ sub_80A1394(timer >> 3, 1);
+ if ((timer & 0x07) == 2)
+ sub_80A1394(timer >> 3, 2);
+ if ((timer & 0x07) == 3)
+ sub_80A1394(timer >> 3, 3);
+ if ((timer & 0x07) == 4)
+ sub_80A1394(timer >> 3, 4);
+ if ((timer & 0x07) == 5)
+ sub_80A1394(timer >> 3, 5);
+ if ((timer & 0x07) == 6)
+ sub_80A1394(timer >> 3, 6);
+ if ((timer & 0x07) == 7)
+ sub_80A1394(timer >> 3, 7);
+}
+
+static void sub_80A115C(u16 timer)
+{
+ static void sub_80A12D4(u8);
+ static void sub_80A1498(u16);
+
+ if ((timer & 0x0F) == 0)
+ sub_80A12D4(timer >> 4);
+ if ((timer & 0x0F) == 1)
+ sub_80A1498(timer >> 4);
+}
+
+static void sub_80A1188(u16 timer)
+{
+ static void sub_80A14C0(u16, u8);
+
+ if ((timer & 0x07) == 0)
+ sub_80A14C0(timer >> 3, 0);
+ if ((timer & 0x07) == 1)
+ sub_80A14C0(timer >> 3, 1);
+ if ((timer & 0x07) == 2)
+ sub_80A14C0(timer >> 3, 2);
+ if ((timer & 0x07) == 3)
+ sub_80A14C0(timer >> 3, 3);
+ if ((timer & 0x07) == 4)
+ sub_80A14C0(timer >> 3, 4);
+ if ((timer & 0x07) == 5)
+ sub_80A14C0(timer >> 3, 5);
+ if ((timer & 0x07) == 6)
+ sub_80A14C0(timer >> 3, 6);
+ if ((timer & 0x07) == 7)
+ sub_80A14C0(timer >> 3, 7);
+}
+
+static void sub_80A11FC(u16 timer)
+{
+ static void sub_80A131C(u8);
+ static void sub_80A136C(u8);
+
+ if ((timer & 0x0F) == 0)
+ sub_80A131C(timer >> 4);
+ if ((timer & 0x0F) == 1)
+ sub_80A136C(timer >> 4);
+}
+
+static void sub_80A122C(u16 timer)
+{
+ static void sub_80A1798(u16);
+
+ if ((timer & 0x0F) == 0)
+ sub_80A1798(timer >> 4);
+}
+
+static void sub_80A1244(u16 timer)
+{
+ static void sub_80A1344(u8);
+
+ if ((timer & 0x0F) == 0)
+ sub_80A1344(timer >> 4);
+}
+
+static void sub_80A1260(u16 timer)
+{
+ static void sub_80A14F8(u16);
+
+ if ((timer & 0x0F) == 1)
+ sub_80A14F8(timer >> 4);
+}
+
+static void sub_80A127C(u16 timer)
+{
+ static void sub_80A1548(u16);
+
+ if ((timer & 0x07) == 0)
+ sub_80A1548(timer >> 3);
+}
+
+static void sub_80A1294(u16 timer)
+{
+ static void sub_80A1570(u16);
+
+ if ((timer & 0x07) == 0)
+ sub_80A1570(timer >> 3);
+}
+
+static void sub_80A12AC(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_General4[idx], (u16 *)(BG_VRAM + 0x3c00), 0x140);
+}
+
+static void sub_80A12D4(u8 timer)
+{
+ u8 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Lavaridge0[idx], (u16 *)(BG_VRAM + 0x6400), 0x80);
+
+ idx = (timer + 2) % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Lavaridge0[idx], (u16 *)(BG_VRAM + 0x6480), 0x80);
+}
+
+static void sub_80A131C(u8 timer)
+{
+ u8 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Pacifidlog0[idx], (u16 *)(BG_VRAM + 0x7a00), 0x3C0);
+}
+
+static void sub_80A1344(u8 timer)
+{
+ u8 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Underwater0[idx], (u16 *)(BG_VRAM + 0x7e00), 0x80);
+}
+
+static void sub_80A136C(u8 timer)
+{
+ u8 idx;
+
+ idx = timer % 8;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Pacifidlog1[idx], (u16 *)(BG_VRAM + 0x7e00), 0x100);
+}
+
+static void sub_80A1394(u16 timer_div, u8 timer_mod)
+{
+ timer_div -= timer_mod;
+ if (timer_div < 12) // almost certainly a typo
+ {
+ timer_div %= 12;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Mauville0a[timer_div], gTilesetAnims_MauvilleVDests0[timer_mod], 0x80);
+ AppendTilesetAnimToBuffer(gTilesetAnims_Mauville0b[timer_div], gTilesetAnims_MauvilleVDests1[timer_mod], 0x80);
+ }
+ else
+ {
+ timer_div %= 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Mauville1a[timer_div], gTilesetAnims_MauvilleVDests0[timer_mod], 0x80);
+ AppendTilesetAnimToBuffer(gTilesetAnims_Mauville1b[timer_div], gTilesetAnims_MauvilleVDests1[timer_mod], 0x80);
+ }
+}
+
+static void sub_80A1434(u16 timer_div, u8 timer_mod)
+{
+ timer_div -= timer_mod;
+ timer_div %= 8;
+ if (gTilesetAnims_Rustboro0[timer_div])
+ AppendTilesetAnimToBuffer(gTilesetAnims_Rustboro0[timer_div], gTilesetAnims_RustboroVDests0[timer_mod], 0x80);
+}
+
+static void sub_80A1470(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 2;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Rustboro1[idx], (u16 *)(BG_VRAM + 0x7800), 0x80);
+}
+
+static void sub_80A1498(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Lavaridge1_Cave0[idx], (u16 *)(BG_VRAM + 0x5400), 0x80);
+}
+
+static void sub_80A14C0(u16 timer_div, u8 timer_mod)
+{
+ timer_div -= timer_mod;
+ timer_div %= 8;
+
+ AppendTilesetAnimToBuffer(gTilesetAnims_EverGrande0[timer_div], gTilesetAnims_EverGrandeVDests0[timer_mod], 0x80);
+}
+
+static void sub_80A14F8(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Lavaridge1_Cave0[idx], (u16 *)(BG_VRAM + 0x7400), 0x80);
+}
+
+static void sub_80A1520(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Dewford0[idx], (u16 *)(BG_VRAM + 0x5540), 0xC0);
+}
+
+static void sub_80A1548(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_BattleFrontierOutsideWest0[idx], (u16 *)(BG_VRAM + 0x5b40), 0xC0);
+}
+
+static void sub_80A1570(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_BattleFrontierOutsideEast0[idx], (u16 *)(BG_VRAM + 0x5b40), 0xC0);
+}
+
+static void sub_80A1598(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Slateport0[idx], (u16 *)(BG_VRAM + 0x5c00), 0x80);
+}
+
+static void sub_80A15C0(u16 timer)
+{
+ static void sub_80A1748(u16);
+
+ if ((timer & 1) == 0)
+ sub_80A1748(timer >> 1);
+}
+
+static void sub_80A15D8(u16 timer)
+{
+ static void sub_80A16B0(u16);
+
+ if ((timer & 7) == 0)
+ sub_80A16B0(timer >> 3);
+}
+
+static void sub_80A15F0(u16 timer)
+{
+ static void sub_80A1720(u16);
+ static void sub_80A16F8(u16);
+
+ if ((timer & 0x3f) == 1)
+ sub_80A1720(timer >> 6);
+ if ((timer & 0x07) == 1)
+ sub_80A16F8(timer >> 3);
+}
+static void sub_80A161C(u16 timer)
+{
+ static void sub_80A1770(u16);
+
+ if ((timer & 3) == 0)
+ sub_80A1770(timer >> 2);
+}
+
+static void sub_80A1634(u16 timer)
+{
+ static void sub_80A17C0(u16);
+ static void sub_80A17EC(u16);
+
+ if ((timer & 7) == 0)
+ {
+ sub_80A17C0(timer >> 3);
+ sub_80A17EC(timer >> 3);
+ }
+}
+
+static void sub_80A1658(u16 timer)
+{
+ static void sub_80A1818(u16);
+
+ if ((timer & 3) == 0)
+ sub_80A1818(timer >> 2);
+}
+
+static void sub_80A1670(u16 timer)
+{
+ static void sub_80A1884(u16);
+
+ if ((timer & 3) == 0)
+ sub_80A1884(timer >> 2);
+}
+
+static void sub_80A1688(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 2;
+ AppendTilesetAnimToBuffer(gTilesetAnims_InsideBuilding0[idx], (u16 *)(BG_VRAM + 0x3e00), 0x80);
+}
+
+static void sub_80A16B0(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 3;
+ AppendTilesetAnimToBuffer(gTilesetAnims_SootopolisGym0[idx], (u16 *)(BG_VRAM + 0x7e00), 0x180);
+ AppendTilesetAnimToBuffer(gTilesetAnims_SootopolisGym1[idx], (u16 *)(BG_VRAM + 0x7a00), 0x280);
+}
+
+static void sub_80A16F8(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 4;
+ AppendTilesetAnimToBuffer(gTilesetAnims_EliteFour1[idx], (u16 *)(BG_VRAM + 0x7f00), 0x20);
+}
+
+static void sub_80A1720(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 2;
+ AppendTilesetAnimToBuffer(gTilesetAnims_EliteFour0[idx], (u16 *)(BG_VRAM + 0x7c00), 0x80);
+}
+
+static void sub_80A1748(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 2;
+ AppendTilesetAnimToBuffer(gTilesetAnims_MauvilleGym0[idx], (u16 *)(BG_VRAM + 0x5200), 0x200);
+}
+
+static void sub_80A1770(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 2;
+ AppendTilesetAnimToBuffer(gTilesetAnims_BikeShop0[idx], (u16 *)(BG_VRAM + 0x7e00), 0x120);
+}
+
+static void sub_80A1798(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 8;
+ AppendTilesetAnimToBuffer(gTilesetAnims_Sootopolis0[idx], (u16 *)(BG_VRAM + 0x5e00), 0xc00);
+}
+
+static void sub_80A17C0(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 3;
+ AppendTilesetAnimToBuffer(gTilesetAnims_BattlePyramid0[idx], (u16 *)(BG_VRAM + 0x52e0), 0x100);
+}
+
+static void sub_80A17EC(u16 timer)
+{
+ u16 idx;
+
+ idx = timer % 3;
+ AppendTilesetAnimToBuffer(gTilesetAnims_BattlePyramid1[idx], (u16 *)(BG_VRAM + 0x50e0), 0x100);
+}
+
+static void sub_80A1818(u16 a1)
+{
+ CpuCopy16(gTilesetAnims_BattleDomePals0[a1 & 0x3], gPlttBufferUnfaded + 0x80, 32);
+ BlendPalette(0x80, 0x10, gPaletteFade.y, gPaletteFade.blendColor & 0x7FFF);
+ if ((u8)FindTaskIdByFunc(sub_8149DFC) != 0xFF )
+ {
+ sSecondaryTilesetCB = sub_80A1670;
+ sSecondaryTilesetCBBufferSize = 0x20;
+ }
+}
+
+static void sub_80A1884(u16 a1)
+{
+ CpuCopy16(gTilesetAnims_BattleDomePals0[a1 & 0x3], gPlttBufferUnfaded + 0x80, 32);
+ if ((u8)FindTaskIdByFunc(sub_8149DFC) == 0xFF )
+ {
+ BlendPalette(0x80, 0x10, gPaletteFade.y, gPaletteFade.blendColor & 0x7FFF);
+ if (!--sSecondaryTilesetCBBufferSize)
+ sSecondaryTilesetCB = NULL;
+ }
+}
diff --git a/src/trig.c b/src/trig.c
index e16a69e63..c2bca3059 100644
--- a/src/trig.c
+++ b/src/trig.c
@@ -1,12 +1,6 @@
#include "global.h"
#include "trig.h"
-// Converts a number to Q8.8 fixed-point format
-#define Q_8_8(n) ((s16)((n) * 256))
-
-// Converts a number to Q4.12 fixed-point format
-#define Q_4_12(n) ((s16)((n) * 4096))
-
// Values of sin(x*(π/128)) as Q8.8 fixed-point numbers from x = 0 to x = 319
const s16 gSineTable[] =
{
diff --git a/src/unk_text_util_2.c b/src/unk_text_util_2.c
new file mode 100644
index 000000000..d88af611f
--- /dev/null
+++ b/src/unk_text_util_2.c
@@ -0,0 +1,219 @@
+#include "global.h"
+#include "main.h"
+#include "window.h"
+#include "text.h"
+#include "sound.h"
+
+static const u8 gUnknown_08616124[] = {1, 2, 4};
+static const u16 gFont6BrailleGlyphs[] = INCBIN_U16("data/graphics/fonts/font6.fwjpnfont");
+
+static void DecompressGlyphFont6(u16);
+
+u16 Font6Func(struct TextPrinter *textPrinter)
+{
+ u16 char_;
+ struct TextPrinterSubStruct *sub;
+
+ sub = &textPrinter->sub_union.sub;
+ switch (textPrinter->state)
+ {
+ case 0:
+ if (gMain.heldKeys & (A_BUTTON | B_BUTTON) && sub->font_type_upper)
+ {
+ textPrinter->delayCounter = 0;
+ }
+ if (textPrinter->delayCounter && textPrinter->text_speed)
+ {
+ textPrinter->delayCounter --;
+ if (gTextFlags.flag_0 && gMain.newKeys & (A_BUTTON | B_BUTTON))
+ {
+ sub->font_type_upper = TRUE;
+ textPrinter->delayCounter = 0;
+ }
+ return 3;
+ }
+ if (gTextFlags.flag_2)
+ {
+ textPrinter->delayCounter = 3;
+ }
+ else
+ {
+ textPrinter->delayCounter = textPrinter->text_speed;
+ }
+ char_ = *textPrinter->subPrinter.current_text_offset ++;
+ switch (char_)
+ {
+ case EOS:
+ return 1;
+ case CHAR_NEWLINE:
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
+ textPrinter->subPrinter.currentY += gFonts[textPrinter->subPrinter.fontId].maxLetterHeight + textPrinter->subPrinter.lineSpacing;
+ return 2;
+ case PLACEHOLDER_BEGIN:
+ textPrinter->subPrinter.current_text_offset ++;
+ return 2;
+ case EXT_CTRL_CODE_BEGIN:
+ char_ = *textPrinter->subPrinter.current_text_offset ++;
+ switch (char_)
+ {
+ case 1:
+ textPrinter->subPrinter.fontColor_h = *textPrinter->subPrinter.current_text_offset ++;
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fontColor_h, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 2:
+ textPrinter->subPrinter.bgColor = *textPrinter->subPrinter.current_text_offset ++;
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fontColor_h, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 3:
+ textPrinter->subPrinter.shadowColor = *textPrinter->subPrinter.current_text_offset ++;
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fontColor_h, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 4:
+ textPrinter->subPrinter.fontColor_h = *textPrinter->subPrinter.current_text_offset;
+ textPrinter->subPrinter.bgColor = *++ textPrinter->subPrinter.current_text_offset;
+ textPrinter->subPrinter.shadowColor = *++ textPrinter->subPrinter.current_text_offset;
+ textPrinter->subPrinter.current_text_offset ++;
+
+ GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fontColor_h, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
+ return 2;
+ case 5:
+ textPrinter->subPrinter.current_text_offset ++;
+ return 2;
+ case 6:
+ sub->font_type = *textPrinter->subPrinter.current_text_offset;
+ textPrinter->subPrinter.current_text_offset ++;
+ return 2;
+ case 7:
+ return 2;
+ case 8:
+ textPrinter->delayCounter = *textPrinter->subPrinter.current_text_offset ++;
+ textPrinter->state = 6;
+ return 2;
+ case 9:
+ textPrinter->state = 1;
+ if (gTextFlags.flag_2)
+ {
+ sub->frames_visible_counter = 0;
+ }
+ return 3;
+ case 10:
+ textPrinter->state = 5;
+ return 3;
+ case 11:
+ case 16:
+ textPrinter->subPrinter.current_text_offset += 2;
+ return 2;
+ case 12:
+ char_ = *++textPrinter->subPrinter.current_text_offset;
+ break;
+ case 13:
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x + *textPrinter->subPrinter.current_text_offset ++;
+ return 2;
+ case 14:
+ textPrinter->subPrinter.currentY = textPrinter->subPrinter.y + *textPrinter->subPrinter.current_text_offset ++;
+ return 2;
+ case 15:
+ FillWindowPixelBuffer(textPrinter->subPrinter.windowId, textPrinter->subPrinter.bgColor | (textPrinter->subPrinter.bgColor << 4));
+ return 2;
+ }
+ break;
+ case CHAR_PROMPT_CLEAR:
+ textPrinter->state = 2;
+ TextPrinterInitDownArrowCounters(textPrinter);
+ return 3;
+ case CHAR_PROMPT_SCROLL:
+ textPrinter->state = 3;
+ TextPrinterInitDownArrowCounters(textPrinter);
+ return 3;
+ case 0xF9:
+ char_ = *textPrinter->subPrinter.current_text_offset ++ | 0x100;
+ break;
+ case 0xF8:
+ textPrinter->subPrinter.current_text_offset ++;
+ return 0;
+ }
+ DecompressGlyphFont6(char_);
+ CopyGlyphToWindow(textPrinter);
+ textPrinter->subPrinter.currentX += gUnknown_03002F90[0x80] + textPrinter->subPrinter.letterSpacing;
+ return 0;
+ case 1:
+ if (TextPrinterWait(textPrinter))
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 2:
+ if (TextPrinterWaitWithDownArrow(textPrinter))
+ {
+ FillWindowPixelBuffer(textPrinter->subPrinter.windowId, textPrinter->subPrinter.bgColor | (textPrinter->subPrinter.bgColor << 4));
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
+ textPrinter->subPrinter.currentY = textPrinter->subPrinter.y;
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 3:
+ if (TextPrinterWaitWithDownArrow(textPrinter))
+ {
+ TextPrinterClearDownArrow(textPrinter);
+ textPrinter->scrollDistance = gFonts[textPrinter->subPrinter.fontId].maxLetterHeight + textPrinter->subPrinter.lineSpacing;
+ textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
+ textPrinter->state = 4;
+ }
+ return 3;
+ case 4:
+ if (textPrinter->scrollDistance)
+ {
+ if (textPrinter->scrollDistance < gUnknown_08616124[gSaveBlock2Ptr->optionsTextSpeed])
+ {
+ ScrollWindow(textPrinter->subPrinter.windowId, 0, textPrinter->scrollDistance, textPrinter->subPrinter.bgColor | (textPrinter->subPrinter.bgColor << 4));
+ textPrinter->scrollDistance = 0;
+ }
+ else
+ {
+ ScrollWindow(textPrinter->subPrinter.windowId, 0, gUnknown_08616124[gSaveBlock2Ptr->optionsTextSpeed], textPrinter->subPrinter.bgColor | (textPrinter->subPrinter.bgColor << 4));
+ textPrinter->scrollDistance -= gUnknown_08616124[gSaveBlock2Ptr->optionsTextSpeed];
+ }
+ CopyWindowToVram(textPrinter->subPrinter.windowId, 2);
+ }
+ else
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 5:
+ if (!IsSEPlaying())
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ case 6:
+ if (textPrinter->delayCounter)
+ {
+ textPrinter->delayCounter --;
+ }
+ else
+ {
+ textPrinter->state = 0;
+ }
+ return 3;
+ }
+ return 1;
+}
+
+static void DecompressGlyphFont6(u16 glyph)
+{
+ const u16 *glyphs;
+
+ glyphs = gFont6BrailleGlyphs + 0x100 * (glyph / 8) + 0x10 * (glyph % 8);
+ DecompressGlyphTile(glyphs, (u16 *)gUnknown_03002F90);
+ DecompressGlyphTile(glyphs + 0x8, (u16 *)(gUnknown_03002F90 + 0x20));
+ DecompressGlyphTile(glyphs + 0x80, (u16 *)(gUnknown_03002F90 + 0x40));
+ DecompressGlyphTile(glyphs + 0x88, (u16 *)(gUnknown_03002F90 + 0x60));
+ gUnknown_03002F90[0x80] = 0x10;
+ gUnknown_03002F90[0x81] = 0x10;
+}
+
+u8 GetGlyphWidthFont6(void)
+{
+ return 0x10;
+}
diff --git a/src/window.c b/src/window.c
index 574b13aa0..704060b9d 100644
--- a/src/window.c
+++ b/src/window.c
@@ -35,7 +35,7 @@ static void nullsub_8(void)
}
-bool16 InitWindows(struct WindowTemplate *templates)
+bool16 InitWindows(const struct WindowTemplate *templates)
{
int i;
void *bgTilemapBuffer;
@@ -451,7 +451,7 @@ void FillWindowPixelRect(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16
FillBitmapRect4Bit(&pixelRect, x, y, width, height, fillValue);
}
-void CopyToWindowPixelBuffer(u8 windowId, u8 *src, u16 size, u16 tileOffset)
+void CopyToWindowPixelBuffer(u8 windowId, const u8 *src, u16 size, u16 tileOffset)
{
if (size != 0)
CpuCopy16(src, gWindows[windowId].tileData + (0x20 * tileOffset), size);