diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_anim_mon_movement.c | 2 | ||||
-rw-r--r-- | src/battle_anim_mons.c | 14 | ||||
-rw-r--r-- | src/battle_anim_utility_funcs.c | 4 | ||||
-rw-r--r-- | src/battle_controller_oak_old_man.c | 6 | ||||
-rw-r--r-- | src/battle_controller_opponent.c | 2 | ||||
-rw-r--r-- | src/battle_controller_player.c | 3 | ||||
-rw-r--r-- | src/battle_controller_pokedude.c | 2739 | ||||
-rw-r--r-- | src/battle_controllers.c | 12 | ||||
-rw-r--r-- | src/battle_script_commands.c | 2 | ||||
-rw-r--r-- | src/battle_setup.c | 2 | ||||
-rw-r--r-- | src/bug.c | 14 | ||||
-rw-r--r-- | src/electric.c | 1272 | ||||
-rw-r--r-- | src/fighting.c | 971 | ||||
-rw-r--r-- | src/fire.c | 1193 | ||||
-rw-r--r-- | src/flying.c | 30 | ||||
-rw-r--r-- | src/ghost.c | 12 | ||||
-rw-r--r-- | src/ground.c | 8 | ||||
-rw-r--r-- | src/ice.c | 1477 | ||||
-rw-r--r-- | src/poison.c | 298 | ||||
-rw-r--r-- | src/pokemon.c | 20 | ||||
-rw-r--r-- | src/psychic.c | 22 | ||||
-rw-r--r-- | src/quest_log.c | 2 | ||||
-rw-r--r-- | src/quest_log_815A008.c (renamed from src/unk_8159F40.c) | 147 | ||||
-rw-r--r-- | src/rock.c | 8 | ||||
-rw-r--r-- | src/teachy_tv.c | 2 |
25 files changed, 8032 insertions, 230 deletions
diff --git a/src/battle_anim_mon_movement.c b/src/battle_anim_mon_movement.c index 21d07246f..ffd66871c 100644 --- a/src/battle_anim_mon_movement.c +++ b/src/battle_anim_mon_movement.c @@ -888,7 +888,7 @@ void sub_8099BD4(u8 taskId) gTasks[taskId].data[12] = 0; gTasks[taskId].data[10] = gBattleAnimArgs[3]; gTasks[taskId].data[11] = gBattleAnimArgs[4]; - gTasks[taskId].data[7] = GetAnimBattlerSpriteId(1); + gTasks[taskId].data[7] = GetAnimBattlerSpriteId(ANIM_TARGET); gTasks[taskId].data[8] = gSprites[gTasks[taskId].data[7]].pos2.x; gTasks[taskId].data[9] = gSprites[gTasks[taskId].data[7]].pos2.y; gTasks[taskId].data[0] = 0; diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c index c19af4cb7..a3bd26898 100644 --- a/src/battle_anim_mons.c +++ b/src/battle_anim_mons.c @@ -1393,7 +1393,7 @@ void TranslateAnimSpriteToTargetMonLocation(struct Sprite *sprite) void AnimThrowProjectile(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, 1); - if (GetBattlerSide(gBattleAnimAttacker)) + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) gBattleAnimArgs[2] = -gBattleAnimArgs[2]; sprite->data[0] = gBattleAnimArgs[4]; sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; @@ -1409,7 +1409,7 @@ static void AnimThrowProjectile_Step(struct Sprite *sprite) DestroyAnimSprite(sprite); } -void sub_8075F0C(struct Sprite *sprite) +void AnimSnoreZ(struct Sprite *sprite) { bool8 r4; u8 battlerId, coordType; @@ -1434,7 +1434,7 @@ void sub_8075F0C(struct Sprite *sprite) InitSpritePosToAnimTarget(sprite, r4); battlerId = gBattleAnimTarget; } - if (GetBattlerSide(gBattleAnimAttacker)) + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) gBattleAnimArgs[2] = -gBattleAnimArgs[2]; InitSpritePosToAnimTarget(sprite, r4); sprite->data[0] = gBattleAnimArgs[4]; @@ -2070,7 +2070,7 @@ u8 sub_8076E34(s32 battlerId, u8 spriteId, s32 species) void sub_8076ED8(struct Sprite *sprite) { SetSpriteCoordsToAnimAttackerCoords(sprite); - if (GetBattlerSide(gBattleAnimAttacker)) + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) { sprite->pos1.x -= gBattleAnimArgs[0]; gBattleAnimArgs[3] = -gBattleAnimArgs[3]; @@ -2113,7 +2113,7 @@ void sub_8076F58(struct Sprite *sprite) void sub_8076FD0(struct Sprite *sprite) { SetSpriteCoordsToAnimAttackerCoords(sprite); - if (GetBattlerSide(gBattleAnimAttacker)) + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) sprite->pos1.x -= gBattleAnimArgs[0]; else sprite->pos1.x += gBattleAnimArgs[0]; @@ -2210,7 +2210,7 @@ void sub_807729C(struct Sprite *sprite) { sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); - if (!GetBattlerSide(gBattleAnimAttacker)) + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) sprite->data[0] = 5; else sprite->data[0] = -10; @@ -2237,7 +2237,7 @@ void sub_8077350(struct Sprite *sprite) sprite->data[0] = gBattleAnimArgs[2]; sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[4]; sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[5]; - if (!GetBattlerSide(gBattleAnimTarget)) + if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) { x = (u16)gBattleAnimArgs[4] + 30; sprite->pos1.x += x; diff --git a/src/battle_anim_utility_funcs.c b/src/battle_anim_utility_funcs.c index 14c5ef6c8..d9a6754c7 100644 --- a/src/battle_anim_utility_funcs.c +++ b/src/battle_anim_utility_funcs.c @@ -309,7 +309,7 @@ void sub_80BACEC(u8 taskId) species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES); else species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES); - spriteId = GetAnimBattlerSpriteId(0); + spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); newSpriteId = sub_8076E34(gBattleAnimAttacker, spriteId, species); sub_80752A0(&animBgData); AnimLoadCompressedBgTilemap(animBgData.bgId, gFile_graphics_battle_anims_masks_curse_tilemap); @@ -354,7 +354,7 @@ static void sub_80BAF38(u8 taskId) SetGpuReg(REG_OFFSET_DISPCNT, GetGpuReg(REG_OFFSET_DISPCNT) ^ DISPCNT_OBJWIN_ON); SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); - sprite = &gSprites[GetAnimBattlerSpriteId(0)]; // unused + sprite = &gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)]; // unused sprite = &gSprites[gTasks[taskId].data[0]]; DestroySprite(sprite); sub_80752A0(&animBgData); diff --git a/src/battle_controller_oak_old_man.c b/src/battle_controller_oak_old_man.c index 99391ab3e..a6730cbbb 100644 --- a/src/battle_controller_oak_old_man.c +++ b/src/battle_controller_oak_old_man.c @@ -181,7 +181,7 @@ static void OakOldManBufferRunCommand(void) { if (gBattleControllerExecFlags & gBitTable[gActiveBattler]) { - if (gBattleBufferA[gActiveBattler][0] < ARRAY_COUNT(sOakOldManBufferCommands)) + if (gBattleBufferA[gActiveBattler][0] < NELEMS(sOakOldManBufferCommands)) sOakOldManBufferCommands[gBattleBufferA[gActiveBattler][0]](); else OakOldManBufferExecCompleted(); @@ -463,7 +463,7 @@ static void sub_80E7CD8(void) static void Task_GiveExpToMon(u8 taskId) { - u32 monId = (u8)(gTasks[taskId].tExpTask_monId); + u32 monId = (u8)gTasks[taskId].tExpTask_monId; u8 battlerId = gTasks[taskId].tExpTask_battler; s16 gainedExp = gTasks[taskId].tExpTask_gainedExp; @@ -487,7 +487,7 @@ static void Task_GiveExpToMon(u8 taskId) BtlController_EmitTwoReturnValues(1, RET_VALUE_LEVELED_UP, gainedExp); gActiveBattler = savedActiveBattler; if (IsDoubleBattle() == TRUE - && ((u16)(monId) == gBattlerPartyIndexes[battlerId] || (u16)(monId) == gBattlerPartyIndexes[battlerId ^ BIT_FLANK])) + && ((u16)monId == gBattlerPartyIndexes[battlerId] || (u16)monId == gBattlerPartyIndexes[battlerId ^ BIT_FLANK])) gTasks[taskId].func = Task_LaunchLvlUpAnim; else gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index a9173f1a9..3cb6d1432 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -1497,7 +1497,7 @@ static void OpponentHandleStatusIconUpdate(void) UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_STATUS_ICON); battlerId = gActiveBattler; - gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = 0; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = FALSE; gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; } } diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index f8d5958ba..16bf1ec87 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1003,7 +1003,6 @@ static void CompleteOnHealthbarDone(void) s16 hpValue = MoveBattleBar(gActiveBattler, gHealthboxSpriteIds[gActiveBattler], HEALTH_BAR, 0); SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler]); - if (hpValue != -1) { UpdateHpTextInHealthbox(gHealthboxSpriteIds[gActiveBattler], hpValue, HP_CURRENT); @@ -2544,7 +2543,7 @@ static void PlayerHandleStatusIconUpdate(void) UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_STATUS_ICON); battlerId = gActiveBattler; - gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = 0; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = FALSE; gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; } } diff --git a/src/battle_controller_pokedude.c b/src/battle_controller_pokedude.c new file mode 100644 index 000000000..57a405f3c --- /dev/null +++ b/src/battle_controller_pokedude.c @@ -0,0 +1,2739 @@ +#include "global.h" +#include "task.h" +#include "pokemon.h" +#include "party_menu.h" +#include "pokeball.h" +#include "bg.h" +#include "data.h" +#include "palette.h" +#include "util.h" +#include "m4a.h" +#include "link.h" +#include "sound.h" +#include "event_data.h" +#include "item.h" +#include "item_menu.h" +#include "text.h" +#include "strings.h" +#include "string_util.h" +#include "window.h" +#include "battle.h" +#include "battle_anim.h" +#include "battle_controllers.h" +#include "battle_interface.h" +#include "battle_message.h" +#include "reshow_battle_screen.h" +#include "constants/songs.h" +#include "constants/items.h" +#include "constants/moves.h" +#include "constants/pokemon.h" +#include "constants/trainers.h" + +struct Unk_84790E8 +{ + u8 unk_0; + u8 unk_1; + u16 unk_2; + void (*unk_4)(void); +}; + +struct PokedudeBattlePartyInfo +{ + u8 side; + u8 level; + u16 species; + u16 moves[4]; + u8 nature; + u8 gender; +}; + +static void PokedudeHandleGetMonData(void); +static void PokedudeHandleGetRawMonData(void); +static void PokedudeHandleSetMonData(void); +static void PokedudeHandleSetRawMonData(void); +static void PokedudeHandleLoadMonSprite(void); +static void PokedudeHandleSwitchInAnim(void); +static void PokedudeHandleReturnMonToBall(void); +static void PokedudeHandleDrawTrainerPic(void); +static void PokedudeHandleTrainerSlide(void); +static void PokedudeHandleTrainerSlideBack(void); +static void PokedudeHandleFaintAnimation(void); +static void PokedudeHandlePaletteFade(void); +static void PokedudeHandleSuccessBallThrowAnim(void); +static void PokedudeHandleBallThrowAnim(void); +static void PokedudeHandlePause(void); +static void PokedudeHandleMoveAnimation(void); +static void PokedudeHandlePrintString(void); +static void PokedudeHandlePrintSelectionString(void); +static void PokedudeHandleChooseAction(void); +static void PokedudeHandleUnknownYesNoBox(void); +static void PokedudeHandleChooseMove(void); +static void PokedudeHandleChooseItem(void); +static void PokedudeHandleChoosePokemon(void); +static void PokedudeHandleCmd23(void); +static void PokedudeHandleHealthBarUpdate(void); +static void PokedudeHandleExpUpdate(void); +static void PokedudeHandleStatusIconUpdate(void); +static void PokedudeHandleStatusAnimation(void); +static void PokedudeHandleStatusXor(void); +static void PokedudeHandleDataTransfer(void); +static void PokedudeHandleDMA3Transfer(void); +static void PokedudeHandlePlayBGM(void); +static void PokedudeHandleCmd32(void); +static void PokedudeHandleTwoReturnValues(void); +static void PokedudeHandleChosenMonReturnValue(void); +static void PokedudeHandleOneReturnValue(void); +static void PokedudeHandleOneReturnValue_Duplicate(void); +static void PokedudeHandleCmd37(void); +static void PokedudeHandleCmd38(void); +static void PokedudeHandleCmd39(void); +static void PokedudeHandleCmd40(void); +static void PokedudeHandleHitAnimation(void); +static void PokedudeHandleCmd42(void); +static void PokedudeHandlePlaySE(void); +static void PokedudeHandlePlayFanfare(void); +static void PokedudeHandleFaintingCry(void); +static void PokedudeHandleIntroSlide(void); +static void PokedudeHandleIntroTrainerBallThrow(void); +static void PokedudeHandleDrawPartyStatusSummary(void); +static void PokedudeHandleHidePartyStatusSummary(void); +static void PokedudeHandleEndBounceEffect(void); +static void PokedudeHandleSpriteInvisibility(void); +static void PokedudeHandleBattleAnimation(void); +static void PokedudeHandleLinkStandbyMsg(void); +static void PokedudeHandleResetActionMoveSelection(void); +static void PokedudeHandleCmd55(void); +static void PokedudeCmdEnd(void); + +static void sub_8159BA8(void); +static void sub_8159D04(void); +static void PokedudeBufferExecCompleted(void); +static void sub_8159824(void); +static void PokedudeBufferRunCommand(void); +static bool8 sub_8159AB8(void); +static void sub_8159998(void); +static void WaitForMonSelection(void); +static void CompleteWhenChoseItem(void); +static void sub_81567B0(void); +static void Task_LaunchLvlUpAnim(u8 taskId); +static void DestroyExpTaskAndCompleteOnInactiveTextPrinter(u8 taskId); +static void CompleteOnInactiveTextPrinter2(void); +static void Task_PrepareToGiveExpWithExpBar(u8 taskId); +static void sub_8156B24(u8 taskId); +static void Task_UpdateLvlInHealthbox(u8 taskId); +static u32 CopyPokedudeMonData(u8 monId, u8 *dst); +static void SetPokedudeMonData(u8 monId); +static void sub_8159478(u8 battlerId); +static void PokedudeDoMoveAnimation(void); +static void sub_81595EC(u8 taskId); +static const u8 *sub_8159EF0(void); + +u8 *gUnknown_3005EE0[MAX_BATTLERS_COUNT]; + +static void (*const sPokedudeBufferCommands[CONTROLLER_CMDS_COUNT])(void) = +{ + PokedudeHandleGetMonData, + PokedudeHandleGetRawMonData, + PokedudeHandleSetMonData, + PokedudeHandleSetRawMonData, + PokedudeHandleLoadMonSprite, + PokedudeHandleSwitchInAnim, + PokedudeHandleReturnMonToBall, + PokedudeHandleDrawTrainerPic, + PokedudeHandleTrainerSlide, + PokedudeHandleTrainerSlideBack, + PokedudeHandleFaintAnimation, + PokedudeHandlePaletteFade, + PokedudeHandleSuccessBallThrowAnim, + PokedudeHandleBallThrowAnim, + PokedudeHandlePause, + PokedudeHandleMoveAnimation, + PokedudeHandlePrintString, + PokedudeHandlePrintSelectionString, + PokedudeHandleChooseAction, + PokedudeHandleUnknownYesNoBox, + PokedudeHandleChooseMove, + PokedudeHandleChooseItem, + PokedudeHandleChoosePokemon, + PokedudeHandleCmd23, + PokedudeHandleHealthBarUpdate, + PokedudeHandleExpUpdate, + PokedudeHandleStatusIconUpdate, + PokedudeHandleStatusAnimation, + PokedudeHandleStatusXor, + PokedudeHandleDataTransfer, + PokedudeHandleDMA3Transfer, + PokedudeHandlePlayBGM, + PokedudeHandleCmd32, + PokedudeHandleTwoReturnValues, + PokedudeHandleChosenMonReturnValue, + PokedudeHandleOneReturnValue, + PokedudeHandleOneReturnValue_Duplicate, + PokedudeHandleCmd37, + PokedudeHandleCmd38, + PokedudeHandleCmd39, + PokedudeHandleCmd40, + PokedudeHandleHitAnimation, + PokedudeHandleCmd42, + PokedudeHandlePlaySE, + PokedudeHandlePlayFanfare, + PokedudeHandleFaintingCry, + PokedudeHandleIntroSlide, + PokedudeHandleIntroTrainerBallThrow, + PokedudeHandleDrawPartyStatusSummary, + PokedudeHandleHidePartyStatusSummary, + PokedudeHandleEndBounceEffect, + PokedudeHandleSpriteInvisibility, + PokedudeHandleBattleAnimation, + PokedudeHandleLinkStandbyMsg, + PokedudeHandleResetActionMoveSelection, + PokedudeHandleCmd55, + PokedudeCmdEnd, +}; + +// not used +static const u8 gUnknown_8479000[] = { 0x48, 0x48, 0x20, 0x5a, 0x50, 0x50, 0x50, 0x58 }; + +static const u8 gUnknown_8479008[][8] = +{ + { 0, 0, 0, 0, 64, 0, 0, 0 }, + { 4, 4, 0, 0, 0, 0, 0, 0 }, +}; + +static const u8 gUnknown_8479018[][8] = +{ + { 0, 0, 0, 0, 64, 0, 0, 0 }, + { 1, 0, 0, 0, 64, 0, 0, 0 }, + { 0, 0, 0, 0, 64, 0, 0, 0 }, +}; + +static const u8 gUnknown_8479030[][8] = +{ + { 0, 0, 0, 0, 64, 0, 0, 0 }, + { 2, 0, 0, 0, 64, 0, 0, 0 }, + { 0, 0, 0, 0, 64, 0, 0, 0 }, +}; + +static const u8 gUnknown_8479048[][8] = +{ + { 0, 0, 0, 0, 64, 0, 0, 0 }, + { 0, 0, 0, 0, 64, 0, 0, 0 }, + { 1, 0, 0, 0, 64, 0, 0, 0 }, +}; + +static const u8 (*const gUnknown_8479060[])[8] = +{ + gUnknown_8479008, + gUnknown_8479018, + gUnknown_8479030, + gUnknown_8479048, +}; + +static const u8 gUnknown_8479070[][8] = +{ + { 2, 2, 0, 0, 64, 0, 0, 0 }, + { 255, 255, 0, 0, 0, 0, 0, 0 }, +}; + +static const u8 gUnknown_8479080[][8] = +{ + { 2, 2, 0, 0, 64, 0, 0, 0 }, + { 2, 0, 0, 0, 64, 0, 0, 0 }, + { 2, 0, 0, 0, 64, 0, 0, 0 }, + { 255, 255, 0, 0, 0, 0, 0, 0 }, +}; + +static const u8 gUnknown_84790A0[][8] = +{ + { 2, 0, 0, 0, 64, 0, 0, 0 }, + { 0, 0, 0, 0, 64, 0, 0, 0 }, + { 0, 0, 0, 0, 64, 0, 0, 0 }, + { 255, 255, 0, 0, 0, 0, 0, 0 }, +}; + +static const u8 gUnknown_84790C0[][8] = +{ + { 0, 2, 0, 0, 64, 0, 0, 0 }, + { 2, 2, 0, 0, 64, 0, 0, 0 }, + { 255, 255, 0, 0, 0, 0, 0, 0 }, +}; + +static const u8 (*const gUnknown_84790D8[])[8] = +{ + gUnknown_8479070, + gUnknown_8479080, + gUnknown_84790A0, + gUnknown_84790C0, +}; + +static const struct Unk_84790E8 gUnknown_84790E8[] = +{ + { + .unk_0 = 18, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 16, + .unk_1 = 1, + .unk_2 = 4, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 18, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 16, + .unk_1 = 0, + .unk_2 = 13, + .unk_4 = sub_8159BA8, + }, +}; + +static const struct Unk_84790E8 gUnknown_8479108[] = +{ + { + .unk_0 = 18, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = NULL, + }, + { + .unk_0 = 18, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159D04, + }, + { + .unk_0 = 21, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 16, + .unk_1 = 1, + .unk_2 = 4, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 16, + .unk_1 = 0, + .unk_2 = 13, + .unk_4 = sub_8159BA8, + }, +}; + +static const struct Unk_84790E8 gUnknown_8479130[] = +{ + { + .unk_0 = 16, + .unk_1 = 1, + .unk_2 = 4, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 18, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 22, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 16, + .unk_1 = 1, + .unk_2 = 4, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 18, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 20, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 16, + .unk_1 = 0, + .unk_2 = 13, + .unk_4 = sub_8159BA8, + }, +}; + +static const struct Unk_84790E8 gUnknown_8479168[] = +{ + { + .unk_0 = 18, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 18, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = NULL, + }, + { + .unk_0 = 18, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 16, + .unk_1 = 1, + .unk_2 = 107, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 21, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, + { + .unk_0 = 55, + .unk_1 = 0, + .unk_2 = 0, + .unk_4 = sub_8159BA8, + }, +}; + +static const struct Unk_84790E8 *const gUnknown_8479198[] = +{ + gUnknown_84790E8, + gUnknown_8479108, + gUnknown_8479130, + gUnknown_8479168, +}; + +static const u8 *const gUnknown_84791A8[] = +{ + gUnknown_81C5F69, + gUnknown_81C5FA7, + gUnknown_81C5FDC, + gUnknown_81C601C, +}; + +static const u8 *const gUnknown_84791B8[] = +{ + gUnknown_81C60FA, + gUnknown_81C60FA, + gUnknown_81C615A, + gUnknown_81C6196, + gUnknown_81C61EA, +}; + +static const u8 *const gUnknown_84791CC[] = +{ + gUnknown_81C6202, + gUnknown_81C6301, + gUnknown_81C63A9, + gUnknown_81C63F9, + gUnknown_81C6446, + gUnknown_81C657A, + gUnknown_81C6637, +}; + +static const u8 *const gUnknown_84791E8[] = +{ + gUnknown_81C6645, + gUnknown_81C6645, + gUnknown_81C66CF, + gUnknown_81C6787, + gUnknown_81C684B, + gUnknown_81C686C, +}; + +static const struct PokedudeBattlePartyInfo sParties_Battle[] = +{ + { + .side = B_SIDE_PLAYER, + .level = 15, + .species = SPECIES_RATTATA, + .moves = { MOVE_TACKLE, MOVE_TAIL_WHIP, MOVE_HYPER_FANG, MOVE_QUICK_ATTACK }, + .nature = NATURE_LONELY, + .gender = MALE, + }, + { + .side = B_SIDE_OPPONENT, + .level = 18, + .species = SPECIES_PIDGEY, + .moves = { MOVE_TACKLE, MOVE_SAND_ATTACK, MOVE_GUST, MOVE_QUICK_ATTACK }, + .nature = NATURE_NAUGHTY, + .gender = MALE, + }, + {0xFF} +}; + +static const struct PokedudeBattlePartyInfo sParties_Status[] = +{ + { + .side = B_SIDE_PLAYER, + .level = 15, + .species = SPECIES_RATTATA, + .moves = { MOVE_TACKLE, MOVE_TAIL_WHIP, MOVE_HYPER_FANG, MOVE_QUICK_ATTACK }, + .nature = NATURE_LONELY, + .gender = MALE, + }, + { + .side = B_SIDE_OPPONENT, + .level = 14, + .species = SPECIES_ODDISH, + .moves = { MOVE_ABSORB, MOVE_SWEET_SCENT, MOVE_POISON_POWDER }, + .nature = NATURE_RASH, + .gender = MALE, + }, + {0xFF} +}; + +static const struct PokedudeBattlePartyInfo sParties_Matchups[] = +{ + { + .side = B_SIDE_PLAYER, + .level = 15, + .species = SPECIES_POLIWAG, + .moves = { MOVE_WATER_GUN, MOVE_HYPNOSIS, MOVE_BUBBLE }, + .nature = NATURE_RASH, + .gender = MALE, + }, + { + .side = B_SIDE_PLAYER, + .level = 15, + .species = SPECIES_BUTTERFREE, + .moves = { MOVE_CONFUSION, MOVE_POISON_POWDER, MOVE_STUN_SPORE, MOVE_SLEEP_POWDER }, + .nature = NATURE_RASH, + .gender = MALE, + }, + { + .side = B_SIDE_OPPONENT, + .level = 14, + .species = SPECIES_ODDISH, + .moves = { MOVE_ABSORB, MOVE_SWEET_SCENT, MOVE_POISON_POWDER }, + .nature = NATURE_RASH, + .gender = MALE, + }, + {0xFF} +}; + +static const struct PokedudeBattlePartyInfo sParties_Catching[] = +{ + { + .side = B_SIDE_PLAYER, + .level = 15, + .species = SPECIES_BUTTERFREE, + .moves = { MOVE_CONFUSION, MOVE_POISON_POWDER, MOVE_SLEEP_POWDER, MOVE_STUN_SPORE }, + .nature = NATURE_RASH, + .gender = MALE, + }, + { + .side = B_SIDE_OPPONENT, + .level = 11, + .species = SPECIES_JIGGLYPUFF, + .moves = { MOVE_SING, MOVE_DEFENSE_CURL, MOVE_POUND }, + .nature = NATURE_CAREFUL, + .gender = MALE, + }, + {0xFF} +}; + + +static const struct PokedudeBattlePartyInfo *const sPokedudeBattlePartyPointers[] = +{ + sParties_Battle, + sParties_Status, + sParties_Matchups, + sParties_Catching, +}; + +static void nullsub_99(void) +{ +} + +void SetControllerToPokedude(void) +{ + gBattlerControllerFuncs[gActiveBattler] = PokedudeBufferRunCommand; + *(&gBattleStruct->field_96) = gSpecialVar_0x8004; + gBattleStruct->field_97 = 0; +} + +static void PokedudeBufferRunCommand(void) +{ + if (gBattleControllerExecFlags & gBitTable[gActiveBattler]) + { + if (gBattleBufferA[gActiveBattler][0] < NELEMS(sPokedudeBufferCommands)) + { + if (!sub_8159AB8()) + sPokedudeBufferCommands[gBattleBufferA[gActiveBattler][0]](); + } + else + { + PokedudeBufferExecCompleted(); + } + } +} + +static void sub_8156140(void) +{ + sub_8159824(); +} + +static void CompleteOnBattlerSpriteCallbackDummy(void) +{ + if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + PokedudeBufferExecCompleted(); +} + +static void sub_8156184(void) +{ + if (gSprites[gBattlerSpriteIds[gActiveBattler]].animEnded == TRUE + && gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x == 0) + { + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80) + { + sub_80F1720(gActiveBattler, &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]]); + } + else if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + PokedudeBufferExecCompleted(); + } + } +} + +static void CompleteOnInactiveTextPrinter(void) +{ + if (!IsTextPrinterActive(0)) + PokedudeBufferExecCompleted(); +} + +static void sub_8156254(void) +{ + if (!gPaletteFade.active) + { + gMain.inBattle = FALSE; + gMain.callback1 = gPreBattleCallback1; + SetMainCallback2(gMain.savedCallback); + } +} + +static void sub_8156294(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive) + { + CreateTask(c3_0802FDF4, 10); + HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); + PokedudeBufferExecCompleted(); + } +} + +static void sub_81562F0(void) +{ + if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy + && gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute) + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_MON_TO_SUBSTITUTE); + gBattlerControllerFuncs[gActiveBattler] = sub_8156294; + } +} + +static void sub_81563A8(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 + && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive) + sub_80F1720(gActiveBattler, &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]]); + if (gSprites[gUnknown_3004FFC[gActiveBattler]].callback == SpriteCallbackDummy + && !(gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive)) + { + DestroySprite(&gSprites[gUnknown_3004FFC[gActiveBattler]]); + UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], + &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], + HEALTHBOX_ALL); + sub_804BD94(gActiveBattler); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler]); + CopyBattleSpriteInvisibility(gActiveBattler); + gBattlerControllerFuncs[gActiveBattler] = sub_81562F0; + } +} + +static void CompleteOnSpecialAnimDone(void) +{ + if (!gDoingBattleAnim) + PokedudeBufferExecCompleted(); +} + +static void sub_815649C(void) +{ + if (--gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_9 == 255) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_9 = 0; + PokedudeBufferExecCompleted(); + } +} + +static void sub_81564E4(void) +{ + sub_8159998(); +} + +static void OpenPartyMenuToChooseMon(void) +{ + if (!gPaletteFade.active) + { + gBattlerControllerFuncs[gActiveBattler] = WaitForMonSelection; + DestroyTask(gUnknown_3004FFC[gActiveBattler]); + FreeAllWindowBuffers(); + sub_8127968(); + } +} + +static void WaitForMonSelection(void) +{ + if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) + { + if (gUnknown_203B0C0 == 1) + BtlController_EmitChosenMonReturnValue(1, gUnknown_203B0C1, gUnknown_203B0DC); + else + BtlController_EmitChosenMonReturnValue(1, 6, NULL); + PokedudeBufferExecCompleted(); + } +} + +static void OpenBagAndChooseItem(void) +{ + u8 callbackId; + + if (!gPaletteFade.active) + { + gBattlerControllerFuncs[gActiveBattler] = CompleteWhenChoseItem; + nullsub_44(); + FreeAllWindowBuffers(); + switch (gSpecialVar_0x8004) + { + case 1: + default: + callbackId = 7; + break; + case 3: + callbackId = 8; + break; + } + sub_810B108(callbackId); + } +} + +static void CompleteWhenChoseItem(void) +{ + if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) + { + BtlController_EmitOneReturnValue(1, gSpecialVar_ItemId); + PokedudeBufferExecCompleted(); + } +} + +static void sub_8156624(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 + && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive) + sub_80F1720(gActiveBattler, &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]]); + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].flag_x80 + && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].ballAnimActive) + sub_80F1720(gActiveBattler ^ BIT_FLANK, &gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]]); + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].ballAnimActive && !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].ballAnimActive) + { + if (IsDoubleBattle() && !(gBattleTypeFlags & BATTLE_TYPE_MULTI)) + { + DestroySprite(&gSprites[gUnknown_3004FFC[gActiveBattler ^ BIT_FLANK]]); + UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK], + &gPlayerParty[gBattlerPartyIndexes[gActiveBattler ^ BIT_FLANK]], + HEALTHBOX_ALL); + sub_804BD94(gActiveBattler ^ BIT_FLANK); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler ^ BIT_FLANK]); + } + DestroySprite(&gSprites[gUnknown_3004FFC[gActiveBattler]]); + UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], + &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], + HEALTHBOX_ALL); + sub_804BD94(gActiveBattler); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler]); + gBattleSpritesDataPtr->animationData->field_9_x1 = 0; + gBattlerControllerFuncs[gActiveBattler] = sub_81567B0; + } +} + +static void sub_81567B0(void) +{ + bool32 r4 = FALSE; + + if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + r4 = TRUE; + if (r4 + && gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1 + && gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].field_1_x1) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].field_1_x1 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].flag_x80 = 0; + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler ^ BIT_FLANK].field_1_x1 = 0; + FreeSpriteTilesByTag(0x27F9); + FreeSpritePaletteByTag(0x27F9); + CreateTask(c3_0802FDF4, 10); + HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); + gBattlerControllerFuncs[gActiveBattler] = sub_815649C; + } +} + +#define tExpTask_monId data[0] +#define tExpTask_gainedExp data[1] +#define tExpTask_battler data[2] +#define tExpTask_frames data[10] + +static void Task_GiveExpToMon(u8 taskId) +{ + u32 monId = (u8)gTasks[taskId].tExpTask_monId; + u8 battlerId = gTasks[taskId].tExpTask_battler; + s16 gainedExp = gTasks[taskId].tExpTask_gainedExp; + + if (IsDoubleBattle() == TRUE || monId != gBattlerPartyIndexes[battlerId]) // Give exp without moving the expbar. + { + struct Pokemon *mon = &gPlayerParty[monId]; + u16 species = GetMonData(mon, MON_DATA_SPECIES); + u8 level = GetMonData(mon, MON_DATA_LEVEL); + u32 currExp = GetMonData(mon, MON_DATA_EXP); + u32 nextLvlExp = gExperienceTables[gBaseStats[species].growthRate][level + 1]; + + if (currExp + gainedExp >= nextLvlExp) + { + u8 savedActiveBattler; + + SetMonData(mon, MON_DATA_EXP, &nextLvlExp); + CalculateMonStats(mon); + gainedExp -= nextLvlExp - currExp; + savedActiveBattler = gActiveBattler; + gActiveBattler = battlerId; + BtlController_EmitTwoReturnValues(1, RET_VALUE_LEVELED_UP, gainedExp); + gActiveBattler = savedActiveBattler; + if (IsDoubleBattle() == TRUE + && ((u16)monId == gBattlerPartyIndexes[battlerId] || (u16)monId == gBattlerPartyIndexes[battlerId ^ BIT_FLANK])) + gTasks[taskId].func = Task_LaunchLvlUpAnim; + else + gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; + } + else + { + currExp += gainedExp; + SetMonData(mon, MON_DATA_EXP, &currExp); + gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter2; + DestroyTask(taskId); + } + } + else + { + gTasks[taskId].func = Task_PrepareToGiveExpWithExpBar; + } +} + +static void Task_PrepareToGiveExpWithExpBar(u8 taskId) +{ + u8 monIndex = gTasks[taskId].tExpTask_monId; + s32 gainedExp = gTasks[taskId].tExpTask_gainedExp; + u8 battlerId = gTasks[taskId].tExpTask_battler; + struct Pokemon *mon = &gPlayerParty[monIndex]; + u8 level = GetMonData(mon, MON_DATA_LEVEL); + u16 species = GetMonData(mon, MON_DATA_SPECIES); + u32 exp = GetMonData(mon, MON_DATA_EXP); + u32 currLvlExp = gExperienceTables[gBaseStats[species].growthRate][level]; + u32 expToNextLvl; + + exp -= currLvlExp; + expToNextLvl = gExperienceTables[gBaseStats[species].growthRate][level + 1] - currLvlExp; + SetBattleBarStruct(battlerId, gHealthboxSpriteIds[battlerId], expToNextLvl, exp, -gainedExp); + PlaySE(SE_EXP); + gTasks[taskId].func = sub_8156B24; +} + +static void sub_8156B24(u8 taskId) +{ + if (gTasks[taskId].tExpTask_frames < 13) + { + ++gTasks[taskId].tExpTask_frames; + } + else + { + u8 monId = gTasks[taskId].tExpTask_monId; + s16 gainedExp = gTasks[taskId].tExpTask_gainedExp; + u8 battlerId = gTasks[taskId].tExpTask_battler; + s16 newExpPoints; + + newExpPoints = MoveBattleBar(battlerId, gHealthboxSpriteIds[battlerId], EXP_BAR, 0); + SetHealthboxSpriteVisible(gHealthboxSpriteIds[battlerId]); + if (newExpPoints == -1) // The bar has been filled with given exp points. + { + u8 level; + s32 currExp; + u16 species; + s32 expOnNextLvl; + + m4aSongNumStop(SE_EXP); + level = GetMonData(&gPlayerParty[monId], MON_DATA_LEVEL); + currExp = GetMonData(&gPlayerParty[monId], MON_DATA_EXP); + species = GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES); + expOnNextLvl = gExperienceTables[gBaseStats[species].growthRate][level + 1]; + if (currExp + gainedExp >= expOnNextLvl) + { + u8 savedActiveBattler; + + SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &expOnNextLvl); + CalculateMonStats(&gPlayerParty[monId]); + gainedExp -= expOnNextLvl - currExp; + savedActiveBattler = gActiveBattler; + gActiveBattler = battlerId; + BtlController_EmitTwoReturnValues(1, RET_VALUE_LEVELED_UP, gainedExp); + gActiveBattler = savedActiveBattler; + gTasks[taskId].func = Task_LaunchLvlUpAnim; + } + else + { + currExp += gainedExp; + SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &currExp); + gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter2; + DestroyTask(taskId); + } + } + } +} + +static void Task_LaunchLvlUpAnim(u8 taskId) +{ + u8 battlerId = gTasks[taskId].tExpTask_battler; + u8 monIndex = gTasks[taskId].tExpTask_monId; + + if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[battlerId ^ BIT_FLANK]) + battlerId ^= BIT_FLANK; + InitAndLaunchSpecialAnimation(battlerId, battlerId, battlerId, B_ANIM_LVL_UP); + gTasks[taskId].func = Task_UpdateLvlInHealthbox; +} + +static void Task_UpdateLvlInHealthbox(u8 taskId) +{ + u8 battlerId = gTasks[taskId].tExpTask_battler; + + if (!gBattleSpritesDataPtr->healthBoxesData[battlerId].specialAnimActive) + { + u8 monIndex = gTasks[taskId].tExpTask_monId; + + GetMonData(&gPlayerParty[monIndex], MON_DATA_LEVEL); // Unused return value. + if (IsDoubleBattle() == TRUE && monIndex == gBattlerPartyIndexes[battlerId ^ BIT_FLANK]) + UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId ^ BIT_FLANK], &gPlayerParty[monIndex], HEALTHBOX_ALL); + else + UpdateHealthboxAttribute(gHealthboxSpriteIds[battlerId], &gPlayerParty[monIndex], HEALTHBOX_ALL); + gTasks[taskId].func = DestroyExpTaskAndCompleteOnInactiveTextPrinter; + } +} + +static void DestroyExpTaskAndCompleteOnInactiveTextPrinter(u8 taskId) +{ + u8 monIndex = gTasks[taskId].tExpTask_monId; + u8 battlerId; + + GetMonData(&gPlayerParty[monIndex], MON_DATA_LEVEL); // Unused return value + battlerId = gTasks[taskId].tExpTask_battler; + gBattlerControllerFuncs[battlerId] = CompleteOnInactiveTextPrinter2; + DestroyTask(taskId); +} + +static void sub_8156DCC(void) +{ + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + { + if (gSprites[gBattlerSpriteIds[gActiveBattler]].pos1.y + gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.y > DISPLAY_HEIGHT) + { + FreeOamMatrix(gSprites[gBattlerSpriteIds[gActiveBattler]].oam.matrixNum); + DestroySprite(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + SetHealthboxSpriteInvisible(gHealthboxSpriteIds[gActiveBattler]); + PokedudeBufferExecCompleted(); + } + } + else + { + if (!gSprites[gBattlerSpriteIds[gActiveBattler]].inUse) + { + SetHealthboxSpriteInvisible(gHealthboxSpriteIds[gActiveBattler]); + PokedudeBufferExecCompleted(); + } + } +} + +static void CompleteOnHealthbarDone(void) +{ + s16 hpValue = MoveBattleBar(gActiveBattler, gHealthboxSpriteIds[gActiveBattler], HEALTH_BAR, 0); + + SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler]); + if (hpValue != -1) + { + UpdateHpTextInHealthbox(gHealthboxSpriteIds[gActiveBattler], hpValue, HP_CURRENT); + } + else + { + HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); + PokedudeBufferExecCompleted(); + } +} + +static void CompleteOnInactiveTextPrinter2(void) +{ + if (!IsTextPrinterActive(0)) + PokedudeBufferExecCompleted(); +} + +static void DoHitAnimBlinkSpriteEffect(void) +{ + u8 spriteId = gBattlerSpriteIds[gActiveBattler]; + + if (gSprites[spriteId].data[1] == 32) + { + gSprites[spriteId].data[1] = 0; + gSprites[spriteId].invisible = FALSE; + gDoingBattleAnim = FALSE; + PokedudeBufferExecCompleted(); + } + else + { + if ((gSprites[spriteId].data[1] % 4) == 0) + gSprites[spriteId].invisible ^= 1; + ++gSprites[spriteId].data[1]; + } +} + +static void sub_8156F7C(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive) + { + FreeSpriteOamMatrix(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + DestroySprite(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + SetHealthboxSpriteInvisible(gHealthboxSpriteIds[gActiveBattler]); + PokedudeBufferExecCompleted(); + } +} + +static void CompleteOnBattlerSpriteCallbackDummy2(void) +{ + if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy) + PokedudeBufferExecCompleted(); +} + +static void CompleteOnFinishedBattleAnimation(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animFromTableActive) + PokedudeBufferExecCompleted(); +} + +static void CompleteOnFinishedStatusAnimation(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].statusAnimActive) + PokedudeBufferExecCompleted(); +} + +static void PokedudeBufferExecCompleted(void) +{ + gBattlerControllerFuncs[gActiveBattler] = PokedudeBufferRunCommand; + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + u8 playerId = GetMultiplayerId(); + + PrepareBufferDataTransferLink(2, 4, &playerId); + gBattleBufferA[gActiveBattler][0] = CONTROLLER_TERMINATOR_NOP; + } + else + { + gBattleControllerExecFlags &= ~gBitTable[gActiveBattler]; + } +} + +// not used +static void CompleteOnFinishedStatusAnimation2(void) +{ + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].statusAnimActive) + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleGetMonData(void) +{ + u8 monData[sizeof(struct Pokemon) * 2 + 56]; // this allows to get full data of two pokemon, trying to get more will result in overwriting data + u32 size = 0; + u8 monToCheck; + s32 i; + + if (gBattleBufferA[gActiveBattler][2] == 0) + { + size += CopyPokedudeMonData(gBattlerPartyIndexes[gActiveBattler], monData); + } + else + { + monToCheck = gBattleBufferA[gActiveBattler][2]; + for (i = 0; i < PARTY_SIZE; ++i) + { + if (monToCheck & 1) + size += CopyPokedudeMonData(i, monData + size); + monToCheck >>= 1; + } + } + BtlController_EmitDataTransfer(1, size, monData); + PokedudeBufferExecCompleted(); +} + +static u32 CopyPokedudeMonData(u8 monId, u8 *dst) +{ + struct BattlePokemon battleMon; + struct MovePpInfo moveData; + u8 nickname[20]; + u8 *src; + s16 data16; + u32 data32; + s32 size = 0; + struct Pokemon *mon; + + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + mon = &gPlayerParty[monId]; + else + mon = &gEnemyParty[monId]; + switch (gBattleBufferA[gActiveBattler][1]) + { + case REQUEST_ALL_BATTLE: + battleMon.species = GetMonData(mon, MON_DATA_SPECIES); + battleMon.item = GetMonData(mon, MON_DATA_HELD_ITEM); + for (size = 0; size < MAX_MON_MOVES; ++size) + { + battleMon.moves[size] = GetMonData(mon, MON_DATA_MOVE1 + size); + battleMon.pp[size] = GetMonData(mon, MON_DATA_PP1 + size); + } + battleMon.ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES); + battleMon.friendship = GetMonData(mon, MON_DATA_FRIENDSHIP); + battleMon.experience = GetMonData(mon, MON_DATA_EXP); + battleMon.hpIV = GetMonData(mon, MON_DATA_HP_IV); + battleMon.attackIV = GetMonData(mon, MON_DATA_ATK_IV); + battleMon.defenseIV = GetMonData(mon, MON_DATA_DEF_IV); + battleMon.speedIV = GetMonData(mon, MON_DATA_SPEED_IV); + battleMon.spAttackIV = GetMonData(mon, MON_DATA_SPATK_IV); + battleMon.spDefenseIV = GetMonData(mon, MON_DATA_SPDEF_IV); + battleMon.personality = GetMonData(mon, MON_DATA_PERSONALITY); + battleMon.status1 = GetMonData(mon, MON_DATA_STATUS); + battleMon.level = GetMonData(mon, MON_DATA_LEVEL); + battleMon.hp = GetMonData(mon, MON_DATA_HP); + battleMon.maxHP = GetMonData(mon, MON_DATA_MAX_HP); + battleMon.attack = GetMonData(mon, MON_DATA_ATK); + battleMon.defense = GetMonData(mon, MON_DATA_DEF); + battleMon.speed = GetMonData(mon, MON_DATA_SPEED); + battleMon.spAttack = GetMonData(mon, MON_DATA_SPATK); + battleMon.spDefense = GetMonData(mon, MON_DATA_SPDEF); + battleMon.isEgg = GetMonData(mon, MON_DATA_IS_EGG); + battleMon.abilityNum = GetMonData(mon, MON_DATA_ABILITY_NUM); + battleMon.otId = GetMonData(mon, MON_DATA_OT_ID); + GetMonData(mon, MON_DATA_NICKNAME, nickname); + StringCopy10(battleMon.nickname, nickname); + GetMonData(mon, MON_DATA_OT_NAME, battleMon.otName); + src = (u8 *)&battleMon; + for (size = 0; size < sizeof(battleMon); ++size) + dst[size] = src[size]; + break; + case REQUEST_SPECIES_BATTLE: + data16 = GetMonData(mon, MON_DATA_SPECIES); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_HELDITEM_BATTLE: + data16 = GetMonData(mon, MON_DATA_HELD_ITEM); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_MOVES_PP_BATTLE: + for (size = 0; size < MAX_MON_MOVES; ++size) + { + moveData.moves[size] = GetMonData(mon, MON_DATA_MOVE1 + size); + moveData.pp[size] = GetMonData(mon, MON_DATA_PP1 + size); + } + moveData.ppBonuses = GetMonData(mon, MON_DATA_PP_BONUSES); + src = (u8 *)(&moveData); + for (size = 0; size < sizeof(moveData); ++size) + dst[size] = src[size]; + break; + case REQUEST_MOVE1_BATTLE: + case REQUEST_MOVE2_BATTLE: + case REQUEST_MOVE3_BATTLE: + case REQUEST_MOVE4_BATTLE: + data16 = GetMonData(mon, MON_DATA_MOVE1 + gBattleBufferA[gActiveBattler][1] - REQUEST_MOVE1_BATTLE); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_PP_DATA_BATTLE: + for (size = 0; size < MAX_MON_MOVES; ++size) + dst[size] = GetMonData(mon, MON_DATA_PP1 + size); + dst[size] = GetMonData(mon, MON_DATA_PP_BONUSES); + ++size; + break; + case REQUEST_PPMOVE1_BATTLE: + case REQUEST_PPMOVE2_BATTLE: + case REQUEST_PPMOVE3_BATTLE: + case REQUEST_PPMOVE4_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_PP1 + gBattleBufferA[gActiveBattler][1] - REQUEST_PPMOVE1_BATTLE); + size = 1; + break; + case REQUEST_OTID_BATTLE: + data32 = GetMonData(mon, MON_DATA_OT_ID); + dst[0] = (data32 & 0x000000FF); + dst[1] = (data32 & 0x0000FF00) >> 8; + dst[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case REQUEST_EXP_BATTLE: + data32 = GetMonData(mon, MON_DATA_EXP); + dst[0] = (data32 & 0x000000FF); + dst[1] = (data32 & 0x0000FF00) >> 8; + dst[2] = (data32 & 0x00FF0000) >> 16; + size = 3; + break; + case REQUEST_HP_EV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_HP_EV); + size = 1; + break; + case REQUEST_ATK_EV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_ATK_EV); + size = 1; + break; + case REQUEST_DEF_EV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_DEF_EV); + size = 1; + break; + case REQUEST_SPEED_EV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_SPEED_EV); + size = 1; + break; + case REQUEST_SPATK_EV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_SPATK_EV); + size = 1; + break; + case REQUEST_SPDEF_EV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_SPDEF_EV); + size = 1; + break; + case REQUEST_FRIENDSHIP_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_FRIENDSHIP); + size = 1; + break; + case REQUEST_POKERUS_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_POKERUS); + size = 1; + break; + case REQUEST_MET_LOCATION_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_MET_LOCATION); + size = 1; + break; + case REQUEST_MET_LEVEL_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_MET_LEVEL); + size = 1; + break; + case REQUEST_MET_GAME_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_MET_GAME); + size = 1; + break; + case REQUEST_POKEBALL_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_POKEBALL); + size = 1; + break; + case REQUEST_ALL_IVS_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_HP_IV); + dst[1] = GetMonData(mon, MON_DATA_ATK_IV); + dst[2] = GetMonData(mon, MON_DATA_DEF_IV); + dst[3] = GetMonData(mon, MON_DATA_SPEED_IV); + dst[4] = GetMonData(mon, MON_DATA_SPATK_IV); + dst[5] = GetMonData(mon, MON_DATA_SPDEF_IV); + size = 6; + break; + case REQUEST_HP_IV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_HP_IV); + size = 1; + break; + case REQUEST_ATK_IV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_ATK_IV); + size = 1; + break; + case REQUEST_DEF_IV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_DEF_IV); + size = 1; + break; + case REQUEST_SPEED_IV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_SPEED_IV); + size = 1; + break; + case REQUEST_SPATK_IV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_SPATK_IV); + size = 1; + break; + case REQUEST_SPDEF_IV_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_SPDEF_IV); + size = 1; + break; + case REQUEST_PERSONALITY_BATTLE: + data32 = GetMonData(mon, MON_DATA_PERSONALITY); + dst[0] = (data32 & 0x000000FF); + dst[1] = (data32 & 0x0000FF00) >> 8; + dst[2] = (data32 & 0x00FF0000) >> 16; + dst[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case REQUEST_CHECKSUM_BATTLE: + data16 = GetMonData(mon, MON_DATA_CHECKSUM); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_STATUS_BATTLE: + data32 = GetMonData(mon, MON_DATA_STATUS); + dst[0] = (data32 & 0x000000FF); + dst[1] = (data32 & 0x0000FF00) >> 8; + dst[2] = (data32 & 0x00FF0000) >> 16; + dst[3] = (data32 & 0xFF000000) >> 24; + size = 4; + break; + case REQUEST_LEVEL_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_LEVEL); + size = 1; + break; + case REQUEST_HP_BATTLE: + data16 = GetMonData(mon, MON_DATA_HP); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_MAX_HP_BATTLE: + data16 = GetMonData(mon, MON_DATA_MAX_HP); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_ATK_BATTLE: + data16 = GetMonData(mon, MON_DATA_ATK); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_DEF_BATTLE: + data16 = GetMonData(mon, MON_DATA_DEF); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_SPEED_BATTLE: + data16 = GetMonData(mon, MON_DATA_SPEED); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_SPATK_BATTLE: + data16 = GetMonData(mon, MON_DATA_SPATK); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_SPDEF_BATTLE: + data16 = GetMonData(mon, MON_DATA_SPDEF); + dst[0] = data16; + dst[1] = data16 >> 8; + size = 2; + break; + case REQUEST_COOL_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_COOL); + size = 1; + break; + case REQUEST_BEAUTY_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_BEAUTY); + size = 1; + break; + case REQUEST_CUTE_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_CUTE); + size = 1; + break; + case REQUEST_SMART_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_SMART); + size = 1; + break; + case REQUEST_TOUGH_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_TOUGH); + size = 1; + break; + case REQUEST_SHEEN_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_SHEEN); + size = 1; + break; + case REQUEST_COOL_RIBBON_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_COOL_RIBBON); + size = 1; + break; + case REQUEST_BEAUTY_RIBBON_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_BEAUTY_RIBBON); + size = 1; + break; + case REQUEST_CUTE_RIBBON_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_CUTE_RIBBON); + size = 1; + break; + case REQUEST_SMART_RIBBON_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_SMART_RIBBON); + size = 1; + break; + case REQUEST_TOUGH_RIBBON_BATTLE: + dst[0] = GetMonData(mon, MON_DATA_TOUGH_RIBBON); + size = 1; + break; + } + return size; +} + +static void PokedudeHandleGetRawMonData(void) +{ + PlayerHandleGetRawMonData(); +} + +static void PokedudeHandleSetMonData(void) +{ + u8 monToCheck; + u8 i; + + if (gBattleBufferA[gActiveBattler][2] == 0) + { + SetPokedudeMonData(gBattlerPartyIndexes[gActiveBattler]); + } + else + { + monToCheck = gBattleBufferA[gActiveBattler][2]; + for (i = 0; i < PARTY_SIZE; ++i) + { + if (monToCheck & 1) + SetPokedudeMonData(i); + monToCheck >>= 1; + } + } + PokedudeBufferExecCompleted(); +} + +static void SetPokedudeMonData(u8 monId) +{ + struct BattlePokemon *battlePokemon = (struct BattlePokemon *)&gBattleBufferA[gActiveBattler][3]; + struct MovePpInfo *moveData = (struct MovePpInfo *)&gBattleBufferA[gActiveBattler][3]; + s32 i; + struct Pokemon *mon; + + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + mon = &gPlayerParty[monId]; + else + mon = &gEnemyParty[monId]; + switch (gBattleBufferA[gActiveBattler][1]) + { + case REQUEST_ALL_BATTLE: + { + u8 iv; + + SetMonData(mon, MON_DATA_SPECIES, &battlePokemon->species); + SetMonData(mon, MON_DATA_HELD_ITEM, &battlePokemon->item); + for (i = 0; i < MAX_MON_MOVES; ++i) + { + SetMonData(mon, MON_DATA_MOVE1 + i, &battlePokemon->moves[i]); + SetMonData(mon, MON_DATA_PP1 + i, &battlePokemon->pp[i]); + } + SetMonData(mon, MON_DATA_PP_BONUSES, &battlePokemon->ppBonuses); + SetMonData(mon, MON_DATA_FRIENDSHIP, &battlePokemon->friendship); + SetMonData(mon, MON_DATA_EXP, &battlePokemon->experience); + iv = battlePokemon->hpIV; + SetMonData(mon, MON_DATA_HP_IV, &iv); + iv = battlePokemon->attackIV; + SetMonData(mon, MON_DATA_ATK_IV, &iv); + iv = battlePokemon->defenseIV; + SetMonData(mon, MON_DATA_DEF_IV, &iv); + iv = battlePokemon->speedIV; + SetMonData(mon, MON_DATA_SPEED_IV, &iv); + iv = battlePokemon->spAttackIV; + SetMonData(mon, MON_DATA_SPATK_IV, &iv); + iv = battlePokemon->spDefenseIV; + SetMonData(mon, MON_DATA_SPDEF_IV, &iv); + SetMonData(mon, MON_DATA_PERSONALITY, &battlePokemon->personality); + SetMonData(mon, MON_DATA_STATUS, &battlePokemon->status1); + SetMonData(mon, MON_DATA_LEVEL, &battlePokemon->level); + SetMonData(mon, MON_DATA_HP, &battlePokemon->hp); + SetMonData(mon, MON_DATA_MAX_HP, &battlePokemon->maxHP); + SetMonData(mon, MON_DATA_ATK, &battlePokemon->attack); + SetMonData(mon, MON_DATA_DEF, &battlePokemon->defense); + SetMonData(mon, MON_DATA_SPEED, &battlePokemon->speed); + SetMonData(mon, MON_DATA_SPATK, &battlePokemon->spAttack); + SetMonData(mon, MON_DATA_SPDEF, &battlePokemon->spDefense); + } + break; + case REQUEST_SPECIES_BATTLE: + SetMonData(mon, MON_DATA_SPECIES, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_HELDITEM_BATTLE: + SetMonData(mon, MON_DATA_HELD_ITEM, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_MOVES_PP_BATTLE: + for (i = 0; i < MAX_MON_MOVES; ++i) + { + SetMonData(mon, MON_DATA_MOVE1 + i, &moveData->moves[i]); + SetMonData(mon, MON_DATA_PP1 + i, &moveData->pp[i]); + } + SetMonData(mon, MON_DATA_PP_BONUSES, &moveData->ppBonuses); + break; + case REQUEST_MOVE1_BATTLE: + case REQUEST_MOVE2_BATTLE: + case REQUEST_MOVE3_BATTLE: + case REQUEST_MOVE4_BATTLE: + SetMonData(mon, MON_DATA_MOVE1 + gBattleBufferA[gActiveBattler][1] - REQUEST_MOVE1_BATTLE, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_PP_DATA_BATTLE: + SetMonData(mon, MON_DATA_PP1, &gBattleBufferA[gActiveBattler][3]); + SetMonData(mon, MON_DATA_PP2, &gBattleBufferA[gActiveBattler][4]); + SetMonData(mon, MON_DATA_PP3, &gBattleBufferA[gActiveBattler][5]); + SetMonData(mon, MON_DATA_PP4, &gBattleBufferA[gActiveBattler][6]); + SetMonData(mon, MON_DATA_PP_BONUSES, &gBattleBufferA[gActiveBattler][7]); + break; + case REQUEST_PPMOVE1_BATTLE: + case REQUEST_PPMOVE2_BATTLE: + case REQUEST_PPMOVE3_BATTLE: + case REQUEST_PPMOVE4_BATTLE: + SetMonData(mon, MON_DATA_PP1 + gBattleBufferA[gActiveBattler][1] - REQUEST_PPMOVE1_BATTLE, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_OTID_BATTLE: + SetMonData(mon, MON_DATA_OT_ID, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_EXP_BATTLE: + SetMonData(mon, MON_DATA_EXP, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_HP_EV_BATTLE: + SetMonData(mon, MON_DATA_HP_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_ATK_EV_BATTLE: + SetMonData(mon, MON_DATA_ATK_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_DEF_EV_BATTLE: + SetMonData(mon, MON_DATA_DEF_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPEED_EV_BATTLE: + SetMonData(mon, MON_DATA_SPEED_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPATK_EV_BATTLE: + SetMonData(mon, MON_DATA_SPATK_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPDEF_EV_BATTLE: + SetMonData(mon, MON_DATA_SPDEF_EV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_FRIENDSHIP_BATTLE: + SetMonData(mon, MON_DATA_FRIENDSHIP, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_POKERUS_BATTLE: + SetMonData(mon, MON_DATA_POKERUS, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_MET_LOCATION_BATTLE: + SetMonData(mon, MON_DATA_MET_LOCATION, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_MET_LEVEL_BATTLE: + SetMonData(mon, MON_DATA_MET_LEVEL, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_MET_GAME_BATTLE: + SetMonData(mon, MON_DATA_MET_GAME, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_POKEBALL_BATTLE: + SetMonData(mon, MON_DATA_POKEBALL, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_ALL_IVS_BATTLE: + SetMonData(mon, MON_DATA_HP_IV, &gBattleBufferA[gActiveBattler][3]); + SetMonData(mon, MON_DATA_ATK_IV, &gBattleBufferA[gActiveBattler][4]); + SetMonData(mon, MON_DATA_DEF_IV, &gBattleBufferA[gActiveBattler][5]); + SetMonData(mon, MON_DATA_SPEED_IV, &gBattleBufferA[gActiveBattler][6]); + SetMonData(mon, MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBattler][7]); + SetMonData(mon, MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBattler][8]); + break; + case REQUEST_HP_IV_BATTLE: + SetMonData(mon, MON_DATA_HP_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_ATK_IV_BATTLE: + SetMonData(mon, MON_DATA_ATK_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_DEF_IV_BATTLE: + SetMonData(mon, MON_DATA_DEF_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPEED_IV_BATTLE: + SetMonData(mon, MON_DATA_SPEED_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPATK_IV_BATTLE: + SetMonData(mon, MON_DATA_SPATK_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPDEF_IV_BATTLE: + SetMonData(mon, MON_DATA_SPDEF_IV, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_PERSONALITY_BATTLE: + SetMonData(mon, MON_DATA_PERSONALITY, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_CHECKSUM_BATTLE: + SetMonData(mon, MON_DATA_CHECKSUM, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_STATUS_BATTLE: + SetMonData(mon, MON_DATA_STATUS, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_LEVEL_BATTLE: + SetMonData(mon, MON_DATA_LEVEL, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_HP_BATTLE: + SetMonData(mon, MON_DATA_HP, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_MAX_HP_BATTLE: + SetMonData(mon, MON_DATA_MAX_HP, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_ATK_BATTLE: + SetMonData(mon, MON_DATA_ATK, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_DEF_BATTLE: + SetMonData(mon, MON_DATA_DEF, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPEED_BATTLE: + SetMonData(mon, MON_DATA_SPEED, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPATK_BATTLE: + SetMonData(mon, MON_DATA_SPATK, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SPDEF_BATTLE: + SetMonData(mon, MON_DATA_SPDEF, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_COOL_BATTLE: + SetMonData(mon, MON_DATA_COOL, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_BEAUTY_BATTLE: + SetMonData(mon, MON_DATA_BEAUTY, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_CUTE_BATTLE: + SetMonData(mon, MON_DATA_CUTE, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SMART_BATTLE: + SetMonData(mon, MON_DATA_SMART, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_TOUGH_BATTLE: + SetMonData(mon, MON_DATA_TOUGH, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SHEEN_BATTLE: + SetMonData(mon, MON_DATA_SHEEN, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_COOL_RIBBON_BATTLE: + SetMonData(mon, MON_DATA_COOL_RIBBON, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_BEAUTY_RIBBON_BATTLE: + SetMonData(mon, MON_DATA_BEAUTY_RIBBON, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_CUTE_RIBBON_BATTLE: + SetMonData(mon, MON_DATA_CUTE_RIBBON, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_SMART_RIBBON_BATTLE: + SetMonData(mon, MON_DATA_SMART_RIBBON, &gBattleBufferA[gActiveBattler][3]); + break; + case REQUEST_TOUGH_RIBBON_BATTLE: + SetMonData(mon, MON_DATA_TOUGH_RIBBON, &gBattleBufferA[gActiveBattler][3]); + break; + } + HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); +} + +static void PokedudeHandleSetRawMonData(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleLoadMonSprite(void) +{ + u32 y; + u16 species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES); + + BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); + y = GetBattlerSpriteDefault_Y(gActiveBattler); + SetMultiuseSpriteTemplateToPokemon(species, GetBattlerPosition(gActiveBattler)); + gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate, + GetBattlerSpriteCoord(gActiveBattler, 2), + y, + GetBattlerSpriteSubpriority(gActiveBattler)); + gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x = -240; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = gActiveBattler; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[2] = species; + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = gActiveBattler; + StartSpriteAnim(&gSprites[gBattlerSpriteIds[gActiveBattler]], gBattleMonForms[gActiveBattler]); + SetBattlerShadowSpriteCallback(gActiveBattler, GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES)); + gBattlerControllerFuncs[gActiveBattler] = sub_8156184; + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleSwitchInAnim(void) +{ + ClearTemporarySpeciesSpriteData(gActiveBattler, gBattleBufferA[gActiveBattler][2]); + gBattlerPartyIndexes[gActiveBattler] = gBattleBufferA[gActiveBattler][1]; + BattleLoadPlayerMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); + gActionSelectionCursor[gActiveBattler] = 0; + gMoveSelectionCursor[gActiveBattler] = 0; + sub_8159478(gActiveBattler); + gBattlerControllerFuncs[gActiveBattler] = sub_81563A8; +} + +static void PokedudeHandleReturnMonToBall(void) +{ + if (gBattleBufferA[gActiveBattler][1] == 0) + { + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_SWITCH_OUT_PLAYER_MON); + gBattlerControllerFuncs[gActiveBattler] = sub_8156F7C; + } + else + { + FreeSpriteOamMatrix(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + DestroySprite(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + SetHealthboxSpriteInvisible(gHealthboxSpriteIds[gActiveBattler]); + PokedudeBufferExecCompleted(); + } +} + +static void PokedudeHandleDrawTrainerPic(void) +{ + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + { + DecompressTrainerBackPalette(4, gActiveBattler); + SetMultiuseSpriteTemplateToTrainerBack(4, GetBattlerPosition(gActiveBattler)); + gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate, + 80, + (8 - gTrainerBackPicCoords[4].size) * 4 + 80, + 30); + gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x = 240; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = -2; + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = gActiveBattler; + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_8033EEC; + } + else + { + u32 tranerPicid = TRAINER_PIC_PROFESSOR_OAK; + DecompressTrainerFrontPic(tranerPicid, gActiveBattler); + SetMultiuseSpriteTemplateToTrainerBack(tranerPicid, GetBattlerPosition(gActiveBattler)); + gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate, + 176, + (8 - gTrainerFrontPicCoords[tranerPicid].size) * 4 + 40, + GetBattlerSpriteSubpriority(gActiveBattler)); + gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x = -240; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = 2; + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = IndexOfSpritePaletteTag(gTrainerFrontPicPaletteTable[tranerPicid].tag); + gSprites[gBattlerSpriteIds[gActiveBattler]].data[5] = gSprites[gBattlerSpriteIds[gActiveBattler]].oam.tileNum; + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.tileNum = GetSpriteTileStartByTag(gTrainerFrontPicTable[tranerPicid].tag); + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.affineParam = tranerPicid; + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_8033EEC; + } + gBattlerControllerFuncs[gActiveBattler] = CompleteOnBattlerSpriteCallbackDummy; +} + +static void PokedudeHandleTrainerSlide(void) +{ + DecompressTrainerBackPalette(4, gActiveBattler); + SetMultiuseSpriteTemplateToTrainerBack(4, GetBattlerPosition(gActiveBattler)); + gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate, + 80, + (8 - gTrainerBackPicCoords[4].size) * 4 + 80, + 30); + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = gActiveBattler; + gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x = -96; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = 2; + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_8033EEC; + gBattlerControllerFuncs[gActiveBattler] = CompleteOnBattlerSpriteCallbackDummy2; +} + +static void PokedudeHandleTrainerSlideBack(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleFaintAnimation(void) +{ + if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState == 0) + { + if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute) + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_SUBSTITUTE_TO_MON); + ++gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState; + } + else + { + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive) + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + { + HandleLowHpMusicChange(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], gActiveBattler); + PlaySE12WithPanning(SE_POKE_DEAD, SOUND_PAN_ATTACKER); + gSprites[gBattlerSpriteIds[gActiveBattler]].data[1] = 0; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[2] = 5; + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_8012110; + } + else + { + PlaySE12WithPanning(SE_POKE_DEAD, SOUND_PAN_TARGET); + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = SpriteCB_FaintOpponentMon; + } + gBattlerControllerFuncs[gActiveBattler] = sub_8156DCC; + } + } +} + +static void PokedudeHandlePaletteFade(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleSuccessBallThrowAnim(void) +{ + gBattleSpritesDataPtr->animationData->ballThrowCaseId = BALL_3_SHAKES_SUCCESS; + gDoingBattleAnim = TRUE; + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), B_ANIM_BALL_THROW); + gBattlerControllerFuncs[gActiveBattler] = CompleteOnSpecialAnimDone; +} + +static void PokedudeHandleBallThrowAnim(void) +{ + u8 ballThrowCaseId = gBattleBufferA[gActiveBattler][1]; + + gBattleSpritesDataPtr->animationData->ballThrowCaseId = ballThrowCaseId; + gDoingBattleAnim = TRUE; + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), B_ANIM_BALL_THROW); + gBattlerControllerFuncs[gActiveBattler] = CompleteOnSpecialAnimDone; +} + +static void PokedudeHandlePause(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleMoveAnimation(void) +{ + u16 move = gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8); + + gAnimMoveTurn = gBattleBufferA[gActiveBattler][3]; + gAnimMovePower = gBattleBufferA[gActiveBattler][4] | (gBattleBufferA[gActiveBattler][5] << 8); + gAnimMoveDmg = gBattleBufferA[gActiveBattler][6] | (gBattleBufferA[gActiveBattler][7] << 8) | (gBattleBufferA[gActiveBattler][8] << 16) | (gBattleBufferA[gActiveBattler][9] << 24); + gAnimFriendship = gBattleBufferA[gActiveBattler][10]; + gWeatherMoveAnim = gBattleBufferA[gActiveBattler][12] | (gBattleBufferA[gActiveBattler][13] << 8); + gAnimDisableStructPtr = (struct DisableStruct *)&gBattleBufferA[gActiveBattler][16]; + gTransformedPersonalities[gActiveBattler] = gAnimDisableStructPtr->transformedMonPersonality; + if (IsMoveWithoutAnimation(move, gAnimMoveTurn)) // always returns FALSE + { + PokedudeBufferExecCompleted(); + } + else + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; + gBattlerControllerFuncs[gActiveBattler] = PokedudeDoMoveAnimation; + } +} + +static void PokedudeDoMoveAnimation(void) +{ + u16 move = gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8); + + switch (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState) + { + case 0: + if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute) + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_SUBSTITUTE_TO_MON); + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 1; + break; + case 1: + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive) + { + sub_8035450(0); + DoMoveAnim(move); + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 2; + } + break; + case 2: + gAnimScriptCallback(); + if (!gAnimScriptActive) + { + sub_8035450(1); + if (gBattleSpritesDataPtr->battlerData[gActiveBattler].behindSubstitute) + InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, gActiveBattler, B_ANIM_MON_TO_SUBSTITUTE); + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 3; + } + break; + case 3: + if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive) + { + CopyAllBattleSpritesInvisibilities(); + TrySetBehindSubstituteSpriteBit(gActiveBattler, gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8)); + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animationState = 0; + PokedudeBufferExecCompleted(); + } + break; + } +} + +static void PokedudeHandlePrintString(void) +{ + u16 *stringId; + + gBattle_BG0_X = 0; + gBattle_BG0_Y = 0; + stringId = (u16 *)(&gBattleBufferA[gActiveBattler][2]); + BufferStringBattle(*stringId); + if (sub_80D89B0(*stringId)) + BattlePutTextOnWindow(gDisplayedStringBattle, 64); + else + BattlePutTextOnWindow(gDisplayedStringBattle, 0); + gBattlerControllerFuncs[gActiveBattler] = CompleteOnInactiveTextPrinter; +} + +static void PokedudeHandlePrintSelectionString(void) +{ + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + PokedudeHandlePrintString(); + else + PokedudeBufferExecCompleted(); +} + +static void sub_8158B20(void) +{ + if (!IsDma3ManagerBusyWithBgCopy()) + { + gBattle_BG0_X = 0; + gBattle_BG0_Y = 160; + gBattlerControllerFuncs[gActiveBattler] = sub_8156140; + } +} + +static void PokedudeHandleChooseAction(void) +{ + s32 i; + + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + { + gBattlerControllerFuncs[gActiveBattler] = sub_8158B20; + BattlePutTextOnWindow(gUnknown_83FDA4C, 0); + BattlePutTextOnWindow(gUnknown_83FE725, 2); + for (i = 0; i < MAX_MON_MOVES; ++i) + ActionSelectionDestroyCursorAt((u8)i); + ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0); + BattleStringExpandPlaceholdersToDisplayedString(gText_WhatWillPkmnDo); + BattlePutTextOnWindow(gDisplayedStringBattle, 1); + } + else + { + gBattlerControllerFuncs[gActiveBattler] = sub_8156140; + } +} + +static void PokedudeHandleUnknownYesNoBox(void) +{ + PokedudeBufferExecCompleted(); +} + +static void sub_8158C04(void) +{ + if (!IsDma3ManagerBusyWithBgCopy()) + { + gBattle_BG0_X = 0; + gBattle_BG0_Y = 320; + gBattlerControllerFuncs[gActiveBattler] = sub_81564E4; + } +} + +static void PokedudeHandleChooseMove(void) +{ + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + { + InitMoveSelectionsVarsAndStrings(); + gBattlerControllerFuncs[gActiveBattler] = sub_8158C04; + } + else + { + gBattlerControllerFuncs[gActiveBattler] = sub_81564E4; + } +} + +static void PokedudeHandleChooseItem(void) +{ + s32 i; + + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK); + gBattlerControllerFuncs[gActiveBattler] = OpenBagAndChooseItem; + gBattlerInMenuId = gActiveBattler; + for (i = 0; i < 3; ++i) + gUnknown_203B0DC[i] = gBattleBufferA[gActiveBattler][i + 1]; +} + +static void PokedudeHandleChoosePokemon(void) +{ + s32 i; + + gUnknown_3004FFC[gActiveBattler] = CreateTask(TaskDummy, 0xFF); + gTasks[gUnknown_3004FFC[gActiveBattler]].data[0] = gBattleBufferA[gActiveBattler][1] & 0xF; + *(&gBattleStruct->battlerPreventingSwitchout) = gBattleBufferA[gActiveBattler][1] >> 4; + *(&gBattleStruct->field_8B) = gBattleBufferA[gActiveBattler][2]; + *(&gBattleStruct->abilityPreventingSwitchout) = gBattleBufferA[gActiveBattler][3]; + for (i = 0; i < 3; ++i) + gUnknown_203B0DC[i] = gBattleBufferA[gActiveBattler][4 + i]; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK); + gBattlerControllerFuncs[gActiveBattler] = OpenPartyMenuToChooseMon; + gBattlerInMenuId = gActiveBattler; +} + +static void PokedudeHandleCmd23(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleHealthBarUpdate(void) +{ + s16 hpVal; + struct Pokemon *mon; + + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + mon = &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]]; + else + mon = &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]]; + LoadBattleBarGfx(0); + hpVal = gBattleBufferA[gActiveBattler][2] | (gBattleBufferA[gActiveBattler][3] << 8); + if (hpVal != INSTANT_HP_BAR_DROP) + { + u32 maxHP = GetMonData(mon, MON_DATA_MAX_HP); + u32 curHP = GetMonData(mon, MON_DATA_HP); + + SetBattleBarStruct(gActiveBattler, gHealthboxSpriteIds[gActiveBattler], maxHP, curHP, hpVal); + } + else + { + u32 maxHP = GetMonData(mon, MON_DATA_MAX_HP); + + SetBattleBarStruct(gActiveBattler, gHealthboxSpriteIds[gActiveBattler], maxHP, 0, hpVal); + UpdateHpTextInHealthbox(gHealthboxSpriteIds[gActiveBattler], 0, HP_CURRENT); + } + gBattlerControllerFuncs[gActiveBattler] = CompleteOnHealthbarDone; +} + +static void PokedudeHandleExpUpdate(void) +{ + u8 monId = gBattleBufferA[gActiveBattler][1]; + + if (GetMonData(&gPlayerParty[monId], MON_DATA_LEVEL) >= MAX_LEVEL) + { + PokedudeBufferExecCompleted(); + } + else + { + s16 expPointsToGive; + u8 taskId; + + LoadBattleBarGfx(1); + GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES); // Unused return value. + expPointsToGive = T1_READ_16(&gBattleBufferA[gActiveBattler][2]); + taskId = CreateTask(Task_GiveExpToMon, 10); + gTasks[taskId].tExpTask_monId = monId; + gTasks[taskId].tExpTask_gainedExp = expPointsToGive; + gTasks[taskId].tExpTask_battler = gActiveBattler; + gBattlerControllerFuncs[gActiveBattler] = nullsub_99; + } +} + +static void PokedudeHandleStatusIconUpdate(void) +{ + if (!mplay_80342A4(gActiveBattler)) + { + u8 battlerId; + struct Pokemon *mon; + + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + mon = &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]]; + else + mon = &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]]; + UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], mon, HEALTHBOX_STATUS_ICON); + battlerId = gActiveBattler; + gBattleSpritesDataPtr->healthBoxesData[battlerId].statusAnimActive = FALSE; + gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; + } +} + +static void PokedudeHandleStatusAnimation(void) +{ + if (!mplay_80342A4(gActiveBattler)) + { + InitAndLaunchChosenStatusAnimation(gBattleBufferA[gActiveBattler][1], + gBattleBufferA[gActiveBattler][2] | (gBattleBufferA[gActiveBattler][3] << 8) | (gBattleBufferA[gActiveBattler][4] << 16) | (gBattleBufferA[gActiveBattler][5] << 24)); + gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedStatusAnimation; + } +} + +static void PokedudeHandleStatusXor(void) +{ + struct Pokemon *mon; + u8 val; + + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + mon = &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]]; + else + mon = &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]]; + val = GetMonData(mon, MON_DATA_STATUS) ^ gBattleBufferA[gActiveBattler][1]; + SetMonData(mon, MON_DATA_STATUS, &val); + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleDataTransfer(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleDMA3Transfer(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandlePlayBGM(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleCmd32(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleTwoReturnValues(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleChosenMonReturnValue(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleOneReturnValue(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleOneReturnValue_Duplicate(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleCmd37(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleCmd38(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleCmd39(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleCmd40(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleHitAnimation(void) +{ + if (gSprites[gBattlerSpriteIds[gActiveBattler]].invisible == TRUE) + { + PokedudeBufferExecCompleted(); + } + else + { + gDoingBattleAnim = TRUE; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[1] = 0; + DoHitAnimHealthboxEffect(gActiveBattler); + gBattlerControllerFuncs[gActiveBattler] = DoHitAnimBlinkSpriteEffect; + } +} + +static void PokedudeHandleCmd42(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandlePlaySE(void) +{ + PlaySE(gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8)); + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandlePlayFanfare(void) +{ + PlayFanfare(gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8)); + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleFaintingCry(void) +{ + struct Pokemon *mon; + u16 species; + + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + mon = &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]]; + else + mon = &gEnemyParty[gBattlerPartyIndexes[gActiveBattler]]; + species = GetMonData(mon, MON_DATA_SPECIES); + PlayCry1(species, 25); + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleIntroSlide(void) +{ + HandleIntroSlide(gBattleBufferA[gActiveBattler][1]); + gIntroSlideFlags |= 1; + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleIntroTrainerBallThrow(void) +{ + u8 paletteNum; + u8 taskId; + + SetSpritePrimaryCoordsFromSecondaryCoords(&gSprites[gBattlerSpriteIds[gActiveBattler]]); + gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = 50; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[2] = -40; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[4] = gSprites[gBattlerSpriteIds[gActiveBattler]].pos1.y; + gSprites[gBattlerSpriteIds[gActiveBattler]].callback = StartAnimLinearTranslation; + gSprites[gBattlerSpriteIds[gActiveBattler]].data[5] = gActiveBattler; + StoreSpriteCallbackInData6(&gSprites[gBattlerSpriteIds[gActiveBattler]], sub_80335F8); + StartSpriteAnim(&gSprites[gBattlerSpriteIds[gActiveBattler]], 1); + paletteNum = AllocSpritePalette(0xD6F8); + LoadCompressedPalette(gTrainerBackPicPaletteTable[4].data, 0x100 + paletteNum * 16, 32); + gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = paletteNum; + taskId = CreateTask(sub_81595EC, 5); + gTasks[taskId].data[0] = gActiveBattler; + if (gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].partyStatusSummaryShown) + gTasks[gBattlerStatusSummaryTaskId[gActiveBattler]].func = Task_HidePartyStatusSummary; + gBattleSpritesDataPtr->animationData->field_9_x1 = 1; + gBattlerControllerFuncs[gActiveBattler] = nullsub_99; +} + +static void sub_8159478(u8 battlerId) +{ + u16 species; + + gBattleSpritesDataPtr->battlerData[battlerId].transformSpecies = SPECIES_NONE; + gBattlerPartyIndexes[battlerId] = gBattleBufferA[battlerId][1]; + species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); + gUnknown_3004FFC[battlerId] = CreateInvisibleSpriteWithCallback(sub_8033E3C); + SetMultiuseSpriteTemplateToPokemon(species, GetBattlerPosition(battlerId)); + gBattlerSpriteIds[battlerId] = CreateSprite(&gMultiuseSpriteTemplate, + GetBattlerSpriteCoord(battlerId, 2), + GetBattlerSpriteDefault_Y(battlerId), + GetBattlerSpriteSubpriority(battlerId)); + gSprites[gUnknown_3004FFC[battlerId]].data[1] = gBattlerSpriteIds[battlerId]; + gSprites[gBattlerSpriteIds[battlerId]].data[0] = battlerId; + gSprites[gBattlerSpriteIds[battlerId]].data[2] = species; + gSprites[gBattlerSpriteIds[battlerId]].oam.paletteNum = battlerId; + StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerId]], gBattleMonForms[battlerId]); + gSprites[gBattlerSpriteIds[battlerId]].invisible = TRUE; + gSprites[gBattlerSpriteIds[battlerId]].callback = SpriteCallbackDummy; + gSprites[gUnknown_3004FFC[battlerId]].data[0] = DoPokeballSendOutAnimation(0, POKEBALL_PLAYER_SENDOUT); +} + +static void sub_81595EC(u8 taskId) +{ + if (gTasks[taskId].data[1] < 31) + { + ++gTasks[taskId].data[1]; + } + else + { + u8 savedActiveBattler = gActiveBattler; + + gActiveBattler = gTasks[taskId].data[0]; + gBattleBufferA[gActiveBattler][1] = gBattlerPartyIndexes[gActiveBattler]; + sub_8159478(gActiveBattler); + gBattlerControllerFuncs[gActiveBattler] = sub_8156624; + gActiveBattler = savedActiveBattler; + DestroyTask(taskId); + } +} + +static void PokedudeHandleDrawPartyStatusSummary(void) +{ + if (gBattleBufferA[gActiveBattler][1] != 0 + && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + { + PokedudeBufferExecCompleted(); + } + else + { + gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].partyStatusSummaryShown = TRUE; + gBattlerStatusSummaryTaskId[gActiveBattler] = CreatePartyStatusSummarySprites(gActiveBattler, + (struct HpAndStatus *)&gBattleBufferA[gActiveBattler][4], + gBattleBufferA[gActiveBattler][1], + gBattleBufferA[gActiveBattler][2]); + PokedudeBufferExecCompleted(); + } +} + +static void PokedudeHandleHidePartyStatusSummary(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleEndBounceEffect(void) +{ + EndBounceEffect(gActiveBattler, BOUNCE_HEALTHBOX); + EndBounceEffect(gActiveBattler, BOUNCE_MON); + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleSpriteInvisibility(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleBattleAnimation(void) +{ + u8 animationId = gBattleBufferA[gActiveBattler][1]; + u16 argument = gBattleBufferA[gActiveBattler][2] | (gBattleBufferA[gActiveBattler][3] << 8); + + if (TryHandleLaunchBattleTableAnimation(gActiveBattler, gActiveBattler, gActiveBattler, animationId, argument)) + PokedudeBufferExecCompleted(); + else + gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedBattleAnimation; +} + +static void PokedudeHandleLinkStandbyMsg(void) +{ + switch (gBattleBufferA[gActiveBattler][1]) + { + case 0: + case 1: + EndBounceEffect(gActiveBattler, BOUNCE_HEALTHBOX); + EndBounceEffect(gActiveBattler, BOUNCE_MON); + break; + case 2: + break; + } + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleResetActionMoveSelection(void) +{ + PokedudeBufferExecCompleted(); +} + +static void PokedudeHandleCmd55(void) +{ + gBattleOutcome = gBattleBufferA[gActiveBattler][1]; + FadeOutMapMusic(5); + BeginFastPaletteFade(3); + PokedudeBufferExecCompleted(); + if (!(gBattleTypeFlags & BATTLE_TYPE_IS_MASTER) && gBattleTypeFlags & BATTLE_TYPE_LINK) + gBattlerControllerFuncs[gActiveBattler] = sub_8156254; +} + +static void PokedudeCmdEnd(void) +{ +} + +static void sub_8159824(void) +{ + const u8 (*r7)[8] = gUnknown_8479060[gBattleStruct->field_96]; + + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + { + DoBounceEffect(gActiveBattler, BOUNCE_HEALTHBOX, 7, 1); + DoBounceEffect(gActiveBattler, BOUNCE_MON, 7, 1); + } + if (*(r7[gUnknown_3005EE0[gActiveBattler][0]] + gActiveBattler + 4) == gUnknown_3005EE0[gActiveBattler][2]) + { + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + PlaySE(SE_SELECT); + gUnknown_3005EE0[gActiveBattler][2] = 0; + switch (r7[gUnknown_3005EE0[gActiveBattler][0]][gActiveBattler]) + { + case 0: + BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, 0); + break; + case 1: + BtlController_EmitTwoReturnValues(1, B_ACTION_USE_ITEM, 0); + break; + case 2: + BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0); + break; + case 3: + BtlController_EmitTwoReturnValues(1, B_ACTION_RUN, 0); + break; + } + PokedudeBufferExecCompleted(); + ++gUnknown_3005EE0[gActiveBattler][0]; + if (r7[gUnknown_3005EE0[gActiveBattler][0]][gActiveBattler] == 4) + gUnknown_3005EE0[gActiveBattler][0] = 0; + } + else + { + if (gActionSelectionCursor[gActiveBattler] != r7[gUnknown_3005EE0[gActiveBattler][0]][gActiveBattler] + && r7[gUnknown_3005EE0[gActiveBattler][0]][gActiveBattler + 4] / 2 == gUnknown_3005EE0[gActiveBattler][2]) + { + PlaySE(SE_SELECT); + ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBattler]); + gActionSelectionCursor[gActiveBattler] = r7[gUnknown_3005EE0[gActiveBattler][0]][gActiveBattler]; + ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0); + } + ++gUnknown_3005EE0[gActiveBattler][2]; + } +} + +static void sub_8159998(void) +{ + const u8 (*r7)[8] = gUnknown_84790D8[gBattleStruct->field_96]; + + if (*(r7[gUnknown_3005EE0[gActiveBattler][1]] + gActiveBattler + 4) == gUnknown_3005EE0[gActiveBattler][2]) + { + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + PlaySE(SE_SELECT); + gUnknown_3005EE0[gActiveBattler][2] = 0; + BtlController_EmitTwoReturnValues(1, + B_ACTION_EXEC_SCRIPT, + r7[gUnknown_3005EE0[gActiveBattler][1]][gActiveBattler] | ((gActiveBattler ^ BIT_SIDE) << 8)); + PokedudeBufferExecCompleted(); + ++gUnknown_3005EE0[gActiveBattler][1]; + if (r7[gUnknown_3005EE0[gActiveBattler][1]][gActiveBattler] == 255) + gUnknown_3005EE0[gActiveBattler][1] = 0; + } + else + { + if (r7[gUnknown_3005EE0[gActiveBattler][1]][gActiveBattler] != gMoveSelectionCursor[gActiveBattler] + && r7[gUnknown_3005EE0[gActiveBattler][1]][gActiveBattler + 4] / 2 == gUnknown_3005EE0[gActiveBattler][2]) + { + PlaySE(SE_SELECT); + MoveSelectionDestroyCursorAt(gMoveSelectionCursor[gActiveBattler]); + gMoveSelectionCursor[gActiveBattler] = r7[gUnknown_3005EE0[gActiveBattler][1]][gActiveBattler]; + MoveSelectionCreateCursorAt(gMoveSelectionCursor[gActiveBattler], 0); + } + ++gUnknown_3005EE0[gActiveBattler][2]; + } +} + +#ifdef NONMATCHING +static bool8 sub_8159AB8(void) +{ + const struct Unk_84790E8 *r6 = gUnknown_8479198[gBattleStruct->field_96]; + // why is address of unk_2 loaded first? + const struct Unk_84790E8 *r12 = (const struct Unk_84790E8 *)gBattleBufferA[gActiveBattler]; + + if (r12->unk_0 == r6[gBattleStruct->field_97].unk_0 + && gActiveBattler == r6[gBattleStruct->field_97].unk_1 + && (r12->unk_0 != 16 || r6[gBattleStruct->field_97].unk_2 == r12->unk_2)) + { + // why is mem reloaded here? + // asm("":::"memory"); + if (r6[gBattleStruct->field_97].unk_4 != NULL) + { + gBattlerControllerFuncs[gActiveBattler] = r6[gBattleStruct->field_97].unk_4; + gUnknown_3005EE0[gActiveBattler][2] = 0; + gUnknown_3005EE0[gActiveBattler][3] = r6[gBattleStruct->field_97].unk_2; + ++gBattleStruct->field_97; + return TRUE; + } + ++gBattleStruct->field_97; + } + return FALSE; +} +#else +NAKED +static bool8 sub_8159AB8(void) +{ + asm_unified("\n\ + push {r4-r7,lr}\n\ + ldr r1, _08159B54 @ =gUnknown_8479198\n\ + ldr r4, _08159B58 @ =gBattleStruct\n\ + ldr r2, [r4]\n\ + adds r0, r2, 0\n\ + adds r0, 0x96\n\ + ldrb r0, [r0]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r6, [r0]\n\ + ldr r3, _08159B5C @ =gActiveBattler\n\ + ldrb r5, [r3]\n\ + lsls r1, r5, 9\n\ + ldr r0, _08159B60 @ =gBattleBufferA + 2\n\ + adds r7, r1, r0\n\ + mov r12, r7\n\ + subs r0, 0x2\n\ + adds r1, r0\n\ + adds r2, 0x97\n\ + ldrb r0, [r2]\n\ + lsls r0, 3\n\ + adds r0, r6\n\ + ldrb r1, [r1]\n\ + adds r7, r4, 0\n\ + adds r4, r3, 0\n\ + ldrb r2, [r0]\n\ + cmp r1, r2\n\ + bne _08159B70\n\ + ldrb r2, [r0, 0x1]\n\ + cmp r5, r2\n\ + bne _08159B70\n\ + cmp r1, 0x10\n\ + bne _08159B04\n\ + ldrh r0, [r0, 0x2]\n\ + mov r1, r12\n\ + ldrh r1, [r1]\n\ + cmp r0, r1\n\ + bne _08159B70\n\ + _08159B04:\n\ + ldr r0, [r7]\n\ + adds r3, r0, 0\n\ + adds r3, 0x97\n\ + ldrb r1, [r3]\n\ + lsls r0, r1, 3\n\ + adds r0, r6\n\ + ldr r2, [r0, 0x4]\n\ + cmp r2, 0\n\ + beq _08159B6C\n\ + ldr r1, _08159B64 @ =gBattlerControllerFuncs\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + str r2, [r0]\n\ + ldr r2, _08159B68 @ =gUnknown_3005EE0\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldr r1, [r0]\n\ + movs r0, 0\n\ + strb r0, [r1, 0x2]\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r2\n\ + ldr r1, [r0]\n\ + ldr r0, [r7]\n\ + adds r0, 0x97\n\ + ldrb r0, [r0]\n\ + lsls r0, 3\n\ + adds r0, r6\n\ + ldrh r0, [r0, 0x2]\n\ + strb r0, [r1, 0x3]\n\ + ldr r1, [r7]\n\ + adds r1, 0x97\n\ + ldrb r0, [r1]\n\ + adds r0, 0x1\n\ + strb r0, [r1]\n\ + movs r0, 0x1\n\ + b _08159B72\n\ + .align 2, 0\n\ + _08159B54: .4byte gUnknown_8479198\n\ + _08159B58: .4byte gBattleStruct\n\ + _08159B5C: .4byte gActiveBattler\n\ + _08159B60: .4byte gBattleBufferA + 2\n\ + _08159B64: .4byte gBattlerControllerFuncs\n\ + _08159B68: .4byte gUnknown_3005EE0\n\ + _08159B6C:\n\ + adds r0, r1, 0x1\n\ + strb r0, [r3]\n\ + _08159B70:\n\ + movs r0, 0\n\ + _08159B72:\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + "); +} +#endif + +static void sub_8159B78(void) +{ + gUnknown_3005EE0[gActiveBattler][2] = 0; + gBattlerControllerFuncs[gActiveBattler] = PokedudeBufferRunCommand; +} + +static void sub_8159BA8(void) +{ + switch (gUnknown_3005EE0[gActiveBattler][2]) + { + case 0: + if (!gPaletteFade.active) + { + BeginNormalPaletteFade(0xFFFFFF7F, 4, 0, 8, RGB_BLACK); + ++gUnknown_3005EE0[gActiveBattler][2]; + } + break; + case 1: + if (!gPaletteFade.active) + { + gUnknown_3005EE0[gActiveBattler][4] = gBattle_BG0_Y; + sub_80EB30C(); + ++gUnknown_3005EE0[gActiveBattler][2]; + } + break; + case 2: + gBattle_BG0_Y = 0; + BattleStringExpandPlaceholdersToDisplayedString(sub_8159EF0()); + BattlePutTextOnWindow(gDisplayedStringBattle, 24); + ++gUnknown_3005EE0[gActiveBattler][2]; + break; + case 3: + if (!IsTextPrinterActive(24) && JOY_NEW(A_BUTTON)) + { + PlaySE(SE_SELECT); + BeginNormalPaletteFade(0xFFFFFF7F, 4, 8, 0, RGB_BLACK); + ++gUnknown_3005EE0[gActiveBattler][2]; + } + break; + case 4: + if (!gPaletteFade.active) + { + if (gUnknown_3005EE0[gActiveBattler][3] == 13) + { + BattleStopLowHpSound(); + PlayBGM(MUS_WIN_YASEI); + } + gBattle_BG0_Y = gUnknown_3005EE0[gActiveBattler][4]; + sub_80EB524(); + sub_8159B78(); + } + break; + } +} + +static void sub_8159D04(void) +{ + switch (gUnknown_3005EE0[gActiveBattler][2]) + { + case 0: + if (!gPaletteFade.active) + { + sub_80EEFC8(&gBattleStruct->field_95, + &gBattleStruct->field_94, + GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)); + BeginNormalPaletteFade(0xFFFFFF7F, 4, 0, 8, RGB_BLACK); + ++gUnknown_3005EE0[gActiveBattler][2]; + } + break; + case 1: + if (!gPaletteFade.active) + { + u32 mask = (gBitTable[gBattleStruct->field_95] | gBitTable[gBattleStruct->field_94]) << 16; + + ++mask; // It's possible that this is influenced by other functions, as + --mask; // this also striked in battle_controller_oak_old_man.c but was naturally fixed. + BeginNormalPaletteFade(mask, 4, 8, 0, RGB_BLACK); + ++gUnknown_3005EE0[gActiveBattler][2]; + } + break; + case 2: + if (!gPaletteFade.active) + { + sub_80EB30C(); + ++gUnknown_3005EE0[gActiveBattler][2]; + } + break; + case 3: + BattleStringExpandPlaceholdersToDisplayedString(sub_8159EF0()); + BattlePutTextOnWindow(gDisplayedStringBattle, 24); + ++gUnknown_3005EE0[gActiveBattler][2]; + break; + case 4: + if (!IsTextPrinterActive(24) && JOY_NEW(A_BUTTON)) + { + u32 mask; + + PlaySE(SE_SELECT); + mask = (gBitTable[gBattleStruct->field_95] | gBitTable[gBattleStruct->field_94]) << 16; + ++mask; + --mask; + BeginNormalPaletteFade(mask, 4, 0, 8, RGB_BLACK); + ++gUnknown_3005EE0[gActiveBattler][2]; + } + break; + case 5: + if (!gPaletteFade.active) + { + BeginNormalPaletteFade(0xFFFFFF7F, 4, 8, 0, RGB_BLACK); + ++gUnknown_3005EE0[gActiveBattler][2]; + } + break; + case 6: + if (!gPaletteFade.active) + { + if (gUnknown_3005EE0[gActiveBattler][3] == 13) + { + BattleStopLowHpSound(); + PlayBGM(MUS_WIN_YASEI); + } + sub_80EF0E0(GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)); + sub_80EB524(); + sub_8159B78(); + } + break; + } +} + +static const u8 *sub_8159EF0(void) +{ + switch (gBattleStruct->field_96) + { + case 0: + default: + return gUnknown_84791A8[gBattleStruct->field_97 - 1]; + case 1: + return gUnknown_84791B8[gBattleStruct->field_97 - 1]; + case 2: + return gUnknown_84791CC[gBattleStruct->field_97 - 1]; + case 3: + return gUnknown_84791E8[gBattleStruct->field_97 - 1]; + } +} + +void InitPokedudePartyAndOpponent(void) +{ + s32 i, j; + struct Pokemon *mon; + s32 myIdx = 0; + s32 opIdx = 0; + const struct PokedudeBattlePartyInfo *data; + + gBattleTypeFlags = BATTLE_TYPE_POKEDUDE; + ZeroPlayerPartyMons(); + ZeroEnemyPartyMons(); + data = sPokedudeBattlePartyPointers[gSpecialVar_0x8004]; + i = 0; + do + { + if (data[i].side == B_SIDE_PLAYER) + mon = &gPlayerParty[myIdx++]; + else + mon = &gEnemyParty[opIdx++]; + CreateMonWithGenderNatureLetter(mon, data[i].species, data[i].level, 0, data[i].gender, data[i].nature, 0); + for (j = 0; j < 4; ++j) + SetMonMoveSlot(mon, data[i].moves[j], j); + } while (data[++i].side != 0xFF); +} diff --git a/src/battle_controllers.c b/src/battle_controllers.c index f3530fc4b..6fb090307 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -85,9 +85,9 @@ static void InitSinglePlayerBtlControllers(void) gBattleMainFunc = BeginBattleIntro; if (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE) { - gBattlerControllerFuncs[0] = SetControllerToPokeDude; + gBattlerControllerFuncs[0] = SetControllerToPokedude; gBattlerPositions[0] = B_POSITION_PLAYER_LEFT; - gBattlerControllerFuncs[1] = SetControllerToPokeDude; + gBattlerControllerFuncs[1] = SetControllerToPokedude; gBattlerPositions[1] = B_POSITION_OPPONENT_LEFT; gBattlersCount = 2; } @@ -110,13 +110,13 @@ static void InitSinglePlayerBtlControllers(void) gBattleMainFunc = BeginBattleIntro; if (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE) { - gBattlerControllerFuncs[0] = SetControllerToPokeDude; + gBattlerControllerFuncs[0] = SetControllerToPokedude; gBattlerPositions[0] = B_POSITION_PLAYER_LEFT; - gBattlerControllerFuncs[1] = SetControllerToPokeDude; + gBattlerControllerFuncs[1] = SetControllerToPokedude; gBattlerPositions[1] = B_POSITION_OPPONENT_LEFT; - gBattlerControllerFuncs[2] = SetControllerToPokeDude; + gBattlerControllerFuncs[2] = SetControllerToPokedude; gBattlerPositions[2] = B_POSITION_PLAYER_RIGHT; - gBattlerControllerFuncs[3] = SetControllerToPokeDude; + gBattlerControllerFuncs[3] = SetControllerToPokedude; gBattlerPositions[3] = B_POSITION_OPPONENT_RIGHT; gBattlersCount = MAX_BATTLERS_COUNT; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 181f59b09..c5c8e89a4 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7064,7 +7064,7 @@ static void atk8F_forcerandomswitch(void) u8 valid; u8 val; - if (!GetBattlerSide(gBattlerTarget)) + if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER) party = gPlayerParty; else party = gEnemyParty; diff --git a/src/battle_setup.c b/src/battle_setup.c index b9da39ddb..9fef6a8a5 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -13,7 +13,6 @@ #include "strings.h" #include "string_util.h" #include "event_data.h" -#include "unk_8159F40.h" #include "map_obj_80688E4.h" #include "metatile_behavior.h" #include "event_scripts.h" @@ -28,6 +27,7 @@ #include "battle.h" #include "battle_setup.h" #include "battle_transition.h" +#include "battle_controllers.h" #include "constants/battle_setup.h" #include "constants/flags.h" #include "constants/items.h" @@ -172,7 +172,7 @@ static const union AffineAnimCmd gUnknown_83E733C[] = AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 18), AFFINEANIMCMD_LOOP(0), - AFFINEANIMCMD_FRAME(0xFFFB, 0xFFFB, 0, 8), + AFFINEANIMCMD_FRAME(-0x5, -0x5, 0, 8), AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 8), AFFINEANIMCMD_LOOP(5), AFFINEANIMCMD_END, @@ -202,7 +202,7 @@ static void sub_80B3FAC(struct Sprite *sprite) gBattleAnimArgs[2] = -gBattleAnimArgs[2]; gBattleAnimArgs[0] = -gBattleAnimArgs[0]; } - else if (!GetBattlerSide(gBattleAnimTarget)) + else if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) { StartSpriteAffineAnim(sprite, 1); gBattleAnimArgs[1] = -gBattleAnimArgs[1]; @@ -226,7 +226,7 @@ static void sub_80B407C(struct Sprite *sprite) gBattleAnimArgs[0] = -gBattleAnimArgs[0]; StartSpriteAffineAnim(sprite, 2); } - else if (!GetBattlerSide(gBattleAnimTarget)) + else if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) { gBattleAnimArgs[1] = -gBattleAnimArgs[1]; gBattleAnimArgs[0] = -gBattleAnimArgs[0]; @@ -283,12 +283,12 @@ static void sub_80B41C0(struct Sprite *sprite) static void sub_80B41F8(struct Sprite *sprite) { SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); - if (GetBattlerSide(gBattleAnimAttacker)) + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) sprite->pos1.x -= gBattleAnimArgs[0]; else sprite->pos1.x += gBattleAnimArgs[0]; sprite->pos1.y += gBattleAnimArgs[1]; - if (!GetBattlerSide(gBattleAnimTarget)) + if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) sprite->pos1.y += 8; sprite->callback = sub_80B4274; } @@ -356,7 +356,7 @@ static void AnimTranslateStinger(struct Sprite *sprite) { gBattleAnimArgs[2] = -gBattleAnimArgs[2]; } - else if (GetBattlerSide(gBattleAnimAttacker)) + else if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) { gBattleAnimArgs[2] = -gBattleAnimArgs[2]; gBattleAnimArgs[1] = -gBattleAnimArgs[1]; @@ -399,7 +399,7 @@ static void AnimTranslateStinger(struct Sprite *sprite) static void AnimMissileArc(struct Sprite *sprite) { InitSpritePosToAnimAttacker(sprite, 1); - if (GetBattlerSide(gBattleAnimAttacker)) + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) gBattleAnimArgs[2] = -gBattleAnimArgs[2]; sprite->data[0] = gBattleAnimArgs[4]; sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2) + gBattleAnimArgs[2]; diff --git a/src/electric.c b/src/electric.c new file mode 100644 index 000000000..025eac48b --- /dev/null +++ b/src/electric.c @@ -0,0 +1,1272 @@ +#include "global.h" +#include "battle_anim.h" +#include "trig.h" +#include "sound.h" +#include "constants/songs.h" + +static void sub_80ADBEC(struct Sprite *sprite); +static void sub_80ADC58(struct Sprite *sprite); +static void sub_80ADCB8(struct Sprite *sprite); +static void sub_80ADD4C(struct Sprite *sprite); +static void sub_80ADEB0(struct Sprite *sprite); +static void sub_80AE000(struct Sprite *sprite); +static void sub_80AE06C(struct Sprite *sprite); +static void sub_80AE1A0(struct Sprite *sprite); +static void sub_80AE420(struct Sprite *sprite); +static void sub_80AE470(struct Sprite *sprite); +static void sub_80AE71C(struct Sprite *sprite); +static void sub_80AE774(struct Sprite *sprite); +static void sub_80AE7DC(struct Sprite *sprite); +static void sub_80AEC34(struct Sprite *sprite); +static void sub_80AEC80(struct Sprite *sprite); +static void sub_80AEF60(struct Sprite *sprite); +static void sub_80ADC3C(struct Sprite *sprite); +static void sub_80ADC9C(struct Sprite *sprite); +static void sub_80ADF38(struct Sprite *sprite); +static void sub_80AE130(struct Sprite *sprite); +static void sub_80AE278(u8 taskId); +static void sub_80AE4F4(struct Sprite *sprite); +static void sub_80AE5BC(u8 taskId); +static void sub_80AE704(struct Sprite *sprite); +static void sub_80AE83C(struct Sprite *sprite); +static bool8 sub_80AEB98(struct Task *task, u8 taskId); +static bool8 sub_80AEE74(struct Task *task, u8 taskId); +static bool8 sub_80AF058(struct Task *task, u8 taskId); +static void sub_80AF0C8(struct Sprite *sprite); + +static const union AnimCmd gUnknown_83E5F1C[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(32, 8), + ANIMCMD_FRAME(48, 5), + ANIMCMD_FRAME(64, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E5F34[] = +{ + gUnknown_83E5F1C, +}; + +const struct SpriteTemplate gUnknown_83E5F38 = +{ + .tileTag = ANIM_TAG_LIGHTNING, + .paletteTag = ANIM_TAG_LIGHTNING, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5F34, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80ADBEC, +}; + +static const union AffineAnimCmd gUnknown_83E5F50[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 20), + AFFINEANIMCMD_FRAME(0x0, 0x0, -16, 60), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E5F70[] = +{ + gUnknown_83E5F50, +}; + +const struct SpriteTemplate gUnknown_83E5F74 = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83ACA38, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E5F70, + .callback = sub_80ADC58, +}; + +static const union AnimCmd gUnknown_83E5F8C[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(32, 5), + ANIMCMD_FRAME(48, 5), + ANIMCMD_FRAME(64, 5), + ANIMCMD_FRAME(80, 5), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E5FA8[] = +{ + gUnknown_83E5F8C, +}; + +const struct SpriteTemplate gUnknown_83E5FAC = +{ + .tileTag = ANIM_TAG_SHOCK, + .paletteTag = ANIM_TAG_SHOCK, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5FA8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80ADCB8, +}; + +const struct SpriteTemplate gUnknown_83E5FC4 = +{ + .tileTag = ANIM_TAG_SPARK_2, + .paletteTag = ANIM_TAG_SPARK_2, + .oam = &gOamData_83ACA30, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80ADD4C, +}; + +const struct SpriteTemplate gUnknown_83E5FDC = +{ + .tileTag = ANIM_TAG_BLACK_BALL_2, + .paletteTag = ANIM_TAG_BLACK_BALL_2, + .oam = &gOamData_83AC9D0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = TranslateAnimSpriteToTargetMonLocation, +}; + +static const union AffineAnimCmd gUnknown_83E5FF4[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 20, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const gUnknown_83E6004[] = +{ + gUnknown_83E5FF4, +}; + +const struct SpriteTemplate gUnknown_83E6008 = +{ + .tileTag = ANIM_TAG_SPARK_2, + .paletteTag = ANIM_TAG_SPARK_2, + .oam = &gOamData_83ACA30, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6004, + .callback = sub_80ADEB0, +}; + +static const union AnimCmd gUnknown_83E6020[] = +{ + ANIMCMD_FRAME(0, 6), + ANIMCMD_FRAME(16, 6), + ANIMCMD_FRAME(32, 6), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E6030[] = +{ + gUnknown_83E6020, +}; + +static const union AffineAnimCmd gUnknown_83E6034[] = +{ + AFFINEANIMCMD_FRAME(0xE8, 0xE8, 0, 0), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 0, 10), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 10), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const gUnknown_83E6054[] = +{ + gUnknown_83E6034, +}; + +const struct SpriteTemplate gUnknown_83E6058 = +{ + .tileTag = ANIM_TAG_SHOCK_3, + .paletteTag = ANIM_TAG_SHOCK_3, + .oam = &gOamData_83ACA38, + .anims = gUnknown_83E6030, + .images = NULL, + .affineAnims = gUnknown_83E6054, + .callback = sub_80AE000, +}; + +const struct SpriteTemplate gUnknown_83E6070 = +{ + .tileTag = ANIM_TAG_SPARK_2, + .paletteTag = ANIM_TAG_SPARK_2, + .oam = &gOamData_83ACA30, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6004, + .callback = sub_80AE06C, +}; + +const struct SpriteTemplate gElectricitySpriteTemplate = +{ + .tileTag = ANIM_TAG_SPARK_2, + .paletteTag = ANIM_TAG_SPARK_2, + .oam = &gOamData_83AC9D0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AE1A0, +}; + +static const struct SpriteTemplate gUnknown_83E60A0 = +{ + .tileTag = ANIM_TAG_SPARK, + .paletteTag = ANIM_TAG_SPARK, + .oam = &gOamData_83AC9C8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AE420, +}; + +const struct SpriteTemplate gUnknown_83E60B8 = +{ + .tileTag = ANIM_TAG_SPARK_H, + .paletteTag = ANIM_TAG_SPARK_H, + .oam = &gOamData_83AC9F8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AE470, +}; + +static const s8 gUnknown_83E60D0[][2] = +{ + { 58, -60}, + {-56, -36}, + { 8, -56}, + {-16, 56}, + { 58, -10}, + {-58, 10}, + { 48, -18}, + {-8, 56}, + { 16, -56}, + {-58, -42}, + { 58, 30}, + {-48, 40}, + { 12, -48}, + { 48, -12}, + {-56, 18}, + { 48, 48}, +}; + +static const union AnimCmd gUnknown_83E60F0[] = +{ + ANIMCMD_FRAME(3, 1), + ANIMCMD_FRAME(2, 1), + ANIMCMD_FRAME(1, 1), + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E6104[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(1, 5), + ANIMCMD_FRAME(2, 5), + ANIMCMD_FRAME(3, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E6118[] = +{ + gUnknown_83E60F0, + gUnknown_83E6104, +}; + +static const struct SpriteTemplate gUnknown_83E6120 = +{ + .tileTag = ANIM_TAG_ELECTRIC_ORBS, + .paletteTag = ANIM_TAG_ELECTRIC_ORBS, + .oam = &gOamData_83AC9C8, + .anims = gUnknown_83E6118, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +static const union AffineAnimCmd gUnknown_83E6138[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 60), + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_LOOP(0), + AFFINEANIMCMD_FRAME(-0x4, -0x4, 0, 5), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 5), + AFFINEANIMCMD_LOOP(10), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E6178[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 30), + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(-0x4, -0x4, 0, 5), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 5), + AFFINEANIMCMD_JUMP(3), +}; + +static const union AffineAnimCmd gUnknown_83E61A8[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 30), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 0, 30), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E61C8[] = +{ + gUnknown_83E6138, + gUnknown_83E6178, + gUnknown_83E61A8, +}; + +const struct SpriteTemplate gUnknown_83E61D4 = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_83ACB60, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E61C8, + .callback = sub_80AE71C, +}; + +static const union AnimCmd gUnknown_83E61EC[] = +{ + ANIMCMD_FRAME(0, 3), + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(48, 3), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E6200[] = +{ + gUnknown_83E61EC, +}; + +const struct SpriteTemplate gUnknown_83E6204 = +{ + .tileTag = ANIM_TAG_ELECTRICITY, + .paletteTag = ANIM_TAG_ELECTRICITY, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E6200, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AE774, +}; + +const struct SpriteTemplate gUnknown_83E621C = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_83ACB60, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E61C8, + .callback = sub_80AE7DC, +}; + +static const union AnimCmd gUnknown_83E6234[] = +{ + ANIMCMD_FRAME(0, 3), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E623C[] = +{ + ANIMCMD_FRAME(2, 3), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E6244[] = +{ + ANIMCMD_FRAME(4, 3), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E624C[] = +{ + ANIMCMD_FRAME(6, 3), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E6254[] = +{ + gUnknown_83E6234, + gUnknown_83E623C, + gUnknown_83E6244, + gUnknown_83E624C, +}; + +static const union AffineAnimCmd gUnknown_83E6264[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E6274[] = +{ + gUnknown_83E6264, +}; + +static const struct SpriteTemplate gUnknown_83E6278 = +{ + .tileTag = ANIM_TAG_SPARK, + .paletteTag = ANIM_TAG_SPARK, + .oam = &gOamData_83ACAC8, + .anims = gUnknown_83E6254, + .images = NULL, + .affineAnims = gUnknown_83E6274, + .callback = sub_80AEC34, +}; + +const struct SpriteTemplate gUnknown_83E6290 = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_83ACB60, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E61C8, + .callback = sub_80AEC80, +}; + +static const struct SpriteTemplate gUnknown_83E62A8 = +{ + .tileTag = ANIM_TAG_SPARK, + .paletteTag = ANIM_TAG_SPARK, + .oam = &gOamData_83AC9C8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AEF60, +}; + +static void sub_80ADBEC(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->callback = sub_80ADC3C; +} + +static void sub_80ADC3C(struct Sprite *sprite) +{ + if (sprite->animEnded) + DestroyAnimSprite(sprite); +} + +static void sub_80ADC58(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->callback = sub_80ADC9C; +} + +static void sub_80ADC9C(struct Sprite *sprite) +{ + if (sprite->affineAnimEnded) + DestroySpriteAndMatrix(sprite); +} + +static void sub_80ADCB8(struct Sprite *sprite) +{ + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + sprite->pos1.y -= gBattleAnimArgs[1]; + } + else + { + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + } + sprite->data[0] = 0; + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[2] = gBattleAnimArgs[3]; + sprite->data[3] = gBattleAnimArgs[4]; + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = TranslateSpriteInCircleOverDuration; +} + +static void sub_80ADD4C(struct Sprite *sprite) +{ + u8 battler; + u32 matrixNum; + s16 sineVal; + + switch (gBattleAnimArgs[4]) + { + case 0: + battler = gBattleAnimAttacker; + break; + case 1: + default: + battler = gBattleAnimTarget; + break; + case 2: + if (!IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + battler = gBattleAnimAttacker; + else + battler = BATTLE_PARTNER(gBattleAnimAttacker); + break; + case 3: + if (IsBattlerSpriteVisible(BATTLE_PARTNER(gBattleAnimAttacker))) + battler = BATTLE_PARTNER(gBattleAnimTarget); + else + battler = gBattleAnimTarget; + break; + } + if (gBattleAnimArgs[5] == 0) + { + sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X); + sprite->pos1.y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y_PIC_OFFSET); + } + sprite->pos2.x = (gSineTable[gBattleAnimArgs[0]] * gBattleAnimArgs[1]) >> 8; + sprite->pos2.y = (gSineTable[gBattleAnimArgs[0] + 64] * gBattleAnimArgs[1]) >> 8; + if (gBattleAnimArgs[6] & 1) + sprite->oam.priority = GetBattlerSpriteBGPriority(battler) + 1; + matrixNum = sprite->oam.matrixNum; + sineVal = gSineTable[gBattleAnimArgs[2]]; + gOamMatrices[matrixNum].a = gOamMatrices[matrixNum].d = gSineTable[gBattleAnimArgs[2] + 64]; + gOamMatrices[matrixNum].b = sineVal; + gOamMatrices[matrixNum].c = -sineVal; + sprite->data[0] = gBattleAnimArgs[3]; + sprite->callback = sub_80B1D3C; +} + +static void sub_80ADEB0(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + sprite->data[0] = gBattleAnimArgs[3]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + InitAnimLinearTranslation(sprite); + sprite->data[5] = gBattleAnimArgs[2]; + sprite->data[6] = gBattleAnimArgs[5]; + sprite->data[7] = gBattleAnimArgs[4]; + sprite->oam.tileNum += gBattleAnimArgs[6] * 4; + sprite->callback = sub_80ADF38; + sprite->callback(sprite); +} + +static void sub_80ADF38(struct Sprite *sprite) +{ + if (!AnimTranslateLinear(sprite)) + { + sprite->pos2.x += Sin(sprite->data[7], sprite->data[5]); + sprite->pos2.y += Cos(sprite->data[7], sprite->data[5]); + sprite->data[7] = (sprite->data[7] + sprite->data[6]) & 0xFF; + if(!(sprite->data[7] % 3)) + sprite->invisible ^= 1; + } + else + { + DestroyAnimSprite(sprite); + } +} + +static void sub_80ADFB0(struct Sprite *sprite) +{ + if (--sprite->data[5] == -1) + { + sprite->invisible ^= 1; + sprite->data[5] = sprite->data[4]; + } + if (sprite->data[3]-- <= 0) + DestroyAnimSprite(sprite); +} + +static void sub_80AE000(struct Sprite *sprite) +{ + if (IsContest() || GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[1]; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[2]; + sprite->data[3] = gBattleAnimArgs[0]; + sprite->data[4] = gBattleAnimArgs[3]; + sprite->data[5] = gBattleAnimArgs[3]; + sprite->callback = sub_80ADFB0; +} + +static void sub_80AE06C(struct Sprite *sprite) +{ + u8 battler; + + sprite->data[0] = gBattleAnimArgs[3]; + if (gBattleAnimArgs[7] & 0x8000) + battler = gBattleAnimTarget; + else + battler = gBattleAnimAttacker; + if (IsContest() || GetBattlerSide(battler) == B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + sprite->pos1.x = GetBattlerSpriteCoord(battler, BATTLER_COORD_X_2) + gBattleAnimArgs[0]; + sprite->pos1.y = GetBattlerSpriteCoord(battler, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[1]; + sprite->data[4] = gBattleAnimArgs[7] & 0x7FFF; + sprite->data[5] = gBattleAnimArgs[2]; + sprite->data[6] = gBattleAnimArgs[5]; + sprite->data[7] = gBattleAnimArgs[4]; + sprite->oam.tileNum += gBattleAnimArgs[6] * 4; + sprite->callback = sub_80AE130; + sprite->callback(sprite); +} + +static void sub_80AE130(struct Sprite *sprite) +{ + sprite->pos2.x = Sin(sprite->data[7], sprite->data[5]); + sprite->pos2.y = Cos(sprite->data[7], sprite->data[5]); + sprite->data[7] = (sprite->data[7] + sprite->data[6]) & 0xFF; + if (sprite->data[7] % sprite->data[4] == 0) + sprite->invisible ^= 1; + if (sprite->data[0]-- <= 0) + DestroyAnimSprite(sprite); +} + +static void sub_80AE1A0(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, FALSE); + sprite->oam.tileNum += gBattleAnimArgs[3] * 4; + if (gBattleAnimArgs[3] == 1) + sprite->oam.matrixNum = ST_OAM_HFLIP; + else if (gBattleAnimArgs[3] == 2) + sprite->oam.matrixNum = ST_OAM_VFLIP; + sprite->data[0] = gBattleAnimArgs[2]; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +void sub_80AE220(u8 taskId) +{ + gTasks[taskId].data[0] = GetBattlerSpriteCoord(gBattleAnimTarget, 0) + gBattleAnimArgs[0]; + gTasks[taskId].data[1] = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + gBattleAnimArgs[1]; + gTasks[taskId].data[2] = gBattleAnimArgs[2]; + gTasks[taskId].func = sub_80AE278; +} + +static void sub_80AE278(u8 taskId) +{ + u16 r8; + u16 r2; + s16 r12; + u8 spriteId = 0; + u8 r7 = 0; + u8 sp = gTasks[taskId].data[2]; + s16 x = gTasks[taskId].data[0]; + s16 y = gTasks[taskId].data[1]; + + if (!gTasks[taskId].data[2]) + { + r8 = 0; + r2 = 1; + r12 = 16; + } + else + { + r12 = 16; + r8 = 8; + r2 = 4; + } + switch (gTasks[taskId].data[10]) + { + case 0: + r12 *= 1; + spriteId = CreateSprite(&gUnknown_83E60A0, x, y + r12, 2); + ++r7; + break; + case 2: + r12 *= 2; + r8 += r2; + spriteId = CreateSprite(&gUnknown_83E60A0, x, y + r12, 2); + ++r7; + break; + case 4: + r12 *= 3; + r8 += r2 * 2; + spriteId = CreateSprite(&gUnknown_83E60A0, x, y + r12, 2); + ++r7; + break; + case 6: + r12 *= 4; + r8 += r2 * 3; + spriteId = CreateSprite(&gUnknown_83E60A0, x, y + r12, 2); + ++r7; + break; + case 8: + r12 *= 5; + spriteId = CreateSprite(&gUnknown_83E60A0, x, y + r12, 2); + ++r7; + break; + case 10: + DestroyAnimVisualTask(taskId); + return; + } + if (r7) + { + gSprites[spriteId].oam.tileNum += r8; + gSprites[spriteId].data[0] = sp; + gSprites[spriteId].callback(&gSprites[spriteId]); + } + ++gTasks[taskId].data[10]; +} + +static void sub_80AE420(struct Sprite *sprite) +{ + if (!sprite->data[0]) + { + sprite->oam.shape = ST_OAM_V_RECTANGLE; + sprite->oam.size = ST_OAM_SIZE_0; + } + else + { + sprite->oam.shape = ST_OAM_SQUARE; + sprite->oam.size = ST_OAM_SIZE_1; + } + if (++sprite->data[1] == 15) + DestroySprite(sprite); +} + +static void sub_80AE470(struct Sprite *sprite) +{ + u8 spriteId; + + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + spriteId = CreateSprite(&gUnknown_83E60B8, sprite->pos1.x + 32, sprite->pos1.y, sprite->subpriority); + gSprites[spriteId].oam.tileNum += 8; + ++gAnimVisualTaskCount; + gSprites[spriteId].callback = sub_80AE4F4; + sprite->callback = sub_80AE4F4; +} + +static void sub_80AE4F4(struct Sprite *sprite) +{ + if (++sprite->data[0] == 3) + { + sprite->data[0] = 0; + sprite->invisible ^= 1; + } + if (++sprite->data[1] == 51) + DestroyAnimSprite(sprite); +} + +void sub_80AE540(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (!gBattleAnimArgs[0]) + { + task->data[14] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + task->data[15] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + } + else + { + task->data[14] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + task->data[15] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + task->data[6] = gBattleAnimArgs[1]; + task->data[7] = 0; + task->data[8] = 0; + task->data[9] = 0; + task->data[10] = 0; + task->data[11] = gBattleAnimArgs[3]; + task->data[12] = 0; + task->data[13] = gBattleAnimArgs[2]; + task->func = sub_80AE5BC; +} + +static void sub_80AE5BC(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (task->data[6]) + { + if (++task->data[12] > task->data[13]) + { + u8 spriteId; + + task->data[12] = 0; + spriteId = CreateSprite(&gUnknown_83E6120, task->data[14], task->data[15], 2); + if (spriteId != MAX_SPRITES) + { + struct Sprite *sprite = &gSprites[spriteId]; + + sprite->pos1.x += gUnknown_83E60D0[task->data[9]][0]; + sprite->pos1.y += gUnknown_83E60D0[task->data[9]][1]; + sprite->data[0] = 40 - task->data[8] * 5; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = task->data[14]; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = task->data[15]; + sprite->data[5] = taskId; + InitAnimLinearTranslation(sprite); + StoreSpriteCallbackInData6(sprite, sub_80AE704); + sprite->callback = RunStoredCallbackWhenAnimEnds; + if (++task->data[9] > 15) + task->data[9] = 0; + if (++task->data[10] >= task->data[11]) + { + task->data[10] = 0; + if (task->data[8] <= 5) + ++task->data[8]; + } + ++task->data[7]; + --task->data[6]; + } + } + } + else if(task->data[7] == 0) + { + DestroyAnimVisualTask(taskId); + } +} + +static void sub_80AE6D0(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + { + --gTasks[sprite->data[5]].data[7]; + DestroySprite(sprite); + } +} + +static void sub_80AE704(struct Sprite *sprite) +{ + StartSpriteAnim(sprite, 1); + sprite->callback = sub_80AE6D0; +} + +static void sub_80AE71C(struct Sprite *sprite) +{ + if (!gBattleAnimArgs[0]) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; +} + +static void sub_80AE774(struct Sprite *sprite) +{ + if (!gBattleAnimArgs[0]) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + sprite->pos2.x = gBattleAnimArgs[1]; + sprite->pos2.y = gBattleAnimArgs[2]; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = RunStoredCallbackWhenAnimEnds; +} + +static void sub_80AE7DC(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, 1); + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + sprite->data[6] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + sprite->data[7] = 16; + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + sprite->data[7] *= -1; + sprite->callback = sub_80AE83C; +} + +static void sub_80AE83C(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (++sprite->data[1] > 40) + ++sprite->data[0]; + break; + case 1: + sprite->pos1.x += sprite->data[7]; + gSprites[sprite->data[6]].pos2.x += sprite->data[7]; + if ((u16)(sprite->pos1.x + 80) > 400) + DestroySpriteAndMatrix(sprite); + break; + } +} + +void sub_80AE8A0(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + task->data[14] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + { + task->data[14] = -32; + task->data[13] = 2; + } + else + { + task->data[14] = 32; + task->data[13] = -2; + } + gSprites[task->data[15]].pos2.x = task->data[14]; + ++task->data[0]; + break; + case 1: + if (++task->data[1] > 1) + { + task->data[1] = 0; + gSprites[task->data[15]].invisible ^= 1; + + if (task->data[14]) + { + task->data[14] += task->data[13]; + gSprites[task->data[15]].pos2.x = task->data[14]; + } + else + { + ++task->data[0]; + } + } + break; + case 2: + if (++task->data[1] > 1) + { + task->data[1] = 0; + gSprites[task->data[15]].invisible ^= 1; + if (++task->data[2] == 8) + ++task->data[0]; + } + break; + case 3: + gSprites[task->data[15]].invisible = FALSE; + DestroyAnimVisualTask(taskId); + break; + } +} + +void sub_80AEA10(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch(task->data[0]) + { + case 0: + task->data[1] = GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER ? 1 : -1; + switch (gBattleAnimArgs[0]) + { + case 0: + task->data[3] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + task->data[5] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + task->data[4] = (task->data[1] * 128) + 120; + break; + case 4: + task->data[3] = 120 - (task->data[1] * 128); + task->data[5] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + task->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) - (task->data[1] * 32); + break; + default: + if ((gBattleAnimArgs[0] & 1) != 0) + { + task->data[3] = 256; + task->data[4] = -16; + } + else + { + task->data[3] = -16; + task->data[4] = 256; + } + if (task->data[1] == 1) + { + task->data[5] = 80 - gBattleAnimArgs[0] * 10; + } + else + { + u16 temp; + + task->data[5] = gBattleAnimArgs[0] * 10 + 40; + temp = task->data[3]; + task->data[3] = task->data[4]; + task->data[4] = temp; + } + } + if (task->data[3] < task->data[4]) + { + task->data[1] = 1; + task->data[6] = 0; + } + else + { + task->data[1] = -1; + task->data[6] = 3; + } + ++task->data[0]; + break; + case 1: + if (++task->data[2] > 0) + { + task->data[2] = 0; + if (sub_80AEB98(task, taskId) || sub_80AEB98(task, taskId)) + ++task->data[0]; + } + break; + case 2: + if (task->data[7] == 0) + DestroyAnimVisualTask(taskId); + break; + } +} + +static bool8 sub_80AEB98(struct Task *task, u8 taskId) +{ + u8 spriteId = CreateSprite(&gUnknown_83E6278, task->data[3], task->data[5], 35); + + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].data[6] = taskId; + gSprites[spriteId].data[7] = 7; + ++task->data[7]; + } + task->data[6] += task->data[1]; + if (task->data[6] < 0) + task->data[6] = 3; + if (task->data[6] > 3) + task->data[6] = 0; + task->data[3] += task->data[1] * 16; + if ((task->data[1] == 1 && task->data[3] >= task->data[4]) + || (task->data[1] == -1 && task->data[3] <= task->data[4])) + return TRUE; + else + return FALSE; +} + +static void sub_80AEC34(struct Sprite *sprite) +{ + if (++sprite->data[0] > 12) + { + --gTasks[sprite->data[6]].data[sprite->data[7]]; + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } +} + +static void sub_80AEC80(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + StartSpriteAffineAnim(sprite, 2); + ++sprite->data[0]; + break; + case 1: + if (sprite->affineAnimEnded) + DestroySpriteAndMatrix(sprite); + break; + } +} + +void sub_80AECE0(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[6] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + task->data[7] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + task->data[8] = 4; + task->data[10] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + task->data[9] = (task->data[10] - task->data[6]) / 5; + task->data[4] = 7; + task->data[5] = -1; + task->data[11] = 12; + task->data[12] = BattleAnimAdjustPanning(task->data[11] - 76); + task->data[13] = BattleAnimAdjustPanning(SOUND_PAN_TARGET); + task->data[14] = task->data[12]; + task->data[15] = (task->data[13] - task->data[12]) / 3; + ++task->data[0]; + break; + case 1: + if (++task->data[1] > 0) + { + task->data[1] = 0; + if (sub_80AEE74(task, taskId)) + { + if (task->data[2] == 5) + task->data[0] = 3; + else + ++task->data[0]; + } + } + if (task->data[11]) + --task->data[11]; + break; + case 2: + if (task->data[11]) + --task->data[11]; + if (++task->data[1] > 4) + { + task->data[1] = 0; + if (task->data[2] & 1) + { + task->data[7] = 4; + task->data[8] = 68; + task->data[4] = 0; + task->data[5] = 1; + } + else + { + task->data[7] = 68; + task->data[8] = 4; + task->data[4] = 7; + task->data[5] = -1; + } + if (task->data[11]) + task->data[0] = 4; + else + task->data[0] = 1; + } + break; + case 3: + if (task->data[3] == 0) + DestroyAnimVisualTask(taskId); + break; + case 4: + if (task->data[11]) + --task->data[11]; + else + task->data[0] = 1; + break; + } +} + +static bool8 sub_80AEE74(struct Task *task, u8 taskId) +{ + u8 spriteId = CreateSprite(&gUnknown_83E62A8, task->data[6], task->data[7], 35); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].oam.tileNum += task->data[4]; + task->data[4] += task->data[5]; + if (task->data[4] < 0) + task->data[4] = 7; + if (task->data[4] > 7) + task->data[4] = 0; + gSprites[spriteId].data[6] = taskId; + gSprites[spriteId].data[7] = 3; + ++task->data[3]; + } + if (task->data[4] == 0 && task->data[5] > 0) + { + task->data[14] += task->data[15]; + PlaySE12WithPanning(SE_W085, task->data[14]); + } + if ((task->data[5] < 0 && task->data[7] <= task->data[8]) + || (task->data[5] > 0 && task->data[7] >= task->data[8])) + { + ++task->data[2]; + task->data[6] += task->data[9]; + return TRUE; + } + else + { + task->data[7] += task->data[5] * 8; + return FALSE; + } +} + +static void sub_80AEF60(struct Sprite *sprite) +{ + if (++sprite->data[0] > 12) + { + --gTasks[sprite->data[6]].data[sprite->data[7]]; + DestroySprite(sprite); + } +} + +void sub_80AEFA0(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[15] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + 32; + task->data[14] = task->data[15]; + while (task->data[14] > 16) + task->data[14] -= 32; + task->data[13] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + task->data[12] = GetBattlerSpriteSubpriority(gBattleAnimTarget) - 2; + ++task->data[0]; + break; + case 1: + if (++task->data[1] > 1) + { + task->data[1] = 0; + if (sub_80AF058(task, taskId)) + ++task->data[0]; + } + break; + case 2: + if (task->data[10] == 0) + DestroyAnimVisualTask(taskId); + break; + } +} + +static bool8 sub_80AF058(struct Task *task, u8 taskId) +{ + u8 spriteId = CreateSprite(&gUnknown_83E5F38, task->data[13], task->data[14], task->data[12]); + + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].callback = sub_80AF0C8; + gSprites[spriteId].data[6] = taskId; + gSprites[spriteId].data[7] = 10; + ++task->data[10]; + } + if (task->data[14] >= task->data[15]) + return TRUE; + task->data[14] += 32; + return FALSE; +} + +static void sub_80AF0C8(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + --gTasks[sprite->data[6]].data[sprite->data[7]]; + DestroySprite(sprite); + } +} diff --git a/src/fighting.c b/src/fighting.c new file mode 100644 index 000000000..496f752ef --- /dev/null +++ b/src/fighting.c @@ -0,0 +1,971 @@ +#include "global.h" +#include "battle_anim.h" +#include "gpu_regs.h" +#include "random.h" +#include "task.h" +#include "trig.h" + +static void unc_080B08A0(struct Sprite *sprite); +static void sub_80B08DC(struct Sprite *sprite); +static void sub_80B0928(struct Sprite *sprite); +static void AnimBasicFistOrFoot(struct Sprite *sprite); +static void sub_80B09A4(struct Sprite *sprite); +static void sub_80B0B80(struct Sprite *sprite); +static void sub_80B0C28(struct Sprite *sprite); +static void AnimSpinningKickOrPunch(struct Sprite *sprite); +static void AnimStompFoot(struct Sprite *sprite); +static void sub_80B0DF0(struct Sprite *sprite); +static void sub_80B0E80(struct Sprite *sprite); +static void sub_80B0F68(struct Sprite *sprite); +static void sub_80B107C(struct Sprite *sprite); +static void sub_80B1188(struct Sprite *sprite); +static void sub_80B12E8(struct Sprite *sprite); +static void sub_80B13F8(struct Sprite *sprite); +static void sub_80B1484(struct Sprite *sprite); +static void sub_80B14F0(struct Sprite *sprite); +static void sub_80B0B2C(struct Sprite *sprite); +static void sub_80B0BD8(struct Sprite *sprite); +static void sub_80B0CB4(struct Sprite *sprite); +static void AnimSpinningKickOrPunchFinish(struct Sprite *sprite); +static void AnimStompFootStep(struct Sprite *sprite); +static void AnimStompFootEnd(struct Sprite *sprite); +static void sub_80B0EF0(struct Sprite *sprite); +static void sub_80B1050(struct Sprite *sprite); +static void sub_80B111C(struct Sprite *sprite); +static void sub_80B11E4(struct Sprite *sprite); +static void sub_80B12A4(struct Sprite *sprite); + +const struct SpriteTemplate gUnknown_83E668C = +{ + .tileTag = ANIM_TAG_HUMANOID_FOOT, + .paletteTag = ANIM_TAG_HUMANOID_FOOT, + .oam = &gOamData_83AC9D8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = unc_080B08A0, +}; + +static const union AnimCmd gUnknown_83E66A4[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E66AC[] = +{ + ANIMCMD_FRAME(16, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E66B4[] = +{ + ANIMCMD_FRAME(32, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E66BC[] = +{ + ANIMCMD_FRAME(48, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E66C4[] = +{ + ANIMCMD_FRAME(48, 1, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E66CC[] = +{ + gUnknown_83E66A4, +}; + +static const union AnimCmd *const gUnknown_83E66D0[] = +{ + gUnknown_83E66AC, + gUnknown_83E66B4, +}; + +static const union AnimCmd *const gUnknown_83E66D8[] = +{ + gUnknown_83E66BC, + gUnknown_83E66C4, +}; + +const struct SpriteTemplate gUnknown_83E66E0 = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E66CC, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B08DC, +}; + +const struct SpriteTemplate gUnknown_83E66F8 = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E66CC, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B0928, +}; + +const struct SpriteTemplate gFistFootSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E66CC, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimBasicFistOrFoot, +}; + +const struct SpriteTemplate gUnknown_83E6728 = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E66CC, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B09A4, +}; + +const struct SpriteTemplate gUnknown_83E6740 = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E66D8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B0B80, +}; + +const struct SpriteTemplate gUnknown_83E6758 = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E66D0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B0C28, +}; + +static const union AffineAnimCmd gUnknown_83E6770[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 20, 1), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const gUnknown_83E6788[] = +{ + gUnknown_83E6770, +}; + +const struct SpriteTemplate gUnknown_83E678C = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83ACA98, + .anims = gUnknown_83E66CC, + .images = NULL, + .affineAnims = gUnknown_83E6788, + .callback = AnimSpinningKickOrPunch, +}; + +static const union AffineAnimCmd gUnknown_83E67A4[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(-0x4, -0x4, 20, 1), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const gUnknown_83E67BC[] = +{ + gUnknown_83E67A4, +}; + +const struct SpriteTemplate gMegaPunchKickSpriteTemplate = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83ACA98, + .anims = gUnknown_83E66CC, + .images = NULL, + .affineAnims = gUnknown_83E67BC, + .callback = AnimSpinningKickOrPunch, +}; + +const struct SpriteTemplate gUnknown_83E67D8 = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E66D0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimStompFoot, +}; + +const struct SpriteTemplate gUnknown_83E67F0 = +{ + .tileTag = ANIM_TAG_DUCK, + .paletteTag = ANIM_TAG_DUCK, + .oam = &gOamData_83AC9D0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B0DF0, +}; + +const struct SpriteTemplate gUnknown_83E6808 = +{ + .tileTag = ANIM_TAG_BLUE_LIGHT_WALL, + .paletteTag = ANIM_TAG_BLUE_LIGHT_WALL, + .oam = &gOamData_83ACB00, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B0E80, +}; + +const struct SpriteTemplate gUnknown_83E6820 = +{ + .tileTag = ANIM_TAG_TORN_METAL, + .paletteTag = ANIM_TAG_TORN_METAL, + .oam = &gOamData_83AC9D8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B0F68, +}; + +static const union AffineAnimCmd gUnknown_83E6838[] = +{ + AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0), + AFFINEANIMCMD_FRAME(0x4, 0x4, 0, 64), + AFFINEANIMCMD_FRAME(-0x6, -0x6, 0, 8), + AFFINEANIMCMD_FRAME(0x6, 0x6, 0, 8), + AFFINEANIMCMD_JUMP(2), +}; + +static const union AffineAnimCmd *const gUnknown_83E6860[] = +{ + gUnknown_83E6838, +}; + +const struct SpriteTemplate gUnknown_83E6864 = +{ + .tileTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .paletteTag = ANIM_TAG_CIRCLE_OF_LIGHT, + .oam = &gOamData_83ACBC0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6860, + .callback = sub_80B107C, +}; + +const struct SpriteTemplate gUnknown_83E687C = +{ + .tileTag = ANIM_TAG_FLAT_ROCK, + .paletteTag = ANIM_TAG_FLAT_ROCK, + .oam = &gOamData_83AC9D0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B1188, +}; + +const struct SpriteTemplate gUnknown_83E6894 = +{ + .tileTag = ANIM_TAG_METEOR, + .paletteTag = ANIM_TAG_METEOR, + .oam = &gOamData_83AC9E0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B12E8, +}; + +const struct SpriteTemplate gUnknown_83E68AC = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E66CC, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B13F8, +}; + +static const union AnimCmd gUnknown_83E68C4[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E68D4[] = +{ + ANIMCMD_FRAME(0, 4, .vFlip = TRUE), + ANIMCMD_FRAME(16, 4, .vFlip = TRUE), + ANIMCMD_FRAME(32, 4, .vFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E68E4[] = +{ + ANIMCMD_FRAME(0, 4, .hFlip = TRUE), + ANIMCMD_FRAME(16, 4, .hFlip = TRUE), + ANIMCMD_FRAME(32, 4, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E68F4[] = +{ + gUnknown_83E68C4, + gUnknown_83E68D4, + gUnknown_83E68E4, +}; + +const struct SpriteTemplate gUnknown_83E6900 = +{ + .tileTag = ANIM_TAG_PURPLE_SCRATCH, + .paletteTag = ANIM_TAG_PURPLE_SCRATCH, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E68F4, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B1484, +}; + +static const union AnimCmd gUnknown_83E6918[] = +{ + ANIMCMD_FRAME(0, 6), + ANIMCMD_FRAME(64, 6), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E6924[] = +{ + ANIMCMD_FRAME(0, 6, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_FRAME(64, 6, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E6930[] = +{ + ANIMCMD_FRAME(0, 6, .hFlip = TRUE), + ANIMCMD_FRAME(64, 6, .hFlip = TRUE), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E693C[] = +{ + gUnknown_83E6918, + gUnknown_83E6924, + gUnknown_83E6930, +}; + +const struct SpriteTemplate gUnknown_83E6948 = +{ + .tileTag = ANIM_TAG_PURPLE_SWIPE, + .paletteTag = ANIM_TAG_PURPLE_SWIPE, + .oam = &gOamData_83AC9E0, + .anims = gUnknown_83E693C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80B1484, +}; + +static const union AffineAnimCmd gUnknown_83E6960[] = +{ + AFFINEANIMCMD_FRAME(0x200, 0x200, 0, 0), + AFFINEANIMCMD_FRAME(-0x20, -0x20, 0, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E6978[] = +{ + gUnknown_83E6960, +}; + +const struct SpriteTemplate gUnknown_83E697C = +{ + .tileTag = ANIM_TAG_HANDS_AND_FEET, + .paletteTag = ANIM_TAG_HANDS_AND_FEET, + .oam = &gOamData_83ACA98, + .anims = gUnknown_83E66CC, + .images = NULL, + .affineAnims = gUnknown_83E6978, + .callback = sub_80B14F0, +}; + +static void unc_080B08A0(struct Sprite *sprite) +{ + SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]); + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = 15; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void sub_80B08DC(struct Sprite *sprite) +{ + if (gBattleAnimArgs[7] == 1 && GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + } + StartSpriteAnim(sprite, gBattleAnimArgs[6]); + gBattleAnimArgs[6] = 0; + AnimSnoreZ(sprite); +} + +static void sub_80B0928(struct Sprite *sprite) +{ + if (IsContest()) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + } + sub_80B08DC(sprite); +} + +// Displays a basic fist or foot sprite for a given duration. +// Used by many fighting moves (and elemental "punch" moves). +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: duration +// arg 3: ? (todo: related to initial pixel offsets) +// arg 4: anim num +static void AnimBasicFistOrFoot(struct Sprite *sprite) +{ + StartSpriteAnim(sprite, gBattleAnimArgs[4]); + if (gBattleAnimArgs[3] == 0) + InitSpritePosToAnimAttacker(sprite, 1); + else + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[2]; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void sub_80B09A4(struct Sprite *sprite) +{ + u8 battler; + s16 xMod, yMod; + s16 x, y; + + if (gBattleAnimArgs[0] == 0) + battler = gBattleAnimAttacker; + else + battler = gBattleAnimTarget; + + if (gBattleAnimArgs[2] < 0) + gBattleAnimArgs[2] = Random() % 5; + StartSpriteAnim(sprite, gBattleAnimArgs[2]); + sprite->pos1.x = GetBattlerSpriteCoord(battler, 2); + sprite->pos1.y = GetBattlerSpriteCoord(battler, 3); + xMod = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_WIDTH) / 2; + yMod = GetBattlerSpriteCoordAttr(battler, BATTLER_COORD_ATTR_HEIGHT) / 4; + x = Random() % xMod; + y = Random() % yMod; + if (Random() & 1) + x *= -1; + if (Random() & 1) + y *= -1; + if ((gBattlerPositions[battler] & BIT_SIDE) == B_SIDE_PLAYER) + y += 0xFFF0; + sprite->pos1.x += x; + sprite->pos1.y += y; + sprite->data[0] = gBattleAnimArgs[1]; + sprite->data[7] = CreateSprite(&gBasicHitSplatSpriteTemplate, sprite->pos1.x, sprite->pos1.y, sprite->subpriority + 1); + if (sprite->data[7] != 64) + { + StartSpriteAffineAnim(&gSprites[sprite->data[7]], 0); + gSprites[sprite->data[7]].callback = SpriteCallbackDummy; + } + sprite->callback = sub_80B0B2C; +} + +static void sub_80B0B2C(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + if (sprite->data[7] != 64) + { + FreeOamMatrix(gSprites[sprite->data[7]].oam.matrixNum); + DestroySprite(&gSprites[sprite->data[7]]); + } + DestroyAnimSprite(sprite); + } + else + { + --sprite->data[0]; + } +} + +static void sub_80B0B80(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[0] = 30; + if (gBattleAnimArgs[2] == 0) + { + sprite->data[2] = sprite->pos1.x - 20; + } + else + { + sprite->data[2] = sprite->pos1.x + 20; + sprite->hFlip = 1; + } + sprite->data[4] = sprite->pos1.y - 20; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, sub_80B0BD8); +} + +static void sub_80B0BD8(struct Sprite *sprite) +{ + if (++sprite->data[5] == 11) + { + sprite->data[2] = sprite->pos1.x - sprite->pos2.x; + sprite->data[4] = sprite->pos1.y - sprite->pos2.y; + sprite->data[0] = 8; + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + } +} + +static void sub_80B0C28(struct Sprite *sprite) +{ + if (BATTLE_PARTNER(gBattleAnimAttacker) == gBattleAnimTarget && GetBattlerPosition(gBattleAnimTarget) < B_POSITION_PLAYER_RIGHT) + gBattleAnimArgs[0] *= -1; + InitSpritePosToAnimTarget(sprite, TRUE); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + sprite->data[0] = gBattleAnimArgs[3]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = sprite->pos1.y; + InitAnimLinearTranslation(sprite); + sprite->data[5] = gBattleAnimArgs[5]; + sprite->data[6] = gBattleAnimArgs[4]; + sprite->data[7] = 0; + sprite->callback = sub_80B0CB4; +} + +static void sub_80B0CB4(struct Sprite *sprite) +{ + if (!AnimTranslateLinear(sprite)) + { + sprite->pos2.y += Sin(sprite->data[7] >> 8, sprite->data[5]); + sprite->data[7] += sprite->data[6]; + } + else + { + DestroyAnimSprite(sprite); + } +} + +// Animates the spinning, shrinking kick or punch, which then +// reappears at full size. Used by moves such as MOVE_MEGA_PUNCH and MOVE_MEGA_KICK. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: anim num +// arg 3: spin duration +static void AnimSpinningKickOrPunch(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + StartSpriteAnim(sprite, gBattleAnimArgs[2]); + sprite->data[0] = gBattleAnimArgs[3]; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, AnimSpinningKickOrPunchFinish); +} + +static void AnimSpinningKickOrPunchFinish(struct Sprite *sprite) +{ + StartSpriteAffineAnim(sprite, 0); + sprite->affineAnimPaused = 1; + sprite->data[0] = 20; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Animates MOVE_STOMP's foot that slides downward. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: initial wait duration +static void AnimStompFoot(struct Sprite *sprite) +{ + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[2]; + sprite->callback = AnimStompFootStep; +} + +static void AnimStompFootStep(struct Sprite *sprite) +{ + if (--sprite->data[0] == -1) + { + sprite->data[0] = 6; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, AnimStompFootEnd); + } +} + +static void AnimStompFootEnd(struct Sprite *sprite) +{ + sprite->data[0] = 15; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void sub_80B0DF0(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + InitSpritePosToAnimTarget(sprite, TRUE); + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[2] = gBattleAnimArgs[3]; + ++sprite->data[0]; + } + else + { + sprite->data[4] += sprite->data[1]; + sprite->pos2.x = sprite->data[4] >> 8; + sprite->pos2.y = Sin(sprite->data[3], sprite->data[2]); + sprite->data[3] = (sprite->data[3] + 3) & 0xFF; + if (sprite->data[3] > 100) + sprite->invisible = sprite->data[3] % 2; + if (sprite->data[3] > 120) + DestroyAnimSprite(sprite); + } +} + +static void sub_80B0E80(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == 0) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1); + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1); + } + sprite->pos1.x += gBattleAnimArgs[1]; + sprite->pos1.y += gBattleAnimArgs[2]; + sprite->data[0] = 0; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->data[2] = gBattleAnimArgs[4]; + sprite->data[3] = 0; + sprite->callback = sub_80B0EF0; +} + +static void sub_80B0EF0(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (--sprite->data[1] == 0) + { + if (sprite->data[2] == 0) + DestroyAnimSprite(sprite); + else + ++sprite->data[0]; + } + break; + case 1: + if (++sprite->data[1] > 1) + { + sprite->data[1] = 0; + ++sprite->data[3]; + if (sprite->data[3] & 1) + sprite->pos2.x = 2; + else + sprite->pos2.x = -2; + } + + if (--sprite->data[2] == 0) + DestroyAnimSprite(sprite); + break; + } +} + +static void sub_80B0F68(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == 0) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, 0) + gBattleAnimArgs[2]; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, 1) + gBattleAnimArgs[3]; + } + else + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 0) + gBattleAnimArgs[2]; + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 1) + gBattleAnimArgs[3]; + } + sprite->oam.tileNum += gBattleAnimArgs[1] * 16; + sprite->data[0] = 0; + switch (gBattleAnimArgs[1]) + { + case 0: + sprite->data[6] = -3; + sprite->data[7] = -3; + break; + case 1: + sprite->data[6] = 3; + sprite->data[7] = -3; + break; + case 2: + sprite->data[6] = -3; + sprite->data[7] = 3; + break; + case 3: + sprite->data[6] = 3; + sprite->data[7] = 3; + break; + default: + DestroyAnimSprite(sprite); + return; + } + sprite->callback = sub_80B1050; +} + +static void sub_80B1050(struct Sprite *sprite) +{ + sprite->pos1.x += sprite->data[6]; + sprite->pos1.y += sprite->data[7]; + if (++sprite->data[0] > 40) + DestroyAnimSprite(sprite); +} + +static void sub_80B107C(struct Sprite *sprite) +{ + if (gBattleAnimArgs[0] == 0) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattlerAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattlerAttacker, 3); + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker); + sprite->data[7] = gBattleAnimTarget; + } + else + { + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); + sprite->data[7] = gBattleAnimAttacker; + } + sprite->data[0] = 0; + sprite->data[1] = 12; + sprite->data[2] = 8; + sprite->callback = sub_80B111C; +} + +static void sub_80B111C(struct Sprite *sprite) +{ + if (++sprite->data[0] == 180) + { + SetGpuReg(REG_OFFSET_BLDCNT, 0); + sprite->data[0] = 16; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(sprite->data[7], 2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(sprite->data[7], 3); + InitAnimLinearTranslation(sprite); + StoreSpriteCallbackInData6(sprite, DestroySpriteAndMatrix); + sprite->callback = sub_807563C; + } +} + +static void sub_80B1188(struct Sprite *sprite) +{ + sprite->pos1.x = gBattleAnimArgs[0]; + sprite->pos1.y = 120; + sprite->data[0] = gBattleAnimArgs[3]; + StorePointerInVars(&sprite->data[4], &sprite->data[5], (void *)(sprite->pos1.y << 8)); + sprite->data[6] = gBattleAnimArgs[1]; + sprite->oam.tileNum += gBattleAnimArgs[2] * 4; + sprite->callback = sub_80B11E4; +} + +static void sub_80B11E4(struct Sprite *sprite) +{ + void *var0; + + if (sprite->data[0] != 0) + { + var0 = LoadPointerFromVars(sprite->data[4], sprite->data[5]); + var0 -= sprite->data[6]; + StorePointerInVars(&sprite->data[4], &sprite->data[5], var0); + var0 = (void *)(((intptr_t)var0) >> 8); + sprite->pos1.y = (intptr_t)var0; + if (sprite->pos1.y < -8) + DestroyAnimSprite(sprite); + else + --sprite->data[0]; + } + else + { + s16 pos0 = GetBattlerSpriteCoord(gBattleAnimAttacker, 2); + s16 pos1 = GetBattlerSpriteCoord(gBattleAnimAttacker, 3); + s16 pos2 = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + s16 pos3 = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + + sprite->data[0] = pos2 - pos0; + sprite->data[1] = pos3 - pos1; + sprite->data[2] = sprite->pos1.x << 4; + sprite->data[3] = sprite->pos1.y << 4; + sprite->callback = sub_80B12A4; + } +} + +static void sub_80B12A4(struct Sprite *sprite) +{ + u16 edgeX; + + sprite->data[2] += sprite->data[0]; + sprite->data[3] += sprite->data[1]; + sprite->pos1.x = sprite->data[2] >> 4; + sprite->pos1.y = sprite->data[3] >> 4; + edgeX = sprite->pos1.x + 8; + if (edgeX > 256 || sprite->pos1.y < -8 || sprite->pos1.y > 120) + DestroyAnimSprite(sprite); +} + +static void sub_80B12E8(struct Sprite *sprite) +{ + u8 battler; + + if (gBattleAnimArgs[0] == 0) + { + sprite->pos1.x = GetBattlerSpriteCoord(gBattlerAttacker, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattlerAttacker, 3); + battler = gBattleAnimTarget; + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker); + } + else + { + battler = gBattleAnimAttacker; + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); + } + if (IsContest()) + sprite->oam.matrixNum |= ST_OAM_HFLIP; + else if (GetBattlerSide(battler) == B_SIDE_PLAYER) + sprite->oam.matrixNum |= (ST_OAM_HFLIP | ST_OAM_VFLIP); + sprite->data[0] = 16; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(battler, 2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(battler, 3); + InitAnimLinearTranslation(sprite); + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = sub_807563C; +} + +static void sub_80B13D4(struct Sprite *sprite) +{ + if (sprite->data[0] == sprite->data[4]) + DestroyAnimSprite(sprite); + ++sprite->data[0]; +} + +static void sub_80B13F8(struct Sprite *sprite) +{ + u8 turn; + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->data[1] = gBattleAnimArgs[3]; + sprite->data[2] = gBattleAnimArgs[0]; + sprite->data[3] = gBattleAnimArgs[1]; + sprite->data[4] = gBattleAnimArgs[2]; + turn = gAnimMoveTurn; + if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + ++turn; + if (turn & 1) + { + sprite->data[2] = -sprite->data[2]; + ++sprite->data[1]; + } + StartSpriteAnim(sprite, sprite->data[1]); + sprite->pos2.x = sprite->data[2]; + sprite->pos2.y = sprite->data[3]; + sprite->callback = sub_80B13D4; +} + +static void sub_80B1484(struct Sprite *sprite) +{ + if (gBattleAnimArgs[2] == 0) + InitSpritePosToAnimAttacker(sprite, 0); + else + InitSpritePosToAnimTarget(sprite, FALSE); + if (IsContest()) + StartSpriteAnim(sprite, 2); + else if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + StartSpriteAnim(sprite, 1); + sprite->callback = RunStoredCallbackWhenAnimEnds; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void sub_80B14F0(struct Sprite *sprite) +{ + if (sprite->affineAnimEnded) + { + sprite->data[1] = (sprite->data[1] + 40) & 0xFF; + sprite->pos2.x = Sin(sprite->data[1], 2); + if (++sprite->data[0] > 40) + DestroyAnimSprite(sprite); + } +} + +void sub_80B1530(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + sub_8075458(0); + task->data[8] = gBattleAnimArgs[0]; + ++task->data[0]; + break; + case 1: + if (--task->data[8] == -1) + ++task->data[0]; + break; + case 2: + default: + task->data[9] += 1280; + break; + } + task->data[10] += 2816; + if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + gBattle_BG3_X += task->data[9] >> 8; + else + gBattle_BG3_X -= task->data[9] >> 8; + gBattle_BG3_Y += task->data[10] >> 8; + task->data[9] &= 0xFF; + task->data[10] &= 0xFF; + if (gBattleAnimArgs[7] == -1) + { + gBattle_BG3_X = 0; + gBattle_BG3_Y = 0; + sub_8075458(1); + DestroyAnimVisualTask(taskId); + } +} diff --git a/src/fire.c b/src/fire.c new file mode 100644 index 000000000..014413f5b --- /dev/null +++ b/src/fire.c @@ -0,0 +1,1193 @@ +#include "global.h" +#include "battle_anim.h" +#include "sound.h" +#include "util.h" +#include "task.h" +#include "trig.h" +#include "constants/songs.h" + +static void sub_80AC90C(struct Sprite *sprite); +static void sub_80AC94C(struct Sprite *sprite); +static void sub_80ACA00(struct Sprite *sprite); +static void sub_80AC990(struct Sprite *sprite); +static void sub_80ACAA8(struct Sprite *sprite); +static void sub_80ACBB0(struct Sprite *sprite); +static void AnimEmberFlare(struct Sprite *sprite); +static void sub_80ACC44(struct Sprite *sprite); +static void AnimFireRing(struct Sprite *sprite); +static void AnimFireCross(struct Sprite *sprite); +static void sub_80ACDE8(struct Sprite *sprite); +static void sub_80AD330(struct Sprite *sprite); +static void sub_80AD454(struct Sprite *sprite); +static void sub_80AD540(struct Sprite *sprite); +static void sub_80AD6F4(struct Sprite *sprite); +static void sub_80ACA6C(struct Sprite *sprite); +static void sub_80ACB1C(struct Sprite *sprite); +static void AnimFireRing_Step1(struct Sprite *sprite); +static void AnimFireRing_Step2(struct Sprite *sprite); +static void AnimFireRing_Step3(struct Sprite *sprite); +static void UpdateFireRingCircleOffset(struct Sprite *sprite); +static void sub_80ACE28(struct Sprite *sprite); +static void sub_80ACE50(struct Sprite *sprite); +static void sub_80ACF14(u8 taskId); +static void sub_80AD1F8(u8 spriteId, u8 taskId, u8 a3); +static u16 sub_80AD374(u8 spriteId); +static void sub_80AD3C8(struct Sprite *sprite, s16 x, s16 y); +static void sub_80AD3E4(struct Sprite *sprite); +static void sub_80AD4A8(struct Sprite *sprite); +static void sub_80AD690(struct Sprite *sprite); +static void sub_80AD870(u8 taskId); + +static const union AnimCmd gUnknown_83E5BB8[] = +{ + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_FRAME(48, 4), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd gUnknown_83E5BC8[] = +{ + ANIMCMD_FRAME(16, 4, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_FRAME(32, 4, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_FRAME(48, 4, .vFlip = TRUE, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E5BD8[] = +{ + gUnknown_83E5BB8, + gUnknown_83E5BC8, +}; + +const struct SpriteTemplate gUnknown_83E5BE0 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5BD8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AC90C, +}; + +const struct SpriteTemplate gUnknown_83E5BF8 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5BD8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AC94C, +}; + +static const union AnimCmd gUnknown_83E5C10[] = +{ + ANIMCMD_FRAME(0, 3), + ANIMCMD_FRAME(16, 3), + ANIMCMD_FRAME(32, 3), + ANIMCMD_FRAME(48, 3), + ANIMCMD_FRAME(64, 3), + ANIMCMD_FRAME(80, 3), + ANIMCMD_FRAME(96, 3), + ANIMCMD_FRAME(112, 3), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E5C34[] = +{ + gUnknown_83E5C10, +}; + +static const union AnimCmd gUnknown_83E5C38[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(32, 5), + ANIMCMD_FRAME(48, 5), + ANIMCMD_FRAME(64, 5), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E5C50[] = +{ + gUnknown_83E5C38, +}; + +static const union AffineAnimCmd gUnknown_83E5C54[] = +{ + AFFINEANIMCMD_FRAME(0x32, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x20, 0x0, 0, 7), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E5C6C[] = +{ + gUnknown_83E5C54, +}; + +const struct SpriteTemplate gUnknown_83E5C70 = +{ + .tileTag = ANIM_TAG_FIRE, + .paletteTag = ANIM_TAG_FIRE, + .oam = &gOamData_83ACA38, + .anims = gUnknown_83E5C34, + .images = NULL, + .affineAnims = gUnknown_83E5C6C, + .callback = sub_80ACA00, +}; + +const struct SpriteTemplate gUnknown_83E5C88 = +{ + .tileTag = ANIM_TAG_FIRE, + .paletteTag = ANIM_TAG_FIRE, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5C34, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80ACA00, +}; + +const struct SpriteTemplate gUnknown_83E5CA0 = +{ + .tileTag = ANIM_TAG_FIRE_PLUME, + .paletteTag = ANIM_TAG_FIRE_PLUME, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5C50, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AC990, +}; + +const struct SpriteTemplate gUnknown_83E5CB8 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5C50, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AC990, +}; + +static const union AnimCmd gUnknown_83E5CD0[] = +{ + ANIMCMD_FRAME(16, 6), + ANIMCMD_FRAME(32, 6), + ANIMCMD_FRAME(48, 6), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E5CE0[] = +{ + gUnknown_83E5CD0, +}; + +const struct SpriteTemplate gUnknown_83E5CE4 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5CE0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80ACAA8, +}; + +static const union AffineAnimCmd gUnknown_83E5CFC[] = +{ + AFFINEANIMCMD_FRAME(0x50, 0x50, 0, 0), + AFFINEANIMCMD_FRAME(0x2, 0x2, 10, 1), + AFFINEANIMCMD_JUMP(1), +}; + +static const union AffineAnimCmd *const gUnknown_83E5D14[] = +{ + gUnknown_83E5CFC, +}; + +const struct SpriteTemplate gUnknown_83E5D18 = +{ + .tileTag = ANIM_TAG_SUNLIGHT, + .paletteTag = ANIM_TAG_SUNLIGHT, + .oam = &gOamData_83ACB58, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E5D14, + .callback = sub_80ACBB0, +}; + +static const union AnimCmd gUnknown_83E5D30[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_FRAME(48, 4), + ANIMCMD_FRAME(64, 4), + ANIMCMD_JUMP(0), +}; + +const union AnimCmd *const gUnknown_83E5D48[] = +{ + gUnknown_83E5D30, +}; + +const struct SpriteTemplate gEmberSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = TranslateAnimSpriteToTargetMonLocation, +}; + +const struct SpriteTemplate gEmberFlareSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5D48, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimEmberFlare, +}; + +const struct SpriteTemplate gUnknown_83E5D7C = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5D48, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80ACC44, +}; + +const struct SpriteTemplate gUnknown_83E5D94 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5D48, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireRing, +}; + +static const union AnimCmd gUnknown_83E5DAC[] = +{ + ANIMCMD_FRAME(32, 6), + ANIMCMD_FRAME(48, 6), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E5DB8[] = +{ + gUnknown_83E5DAC, +}; + +static const union AffineAnimCmd gUnknown_83E5DBC[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 1), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E5DCC[] = +{ + AFFINEANIMCMD_FRAME(0xA0, 0xA0, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E5DDC[] = +{ + gUnknown_83E5DBC, + gUnknown_83E5DCC, +}; + +const struct SpriteTemplate gUnknown_83E5DE4 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5DB8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimFireCross, +}; + +const struct SpriteTemplate gUnknown_83E5DFC = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5D48, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80ACDE8, +}; + +const struct SpriteTemplate gUnknown_83E5E14 = +{ + .tileTag = ANIM_TAG_SMALL_EMBER, + .paletteTag = ANIM_TAG_SMALL_EMBER, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5D48, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_8077350, +}; + +static const struct SpriteTemplate gUnknown_83E5E2C = +{ + .tileTag = ANIM_TAG_WARM_ROCK, + .paletteTag = ANIM_TAG_WARM_ROCK, + .oam = &gOamData_83AC9D0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AD330, +}; + +static const s16 sHeatedRockCoords[][2] = +{ + {-2, -5}, + {-1, -1}, + { 3, -6}, + { 4, -2}, + { 2, -8}, + {-5, -5}, + { 4, -7}, +}; + +const struct SpriteTemplate gUnknown_83E5E60 = +{ + .tileTag = ANIM_TAG_WARM_ROCK, + .paletteTag = ANIM_TAG_WARM_ROCK, + .oam = &gOamData_83AC9D8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AD454, +}; + +static const union AnimCmd gUnknown_83E5E78[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_FRAME(12, 5), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd gUnknown_83E5E8C[] = +{ + ANIMCMD_FRAME(16, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E5E94[] = +{ + ANIMCMD_FRAME(20, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E5E9C[] = +{ + ANIMCMD_FRAME(20, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E5EA4[] = +{ + gUnknown_83E5E78, + gUnknown_83E5E8C, + gUnknown_83E5E94, + gUnknown_83E5E9C, +}; + +const struct SpriteTemplate gUnknown_83E5EB4 = +{ + .tileTag = ANIM_TAG_WISP_ORB, + .paletteTag = ANIM_TAG_WISP_ORB, + .oam = &gOamData_83AC9D0, + .anims = gUnknown_83E5EA4, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AD540, +}; + +static const union AnimCmd gUnknown_83E5ECC[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(32, 5), + ANIMCMD_FRAME(48, 5), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E5EE0[] = +{ + gUnknown_83E5ECC, +}; + +const struct SpriteTemplate gUnknown_83E5EE4 = +{ + .tileTag = ANIM_TAG_WISP_FIRE, + .paletteTag = ANIM_TAG_WISP_FIRE, + .oam = &gOamData_83AC9D8, + .anims = gUnknown_83E5EE0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AD6F4, +}; + +static const s8 gUnknown_83E5EFC[16] = +{ + -1, -1, 0, 1, 1, 0, 0, -1, -1, 1, 1, 0, 0, -1, 0, 1, +}; + +static const s8 gUnknown_83E5F0C[16] = +{ + -1, 0, 1, 0, -1, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 1, +}; + +static void sub_80AC90C(struct Sprite *sprite) +{ + sprite->data[0] = gBattleAnimArgs[0]; + sprite->data[1] = 0x3C; + sprite->data[2] = 0x9; + sprite->data[3] = 0x1E; + sprite->data[4] = 0xFE00; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = TranslateSpriteInGrowingCircleOverDuration; + sprite->callback(sprite); +} + +static void sub_80AC94C(struct Sprite *sprite) +{ + SetAnimSpriteInitialXOffset(sprite, gBattleAnimArgs[0]); + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[2] = gBattleAnimArgs[3]; + sprite->callback = TranslateSpriteLinearFixedPoint; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +static void sub_80AC990(struct Sprite *sprite) +{ + SetSpriteCoordsToAnimAttackerCoords(sprite); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[2] = -gBattleAnimArgs[4]; + } + else + { + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[2] = gBattleAnimArgs[4]; + } + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[4] = gBattleAnimArgs[3]; + sprite->data[3] = gBattleAnimArgs[5]; + sprite->callback = sub_80ACA6C; +} + +static void sub_80ACA00(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[2] = gBattleAnimArgs[4]; + } + else + { + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[2] = -gBattleAnimArgs[4]; + } + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[4] = gBattleAnimArgs[3]; + sprite->data[3] = gBattleAnimArgs[5]; + sprite->callback = sub_80ACA6C; +} + +static void sub_80ACA6C(struct Sprite *sprite) +{ + if (++sprite->data[0] < sprite->data[4]) + { + sprite->pos2.x += sprite->data[2]; + sprite->pos2.y += sprite->data[3]; + } + if (sprite->data[0] == sprite->data[1]) + DestroySpriteAndMatrix(sprite); +} + +static void sub_80ACAA8(struct Sprite *sprite) +{ + SetSpriteCoordsToAnimAttackerCoords(sprite); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + { + sprite->pos1.x -= gBattleAnimArgs[0]; + } + else + { + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->subpriority = 8; + } + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->data[2] = gBattleAnimArgs[4]; + sprite->data[3] = gBattleAnimArgs[5]; + sprite->data[4] = gBattleAnimArgs[6]; + sprite->data[5] = 0; + sprite->callback = sub_80ACB1C; +} + +static void sub_80ACB1C(struct Sprite *sprite) +{ + if (sprite->data[3]) + { + if(sprite->data[5] > 10000) + sprite->subpriority = 1; + sprite->pos2.x = Sin(sprite->data[0], sprite->data[1] + (sprite->data[5] >> 8)); + sprite->pos2.y = Cos(sprite->data[0], sprite->data[1] + (sprite->data[5] >> 8)); + sprite->data[0] += sprite->data[2]; + sprite->data[5] += sprite->data[4]; + if (sprite->data[0] > 255) + sprite->data[0] -= 256; + else if (sprite->data[0] < 0) + sprite->data[0] += 256; + --sprite->data[3]; + } + else + { + DestroySpriteAndMatrix(sprite); + } +} + +//sunlight +static void sub_80ACBB0(struct Sprite *sprite) +{ + sprite->pos1.x = 0; + sprite->pos1.y = 0; + sprite->data[0] = 60; + sprite->data[2] = 140; + sprite->data[4] = 80; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +//fire 2 + +// Animates the secondary effect of MOVE_EMBER, where the flames grow and slide +// horizontally a bit. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x pixel offset +// arg 3: target y pixel offset +// arg 4: duration +// arg 5: ? (TODO: something related to which mon the pixel offsets are based on) +// arg 6: ? (TODO: something related to which mon the pixel offsets are based on) +static void AnimEmberFlare(struct Sprite *sprite) +{ + if (GetBattlerSide(gBattleAnimAttacker) == GetBattlerSide(gBattleAnimTarget) + && (gBattleAnimAttacker == GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT) + || gBattleAnimAttacker == GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT))) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + sprite->callback = AnimSnoreZ; + sprite->callback(sprite); +} + +static void sub_80ACC44(struct Sprite *sprite) +{ + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + sprite->callback = AnimSnoreZ; +} + +// Animates the a fire sprite in the first-half of the MOVE_FIRE_BLAST +// animation. The fire sprite first moves in a circle around the mon, +// and then it is translated towards the target mon, while still rotating. +// Lastly, it moves in a circle around the target mon. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: initial wave offset +//void AnimFireRing(struct Sprite *sprite) +static void AnimFireRing(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + sprite->data[7] = gBattleAnimArgs[2]; + sprite->data[0] = 0; + sprite->callback = AnimFireRing_Step1; +} + +static void AnimFireRing_Step1(struct Sprite *sprite) +{ + UpdateFireRingCircleOffset(sprite); + + if (++sprite->data[0] == 0x12) + { + sprite->data[0] = 0x19; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + InitAnimLinearTranslation(sprite); + sprite->callback = AnimFireRing_Step2; + } +} + +static void AnimFireRing_Step2(struct Sprite *sprite) +{ + if (AnimTranslateLinear(sprite)) + { + sprite->data[0] = 0; + + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->pos2.x = sprite->pos2.y = 0; + sprite->callback = AnimFireRing_Step3; + sprite->callback(sprite); + } + else + { + sprite->pos2.x += Sin(sprite->data[7], 28); + sprite->pos2.y += Cos(sprite->data[7], 28); + sprite->data[7] = (sprite->data[7] + 20) & 0xFF; + } +} + +static void AnimFireRing_Step3(struct Sprite *sprite) +{ + UpdateFireRingCircleOffset(sprite); + if (++sprite->data[0] == 0x1F) + DestroyAnimSprite(sprite); +} + +static void UpdateFireRingCircleOffset(struct Sprite *sprite) +{ + sprite->pos2.x = Sin(sprite->data[7], 28); + sprite->pos2.y = Cos(sprite->data[7], 28); + sprite->data[7] = (sprite->data[7] + 20) & 0xFF; +} + +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: duration +// arg 3: x delta +// arg 4: y delta +// AnimFireCross(struct Sprite *sprite) +static void AnimFireCross(struct Sprite *sprite) +{ + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = gBattleAnimArgs[3]; + sprite->data[2] = gBattleAnimArgs[4]; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = TranslateSpriteLinear; +} + +static void sub_80ACDE8(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, 1); + sprite->data[1] = gBattleAnimArgs[2]; + sprite->data[0] = gBattleAnimArgs[3]; + sprite->invisible = TRUE; + sprite->callback = WaitAnimForDuration; + StoreSpriteCallbackInData6(sprite, sub_80ACE28); +} + +static void sub_80ACE28(struct Sprite *sprite) +{ + sprite->invisible = FALSE; + sprite->data[0] = sprite->data[1]; + sprite->data[1] = 0; + sprite->callback = sub_80ACE50; + sprite->callback(sprite); +} + +static void sub_80ACE50(struct Sprite *sprite) +{ + sprite->pos2.x = Sin(sprite->data[1], sprite->data[2] >> 8); + sprite->pos2.y = Cos(sprite->data[1], sprite->data[2] >> 8); + sprite->data[1] = (sprite->data[1] + 10) & 0xFF; + sprite->data[2] += 0xD0; + if (--sprite->data[0] == -1) + DestroyAnimSprite(sprite); +} + +void sub_80ACEA4(u8 taskId) // initialize animation task for Move_ERUPTION? +{ + struct Task *task = &gTasks[taskId]; + + task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); + task->data[0] = 0; + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = 0; + task->data[4] = gSprites[task->data[15]].pos1.y; + task->data[5] = GetBattlerSide(gBattleAnimAttacker); + task->data[6] = 0; + PrepareBattlerSpriteForRotScale(task->data[15], ST_OAM_OBJ_NORMAL); + task->func = sub_80ACF14; +} + +static void sub_80ACF14(u8 taskId) // animate Move_ERUPTION? +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + sub_80765D4(task, task->data[15], 0x100, 0x100, 0xE0, 0x200, 0x20); + ++task->data[0]; + // fall through + case 1: + if (++task->data[1] > 1) + { + task->data[1] = 0; + if (++task->data[2] & 0x1) + gSprites[task->data[15]].pos2.x = 3; + else + gSprites[task->data[15]].pos2.x = -3; + } + if (task->data[5]) + { + if (++task->data[3] > 4) + { + task->data[3] = 0; + ++gSprites[task->data[15]].pos1.y; + } + } + if(!sub_8076640(task)) + { + SetBattlerSpriteYOffsetFromYScale(task->data[15]); + gSprites[task->data[15]].pos2.x = 0; + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = 0; + ++task->data[0]; + } + break; + case 2: + if (++task->data[1] > 4) + { + if (task->data[5]) + sub_80765D4(task, task->data[15], 0xE0, 0x200, 0x180, 0xF0, 0x6); + else + sub_80765D4(task, task->data[15], 0xE0, 0x200, 0x180, 0xC0, 0x6); + task->data[1] = 0; + ++task->data[0]; + } + break; + case 3: + if (!sub_8076640(task)) + { + sub_80AD1F8(task->data[15], taskId, 6); + ++task->data[0]; + } + break; + case 4: + if (++task->data[1] > 1) + { + task->data[1] = 0; + if (++task->data[2] & 1) + gSprites[task->data[15]].pos2.y += 3; + else + gSprites[task->data[15]].pos2.y -= 3; + } + if (++task->data[3] > 0x18) + { + if (task->data[5]) + sub_80765D4(task, task->data[15], 0x180, 0xF0, 0x100, 0x100, 0x8); + else + sub_80765D4(task, task->data[15], 0x180, 0xC0, 0x100, 0x100, 0x8); + if (task->data[2] & 1) + gSprites[task->data[15]].pos2.y -= 3; + task->data[1] = 0; + task->data[2] = 0; + task->data[3] = 0; + ++task->data[0]; + } + break; + case 5: + if (task->data[5]) + --gSprites[task->data[15]].pos1.y; + if (!sub_8076640(task)) + { + gSprites[task->data[15]].pos1.y = task->data[4]; + ResetSpriteRotScale(task->data[15]); + + task->data[2] = 0; + ++task->data[0]; + } + break; + case 6: + if (!task->data[6]) + DestroyAnimVisualTask(taskId); + break; + } +} + +static void sub_80AD1F8(u8 spriteId, u8 taskId, u8 a3) +{ + u16 i, j; + s8 sign; + u16 y = sub_80AD374(spriteId); + u16 x = gSprites[spriteId].pos1.x; + + if(GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + { + x -= 0xC; + sign = 1; + } + else + { + x += 0x10; + sign = -1; + } + for (i = 0, j = 0; i <= 6; ++i) + { + u8 spriteId = CreateSprite(&gUnknown_83E5E2C, x, y, 2); + + if (spriteId != 0x40) + { + gSprites[spriteId].oam.tileNum += j * 4 + 0x40; + if (++j >= 5) + j = 0; + sub_80AD3C8(&gSprites[spriteId], sHeatedRockCoords[i][0] * sign, sHeatedRockCoords[i][1]); + gSprites[spriteId].data[6] = taskId; + gSprites[spriteId].data[7] = a3; + ++gTasks[taskId].data[a3]; + } + } +} + +static void sub_80AD330(struct Sprite *sprite) +{ + sub_80AD3E4(sprite); + if (sprite->invisible) + { + --gTasks[sprite->data[6]].data[sprite->data[7]]; + DestroySprite(sprite); + } +} + +static u16 sub_80AD374(u8 spriteId) +{ + u16 var1 = gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y + gSprites[spriteId].centerToCornerVecY; + + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + var1 = ((var1 << 16) + 0x4A0000) >> 16; + else + var1 = ((var1 << 16) + 0x2C0000) >> 16; + return var1; +} + +static void sub_80AD3C8(struct Sprite *sprite, s16 x, s16 y) +{ + sprite->data[0] = 0; + sprite->data[1] = 0; + sprite->data[2] = (u16)sprite->pos1.x * 8; + sprite->data[3] = (u16)sprite->pos1.y * 8; + sprite->data[4] = x * 8; + sprite->data[5] = y * 8; +} + +static void sub_80AD3E4(struct Sprite *sprite) +{ + s32 var1; + + if (++sprite->data[0] > 2) + { + sprite->data[0] = 0; + ++sprite->data[1]; + var1 = (u16)sprite->data[1] * (u16)sprite->data[1]; + sprite->data[3] += var1; + } + sprite->data[2] += sprite->data[4]; + sprite->pos1.x = sprite->data[2] >> 3; + sprite->data[3] += sprite->data[5]; + sprite->pos1.y = sprite->data[3] >> 3; + if (sprite->pos1.x < -8 || sprite->pos1.x > 0xf8 || sprite->pos1.y < -8 || sprite->pos1.y > 120) + sprite->invisible = TRUE; +} + +static void sub_80AD454(struct Sprite *sprite) +{ + sprite->pos1.x = gBattleAnimArgs[0]; + sprite->pos1.y = gBattleAnimArgs[1]; + sprite->data[0] = 0; + sprite->data[1] = 0; + sprite->data[2] = 0; + sprite->data[6] = gBattleAnimArgs[2]; + sprite->data[7] = gBattleAnimArgs[3]; + sprite->oam.tileNum += gBattleAnimArgs[4] * 16; + sprite->callback = sub_80AD4A8; +} + +static void sub_80AD4A8(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + if (sprite->data[6] != 0) + { + --sprite->data[6]; + return; + } + ++sprite->data[0]; + // fall through + case 1: + sprite->pos1.y += 8; + if (sprite->pos1.y >= sprite->data[7]) + { + sprite->pos1.y = sprite->data[7]; + ++sprite->data[0]; + } + break; + case 2: + if (++sprite->data[1] > 1) + { + sprite->data[1] = 0; + if ((++sprite->data[2] & 1) != 0) + sprite->pos2.y = -3; + else + sprite->pos2.y = 3; + } + if (++sprite->data[3] > 16) + DestroyAnimSprite(sprite); + break; + } +} + +//wisp orb +static void sub_80AD540(struct Sprite *sprite) +{ + switch (sprite->data[0]) + { + case 0: + InitSpritePosToAnimAttacker(sprite, 0); + StartSpriteAnim(sprite, gBattleAnimArgs[2]); + sprite->data[7] = gBattleAnimArgs[2]; + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->data[4] = 4; + else + sprite->data[4] = -4; + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); + ++sprite->data[0]; + break; + case 1: + sprite->data[1] += 192; + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->pos2.y = -(sprite->data[1] >> 8); + else + sprite->pos2.y = sprite->data[1] >> 8; + sprite->pos2.x = Sin(sprite->data[2], sprite->data[4]); + sprite->data[2] = (sprite->data[2] + 4) & 0xFF; + if (++sprite->data[3] == 1) + { + sprite->data[3] = 0; + ++sprite->data[0]; + } + break; + case 2: + sprite->pos2.x = Sin(sprite->data[2], sprite->data[4]); + sprite->data[2] = (sprite->data[2] + 4) & 0xFF; + if (++sprite->data[3] == 31) + { + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.x = sprite->pos2.y = 0; + sprite->data[0] = 256; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sub_8075678(sprite); + sprite->callback = sub_80AD690; + } + break; + } +} + +static void sub_80AD690(struct Sprite *sprite) +{ + s16 initialData5, newData5; + + if (!AnimTranslateLinear(sprite)) + { + sprite->pos2.x += Sin(sprite->data[5], 16); + initialData5 = sprite->data[5]; + sprite->data[5] = (sprite->data[5] + 4) & 0xFF; + newData5 = sprite->data[5]; + if ((initialData5 == 0 || initialData5 > 196) && newData5 > 0 && sprite->data[7] == 0) + PlaySE12WithPanning(SE_W172, gUnknown_2037F24); + } + else + { + DestroyAnimSprite(sprite); + } +} + +//wisp fire +static void sub_80AD6F4(struct Sprite *sprite) +{ + if (!sprite->data[0]) + { + sprite->data[1] = gBattleAnimArgs[0]; + ++sprite->data[0]; + } + sprite->data[3] += 0xC0 * 2; + sprite->data[4] += 0xA0; + sprite->pos2.x = Sin(sprite->data[1], sprite->data[3] >> 8); + sprite->pos2.y = Cos(sprite->data[1], sprite->data[4] >> 8); + sprite->data[1] = (sprite->data[1] + 7) & 0xFF; + if (!IsContest()) + { + if (sprite->data[1] < 64 || sprite->data[1] > 195) + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget); + else + sprite->oam.priority = GetBattlerSpriteBGPriority(gBattleAnimTarget) + 1; + } + else + { + if (sprite->data[1] < 64 || sprite->data[1] > 195) + sprite->subpriority = 0x1D; + else + sprite->subpriority = 0x1F; + } + if (++sprite->data[2] > 0x14) + sprite->invisible ^= 1; + if (sprite->data[2] == 0x1E) + DestroyAnimSprite(sprite); +} + +void sub_80AD800(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->data[12] = GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER ? 1 : -1; + task->data[13] = IsBattlerSpriteVisible(gBattleAnimTarget ^ BIT_FLANK) + 1; + task->data[14] = GetAnimBattlerSpriteId(ANIM_TARGET); + task->data[15] = GetAnimBattlerSpriteId(ANIM_DEF_PARTNER); + task->func = sub_80AD870; +} + +static void sub_80AD870(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[10] += task->data[12] * 2; + if (++task->data[1] >= 2) + { + task->data[1] = 0; + ++task->data[2]; + if (task->data[2] & 1) + task->data[11] = 2; + else + task->data[11] = -2; + } + for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) + gSprites[task->data[task->data[3] + 14]].pos2.x = task->data[10] + task->data[11]; + if (++task->data[9] == 16) + { + task->data[9] = 0; + ++task->data[0]; + } + break; + case 1: + if (++task->data[1] >= 5) + { + task->data[1] = 0; + ++task->data[2]; + if (task->data[2] & 1) + task->data[11] = 2; + else + task->data[11] = -2; + } + for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) + gSprites[task->data[task->data[3] + 14]].pos2.x = task->data[10] + task->data[11]; + if (++task->data[9] == 96) + { + task->data[9] = 0; + ++task->data[0]; + } + break; + case 2: + task->data[10] -= task->data[12] * 2; + if (++task->data[1] >= 2) + { + task->data[1] = 0; + ++task->data[2]; + if (task->data[2] & 1) + task->data[11] = 2; + else + task->data[11] = -2; + } + for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) + gSprites[task->data[task->data[3] + 14]].pos2.x = task->data[10] + task->data[11]; + if (++task->data[9] == 16) + ++task->data[0]; + break; + case 3: + for (task->data[3] = 0; task->data[3] < task->data[13]; task->data[3]++) + gSprites[task->data[task->data[3] + 14]].pos2.x = 0; + DestroyAnimVisualTask(taskId); + break; + } +} + +// Used to add a color mask to the battle interface / HUD in Heat Wave. +// arg 0: opacity +// arg 1: color code +void AnimTask_BlendBackground(u8 taskId) +{ + struct BattleAnimBgData animBg; + + sub_80752A0(&animBg); + BlendPalette(animBg.paletteId * 16, 16, gBattleAnimArgs[0], gBattleAnimArgs[1]); + DestroyAnimVisualTask(taskId); +} + +void sub_80ADAD8(u8 taskId) +{ + s8 unk; + u8 spriteId; + + if (gTasks[taskId].data[0] == 0) + { + gTasks[taskId].data[1] = gBattleAnimArgs[0]; + gTasks[taskId].data[2] = gBattleAnimArgs[1]; + gTasks[taskId].data[3] = gBattleAnimArgs[2]; + gTasks[taskId].data[4] = gBattleAnimArgs[3]; + } + ++gTasks[taskId].data[0]; + spriteId = gBattlerSpriteIds[gBattleAnimTarget]; + if (!gTasks[taskId].data[4]) + unk = gUnknown_83E5EFC[gTasks[taskId].data[0] % 10]; + else + unk = gUnknown_83E5F0C[gTasks[taskId].data[0] % 10]; + if (gTasks[taskId].data[3] == 1) + gSprites[spriteId].pos2.y = gBattleAnimArgs[1] * unk < 0 ? -(gBattleAnimArgs[1] * unk) : gBattleAnimArgs[1] * unk; + else + gSprites[spriteId].pos2.x = gBattleAnimArgs[1] * unk; + if (gTasks[taskId].data[0] == gTasks[taskId].data[1]) + { + gSprites[spriteId].pos2.x = 0; + gSprites[spriteId].pos2.y = 0; + DestroyAnimVisualTask(taskId); + } +} diff --git a/src/flying.c b/src/flying.c index 8c3ccb52a..59378c2f1 100644 --- a/src/flying.c +++ b/src/flying.c @@ -98,8 +98,8 @@ static const union AffineAnimCmd gUnknown_83E6B64[] = { AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), AFFINEANIMCMD_FRAME(0x28, 0x0, 0, 6), - AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 5), - AFFINEANIMCMD_FRAME(0xFFF0, 0x20, 0, 10), + AFFINEANIMCMD_FRAME(0x0, -0x20, 0, 5), + AFFINEANIMCMD_FRAME(-0x10, 0x20, 0, 10), AFFINEANIMCMD_END, }; @@ -232,9 +232,9 @@ static const union AffineAnimCmd gUnknown_83E6C9C[] = { AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), AFFINEANIMCMD_FRAME(0x28, 0x0, 0, 6), - AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 5), - AFFINEANIMCMD_FRAME(0xFFEC, 0x0, 0, 7), - AFFINEANIMCMD_FRAME(0xFFEC, 0xFFEC, 0, 5), + AFFINEANIMCMD_FRAME(0x0, -0x20, 0, 5), + AFFINEANIMCMD_FRAME(-0x14, 0x0, 0, 7), + AFFINEANIMCMD_FRAME(-0x14, -0x14, 0, 5), AFFINEANIMCMD_END, }; @@ -280,8 +280,8 @@ static const union AffineAnimCmd gUnknown_83E6D14[] = { AFFINEANIMCMD_FRAME(0x10, 0x100, 0, 0), AFFINEANIMCMD_FRAME(0x28, 0x0, 0, 6), - AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 5), - AFFINEANIMCMD_FRAME(0xFFF0, 0x20, 0, 10), + AFFINEANIMCMD_FRAME(0x0, -0x20, 0, 5), + AFFINEANIMCMD_FRAME(-0x10, 0x20, 0, 10), AFFINEANIMCMD_END, }; @@ -306,7 +306,7 @@ static const union AffineAnimCmd gUnknown_83E6D58[] = { AFFINEANIMCMD_FRAME(0x100, 0x0, 0, 0), AFFINEANIMCMD_FRAME(0x0, 0x20, 0, 12), - AFFINEANIMCMD_FRAME(0x0, 0xFFE0, 0, 11), + AFFINEANIMCMD_FRAME(0x0, -0x20, 0, 11), AFFINEANIMCMD_END, }; @@ -995,8 +995,8 @@ static void sub_80B2780(struct Sprite *sprite) InitSpritePosToAnimAttacker(sprite, 0); else InitSpritePosToAnimTarget(sprite, FALSE); - if ((!gBattleAnimArgs[2] && !GetBattlerSide(gBattleAnimAttacker)) - || (gBattleAnimArgs[2] == 1 && !GetBattlerSide(gBattleAnimTarget))) + if ((!gBattleAnimArgs[2] && GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) + || (gBattleAnimArgs[2] == 1 && GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER)) sprite->pos1.x += 8; SeekSpriteAnim(sprite, gBattleAnimArgs[4]); sprite->pos1.x -= 32; @@ -1048,7 +1048,7 @@ static void sub_80B2914(struct Sprite *sprite) { case 0: InitSpritePosToAnimAttacker(sprite, 1); - gSprites[GetAnimBattlerSpriteId(0)].invisible = TRUE; + gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = TRUE; ++sprite->data[0]; break; case 1: @@ -1076,7 +1076,7 @@ static void sub_80B2974(struct Sprite *sprite) sprite->pos2.y -= 10; if (sprite->pos1.y + sprite->pos2.y < -32) { - gSprites[GetAnimBattlerSpriteId(0)].invisible = FALSE; + gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = FALSE; DestroyAnimSprite(sprite); } break; @@ -1089,7 +1089,7 @@ static void sub_80B2A08(struct Sprite *sprite) sprite->data[0] = gBattleAnimArgs[2]; sprite->data[1] = gBattleAnimArgs[3]; sprite->callback = sub_80B2A50; - gSprites[GetAnimBattlerSpriteId(0)].invisible = TRUE; + gSprites[GetAnimBattlerSpriteId(ANIM_ATTACKER)].invisible = TRUE; } static void sub_80B2A50(struct Sprite *sprite) @@ -1275,13 +1275,13 @@ static void sub_80B2E64(u8 taskId) { if (gBattleAnimArgs[0] == 0) { - u8 spriteId = GetAnimBattlerSpriteId(0); + u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); gSprites[spriteId].invisible = TRUE; } else { - u8 spriteId = GetAnimBattlerSpriteId(0); + u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); gSprites[spriteId].invisible = FALSE; } diff --git a/src/ghost.c b/src/ghost.c index fbf452af6..30430309e 100644 --- a/src/ghost.c +++ b/src/ghost.c @@ -50,7 +50,7 @@ static void sub_80B71B0(struct Sprite *sprite); static const union AffineAnimCmd gUnknown_83E75A8[] = { AFFINEANIMCMD_FRAME(0x1E, 0x1E, 10, 5), - AFFINEANIMCMD_FRAME(0xFFE2, 0xFFE2, 10, 5), + AFFINEANIMCMD_FRAME(-0x1E, -0x1E, 10, 5), AFFINEANIMCMD_JUMP(0), }; @@ -342,7 +342,7 @@ void sub_80B54E8(u8 taskId) SetGpuReg(REG_OFFSET_BLDCNT, (BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL)); SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0x10)); - spriteId = GetAnimBattlerSpriteId(0); + spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); PrepareBattlerSpriteForRotScale(spriteId, ST_OAM_OBJ_BLEND); SetSpriteRotScale(spriteId, 128, 128, 0); gSprites[spriteId].invisible = FALSE; @@ -377,7 +377,7 @@ static void sub_80B55C8(u8 taskId) gTasks[taskId].data[1] -= 1; return; } - spriteId = GetAnimBattlerSpriteId(0); + spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); gTasks[taskId].data[0] += 8; if (gTasks[taskId].data[0] <= 0xFF) { @@ -626,7 +626,7 @@ static void sub_80B5AD4(u8 taskId) task->data[1] = 0; task->data[2] = 0; task->data[3] = 16; - task->data[13] = GetAnimBattlerSpriteId(1); + task->data[13] = GetAnimBattlerSpriteId(ANIM_TARGET); task->data[4] = (gSprites[task->data[13]].oam.paletteNum + 16) * 16; if (position == 1) { @@ -711,7 +711,7 @@ static void sub_80B5DCC(u8 taskId) { case 0: gScanlineEffect.state = 3; - task->data[14] = GetAnimBattlerSpriteId(1); + task->data[14] = GetAnimBattlerSpriteId(ANIM_TARGET); if (rank == 1) ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG1_ON); else @@ -1288,7 +1288,7 @@ static void sub_80B6BE4(u8 taskId) task->data[1] = 0; task->data[2] = 0; task->data[3] = 16; - task->data[4] = GetAnimBattlerSpriteId(0); + task->data[4] = GetAnimBattlerSpriteId(ANIM_ATTACKER); task->data[5] = gSprites[task->data[4]].oam.priority; task->data[6] = (gSprites[task->data[4]].oam.paletteNum + 16) << 4; gSprites[task->data[4]].oam.objMode = ST_OAM_OBJ_BLEND; diff --git a/src/ground.c b/src/ground.c index 97f42e5c5..7ab6b6e95 100644 --- a/src/ground.c +++ b/src/ground.c @@ -298,7 +298,7 @@ static void sub_80B8ED4(u8 taskId) switch (task->data[0]) { case 0: - task->data[10] = GetAnimBattlerSpriteId(0); + task->data[10] = GetAnimBattlerSpriteId(ANIM_ATTACKER); task->data[11] = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker); if (task->data[11] == 1) { @@ -360,7 +360,7 @@ static void sub_80B8ED4(u8 taskId) static void sub_80B908C(u8 taskId) { - u8 spriteId = GetAnimBattlerSpriteId(0); + u8 spriteId = GetAnimBattlerSpriteId(ANIM_ATTACKER); gSprites[spriteId].invisible = TRUE; gSprites[spriteId].pos2.x = 0; @@ -391,7 +391,7 @@ static void sub_80B912C(u8 taskId) switch (task->data[0]) { case 0: - task->data[10] = GetAnimBattlerSpriteId(0); + task->data[10] = GetAnimBattlerSpriteId(ANIM_ATTACKER); gSprites[task->data[10]].invisible = FALSE; gSprites[task->data[10]].pos2.x = 0; gSprites[task->data[10]].pos2.y = 160 - gSprites[task->data[10]].pos1.y; @@ -410,7 +410,7 @@ static void sub_80B91B0(u8 taskId) switch (task->data[0]) { case 0: - task->data[10] = GetAnimBattlerSpriteId(0); + task->data[10] = GetAnimBattlerSpriteId(ANIM_ATTACKER); task->data[11] = GetBattlerSpriteBGPriorityRank(gBattleAnimAttacker); if (task->data[11] == 1) task->data[12] = gBattle_BG1_X; diff --git a/src/ice.c b/src/ice.c new file mode 100644 index 000000000..9914a6992 --- /dev/null +++ b/src/ice.c @@ -0,0 +1,1477 @@ +#include "global.h" +#include "battle_anim.h" +#include "bg.h" +#include "field_weather.h" +#include "gpu_regs.h" +#include "graphics.h" +#include "main.h" +#include "palette.h" +#include "random.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" +#include "constants/battle_anim.h" + +struct HailStruct +{ + s32 unk0:10; + s32 unk1:10; + s32 unk2:8; + s32 unk3:4; +}; + +static void sub_80AF108(struct Sprite *sprite); +static void sub_80AF28C(struct Sprite *sprite); +static void AnimIcePunchSwirlingParticle(struct Sprite *sprite); +static void AnimIceBeamParticle(struct Sprite *sprite); +static void AnimIceEffectParticle(struct Sprite *sprite); +static void AnimFlickerIceEffectParticle(struct Sprite *sprite); +static void AnimSwirlingSnowball_Step1(struct Sprite *sprite); +static void AnimSwirlingSnowball_Step2(struct Sprite *sprite); +static void AnimSwirlingSnowball_Step3(struct Sprite *sprite); +static void AnimSwirlingSnowball_End(struct Sprite *sprite); +static void AnimMoveParticleBeyondTarget(struct Sprite *sprite); +static void AnimWiggleParticleTowardsTarget(struct Sprite *sprite); +static void AnimWaveFromCenterOfTarget(struct Sprite *sprite); +static void InitSwirlingFogAnim(struct Sprite *sprite); +static void AnimSwirlingFogAnim(struct Sprite *sprite); +static void AnimThrowMistBall(struct Sprite *sprite); +static void InitPoisonGasCloudAnim(struct Sprite *sprite); +static void MovePoisonGasCloud(struct Sprite *sprite); +static void AnimHailBegin(struct Sprite *sprite); +static void AnimHailContinue(struct Sprite *sprite); +static void InitIceBallAnim(struct Sprite *sprite); +static void AnimThrowIceBall(struct Sprite *sprite); +static void InitIceBallParticle(struct Sprite *sprite); +static void AnimIceBallParticle(struct Sprite *sprite); +static void AnimTask_Haze2(u8 taskId); +static void AnimTask_OverlayFogTiles(u8 taskId); +static void AnimTask_Hail2(u8 taskId); +static bool8 GenerateHailParticle(u8 hailStructId, u8 affineAnimNum, u8 taskId, u8 c); + +static const union AnimCmd gUnknown_83E62C0[] = +{ + ANIMCMD_FRAME(0, 5, .hFlip = TRUE), + ANIMCMD_FRAME(1, 5, .hFlip = TRUE), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E62CC[] = +{ + gUnknown_83E62C0, +}; + +// not used +static const struct SpriteTemplate gUnknown_83E62D0 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83AC9C8, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80AF108, +}; + +static const union AnimCmd gUnknown_83E62E8[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E62F0[] = +{ + ANIMCMD_FRAME(4, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E62F8[] = +{ + ANIMCMD_FRAME(6, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E6300[] = +{ + ANIMCMD_FRAME(7, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E6308[] = +{ + ANIMCMD_FRAME(8, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E6310[] = +{ + ANIMCMD_FRAME(12, 6), + ANIMCMD_FRAME(13, 6), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E631C[] = +{ + gUnknown_83E62E8, +}; + +static const union AnimCmd *const gUnknown_83E6320[] = +{ + gUnknown_83E62F0, +}; + +static const union AnimCmd *const gUnknown_83E6324[] = +{ + gUnknown_83E62F8, +}; + +static const union AnimCmd *const gUnknown_83E6328[] = +{ + gUnknown_83E6300, +}; + +static const union AnimCmd *const gUnknown_83E632C[] = +{ + gUnknown_83E6308, +}; + +static const union AnimCmd *const gUnknown_83E6330[] = +{ + gUnknown_83E6310, +}; + +static const union AffineAnimCmd gUnknown_83E6334[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 40, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const gUnknown_83E6344[] = +{ + gUnknown_83E6334, +}; + +const struct SpriteTemplate gUnknown_83E6348 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83ACBE8, + .anims = gUnknown_83E6320, + .images = NULL, + .affineAnims = gUnknown_83E6344, + .callback = AnimIcePunchSwirlingParticle, +}; + +const struct SpriteTemplate gUnknown_83E6360 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83ACAE8, + .anims = gUnknown_83E6324, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimIcePunchSwirlingParticle, +}; + +static const union AffineAnimCmd gUnknown_83E6378[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, 10, 1), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const gUnknown_83E6388[] = +{ + gUnknown_83E6378, +}; + +const struct SpriteTemplate gUnknown_83E638C = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83ACB88, + .anims = gUnknown_83E6320, + .images = NULL, + .affineAnims = gUnknown_83E6388, + .callback = AnimIceBeamParticle, +}; + +const struct SpriteTemplate gUnknown_83E63A4 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83ACAE8, + .anims = gUnknown_83E6324, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimIceBeamParticle, +}; + +static const union AffineAnimCmd gUnknown_83E63BC[] = +{ + AFFINEANIMCMD_FRAME(0xCE, 0xCE, 0, 0), + AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 10), + AFFINEANIMCMD_FRAME(0x0, 0x0, 0, 6), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E63DC[] = +{ + gUnknown_83E63BC, +}; + +const struct SpriteTemplate gUnknown_83E63E0 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83ACB88, + .anims = gUnknown_83E6320, + .images = NULL, + .affineAnims = gUnknown_83E63DC, + .callback = AnimIceEffectParticle, +}; + +const struct SpriteTemplate gUnknown_83E63F8 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83ACB48, + .anims = gUnknown_83E6324, + .images = NULL, + .affineAnims = gUnknown_83E63DC, + .callback = AnimIceEffectParticle, +}; + +const struct SpriteTemplate gUnknown_83E6410 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83AC9C8, + .anims = gUnknown_83E6328, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSwirlingSnowball_Step1, +}; + +const struct SpriteTemplate gUnknown_83E6428 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83AC9D0, + .anims = gUnknown_83E632C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMoveParticleBeyondTarget, +}; + +const struct SpriteTemplate gUnknown_83E6440 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83AC9C8, + .anims = gUnknown_83E6328, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimMoveParticleBeyondTarget, +}; + +static const union AnimCmd gUnknown_83E6458[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(2, 5), + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(6, 5), + ANIMCMD_FRAME(4, 5), + ANIMCMD_FRAME(2, 5), + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E6478[] = +{ + gUnknown_83E6458, +}; + +const struct SpriteTemplate gUnknown_83E647C = +{ + .tileTag = ANIM_TAG_ICE_SPIKES, + .paletteTag = ANIM_TAG_ICE_SPIKES, + .oam = &gOamData_83ACB28, + .anims = gUnknown_83E6478, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimWaveFromCenterOfTarget, +}; + +static const union AnimCmd gUnknown_83E6494[] = +{ + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(8, 8), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const gUnknown_83E64A0[] = +{ + gUnknown_83E6494, +}; + +const struct SpriteTemplate gUnknown_83E64A4 = +{ + .tileTag = ANIM_TAG_MIST_CLOUD, + .paletteTag = ANIM_TAG_MIST_CLOUD, + .oam = &gOamData_83ACB18, + .anims = gUnknown_83E64A0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = InitSwirlingFogAnim, +}; + +const struct SpriteTemplate gUnknown_83E64BC = +{ + .tileTag = ANIM_TAG_PURPLE_GAS_CLOUD, + .paletteTag = ANIM_TAG_PURPLE_GAS_CLOUD, + .oam = &gOamData_83ACB18, + .anims = gUnknown_83E64A0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = InitSwirlingFogAnim, +}; + +static const u8 gUnknown_83E64D4[] = +{ + 0, 1, 2, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 6, 7, 8, 8, 8, 9, +}; + +const struct SpriteTemplate gUnknown_83E64E8 = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_83AC9D0, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimThrowMistBall, +}; + +static const u8 gUnknown_83E6500[] = +{ + 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, +}; + +const struct SpriteTemplate gUnknown_83E6514 = +{ + .tileTag = ANIM_TAG_PURPLE_GAS_CLOUD, + .paletteTag = ANIM_TAG_PURPLE_GAS_CLOUD, + .oam = &gOamData_83ACB18, + .anims = gUnknown_83E64A0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = InitPoisonGasCloudAnim, +}; + +static const struct HailStruct gUnknown_83E652C[] = +{ + {100, 120, 0, 2}, + {85, 120, 0, 0}, + {242, 120, 1, 1}, + {66, 120, 2, 1}, + {182, 120, 3, 0}, + {60, 120, 0, 2}, + {214, 120, 1, 0}, + {113, 120, 0, 1}, + {210, 120, 3, 1}, + {38, 120, 2, 0}, +}; + +static const union AffineAnimCmd gUnknown_83E6554[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E6564[] = +{ + AFFINEANIMCMD_FRAME(0xF0, 0xF0, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E6574[] = +{ + AFFINEANIMCMD_FRAME(0xE0, 0xE0, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E6584[] = +{ + AFFINEANIMCMD_FRAME(0x150, 0x150, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E6594[] = +{ + gUnknown_83E6554, + gUnknown_83E6564, + gUnknown_83E6574, +}; + +static const union AffineAnimCmd *const gUnknown_83E65A0[] = +{ + gUnknown_83E6584, +}; + +static const struct SpriteTemplate gUnknown_83E65A4 = +{ + .tileTag = ANIM_TAG_HAIL, + .paletteTag = ANIM_TAG_HAIL, + .oam = &gOamData_83ACA30, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E6594, + .callback = AnimHailBegin, +}; + +const struct SpriteTemplate gUnknown_83E65BC = +{ + .tileTag = ANIM_TAG_HAIL, + .paletteTag = ANIM_TAG_HAIL, + .oam = &gOamData_83ACA30, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gUnknown_83E65A0, + .callback = sub_8077350, +}; + +static const union AnimCmd gUnknown_83E65D4[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E65DC[] = +{ + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_FRAME(48, 4), + ANIMCMD_FRAME(64, 4), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E65F0[] = +{ + gUnknown_83E65D4, + gUnknown_83E65DC, +}; + +static const union AffineAnimCmd gUnknown_83E65F8[] = +{ + AFFINEANIMCMD_FRAME(0xE0, 0xE0, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E6608[] = +{ + AFFINEANIMCMD_FRAME(0x118, 0x118, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E6618[] = +{ + AFFINEANIMCMD_FRAME(0x150, 0x150, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E6628[] = +{ + AFFINEANIMCMD_FRAME(0x180, 0x180, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gUnknown_83E6638[] = +{ + AFFINEANIMCMD_FRAME(0x1C0, 0x1C0, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E6648[] = +{ + gUnknown_83E65F8, + gUnknown_83E6608, + gUnknown_83E6618, + gUnknown_83E6628, + gUnknown_83E6638, +}; + +const struct SpriteTemplate gUnknown_83E665C = +{ + .tileTag = ANIM_TAG_ICE_CHUNK, + .paletteTag = ANIM_TAG_ICE_CHUNK, + .oam = &gOamData_83ACA98, + .anims = gUnknown_83E65F0, + .images = NULL, + .affineAnims = gUnknown_83E6648, + .callback = InitIceBallAnim, +}; + +const struct SpriteTemplate gUnknown_83E6674 = +{ + .tileTag = ANIM_TAG_ICE_CRYSTALS, + .paletteTag = ANIM_TAG_ICE_CRYSTALS, + .oam = &gOamData_83AC9C8, + .anims = gUnknown_83E6324, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = InitIceBallParticle, +}; + +// not used +static void sub_80AF108(struct Sprite *sprite) +{ + s16 targetX, targetY, attackerX, attackerY; + + sprite->oam.tileNum += 7; + targetX = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + targetY = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + attackerX = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + attackerY = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = gBattleAnimArgs[0] + attackerX; + sprite->data[2] = gBattleAnimArgs[2] + targetX; + sprite->data[3] = gBattleAnimArgs[1] + attackerY; + sprite->data[4] = gBattleAnimArgs[3] + targetY; + sub_8074C80(sprite); + // won't match with while loop + for (; (targetX >= -32 && targetX <= 272) && (targetY >= -32 && targetY <= 192); targetX += sprite->data[1], targetY += sprite->data[2]) + ; + sprite->data[1] = -sprite->data[1]; + sprite->data[2] = -sprite->data[2]; + for (; (attackerX >= -32 && attackerX <= 272) && (attackerY >= -32 && attackerY <= 192); attackerX += sprite->data[1], attackerY += sprite->data[2]) + ; + sprite->pos1.x = attackerX; + sprite->pos1.y = attackerY; + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = attackerX; + sprite->data[2] = targetX; + sprite->data[3] = attackerY; + sprite->data[4] = targetY; + sub_8074C80(sprite); + sprite->data[3] = gBattleAnimArgs[5]; + sprite->data[4] = gBattleAnimArgs[6]; + sprite->callback = sub_80AF28C; +} + +// not used +static void sub_80AF28C(struct Sprite *sprite) +{ + if (sprite->data[0] != 0) + { + sprite->data[5] += sprite->data[1]; + sprite->data[6] += sprite->data[2]; + sprite->pos2.x = sprite->data[5]; + sprite->pos2.y = sprite->data[6]; + sprite->pos2.x += Sin(sprite->data[7], sprite->data[3]); + sprite->pos2.y += Sin(sprite->data[7], sprite->data[3]); + sprite->data[7] = (sprite->data[7] + sprite->data[4]) & 0xFF; + --sprite->data[0]; + } + else + { + DestroyAnimSprite(sprite); + } +} + +// Animates the swirling ice crystals in Ice Punch. +// arg 0: initial position angle around circle (0-256) +static void AnimIcePunchSwirlingParticle(struct Sprite *sprite) +{ + sprite->data[0] = gBattleAnimArgs[0]; + sprite->data[1] = 60; + sprite->data[2] = 9; + sprite->data[3] = 30; + sprite->data[4] = -512; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = TranslateSpriteInGrowingCircleOverDuration; + sprite->callback(sprite); +} + +// Animates the ice particles in Ice Beam. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x offset +// arg 3: target y offset +// arg 4: duration +static void AnimIceBeamParticle(struct Sprite *sprite) +{ + InitSpritePosToAnimAttacker(sprite, TRUE); + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->data[2] -= gBattleAnimArgs[2]; + else + sprite->data[2] += gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; + sprite->data[0] = gBattleAnimArgs[4]; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + sprite->callback = StartAnimLinearTranslation; +} + +// Animates the ice crystals at the end of Ice Punch, Ice Beam, Tri Attack, +// Weather Ball (Hail), Blizzard, and Powder Snow. +// arg 0: target x offset +// arg 1: target y offset +// arg 2: ??? unknown boolean +static void AnimIceEffectParticle(struct Sprite *sprite) +{ + if (gBattleAnimArgs[2] == 0) + { + InitSpritePosToAnimTarget(sprite, TRUE); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->pos1.x, &sprite->pos1.y); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + } + StoreSpriteCallbackInData6(sprite, AnimFlickerIceEffectParticle); + sprite->callback = RunStoredCallbackWhenAffineAnimEnds; +} + +static void AnimFlickerIceEffectParticle(struct Sprite *sprite) +{ + sprite->invisible ^= 1; + if (++sprite->data[0] == 20) + DestroySpriteAndMatrix(sprite); +} + +// Animates the small snowballs that swirl around the target in Blizzard and Icy Wind. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x offset +// arg 3: target y offset +// arg 4: particle speed +// arg 5: multiple targets? (boolean) +static void AnimSwirlingSnowball_Step1(struct Sprite *sprite) +{ + s32 i; + s16 tempDataHolder[8]; + + InitSpritePosToAnimAttacker(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + if (!gBattleAnimArgs[5]) + { + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->data[2], &sprite->data[4]); + } + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->data[2] -= gBattleAnimArgs[2]; + else + sprite->data[2] += gBattleAnimArgs[2]; + for (i = 0; i < 8; ++i) + tempDataHolder[i] = sprite->data[i]; + InitAnimFastLinearTranslationWithSpeed(sprite); + sprite->data[1] ^= 1; + sprite->data[2] ^= 1; + while (1) + { + sprite->data[0] = 1; + AnimFastTranslateLinear(sprite); + if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 + || sprite->pos1.y + sprite->pos2.y > 160 + || sprite->pos1.y + sprite->pos2.y < -16) + break; + } + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.x = sprite->pos2.y = 0; + for (i = 0; i < 8; ++i) + sprite->data[i] = tempDataHolder[i]; + sprite->callback = sub_8075830; + StoreSpriteCallbackInData6(sprite, AnimSwirlingSnowball_Step2); +} + +static void AnimSwirlingSnowball_Step2(struct Sprite *sprite) +{ + s16 tempVar; + + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + sprite->data[0] = 128; + tempVar = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? 20 : -20; + sprite->data[3] = Sin(sprite->data[0], tempVar); + sprite->data[4] = Cos(sprite->data[0], 0xF); + sprite->data[5] = 0; + sprite->callback = AnimSwirlingSnowball_Step3; + sprite->callback(sprite); +} + +static void AnimSwirlingSnowball_Step3(struct Sprite *sprite) +{ + s16 tempVar = GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER ? 20 : -20; + + if (sprite->data[5] <= 31) + { + sprite->pos2.x = Sin(sprite->data[0], tempVar) - sprite->data[3]; + sprite->pos2.y = Cos(sprite->data[0], 15) - sprite->data[4]; + sprite->data[0] = (sprite->data[0] + 16) & 0xFF; + sprite->data[5] += 1; + } + else + { + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.x = sprite->pos2.y = 0; + sprite->data[3] = sprite->data[4] = 0; + sprite->callback = AnimSwirlingSnowball_End; + } +} + +static void AnimSwirlingSnowball_End(struct Sprite *sprite) +{ + sprite->data[0] = 1; + AnimFastTranslateLinear(sprite); + if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 + || sprite->pos1.y + sprite->pos2.y > 256 + || sprite->pos1.y + sprite->pos2.y < -16) + DestroyAnimSprite(sprite); +} + +// Moves particles towards the target mon and off the screen. Used to animate +// the large snowballs in Blizzard and the small snowballs in Powder Snow. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x offset +// arg 3: target y offset +// arg 4: speed +// arg 5: wave amplitude +// arg 6: wave frequency +// arg 7: multiple targets? (boolean) +static void AnimMoveParticleBeyondTarget(struct Sprite *sprite) +{ + s32 i; + s16 tempDataHolder[8]; + + InitSpritePosToAnimAttacker(sprite, TRUE); + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[1] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + if (!gBattleAnimArgs[7]) + { + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 1, &sprite->data[2], &sprite->data[4]); + } + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->data[2] -= gBattleAnimArgs[2]; + else + sprite->data[2] += gBattleAnimArgs[2]; + sprite->data[4] += gBattleAnimArgs[3]; + InitAnimFastLinearTranslationWithSpeed(sprite); + for (i = 0; i < 8; ++i) + tempDataHolder[i] = sprite->data[i]; + sprite->data[1] ^= 1; + sprite->data[2] ^= 1; + while (1) + { + sprite->data[0] = 1; + AnimFastTranslateLinear(sprite); + if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 + || sprite->pos1.y + sprite->pos2.y > 160 + || sprite->pos1.y + sprite->pos2.y < -16) + break; + } + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.y = 0; + sprite->pos2.x = 0; + for (i = 0; i < 8; ++i) + sprite->data[i] = tempDataHolder[i]; + sprite->data[5] = gBattleAnimArgs[5]; + sprite->data[6] = gBattleAnimArgs[6]; + sprite->callback = AnimWiggleParticleTowardsTarget; +} + +// Moves particles in a sine wave towards the target. +static void AnimWiggleParticleTowardsTarget(struct Sprite *sprite) +{ + AnimFastTranslateLinear(sprite); + if (sprite->data[0] == 0) + sprite->data[0] = 1; + sprite->pos2.y += Sin(sprite->data[7], sprite->data[5]); + sprite->data[7] = (sprite->data[7] + sprite->data[6]) & 0xFF; + if (sprite->data[0] == 1) + { + if ((u32)(sprite->pos1.x + sprite->pos2.x + 16) > 272 + || sprite->pos1.y + sprite->pos2.y > 160 + || sprite->pos1.y + sprite->pos2.y < -16) + DestroyAnimSprite(sprite); + } +} + +// Animates the ice pilar wave used by Icy Wind. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: ??? unknown boolean +static void AnimWaveFromCenterOfTarget(struct Sprite *sprite) +{ + if (sprite->data[0] == 0) + { + if (gBattleAnimArgs[2] == 0) + { + InitSpritePosToAnimTarget(sprite, FALSE); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + } + ++sprite->data[0]; + } + else + { + if (sprite->animEnded) + DestroyAnimSprite(sprite); + } +} + +// Animates the fog that swirls around the mon in Mist and Smog. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: change in y pixels per rotation +// arg 3: duration +// arg 4: animate on opponent? (boolean) +// arg 5: ??? unknown boolean +static void InitSwirlingFogAnim(struct Sprite *sprite) +{ + s16 tempVar; + u8 battler; + + if (gBattleAnimArgs[4] == 0) + { + if (gBattleAnimArgs[5] == 0) + { + InitSpritePosToAnimAttacker(sprite, FALSE); + } + else + { + SetAverageBattlerPositions(gBattleAnimAttacker, 0, &sprite->pos1.x, &sprite->pos1.y); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + } + battler = gBattleAnimAttacker; + } + else + { + if (gBattleAnimArgs[5] == 0) + { + InitSpritePosToAnimTarget(sprite, FALSE); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, 0, &sprite->pos1.x, &sprite->pos1.y); + if (GetBattlerSide(gBattleAnimTarget) != B_SIDE_PLAYER) + sprite->pos1.x -= gBattleAnimArgs[0]; + else + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + } + battler = gBattleAnimTarget; + } + sprite->data[7] = battler; + if (gBattleAnimArgs[5] == 0 || !IsDoubleBattle()) + tempVar = 0x20; + else + tempVar = 0x40; + sprite->data[6] = tempVar; + if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) + sprite->pos1.y += 8; + sprite->data[0] = gBattleAnimArgs[3]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = sprite->pos1.x; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[2]; + InitAnimLinearTranslation(sprite); + sprite->data[5] = 64; + sprite->callback = AnimSwirlingFogAnim; + sprite->callback(sprite); +} + +// Animates swirling fog initialized by InitSwirlingFogAnim. +static void AnimSwirlingFogAnim(struct Sprite *sprite) +{ + if (!AnimTranslateLinear(sprite)) + { + sprite->pos2.x += Sin(sprite->data[5], sprite->data[6]); + sprite->pos2.y += Cos(sprite->data[5], -6); + if ((u16)(sprite->data[5] - 64) <= 0x7F) + sprite->oam.priority = GetBattlerSpriteBGPriority(sprite->data[7]); + else + sprite->oam.priority = GetBattlerSpriteBGPriority(sprite->data[7]) + 1; + sprite->data[5] = (sprite->data[5] + 3) & 0xFF; + } + else + { + DestroyAnimSprite(sprite); + } +} + +// Fades mons to black and places foggy overlay in Haze. +void AnimTask_Haze1(u8 taskId) +{ + struct BattleAnimBgData animBg; + + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0); + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); + SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); + sub_80752A0(&animBg); + LoadBgTiles(animBg.bgId, gWeatherFog1Tiles, 0x800, animBg.tilesOffset); + AnimLoadCompressedBgTilemap(animBg.bgId, gBattleAnimFogTilemap); + LoadPalette(&gUnknown_83C2CE0, animBg.paletteId * 16, 32); + if (IsContest()) + sub_80730C0(animBg.paletteId, animBg.bgTilemap, 0, 0); + gTasks[taskId].func = AnimTask_Haze2; +} + +static void AnimTask_Haze2(u8 taskId) +{ + struct BattleAnimBgData animBg; + + gBattle_BG1_X += -1; + switch (gTasks[taskId].data[12]) + { + case 0: + if (++gTasks[taskId].data[10] == 4) + { + gTasks[taskId].data[10] = 0; + ++gTasks[taskId].data[9]; + gTasks[taskId].data[11] = gUnknown_83E64D4[gTasks[taskId].data[9]]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); + if (gTasks[taskId].data[11] == 9) + { + ++gTasks[taskId].data[12]; + gTasks[taskId].data[11] = 0; + } + } + break; + case 1: + if (++gTasks[taskId].data[11] == 0x51) + { + gTasks[taskId].data[11] = 9; + ++gTasks[taskId].data[12]; + } + break; + case 2: + if (++gTasks[taskId].data[10] == 4) + { + gTasks[taskId].data[10] = 0; + --gTasks[taskId].data[11]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); + if (gTasks[taskId].data[11] == 0) + { + ++gTasks[taskId].data[12]; + gTasks[taskId].data[11] = 0; + } + } + break; + case 3: + sub_80752A0(&animBg); + sub_8075358(1); + sub_8075358(2); + ++gTasks[taskId].data[12]; + // fall through + case 4: + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + DestroyAnimVisualTask(taskId); + break; + } +} + +// Throws the ball in Mist Ball. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: targey x offset +// arg 3: target y offset +// arg 4: duration +// arg 5: ??? unknown (seems to vibrate target mon somehow) +static void AnimThrowMistBall(struct Sprite *sprite) +{ + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + sprite->callback = TranslateAnimSpriteToTargetMonLocation; +} + +// Displays misty background in Mist Ball. +void AnimTask_LoadMistTiles(u8 taskId) +{ + struct BattleAnimBgData animBg; + + SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_ALL); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 16)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + SetAnimBgAttribute(1, BG_ANIM_SCREEN_SIZE, 0); + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 1); + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + SetGpuReg(REG_OFFSET_BG1HOFS, gBattle_BG1_X); + SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y); + sub_80752A0(&animBg); + LoadBgTiles(animBg.bgId, gWeatherFog1Tiles, 0x800, animBg.tilesOffset); + AnimLoadCompressedBgTilemap(animBg.bgId, gBattleAnimFogTilemap); + LoadPalette(&gUnknown_83C2CE0, animBg.paletteId * 16, 32); + if (IsContest()) + sub_80730C0(animBg.paletteId, animBg.bgTilemap, 0, 0); + gTasks[taskId].data[15] = -1; + gTasks[taskId].func = AnimTask_OverlayFogTiles; +} + +static void AnimTask_OverlayFogTiles(u8 taskId) +{ + struct BattleAnimBgData animBg; + + gBattle_BG1_X += gTasks[taskId].data[15]; + switch (gTasks[taskId].data[12]) + { + case 0: + gTasks[taskId].data[9] += 1; + gTasks[taskId].data[11] = gUnknown_83E6500[gTasks[taskId].data[9]]; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 17 - gTasks[taskId].data[11])); + if (gTasks[taskId].data[11] == 5) + { + ++gTasks[taskId].data[12]; + gTasks[taskId].data[11] = 0; + } + break; + case 1: + if (++gTasks[taskId].data[11] == 0x51) + { + gTasks[taskId].data[11] = 5; + ++gTasks[taskId].data[12]; + } + break; + case 2: + if (++gTasks[taskId].data[10] == 4) + { + gTasks[taskId].data[10] = 0; + gTasks[taskId].data[11] -= 1; + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(gTasks[taskId].data[11], 16 - gTasks[taskId].data[11])); + if (gTasks[taskId].data[11] == 0) + { + ++gTasks[taskId].data[12]; + gTasks[taskId].data[11] = 0; + } + } + break; + case 3: + sub_80752A0(&animBg); + sub_8075358(1); + sub_8075358(2); + ++gTasks[taskId].data[12]; + // fall through + case 4: + if (!IsContest()) + SetAnimBgAttribute(1, BG_ANIM_CHAR_BASE_BLOCK, 0); + gBattle_BG1_X = 0; + gBattle_BG1_Y = 0; + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); + SetAnimBgAttribute(1, BG_ANIM_PRIORITY, 1); + DestroyAnimVisualTask(taskId); + break; + } +} + +// Initializes gas clouds in the Poison Gas animation. +// arg 0: duration +// arg 1: ? target x offset +// arg 2: ? target y offset +// arg 3: ? swirl start x +// arg 4: ? swirl start y +// arg 5: ??? unknown +// arg 6: ??? unknown +// arg 7: ??? unknown boolean +static void InitPoisonGasCloudAnim(struct Sprite *sprite) +{ + sprite->data[0] = gBattleAnimArgs[0]; + if (GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2) < GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2)) + sprite->data[7] = 0x8000; + if ((gBattlerPositions[gBattleAnimTarget] & BIT_SIDE) == B_SIDE_PLAYER) + { + gBattleAnimArgs[1] = -gBattleAnimArgs[1]; + gBattleAnimArgs[3] = -gBattleAnimArgs[3]; + if ((sprite->data[7] & 0x8000) && (gBattlerPositions[gBattleAnimAttacker] & BIT_SIDE) == B_SIDE_PLAYER) + sprite->subpriority = gSprites[GetAnimBattlerSpriteId(ANIM_TARGET)].subpriority + 1; + sprite->data[6] = 1; + } + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->pos1.y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + if (gBattleAnimArgs[7]) + { + sprite->data[1] = sprite->pos1.x + gBattleAnimArgs[1]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[3]; + sprite->data[3] = sprite->pos1.y + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[4]; + sprite->data[7] |= GetBattlerSpriteBGPriority(gBattleAnimTarget) << 8; + } + else + { + sprite->data[1] = sprite->pos1.x + gBattleAnimArgs[1]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X) + gBattleAnimArgs[3]; + sprite->data[3] = sprite->pos1.y + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y) + gBattleAnimArgs[4]; + sprite->data[7] |= GetBattlerSpriteBGPriority(gBattleAnimTarget) << 8; + } + if (IsContest()) + { + sprite->data[6] = 1; + sprite->subpriority = 0x80; + } + InitAnimLinearTranslation(sprite); + sprite->callback = MovePoisonGasCloud; +} + +static void MovePoisonGasCloud(struct Sprite *sprite) +{ + s32 value; + + switch (sprite->data[7] & 0xFF) + { + case 0: + AnimTranslateLinear(sprite); + value = gSineTable[sprite->data[5]]; + sprite->pos2.x += value >> 4; + if (sprite->data[6]) + sprite->data[5] = (sprite->data[5] - 8) & 0xFF; + else + sprite->data[5] = (sprite->data[5] + 8) & 0xFF; + if (sprite->data[0] <= 0) + { + sprite->data[0] = 80; + sprite->pos1.x = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X); + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = sprite->pos1.x; + sprite->pos1.y += sprite->pos2.y; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = sprite->pos1.y + 29; + ++sprite->data[7]; + if (IsContest()) + sprite->data[5] = 80; + else if (GET_BATTLER_SIDE2(gBattleAnimTarget) != B_SIDE_PLAYER) + sprite->data[5] = 204; + else + sprite->data[5] = 80; + sprite->pos2.y = 0; + value = gSineTable[sprite->data[5]]; + sprite->pos2.x = value >> 3; + sprite->data[5] = (sprite->data[5] + 2) & 0xFF; + InitAnimLinearTranslation(sprite); + } + break; + case 1: + AnimTranslateLinear(sprite); + value = gSineTable[sprite->data[5]]; + sprite->pos2.x += value >> 3; + sprite->pos2.y += (gSineTable[sprite->data[5] + 0x40] * -3) >> 8; + if (!IsContest()) + { + u16 var0 = sprite->data[5] - 0x40; + + if (var0 <= 0x7F) + sprite->oam.priority = sprite->data[7] >> 8; + else + sprite->oam.priority = (sprite->data[7] >> 8) + 1; + sprite->data[5] = (sprite->data[5] + 4) & 0xFF; + } + else + { + u16 var0 = sprite->data[5] - 0x40; + + if (var0 <= 0x7F) + sprite->subpriority = 128; + else + sprite->subpriority = 140; + sprite->data[5] = (sprite->data[5] - 4) & 0xFF; + } + if (sprite->data[0] <= 0) + { + sprite->data[0] = 0x300; + sprite->data[1] = sprite->pos1.x += sprite->pos2.x; + sprite->data[3] = sprite->pos1.y += sprite->pos2.y; + sprite->data[4] = sprite->pos1.y + 4; + if (IsContest()) + sprite->data[2] = -0x10; + else if (GET_BATTLER_SIDE2(gBattleAnimTarget) != B_SIDE_PLAYER) + sprite->data[2] = 0x100; + else + sprite->data[2] = -0x10; + ++sprite->data[7]; + sprite->pos2.x = sprite->pos2.y = 0; + sub_8075678(sprite); + } + break; + case 2: + if (AnimTranslateLinear(sprite)) + { + if (sprite->oam.affineMode & 1) + { + FreeOamMatrix(sprite->oam.matrixNum); + sprite->oam.affineMode = ST_OAM_AFFINE_OFF; + } + DestroySprite(sprite); + --gAnimVisualTaskCount; + } + break; + } +} + +// Creates Hail. +void AnimTask_Hail1(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->func = AnimTask_Hail2; +} + +static void AnimTask_Hail2(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + if (++task->data[4] > 2) + { + task->data[4] = 0; + task->data[5] = 0; + task->data[2] = 0; + ++task->data[0]; + } + break; + case 1: + if (task->data[5] == 0) + { + if (GenerateHailParticle(task->data[3], task->data[2], taskId, 1)) + ++task->data[1]; + if (++task->data[2] == 3) + { + if (++task->data[3] == 10) + ++task->data[0]; + else + --task->data[0]; + } + else + { + task->data[5] = 1; + } + } + else + { + --task->data[5]; + } + break; + case 2: + if (task->data[1] == 0) + DestroyAnimVisualTask(taskId); + break; + } +} + +static bool8 GenerateHailParticle(u8 hailStructId, u8 affineAnimNum, u8 taskId, u8 c) +{ + u8 id; + s16 battlerX, battlerY; + s16 spriteX; + bool8 possibleBool = FALSE; + s8 unk = gUnknown_83E652C[hailStructId].unk3; + + if (unk != 2) + { + id = GetBattlerAtPosition(gUnknown_83E652C[hailStructId].unk2); + if (IsBattlerSpriteVisible(id)) + { + possibleBool = TRUE; + battlerX = GetBattlerSpriteCoord(id, BATTLER_COORD_X_2); + battlerY = GetBattlerSpriteCoord(id, BATTLER_COORD_Y_PIC_OFFSET); + switch (unk) + { + case 0: + battlerX -= GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_WIDTH) / 6; + battlerY -= GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_HEIGHT) / 6; + break; + case 1: + battlerX += GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_WIDTH) / 6; + battlerY += GetBattlerSpriteCoordAttr(id, BATTLER_COORD_ATTR_HEIGHT) / 6; + break; + } + } + else + { + battlerX = (gUnknown_83E652C[hailStructId].unk0); + battlerY = (gUnknown_83E652C[hailStructId].unk1); + } + } + else + { + battlerX = (gUnknown_83E652C[hailStructId].unk0); + battlerY = (gUnknown_83E652C[hailStructId].unk1); + } + spriteX = battlerX - ((battlerY + 8) / 2); + id = CreateSprite(&gUnknown_83E65A4, spriteX, -8, 18); + if (id == MAX_SPRITES) + { + return FALSE; + } + else + { + StartSpriteAffineAnim(&gSprites[id], affineAnimNum); + gSprites[id].data[0] = possibleBool; + gSprites[id].data[3] = battlerX; + gSprites[id].data[4] = battlerY; + gSprites[id].data[5] = affineAnimNum; + gSprites[id].data[6] = taskId; + gSprites[id].data[7] = c; + return TRUE; + } +} + +static void AnimHailBegin(struct Sprite *sprite) +{ + u8 spriteId; + + sprite->pos1.x += 4; + sprite->pos1.y += 8; + if (sprite->pos1.x < sprite->data[3] && sprite->pos1.y < sprite->data[4]) + return; + if (sprite->data[0] == 1 && sprite->data[5] == 0) + { + spriteId = CreateSprite(&gUnknown_83E63E0, sprite->data[3], sprite->data[4], sprite->subpriority); + sprite->data[0] = spriteId; + if (spriteId != 64) + { + gSprites[sprite->data[0]].callback = AnimHailContinue; + gSprites[sprite->data[0]].data[6] = sprite->data[6]; + gSprites[sprite->data[0]].data[7] = sprite->data[7]; + } + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } + else + { + --gTasks[sprite->data[6]].data[sprite->data[7]]; + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } +} + +static void AnimHailContinue(struct Sprite *sprite) +{ + if (++sprite->data[0] == 20) + { + --gTasks[sprite->data[6]].data[sprite->data[7]]; + FreeOamMatrix(sprite->oam.matrixNum); + DestroySprite(sprite); + } +} + +// Initializes the animation for Ice Ball. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: target x offset +// arg 3: target y offset +// arg 4: duration +// arg 5: arc height (negative) +static void InitIceBallAnim(struct Sprite *sprite) +{ + u8 animNum = gAnimDisableStructPtr->rolloutTimerStartValue - gAnimDisableStructPtr->rolloutTimer - 1; + + if (animNum > 4) + animNum = 4; + StartSpriteAffineAnim(sprite, animNum); + InitSpritePosToAnimAttacker(sprite, 1); + sprite->data[0] = gBattleAnimArgs[4]; + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; + sprite->data[5] = gBattleAnimArgs[5]; + InitAnimArcTranslation(sprite); + sprite->callback = AnimThrowIceBall; +} + +// Throws the ball of ice in Ice Ball. +static void AnimThrowIceBall(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + { + StartSpriteAnim(sprite, 1); + sprite->callback = RunStoredCallbackWhenAnimEnds; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + } +} + +// Initializes the particles that scatter at the end of the Ice Ball animation. +static void InitIceBallParticle(struct Sprite *sprite) +{ + s16 randA, randB; + + sprite->oam.tileNum += 8; + InitSpritePosToAnimTarget(sprite, TRUE); + randA = (Random() & 0xFF) + 256; + randB = Random() & 0x1FF; + if (randB > 0xFF) + randB = 256 - randB; + sprite->data[1] = randA; + sprite->data[2] = randB; + sprite->callback = AnimIceBallParticle; +} + +// Animates the particles created by InitIceBallParticle. +static void AnimIceBallParticle(struct Sprite *sprite) +{ + sprite->data[3] += sprite->data[1]; + sprite->data[4] += sprite->data[2]; + if (sprite->data[1] & 1) + sprite->pos2.x = -(sprite->data[3] >> 8); + else + sprite->pos2.x = sprite->data[3] >> 8; + sprite->pos2.y = sprite->data[4] >> 8; + if (++sprite->data[0] == 21) + DestroyAnimSprite(sprite); +} + +// Counter for Ice Ball. +void AnimTask_GetRolloutCounter(u8 taskId) +{ + u8 arg = gBattleAnimArgs[0]; + + gBattleAnimArgs[arg] = gAnimDisableStructPtr->rolloutTimerStartValue - gAnimDisableStructPtr->rolloutTimer - 1; + DestroyAnimVisualTask(taskId); +} diff --git a/src/poison.c b/src/poison.c new file mode 100644 index 000000000..004e9aa98 --- /dev/null +++ b/src/poison.c @@ -0,0 +1,298 @@ +#include "global.h" +#include "battle_anim.h" +#include "trig.h" + +static void sub_80B1620(struct Sprite *sprite); +static void sub_80B16A0(struct Sprite *sprite); +static void sub_80B1744(struct Sprite *sprite); +static void sub_80B17C4(struct Sprite *sprite); +static void AnimBubbleEffect(struct Sprite *sprite); +static void sub_80B1684(struct Sprite *sprite); +static void sub_80B1728(struct Sprite *sprite); +static void sub_80B1798(struct Sprite *sprite); +static void AnimBubbleEffectStep(struct Sprite *sprite); + +static const union AnimCmd gUnknown_83E6994[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_FRAME(8, 5), + ANIMCMD_FRAME(16, 5), + ANIMCMD_FRAME(24, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E69A8[] = +{ + gUnknown_83E6994, +}; + +const struct SpriteTemplate gUnknown_83E69AC = +{ + .tileTag = ANIM_TAG_TOXIC_BUBBLE, + .paletteTag = ANIM_TAG_TOXIC_BUBBLE, + .oam = &gOamData_83ACA18, + .anims = gUnknown_83E69A8, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = AnimSpriteOnMonPos, +}; + +static const union AnimCmd gUnknown_83E69C4[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E69CC[] = +{ + ANIMCMD_FRAME(4, 1), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_83E69D4[] = +{ + ANIMCMD_FRAME(8, 1), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_83E69DC[] = +{ + gUnknown_83E69C4, +}; + +static const union AnimCmd *const gUnknown_83E69E0[] = +{ + gUnknown_83E69CC, +}; + +static const union AnimCmd *const gUnknown_83E69E4[] = +{ + gUnknown_83E69D4, +}; + +static const union AffineAnimCmd gUnknown_83E69E8[] = +{ + AFFINEANIMCMD_FRAME(0x160, 0x160, 0, 0), + AFFINEANIMCMD_FRAME(-0xA, -0xA, 0, 10), + AFFINEANIMCMD_FRAME(0xA, 0xA, 0, 10), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd gUnknown_83E6A08[] = +{ + AFFINEANIMCMD_FRAME(0xEC, 0xEC, 0, 0), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E6A18[] = +{ + gUnknown_83E69E8, +}; + +static const union AffineAnimCmd *const gUnknown_83E6A1C[] = +{ + gUnknown_83E6A08, +}; + +const struct SpriteTemplate gUnknown_83E6A20 = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_83ACA90, + .anims = gUnknown_83E69DC, + .images = NULL, + .affineAnims = gUnknown_83E6A18, + .callback = sub_80B1620, +}; + +const struct SpriteTemplate gUnknown_83E6A38 = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_83ACA90, + .anims = gUnknown_83E69DC, + .images = NULL, + .affineAnims = gUnknown_83E6A18, + .callback = sub_80B16A0, +}; + +const struct SpriteTemplate gUnknown_83E6A50 = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_83ACA30, + .anims = gUnknown_83E69E4, + .images = NULL, + .affineAnims = gUnknown_83E6A1C, + .callback = sub_80B1744, +}; + +static const union AffineAnimCmd gUnknown_83E6A68[] = +{ + AFFINEANIMCMD_FRAME(-0x10, 0x10, 0, 6), + AFFINEANIMCMD_FRAME(0x10, -0x10, 0, 6), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const gUnknown_83E6A80[] = +{ + gUnknown_83E6A68, +}; + +const struct SpriteTemplate gUnknown_83E6A84 = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_83ACA90, + .anims = gUnknown_83E69E0, + .images = NULL, + .affineAnims = gUnknown_83E6A80, + .callback = sub_80B17C4, +}; + +static const union AffineAnimCmd gUnknown_83E6A9C[] = +{ + AFFINEANIMCMD_FRAME(0x9C, 0x9C, 0, 0), + AFFINEANIMCMD_FRAME(0x5, 0x5, 0, 20), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gUnknown_83E6AB4[] = +{ + gUnknown_83E6A9C, +}; + +const struct SpriteTemplate gPoisonBubbleSpriteTemplate = +{ + .tileTag = ANIM_TAG_POISON_BUBBLE, + .paletteTag = ANIM_TAG_POISON_BUBBLE, + .oam = &gOamData_83ACA30, + .anims = gUnknown_83E69DC, + .images = NULL, + .affineAnims = gUnknown_83E6AB4, + .callback = AnimBubbleEffect, +}; + +const struct SpriteTemplate gWaterBubbleSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_SMALL_BUBBLES, + .oam = &gOamData_83ACB50, + .anims = gUnknown_83E5A78, + .images = NULL, + .affineAnims = gUnknown_83E6AB4, + .callback = AnimBubbleEffect, +}; + +static void sub_80B1620(struct Sprite *sprite) +{ + if (!gBattleAnimArgs[3]) + StartSpriteAnim(sprite, 2); + InitSpritePosToAnimAttacker(sprite, 1); + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, 2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, 3); + sprite->data[5] = -30; + InitAnimArcTranslation(sprite); + sprite->callback = sub_80B1684; +} + +static void sub_80B1684(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + DestroyAnimSprite(sprite); +} + +static void sub_80B16A0(struct Sprite *sprite) +{ + s16 l1, l2; + + if (!gBattleAnimArgs[3]) + StartSpriteAnim(sprite, 2); + InitSpritePosToAnimAttacker(sprite, 1); + SetAverageBattlerPositions(gBattleAnimTarget, 1, &l1, &l2); + if (GetBattlerSide(gBattleAnimAttacker)) + gBattleAnimArgs[4] = -gBattleAnimArgs[4]; + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[2] = l1 + gBattleAnimArgs[4]; + sprite->data[4] = l2 + gBattleAnimArgs[5]; + sprite->data[5] = -30; + InitAnimArcTranslation(sprite); + sprite->callback = sub_80B1728; +} + +static void sub_80B1728(struct Sprite *sprite) +{ + if (TranslateAnimHorizontalArc(sprite)) + DestroyAnimSprite(sprite); +} + +static void sub_80B1744(struct Sprite *sprite) +{ + sprite->data[0] = gBattleAnimArgs[2]; + sprite->data[1] = sprite->pos1.x; + sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[0]; + sprite->data[3] = sprite->pos1.y; + sprite->data[4] = sprite->pos1.y + gBattleAnimArgs[1]; + InitSpriteDataForLinearTranslation(sprite); + sprite->data[5] = sprite->data[1] / gBattleAnimArgs[2]; + sprite->data[6] = sprite->data[2] / gBattleAnimArgs[2]; + sprite->callback = sub_80B1798; +} + +static void sub_80B1798(struct Sprite *sprite) +{ + TranslateSpriteLinearFixedPoint(sprite); + sprite->data[1] -= sprite->data[5]; + sprite->data[2] -= sprite->data[6]; + if (!sprite->data[0]) + DestroyAnimSprite(sprite); +} + +static void sub_80B17C4(struct Sprite *sprite) +{ + SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->pos1.x, &sprite->pos1.y); + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[2] = sprite->pos1.x + gBattleAnimArgs[2]; + sprite->data[4] = sprite->pos1.y + sprite->data[0]; + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); +} + +// Animates a bubble by rising upward, swaying side to side, and +// enlarging the sprite. This is used as an after-effect by poison-type +// moves, along with MOVE_BUBBLE, and MOVE_BUBBLEBEAM. +// arg 0: initial x pixel offset +// arg 1: initial y pixel offset +// arg 2: 0 = single-target, 1 = multi-target +static void AnimBubbleEffect(struct Sprite *sprite) +{ + if (!gBattleAnimArgs[2]) + { + InitSpritePosToAnimTarget(sprite, TRUE); + } + else + { + SetAverageBattlerPositions(gBattleAnimTarget, TRUE, &sprite->pos1.x, &sprite->pos1.y); + + if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER) + gBattleAnimArgs[0] = -gBattleAnimArgs[0]; + sprite->pos1.x += gBattleAnimArgs[0]; + sprite->pos1.y += gBattleAnimArgs[1]; + } + sprite->callback = AnimBubbleEffectStep; +} + +static void AnimBubbleEffectStep(struct Sprite *sprite) +{ + sprite->data[0] = (sprite->data[0] + 0xB) & 0xFF; + sprite->pos2.x = Sin(sprite->data[0], 4); + sprite->data[1] += 0x30; + sprite->pos2.y = -(sprite->data[1] >> 8); + if (sprite->affineAnimEnded) + DestroyAnimSprite(sprite); +} diff --git a/src/pokemon.c b/src/pokemon.c index c4ae0c4da..57633dbad 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -2365,25 +2365,25 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | /*BATTLE_TYPE_BATTLE_TOWER |*/ BATTLE_TYPE_EREADER_TRAINER))) { if (FlagGet(FLAG_BADGE01_GET) - && !GetBattlerSide(battlerIdAtk)) + && GetBattlerSide(battlerIdAtk) == B_SIDE_PLAYER) attack = (110 * attack) / 100; } if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | /*BATTLE_TYPE_BATTLE_TOWER |*/ BATTLE_TYPE_EREADER_TRAINER))) { if (FlagGet(FLAG_BADGE05_GET) - && !GetBattlerSide(battlerIdDef)) + && GetBattlerSide(battlerIdDef) == B_SIDE_PLAYER) defense = (110 * defense) / 100; } if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | /*BATTLE_TYPE_BATTLE_TOWER |*/ BATTLE_TYPE_EREADER_TRAINER))) { if (FlagGet(FLAG_BADGE07_GET) - && !GetBattlerSide(battlerIdAtk)) + && GetBattlerSide(battlerIdAtk) == B_SIDE_PLAYER) spAttack = (110 * spAttack) / 100; } if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | /*BATTLE_TYPE_BATTLE_TOWER |*/ BATTLE_TYPE_EREADER_TRAINER))) { if (FlagGet(FLAG_BADGE07_GET) - && !GetBattlerSide(battlerIdDef)) + && GetBattlerSide(battlerIdDef) == B_SIDE_PLAYER) spDefense = (110 * spDefense) / 100; } @@ -3917,7 +3917,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov if (gMain.inBattle) { gActiveBattler = gBattlerInMenuId; - cmdIndex = (GetBattlerSide(gActiveBattler) != 0); + cmdIndex = (GetBattlerSide(gActiveBattler) != B_SIDE_PLAYER); while (cmdIndex < gBattlersCount) { if (gBattlerPartyIndexes[cmdIndex] == partyIndex) @@ -4118,13 +4118,13 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov { gAbsentBattlerFlags &= ~gBitTable[sp34]; CopyPlayerPartyMonToBattleData(sp34, pokemon_order_func(gBattlerPartyIndexes[sp34])); - if (GetBattlerSide(gActiveBattler) == 0 && gBattleResults.numRevivesUsed < 255) + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.numRevivesUsed < 255) gBattleResults.numRevivesUsed++; } else { gAbsentBattlerFlags &= ~gBitTable[gActiveBattler ^ 2]; - if (GetBattlerSide(gActiveBattler) == 0 && gBattleResults.numRevivesUsed < 255) + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleResults.numRevivesUsed < 255) gBattleResults.numRevivesUsed++; } } @@ -4163,7 +4163,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov if (gMain.inBattle && sp34 != 4) { gBattleMons[sp34].hp = data; - if (!(r10 & 0x10) && GetBattlerSide(gActiveBattler) == 0) + if (!(r10 & 0x10) && GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) { if (gBattleResults.numHealingItemsUsed < 255) gBattleResults.numHealingItemsUsed++; @@ -6039,11 +6039,11 @@ void HandleSetPokedexFlag(u16 nationalNum, u8 caseId, u32 personality) } } -bool8 CheckBattleTypeGhost(struct Pokemon *mon, u8 bank) +bool8 CheckBattleTypeGhost(struct Pokemon *mon, u8 battlerId) { u8 buffer[12]; - if (gBattleTypeFlags & BATTLE_TYPE_GHOST && GetBattlerSide(bank)) + if (gBattleTypeFlags & BATTLE_TYPE_GHOST && GetBattlerSide(battlerId) != B_SIDE_PLAYER) { GetMonData(mon, MON_DATA_NICKNAME, buffer); StringGetEnd10(buffer); diff --git a/src/psychic.c b/src/psychic.c index a8108c55a..bbb6c3ed5 100644 --- a/src/psychic.c +++ b/src/psychic.c @@ -30,7 +30,7 @@ static void sub_80B3D78(u8 taskId); static const union AffineAnimCmd gUnknown_83E6DDC[] = { AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0xFFFE, 0xFFFE, -10, 120), + AFFINEANIMCMD_FRAME(-0x2, -0x2, -10, 120), AFFINEANIMCMD_END, }; @@ -305,7 +305,7 @@ const struct SpriteTemplate gUnknown_83E705C = static const union AffineAnimCmd gUnknown_83E7074[] = { - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 8), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 0, 8), AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), AFFINEANIMCMD_JUMP(0), }; @@ -313,27 +313,27 @@ static const union AffineAnimCmd gUnknown_83E7074[] = static const union AffineAnimCmd gUnknown_83E708C[] = { AFFINEANIMCMD_FRAME(0xF0, 0xF0, 0, 0), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 6), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 0, 6), AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 2), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 0, 2), AFFINEANIMCMD_JUMP(1), }; static const union AffineAnimCmd gUnknown_83E70B4[] = { AFFINEANIMCMD_FRAME(0xD0, 0xD0, 0, 0), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 4), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 0, 4), AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 4), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 0, 4), AFFINEANIMCMD_JUMP(1), }; static const union AffineAnimCmd gUnknown_83E70DC[] = { AFFINEANIMCMD_FRAME(0xB0, 0xB0, 0, 0), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 2), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 0, 2), AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 8), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 6), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 0, 6), AFFINEANIMCMD_JUMP(1), }; @@ -384,11 +384,11 @@ static const union AffineAnimCmd gUnknown_83E7160[] = AFFINEANIMCMD_FRAME(0x20, 0x20, 0, 0), AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 17), AFFINEANIMCMD_LOOP(0), - AFFINEANIMCMD_FRAME(0xFFF8, 0xFFF8, 0, 10), + AFFINEANIMCMD_FRAME(-0x8, -0x8, 0, 10), AFFINEANIMCMD_FRAME(0x8, 0x8, 0, 10), AFFINEANIMCMD_LOOP(4), AFFINEANIMCMD_LOOP(0), - AFFINEANIMCMD_FRAME(0xFFF0, 0xFFF0, 0, 5), + AFFINEANIMCMD_FRAME(-0x10, -0x10, 0, 5), AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 5), AFFINEANIMCMD_LOOP(7), AFFINEANIMCMD_END, @@ -396,7 +396,7 @@ static const union AffineAnimCmd gUnknown_83E7160[] = static const union AffineAnimCmd gUnknown_83E71B8[] = { - AFFINEANIMCMD_FRAME(0xFFEC, 0x18, 0, 15), + AFFINEANIMCMD_FRAME(-0x14, 0x18, 0, 15), AFFINEANIMCMD_END, }; diff --git a/src/quest_log.c b/src/quest_log.c index 78fa73de7..d7b544882 100644 --- a/src/quest_log.c +++ b/src/quest_log.c @@ -31,10 +31,10 @@ #include "wild_encounter.h" #include "help_system.h" #include "party_menu.h" -#include "unk_8159F40.h" #include "pokemon_storage_system.h" #include "save.h" #include "link.h" +#include "quest_log_815A008.h" #include "quest_log_8150454.h" #include "quest_log.h" #include "new_menu_helpers.h" diff --git a/src/unk_8159F40.c b/src/quest_log_815A008.c index ef21d19d0..2d488a845 100644 --- a/src/unk_8159F40.c +++ b/src/quest_log_815A008.c @@ -1,5 +1,4 @@ #include "global.h" -#include "battle.h" #include "event_data.h" #include "quest_log.h" #include "fieldmap.h" @@ -7,152 +6,6 @@ #include "metatile_behavior.h" #include "link.h" #include "link_rfu.h" -#include "constants/species.h" -#include "constants/moves.h" -#include "constants/pokemon.h" - -struct PokedudeBattlePartyInfo -{ - u8 side; - u8 level; - u16 species; - u16 moves[4]; - u8 nature; - u8 gender; -}; - -static const struct PokedudeBattlePartyInfo sParties_Battle[] = { - { - .side = 0, - .level = 15, - .species = SPECIES_RATTATA, - .moves = {MOVE_TACKLE, MOVE_TAIL_WHIP, MOVE_HYPER_FANG, MOVE_QUICK_ATTACK}, - .nature = NATURE_LONELY, - .gender = MALE - }, - { - .side = 1, - .level = 18, - .species = SPECIES_PIDGEY, - .moves = {MOVE_TACKLE, MOVE_SAND_ATTACK, MOVE_GUST, MOVE_QUICK_ATTACK}, - .nature = NATURE_NAUGHTY, - .gender = MALE - }, - {0xFF} -}; - -static const struct PokedudeBattlePartyInfo sParties_Status[] = { - { - .side = 0, - .level = 15, - .species = SPECIES_RATTATA, - .moves = {MOVE_TACKLE, MOVE_TAIL_WHIP, MOVE_HYPER_FANG, MOVE_QUICK_ATTACK}, - .nature = NATURE_LONELY, - .gender = MALE - }, - { - .side = 1, - .level = 14, - .species = SPECIES_ODDISH, - .moves = {MOVE_ABSORB, MOVE_SWEET_SCENT, MOVE_POISON_POWDER}, - .nature = NATURE_RASH, - .gender = MALE - }, - {0xFF} -}; - -static const struct PokedudeBattlePartyInfo sParties_Matchups[] = { - { - .side = 0, - .level = 15, - .species = SPECIES_POLIWAG, - .moves = {MOVE_WATER_GUN, MOVE_HYPNOSIS, MOVE_BUBBLE}, - .nature = NATURE_RASH, - .gender = MALE - }, - { - .side = 0, - .level = 15, - .species = SPECIES_BUTTERFREE, - .moves = {MOVE_CONFUSION, MOVE_POISON_POWDER, MOVE_STUN_SPORE, MOVE_SLEEP_POWDER}, - .nature = NATURE_RASH, - .gender = MALE - }, - { - .side = 1, - .level = 14, - .species = SPECIES_ODDISH, - .moves = {MOVE_ABSORB, MOVE_SWEET_SCENT, MOVE_POISON_POWDER}, - .nature = NATURE_RASH, - .gender = MALE - }, - {0xFF} -}; - -static const struct PokedudeBattlePartyInfo sParties_Catching[] = { - { - .side = 0, - .level = 15, - .species = SPECIES_BUTTERFREE, - .moves = {MOVE_CONFUSION, MOVE_POISON_POWDER, MOVE_SLEEP_POWDER, MOVE_STUN_SPORE}, - .nature = NATURE_RASH, - .gender = MALE - }, - { - .side = 1, - .level = 11, - .species = SPECIES_JIGGLYPUFF, - .moves = {MOVE_SING, MOVE_DEFENSE_CURL, MOVE_POUND}, - .nature = NATURE_CAREFUL, - .gender = MALE - }, - {0xFF} -}; - - -static const struct PokedudeBattlePartyInfo *const sPokedudeBattlePartyPointers[] = { - sParties_Battle, - sParties_Status, - sParties_Matchups, - sParties_Catching -}; - -void InitPokedudePartyAndOpponent(void) -{ - s32 i, j; - struct Pokemon * mon; - s32 myIdx = 0; - s32 opIdx = 0; - const struct PokedudeBattlePartyInfo * data; - - gBattleTypeFlags = BATTLE_TYPE_POKEDUDE; - ZeroPlayerPartyMons(); - ZeroEnemyPartyMons(); - data = sPokedudeBattlePartyPointers[gSpecialVar_0x8004]; - - i = 0; - do - { - if (data[i].side == 0) - { - mon = &gPlayerParty[myIdx]; - myIdx++; - } - else - { - mon = &gEnemyParty[opIdx]; - opIdx++; - } - CreateMonWithGenderNatureLetter(mon, data[i].species, data[i].level, 0, data[i].gender, data[i].nature, 0); - for (j = 0; j < 4; j++) - { - SetMonMoveSlot(mon, data[i].moves[j], j); - } - i++; - } while (data[i].side != 0xFF); -} - -// file boundary? void sub_815A008(struct QuestLog * questLog) { diff --git a/src/rock.c b/src/rock.c index 4db903344..c4b668941 100644 --- a/src/rock.c +++ b/src/rock.c @@ -87,8 +87,8 @@ const struct SpriteTemplate gUnknown_83E73E4 = static const union AffineAnimCmd gUnknown_83E73FC[] = { AFFINEANIMCMD_FRAME(0xC0, 0xC0, 0, 0), - AFFINEANIMCMD_FRAME(0x2, 0xFFFD, 0, 5), - AFFINEANIMCMD_FRAME(0xFFFE, 0x3, 0, 5), + AFFINEANIMCMD_FRAME(0x2, -0x3, 0, 5), + AFFINEANIMCMD_FRAME(-0x2, 0x3, 0, 5), AFFINEANIMCMD_JUMP(1), }; @@ -152,7 +152,7 @@ static const struct Subsprite gUnknown_83E7468[] = static const struct SubspriteTable gUnknown_83E7470[] = { - { ARRAY_COUNT(gUnknown_83E7468), gUnknown_83E7468 }, + { NELEMS(gUnknown_83E7468), gUnknown_83E7468 }, }; static const union AnimCmd gUnknown_83E7478[] = @@ -588,7 +588,7 @@ void sub_80B4BD0(u8 taskId) task->data[13] = pan1; task->data[14] = (pan2 - pan1) / task->data[8]; task->data[1] = var4; - task->data[15] = GetAnimBattlerSpriteId(0); + task->data[15] = GetAnimBattlerSpriteId(ANIM_ATTACKER); task->func = sub_80B4D00; } diff --git a/src/teachy_tv.c b/src/teachy_tv.c index e33cb9d2e..2720f3204 100644 --- a/src/teachy_tv.c +++ b/src/teachy_tv.c @@ -25,11 +25,11 @@ #include "battle_transition.h" #include "battle_main.h" #include "battle.h" +#include "battle_controllers.h" #include "global.fieldmap.h" #include "teachy_tv.h" #include "help_system.h" #include "overworld.h" -#include "unk_8159F40.h" #include "graphics.h" #include "fieldmap.h" #include "strings.h" |