2017-10-01 01:12:42 +02:00
# include "global.h"
# include "battle.h"
2019-03-31 19:15:39 +02:00
# include "battle_anim.h"
2020-12-20 22:47:20 +01:00
# include "battle_ai_main.h"
2020-12-16 05:57:33 +01:00
# include "battle_ai_util.h"
2018-11-13 23:28:46 +01:00
# include "battle_arena.h"
# include "battle_controllers.h"
2018-02-09 01:09:02 +01:00
# include "battle_interface.h"
2018-12-07 20:47:20 +01:00
# include "battle_main.h"
2018-11-13 23:28:46 +01:00
# include "battle_message.h"
2018-11-18 17:52:22 +01:00
# include "battle_pyramid.h"
2018-11-13 23:28:46 +01:00
# include "battle_scripts.h"
# include "battle_setup.h"
# include "battle_tower.h"
2020-09-08 22:44:04 +02:00
# include "battle_util.h"
2017-10-01 01:12:42 +02:00
# include "berry.h"
2018-11-13 23:28:46 +01:00
# include "bg.h"
2019-04-04 23:53:06 +02:00
# include "data.h"
2018-11-13 23:28:46 +01:00
# include "decompress.h"
2018-11-14 01:01:50 +01:00
# include "dma3.h"
2018-11-13 23:28:46 +01:00
# include "event_data.h"
# include "evolution_scene.h"
2018-12-19 03:15:59 +01:00
# include "graphics.h"
2018-11-13 23:28:46 +01:00
# include "gpu_regs.h"
# include "international_string_util.h"
2017-10-02 23:32:39 +02:00
# include "item.h"
2017-10-01 01:12:42 +02:00
# include "link.h"
2017-11-11 04:08:17 +01:00
# include "link_rfu.h"
2018-11-13 23:28:46 +01:00
# include "load_save.h"
# include "main.h"
2019-09-09 03:07:54 +02:00
# include "malloc.h"
2017-10-01 18:54:01 +02:00
# include "m4a.h"
2018-11-13 23:28:46 +01:00
# include "palette.h"
# include "party_menu.h"
# include "pokeball.h"
# include "pokedex.h"
# include "pokemon.h"
2017-12-05 19:27:33 +01:00
# include "random.h"
2018-11-13 23:28:46 +01:00
# include "recorded_battle.h"
# include "roamer.h"
# include "safari_zone.h"
# include "scanline_effect.h"
2017-10-01 18:54:01 +02:00
# include "sound.h"
# include "sprite.h"
2018-11-13 23:28:46 +01:00
# include "string_util.h"
2018-12-24 00:02:29 +01:00
# include "strings.h"
2018-11-13 23:28:46 +01:00
# include "task.h"
# include "text.h"
2017-10-02 23:32:39 +02:00
# include "trig.h"
2018-11-13 23:28:46 +01:00
# include "tv.h"
# include "util.h"
# include "window.h"
2017-12-05 18:55:48 +01:00
# include "constants/abilities.h"
2018-11-15 21:53:32 +01:00
# include "constants/battle_config.h"
2018-11-13 23:28:46 +01:00
# include "constants/battle_move_effects.h"
# include "constants/battle_string_ids.h"
# include "constants/hold_effects.h"
# include "constants/items.h"
2017-12-11 19:27:51 +01:00
# include "constants/moves.h"
2019-10-18 01:22:03 +02:00
# include "constants/party_menu.h"
2018-06-20 23:07:51 +02:00
# include "constants/rgb.h"
2018-11-13 23:28:46 +01:00
# include "constants/songs.h"
2018-11-14 01:01:50 +01:00
# include "constants/trainers.h"
2019-03-02 04:32:50 +01:00
# include "cable_club.h"
2017-10-01 01:12:42 +02:00
2018-01-10 04:30:54 +01:00
extern struct MusicPlayerInfo gMPlayInfo_SE1 ;
extern struct MusicPlayerInfo gMPlayInfo_SE2 ;
2017-10-01 18:54:01 +02:00
2018-06-17 16:48:58 +02:00
extern const struct BgTemplate gBattleBgTemplates [ ] ;
2018-06-28 21:06:32 +02:00
extern const struct WindowTemplate * const gBattleWindowTemplates [ ] ;
2017-10-02 23:32:39 +02:00
2017-10-01 01:12:42 +02:00
// this file's functions
static void CB2_InitBattleInternal ( void ) ;
static void CB2_PreInitMultiBattle ( void ) ;
static void CB2_PreInitIngamePlayerPartnerBattle ( void ) ;
static void CB2_HandleStartMultiPartnerBattle ( void ) ;
static void CB2_HandleStartMultiBattle ( void ) ;
static void CB2_HandleStartBattle ( void ) ;
2017-10-01 18:54:01 +02:00
static void TryCorrectShedinjaLanguage ( struct Pokemon * mon ) ;
static u8 CreateNPCTrainerParty ( struct Pokemon * party , u16 trainerNum , bool8 firstTrainer ) ;
2017-10-06 19:09:37 +02:00
static void BattleMainCB1 ( void ) ;
2017-10-01 18:54:01 +02:00
static void sub_8038538 ( struct Sprite * sprite ) ;
2021-01-23 02:03:21 +01:00
static void CB2_EndLinkBattle ( void ) ;
static void EndLinkBattleInSteps ( void ) ;
2017-10-01 18:54:01 +02:00
static void sub_80392A8 ( void ) ;
static void sub_803937C ( void ) ;
static void sub_803939C ( void ) ;
2018-12-23 14:52:47 +01:00
static void SpriteCb_MoveWildMonToRight ( struct Sprite * sprite ) ;
static void SpriteCb_WildMonShowHealthbox ( struct Sprite * sprite ) ;
static void SpriteCb_WildMonAnimate ( struct Sprite * sprite ) ;
2017-10-01 18:54:01 +02:00
static void sub_80398D0 ( struct Sprite * sprite ) ;
2018-06-20 23:07:51 +02:00
static void SpriteCB_AnimFaintOpponent ( struct Sprite * sprite ) ;
2020-07-14 11:13:03 +02:00
static void SpriteCb_BlinkVisible ( struct Sprite * sprite ) ;
2017-10-06 19:09:37 +02:00
static void SpriteCallbackDummy_3 ( struct Sprite * sprite ) ;
2021-01-23 05:22:37 +01:00
static void SpriteCB_BattleSpriteSlideLeft ( struct Sprite * sprite ) ;
2017-10-06 19:09:37 +02:00
static void TurnValuesCleanUp ( bool8 var0 ) ;
2018-06-20 23:07:51 +02:00
static void SpriteCB_BounceEffect ( struct Sprite * sprite ) ;
2017-10-02 23:32:39 +02:00
static void BattleStartClearSetData ( void ) ;
2018-12-23 18:47:00 +01:00
static void DoBattleIntro ( void ) ;
2017-10-02 23:32:39 +02:00
static void TryDoEventsBeforeFirstTurn ( void ) ;
2017-10-06 19:09:37 +02:00
static void HandleTurnActionSelectionState ( void ) ;
2017-10-06 00:12:01 +02:00
static void RunTurnActionsFunctions ( void ) ;
2018-02-08 11:17:41 +01:00
static void SetActionsAndBattlersTurnOrder ( void ) ;
2017-10-06 19:09:37 +02:00
static void sub_803CDF8 ( void ) ;
2018-07-07 21:14:41 +02:00
static bool8 AllAtActionConfirmed ( void ) ;
2017-10-06 00:12:01 +02:00
static void CheckFocusPunch_ClearVarsBeforeTurnStarts ( void ) ;
2018-09-16 18:55:32 +02:00
static void CheckMegaEvolutionBeforeTurn ( void ) ;
2021-01-06 17:37:31 +01:00
static void CheckQuickClaw_CustapBerryActivation ( void ) ;
2017-10-06 00:12:01 +02:00
static void FreeResetData_ReturnToOvOrDoEvolutions ( void ) ;
static void ReturnFromBattleToOverworld ( void ) ;
static void TryEvolvePokemon ( void ) ;
static void WaitForEvoSceneToFinish ( void ) ;
2017-10-06 19:09:37 +02:00
static void HandleEndTurn_ContinueBattle ( void ) ;
static void HandleEndTurn_BattleWon ( void ) ;
static void HandleEndTurn_BattleLost ( void ) ;
static void HandleEndTurn_RanFromBattle ( void ) ;
static void HandleEndTurn_MonFled ( void ) ;
static void HandleEndTurn_FinishBattle ( void ) ;
2018-02-07 22:53:40 +01:00
// EWRAM vars
2018-11-19 17:36:39 +01:00
EWRAM_DATA u16 gBattle_BG0_X = 0 ;
EWRAM_DATA u16 gBattle_BG0_Y = 0 ;
EWRAM_DATA u16 gBattle_BG1_X = 0 ;
EWRAM_DATA u16 gBattle_BG1_Y = 0 ;
EWRAM_DATA u16 gBattle_BG2_X = 0 ;
EWRAM_DATA u16 gBattle_BG2_Y = 0 ;
EWRAM_DATA u16 gBattle_BG3_X = 0 ;
EWRAM_DATA u16 gBattle_BG3_Y = 0 ;
EWRAM_DATA u16 gBattle_WIN0H = 0 ;
EWRAM_DATA u16 gBattle_WIN0V = 0 ;
EWRAM_DATA u16 gBattle_WIN1H = 0 ;
EWRAM_DATA u16 gBattle_WIN1V = 0 ;
2018-12-01 11:12:31 +01:00
EWRAM_DATA u8 gDisplayedStringBattle [ 400 ] = { 0 } ;
2018-06-30 15:35:54 +02:00
EWRAM_DATA u8 gBattleTextBuff1 [ TEXT_BUFF_ARRAY_COUNT ] = { 0 } ;
EWRAM_DATA u8 gBattleTextBuff2 [ TEXT_BUFF_ARRAY_COUNT ] = { 0 } ;
EWRAM_DATA u8 gBattleTextBuff3 [ TEXT_BUFF_ARRAY_COUNT ] = { 0 } ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u32 gBattleTypeFlags = 0 ;
EWRAM_DATA u8 gBattleTerrain = 0 ;
2021-01-22 08:48:22 +01:00
EWRAM_DATA u32 gUnusedFirstBattleVar1 = 0 ; // Never read
2019-11-01 02:33:01 +01:00
EWRAM_DATA struct UnknownPokemonStruct4 gMultiPartnerParty [ MULTI_PARTY_SIZE ] = { 0 } ;
2019-10-18 01:22:03 +02:00
EWRAM_DATA static struct UnknownPokemonStruct4 * sMultiPartnerPartyBuffer = NULL ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u8 * gUnknown_0202305C = NULL ;
EWRAM_DATA u8 * gUnknown_02023060 = NULL ;
EWRAM_DATA u8 gActiveBattler = 0 ;
EWRAM_DATA u32 gBattleControllerExecFlags = 0 ;
EWRAM_DATA u8 gBattlersCount = 0 ;
EWRAM_DATA u16 gBattlerPartyIndexes [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u8 gBattlerPositions [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u8 gActionsByTurnOrder [ MAX_BATTLERS_COUNT ] = { 0 } ;
2018-06-28 21:06:32 +02:00
EWRAM_DATA u8 gBattlerByTurnOrder [ MAX_BATTLERS_COUNT ] = { 0 } ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u8 gCurrentTurnActionNumber = 0 ;
EWRAM_DATA u8 gCurrentActionFuncId = 0 ;
EWRAM_DATA struct BattlePokemon gBattleMons [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u8 gBattlerSpriteIds [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u8 gCurrMovePos = 0 ;
2018-02-08 11:17:41 +01:00
EWRAM_DATA u8 gChosenMovePos = 0 ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u16 gCurrentMove = 0 ;
EWRAM_DATA u16 gChosenMove = 0 ;
2018-09-22 18:41:00 +02:00
EWRAM_DATA u16 gCalledMove = 0 ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA s32 gBattleMoveDamage = 0 ;
EWRAM_DATA s32 gHpDealt = 0 ;
EWRAM_DATA s32 gTakenDmg [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u16 gLastUsedItem = 0 ;
2020-05-18 23:54:12 +02:00
EWRAM_DATA u16 gLastUsedAbility = 0 ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u8 gBattlerAttacker = 0 ;
EWRAM_DATA u8 gBattlerTarget = 0 ;
2018-02-08 11:17:41 +01:00
EWRAM_DATA u8 gBattlerFainted = 0 ;
EWRAM_DATA u8 gEffectBattler = 0 ;
2018-02-08 12:13:29 +01:00
EWRAM_DATA u8 gPotentialItemEffectBattler = 0 ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u8 gAbsentBattlerFlags = 0 ;
2018-07-14 22:56:03 +02:00
EWRAM_DATA u8 gIsCriticalHit = FALSE ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u8 gMultiHitCounter = 0 ;
EWRAM_DATA const u8 * gBattlescriptCurrInstr = NULL ;
EWRAM_DATA u8 gChosenActionByBattler [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA const u8 * gSelectionBattleScripts [ MAX_BATTLERS_COUNT ] = { NULL } ;
EWRAM_DATA const u8 * gPalaceSelectionBattleScripts [ MAX_BATTLERS_COUNT ] = { NULL } ;
EWRAM_DATA u16 gLastPrintedMoves [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u16 gLastMoves [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u16 gLastLandedMoves [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u16 gLastHitByType [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u16 gLastResultingMoves [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u16 gLockedMoves [ MAX_BATTLERS_COUNT ] = { 0 } ;
2018-09-22 18:37:03 +02:00
EWRAM_DATA u16 gLastUsedMove = 0 ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u8 gLastHitBy [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u16 gChosenMoveByBattler [ MAX_BATTLERS_COUNT ] = { 0 } ;
2018-07-21 15:11:13 +02:00
EWRAM_DATA u16 gMoveResultFlags = 0 ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u32 gHitMarker = 0 ;
EWRAM_DATA u8 gTakenDmgByBattler [ MAX_BATTLERS_COUNT ] = { 0 } ;
2021-01-22 08:48:22 +01:00
EWRAM_DATA u8 gUnusedFirstBattleVar2 = 0 ; // Never read
2018-07-24 20:13:02 +02:00
EWRAM_DATA u32 gSideStatuses [ 2 ] = { 0 } ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA struct SideTimer gSideTimers [ 2 ] = { 0 } ;
EWRAM_DATA u32 gStatuses3 [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA struct DisableStruct gDisableStructs [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u16 gPauseCounterBattle = 0 ;
EWRAM_DATA u16 gPaydayMoney = 0 ;
EWRAM_DATA u16 gRandomTurnNumber = 0 ;
EWRAM_DATA u8 gBattleCommunication [ BATTLE_COMMUNICATION_ENTRIES_COUNT ] = { 0 } ;
EWRAM_DATA u8 gBattleOutcome = 0 ;
EWRAM_DATA struct ProtectStruct gProtectStructs [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA struct SpecialStatus gSpecialStatuses [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u16 gBattleWeather = 0 ;
EWRAM_DATA struct WishFutureKnock gWishFutureKnock = { 0 } ;
2018-02-08 11:17:41 +01:00
EWRAM_DATA u16 gIntroSlideFlags = 0 ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u8 gSentPokesToOpponent [ 2 ] = { 0 } ;
EWRAM_DATA u16 gExpShareExp = 0 ;
EWRAM_DATA struct BattleEnigmaBerry gEnigmaBerries [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA struct BattleScripting gBattleScripting = { 0 } ;
EWRAM_DATA struct BattleStruct * gBattleStruct = NULL ;
EWRAM_DATA u8 * gLinkBattleSendBuffer = NULL ;
EWRAM_DATA u8 * gLinkBattleRecvBuffer = NULL ;
EWRAM_DATA struct BattleResources * gBattleResources = NULL ;
EWRAM_DATA u8 gActionSelectionCursor [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u8 gMoveSelectionCursor [ MAX_BATTLERS_COUNT ] = { 0 } ;
2018-02-08 11:17:41 +01:00
EWRAM_DATA u8 gBattlerStatusSummaryTaskId [ MAX_BATTLERS_COUNT ] = { 0 } ;
2018-02-07 22:53:40 +01:00
EWRAM_DATA u8 gBattlerInMenuId = 0 ;
EWRAM_DATA bool8 gDoingBattleAnim = FALSE ;
EWRAM_DATA u32 gTransformedPersonalities [ MAX_BATTLERS_COUNT ] = { 0 } ;
EWRAM_DATA u8 gPlayerDpadHoldFrames = 0 ;
EWRAM_DATA struct BattleSpriteData * gBattleSpritesDataPtr = NULL ;
EWRAM_DATA struct MonSpritesGfx * gMonSpritesGfxPtr = NULL ;
2021-01-23 03:35:16 +01:00
EWRAM_DATA struct BattleHealthboxInfo * gBattleControllerOpponentHealthboxData = NULL ; // Never read
EWRAM_DATA struct BattleHealthboxInfo * gBattleControllerOpponentFlankHealthboxData = NULL ; // Never read
2018-02-07 22:53:40 +01:00
EWRAM_DATA u16 gBattleMovePower = 0 ;
EWRAM_DATA u16 gMoveToLearn = 0 ;
EWRAM_DATA u8 gBattleMonForms [ MAX_BATTLERS_COUNT ] = { 0 } ;
2018-07-14 13:17:10 +02:00
EWRAM_DATA u32 gFieldStatuses = 0 ;
EWRAM_DATA struct FieldTimer gFieldTimers = { 0 } ;
2020-11-17 19:32:24 +01:00
EWRAM_DATA u8 gBattlerAbility = 0 ;
2018-11-24 01:02:02 +01:00
EWRAM_DATA u16 gPartnerSpriteId = 0 ;
2020-11-19 18:35:37 +01:00
EWRAM_DATA struct TotemBoost gTotemBoosts [ MAX_BATTLERS_COUNT ] = { 0 } ;
2020-12-03 03:09:35 +01:00
EWRAM_DATA bool8 gHasFetchedBall = FALSE ;
2020-12-05 07:03:55 +01:00
EWRAM_DATA u8 gLastUsedBall = 0 ;
2018-02-07 22:53:40 +01:00
2018-02-07 23:21:51 +01:00
// IWRAM common vars
void ( * gPreBattleCallback1 ) ( void ) ;
void ( * gBattleMainFunc ) ( void ) ;
struct BattleResults gBattleResults ;
u8 gLeveledUpInBattle ;
void ( * gBattlerControllerFuncs [ MAX_BATTLERS_COUNT ] ) ( void ) ;
u8 gHealthboxSpriteIds [ MAX_BATTLERS_COUNT ] ;
u8 gMultiUsePlayerCursor ;
u8 gNumberOfMovesToChoose ;
2021-01-23 02:03:21 +01:00
u8 gBattleControllerData [ MAX_BATTLERS_COUNT ] ; // Used by the battle controllers to store misc sprite/task IDs for each battler
2018-02-07 23:21:51 +01:00
2017-10-06 19:09:37 +02:00
// rom const data
2018-12-23 14:52:47 +01:00
static const struct ScanlineEffectParams sIntroScanlineParams16Bit =
{
( void * ) REG_ADDR_BG3HOFS , SCANLINE_EFFECT_DMACNT_16BIT , 1
} ;
// unused
static const struct ScanlineEffectParams sIntroScanlineParams32Bit =
{
( void * ) REG_ADDR_BG3HOFS , SCANLINE_EFFECT_DMACNT_32BIT , 1
} ;
const struct SpriteTemplate gUnknown_0831AC88 =
{
. tileTag = 0 ,
. paletteTag = 0 ,
. oam = & gDummyOamData ,
. anims = gDummySpriteAnimTable ,
. images = NULL ,
. affineAnims = gDummySpriteAffineAnimTable ,
. callback = sub_8038528 ,
} ;
static const u8 sText_ShedinjaJpnName [ ] = _ ( " ヌケニン " ) ; // Nukenin
2021-01-23 05:22:37 +01:00
const struct OamData gOamData_BattleSpriteOpponentSide =
2018-12-23 14:52:47 +01:00
{
. y = 0 ,
2019-04-02 00:31:10 +02:00
. affineMode = ST_OAM_AFFINE_NORMAL ,
. objMode = ST_OAM_OBJ_NORMAL ,
. bpp = ST_OAM_4BPP ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 64 x64 ) ,
2018-12-23 14:52:47 +01:00
. x = 0 ,
2019-03-11 08:12:15 +01:00
. size = SPRITE_SIZE ( 64 x64 ) ,
2018-12-23 14:52:47 +01:00
. tileNum = 0 ,
. priority = 2 ,
. paletteNum = 0 ,
2019-04-02 00:31:10 +02:00
. affineParam = 0 ,
2018-12-23 14:52:47 +01:00
} ;
2021-01-23 05:22:37 +01:00
const struct OamData gOamData_BattleSpritePlayerSide =
2018-12-23 14:52:47 +01:00
{
. y = 0 ,
2019-04-02 00:31:10 +02:00
. affineMode = ST_OAM_AFFINE_NORMAL ,
. objMode = ST_OAM_OBJ_NORMAL ,
. bpp = ST_OAM_4BPP ,
2019-03-11 08:12:15 +01:00
. shape = SPRITE_SHAPE ( 64 x64 ) ,
2018-12-23 14:52:47 +01:00
. x = 0 ,
2019-03-11 08:12:15 +01:00
. size = SPRITE_SIZE ( 64 x64 ) ,
2018-12-23 14:52:47 +01:00
. tileNum = 0 ,
. priority = 2 ,
. paletteNum = 2 ,
2019-04-02 00:31:10 +02:00
. affineParam = 0 ,
2018-12-23 14:52:47 +01:00
} ;
2018-12-23 13:52:53 +01:00
2018-07-01 15:28:57 +02:00
static const s8 gUnknown_0831ACE0 [ ] = { - 32 , - 16 , - 16 , - 32 , - 32 , 0 , 0 , 0 } ;
2018-02-26 14:29:17 +01:00
2019-10-18 01:22:03 +02:00
const u8 gTypeNames [ NUMBER_OF_MON_TYPES ] [ TYPE_NAME_LENGTH + 1 ] =
2018-02-26 14:29:17 +01:00
{
2021-04-28 03:36:37 +02:00
[ TYPE_NORMAL ] = _ ( " Normal " ) ,
[ TYPE_FIGHTING ] = _ ( " Fight " ) ,
[ TYPE_FLYING ] = _ ( " Flying " ) ,
[ TYPE_POISON ] = _ ( " Poison " ) ,
[ TYPE_GROUND ] = _ ( " Ground " ) ,
[ TYPE_ROCK ] = _ ( " Rock " ) ,
[ TYPE_BUG ] = _ ( " Bug " ) ,
[ TYPE_GHOST ] = _ ( " Ghost " ) ,
[ TYPE_STEEL ] = _ ( " Steel " ) ,
2021-04-13 00:33:20 +02:00
[ TYPE_MYSTERY ] = _ ( " ??? " ) ,
2021-04-28 03:36:37 +02:00
[ TYPE_FIRE ] = _ ( " Fire " ) ,
[ TYPE_WATER ] = _ ( " Water " ) ,
[ TYPE_GRASS ] = _ ( " Grass " ) ,
[ TYPE_ELECTRIC ] = _ ( " Electr " ) ,
[ TYPE_PSYCHIC ] = _ ( " Psychc " ) ,
[ TYPE_ICE ] = _ ( " Ice " ) ,
[ TYPE_DRAGON ] = _ ( " Dragon " ) ,
[ TYPE_DARK ] = _ ( " Dark " ) ,
[ TYPE_FAIRY ] = _ ( " Fairy " ) ,
2018-02-26 14:29:17 +01:00
} ;
// This is a factor in how much money you get for beating a trainer.
const struct TrainerMoney gTrainerMoneyTable [ ] =
{
{ TRAINER_CLASS_TEAM_AQUA , 5 } ,
{ TRAINER_CLASS_AQUA_ADMIN , 10 } ,
{ TRAINER_CLASS_AQUA_LEADER , 20 } ,
{ TRAINER_CLASS_AROMA_LADY , 10 } ,
{ TRAINER_CLASS_RUIN_MANIAC , 15 } ,
{ TRAINER_CLASS_INTERVIEWER , 12 } ,
2018-12-03 04:35:11 +01:00
{ TRAINER_CLASS_TUBER_F , 1 } ,
{ TRAINER_CLASS_TUBER_M , 1 } ,
2018-02-26 14:29:17 +01:00
{ TRAINER_CLASS_SIS_AND_BRO , 3 } ,
2018-12-03 04:35:11 +01:00
{ TRAINER_CLASS_COOLTRAINER , 12 } ,
2018-02-26 14:29:17 +01:00
{ TRAINER_CLASS_HEX_MANIAC , 6 } ,
{ TRAINER_CLASS_LADY , 50 } ,
{ TRAINER_CLASS_BEAUTY , 20 } ,
{ TRAINER_CLASS_RICH_BOY , 50 } ,
{ TRAINER_CLASS_POKEMANIAC , 15 } ,
{ TRAINER_CLASS_SWIMMER_M , 2 } ,
{ TRAINER_CLASS_BLACK_BELT , 8 } ,
{ TRAINER_CLASS_GUITARIST , 8 } ,
{ TRAINER_CLASS_KINDLER , 8 } ,
{ TRAINER_CLASS_CAMPER , 4 } ,
{ TRAINER_CLASS_OLD_COUPLE , 10 } ,
{ TRAINER_CLASS_BUG_MANIAC , 15 } ,
{ TRAINER_CLASS_PSYCHIC , 6 } ,
{ TRAINER_CLASS_GENTLEMAN , 20 } ,
{ TRAINER_CLASS_ELITE_FOUR , 25 } ,
{ TRAINER_CLASS_LEADER , 25 } ,
{ TRAINER_CLASS_SCHOOL_KID , 5 } ,
{ TRAINER_CLASS_SR_AND_JR , 4 } ,
{ TRAINER_CLASS_POKEFAN , 20 } ,
{ TRAINER_CLASS_EXPERT , 10 } ,
{ TRAINER_CLASS_YOUNGSTER , 4 } ,
{ TRAINER_CLASS_CHAMPION , 50 } ,
{ TRAINER_CLASS_FISHERMAN , 10 } ,
{ TRAINER_CLASS_TRIATHLETE , 10 } ,
{ TRAINER_CLASS_DRAGON_TAMER , 12 } ,
{ TRAINER_CLASS_BIRD_KEEPER , 8 } ,
{ TRAINER_CLASS_NINJA_BOY , 3 } ,
{ TRAINER_CLASS_BATTLE_GIRL , 6 } ,
{ TRAINER_CLASS_PARASOL_LADY , 10 } ,
{ TRAINER_CLASS_SWIMMER_F , 2 } ,
{ TRAINER_CLASS_PICNICKER , 4 } ,
{ TRAINER_CLASS_TWINS , 3 } ,
{ TRAINER_CLASS_SAILOR , 8 } ,
{ TRAINER_CLASS_COLLECTOR , 15 } ,
{ TRAINER_CLASS_PKMN_TRAINER_3 , 15 } ,
{ TRAINER_CLASS_PKMN_BREEDER , 10 } ,
{ TRAINER_CLASS_PKMN_RANGER , 12 } ,
{ TRAINER_CLASS_TEAM_MAGMA , 5 } ,
{ TRAINER_CLASS_MAGMA_ADMIN , 10 } ,
{ TRAINER_CLASS_MAGMA_LEADER , 20 } ,
{ TRAINER_CLASS_LASS , 4 } ,
{ TRAINER_CLASS_BUG_CATCHER , 4 } ,
{ TRAINER_CLASS_HIKER , 10 } ,
{ TRAINER_CLASS_YOUNG_COUPLE , 8 } ,
{ TRAINER_CLASS_WINSTRATE , 10 } ,
{ 0xFF , 5 } ,
} ;
# include "data/text/abilities.h"
2017-10-06 19:09:37 +02:00
static void ( * const sTurnActionsFuncsTable [ ] ) ( void ) =
{
2018-12-08 07:10:30 +01:00
[ B_ACTION_USE_MOVE ] = HandleAction_UseMove ,
[ B_ACTION_USE_ITEM ] = HandleAction_UseItem ,
[ B_ACTION_SWITCH ] = HandleAction_Switch ,
[ B_ACTION_RUN ] = HandleAction_Run ,
[ B_ACTION_SAFARI_WATCH_CAREFULLY ] = HandleAction_WatchesCarefully ,
[ B_ACTION_SAFARI_BALL ] = HandleAction_SafariZoneBallThrow ,
[ B_ACTION_SAFARI_POKEBLOCK ] = HandleAction_ThrowPokeblock ,
[ B_ACTION_SAFARI_GO_NEAR ] = HandleAction_GoNear ,
[ B_ACTION_SAFARI_RUN ] = HandleAction_SafariZoneRun ,
[ B_ACTION_WALLY_THROW ] = HandleAction_WallyBallThrow ,
[ B_ACTION_EXEC_SCRIPT ] = HandleAction_RunBattleScript ,
2019-02-02 11:32:00 +01:00
[ B_ACTION_TRY_FINISH ] = HandleAction_TryFinish ,
2018-12-08 07:10:30 +01:00
[ B_ACTION_FINISHED ] = HandleAction_ActionFinished ,
[ B_ACTION_NOTHING_FAINTED ] = HandleAction_NothingIsFainted ,
2017-10-06 19:09:37 +02:00
} ;
static void ( * const sEndTurnFuncsTable [ ] ) ( void ) =
{
2018-12-08 07:10:30 +01:00
[ 0 ] = HandleEndTurn_ContinueBattle , //B_OUTCOME_NONE?
[ B_OUTCOME_WON ] = HandleEndTurn_BattleWon ,
[ B_OUTCOME_LOST ] = HandleEndTurn_BattleLost ,
[ B_OUTCOME_DREW ] = HandleEndTurn_BattleLost ,
[ B_OUTCOME_RAN ] = HandleEndTurn_RanFromBattle ,
[ B_OUTCOME_PLAYER_TELEPORTED ] = HandleEndTurn_FinishBattle ,
[ B_OUTCOME_MON_FLED ] = HandleEndTurn_MonFled ,
[ B_OUTCOME_CAUGHT ] = HandleEndTurn_FinishBattle ,
[ B_OUTCOME_NO_SAFARI_BALLS ] = HandleEndTurn_FinishBattle ,
[ B_OUTCOME_FORFEITED ] = HandleEndTurn_FinishBattle ,
[ B_OUTCOME_MON_TELEPORTED ] = HandleEndTurn_FinishBattle ,
2017-10-06 19:09:37 +02:00
} ;
const u8 gStatusConditionString_PoisonJpn [ 8 ] = _ ( " どく$$$$$ " ) ;
const u8 gStatusConditionString_SleepJpn [ 8 ] = _ ( " ねむり$$$$ " ) ;
const u8 gStatusConditionString_ParalysisJpn [ 8 ] = _ ( " まひ$$$$$ " ) ;
const u8 gStatusConditionString_BurnJpn [ 8 ] = _ ( " やけど$$$$ " ) ;
const u8 gStatusConditionString_IceJpn [ 8 ] = _ ( " こおり$$$$ " ) ;
const u8 gStatusConditionString_ConfusionJpn [ 8 ] = _ ( " こんらん$$$ " ) ;
const u8 gStatusConditionString_LoveJpn [ 8 ] = _ ( " メロメロ$$$ " ) ;
2017-10-07 19:59:41 +02:00
const u8 * const gStatusConditionStringsTable [ 7 ] [ 2 ] =
2017-10-06 19:09:37 +02:00
{
{ gStatusConditionString_PoisonJpn , gText_Poison } ,
{ gStatusConditionString_SleepJpn , gText_Sleep } ,
{ gStatusConditionString_ParalysisJpn , gText_Paralysis } ,
{ gStatusConditionString_BurnJpn , gText_Burn } ,
{ gStatusConditionString_IceJpn , gText_Ice } ,
{ gStatusConditionString_ConfusionJpn , gText_Confusion } ,
{ gStatusConditionString_LoveJpn , gText_Love }
} ;
2018-06-30 14:12:17 +02:00
// code
2017-10-01 01:12:42 +02:00
void CB2_InitBattle ( void )
{
MoveSaveBlocks_ResetHeap ( ) ;
2017-11-12 16:39:21 +01:00
AllocateBattleResources ( ) ;
2017-10-01 01:12:42 +02:00
AllocateBattleSpritesData ( ) ;
AllocateMonSpritesGfx ( ) ;
2021-03-12 22:55:58 +01:00
RecordedBattle_ClearFrontierPassFlag ( ) ;
2017-10-01 01:12:42 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_MULTI )
{
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED )
{
CB2_InitBattleInternal ( ) ;
}
else if ( ! ( gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER ) )
{
HandleLinkBattleSetup ( ) ;
SetMainCallback2 ( CB2_PreInitMultiBattle ) ;
}
else
{
SetMainCallback2 ( CB2_PreInitIngamePlayerPartnerBattle ) ;
}
gBattleCommunication [ MULTIUSE_STATE ] = 0 ;
}
else
{
CB2_InitBattleInternal ( ) ;
}
}
static void CB2_InitBattleInternal ( void )
{
s32 i ;
SetHBlankCallback ( NULL ) ;
SetVBlankCallback ( NULL ) ;
2017-10-01 18:54:01 +02:00
CpuFill32 ( 0 , ( void * ) ( VRAM ) , VRAM_SIZE ) ;
2017-10-01 01:12:42 +02:00
SetGpuReg ( REG_OFFSET_MOSAIC , 0 ) ;
2021-04-15 08:04:01 +02:00
SetGpuReg ( REG_OFFSET_WIN0H , DISPLAY_WIDTH ) ;
SetGpuReg ( REG_OFFSET_WIN0V , WIN_RANGE ( DISPLAY_HEIGHT / 2 , DISPLAY_HEIGHT / 2 + 1 ) ) ;
2017-10-01 01:12:42 +02:00
SetGpuReg ( REG_OFFSET_WININ , 0 ) ;
SetGpuReg ( REG_OFFSET_WINOUT , 0 ) ;
2021-04-15 08:04:01 +02:00
gBattle_WIN0H = DISPLAY_WIDTH ;
2017-10-01 01:12:42 +02:00
2018-11-24 01:02:02 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER & & gPartnerTrainerId ! = TRAINER_STEVEN_PARTNER & & gPartnerTrainerId < TRAINER_CUSTOM_PARTNER )
2017-10-01 01:12:42 +02:00
{
2021-04-15 08:04:01 +02:00
gBattle_WIN0V = DISPLAY_HEIGHT - 1 ;
gBattle_WIN1H = DISPLAY_WIDTH ;
2017-10-01 01:12:42 +02:00
gBattle_WIN1V = 32 ;
}
else
{
2021-04-15 08:04:01 +02:00
gBattle_WIN0V = WIN_RANGE ( DISPLAY_HEIGHT / 2 , DISPLAY_HEIGHT / 2 + 1 ) ;
2018-01-29 17:47:12 +01:00
ScanlineEffect_Clear ( ) ;
2017-10-01 01:12:42 +02:00
2019-01-05 19:25:46 +01:00
i = 0 ;
while ( i < 80 )
2017-10-01 01:12:42 +02:00
{
2018-01-29 17:47:12 +01:00
gScanlineEffectRegBuffers [ 0 ] [ i ] = 0xF0 ;
gScanlineEffectRegBuffers [ 1 ] [ i ] = 0xF0 ;
2019-01-05 19:25:46 +01:00
i + + ;
2017-10-01 01:12:42 +02:00
}
2019-01-05 19:25:46 +01:00
while ( i < 160 )
2017-10-01 01:12:42 +02:00
{
2018-01-29 17:47:12 +01:00
gScanlineEffectRegBuffers [ 0 ] [ i ] = 0xFF10 ;
gScanlineEffectRegBuffers [ 1 ] [ i ] = 0xFF10 ;
2019-01-05 19:25:46 +01:00
i + + ;
2017-10-01 01:12:42 +02:00
}
2018-12-23 14:52:47 +01:00
ScanlineEffect_SetParams ( sIntroScanlineParams16Bit ) ;
2017-10-01 01:12:42 +02:00
}
ResetPaletteFade ( ) ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
gBattle_BG1_X = 0 ;
gBattle_BG1_Y = 0 ;
gBattle_BG2_X = 0 ;
gBattle_BG2_Y = 0 ;
gBattle_BG3_X = 0 ;
gBattle_BG3_Y = 0 ;
gBattleTerrain = BattleSetup_GetTerrainId ( ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED )
2017-12-16 01:08:55 +01:00
gBattleTerrain = BATTLE_TERRAIN_BUILDING ;
2017-10-01 01:12:42 +02:00
2019-11-07 01:18:11 +01:00
InitBattleBgsVideo ( ) ;
2017-10-01 01:12:42 +02:00
LoadBattleTextboxAndBackground ( ) ;
ResetSpriteData ( ) ;
ResetTasks ( ) ;
2018-06-17 16:48:58 +02:00
DrawBattleEntryBackground ( ) ;
2017-10-01 01:12:42 +02:00
FreeAllSpritePalettes ( ) ;
gReservedSpritePaletteCount = 4 ;
SetVBlankCallback ( VBlankCB_Battle ) ;
SetUpBattleVarsAndBirchZigzagoon ( ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_MULTI & & gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER )
SetMainCallback2 ( CB2_HandleStartMultiPartnerBattle ) ;
else if ( gBattleTypeFlags & BATTLE_TYPE_MULTI & & gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER )
SetMainCallback2 ( CB2_HandleStartMultiPartnerBattle ) ;
else if ( gBattleTypeFlags & BATTLE_TYPE_MULTI )
SetMainCallback2 ( CB2_HandleStartMultiBattle ) ;
else
SetMainCallback2 ( CB2_HandleStartBattle ) ;
if ( ! ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED ) ) )
{
CreateNPCTrainerParty ( & gEnemyParty [ 0 ] , gTrainerBattleOpponent_A , TRUE ) ;
2019-01-27 20:54:34 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS & & ! BATTLE_TWO_VS_ONE_OPPONENT )
2017-10-01 01:12:42 +02:00
CreateNPCTrainerParty ( & gEnemyParty [ 3 ] , gTrainerBattleOpponent_B , FALSE ) ;
SetWildMonHeldItem ( ) ;
}
gMain . inBattle = TRUE ;
2019-12-14 09:58:20 +01:00
gSaveBlock2Ptr - > frontier . disableRecordBattle = FALSE ;
2017-10-01 01:12:42 +02:00
2018-06-20 23:07:51 +02:00
for ( i = 0 ; i < PARTY_SIZE ; i + + )
2020-02-02 19:28:54 +01:00
AdjustFriendship ( & gPlayerParty [ i ] , FRIENDSHIP_EVENT_LEAGUE_BATTLE ) ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] = 0 ;
}
2021-01-23 05:22:37 +01:00
# define BUFFER_PARTY_VS_SCREEN_STATUS(party, flags, i) \
for ( ( i ) = 0 ; ( i ) < PARTY_SIZE ; ( i ) + + ) \
{ \
u16 species = GetMonData ( & ( party ) [ ( i ) ] , MON_DATA_SPECIES2 ) ; \
u16 hp = GetMonData ( & ( party ) [ ( i ) ] , MON_DATA_HP ) ; \
u32 status = GetMonData ( & ( party ) [ ( i ) ] , MON_DATA_STATUS ) ; \
\
if ( species = = SPECIES_NONE ) \
continue ; \
\
/* Is healthy mon? */ \
if ( species ! = SPECIES_EGG & & hp ! = 0 & & status = = 0 ) \
( flags ) | = 1 < < ( i ) * 2 ; \
\
if ( species = = SPECIES_NONE ) /* Redundant */ \
continue ; \
\
/* Is Egg or statused? */ \
if ( hp ! = 0 & & ( species = = SPECIES_EGG | | status ! = 0 ) ) \
( flags ) | = 2 < < ( i ) * 2 ; \
\
if ( species = = SPECIES_NONE ) /* Redundant */ \
continue ; \
\
/* Is fainted? */ \
if ( species ! = SPECIES_EGG & & hp = = 0 ) \
( flags ) | = 3 < < ( i ) * 2 ; \
}
// For Vs Screen at link battle start
static void BufferPartyVsScreenHealth_AtStart ( void )
2017-10-01 01:12:42 +02:00
{
2021-01-23 05:22:37 +01:00
u16 flags = 0 ;
2017-10-01 01:12:42 +02:00
s32 i ;
2021-01-23 05:22:37 +01:00
BUFFER_PARTY_VS_SCREEN_STATUS ( gPlayerParty , flags , i ) ;
2021-03-15 20:22:41 +01:00
gBattleStruct - > multiBuffer . linkBattlerHeader . vsScreenHealthFlagsLo = flags ;
* ( & gBattleStruct - > multiBuffer . linkBattlerHeader . vsScreenHealthFlagsHi ) = flags > > 8 ;
gBattleStruct - > multiBuffer . linkBattlerHeader . vsScreenHealthFlagsHi | = FlagGet ( FLAG_SYS_FRONTIER_PASS ) < < 7 ;
2017-10-01 01:12:42 +02:00
}
static void SetPlayerBerryDataInBattleStruct ( void )
{
s32 i ;
struct BattleStruct * battleStruct = gBattleStruct ;
2021-03-15 20:22:41 +01:00
struct BattleEnigmaBerry * battleBerry = & battleStruct - > multiBuffer . linkBattlerHeader . battleEnigmaBerry ;
2017-10-01 01:12:42 +02:00
if ( IsEnigmaBerryValid ( ) = = TRUE )
{
2018-09-01 22:03:21 +02:00
for ( i = 0 ; i < BERRY_NAME_LENGTH ; i + + )
2017-10-01 01:12:42 +02:00
battleBerry - > name [ i ] = gSaveBlock1Ptr - > enigmaBerry . berry . name [ i ] ;
battleBerry - > name [ i ] = EOS ;
for ( i = 0 ; i < BERRY_ITEM_EFFECT_COUNT ; i + + )
battleBerry - > itemEffect [ i ] = gSaveBlock1Ptr - > enigmaBerry . itemEffect [ i ] ;
battleBerry - > holdEffect = gSaveBlock1Ptr - > enigmaBerry . holdEffect ;
battleBerry - > holdEffectParam = gSaveBlock1Ptr - > enigmaBerry . holdEffectParam ;
}
else
{
2018-06-20 23:07:51 +02:00
const struct Berry * berryData = GetBerryInfo ( ItemIdToBerryType ( ITEM_ENIGMA_BERRY ) ) ;
2017-10-01 01:12:42 +02:00
2018-09-01 22:03:21 +02:00
for ( i = 0 ; i < BERRY_NAME_LENGTH ; i + + )
2017-10-01 01:12:42 +02:00
battleBerry - > name [ i ] = berryData - > name [ i ] ;
battleBerry - > name [ i ] = EOS ;
for ( i = 0 ; i < BERRY_ITEM_EFFECT_COUNT ; i + + )
battleBerry - > itemEffect [ i ] = 0 ;
battleBerry - > holdEffect = HOLD_EFFECT_NONE ;
battleBerry - > holdEffectParam = 0 ;
}
}
static void SetAllPlayersBerryData ( void )
{
s32 i ;
s32 j ;
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_LINK ) )
{
if ( IsEnigmaBerryValid ( ) = = TRUE )
{
2018-09-01 22:03:21 +02:00
for ( i = 0 ; i < BERRY_NAME_LENGTH ; i + + )
2017-10-01 01:12:42 +02:00
{
gEnigmaBerries [ 0 ] . name [ i ] = gSaveBlock1Ptr - > enigmaBerry . berry . name [ i ] ;
gEnigmaBerries [ 2 ] . name [ i ] = gSaveBlock1Ptr - > enigmaBerry . berry . name [ i ] ;
}
gEnigmaBerries [ 0 ] . name [ i ] = EOS ;
gEnigmaBerries [ 2 ] . name [ i ] = EOS ;
for ( i = 0 ; i < BERRY_ITEM_EFFECT_COUNT ; i + + )
{
gEnigmaBerries [ 0 ] . itemEffect [ i ] = gSaveBlock1Ptr - > enigmaBerry . itemEffect [ i ] ;
gEnigmaBerries [ 2 ] . itemEffect [ i ] = gSaveBlock1Ptr - > enigmaBerry . itemEffect [ i ] ;
}
gEnigmaBerries [ 0 ] . holdEffect = gSaveBlock1Ptr - > enigmaBerry . holdEffect ;
gEnigmaBerries [ 2 ] . holdEffect = gSaveBlock1Ptr - > enigmaBerry . holdEffect ;
gEnigmaBerries [ 0 ] . holdEffectParam = gSaveBlock1Ptr - > enigmaBerry . holdEffectParam ;
gEnigmaBerries [ 2 ] . holdEffectParam = gSaveBlock1Ptr - > enigmaBerry . holdEffectParam ;
}
else
{
2018-06-20 23:07:51 +02:00
const struct Berry * berryData = GetBerryInfo ( ItemIdToBerryType ( ITEM_ENIGMA_BERRY ) ) ;
2017-10-01 01:12:42 +02:00
2018-09-01 22:03:21 +02:00
for ( i = 0 ; i < BERRY_NAME_LENGTH ; i + + )
2017-10-01 01:12:42 +02:00
{
gEnigmaBerries [ 0 ] . name [ i ] = berryData - > name [ i ] ;
gEnigmaBerries [ 2 ] . name [ i ] = berryData - > name [ i ] ;
}
gEnigmaBerries [ 0 ] . name [ i ] = EOS ;
gEnigmaBerries [ 2 ] . name [ i ] = EOS ;
for ( i = 0 ; i < BERRY_ITEM_EFFECT_COUNT ; i + + )
{
gEnigmaBerries [ 0 ] . itemEffect [ i ] = 0 ;
gEnigmaBerries [ 2 ] . itemEffect [ i ] = 0 ;
}
gEnigmaBerries [ 0 ] . holdEffect = 0 ;
gEnigmaBerries [ 2 ] . holdEffect = 0 ;
gEnigmaBerries [ 0 ] . holdEffectParam = 0 ;
gEnigmaBerries [ 2 ] . holdEffectParam = 0 ;
}
}
else
{
s32 numPlayers ;
struct BattleEnigmaBerry * src ;
2018-06-20 23:07:51 +02:00
u8 battlerId ;
2017-10-01 01:12:42 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_MULTI )
{
if ( gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER )
numPlayers = 2 ;
else
numPlayers = 4 ;
for ( i = 0 ; i < numPlayers ; i + + )
{
src = ( struct BattleEnigmaBerry * ) ( gBlockRecvBuffer [ i ] + 2 ) ;
2018-07-22 13:14:58 +02:00
battlerId = gLinkPlayers [ i ] . id ;
2017-10-01 01:12:42 +02:00
2018-09-01 22:03:21 +02:00
for ( j = 0 ; j < BERRY_NAME_LENGTH ; j + + )
2018-06-20 23:07:51 +02:00
gEnigmaBerries [ battlerId ] . name [ j ] = src - > name [ j ] ;
gEnigmaBerries [ battlerId ] . name [ j ] = EOS ;
2017-10-01 01:12:42 +02:00
for ( j = 0 ; j < BERRY_ITEM_EFFECT_COUNT ; j + + )
2018-06-20 23:07:51 +02:00
gEnigmaBerries [ battlerId ] . itemEffect [ j ] = src - > itemEffect [ j ] ;
2017-10-01 01:12:42 +02:00
2018-06-20 23:07:51 +02:00
gEnigmaBerries [ battlerId ] . holdEffect = src - > holdEffect ;
gEnigmaBerries [ battlerId ] . holdEffectParam = src - > holdEffectParam ;
2017-10-01 01:12:42 +02:00
}
}
else
{
for ( i = 0 ; i < 2 ; i + + )
{
src = ( struct BattleEnigmaBerry * ) ( gBlockRecvBuffer [ i ] + 2 ) ;
2018-09-01 22:03:21 +02:00
for ( j = 0 ; j < BERRY_NAME_LENGTH ; j + + )
2017-10-01 01:12:42 +02:00
{
gEnigmaBerries [ i ] . name [ j ] = src - > name [ j ] ;
gEnigmaBerries [ i + 2 ] . name [ j ] = src - > name [ j ] ;
}
gEnigmaBerries [ i ] . name [ j ] = EOS ;
gEnigmaBerries [ i + 2 ] . name [ j ] = EOS ;
for ( j = 0 ; j < BERRY_ITEM_EFFECT_COUNT ; j + + )
{
gEnigmaBerries [ i ] . itemEffect [ j ] = src - > itemEffect [ j ] ;
gEnigmaBerries [ i + 2 ] . itemEffect [ j ] = src - > itemEffect [ j ] ;
}
gEnigmaBerries [ i ] . holdEffect = src - > holdEffect ;
gEnigmaBerries [ i + 2 ] . holdEffect = src - > holdEffect ;
gEnigmaBerries [ i ] . holdEffectParam = src - > holdEffectParam ;
gEnigmaBerries [ i + 2 ] . holdEffectParam = src - > holdEffectParam ;
}
}
}
}
2021-03-12 22:55:58 +01:00
// This was inlined in Ruby/Sapphire
static void FindLinkBattleMaster ( u8 numPlayers , u8 multiPlayerId )
2017-10-01 01:12:42 +02:00
{
2021-03-12 22:55:58 +01:00
u8 found = 0 ;
2017-10-01 01:12:42 +02:00
2021-03-12 22:55:58 +01:00
// If player 1 is playing the minimum version, player 1 is master.
if ( gBlockRecvBuffer [ 0 ] [ 0 ] = = 0x100 )
2017-10-01 01:12:42 +02:00
{
2021-03-12 22:55:58 +01:00
if ( multiPlayerId = = 0 )
2018-09-20 11:55:35 +02:00
gBattleTypeFlags | = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER ;
2017-10-01 01:12:42 +02:00
else
gBattleTypeFlags | = BATTLE_TYPE_TRAINER ;
2021-03-12 22:55:58 +01:00
found + + ;
2017-10-01 01:12:42 +02:00
}
2021-03-12 22:55:58 +01:00
if ( found = = 0 )
2017-10-01 01:12:42 +02:00
{
2021-03-12 22:55:58 +01:00
// If multiple different versions are being used, player 1 is master.
2017-10-01 01:12:42 +02:00
s32 i ;
2021-03-12 22:55:58 +01:00
for ( i = 0 ; i < numPlayers ; i + + )
2017-10-01 01:12:42 +02:00
{
if ( gBlockRecvBuffer [ 0 ] [ 0 ] ! = gBlockRecvBuffer [ i ] [ 0 ] )
break ;
}
2021-03-12 22:55:58 +01:00
if ( i = = numPlayers )
2017-10-01 01:12:42 +02:00
{
2021-03-12 22:55:58 +01:00
if ( multiPlayerId = = 0 )
2018-09-20 11:55:35 +02:00
gBattleTypeFlags | = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER ;
2017-10-01 01:12:42 +02:00
else
gBattleTypeFlags | = BATTLE_TYPE_TRAINER ;
2021-03-12 22:55:58 +01:00
found + + ;
2017-10-01 01:12:42 +02:00
}
2021-03-12 22:55:58 +01:00
if ( found = = 0 )
2017-10-01 01:12:42 +02:00
{
2021-03-12 22:55:58 +01:00
// Lowest index player with the highest game version is master.
for ( i = 0 ; i < numPlayers ; i + + )
2017-10-01 01:12:42 +02:00
{
2021-03-12 22:55:58 +01:00
if ( gBlockRecvBuffer [ i ] [ 0 ] = = 0x300 & & i ! = multiPlayerId )
2017-10-01 01:12:42 +02:00
{
2021-03-12 22:55:58 +01:00
if ( i < multiPlayerId )
2017-10-01 01:12:42 +02:00
break ;
}
2021-03-12 22:55:58 +01:00
if ( gBlockRecvBuffer [ i ] [ 0 ] > 0x300 & & i ! = multiPlayerId )
2017-10-01 01:12:42 +02:00
break ;
}
2021-03-12 22:55:58 +01:00
if ( i = = numPlayers )
2018-09-20 11:55:35 +02:00
gBattleTypeFlags | = BATTLE_TYPE_IS_MASTER | BATTLE_TYPE_TRAINER ;
2017-10-01 01:12:42 +02:00
else
gBattleTypeFlags | = BATTLE_TYPE_TRAINER ;
}
}
}
static void CB2_HandleStartBattle ( void )
{
u8 playerMultiplayerId ;
u8 enemyMultiplayerId ;
RunTasks ( ) ;
AnimateSprites ( ) ;
BuildOamBuffer ( ) ;
playerMultiplayerId = GetMultiplayerId ( ) ;
gBattleScripting . multiplayerId = playerMultiplayerId ;
enemyMultiplayerId = playerMultiplayerId ^ BIT_SIDE ;
switch ( gBattleCommunication [ MULTIUSE_STATE ] )
{
case 0 :
if ( ! IsDma3ManagerBusyWithBgCopy ( ) )
{
ShowBg ( 0 ) ;
ShowBg ( 1 ) ;
ShowBg ( 2 ) ;
ShowBg ( 3 ) ;
sub_805EF14 ( ) ;
gBattleCommunication [ MULTIUSE_STATE ] = 1 ;
}
2017-11-13 05:58:05 +01:00
if ( gWirelessCommType )
2019-04-04 23:05:46 +02:00
LoadWirelessStatusIndicatorSpriteGfx ( ) ;
2017-10-01 01:12:42 +02:00
break ;
case 1 :
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
if ( gReceivedRemoteLinkPlayers ! = 0 )
{
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
2021-03-12 22:55:58 +01:00
// 0x300
2021-03-15 20:22:41 +01:00
* ( & gBattleStruct - > multiBuffer . linkBattlerHeader . versionSignatureLo ) = 0 ;
* ( & gBattleStruct - > multiBuffer . linkBattlerHeader . versionSignatureHi ) = 3 ;
2021-01-23 05:22:37 +01:00
BufferPartyVsScreenHealth_AtStart ( ) ;
2017-10-01 01:12:42 +02:00
SetPlayerBerryDataInBattleStruct ( ) ;
2020-06-03 21:28:29 +02:00
if ( gTrainerBattleOpponent_A = = TRAINER_UNION_ROOM )
2017-10-01 01:12:42 +02:00
{
2018-07-22 12:49:49 +02:00
gLinkPlayers [ 0 ] . id = 0 ;
gLinkPlayers [ 1 ] . id = 1 ;
2017-10-01 01:12:42 +02:00
}
2021-03-15 20:22:41 +01:00
SendBlock ( bitmask_all_link_players_but_self ( ) , & gBattleStruct - > multiBuffer . linkBattlerHeader , sizeof ( gBattleStruct - > multiBuffer . linkBattlerHeader ) ) ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] = 2 ;
}
2017-11-13 05:58:05 +01:00
if ( gWirelessCommType )
2017-12-04 04:01:06 +01:00
CreateWirelessStatusIndicatorSprite ( 0 , 0 ) ;
2017-10-01 01:12:42 +02:00
}
}
else
{
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED ) )
2018-09-20 11:55:35 +02:00
gBattleTypeFlags | = BATTLE_TYPE_IS_MASTER ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] = 15 ;
SetAllPlayersBerryData ( ) ;
}
break ;
case 2 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
u8 taskId ;
ResetBlockReceivedFlags ( ) ;
2021-03-12 22:55:58 +01:00
FindLinkBattleMaster ( 2 , playerMultiplayerId ) ;
2017-10-01 01:12:42 +02:00
SetAllPlayersBerryData ( ) ;
2019-11-07 01:18:11 +01:00
taskId = CreateTask ( InitLinkBattleVsScreen , 0 ) ;
2017-10-01 01:12:42 +02:00
gTasks [ taskId ] . data [ 1 ] = 0x10E ;
gTasks [ taskId ] . data [ 2 ] = 0x5A ;
gTasks [ taskId ] . data [ 5 ] = 0 ;
2021-03-15 20:22:41 +01:00
gTasks [ taskId ] . data [ 3 ] = gBattleStruct - > multiBuffer . linkBattlerHeader . vsScreenHealthFlagsLo | ( gBattleStruct - > multiBuffer . linkBattlerHeader . vsScreenHealthFlagsHi < < 8 ) ;
2017-10-01 01:12:42 +02:00
gTasks [ taskId ] . data [ 4 ] = gBlockRecvBuffer [ enemyMultiplayerId ] [ 1 ] ;
2021-03-12 22:55:58 +01:00
RecordedBattle_SetFrontierPassFlagFromHword ( gBlockRecvBuffer [ playerMultiplayerId ] [ 1 ] ) ;
RecordedBattle_SetFrontierPassFlagFromHword ( gBlockRecvBuffer [ enemyMultiplayerId ] [ 1 ] ) ;
2018-02-09 15:55:12 +01:00
SetDeoxysStats ( ) ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 3 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , gPlayerParty , sizeof ( struct Pokemon ) * 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 4 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
ResetBlockReceivedFlags ( ) ;
memcpy ( gEnemyParty , gBlockRecvBuffer [ enemyMultiplayerId ] , sizeof ( struct Pokemon ) * 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 7 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , gPlayerParty + 2 , sizeof ( struct Pokemon ) * 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 8 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
ResetBlockReceivedFlags ( ) ;
memcpy ( gEnemyParty + 2 , gBlockRecvBuffer [ enemyMultiplayerId ] , sizeof ( struct Pokemon ) * 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 11 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , gPlayerParty + 4 , sizeof ( struct Pokemon ) * 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 12 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
ResetBlockReceivedFlags ( ) ;
memcpy ( gEnemyParty + 4 , gBlockRecvBuffer [ enemyMultiplayerId ] , sizeof ( struct Pokemon ) * 2 ) ;
2017-10-01 18:54:01 +02:00
TryCorrectShedinjaLanguage ( & gEnemyParty [ 0 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 1 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 2 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 3 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 4 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 5 ] ) ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 15 :
2021-01-22 08:48:22 +01:00
InitBattleControllers ( ) ;
2017-10-01 01:12:42 +02:00
sub_8184E58 ( ) ;
gBattleCommunication [ SPRITES_INIT_STATE1 ] = 0 ;
gBattleCommunication [ SPRITES_INIT_STATE2 ] = 0 ;
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
s32 i ;
2017-10-13 17:09:36 +02:00
for ( i = 0 ; i < 2 & & ( gLinkPlayers [ i ] . version & 0xFF ) = = VERSION_EMERALD ; i + + ) ;
2017-10-01 01:12:42 +02:00
if ( i = = 2 )
gBattleCommunication [ MULTIUSE_STATE ] = 16 ;
else
gBattleCommunication [ MULTIUSE_STATE ] = 18 ;
}
else
{
gBattleCommunication [ MULTIUSE_STATE ] = 18 ;
}
break ;
case 16 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , & gRecordedBattleRngSeed , sizeof ( gRecordedBattleRngSeed ) ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 17 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
ResetBlockReceivedFlags ( ) ;
2018-09-20 11:55:35 +02:00
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_IS_MASTER ) )
2017-10-01 01:12:42 +02:00
memcpy ( & gRecordedBattleRngSeed , gBlockRecvBuffer [ enemyMultiplayerId ] , sizeof ( gRecordedBattleRngSeed ) ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 18 :
if ( BattleInitAllSprites ( & gBattleCommunication [ SPRITES_INIT_STATE1 ] , & gBattleCommunication [ SPRITES_INIT_STATE2 ] ) )
{
gPreBattleCallback1 = gMain . callback1 ;
gMain . callback1 = BattleMainCB1 ;
SetMainCallback2 ( BattleMainCB2 ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
2021-01-13 21:17:32 +01:00
gBattleTypeFlags | = BATTLE_TYPE_LINK_IN_BATTLE ;
2017-10-01 01:12:42 +02:00
}
}
break ;
case 5 :
case 9 :
case 13 :
gBattleCommunication [ MULTIUSE_STATE ] + + ;
gBattleCommunication [ 1 ] = 1 ;
case 6 :
case 10 :
case 14 :
if ( - - gBattleCommunication [ 1 ] = = 0 )
gBattleCommunication [ MULTIUSE_STATE ] + + ;
break ;
}
}
static void CB2_HandleStartMultiPartnerBattle ( void )
{
u8 playerMultiplayerId ;
u8 enemyMultiplayerId ;
RunTasks ( ) ;
AnimateSprites ( ) ;
BuildOamBuffer ( ) ;
playerMultiplayerId = GetMultiplayerId ( ) ;
gBattleScripting . multiplayerId = playerMultiplayerId ;
enemyMultiplayerId = playerMultiplayerId ^ BIT_SIDE ;
switch ( gBattleCommunication [ MULTIUSE_STATE ] )
{
case 0 :
if ( ! IsDma3ManagerBusyWithBgCopy ( ) )
{
ShowBg ( 0 ) ;
ShowBg ( 1 ) ;
ShowBg ( 2 ) ;
ShowBg ( 3 ) ;
sub_805EF14 ( ) ;
gBattleCommunication [ MULTIUSE_STATE ] = 1 ;
}
2017-11-13 05:58:05 +01:00
if ( gWirelessCommType )
2019-04-04 23:05:46 +02:00
LoadWirelessStatusIndicatorSpriteGfx ( ) ;
2017-10-01 01:12:42 +02:00
// fall through
case 1 :
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
if ( gReceivedRemoteLinkPlayers ! = 0 )
{
u8 language ;
2018-07-22 12:49:49 +02:00
gLinkPlayers [ 0 ] . id = 0 ;
gLinkPlayers [ 1 ] . id = 2 ;
gLinkPlayers [ 2 ] . id = 1 ;
gLinkPlayers [ 3 ] . id = 3 ;
2017-10-01 01:12:42 +02:00
GetFrontierTrainerName ( gLinkPlayers [ 2 ] . name , gTrainerBattleOpponent_A ) ;
GetFrontierTrainerName ( gLinkPlayers [ 3 ] . name , gTrainerBattleOpponent_B ) ;
2018-10-24 23:14:45 +02:00
GetBattleTowerTrainerLanguage ( & language , gTrainerBattleOpponent_A ) ;
2017-10-01 01:12:42 +02:00
gLinkPlayers [ 2 ] . language = language ;
2018-10-24 23:14:45 +02:00
GetBattleTowerTrainerLanguage ( & language , gTrainerBattleOpponent_B ) ;
2017-10-01 01:12:42 +02:00
gLinkPlayers [ 3 ] . language = language ;
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
2021-03-12 22:55:58 +01:00
// 0x300
2021-03-15 20:22:41 +01:00
* ( & gBattleStruct - > multiBuffer . linkBattlerHeader . versionSignatureLo ) = 0 ;
* ( & gBattleStruct - > multiBuffer . linkBattlerHeader . versionSignatureHi ) = 3 ;
2021-01-23 05:22:37 +01:00
BufferPartyVsScreenHealth_AtStart ( ) ;
2017-10-01 01:12:42 +02:00
SetPlayerBerryDataInBattleStruct ( ) ;
2021-03-15 20:22:41 +01:00
SendBlock ( bitmask_all_link_players_but_self ( ) , & gBattleStruct - > multiBuffer . linkBattlerHeader , sizeof ( gBattleStruct - > multiBuffer . linkBattlerHeader ) ) ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] = 2 ;
}
2017-11-13 05:58:05 +01:00
if ( gWirelessCommType )
2017-12-04 04:01:06 +01:00
CreateWirelessStatusIndicatorSprite ( 0 , 0 ) ;
2017-10-01 01:12:42 +02:00
}
}
else
{
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED ) )
2018-09-20 11:55:35 +02:00
gBattleTypeFlags | = BATTLE_TYPE_IS_MASTER ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] = 13 ;
SetAllPlayersBerryData ( ) ;
}
break ;
case 2 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
u8 taskId ;
ResetBlockReceivedFlags ( ) ;
2021-03-12 22:55:58 +01:00
FindLinkBattleMaster ( 2 , playerMultiplayerId ) ;
2017-10-01 01:12:42 +02:00
SetAllPlayersBerryData ( ) ;
2019-11-07 01:18:11 +01:00
taskId = CreateTask ( InitLinkBattleVsScreen , 0 ) ;
2017-10-01 01:12:42 +02:00
gTasks [ taskId ] . data [ 1 ] = 0x10E ;
gTasks [ taskId ] . data [ 2 ] = 0x5A ;
gTasks [ taskId ] . data [ 5 ] = 0 ;
gTasks [ taskId ] . data [ 3 ] = 0x145 ;
gTasks [ taskId ] . data [ 4 ] = 0x145 ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 3 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , gPlayerParty , sizeof ( struct Pokemon ) * 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 4 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
ResetBlockReceivedFlags ( ) ;
2018-07-22 12:49:49 +02:00
if ( gLinkPlayers [ playerMultiplayerId ] . id ! = 0 )
2017-10-01 01:12:42 +02:00
{
memcpy ( gPlayerParty , gBlockRecvBuffer [ enemyMultiplayerId ] , sizeof ( struct Pokemon ) * 2 ) ;
2019-11-01 02:33:01 +01:00
memcpy ( gPlayerParty + MULTI_PARTY_SIZE , gBlockRecvBuffer [ playerMultiplayerId ] , sizeof ( struct Pokemon ) * 2 ) ;
2017-10-01 01:12:42 +02:00
}
else
{
memcpy ( gPlayerParty , gBlockRecvBuffer [ playerMultiplayerId ] , sizeof ( struct Pokemon ) * 2 ) ;
2019-11-01 02:33:01 +01:00
memcpy ( gPlayerParty + MULTI_PARTY_SIZE , gBlockRecvBuffer [ enemyMultiplayerId ] , sizeof ( struct Pokemon ) * 2 ) ;
2017-10-01 01:12:42 +02:00
}
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 5 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , gPlayerParty + 2 , sizeof ( struct Pokemon ) ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 6 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
ResetBlockReceivedFlags ( ) ;
2018-07-22 12:49:49 +02:00
if ( gLinkPlayers [ playerMultiplayerId ] . id ! = 0 )
2017-10-01 01:12:42 +02:00
{
memcpy ( gPlayerParty + 2 , gBlockRecvBuffer [ enemyMultiplayerId ] , sizeof ( struct Pokemon ) ) ;
memcpy ( gPlayerParty + 5 , gBlockRecvBuffer [ playerMultiplayerId ] , sizeof ( struct Pokemon ) ) ;
}
else
{
memcpy ( gPlayerParty + 2 , gBlockRecvBuffer [ playerMultiplayerId ] , sizeof ( struct Pokemon ) ) ;
memcpy ( gPlayerParty + 5 , gBlockRecvBuffer [ enemyMultiplayerId ] , sizeof ( struct Pokemon ) ) ;
}
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 7 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , gEnemyParty , sizeof ( struct Pokemon ) * 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 8 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
ResetBlockReceivedFlags ( ) ;
if ( GetMultiplayerId ( ) ! = 0 )
{
memcpy ( gEnemyParty , gBlockRecvBuffer [ 0 ] , sizeof ( struct Pokemon ) * 2 ) ;
}
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 9 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , gEnemyParty + 2 , sizeof ( struct Pokemon ) * 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 10 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
ResetBlockReceivedFlags ( ) ;
if ( GetMultiplayerId ( ) ! = 0 )
{
memcpy ( gEnemyParty + 2 , gBlockRecvBuffer [ 0 ] , sizeof ( struct Pokemon ) * 2 ) ;
}
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 11 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , gEnemyParty + 4 , sizeof ( struct Pokemon ) * 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 12 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
ResetBlockReceivedFlags ( ) ;
if ( GetMultiplayerId ( ) ! = 0 )
memcpy ( gEnemyParty + 4 , gBlockRecvBuffer [ 0 ] , sizeof ( struct Pokemon ) * 2 ) ;
2017-10-01 18:54:01 +02:00
TryCorrectShedinjaLanguage ( & gPlayerParty [ 0 ] ) ;
TryCorrectShedinjaLanguage ( & gPlayerParty [ 1 ] ) ;
TryCorrectShedinjaLanguage ( & gPlayerParty [ 2 ] ) ;
TryCorrectShedinjaLanguage ( & gPlayerParty [ 3 ] ) ;
TryCorrectShedinjaLanguage ( & gPlayerParty [ 4 ] ) ;
TryCorrectShedinjaLanguage ( & gPlayerParty [ 5 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 0 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 1 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 2 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 3 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 4 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 5 ] ) ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 13 :
2021-01-22 08:48:22 +01:00
InitBattleControllers ( ) ;
2017-10-01 01:12:42 +02:00
sub_8184E58 ( ) ;
gBattleCommunication [ SPRITES_INIT_STATE1 ] = 0 ;
gBattleCommunication [ SPRITES_INIT_STATE2 ] = 0 ;
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
gBattleCommunication [ MULTIUSE_STATE ] = 14 ;
}
else
{
gBattleCommunication [ MULTIUSE_STATE ] = 16 ;
}
break ;
case 14 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , & gRecordedBattleRngSeed , sizeof ( gRecordedBattleRngSeed ) ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 15 :
if ( ( GetBlockReceivedStatus ( ) & 3 ) = = 3 )
{
ResetBlockReceivedFlags ( ) ;
2018-09-20 11:55:35 +02:00
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_IS_MASTER ) )
2017-10-01 01:12:42 +02:00
memcpy ( & gRecordedBattleRngSeed , gBlockRecvBuffer [ enemyMultiplayerId ] , sizeof ( gRecordedBattleRngSeed ) ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 16 :
if ( BattleInitAllSprites ( & gBattleCommunication [ SPRITES_INIT_STATE1 ] , & gBattleCommunication [ SPRITES_INIT_STATE2 ] ) )
{
2020-12-24 22:18:47 +01:00
TrySetLinkBattleTowerEnemyPartyLevel ( ) ;
2017-10-01 01:12:42 +02:00
gPreBattleCallback1 = gMain . callback1 ;
gMain . callback1 = BattleMainCB1 ;
SetMainCallback2 ( BattleMainCB2 ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
2021-01-13 21:17:32 +01:00
gBattleTypeFlags | = BATTLE_TYPE_LINK_IN_BATTLE ;
2017-10-01 01:12:42 +02:00
}
}
break ;
}
}
static void sub_80379F8 ( u8 arrayIdPlus )
{
s32 i ;
2019-10-18 01:22:03 +02:00
for ( i = 0 ; i < ( int ) ARRAY_COUNT ( gMultiPartnerParty ) ; i + + )
2017-10-01 01:12:42 +02:00
{
2019-10-18 01:22:03 +02:00
gMultiPartnerParty [ i ] . species = GetMonData ( & gPlayerParty [ arrayIdPlus + i ] , MON_DATA_SPECIES ) ;
gMultiPartnerParty [ i ] . heldItem = GetMonData ( & gPlayerParty [ arrayIdPlus + i ] , MON_DATA_HELD_ITEM ) ;
GetMonData ( & gPlayerParty [ arrayIdPlus + i ] , MON_DATA_NICKNAME , gMultiPartnerParty [ i ] . nickname ) ;
gMultiPartnerParty [ i ] . level = GetMonData ( & gPlayerParty [ arrayIdPlus + i ] , MON_DATA_LEVEL ) ;
gMultiPartnerParty [ i ] . hp = GetMonData ( & gPlayerParty [ arrayIdPlus + i ] , MON_DATA_HP ) ;
gMultiPartnerParty [ i ] . maxhp = GetMonData ( & gPlayerParty [ arrayIdPlus + i ] , MON_DATA_MAX_HP ) ;
gMultiPartnerParty [ i ] . status = GetMonData ( & gPlayerParty [ arrayIdPlus + i ] , MON_DATA_STATUS ) ;
gMultiPartnerParty [ i ] . personality = GetMonData ( & gPlayerParty [ arrayIdPlus + i ] , MON_DATA_PERSONALITY ) ;
gMultiPartnerParty [ i ] . gender = GetMonGender ( & gPlayerParty [ arrayIdPlus + i ] ) ;
StripExtCtrlCodes ( gMultiPartnerParty [ i ] . nickname ) ;
2017-10-01 01:12:42 +02:00
if ( GetMonData ( & gPlayerParty [ arrayIdPlus + i ] , MON_DATA_LANGUAGE ) ! = LANGUAGE_JAPANESE )
2019-10-18 01:22:03 +02:00
PadNameString ( gMultiPartnerParty [ i ] . nickname , CHAR_SPACE ) ;
2017-10-01 01:12:42 +02:00
}
2019-10-18 01:22:03 +02:00
memcpy ( sMultiPartnerPartyBuffer , gMultiPartnerParty , sizeof ( gMultiPartnerParty ) ) ;
2017-10-01 01:12:42 +02:00
}
static void CB2_PreInitMultiBattle ( void )
{
s32 i ;
u8 playerMultiplierId ;
s32 numPlayers = 4 ;
u8 r4 = 0xF ;
2018-06-20 23:07:51 +02:00
u32 * savedBattleTypeFlags ;
2017-10-01 01:12:42 +02:00
void ( * * savedCallback ) ( void ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_BATTLE_TOWER )
{
numPlayers = 2 ;
r4 = 3 ;
}
playerMultiplierId = GetMultiplayerId ( ) ;
gBattleScripting . multiplayerId = playerMultiplierId ;
savedCallback = & gBattleStruct - > savedCallback ;
savedBattleTypeFlags = & gBattleStruct - > savedBattleTypeFlags ;
RunTasks ( ) ;
AnimateSprites ( ) ;
BuildOamBuffer ( ) ;
switch ( gBattleCommunication [ MULTIUSE_STATE ] )
{
case 0 :
2018-12-31 09:22:21 +01:00
if ( gReceivedRemoteLinkPlayers ! = 0 & & IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
2019-10-18 01:22:03 +02:00
sMultiPartnerPartyBuffer = Alloc ( sizeof ( struct UnknownPokemonStruct4 ) * ARRAY_COUNT ( gMultiPartnerParty ) ) ;
2017-10-01 01:12:42 +02:00
sub_80379F8 ( 0 ) ;
2019-10-18 01:22:03 +02:00
SendBlock ( bitmask_all_link_players_but_self ( ) , sMultiPartnerPartyBuffer , sizeof ( struct UnknownPokemonStruct4 ) * ARRAY_COUNT ( gMultiPartnerParty ) ) ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 1 :
if ( ( GetBlockReceivedStatus ( ) & r4 ) = = r4 )
{
ResetBlockReceivedFlags ( ) ;
for ( i = 0 ; i < numPlayers ; i + + )
{
if ( i = = playerMultiplierId )
continue ;
2019-10-18 01:22:03 +02:00
if ( numPlayers = = MAX_LINK_PLAYERS )
2017-10-01 01:12:42 +02:00
{
2018-07-22 12:49:49 +02:00
if ( ( ! ( gLinkPlayers [ i ] . id & 1 ) & & ! ( gLinkPlayers [ playerMultiplierId ] . id & 1 ) )
| | ( gLinkPlayers [ i ] . id & 1 & & gLinkPlayers [ playerMultiplierId ] . id & 1 ) )
2017-10-01 01:12:42 +02:00
{
2019-10-18 01:22:03 +02:00
memcpy ( gMultiPartnerParty , gBlockRecvBuffer [ i ] , sizeof ( struct UnknownPokemonStruct4 ) * ARRAY_COUNT ( gMultiPartnerParty ) ) ;
2017-10-01 01:12:42 +02:00
}
}
else
{
2019-10-18 01:22:03 +02:00
memcpy ( gMultiPartnerParty , gBlockRecvBuffer [ i ] , sizeof ( struct UnknownPokemonStruct4 ) * ARRAY_COUNT ( gMultiPartnerParty ) ) ;
2017-10-01 01:12:42 +02:00
}
}
gBattleCommunication [ MULTIUSE_STATE ] + + ;
* savedCallback = gMain . savedCallback ;
* savedBattleTypeFlags = gBattleTypeFlags ;
gMain . savedCallback = CB2_PreInitMultiBattle ;
2019-10-18 01:22:03 +02:00
ShowPartyMenuToShowcaseMultiBattleParty ( ) ;
2017-10-01 01:12:42 +02:00
}
break ;
case 2 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) & & ! gPaletteFade . active )
2017-10-01 01:12:42 +02:00
{
gBattleCommunication [ MULTIUSE_STATE ] + + ;
2017-11-13 05:58:05 +01:00
if ( gWirelessCommType )
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback ( ) ;
2017-10-01 01:12:42 +02:00
else
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback ( ) ;
2017-10-01 01:12:42 +02:00
}
break ;
case 3 :
2017-11-13 05:58:05 +01:00
if ( gWirelessCommType )
2017-10-01 01:12:42 +02:00
{
2019-10-09 11:56:44 +02:00
if ( IsLinkRfuTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
gBattleTypeFlags = * savedBattleTypeFlags ;
gMain . savedCallback = * savedCallback ;
SetMainCallback2 ( CB2_InitBattleInternal ) ;
2019-10-18 01:22:03 +02:00
Free ( sMultiPartnerPartyBuffer ) ;
sMultiPartnerPartyBuffer = NULL ;
2017-10-01 01:12:42 +02:00
}
}
else if ( gReceivedRemoteLinkPlayers = = 0 )
{
gBattleTypeFlags = * savedBattleTypeFlags ;
gMain . savedCallback = * savedCallback ;
SetMainCallback2 ( CB2_InitBattleInternal ) ;
2019-10-18 01:22:03 +02:00
Free ( sMultiPartnerPartyBuffer ) ;
sMultiPartnerPartyBuffer = NULL ;
2017-10-01 01:12:42 +02:00
}
break ;
}
}
static void CB2_PreInitIngamePlayerPartnerBattle ( void )
{
2018-06-20 23:07:51 +02:00
u32 * savedBattleTypeFlags ;
2017-10-01 01:12:42 +02:00
void ( * * savedCallback ) ( void ) ;
savedCallback = & gBattleStruct - > savedCallback ;
savedBattleTypeFlags = & gBattleStruct - > savedBattleTypeFlags ;
RunTasks ( ) ;
AnimateSprites ( ) ;
BuildOamBuffer ( ) ;
switch ( gBattleCommunication [ MULTIUSE_STATE ] )
{
case 0 :
2019-10-18 01:22:03 +02:00
sMultiPartnerPartyBuffer = Alloc ( sizeof ( struct UnknownPokemonStruct4 ) * ARRAY_COUNT ( gMultiPartnerParty ) ) ;
2017-10-01 01:12:42 +02:00
sub_80379F8 ( 3 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
* savedCallback = gMain . savedCallback ;
* savedBattleTypeFlags = gBattleTypeFlags ;
gMain . savedCallback = CB2_PreInitIngamePlayerPartnerBattle ;
2019-10-18 01:22:03 +02:00
ShowPartyMenuToShowcaseMultiBattleParty ( ) ;
2017-10-01 01:12:42 +02:00
break ;
case 1 :
if ( ! gPaletteFade . active )
{
gBattleCommunication [ MULTIUSE_STATE ] = 2 ;
gBattleTypeFlags = * savedBattleTypeFlags ;
gMain . savedCallback = * savedCallback ;
SetMainCallback2 ( CB2_InitBattleInternal ) ;
2019-10-18 01:22:03 +02:00
Free ( sMultiPartnerPartyBuffer ) ;
sMultiPartnerPartyBuffer = NULL ;
2017-10-01 01:12:42 +02:00
}
break ;
}
}
static void CB2_HandleStartMultiBattle ( void )
{
u8 playerMultiplayerId ;
s32 id ;
u8 var ;
playerMultiplayerId = GetMultiplayerId ( ) ;
gBattleScripting . multiplayerId = playerMultiplayerId ;
RunTasks ( ) ;
AnimateSprites ( ) ;
BuildOamBuffer ( ) ;
switch ( gBattleCommunication [ MULTIUSE_STATE ] )
{
case 0 :
if ( ! IsDma3ManagerBusyWithBgCopy ( ) )
{
ShowBg ( 0 ) ;
ShowBg ( 1 ) ;
ShowBg ( 2 ) ;
ShowBg ( 3 ) ;
sub_805EF14 ( ) ;
gBattleCommunication [ MULTIUSE_STATE ] = 1 ;
}
2017-11-13 05:58:05 +01:00
if ( gWirelessCommType )
2019-04-04 23:05:46 +02:00
LoadWirelessStatusIndicatorSpriteGfx ( ) ;
2017-10-01 01:12:42 +02:00
break ;
case 1 :
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
if ( gReceivedRemoteLinkPlayers ! = 0 )
{
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
2021-03-12 22:55:58 +01:00
// 0x300
2021-03-15 20:22:41 +01:00
* ( & gBattleStruct - > multiBuffer . linkBattlerHeader . versionSignatureLo ) = 0 ;
* ( & gBattleStruct - > multiBuffer . linkBattlerHeader . versionSignatureHi ) = 3 ;
2021-01-23 05:22:37 +01:00
BufferPartyVsScreenHealth_AtStart ( ) ;
2017-10-01 01:12:42 +02:00
SetPlayerBerryDataInBattleStruct ( ) ;
2021-03-15 20:22:41 +01:00
SendBlock ( bitmask_all_link_players_but_self ( ) , & gBattleStruct - > multiBuffer . linkBattlerHeader , sizeof ( gBattleStruct - > multiBuffer . linkBattlerHeader ) ) ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
2017-11-13 05:58:05 +01:00
if ( gWirelessCommType )
2017-12-04 04:01:06 +01:00
CreateWirelessStatusIndicatorSprite ( 0 , 0 ) ;
2017-10-01 01:12:42 +02:00
}
}
else
{
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED ) )
2018-09-20 11:55:35 +02:00
gBattleTypeFlags | = BATTLE_TYPE_IS_MASTER ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] = 7 ;
SetAllPlayersBerryData ( ) ;
}
break ;
case 2 :
if ( ( GetBlockReceivedStatus ( ) & 0xF ) = = 0xF )
{
ResetBlockReceivedFlags ( ) ;
2021-03-12 22:55:58 +01:00
FindLinkBattleMaster ( 4 , playerMultiplayerId ) ;
2017-10-01 01:12:42 +02:00
SetAllPlayersBerryData ( ) ;
2018-02-09 15:55:12 +01:00
SetDeoxysStats ( ) ;
2019-11-07 01:18:11 +01:00
var = CreateTask ( InitLinkBattleVsScreen , 0 ) ;
2017-10-01 01:12:42 +02:00
gTasks [ var ] . data [ 1 ] = 0x10E ;
gTasks [ var ] . data [ 2 ] = 0x5A ;
gTasks [ var ] . data [ 5 ] = 0 ;
gTasks [ var ] . data [ 3 ] = 0 ;
gTasks [ var ] . data [ 4 ] = 0 ;
for ( id = 0 ; id < MAX_LINK_PLAYERS ; id + + )
{
2021-03-12 22:55:58 +01:00
RecordedBattle_SetFrontierPassFlagFromHword ( gBlockRecvBuffer [ id ] [ 1 ] ) ;
2018-07-22 12:49:49 +02:00
switch ( gLinkPlayers [ id ] . id )
2017-10-01 01:12:42 +02:00
{
case 0 :
gTasks [ var ] . data [ 3 ] | = gBlockRecvBuffer [ id ] [ 1 ] & 0x3F ;
break ;
case 1 :
gTasks [ var ] . data [ 4 ] | = gBlockRecvBuffer [ id ] [ 1 ] & 0x3F ;
break ;
case 2 :
gTasks [ var ] . data [ 3 ] | = ( gBlockRecvBuffer [ id ] [ 1 ] & 0x3F ) < < 6 ;
break ;
case 3 :
gTasks [ var ] . data [ 4 ] | = ( gBlockRecvBuffer [ id ] [ 1 ] & 0x3F ) < < 6 ;
break ;
}
}
ZeroEnemyPartyMons ( ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
else
break ;
// fall through
case 3 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , gPlayerParty , sizeof ( struct Pokemon ) * 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 4 :
if ( ( GetBlockReceivedStatus ( ) & 0xF ) = = 0xF )
{
ResetBlockReceivedFlags ( ) ;
for ( id = 0 ; id < MAX_LINK_PLAYERS ; id + + )
{
if ( id = = playerMultiplayerId )
{
2018-07-22 12:49:49 +02:00
switch ( gLinkPlayers [ id ] . id )
2017-10-01 01:12:42 +02:00
{
case 0 :
case 3 :
memcpy ( gPlayerParty , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) * 2 ) ;
break ;
case 1 :
case 2 :
2019-11-01 02:33:01 +01:00
memcpy ( gPlayerParty + MULTI_PARTY_SIZE , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) * 2 ) ;
2017-10-01 01:12:42 +02:00
break ;
}
}
else
{
2018-07-22 12:49:49 +02:00
if ( ( ! ( gLinkPlayers [ id ] . id & 1 ) & & ! ( gLinkPlayers [ playerMultiplayerId ] . id & 1 ) )
| | ( ( gLinkPlayers [ id ] . id & 1 ) & & ( gLinkPlayers [ playerMultiplayerId ] . id & 1 ) ) )
2017-10-01 01:12:42 +02:00
{
2018-07-22 12:49:49 +02:00
switch ( gLinkPlayers [ id ] . id )
2017-10-01 01:12:42 +02:00
{
case 0 :
case 3 :
memcpy ( gPlayerParty , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) * 2 ) ;
break ;
case 1 :
case 2 :
2019-11-01 02:33:01 +01:00
memcpy ( gPlayerParty + MULTI_PARTY_SIZE , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) * 2 ) ;
2017-10-01 01:12:42 +02:00
break ;
}
}
else
{
2018-07-22 12:49:49 +02:00
switch ( gLinkPlayers [ id ] . id )
2017-10-01 01:12:42 +02:00
{
case 0 :
case 3 :
memcpy ( gEnemyParty , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) * 2 ) ;
break ;
case 1 :
case 2 :
2019-11-01 02:33:01 +01:00
memcpy ( gEnemyParty + MULTI_PARTY_SIZE , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) * 2 ) ;
2017-10-01 01:12:42 +02:00
break ;
}
}
}
}
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 5 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
SendBlock ( bitmask_all_link_players_but_self ( ) , gPlayerParty + 2 , sizeof ( struct Pokemon ) ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 6 :
if ( ( GetBlockReceivedStatus ( ) & 0xF ) = = 0xF )
{
ResetBlockReceivedFlags ( ) ;
for ( id = 0 ; id < MAX_LINK_PLAYERS ; id + + )
{
if ( id = = playerMultiplayerId )
{
2018-07-22 12:49:49 +02:00
switch ( gLinkPlayers [ id ] . id )
2017-10-01 01:12:42 +02:00
{
case 0 :
case 3 :
memcpy ( gPlayerParty + 2 , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) ) ;
break ;
case 1 :
case 2 :
memcpy ( gPlayerParty + 5 , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) ) ;
break ;
}
}
else
{
2018-07-22 12:49:49 +02:00
if ( ( ! ( gLinkPlayers [ id ] . id & 1 ) & & ! ( gLinkPlayers [ playerMultiplayerId ] . id & 1 ) )
| | ( ( gLinkPlayers [ id ] . id & 1 ) & & ( gLinkPlayers [ playerMultiplayerId ] . id & 1 ) ) )
2017-10-01 01:12:42 +02:00
{
2018-07-22 12:49:49 +02:00
switch ( gLinkPlayers [ id ] . id )
2017-10-01 01:12:42 +02:00
{
case 0 :
case 3 :
memcpy ( gPlayerParty + 2 , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) ) ;
break ;
case 1 :
case 2 :
memcpy ( gPlayerParty + 5 , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) ) ;
break ;
}
}
else
{
2018-07-22 12:49:49 +02:00
switch ( gLinkPlayers [ id ] . id )
2017-10-01 01:12:42 +02:00
{
case 0 :
case 3 :
memcpy ( gEnemyParty + 2 , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) ) ;
break ;
case 1 :
case 2 :
memcpy ( gEnemyParty + 5 , gBlockRecvBuffer [ id ] , sizeof ( struct Pokemon ) ) ;
break ;
}
}
}
}
2017-10-01 18:54:01 +02:00
TryCorrectShedinjaLanguage ( & gPlayerParty [ 0 ] ) ;
TryCorrectShedinjaLanguage ( & gPlayerParty [ 1 ] ) ;
TryCorrectShedinjaLanguage ( & gPlayerParty [ 2 ] ) ;
TryCorrectShedinjaLanguage ( & gPlayerParty [ 3 ] ) ;
TryCorrectShedinjaLanguage ( & gPlayerParty [ 4 ] ) ;
TryCorrectShedinjaLanguage ( & gPlayerParty [ 5 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 0 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 1 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 2 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 3 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 4 ] ) ;
TryCorrectShedinjaLanguage ( & gEnemyParty [ 5 ] ) ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 7 :
2021-01-22 08:48:22 +01:00
InitBattleControllers ( ) ;
2017-10-01 01:12:42 +02:00
sub_8184E58 ( ) ;
gBattleCommunication [ SPRITES_INIT_STATE1 ] = 0 ;
gBattleCommunication [ SPRITES_INIT_STATE2 ] = 0 ;
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
2019-09-08 18:21:24 +02:00
for ( id = 0 ; id < MAX_LINK_PLAYERS & & ( gLinkPlayers [ id ] . version & 0xFF ) = = VERSION_EMERALD ; id + + ) ;
2017-10-01 01:12:42 +02:00
2019-09-08 18:21:24 +02:00
if ( id = = MAX_LINK_PLAYERS )
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] = 8 ;
else
gBattleCommunication [ MULTIUSE_STATE ] = 10 ;
}
else
{
gBattleCommunication [ MULTIUSE_STATE ] = 10 ;
}
break ;
case 8 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) )
2017-10-01 01:12:42 +02:00
{
2021-03-12 21:37:31 +01:00
u32 * ptr = gBattleStruct - > multiBuffer . battleVideo ;
2017-10-01 01:12:42 +02:00
ptr [ 0 ] = gBattleTypeFlags ;
ptr [ 1 ] = gRecordedBattleRngSeed ; // UB: overwrites berry data
2021-03-12 21:37:31 +01:00
SendBlock ( bitmask_all_link_players_but_self ( ) , ptr , sizeof ( gBattleStruct - > multiBuffer . battleVideo ) ) ;
2017-10-01 01:12:42 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 9 :
if ( ( GetBlockReceivedStatus ( ) & 0xF ) = = 0xF )
{
ResetBlockReceivedFlags ( ) ;
for ( var = 0 ; var < 4 ; var + + )
{
u32 blockValue = gBlockRecvBuffer [ var ] [ 0 ] ;
if ( blockValue & 4 )
{
memcpy ( & gRecordedBattleRngSeed , & gBlockRecvBuffer [ var ] [ 2 ] , sizeof ( gRecordedBattleRngSeed ) ) ;
break ;
}
}
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 10 :
if ( BattleInitAllSprites ( & gBattleCommunication [ SPRITES_INIT_STATE1 ] , & gBattleCommunication [ SPRITES_INIT_STATE2 ] ) )
{
gPreBattleCallback1 = gMain . callback1 ;
gMain . callback1 = BattleMainCB1 ;
SetMainCallback2 ( BattleMainCB2 ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
2018-07-01 11:15:42 +02:00
gTrainerBattleOpponent_A = TRAINER_LINK_OPPONENT ;
2021-01-13 21:17:32 +01:00
gBattleTypeFlags | = BATTLE_TYPE_LINK_IN_BATTLE ;
2017-10-01 01:12:42 +02:00
}
}
break ;
}
}
2017-10-01 18:54:01 +02:00
void BattleMainCB2 ( void )
{
AnimateSprites ( ) ;
BuildOamBuffer ( ) ;
RunTextPrinters ( ) ;
UpdatePaletteFade ( ) ;
RunTasks ( ) ;
2020-09-05 03:11:55 +02:00
if ( JOY_HELD ( B_BUTTON ) & & gBattleTypeFlags & BATTLE_TYPE_RECORDED & & sub_8186450 ( ) )
2017-10-01 18:54:01 +02:00
{
2018-01-16 22:12:38 +01:00
gSpecialVar_Result = gBattleOutcome = B_OUTCOME_PLAYER_TELEPORTED ;
2017-10-01 18:54:01 +02:00
ResetPaletteFadeControl ( ) ;
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade ( PALETTES_ALL , 0 , 0 , 0x10 , RGB_BLACK ) ;
2017-10-01 18:54:01 +02:00
SetMainCallback2 ( CB2_QuitRecordedBattle ) ;
}
}
static void FreeRestoreBattleData ( void )
{
gMain . callback1 = gPreBattleCallback1 ;
2018-01-29 17:47:12 +01:00
gScanlineEffect . state = 3 ;
2017-10-01 18:54:01 +02:00
gMain . inBattle = 0 ;
ZeroEnemyPartyMons ( ) ;
2020-08-21 00:02:00 +02:00
m4aSongNumStop ( SE_LOW_HEALTH ) ;
2017-10-01 18:54:01 +02:00
FreeMonSpritesGfx ( ) ;
FreeBattleSpritesData ( ) ;
FreeBattleResources ( ) ;
}
void CB2_QuitRecordedBattle ( void )
{
UpdatePaletteFade ( ) ;
if ( ! gPaletteFade . active )
{
2018-01-10 04:30:54 +01:00
m4aMPlayStop ( & gMPlayInfo_SE1 ) ;
m4aMPlayStop ( & gMPlayInfo_SE2 ) ;
2017-10-01 18:54:01 +02:00
FreeRestoreBattleData ( ) ;
FreeAllWindowBuffers ( ) ;
SetMainCallback2 ( gMain . savedCallback ) ;
}
}
2017-10-09 20:32:26 +02:00
void sub_8038528 ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
2017-12-02 21:44:50 +01:00
sprite - > data [ 0 ] = 0 ;
2017-10-01 18:54:01 +02:00
sprite - > callback = sub_8038538 ;
}
static void sub_8038538 ( struct Sprite * sprite )
{
u16 * arr = ( u16 * ) ( gDecompressionBuffer ) ;
2017-12-02 21:44:50 +01:00
switch ( sprite - > data [ 0 ] )
2017-10-01 18:54:01 +02:00
{
case 0 :
2017-12-02 21:44:50 +01:00
sprite - > data [ 0 ] + + ;
sprite - > data [ 1 ] = 0 ;
sprite - > data [ 2 ] = 0x281 ;
sprite - > data [ 3 ] = 0 ;
sprite - > data [ 4 ] = 1 ;
2017-10-01 18:54:01 +02:00
// fall through
case 1 :
2017-12-02 21:44:50 +01:00
sprite - > data [ 4 ] - - ;
if ( sprite - > data [ 4 ] = = 0 )
2017-10-01 18:54:01 +02:00
{
s32 i ;
s32 r2 ;
s32 r0 ;
2017-12-02 21:44:50 +01:00
sprite - > data [ 4 ] = 2 ;
r2 = sprite - > data [ 1 ] + sprite - > data [ 3 ] * 32 ;
r0 = sprite - > data [ 2 ] - sprite - > data [ 3 ] * 32 ;
2017-10-01 18:54:01 +02:00
for ( i = 0 ; i < 29 ; i + = 2 )
{
arr [ r2 + i ] = 0x3D ;
arr [ r0 + i ] = 0x3D ;
}
2017-12-02 21:44:50 +01:00
sprite - > data [ 3 ] + + ;
if ( sprite - > data [ 3 ] = = 21 )
2017-10-01 18:54:01 +02:00
{
2017-12-02 21:44:50 +01:00
sprite - > data [ 0 ] + + ;
sprite - > data [ 1 ] = 32 ;
2017-10-01 18:54:01 +02:00
}
}
break ;
case 2 :
2017-12-02 21:44:50 +01:00
sprite - > data [ 1 ] - - ;
if ( sprite - > data [ 1 ] = = 20 )
2017-10-01 18:54:01 +02:00
SetMainCallback2 ( CB2_InitBattle ) ;
break ;
}
}
static u8 CreateNPCTrainerParty ( struct Pokemon * party , u16 trainerNum , bool8 firstTrainer )
{
u32 nameHash = 0 ;
u32 personalityValue ;
u8 fixedIV ;
s32 i , j ;
u8 monsCount ;
2018-06-30 18:55:34 +02:00
if ( trainerNum = = TRAINER_SECRET_BASE )
2017-10-01 18:54:01 +02:00
return 0 ;
if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER & & ! ( gBattleTypeFlags & ( BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_EREADER_TRAINER
2018-09-20 22:00:00 +02:00
| BATTLE_TYPE_TRAINER_HILL ) ) )
2017-10-01 18:54:01 +02:00
{
if ( firstTrainer = = TRUE )
ZeroEnemyPartyMons ( ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS )
{
if ( gTrainers [ trainerNum ] . partySize > 3 )
monsCount = 3 ;
else
monsCount = gTrainers [ trainerNum ] . partySize ;
}
else
{
monsCount = gTrainers [ trainerNum ] . partySize ;
}
for ( i = 0 ; i < monsCount ; i + + )
{
if ( gTrainers [ trainerNum ] . doubleBattle = = TRUE )
personalityValue = 0x80 ;
2021-06-25 17:50:09 +02:00
else if ( gTrainers [ trainerNum ] . encounterMusic_gender & F_TRAINER_FEMALE )
personalityValue = 0x78 ; // Use personality more likely to result in a female Pokémon
2017-10-01 18:54:01 +02:00
else
2021-06-25 17:50:09 +02:00
personalityValue = 0x88 ; // Use personality more likely to result in a male Pokémon
2017-10-01 18:54:01 +02:00
2018-02-08 11:17:41 +01:00
for ( j = 0 ; gTrainers [ trainerNum ] . trainerName [ j ] ! = EOS ; j + + )
2017-10-01 18:54:01 +02:00
nameHash + = gTrainers [ trainerNum ] . trainerName [ j ] ;
switch ( gTrainers [ trainerNum ] . partyFlags )
{
case 0 :
{
const struct TrainerMonNoItemDefaultMoves * partyData = gTrainers [ trainerNum ] . party . NoItemDefaultMoves ;
2017-12-17 21:19:08 +01:00
for ( j = 0 ; gSpeciesNames [ partyData [ i ] . species ] [ j ] ! = EOS ; j + + )
2017-10-01 18:54:01 +02:00
nameHash + = gSpeciesNames [ partyData [ i ] . species ] [ j ] ;
personalityValue + = nameHash < < 8 ;
2021-01-07 23:13:14 +01:00
fixedIV = partyData [ i ] . iv * MAX_PER_STAT_IVS / 255 ;
2017-10-01 18:54:01 +02:00
CreateMon ( & party [ i ] , partyData [ i ] . species , partyData [ i ] . lvl , fixedIV , TRUE , personalityValue , OT_ID_RANDOM_NO_SHINY , 0 ) ;
break ;
}
2017-12-17 21:19:08 +01:00
case F_TRAINER_PARTY_CUSTOM_MOVESET :
2017-10-01 18:54:01 +02:00
{
const struct TrainerMonNoItemCustomMoves * partyData = gTrainers [ trainerNum ] . party . NoItemCustomMoves ;
2017-12-17 21:19:08 +01:00
for ( j = 0 ; gSpeciesNames [ partyData [ i ] . species ] [ j ] ! = EOS ; j + + )
2017-10-01 18:54:01 +02:00
nameHash + = gSpeciesNames [ partyData [ i ] . species ] [ j ] ;
personalityValue + = nameHash < < 8 ;
2021-01-07 23:13:14 +01:00
fixedIV = partyData [ i ] . iv * MAX_PER_STAT_IVS / 255 ;
2019-08-31 05:06:43 +02:00
CreateMon ( & party [ i ] , partyData [ i ] . species , partyData [ i ] . lvl , fixedIV , TRUE , personalityValue , OT_ID_RANDOM_NO_SHINY , 0 ) ;
2017-10-01 18:54:01 +02:00
2018-12-25 18:50:15 +01:00
for ( j = 0 ; j < MAX_MON_MOVES ; j + + )
2017-10-01 18:54:01 +02:00
{
SetMonData ( & party [ i ] , MON_DATA_MOVE1 + j , & partyData [ i ] . moves [ j ] ) ;
SetMonData ( & party [ i ] , MON_DATA_PP1 + j , & gBattleMoves [ partyData [ i ] . moves [ j ] ] . pp ) ;
}
break ;
}
2017-12-17 21:19:08 +01:00
case F_TRAINER_PARTY_HELD_ITEM :
2017-10-01 18:54:01 +02:00
{
const struct TrainerMonItemDefaultMoves * partyData = gTrainers [ trainerNum ] . party . ItemDefaultMoves ;
2017-12-17 21:19:08 +01:00
for ( j = 0 ; gSpeciesNames [ partyData [ i ] . species ] [ j ] ! = EOS ; j + + )
2017-10-01 18:54:01 +02:00
nameHash + = gSpeciesNames [ partyData [ i ] . species ] [ j ] ;
personalityValue + = nameHash < < 8 ;
2021-01-07 23:13:14 +01:00
fixedIV = partyData [ i ] . iv * MAX_PER_STAT_IVS / 255 ;
2019-08-31 05:06:43 +02:00
CreateMon ( & party [ i ] , partyData [ i ] . species , partyData [ i ] . lvl , fixedIV , TRUE , personalityValue , OT_ID_RANDOM_NO_SHINY , 0 ) ;
2017-10-01 18:54:01 +02:00
SetMonData ( & party [ i ] , MON_DATA_HELD_ITEM , & partyData [ i ] . heldItem ) ;
break ;
}
2017-12-17 21:19:08 +01:00
case F_TRAINER_PARTY_CUSTOM_MOVESET | F_TRAINER_PARTY_HELD_ITEM :
2017-10-01 18:54:01 +02:00
{
const struct TrainerMonItemCustomMoves * partyData = gTrainers [ trainerNum ] . party . ItemCustomMoves ;
2017-12-17 21:19:08 +01:00
for ( j = 0 ; gSpeciesNames [ partyData [ i ] . species ] [ j ] ! = EOS ; j + + )
2017-10-01 18:54:01 +02:00
nameHash + = gSpeciesNames [ partyData [ i ] . species ] [ j ] ;
personalityValue + = nameHash < < 8 ;
2021-01-07 23:13:14 +01:00
fixedIV = partyData [ i ] . iv * MAX_PER_STAT_IVS / 255 ;
2019-08-31 05:06:43 +02:00
CreateMon ( & party [ i ] , partyData [ i ] . species , partyData [ i ] . lvl , fixedIV , TRUE , personalityValue , OT_ID_RANDOM_NO_SHINY , 0 ) ;
2017-10-01 18:54:01 +02:00
SetMonData ( & party [ i ] , MON_DATA_HELD_ITEM , & partyData [ i ] . heldItem ) ;
2018-12-25 18:50:15 +01:00
for ( j = 0 ; j < MAX_MON_MOVES ; j + + )
2017-10-01 18:54:01 +02:00
{
SetMonData ( & party [ i ] , MON_DATA_MOVE1 + j , & partyData [ i ] . moves [ j ] ) ;
SetMonData ( & party [ i ] , MON_DATA_PP1 + j , & gBattleMoves [ partyData [ i ] . moves [ j ] ] . pp ) ;
}
break ;
}
}
}
gBattleTypeFlags | = gTrainers [ trainerNum ] . doubleBattle ;
}
return gTrainers [ trainerNum ] . partySize ;
}
void VBlankCB_Battle ( void )
{
2018-06-20 23:07:51 +02:00
// Change gRngSeed every vblank unless the battle could be recorded.
2017-10-01 18:54:01 +02:00
if ( ! ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_RECORDED ) ) )
Random ( ) ;
SetGpuReg ( REG_OFFSET_BG0HOFS , gBattle_BG0_X ) ;
SetGpuReg ( REG_OFFSET_BG0VOFS , gBattle_BG0_Y ) ;
SetGpuReg ( REG_OFFSET_BG1HOFS , gBattle_BG1_X ) ;
SetGpuReg ( REG_OFFSET_BG1VOFS , gBattle_BG1_Y ) ;
SetGpuReg ( REG_OFFSET_BG2HOFS , gBattle_BG2_X ) ;
SetGpuReg ( REG_OFFSET_BG2VOFS , gBattle_BG2_Y ) ;
SetGpuReg ( REG_OFFSET_BG3HOFS , gBattle_BG3_X ) ;
SetGpuReg ( REG_OFFSET_BG3VOFS , gBattle_BG3_Y ) ;
SetGpuReg ( REG_OFFSET_WIN0H , gBattle_WIN0H ) ;
SetGpuReg ( REG_OFFSET_WIN0V , gBattle_WIN0V ) ;
SetGpuReg ( REG_OFFSET_WIN1H , gBattle_WIN1H ) ;
SetGpuReg ( REG_OFFSET_WIN1V , gBattle_WIN1V ) ;
LoadOam ( ) ;
ProcessSpriteCopyRequests ( ) ;
TransferPlttBuffer ( ) ;
2018-01-29 17:47:12 +01:00
ScanlineEffect_InitHBlankDmaTransfer ( ) ;
2017-10-01 18:54:01 +02:00
}
2021-01-23 05:22:37 +01:00
void SpriteCB_VsLetterDummy ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
}
2021-01-23 05:22:37 +01:00
static void SpriteCB_VsLetter ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
2017-12-02 21:44:50 +01:00
if ( sprite - > data [ 0 ] ! = 0 )
2021-07-07 15:11:52 +02:00
sprite - > x = sprite - > data [ 1 ] + ( ( sprite - > data [ 2 ] & 0xFF00 ) > > 8 ) ;
2017-10-01 18:54:01 +02:00
else
2021-07-07 15:11:52 +02:00
sprite - > x = sprite - > data [ 1 ] - ( ( sprite - > data [ 2 ] & 0xFF00 ) > > 8 ) ;
2017-10-01 18:54:01 +02:00
2017-12-02 21:44:50 +01:00
sprite - > data [ 2 ] + = 0x180 ;
2017-10-01 18:54:01 +02:00
if ( sprite - > affineAnimEnded )
{
2021-01-23 02:03:21 +01:00
FreeSpriteTilesByTag ( ANIM_SPRITES_START ) ;
FreeSpritePaletteByTag ( ANIM_SPRITES_START ) ;
2017-10-01 18:54:01 +02:00
FreeSpriteOamMatrix ( sprite ) ;
DestroySprite ( sprite ) ;
}
}
2021-01-23 05:22:37 +01:00
void SpriteCB_VsLetterInit ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
StartSpriteAffineAnim ( sprite , 1 ) ;
2021-01-23 05:22:37 +01:00
sprite - > callback = SpriteCB_VsLetter ;
2020-08-21 00:02:00 +02:00
PlaySE ( SE_MUGSHOT ) ;
2017-10-01 18:54:01 +02:00
}
2021-01-23 05:22:37 +01:00
static void BufferPartyVsScreenHealth_AtEnd ( u8 taskId )
2017-10-01 18:54:01 +02:00
{
2021-01-23 02:03:21 +01:00
struct Pokemon * party1 = NULL ;
struct Pokemon * party2 = NULL ;
u8 multiplayerId = gBattleScripting . multiplayerId ;
2021-01-23 05:22:37 +01:00
u32 flags ;
2017-10-01 18:54:01 +02:00
s32 i ;
if ( gBattleTypeFlags & BATTLE_TYPE_MULTI )
{
2021-01-23 02:03:21 +01:00
switch ( gLinkPlayers [ multiplayerId ] . id )
2017-10-01 18:54:01 +02:00
{
case 0 :
case 2 :
2021-01-23 02:03:21 +01:00
party1 = gPlayerParty ;
party2 = gEnemyParty ;
2017-10-01 18:54:01 +02:00
break ;
case 1 :
case 3 :
2021-01-23 02:03:21 +01:00
party1 = gEnemyParty ;
party2 = gPlayerParty ;
2017-10-01 18:54:01 +02:00
break ;
}
}
else
{
2021-01-23 02:03:21 +01:00
party1 = gPlayerParty ;
party2 = gEnemyParty ;
2017-10-01 18:54:01 +02:00
}
2021-01-23 05:22:37 +01:00
flags = 0 ;
BUFFER_PARTY_VS_SCREEN_STATUS ( party1 , flags , i ) ;
gTasks [ taskId ] . data [ 3 ] = flags ;
2017-10-01 18:54:01 +02:00
2021-01-23 05:22:37 +01:00
flags = 0 ;
BUFFER_PARTY_VS_SCREEN_STATUS ( party2 , flags , i ) ;
gTasks [ taskId ] . data [ 4 ] = flags ;
2017-10-01 18:54:01 +02:00
}
2021-01-23 02:03:21 +01:00
void CB2_InitEndLinkBattle ( void )
2017-10-01 18:54:01 +02:00
{
s32 i ;
u8 taskId ;
SetHBlankCallback ( NULL ) ;
SetVBlankCallback ( NULL ) ;
2021-01-13 21:17:32 +01:00
gBattleTypeFlags & = ~ ( BATTLE_TYPE_LINK_IN_BATTLE ) ;
2017-10-01 18:54:01 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_FRONTIER )
{
SetMainCallback2 ( gMain . savedCallback ) ;
FreeBattleResources ( ) ;
FreeBattleSpritesData ( ) ;
FreeMonSpritesGfx ( ) ;
}
else
{
CpuFill32 ( 0 , ( void * ) ( VRAM ) , VRAM_SIZE ) ;
SetGpuReg ( REG_OFFSET_MOSAIC , 0 ) ;
2021-01-23 02:03:21 +01:00
SetGpuReg ( REG_OFFSET_WIN0H , DISPLAY_WIDTH ) ;
SetGpuReg ( REG_OFFSET_WIN0V , WIN_RANGE ( DISPLAY_HEIGHT / 2 , DISPLAY_HEIGHT / 2 + 1 ) ) ;
2017-10-01 18:54:01 +02:00
SetGpuReg ( REG_OFFSET_WININ , 0 ) ;
SetGpuReg ( REG_OFFSET_WINOUT , 0 ) ;
2021-01-23 02:03:21 +01:00
gBattle_WIN0H = DISPLAY_WIDTH ;
gBattle_WIN0V = WIN_RANGE ( DISPLAY_HEIGHT / 2 , DISPLAY_HEIGHT / 2 + 1 ) ;
2018-01-29 17:47:12 +01:00
ScanlineEffect_Clear ( ) ;
2017-10-01 18:54:01 +02:00
2019-01-05 19:25:46 +01:00
i = 0 ;
while ( i < 80 )
2017-10-01 18:54:01 +02:00
{
2018-01-29 17:47:12 +01:00
gScanlineEffectRegBuffers [ 0 ] [ i ] = 0xF0 ;
gScanlineEffectRegBuffers [ 1 ] [ i ] = 0xF0 ;
2019-01-05 19:25:46 +01:00
i + + ;
2017-10-01 18:54:01 +02:00
}
2019-01-05 19:25:46 +01:00
while ( i < 160 )
2017-10-01 18:54:01 +02:00
{
2018-01-29 17:47:12 +01:00
gScanlineEffectRegBuffers [ 0 ] [ i ] = 0xFF10 ;
gScanlineEffectRegBuffers [ 1 ] [ i ] = 0xFF10 ;
2019-01-05 19:25:46 +01:00
i + + ;
2017-10-01 18:54:01 +02:00
}
ResetPaletteFade ( ) ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
gBattle_BG1_X = 0 ;
gBattle_BG1_Y = 0 ;
gBattle_BG2_X = 0 ;
gBattle_BG2_Y = 0 ;
gBattle_BG3_X = 0 ;
gBattle_BG3_Y = 0 ;
2019-11-07 01:18:11 +01:00
InitBattleBgsVideo ( ) ;
2017-12-17 20:10:57 +01:00
LoadCompressedPalette ( gBattleTextboxPalette , 0 , 64 ) ;
2018-06-17 16:48:58 +02:00
LoadBattleMenuWindowGfx ( ) ;
2017-10-01 18:54:01 +02:00
ResetSpriteData ( ) ;
ResetTasks ( ) ;
2018-06-17 16:48:58 +02:00
DrawBattleEntryBackground ( ) ;
2021-01-23 02:03:21 +01:00
SetGpuReg ( REG_OFFSET_WINOUT , WINOUT_WIN01_BG0 | WINOUT_WIN01_BG1 | WINOUT_WIN01_BG2 | WINOUT_WIN01_OBJ | WINOUT_WIN01_CLR ) ;
2017-10-01 18:54:01 +02:00
FreeAllSpritePalettes ( ) ;
gReservedSpritePaletteCount = 4 ;
SetVBlankCallback ( VBlankCB_Battle ) ;
2021-01-23 02:03:21 +01:00
// Show end Vs screen with battle results
2019-11-07 01:18:11 +01:00
taskId = CreateTask ( InitLinkBattleVsScreen , 0 ) ;
2017-10-01 18:54:01 +02:00
gTasks [ taskId ] . data [ 1 ] = 0x10E ;
gTasks [ taskId ] . data [ 2 ] = 0x5A ;
gTasks [ taskId ] . data [ 5 ] = 1 ;
2021-01-23 05:22:37 +01:00
BufferPartyVsScreenHealth_AtEnd ( taskId ) ;
2021-01-23 02:03:21 +01:00
SetMainCallback2 ( CB2_EndLinkBattle ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] = 0 ;
}
}
2021-01-23 02:03:21 +01:00
static void CB2_EndLinkBattle ( void )
2017-10-01 18:54:01 +02:00
{
2021-01-23 02:03:21 +01:00
EndLinkBattleInSteps ( ) ;
2017-10-01 18:54:01 +02:00
AnimateSprites ( ) ;
BuildOamBuffer ( ) ;
RunTextPrinters ( ) ;
UpdatePaletteFade ( ) ;
RunTasks ( ) ;
}
2021-01-23 02:03:21 +01:00
static void EndLinkBattleInSteps ( void )
2017-10-01 18:54:01 +02:00
{
s32 i ;
switch ( gBattleCommunication [ MULTIUSE_STATE ] )
{
case 0 :
ShowBg ( 0 ) ;
ShowBg ( 1 ) ;
ShowBg ( 2 ) ;
gBattleCommunication [ 1 ] = 0xFF ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
break ;
case 1 :
if ( - - gBattleCommunication [ 1 ] = = 0 )
{
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade ( PALETTES_ALL , 0 , 0 , 0x10 , RGB_BLACK ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 2 :
if ( ! gPaletteFade . active )
{
u8 monsCount ;
2021-03-15 20:22:41 +01:00
gMain . anyLinkBattlerHasFrontierPass = RecordedBattle_GetFrontierPassFlag ( ) ;
2017-10-01 18:54:01 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_MULTI )
monsCount = 4 ;
else
monsCount = 2 ;
2017-10-13 17:09:36 +02:00
for ( i = 0 ; i < monsCount & & ( gLinkPlayers [ i ] . version & 0xFF ) = = VERSION_EMERALD ; i + + ) ;
2017-10-01 18:54:01 +02:00
2019-12-14 09:58:20 +01:00
if ( ! gSaveBlock2Ptr - > frontier . disableRecordBattle & & i = = monsCount )
2017-10-01 18:54:01 +02:00
{
2017-11-08 22:20:10 +01:00
if ( FlagGet ( FLAG_SYS_FRONTIER_PASS ) )
2017-10-01 18:54:01 +02:00
{
FreeAllWindowBuffers ( ) ;
SetMainCallback2 ( sub_80392A8 ) ;
}
2021-03-15 20:22:41 +01:00
else if ( ! gMain . anyLinkBattlerHasFrontierPass )
2017-10-01 18:54:01 +02:00
{
SetMainCallback2 ( gMain . savedCallback ) ;
FreeBattleResources ( ) ;
FreeBattleSpritesData ( ) ;
FreeMonSpritesGfx ( ) ;
}
else if ( gReceivedRemoteLinkPlayers = = 0 )
{
2021-03-04 23:48:40 +01:00
CreateTask ( Task_ReconnectWithLinkPlayers , 5 ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
else
{
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
}
else
{
SetMainCallback2 ( gMain . savedCallback ) ;
FreeBattleResources ( ) ;
FreeBattleSpritesData ( ) ;
FreeMonSpritesGfx ( ) ;
}
}
break ;
case 3 :
CpuFill32 ( 0 , ( void * ) ( VRAM ) , VRAM_SIZE ) ;
for ( i = 0 ; i < 2 ; i + + )
LoadChosenBattleElement ( i ) ;
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade ( PALETTES_ALL , 0 , 0x10 , 0 , RGB_BLACK ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
break ;
case 4 :
if ( ! gPaletteFade . active )
gBattleCommunication [ MULTIUSE_STATE ] + + ;
break ;
case 5 :
2021-03-04 23:48:40 +01:00
if ( ! FuncIsActiveTask ( Task_ReconnectWithLinkPlayers ) )
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
break ;
case 6 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) = = TRUE )
2017-10-01 18:54:01 +02:00
{
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback ( ) ;
2018-06-17 16:48:58 +02:00
BattlePutTextOnWindow ( gText_LinkStandby3 , 0 ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 7 :
if ( ! IsTextPrinterActive ( 0 ) )
{
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) = = TRUE )
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 8 :
2017-11-13 05:58:05 +01:00
if ( ! gWirelessCommType )
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback ( ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
break ;
case 9 :
2021-03-15 20:22:41 +01:00
if ( ! gMain . anyLinkBattlerHasFrontierPass | | gWirelessCommType | | gReceivedRemoteLinkPlayers ! = 1 )
2017-10-01 18:54:01 +02:00
{
2021-03-15 20:22:41 +01:00
gMain . anyLinkBattlerHasFrontierPass = 0 ;
2017-10-01 18:54:01 +02:00
SetMainCallback2 ( gMain . savedCallback ) ;
FreeBattleResources ( ) ;
FreeBattleSpritesData ( ) ;
FreeMonSpritesGfx ( ) ;
}
break ;
}
}
2021-01-23 05:22:37 +01:00
u32 GetBattleBgTemplateData ( u8 arrayId , u8 caseId )
2017-10-01 18:54:01 +02:00
{
u32 ret = 0 ;
switch ( caseId )
{
case 0 :
2018-06-17 16:48:58 +02:00
ret = gBattleBgTemplates [ arrayId ] . bg ;
2017-10-01 18:54:01 +02:00
break ;
case 1 :
2018-06-17 16:48:58 +02:00
ret = gBattleBgTemplates [ arrayId ] . charBaseIndex ;
2017-10-01 18:54:01 +02:00
break ;
case 2 :
2018-06-17 16:48:58 +02:00
ret = gBattleBgTemplates [ arrayId ] . mapBaseIndex ;
2017-10-01 18:54:01 +02:00
break ;
case 3 :
2018-06-17 16:48:58 +02:00
ret = gBattleBgTemplates [ arrayId ] . screenSize ;
2017-10-01 18:54:01 +02:00
break ;
case 4 :
2018-06-17 16:48:58 +02:00
ret = gBattleBgTemplates [ arrayId ] . paletteMode ;
2017-10-01 18:54:01 +02:00
break ;
2021-01-23 05:22:37 +01:00
case 5 : // Only this case is used
2018-06-17 16:48:58 +02:00
ret = gBattleBgTemplates [ arrayId ] . priority ;
2017-10-01 18:54:01 +02:00
break ;
case 6 :
2018-06-17 16:48:58 +02:00
ret = gBattleBgTemplates [ arrayId ] . baseTile ;
2017-10-01 18:54:01 +02:00
break ;
}
return ret ;
}
static void sub_80392A8 ( void )
{
s32 i ;
SetHBlankCallback ( NULL ) ;
SetVBlankCallback ( NULL ) ;
CpuFill32 ( 0 , ( void * ) ( VRAM ) , VRAM_SIZE ) ;
ResetPaletteFade ( ) ;
gBattle_BG0_X = 0 ;
gBattle_BG0_Y = 0 ;
gBattle_BG1_X = 0 ;
gBattle_BG1_Y = 0 ;
gBattle_BG2_X = 0 ;
gBattle_BG2_Y = 0 ;
gBattle_BG3_X = 0 ;
gBattle_BG3_Y = 0 ;
2019-11-07 01:18:11 +01:00
InitBattleBgsVideo ( ) ;
2017-10-01 18:54:01 +02:00
SetGpuReg ( REG_OFFSET_DISPCNT , DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP ) ;
2018-06-17 16:48:58 +02:00
LoadBattleMenuWindowGfx ( ) ;
2017-10-01 18:54:01 +02:00
for ( i = 0 ; i < 2 ; i + + )
LoadChosenBattleElement ( i ) ;
ResetSpriteData ( ) ;
ResetTasks ( ) ;
FreeAllSpritePalettes ( ) ;
gReservedSpritePaletteCount = 4 ;
SetVBlankCallback ( VBlankCB_Battle ) ;
SetMainCallback2 ( sub_803937C ) ;
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade ( PALETTES_ALL , 0 , 0x10 , 0 , RGB_BLACK ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] = 0 ;
}
static void sub_803937C ( void )
{
sub_803939C ( ) ;
AnimateSprites ( ) ;
BuildOamBuffer ( ) ;
RunTextPrinters ( ) ;
UpdatePaletteFade ( ) ;
RunTasks ( ) ;
}
static void sub_803939C ( void )
{
switch ( gBattleCommunication [ MULTIUSE_STATE ] )
{
case 0 :
ShowBg ( 0 ) ;
ShowBg ( 1 ) ;
ShowBg ( 2 ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
break ;
case 1 :
2021-03-15 20:22:41 +01:00
if ( gMain . anyLinkBattlerHasFrontierPass & & gReceivedRemoteLinkPlayers = = 0 )
2021-03-04 23:48:40 +01:00
CreateTask ( Task_ReconnectWithLinkPlayers , 5 ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
break ;
case 2 :
2021-03-04 23:48:40 +01:00
if ( ! FuncIsActiveTask ( Task_ReconnectWithLinkPlayers ) )
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
break ;
case 3 :
if ( ! gPaletteFade . active )
{
2018-06-17 16:48:58 +02:00
BattlePutTextOnWindow ( gText_RecordBattleToPass , 0 ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 4 :
if ( ! IsTextPrinterActive ( 0 ) )
{
2017-10-29 16:15:23 +01:00
HandleBattleWindow ( 0x18 , 8 , 0x1D , 0xD , 0 ) ;
2018-06-17 16:48:58 +02:00
BattlePutTextOnWindow ( gText_BattleYesNoChoice , 0xC ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ CURSOR_POSITION ] = 1 ;
2017-10-29 16:15:23 +01:00
BattleCreateYesNoCursorAt ( 1 ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 5 :
2020-09-05 03:11:55 +02:00
if ( JOY_NEW ( DPAD_UP ) )
2017-10-01 18:54:01 +02:00
{
if ( gBattleCommunication [ CURSOR_POSITION ] ! = 0 )
{
PlaySE ( SE_SELECT ) ;
2017-10-29 16:15:23 +01:00
BattleDestroyYesNoCursorAt ( gBattleCommunication [ CURSOR_POSITION ] ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ CURSOR_POSITION ] = 0 ;
2017-10-29 16:15:23 +01:00
BattleCreateYesNoCursorAt ( 0 ) ;
2017-10-01 18:54:01 +02:00
}
}
2020-09-05 03:11:55 +02:00
else if ( JOY_NEW ( DPAD_DOWN ) )
2017-10-01 18:54:01 +02:00
{
if ( gBattleCommunication [ CURSOR_POSITION ] = = 0 )
{
PlaySE ( SE_SELECT ) ;
2017-10-29 16:15:23 +01:00
BattleDestroyYesNoCursorAt ( gBattleCommunication [ CURSOR_POSITION ] ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ CURSOR_POSITION ] = 1 ;
2017-10-29 16:15:23 +01:00
BattleCreateYesNoCursorAt ( 1 ) ;
2017-10-01 18:54:01 +02:00
}
}
2020-09-05 03:11:55 +02:00
else if ( JOY_NEW ( A_BUTTON ) )
2017-10-01 18:54:01 +02:00
{
PlaySE ( SE_SELECT ) ;
if ( gBattleCommunication [ CURSOR_POSITION ] = = 0 )
{
2017-10-22 01:04:02 +02:00
HandleBattleWindow ( 0x18 , 8 , 0x1D , 0xD , WINDOW_CLEAR ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ 1 ] = MoveRecordedBattleToSaveData ( ) ;
gBattleCommunication [ MULTIUSE_STATE ] = 10 ;
}
else
{
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
}
2020-09-05 03:11:55 +02:00
else if ( JOY_NEW ( B_BUTTON ) )
2017-10-01 18:54:01 +02:00
{
PlaySE ( SE_SELECT ) ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 6 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) = = TRUE )
2017-10-01 18:54:01 +02:00
{
2017-10-22 01:04:02 +02:00
HandleBattleWindow ( 0x18 , 8 , 0x1D , 0xD , WINDOW_CLEAR ) ;
2021-03-15 20:22:41 +01:00
if ( gMain . anyLinkBattlerHasFrontierPass )
2017-10-01 18:54:01 +02:00
{
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback ( ) ;
2018-06-17 16:48:58 +02:00
BattlePutTextOnWindow ( gText_LinkStandby3 , 0 ) ;
2017-10-01 18:54:01 +02:00
}
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 8 :
if ( - - gBattleCommunication [ 1 ] = = 0 )
{
2021-03-15 20:22:41 +01:00
if ( gMain . anyLinkBattlerHasFrontierPass & & ! gWirelessCommType )
2020-08-13 09:09:47 +02:00
SetCloseLinkCallback ( ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 9 :
2021-03-15 20:22:41 +01:00
if ( ! gMain . anyLinkBattlerHasFrontierPass | | gWirelessCommType | | gReceivedRemoteLinkPlayers ! = 1 )
2017-10-01 18:54:01 +02:00
{
2021-03-15 20:22:41 +01:00
gMain . anyLinkBattlerHasFrontierPass = 0 ;
2017-10-01 18:54:01 +02:00
if ( ! gPaletteFade . active )
{
SetMainCallback2 ( gMain . savedCallback ) ;
FreeBattleResources ( ) ;
FreeBattleSpritesData ( ) ;
FreeMonSpritesGfx ( ) ;
}
}
break ;
case 10 :
if ( gBattleCommunication [ 1 ] = = 1 )
{
PlaySE ( SE_SAVE ) ;
BattleStringExpandPlaceholdersToDisplayedString ( gText_BattleRecordedOnPass ) ;
2018-06-17 16:48:58 +02:00
BattlePutTextOnWindow ( gDisplayedStringBattle , 0 ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ 1 ] = 0x80 ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
else
{
2019-12-14 09:58:20 +01:00
BattleStringExpandPlaceholdersToDisplayedString ( BattleFrontier_BattleTowerBattleRoom_Text_RecordCouldntBeSaved ) ;
2018-06-17 16:48:58 +02:00
BattlePutTextOnWindow ( gDisplayedStringBattle , 0 ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ 1 ] = 0x80 ;
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 11 :
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) = = TRUE & & ! IsTextPrinterActive ( 0 ) & & - - gBattleCommunication [ 1 ] = = 0 )
2017-10-01 18:54:01 +02:00
{
2021-03-15 20:22:41 +01:00
if ( gMain . anyLinkBattlerHasFrontierPass )
2017-10-01 18:54:01 +02:00
{
2020-08-13 09:09:47 +02:00
SetLinkStandbyCallback ( ) ;
2018-06-17 16:48:58 +02:00
BattlePutTextOnWindow ( gText_LinkStandby3 , 0 ) ;
2017-10-01 18:54:01 +02:00
}
gBattleCommunication [ MULTIUSE_STATE ] + + ;
}
break ;
case 12 :
case 7 :
if ( ! IsTextPrinterActive ( 0 ) )
{
2021-03-15 20:22:41 +01:00
if ( gMain . anyLinkBattlerHasFrontierPass )
2017-10-01 18:54:01 +02:00
{
2018-12-31 09:22:21 +01:00
if ( IsLinkTaskFinished ( ) = = TRUE )
2017-10-01 18:54:01 +02:00
{
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade ( PALETTES_ALL , 0 , 0 , 0x10 , RGB_BLACK ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ 1 ] = 0x20 ;
gBattleCommunication [ MULTIUSE_STATE ] = 8 ;
}
}
else
{
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade ( PALETTES_ALL , 0 , 0 , 0x10 , RGB_BLACK ) ;
2017-10-01 18:54:01 +02:00
gBattleCommunication [ 1 ] = 0x20 ;
gBattleCommunication [ MULTIUSE_STATE ] = 8 ;
}
}
break ;
}
}
static void TryCorrectShedinjaLanguage ( struct Pokemon * mon )
{
u8 nickname [ POKEMON_NAME_LENGTH + 1 ] ;
u8 language = LANGUAGE_JAPANESE ;
if ( GetMonData ( mon , MON_DATA_SPECIES ) = = SPECIES_SHEDINJA
& & GetMonData ( mon , MON_DATA_LANGUAGE ) ! = language )
{
GetMonData ( mon , MON_DATA_NICKNAME , nickname ) ;
2018-12-23 14:52:47 +01:00
if ( StringCompareWithoutExtCtrlCodes ( nickname , sText_ShedinjaJpnName ) = = 0 )
2017-10-01 18:54:01 +02:00
SetMonData ( mon , MON_DATA_LANGUAGE , & language ) ;
}
}
2021-01-23 05:22:37 +01:00
u32 GetBattleWindowTemplatePixelWidth ( u32 setId , u32 tableId )
2017-10-01 18:54:01 +02:00
{
2018-06-17 16:48:58 +02:00
return gBattleWindowTemplates [ setId ] [ tableId ] . width * 8 ;
2017-10-01 18:54:01 +02:00
}
2018-02-06 23:09:39 +01:00
# define sBattler data[0]
# define sSpeciesId data[2]
2017-10-01 18:54:01 +02:00
2018-12-23 14:52:47 +01:00
void SpriteCb_WildMon ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
2018-12-23 14:52:47 +01:00
sprite - > callback = SpriteCb_MoveWildMonToRight ;
2017-10-01 18:54:01 +02:00
StartSpriteAnimIfDifferent ( sprite , 0 ) ;
2018-10-16 22:19:53 +02:00
if ( WILD_DOUBLE_BATTLE )
BeginNormalPaletteFade ( ( 0x10000 < < sprite - > sBattler ) | ( 0x10000 < < BATTLE_PARTNER ( sprite - > sBattler ) ) , 0 , 10 , 10 , RGB ( 8 , 8 , 8 ) ) ;
else
BeginNormalPaletteFade ( ( 0x10000 < < sprite - > sBattler ) , 0 , 10 , 10 , RGB ( 8 , 8 , 8 ) ) ;
2017-10-01 18:54:01 +02:00
}
2018-12-23 14:52:47 +01:00
static void SpriteCb_MoveWildMonToRight ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
2018-02-08 11:17:41 +01:00
if ( ( gIntroSlideFlags & 1 ) = = 0 )
2017-10-01 18:54:01 +02:00
{
2021-07-07 15:11:52 +02:00
sprite - > x2 + = 2 ;
if ( sprite - > x2 = = 0 )
2017-10-01 18:54:01 +02:00
{
2018-12-23 14:52:47 +01:00
sprite - > callback = SpriteCb_WildMonShowHealthbox ;
2017-10-01 18:54:01 +02:00
}
}
}
2018-12-23 14:52:47 +01:00
static void SpriteCb_WildMonShowHealthbox ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
if ( sprite - > animEnded )
{
2021-01-23 02:03:21 +01:00
StartHealthboxSlideIn ( sprite - > sBattler ) ;
2018-02-06 23:09:39 +01:00
SetHealthboxSpriteVisible ( gHealthboxSpriteIds [ sprite - > sBattler ] ) ;
2018-12-23 14:52:47 +01:00
sprite - > callback = SpriteCb_WildMonAnimate ;
2017-10-01 18:54:01 +02:00
StartSpriteAnimIfDifferent ( sprite , 0 ) ;
2018-10-16 22:19:53 +02:00
if ( WILD_DOUBLE_BATTLE )
BeginNormalPaletteFade ( ( 0x10000 < < sprite - > sBattler ) | ( 0x10000 < < BATTLE_PARTNER ( sprite - > sBattler ) ) , 0 , 10 , 0 , RGB ( 8 , 8 , 8 ) ) ;
else
BeginNormalPaletteFade ( ( 0x10000 < < sprite - > sBattler ) , 0 , 10 , 0 , RGB ( 8 , 8 , 8 ) ) ;
2017-10-01 18:54:01 +02:00
}
}
2018-12-23 14:52:47 +01:00
static void SpriteCb_WildMonAnimate ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
if ( ! gPaletteFade . active )
{
2018-02-06 23:09:39 +01:00
BattleAnimateFrontSprite ( sprite , sprite - > sSpeciesId , FALSE , 1 ) ;
2017-10-01 18:54:01 +02:00
}
}
void SpriteCallbackDummy_2 ( struct Sprite * sprite )
{
}
static void sub_80398D0 ( struct Sprite * sprite )
{
2017-12-02 21:44:50 +01:00
sprite - > data [ 4 ] - - ;
if ( sprite - > data [ 4 ] = = 0 )
2017-10-01 18:54:01 +02:00
{
2017-12-02 21:44:50 +01:00
sprite - > data [ 4 ] = 8 ;
2017-10-01 18:54:01 +02:00
sprite - > invisible ^ = 1 ;
2017-12-02 21:44:50 +01:00
sprite - > data [ 3 ] - - ;
if ( sprite - > data [ 3 ] = = 0 )
2017-10-01 18:54:01 +02:00
{
sprite - > invisible = FALSE ;
sprite - > callback = SpriteCallbackDummy_2 ;
2018-11-24 01:02:02 +01:00
// sUnusedUnknownArray[0] = 0;
2017-10-01 18:54:01 +02:00
}
}
}
extern const struct MonCoords gMonFrontPicCoords [ ] ;
extern const struct MonCoords gCastformFrontSpriteCoords [ ] ;
2018-06-20 23:07:51 +02:00
void SpriteCB_FaintOpponentMon ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
2018-02-06 23:09:39 +01:00
u8 battler = sprite - > sBattler ;
2017-10-01 18:54:01 +02:00
u16 species ;
u8 yOffset ;
2018-02-06 23:09:39 +01:00
if ( gBattleSpritesDataPtr - > battlerData [ battler ] . transformSpecies ! = 0 )
species = gBattleSpritesDataPtr - > battlerData [ battler ] . transformSpecies ;
2017-10-01 18:54:01 +02:00
else
2018-02-06 23:09:39 +01:00
species = sprite - > sSpeciesId ;
2017-10-01 18:54:01 +02:00
2018-06-20 23:07:51 +02:00
GetMonData ( & gEnemyParty [ gBattlerPartyIndexes [ battler ] ] , MON_DATA_PERSONALITY ) ; // Unused return value.
2017-10-01 18:54:01 +02:00
if ( species = = SPECIES_UNOWN )
{
2018-02-06 23:09:39 +01:00
u32 personalityValue = GetMonData ( & gEnemyParty [ gBattlerPartyIndexes [ battler ] ] , MON_DATA_PERSONALITY ) ;
2021-01-19 10:03:16 +01:00
u16 unownForm = GET_UNOWN_LETTER ( personalityValue ) ;
2017-10-01 18:54:01 +02:00
u16 unownSpecies ;
if ( unownForm = = 0 )
2018-06-20 23:07:51 +02:00
unownSpecies = SPECIES_UNOWN ; // Use the A Unown form.
2017-10-01 18:54:01 +02:00
else
2018-06-20 23:07:51 +02:00
unownSpecies = NUM_SPECIES + unownForm ; // Use one of the other Unown letters.
2017-10-01 18:54:01 +02:00
yOffset = gMonFrontPicCoords [ unownSpecies ] . y_offset ;
}
else if ( species = = SPECIES_CASTFORM )
{
2018-02-06 23:09:39 +01:00
yOffset = gCastformFrontSpriteCoords [ gBattleMonForms [ battler ] ] . y_offset ;
2017-10-01 18:54:01 +02:00
}
else if ( species > NUM_SPECIES )
{
yOffset = gMonFrontPicCoords [ SPECIES_NONE ] . y_offset ;
}
else
{
yOffset = gMonFrontPicCoords [ species ] . y_offset ;
}
2017-12-02 21:44:50 +01:00
sprite - > data [ 3 ] = 8 - yOffset / 8 ;
sprite - > data [ 4 ] = 1 ;
2018-06-20 23:07:51 +02:00
sprite - > callback = SpriteCB_AnimFaintOpponent ;
2017-10-01 18:54:01 +02:00
}
2018-06-20 23:07:51 +02:00
static void SpriteCB_AnimFaintOpponent ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
s32 i ;
2018-06-20 23:07:51 +02:00
if ( - - sprite - > data [ 4 ] = = 0 )
2017-10-01 18:54:01 +02:00
{
2017-12-02 21:44:50 +01:00
sprite - > data [ 4 ] = 2 ;
2021-07-07 15:11:52 +02:00
sprite - > y2 + = 8 ; // Move the sprite down.
2018-06-20 23:07:51 +02:00
if ( - - sprite - > data [ 3 ] < 0 )
2017-10-01 18:54:01 +02:00
{
FreeSpriteOamMatrix ( sprite ) ;
DestroySprite ( sprite ) ;
}
2018-06-20 23:07:51 +02:00
else // Erase bottom part of the sprite to create a smooth illusion of mon falling down.
2017-10-01 18:54:01 +02:00
{
2020-09-19 19:37:24 +02:00
u8 * dst = gMonSpritesGfxPtr - > sprites . byte [ GetBattlerPosition ( sprite - > sBattler ) ] + ( gBattleMonForms [ sprite - > sBattler ] < < 11 ) + ( sprite - > data [ 3 ] < < 8 ) ;
2017-10-01 18:54:01 +02:00
for ( i = 0 ; i < 0x100 ; i + + )
* ( dst + + ) = 0 ;
2018-02-06 23:09:39 +01:00
StartSpriteAnim ( sprite , gBattleMonForms [ sprite - > sBattler ] ) ;
2017-10-01 18:54:01 +02:00
}
}
}
2020-07-14 11:13:03 +02:00
// Used when selecting a move, which can hit multiple targets, in double battles.
void SpriteCb_ShowAsMoveTarget ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
2017-12-02 21:44:50 +01:00
sprite - > data [ 3 ] = 8 ;
sprite - > data [ 4 ] = sprite - > invisible ;
2020-07-14 11:13:03 +02:00
sprite - > callback = SpriteCb_BlinkVisible ;
2017-10-01 18:54:01 +02:00
}
2020-07-14 11:13:03 +02:00
static void SpriteCb_BlinkVisible ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
2020-07-14 11:13:03 +02:00
if ( - - sprite - > data [ 3 ] = = 0 )
2017-10-01 18:54:01 +02:00
{
sprite - > invisible ^ = 1 ;
2017-12-02 21:44:50 +01:00
sprite - > data [ 3 ] = 8 ;
2017-10-01 18:54:01 +02:00
}
}
2020-07-14 11:13:03 +02:00
void SpriteCb_HideAsMoveTarget ( struct Sprite * sprite )
2017-10-01 18:54:01 +02:00
{
2017-12-02 21:44:50 +01:00
sprite - > invisible = sprite - > data [ 4 ] ;
sprite - > data [ 4 ] = FALSE ;
2017-10-01 18:54:01 +02:00
sprite - > callback = SpriteCallbackDummy_2 ;
}
2020-07-14 11:13:03 +02:00
void SpriteCb_OpponentMonFromBall ( struct Sprite * sprite )
2017-10-02 23:32:39 +02:00
{
if ( sprite - > affineAnimEnded )
{
2021-01-13 21:17:32 +01:00
if ( ! ( gHitMarker & HITMARKER_NO_ANIMATIONS ) | | gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK ) )
2017-10-02 23:32:39 +02:00
{
2018-02-06 23:09:39 +01:00
if ( HasTwoFramesAnimation ( sprite - > sSpeciesId ) )
2017-10-02 23:32:39 +02:00
StartSpriteAnim ( sprite , 1 ) ;
}
2018-02-06 23:09:39 +01:00
BattleAnimateFrontSprite ( sprite , sprite - > sSpeciesId , TRUE , 1 ) ;
2017-10-02 23:32:39 +02:00
}
}
2021-01-23 05:22:37 +01:00
// This callback is frequently overwritten by SpriteCB_TrainerSlideIn
void SpriteCB_BattleSpriteStartSlideLeft ( struct Sprite * sprite )
2017-10-02 23:32:39 +02:00
{
2021-01-23 05:22:37 +01:00
sprite - > callback = SpriteCB_BattleSpriteSlideLeft ;
2017-10-02 23:32:39 +02:00
}
2021-01-23 05:22:37 +01:00
static void SpriteCB_BattleSpriteSlideLeft ( struct Sprite * sprite )
2017-10-02 23:32:39 +02:00
{
2018-07-01 15:28:57 +02:00
if ( ! ( gIntroSlideFlags & 1 ) )
2017-10-02 23:32:39 +02:00
{
2021-07-07 15:11:52 +02:00
sprite - > x2 - = 2 ;
if ( sprite - > x2 = = 0 )
2017-10-02 23:32:39 +02:00
{
sprite - > callback = SpriteCallbackDummy_3 ;
2017-12-02 21:44:50 +01:00
sprite - > data [ 1 ] = 0 ;
2017-10-02 23:32:39 +02:00
}
}
}
2021-01-23 05:22:37 +01:00
// Unused
static void sub_80105DC ( struct Sprite * sprite )
2017-10-02 23:32:39 +02:00
{
sprite - > callback = SpriteCallbackDummy_3 ;
}
2017-10-06 19:09:37 +02:00
static void SpriteCallbackDummy_3 ( struct Sprite * sprite )
2017-10-02 23:32:39 +02:00
{
}
2021-01-23 02:03:21 +01:00
# define sSpeedX data[1]
# define sSpeedY data[2]
void SpriteCB_FaintSlideAnim ( struct Sprite * sprite )
2017-10-02 23:32:39 +02:00
{
2018-02-08 11:17:41 +01:00
if ( ! ( gIntroSlideFlags & 1 ) )
2017-10-02 23:32:39 +02:00
{
2021-07-07 15:11:52 +02:00
sprite - > x2 + = sprite - > sSpeedX ;
sprite - > y2 + = sprite - > sSpeedY ;
2017-10-02 23:32:39 +02:00
}
}
2021-01-23 02:03:21 +01:00
# undef sSpeedX
# undef sSpeedY
2019-05-02 23:10:01 +02:00
# define sSinIndex data[3]
# define sDelta data[4]
# define sAmplitude data[5]
# define sBouncerSpriteId data[6]
# define sWhich data[7]
2018-06-20 23:07:51 +02:00
void DoBounceEffect ( u8 battler , u8 which , s8 delta , s8 amplitude )
2017-10-02 23:32:39 +02:00
{
2018-06-20 23:07:51 +02:00
u8 invisibleSpriteId ;
u8 bouncerSpriteId ;
2017-10-02 23:32:39 +02:00
2018-06-20 23:07:51 +02:00
switch ( which )
2017-10-02 23:32:39 +02:00
{
2018-06-20 23:07:51 +02:00
case BOUNCE_HEALTHBOX :
default :
if ( gBattleSpritesDataPtr - > healthBoxesData [ battler ] . healthboxIsBouncing )
2017-10-02 23:32:39 +02:00
return ;
2018-06-20 23:07:51 +02:00
break ;
case BOUNCE_MON :
if ( gBattleSpritesDataPtr - > healthBoxesData [ battler ] . battlerIsBouncing )
2017-10-02 23:32:39 +02:00
return ;
2018-06-20 23:07:51 +02:00
break ;
2017-10-02 23:32:39 +02:00
}
2018-06-20 23:07:51 +02:00
invisibleSpriteId = CreateInvisibleSpriteWithCallback ( SpriteCB_BounceEffect ) ;
if ( which = = BOUNCE_HEALTHBOX )
2017-10-02 23:32:39 +02:00
{
2018-06-20 23:07:51 +02:00
bouncerSpriteId = gHealthboxSpriteIds [ battler ] ;
gBattleSpritesDataPtr - > healthBoxesData [ battler ] . healthboxBounceSpriteId = invisibleSpriteId ;
gBattleSpritesDataPtr - > healthBoxesData [ battler ] . healthboxIsBouncing = 1 ;
gSprites [ invisibleSpriteId ] . sSinIndex = 128 ; // 0
2017-10-02 23:32:39 +02:00
}
else
{
2018-06-20 23:07:51 +02:00
bouncerSpriteId = gBattlerSpriteIds [ battler ] ;
gBattleSpritesDataPtr - > healthBoxesData [ battler ] . battlerBounceSpriteId = invisibleSpriteId ;
gBattleSpritesDataPtr - > healthBoxesData [ battler ] . battlerIsBouncing = 1 ;
gSprites [ invisibleSpriteId ] . sSinIndex = 192 ; // -1
}
gSprites [ invisibleSpriteId ] . sDelta = delta ;
gSprites [ invisibleSpriteId ] . sAmplitude = amplitude ;
gSprites [ invisibleSpriteId ] . sBouncerSpriteId = bouncerSpriteId ;
gSprites [ invisibleSpriteId ] . sWhich = which ;
2019-05-02 23:10:01 +02:00
gSprites [ invisibleSpriteId ] . sBattler = battler ;
2021-07-07 15:11:52 +02:00
gSprites [ bouncerSpriteId ] . x2 = 0 ;
gSprites [ bouncerSpriteId ] . y2 = 0 ;
2017-10-02 23:32:39 +02:00
}
2018-06-20 23:07:51 +02:00
void EndBounceEffect ( u8 battler , u8 which )
2017-10-02 23:32:39 +02:00
{
2018-06-20 23:07:51 +02:00
u8 bouncerSpriteId ;
2017-10-02 23:32:39 +02:00
2018-06-20 23:07:51 +02:00
if ( which = = BOUNCE_HEALTHBOX )
2017-10-02 23:32:39 +02:00
{
2018-06-20 23:07:51 +02:00
if ( ! gBattleSpritesDataPtr - > healthBoxesData [ battler ] . healthboxIsBouncing )
2017-10-02 23:32:39 +02:00
return ;
2018-06-20 23:07:51 +02:00
bouncerSpriteId = gSprites [ gBattleSpritesDataPtr - > healthBoxesData [ battler ] . healthboxBounceSpriteId ] . sBouncerSpriteId ;
DestroySprite ( & gSprites [ gBattleSpritesDataPtr - > healthBoxesData [ battler ] . healthboxBounceSpriteId ] ) ;
gBattleSpritesDataPtr - > healthBoxesData [ battler ] . healthboxIsBouncing = 0 ;
2017-10-02 23:32:39 +02:00
}
else
{
2018-06-20 23:07:51 +02:00
if ( ! gBattleSpritesDataPtr - > healthBoxesData [ battler ] . battlerIsBouncing )
2017-10-02 23:32:39 +02:00
return ;
2018-06-20 23:07:51 +02:00
bouncerSpriteId = gSprites [ gBattleSpritesDataPtr - > healthBoxesData [ battler ] . battlerBounceSpriteId ] . sBouncerSpriteId ;
DestroySprite ( & gSprites [ gBattleSpritesDataPtr - > healthBoxesData [ battler ] . battlerBounceSpriteId ] ) ;
gBattleSpritesDataPtr - > healthBoxesData [ battler ] . battlerIsBouncing = 0 ;
2017-10-02 23:32:39 +02:00
}
2018-06-20 23:07:51 +02:00
2021-07-07 15:11:52 +02:00
gSprites [ bouncerSpriteId ] . x2 = 0 ;
gSprites [ bouncerSpriteId ] . y2 = 0 ;
2017-10-02 23:32:39 +02:00
}
2018-06-20 23:07:51 +02:00
static void SpriteCB_BounceEffect ( struct Sprite * sprite )
2017-10-02 23:32:39 +02:00
{
2018-06-20 23:07:51 +02:00
u8 bouncerSpriteId = sprite - > sBouncerSpriteId ;
2019-05-02 23:10:01 +02:00
s32 index = sprite - > sSinIndex ;
s32 y = Sin ( index , sprite - > sAmplitude ) + sprite - > sAmplitude ;
2017-10-02 23:32:39 +02:00
2021-08-12 01:33:10 +02:00
gSprites [ bouncerSpriteId ] . y2 = y ;
2018-06-20 23:07:51 +02:00
sprite - > sSinIndex = ( sprite - > sSinIndex + sprite - > sDelta ) & 0xFF ;
2019-05-02 23:10:01 +02:00
2020-06-24 12:55:08 +02:00
bouncerSpriteId = GetMegaIndicatorSpriteId ( sprite - > sBouncerSpriteId ) ;
2019-05-02 23:10:01 +02:00
if ( sprite - > sWhich = = BOUNCE_HEALTHBOX & & bouncerSpriteId ! = 0xFF )
2021-08-12 01:33:10 +02:00
gSprites [ bouncerSpriteId ] . y2 = y ;
2017-10-02 23:32:39 +02:00
}
2018-06-20 23:07:51 +02:00
# undef sSinIndex
# undef sDelta
# undef sAmplitude
# undef sBouncerSpriteId
# undef sWhich
2020-07-14 11:13:03 +02:00
void SpriteCb_PlayerMonFromBall ( struct Sprite * sprite )
2017-10-02 23:32:39 +02:00
{
if ( sprite - > affineAnimEnded )
2018-02-06 23:09:39 +01:00
BattleAnimateBackSprite ( sprite , sprite - > sSpeciesId ) ;
2017-10-02 23:32:39 +02:00
}
void sub_8039E60 ( struct Sprite * sprite )
{
sub_8039E9C ( sprite ) ;
if ( sprite - > animEnded )
sprite - > callback = SpriteCallbackDummy_3 ;
}
2020-08-30 21:11:44 +02:00
void SpriteCB_TrainerThrowObject ( struct Sprite * sprite )
2017-10-02 23:32:39 +02:00
{
StartSpriteAnim ( sprite , 1 ) ;
sprite - > callback = sub_8039E60 ;
}
void sub_8039E9C ( struct Sprite * sprite )
{
if ( sprite - > animDelayCounter = = 0 )
sprite - > centerToCornerVecX = gUnknown_0831ACE0 [ sprite - > animCmdIndex ] ;
}
2021-01-22 08:48:22 +01:00
void BeginBattleIntroDummy ( void )
2017-10-02 23:32:39 +02:00
{
}
void BeginBattleIntro ( void )
{
BattleStartClearSetData ( ) ;
gBattleCommunication [ 1 ] = 0 ;
2018-12-23 18:47:00 +01:00
gBattleStruct - > introState = 0 ;
gBattleMainFunc = DoBattleIntro ;
2017-10-02 23:32:39 +02:00
}
2017-10-06 19:09:37 +02:00
static void BattleMainCB1 ( void )
2017-10-02 23:32:39 +02:00
{
gBattleMainFunc ( ) ;
2018-02-06 02:46:59 +01:00
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
2018-02-06 20:48:02 +01:00
gBattlerControllerFuncs [ gActiveBattler ] ( ) ;
2017-10-02 23:32:39 +02:00
}
static void BattleStartClearSetData ( void )
{
s32 i ;
2017-10-06 00:12:01 +02:00
TurnValuesCleanUp ( FALSE ) ;
2017-10-02 23:32:39 +02:00
SpecialStatusesClear ( ) ;
2019-01-27 13:52:02 +01:00
memset ( & gDisableStructs , 0 , sizeof ( gDisableStructs ) ) ;
memset ( & gFieldTimers , 0 , sizeof ( gFieldTimers ) ) ;
memset ( & gSideStatuses , 0 , sizeof ( gSideStatuses ) ) ;
memset ( & gSideTimers , 0 , sizeof ( gSideTimers ) ) ;
memset ( & gWishFutureKnock , 0 , sizeof ( gWishFutureKnock ) ) ;
memset ( & gBattleResults , 0 , sizeof ( gBattleResults ) ) ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
2017-10-02 23:32:39 +02:00
{
gStatuses3 [ i ] = 0 ;
2017-11-26 13:26:58 +01:00
gDisableStructs [ i ] . isFirstTurn = 2 ;
2017-11-26 18:07:00 +01:00
gLastMoves [ i ] = 0 ;
2017-11-26 14:17:02 +01:00
gLastLandedMoves [ i ] = 0 ;
gLastHitByType [ i ] = 0 ;
2017-11-26 18:07:00 +01:00
gLastResultingMoves [ i ] = 0 ;
2017-11-26 14:17:02 +01:00
gLastHitBy [ i ] = 0xFF ;
2017-10-02 23:32:39 +02:00
gLockedMoves [ i ] = 0 ;
2017-11-26 18:07:00 +01:00
gLastPrintedMoves [ i ] = 0 ;
2017-10-02 23:32:39 +02:00
gBattleResources - > flags - > flags [ i ] = 0 ;
2017-11-26 17:15:28 +01:00
gPalaceSelectionBattleScripts [ i ] = 0 ;
2019-01-27 13:52:02 +01:00
gBattleStruct - > lastTakenMove [ i ] = 0 ;
gBattleStruct - > usedHeldItems [ i ] = 0 ;
gBattleStruct - > choicedMove [ i ] = 0 ;
gBattleStruct - > changedItems [ i ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ i ] [ 0 ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ i ] [ 1 ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ i ] [ 2 ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ i ] [ 3 ] = 0 ;
gBattleStruct - > AI_monToSwitchIntoId [ i ] = PARTY_SIZE ;
2017-10-02 23:32:39 +02:00
}
2018-09-22 18:37:03 +02:00
gLastUsedMove = 0 ;
2018-08-11 12:16:00 +02:00
gFieldStatuses = 0 ;
2017-10-02 23:32:39 +02:00
2020-12-03 03:09:35 +01:00
gHasFetchedBall = FALSE ;
gLastUsedBall = 0 ;
2018-02-06 23:09:39 +01:00
gBattlerAttacker = 0 ;
gBattlerTarget = 0 ;
2017-10-02 23:32:39 +02:00
gBattleWeather = 0 ;
gHitMarker = 0 ;
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED ) )
{
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_LINK ) & & gSaveBlock2Ptr - > optionsBattleSceneOff = = TRUE )
gHitMarker | = HITMARKER_NO_ANIMATIONS ;
}
2021-01-13 21:17:32 +01:00
else if ( ! ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK ) ) & & GetBattleSceneInRecordedBattle ( ) )
2019-01-27 13:52:02 +01:00
{
2017-10-02 23:32:39 +02:00
gHitMarker | = HITMARKER_NO_ANIMATIONS ;
2019-01-27 13:52:02 +01:00
}
2017-10-02 23:32:39 +02:00
gBattleScripting . battleStyle = gSaveBlock2Ptr - > optionsBattleStyle ;
2018-08-03 18:01:14 +02:00
gBattleScripting . expOnCatch = ( B_EXP_CATCH > = GEN_6 ) ;
gBattleScripting . monCaught = FALSE ;
2017-10-02 23:32:39 +02:00
gMultiHitCounter = 0 ;
gBattleOutcome = 0 ;
2018-02-06 20:48:02 +01:00
gBattleControllerExecFlags = 0 ;
2017-10-02 23:32:39 +02:00
gPaydayMoney = 0 ;
gBattleResources - > battleScriptsStack - > size = 0 ;
gBattleResources - > battleCallbackStack - > size = 0 ;
for ( i = 0 ; i < BATTLE_COMMUNICATION_ENTRIES_COUNT ; i + + )
gBattleCommunication [ i ] = 0 ;
gPauseCounterBattle = 0 ;
gBattleMoveDamage = 0 ;
2018-02-08 11:17:41 +01:00
gIntroSlideFlags = 0 ;
2017-10-02 23:32:39 +02:00
gBattleScripting . animTurn = 0 ;
gBattleScripting . animTargetsHit = 0 ;
gLeveledUpInBattle = 0 ;
2018-02-06 02:46:59 +01:00
gAbsentBattlerFlags = 0 ;
2017-10-06 00:12:01 +02:00
gBattleStruct - > runTries = 0 ;
2018-07-01 11:15:42 +02:00
gBattleStruct - > safariGoNearCounter = 0 ;
gBattleStruct - > safariPkblThrowCounter = 0 ;
2019-01-27 13:52:02 +01:00
gBattleStruct - > safariCatchFactor = gBaseStats [ GetMonData ( & gEnemyParty [ 0 ] , MON_DATA_SPECIES ) ] . catchRate * 100 / 1275 ;
2018-07-01 11:15:42 +02:00
gBattleStruct - > safariEscapeFactor = 3 ;
2017-10-02 23:32:39 +02:00
gBattleStruct - > wildVictorySong = 0 ;
gBattleStruct - > moneyMultiplier = 1 ;
2018-12-07 23:50:56 +01:00
gBattleStruct - > givenExpMons = 0 ;
2020-07-17 02:12:12 +02:00
gBattleStruct - > palaceFlags = 0 ;
2017-10-02 23:32:39 +02:00
gRandomTurnNumber = Random ( ) ;
2018-06-28 21:06:32 +02:00
gBattleResults . shinyWildMon = IsMonShiny ( & gEnemyParty [ 0 ] ) ;
2017-10-02 23:32:39 +02:00
2018-11-11 18:33:16 +01:00
gBattleStruct - > arenaLostPlayerMons = 0 ;
gBattleStruct - > arenaLostOpponentMons = 0 ;
2018-09-16 21:08:49 +02:00
2018-09-20 17:33:27 +02:00
gBattleStruct - > mega . triggerSpriteId = 0xFF ;
2020-12-09 18:28:18 +01:00
for ( i = 0 ; i < PARTY_SIZE ; i + + )
gBattleStruct - > itemStolen [ i ] . originalItem = GetMonData ( & gPlayerParty [ i ] , MON_DATA_HELD_ITEM ) ;
2017-10-02 23:32:39 +02:00
}
void SwitchInClearSetData ( void )
{
s32 i ;
2019-01-27 13:52:02 +01:00
struct DisableStruct disableStructCopy = gDisableStructs [ gActiveBattler ] ;
2017-10-02 23:32:39 +02:00
2020-06-28 19:45:48 +02:00
ClearIllusionMon ( gActiveBattler ) ;
2017-10-02 23:32:39 +02:00
if ( gBattleMoves [ gCurrentMove ] . effect ! = EFFECT_BATON_PASS )
{
2018-11-18 20:00:36 +01:00
for ( i = 0 ; i < NUM_BATTLE_STATS ; i + + )
2020-08-05 02:33:05 +02:00
gBattleMons [ gActiveBattler ] . statStages [ i ] = DEFAULT_STAT_STAGE ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-02 23:32:39 +02:00
{
2018-02-06 23:09:39 +01:00
if ( ( gBattleMons [ i ] . status2 & STATUS2_ESCAPE_PREVENTION ) & & gDisableStructs [ i ] . battlerPreventingEscape = = gActiveBattler )
2017-10-02 23:32:39 +02:00
gBattleMons [ i ] . status2 & = ~ STATUS2_ESCAPE_PREVENTION ;
2018-02-06 23:09:39 +01:00
if ( ( gStatuses3 [ i ] & STATUS3_ALWAYS_HITS ) & & gDisableStructs [ i ] . battlerWithSureHit = = gActiveBattler )
2017-10-02 23:32:39 +02:00
{
gStatuses3 [ i ] & = ~ STATUS3_ALWAYS_HITS ;
2018-02-06 23:09:39 +01:00
gDisableStructs [ i ] . battlerWithSureHit = 0 ;
2017-10-02 23:32:39 +02:00
}
}
}
if ( gBattleMoves [ gCurrentMove ] . effect = = EFFECT_BATON_PASS )
{
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . status2 & = ( STATUS2_CONFUSION | STATUS2_FOCUS_ENERGY | STATUS2_SUBSTITUTE | STATUS2_ESCAPE_PREVENTION | STATUS2_CURSED ) ;
2018-07-14 13:17:10 +02:00
gStatuses3 [ gActiveBattler ] & = ( STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED ) ;
2017-10-02 23:32:39 +02:00
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-02 23:32:39 +02:00
{
2018-02-06 02:46:59 +01:00
if ( GetBattlerSide ( gActiveBattler ) ! = GetBattlerSide ( i )
2017-10-02 23:32:39 +02:00
& & ( gStatuses3 [ i ] & STATUS3_ALWAYS_HITS ) ! = 0
2018-02-06 23:09:39 +01:00
& & ( gDisableStructs [ i ] . battlerWithSureHit = = gActiveBattler ) )
2017-10-02 23:32:39 +02:00
{
2017-12-03 00:47:21 +01:00
gStatuses3 [ i ] & = ~ ( STATUS3_ALWAYS_HITS ) ;
2020-07-17 02:12:12 +02:00
gStatuses3 [ i ] | = STATUS3_ALWAYS_HITS_TURN ( 2 ) ;
2017-10-02 23:32:39 +02:00
}
}
2018-09-29 18:40:14 +02:00
if ( gStatuses3 [ gActiveBattler ] & STATUS3_POWER_TRICK )
SWAP ( gBattleMons [ gActiveBattler ] . attack , gBattleMons [ gActiveBattler ] . defense , i ) ;
2017-10-02 23:32:39 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . status2 = 0 ;
gStatuses3 [ gActiveBattler ] = 0 ;
2017-10-02 23:32:39 +02:00
}
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-02 23:32:39 +02:00
{
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ i ] . status2 & STATUS2_INFATUATED_WITH ( gActiveBattler ) )
gBattleMons [ i ] . status2 & = ~ ( STATUS2_INFATUATED_WITH ( gActiveBattler ) ) ;
if ( ( gBattleMons [ i ] . status2 & STATUS2_WRAPPED ) & & * ( gBattleStruct - > wrappedBy + i ) = = gActiveBattler )
2017-10-02 23:32:39 +02:00
gBattleMons [ i ] . status2 & = ~ ( STATUS2_WRAPPED ) ;
}
2018-02-06 02:46:59 +01:00
gActionSelectionCursor [ gActiveBattler ] = 0 ;
gMoveSelectionCursor [ gActiveBattler ] = 0 ;
2017-10-02 23:32:39 +02:00
2019-01-27 13:52:02 +01:00
memset ( & gDisableStructs [ gActiveBattler ] , 0 , sizeof ( struct DisableStruct ) ) ;
2017-10-02 23:32:39 +02:00
if ( gBattleMoves [ gCurrentMove ] . effect = = EFFECT_BATON_PASS )
{
2018-02-06 02:46:59 +01:00
gDisableStructs [ gActiveBattler ] . substituteHP = disableStructCopy . substituteHP ;
2018-02-06 23:09:39 +01:00
gDisableStructs [ gActiveBattler ] . battlerWithSureHit = disableStructCopy . battlerWithSureHit ;
2018-10-14 18:10:54 +02:00
gDisableStructs [ gActiveBattler ] . perishSongTimer = disableStructCopy . perishSongTimer ;
gDisableStructs [ gActiveBattler ] . perishSongTimerStartValue = disableStructCopy . perishSongTimerStartValue ;
2018-02-06 23:09:39 +01:00
gDisableStructs [ gActiveBattler ] . battlerPreventingEscape = disableStructCopy . battlerPreventingEscape ;
2017-10-02 23:32:39 +02:00
}
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2018-02-06 02:46:59 +01:00
gDisableStructs [ gActiveBattler ] . isFirstTurn = 2 ;
2019-01-19 22:32:25 +01:00
gDisableStructs [ gActiveBattler ] . truantSwitchInHack = disableStructCopy . truantSwitchInHack ;
2018-02-06 02:46:59 +01:00
gLastMoves [ gActiveBattler ] = 0 ;
gLastLandedMoves [ gActiveBattler ] = 0 ;
gLastHitByType [ gActiveBattler ] = 0 ;
gLastResultingMoves [ gActiveBattler ] = 0 ;
gLastPrintedMoves [ gActiveBattler ] = 0 ;
gLastHitBy [ gActiveBattler ] = 0xFF ;
2017-10-02 23:32:39 +02:00
2019-01-27 13:52:02 +01:00
gBattleStruct - > lastTakenMove [ gActiveBattler ] = 0 ;
2020-04-22 12:49:25 +02:00
gBattleStruct - > sameMoveTurns [ gActiveBattler ] = 0 ;
2019-01-27 13:52:02 +01:00
gBattleStruct - > lastTakenMoveFrom [ gActiveBattler ] [ 0 ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ gActiveBattler ] [ 1 ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ gActiveBattler ] [ 2 ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ gActiveBattler ] [ 3 ] = 0 ;
2019-04-13 14:36:08 +02:00
gBattleStruct - > lastMoveFailed & = ~ ( gBitTable [ gActiveBattler ] ) ;
2020-07-17 02:12:12 +02:00
gBattleStruct - > palaceFlags & = ~ ( gBitTable [ gActiveBattler ] ) ;
2017-10-02 23:32:39 +02:00
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-02 23:32:39 +02:00
{
2018-02-06 02:46:59 +01:00
if ( i ! = gActiveBattler & & GetBattlerSide ( i ) ! = GetBattlerSide ( gActiveBattler ) )
2019-01-27 13:52:02 +01:00
gBattleStruct - > lastTakenMove [ i ] = 0 ;
2017-10-02 23:32:39 +02:00
2019-01-27 13:52:02 +01:00
gBattleStruct - > lastTakenMoveFrom [ i ] [ gActiveBattler ] = 0 ;
}
2017-10-02 23:32:39 +02:00
2019-01-27 13:52:02 +01:00
gBattleStruct - > choicedMove [ gActiveBattler ] = 0 ;
2018-02-06 02:46:59 +01:00
gBattleResources - > flags - > flags [ gActiveBattler ] = 0 ;
2017-10-02 23:32:39 +02:00
gCurrentMove = 0 ;
2018-12-07 23:50:56 +01:00
gBattleStruct - > arenaTurnCounter = 0xFF ;
2021-01-08 03:33:39 +01:00
2021-09-02 21:33:42 +02:00
// Reset damage to prevent things like red card activating if the switched-in mon is holding it
2021-01-08 03:33:39 +01:00
gSpecialStatuses [ gActiveBattler ] . physicalDmg = 0 ;
gSpecialStatuses [ gActiveBattler ] . specialDmg = 0 ;
2017-10-02 23:32:39 +02:00
2018-02-06 23:09:39 +01:00
ClearBattlerMoveHistory ( gActiveBattler ) ;
ClearBattlerAbilityHistory ( gActiveBattler ) ;
2021-01-19 20:58:58 +01:00
ClearBattlerItemEffectHistory ( gActiveBattler ) ;
2017-10-02 23:32:39 +02:00
}
void FaintClearSetData ( void )
{
s32 i ;
2018-11-18 20:00:36 +01:00
for ( i = 0 ; i < NUM_BATTLE_STATS ; i + + )
2020-08-05 02:33:05 +02:00
gBattleMons [ gActiveBattler ] . statStages [ i ] = DEFAULT_STAT_STAGE ;
2017-10-02 23:32:39 +02:00
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . status2 = 0 ;
gStatuses3 [ gActiveBattler ] = 0 ;
2017-10-02 23:32:39 +02:00
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-02 23:32:39 +02:00
{
2018-02-06 23:09:39 +01:00
if ( ( gBattleMons [ i ] . status2 & STATUS2_ESCAPE_PREVENTION ) & & gDisableStructs [ i ] . battlerPreventingEscape = = gActiveBattler )
2017-10-02 23:32:39 +02:00
gBattleMons [ i ] . status2 & = ~ STATUS2_ESCAPE_PREVENTION ;
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ i ] . status2 & STATUS2_INFATUATED_WITH ( gActiveBattler ) )
gBattleMons [ i ] . status2 & = ~ ( STATUS2_INFATUATED_WITH ( gActiveBattler ) ) ;
if ( ( gBattleMons [ i ] . status2 & STATUS2_WRAPPED ) & & * ( gBattleStruct - > wrappedBy + i ) = = gActiveBattler )
2017-10-02 23:32:39 +02:00
gBattleMons [ i ] . status2 & = ~ ( STATUS2_WRAPPED ) ;
}
2018-02-06 02:46:59 +01:00
gActionSelectionCursor [ gActiveBattler ] = 0 ;
gMoveSelectionCursor [ gActiveBattler ] = 0 ;
2017-10-02 23:32:39 +02:00
2019-01-27 13:52:02 +01:00
memset ( & gDisableStructs [ gActiveBattler ] , 0 , sizeof ( struct DisableStruct ) ) ;
2017-10-02 23:32:39 +02:00
2018-02-06 02:46:59 +01:00
gProtectStructs [ gActiveBattler ] . protected = 0 ;
2018-10-06 15:50:35 +02:00
gProtectStructs [ gActiveBattler ] . spikyShielded = 0 ;
gProtectStructs [ gActiveBattler ] . kingsShielded = 0 ;
gProtectStructs [ gActiveBattler ] . banefulBunkered = 0 ;
2018-02-06 02:46:59 +01:00
gProtectStructs [ gActiveBattler ] . endured = 0 ;
2018-07-07 19:57:09 +02:00
gProtectStructs [ gActiveBattler ] . noValidMoves = 0 ;
2018-02-06 02:46:59 +01:00
gProtectStructs [ gActiveBattler ] . helpingHand = 0 ;
gProtectStructs [ gActiveBattler ] . bounceMove = 0 ;
gProtectStructs [ gActiveBattler ] . stealMove = 0 ;
gProtectStructs [ gActiveBattler ] . prlzImmobility = 0 ;
gProtectStructs [ gActiveBattler ] . confusionSelfDmg = 0 ;
2021-09-14 17:53:35 +02:00
gProtectStructs [ gActiveBattler ] . targetAffected = 0 ;
2018-02-06 02:46:59 +01:00
gProtectStructs [ gActiveBattler ] . chargingTurn = 0 ;
gProtectStructs [ gActiveBattler ] . fleeFlag = 0 ;
2019-03-02 23:40:38 +01:00
gProtectStructs [ gActiveBattler ] . usedImprisonedMove = 0 ;
2018-02-06 02:46:59 +01:00
gProtectStructs [ gActiveBattler ] . loveImmobility = 0 ;
gProtectStructs [ gActiveBattler ] . usedDisabledMove = 0 ;
gProtectStructs [ gActiveBattler ] . usedTauntedMove = 0 ;
gProtectStructs [ gActiveBattler ] . flag2Unknown = 0 ;
gProtectStructs [ gActiveBattler ] . flinchImmobility = 0 ;
gProtectStructs [ gActiveBattler ] . notFirstStrike = 0 ;
2018-08-02 21:27:28 +02:00
gProtectStructs [ gActiveBattler ] . usedHealBlockedMove = 0 ;
gProtectStructs [ gActiveBattler ] . usesBouncedMove = 0 ;
gProtectStructs [ gActiveBattler ] . usedGravityPreventedMove = 0 ;
2019-04-16 15:01:48 +02:00
gProtectStructs [ gActiveBattler ] . usedThroatChopPreventedMove = 0 ;
2018-02-06 02:46:59 +01:00
gDisableStructs [ gActiveBattler ] . isFirstTurn = 2 ;
gLastMoves [ gActiveBattler ] = 0 ;
gLastLandedMoves [ gActiveBattler ] = 0 ;
gLastHitByType [ gActiveBattler ] = 0 ;
gLastResultingMoves [ gActiveBattler ] = 0 ;
gLastPrintedMoves [ gActiveBattler ] = 0 ;
gLastHitBy [ gActiveBattler ] = 0xFF ;
2019-01-27 13:52:02 +01:00
gBattleStruct - > choicedMove [ gActiveBattler ] = 0 ;
2020-04-22 12:49:25 +02:00
gBattleStruct - > sameMoveTurns [ gActiveBattler ] = 0 ;
2019-01-27 13:52:02 +01:00
gBattleStruct - > lastTakenMove [ gActiveBattler ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ gActiveBattler ] [ 0 ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ gActiveBattler ] [ 1 ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ gActiveBattler ] [ 2 ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ gActiveBattler ] [ 3 ] = 0 ;
2018-02-06 02:46:59 +01:00
2020-07-17 02:12:12 +02:00
gBattleStruct - > palaceFlags & = ~ ( gBitTable [ gActiveBattler ] ) ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( i ! = gActiveBattler & & GetBattlerSide ( i ) ! = GetBattlerSide ( gActiveBattler ) )
2019-01-27 13:52:02 +01:00
gBattleStruct - > lastTakenMove [ i ] = 0 ;
gBattleStruct - > lastTakenMoveFrom [ i ] [ gActiveBattler ] = 0 ;
2017-10-02 23:32:39 +02:00
}
2018-02-06 02:46:59 +01:00
gBattleResources - > flags - > flags [ gActiveBattler ] = 0 ;
2017-10-02 23:32:39 +02:00
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . type1 = gBaseStats [ gBattleMons [ gActiveBattler ] . species ] . type1 ;
gBattleMons [ gActiveBattler ] . type2 = gBaseStats [ gBattleMons [ gActiveBattler ] . species ] . type2 ;
2018-11-17 12:10:24 +01:00
gBattleMons [ gActiveBattler ] . type3 = TYPE_MYSTERY ;
2017-10-02 23:32:39 +02:00
2018-02-06 23:09:39 +01:00
ClearBattlerMoveHistory ( gActiveBattler ) ;
ClearBattlerAbilityHistory ( gActiveBattler ) ;
2021-01-19 20:58:58 +01:00
ClearBattlerItemEffectHistory ( gActiveBattler ) ;
2021-07-16 07:56:53 +02:00
UndoFormChange ( gBattlerPartyIndexes [ gActiveBattler ] , GET_BATTLER_SIDE ( gActiveBattler ) , FALSE ) ;
2018-09-16 21:08:49 +02:00
if ( GetBattlerSide ( gActiveBattler ) = = B_SIDE_PLAYER )
UndoMegaEvolution ( gBattlerPartyIndexes [ gActiveBattler ] ) ;
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
static void DoBattleIntro ( void )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
s32 i ;
u8 * state = & gBattleStruct - > introState ;
switch ( * state )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
case 0 : // Get Data of all battlers.
2018-02-06 02:46:59 +01:00
gActiveBattler = gBattleCommunication [ 1 ] ;
2018-09-20 11:55:35 +02:00
BtlController_EmitGetMonData ( 0 , REQUEST_ALL_BATTLE , 0 ) ;
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2018-12-23 18:47:00 +01:00
( * state ) + + ;
2017-10-02 23:32:39 +02:00
break ;
2018-12-23 18:47:00 +01:00
case 1 : // Loop through all battlers.
if ( ! gBattleControllerExecFlags )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
if ( + + gBattleCommunication [ 1 ] = = gBattlersCount )
( * state ) + + ;
2017-10-02 23:32:39 +02:00
else
2018-12-23 18:47:00 +01:00
* state = 0 ;
2017-10-02 23:32:39 +02:00
}
break ;
2018-12-23 18:47:00 +01:00
case 2 : // Start graphical intro slide.
if ( ! gBattleControllerExecFlags )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( 0 ) ;
BtlController_EmitIntroSlide ( 0 , gBattleTerrain ) ;
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2018-12-23 18:47:00 +01:00
gBattleCommunication [ 0 ] = 0 ;
gBattleCommunication [ 1 ] = 0 ;
( * state ) + + ;
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
break ;
case 3 : // Wait for intro slide.
if ( ! gBattleControllerExecFlags )
( * state ) + + ;
break ;
case 4 : // Copy battler data gotten in cases 0 and 1. Draw trainer/mon sprite.
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
if ( ( gBattleTypeFlags & BATTLE_TYPE_SAFARI ) & & GetBattlerSide ( gActiveBattler ) = = B_SIDE_PLAYER )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
memset ( & gBattleMons [ gActiveBattler ] , 0 , sizeof ( struct BattlePokemon ) ) ;
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
else
2017-10-02 23:32:39 +02:00
{
2019-01-05 16:00:57 +01:00
memcpy ( & gBattleMons [ gActiveBattler ] , & gBattleResources - > bufferB [ gActiveBattler ] [ 4 ] , sizeof ( struct BattlePokemon ) ) ;
2018-12-23 18:47:00 +01:00
gBattleMons [ gActiveBattler ] . type1 = gBaseStats [ gBattleMons [ gActiveBattler ] . species ] . type1 ;
gBattleMons [ gActiveBattler ] . type2 = gBaseStats [ gBattleMons [ gActiveBattler ] . species ] . type2 ;
gBattleMons [ gActiveBattler ] . type3 = TYPE_MYSTERY ;
2019-05-17 09:52:20 +02:00
gBattleMons [ gActiveBattler ] . ability = GetAbilityBySpecies ( gBattleMons [ gActiveBattler ] . species , gBattleMons [ gActiveBattler ] . abilityNum ) ;
2018-12-23 18:47:00 +01:00
gBattleStruct - > hpOnSwitchout [ GetBattlerSide ( gActiveBattler ) ] = gBattleMons [ gActiveBattler ] . hp ;
gBattleMons [ gActiveBattler ] . status2 = 0 ;
for ( i = 0 ; i < NUM_BATTLE_STATS ; i + + )
gBattleMons [ gActiveBattler ] . statStages [ i ] = 6 ;
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
// Draw sprite.
switch ( GetBattlerPosition ( gActiveBattler ) )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
case B_POSITION_PLAYER_LEFT : // player sprite
2018-02-06 20:48:02 +01:00
BtlController_EmitDrawTrainerPic ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2018-12-23 18:47:00 +01:00
break ;
case B_POSITION_OPPONENT_LEFT :
if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER ) // opponent 1 sprite
{
BtlController_EmitDrawTrainerPic ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
}
else // wild mon 1
{
BtlController_EmitLoadMonSprite ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
gBattleResults . lastOpponentSpecies = GetMonData ( & gEnemyParty [ gBattlerPartyIndexes [ gActiveBattler ] ] , MON_DATA_SPECIES , NULL ) ;
}
break ;
case B_POSITION_PLAYER_RIGHT :
if ( gBattleTypeFlags & ( BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER ) ) // partner sprite
{
BtlController_EmitDrawTrainerPic ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
}
break ;
case B_POSITION_OPPONENT_RIGHT :
if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER )
{
2019-01-27 20:54:34 +01:00
if ( gBattleTypeFlags & ( BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS ) & & ! BATTLE_TWO_VS_ONE_OPPONENT ) // opponent 2 if exists
2018-12-23 18:47:00 +01:00
{
BtlController_EmitDrawTrainerPic ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
}
}
else // wild mon 2
{
BtlController_EmitLoadMonSprite ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
gBattleResults . lastOpponentSpecies = GetMonData ( & gEnemyParty [ gBattlerPartyIndexes [ gActiveBattler ] ] , MON_DATA_SPECIES , NULL ) ;
}
break ;
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_ARENA )
BattleArena_InitPoints ( ) ;
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
( * state ) + + ;
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
else // Skip party summary since it is a wild battle.
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
if ( B_FAST_INTRO )
* state = 7 ; // Don't wait for sprite, print message at the same time.
2017-10-02 23:32:39 +02:00
else
2018-12-23 18:47:00 +01:00
* state = 6 ; // Wait for sprite to load.
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
break ;
case 5 : // draw party summary in trainer battles
if ( ! gBattleControllerExecFlags )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
struct HpAndStatus hpStatus [ PARTY_SIZE ] ;
for ( i = 0 ; i < PARTY_SIZE ; i + + )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
if ( GetMonData ( & gEnemyParty [ i ] , MON_DATA_SPECIES2 ) = = SPECIES_NONE
| | GetMonData ( & gEnemyParty [ i ] , MON_DATA_SPECIES2 ) = = SPECIES_EGG )
{
hpStatus [ i ] . hp = 0xFFFF ;
hpStatus [ i ] . status = 0 ;
}
else
{
hpStatus [ i ] . hp = GetMonData ( & gEnemyParty [ i ] , MON_DATA_HP ) ;
hpStatus [ i ] . status = GetMonData ( & gEnemyParty [ i ] , MON_DATA_STATUS ) ;
}
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
BtlController_EmitDrawPartyStatusSummary ( 0 , hpStatus , 0x80 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
for ( i = 0 ; i < PARTY_SIZE ; i + + )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
if ( GetMonData ( & gPlayerParty [ i ] , MON_DATA_SPECIES2 ) = = SPECIES_NONE
| | GetMonData ( & gPlayerParty [ i ] , MON_DATA_SPECIES2 ) = = SPECIES_EGG )
{
hpStatus [ i ] . hp = 0xFFFF ;
hpStatus [ i ] . status = 0 ;
}
else
{
hpStatus [ i ] . hp = GetMonData ( & gPlayerParty [ i ] , MON_DATA_HP ) ;
hpStatus [ i ] . status = GetMonData ( & gPlayerParty [ i ] , MON_DATA_STATUS ) ;
}
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
BtlController_EmitDrawPartyStatusSummary ( 0 , hpStatus , 0x80 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-02 23:32:39 +02:00
2018-12-23 18:47:00 +01:00
( * state ) + + ;
}
break ;
case 6 : // wait for previous action to complete
if ( ! gBattleControllerExecFlags )
( * state ) + + ;
break ;
case 7 : // print battle intro message
if ( ! IsBattlerMarkedForControllerExec ( GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ) )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
PrepareStringBattle ( STRINGID_INTROMSG , GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ) ;
( * state ) + + ;
}
break ;
case 8 : // wait for intro message to be printed
if ( ! IsBattlerMarkedForControllerExec ( GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ) )
{
if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
( * state ) + + ;
2017-10-02 23:32:39 +02:00
}
else
{
2018-12-23 18:47:00 +01:00
if ( B_FAST_INTRO )
* state = 15 ; // Wait for text to be printed.
else
* state = 14 ; // Wait for text and sprite.
2017-10-02 23:32:39 +02:00
}
}
2018-12-23 18:47:00 +01:00
break ;
case 9 : // print opponent sends out
2021-01-29 07:45:58 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK & & ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER ) )
2018-12-23 18:47:00 +01:00
PrepareStringBattle ( STRINGID_INTROSENDOUT , GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ) ;
2017-10-02 23:32:39 +02:00
else
2018-12-23 18:47:00 +01:00
PrepareStringBattle ( STRINGID_INTROSENDOUT , GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ) ;
( * state ) + + ;
break ;
case 10 : // wait for opponent sends out text
if ( ! gBattleControllerExecFlags )
( * state ) + + ;
break ;
case 11 : // first opponent's mon send out animation
2021-01-29 07:45:58 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK & & ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER ) )
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
2017-10-02 23:32:39 +02:00
else
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
2017-10-02 23:32:39 +02:00
2018-12-23 18:47:00 +01:00
BtlController_EmitIntroTrainerBallThrow ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
( * state ) + + ;
break ;
case 12 : // nothing
( * state ) + + ;
case 13 : // second opponent's mon send out
2019-01-27 20:54:34 +01:00
if ( gBattleTypeFlags & ( BATTLE_TYPE_MULTI | BATTLE_TYPE_TWO_OPPONENTS ) & & ! BATTLE_TWO_VS_ONE_OPPONENT )
2017-10-02 23:32:39 +02:00
{
2021-01-29 07:45:58 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK & & ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER ) )
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_PLAYER_RIGHT ) ;
else
gActiveBattler = GetBattlerAtPosition ( B_POSITION_OPPONENT_RIGHT ) ;
2018-02-06 20:48:02 +01:00
BtlController_EmitIntroTrainerBallThrow ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-02 23:32:39 +02:00
}
2021-01-29 07:45:58 +01:00
if ( B_FAST_INTRO & & ! ( gBattleTypeFlags & ( BATTLE_TYPE_RECORDED | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_LINK ) ) )
2018-12-23 18:47:00 +01:00
* state = 15 ; // Print at the same time as trainer sends out second mon.
2017-10-02 23:32:39 +02:00
else
2018-12-23 18:47:00 +01:00
( * state ) + + ;
break ;
case 14 : // wait for opponent 2 send out
if ( ! gBattleControllerExecFlags )
( * state ) + + ;
break ;
case 15 : // wait for wild battle message
if ( ! IsBattlerMarkedForControllerExec ( GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ) )
( * state ) + + ;
break ;
case 16 : // print player sends out
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_SAFARI ) )
2017-10-02 23:32:39 +02:00
{
2021-01-29 07:45:58 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK & & ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER ) )
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
else
gActiveBattler = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
// A hack that makes fast intro work in trainer battles too.
if ( B_FAST_INTRO
& & gBattleTypeFlags & BATTLE_TYPE_TRAINER
2021-01-29 07:45:58 +01:00
& & ! ( gBattleTypeFlags & ( BATTLE_TYPE_RECORDED | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_RECORDED_IS_MASTER | BATTLE_TYPE_LINK ) )
2018-12-23 18:47:00 +01:00
& & gSprites [ gHealthboxSpriteIds [ gActiveBattler ^ BIT_SIDE ] ] . callback = = SpriteCallbackDummy )
2017-10-02 23:32:39 +02:00
{
return ;
}
2018-12-23 18:47:00 +01:00
PrepareStringBattle ( STRINGID_INTROSENDOUT , gActiveBattler ) ;
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
( * state ) + + ;
break ;
case 17 : // wait for player send out message
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_LINK & & gBattleControllerExecFlags ) )
2017-10-02 23:32:39 +02:00
{
2021-01-29 07:45:58 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK & & ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER ) )
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
2017-10-02 23:32:39 +02:00
else
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
2017-10-02 23:32:39 +02:00
2018-12-23 18:47:00 +01:00
if ( ! IsBattlerMarkedForControllerExec ( gActiveBattler ) )
( * state ) + + ;
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
break ;
case 18 : // player 1 send out
2021-01-29 07:45:58 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK & & ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER ) )
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) ;
2017-10-02 23:32:39 +02:00
else
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
2017-10-02 23:32:39 +02:00
2018-12-23 18:47:00 +01:00
BtlController_EmitIntroTrainerBallThrow ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
( * state ) + + ;
break ;
case 19 : // player 2 send out
if ( gBattleTypeFlags & ( BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER ) )
2017-10-02 23:32:39 +02:00
{
2021-01-29 07:45:58 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_LINK & & ! ( gBattleTypeFlags & BATTLE_TYPE_RECORDED_IS_MASTER ) )
2018-12-23 18:47:00 +01:00
gActiveBattler = GetBattlerAtPosition ( B_POSITION_OPPONENT_RIGHT ) ;
else
gActiveBattler = GetBattlerAtPosition ( B_POSITION_PLAYER_RIGHT ) ;
2018-02-06 20:48:02 +01:00
BtlController_EmitIntroTrainerBallThrow ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
( * state ) + + ;
break ;
case 20 : // set dex and battle vars
if ( ! gBattleControllerExecFlags )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
2017-10-02 23:32:39 +02:00
{
2018-12-23 18:47:00 +01:00
if ( GetBattlerSide ( gActiveBattler ) = = B_SIDE_OPPONENT
& & ! ( gBattleTypeFlags & ( BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_LINK
2021-01-29 07:45:58 +01:00
| BATTLE_TYPE_RECORDED_LINK
2018-12-23 18:47:00 +01:00
| BATTLE_TYPE_TRAINER_HILL ) ) )
{
HandleSetPokedexFlag ( SpeciesToNationalPokedexNum ( gBattleMons [ gActiveBattler ] . species ) , FLAG_SET_SEEN , gBattleMons [ gActiveBattler ] . personality ) ;
}
2017-10-02 23:32:39 +02:00
}
2018-12-23 18:47:00 +01:00
gBattleStruct - > switchInAbilitiesCounter = 0 ;
gBattleStruct - > switchInItemsCounter = 0 ;
gBattleStruct - > overworldWeatherDone = FALSE ;
2017-10-02 23:32:39 +02:00
2018-12-23 18:47:00 +01:00
gBattleMainFunc = TryDoEventsBeforeFirstTurn ;
}
break ;
2017-10-02 23:32:39 +02:00
}
}
static void TryDoEventsBeforeFirstTurn ( void )
{
2019-08-05 11:24:49 +02:00
s32 i , j ;
2017-10-02 23:32:39 +02:00
2018-02-06 20:48:02 +01:00
if ( gBattleControllerExecFlags )
2017-10-02 23:32:39 +02:00
return ;
2021-06-08 16:40:47 +02:00
// Set invalid mons as absent(for example when starting a double battle with only one pokemon).
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( gBattleMons [ i ] . hp = = 0 | | gBattleMons [ i ] . species = = SPECIES_NONE )
gAbsentBattlerFlags | = gBitTable [ i ] ;
}
2017-10-02 23:32:39 +02:00
if ( gBattleStruct - > switchInAbilitiesCounter = = 0 )
{
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2018-06-28 21:06:32 +02:00
gBattlerByTurnOrder [ i ] = i ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount - 1 ; i + + )
2017-10-02 23:32:39 +02:00
{
2018-02-06 02:46:59 +01:00
for ( j = i + 1 ; j < gBattlersCount ; j + + )
2017-10-02 23:32:39 +02:00
{
2018-06-28 21:06:32 +02:00
if ( GetWhoStrikesFirst ( gBattlerByTurnOrder [ i ] , gBattlerByTurnOrder [ j ] , TRUE ) ! = 0 )
2017-10-04 19:25:14 +02:00
SwapTurnOrder ( i , j ) ;
2017-10-02 23:32:39 +02:00
}
}
}
if ( ! gBattleStruct - > overworldWeatherDone
& & AbilityBattleEffects ( 0 , 0 , 0 , ABILITYEFFECT_SWITCH_IN_WEATHER , 0 ) ! = 0 )
{
gBattleStruct - > overworldWeatherDone = TRUE ;
return ;
}
2021-01-29 07:45:58 +01:00
2020-12-14 03:42:48 +01:00
if ( ! gBattleStruct - > terrainDone & & AbilityBattleEffects ( 0 , 0 , 0 , ABILITYEFFECT_SWITCH_IN_TERRAIN , 0 ) ! = 0 )
{
gBattleStruct - > terrainDone = TRUE ;
return ;
}
2021-01-29 07:45:58 +01:00
2020-12-06 05:00:51 +01:00
// Totem boosts
for ( i = 0 ; i < gBattlersCount ; i + + )
{
if ( gTotemBoosts [ i ] . stats ! = 0 )
{
gBattlerAttacker = i ;
BattleScriptExecute ( BattleScript_TotemVar ) ;
return ;
}
}
memset ( gTotemBoosts , 0 , sizeof ( gTotemBoosts ) ) ; // erase all totem boosts just to be safe
2021-01-29 07:45:58 +01:00
2018-06-28 21:06:32 +02:00
// Check all switch in abilities happening from the fastest mon to slowest.
2018-02-06 02:46:59 +01:00
while ( gBattleStruct - > switchInAbilitiesCounter < gBattlersCount )
2017-10-02 23:32:39 +02:00
{
2019-08-05 11:24:49 +02:00
gBattlerAttacker = gBattlerByTurnOrder [ gBattleStruct - > switchInAbilitiesCounter + + ] ;
if ( AbilityBattleEffects ( ABILITYEFFECT_ON_SWITCHIN , gBattlerAttacker , 0 , 0 , 0 ) ! = 0 )
2017-10-02 23:32:39 +02:00
return ;
}
if ( AbilityBattleEffects ( ABILITYEFFECT_INTIMIDATE1 , 0 , 0 , 0 , 0 ) ! = 0 )
return ;
2019-08-30 12:25:21 +02:00
if ( AbilityBattleEffects ( ABILITYEFFECT_TRACE1 , 0 , 0 , 0 , 0 ) ! = 0 )
2017-10-02 23:32:39 +02:00
return ;
2018-06-28 21:06:32 +02:00
// Check all switch in items having effect from the fastest mon to slowest.
2018-02-06 02:46:59 +01:00
while ( gBattleStruct - > switchInItemsCounter < gBattlersCount )
2017-10-02 23:32:39 +02:00
{
2019-08-05 11:24:49 +02:00
if ( ItemBattleEffects ( ITEMEFFECT_ON_SWITCH_IN , gBattlerByTurnOrder [ gBattleStruct - > switchInItemsCounter + + ] , FALSE ) )
2017-10-02 23:32:39 +02:00
return ;
}
2021-01-29 07:45:58 +01:00
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
2017-10-02 23:32:39 +02:00
{
2018-06-28 21:06:32 +02:00
* ( gBattleStruct - > monToSwitchIntoId + i ) = PARTY_SIZE ;
2018-02-06 23:09:39 +01:00
gChosenActionByBattler [ i ] = B_ACTION_NONE ;
gChosenMoveByBattler [ i ] = MOVE_NONE ;
2017-10-02 23:32:39 +02:00
}
2017-10-06 00:12:01 +02:00
TurnValuesCleanUp ( FALSE ) ;
2017-10-02 23:32:39 +02:00
SpecialStatusesClear ( ) ;
2018-02-06 02:46:59 +01:00
* ( & gBattleStruct - > field_91 ) = gAbsentBattlerFlags ;
2018-06-17 16:48:58 +02:00
BattlePutTextOnWindow ( gText_EmptyString3 , 0 ) ;
2017-10-04 19:25:14 +02:00
gBattleMainFunc = HandleTurnActionSelectionState ;
2017-10-02 23:32:39 +02:00
ResetSentPokesToOpponentValue ( ) ;
for ( i = 0 ; i < BATTLE_COMMUNICATION_ENTRIES_COUNT ; i + + )
gBattleCommunication [ i ] = 0 ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-02 23:32:39 +02:00
gBattleMons [ i ] . status2 & = ~ ( STATUS2_FLINCHED ) ;
* ( & gBattleStruct - > turnEffectsTracker ) = 0 ;
2018-02-07 22:53:40 +01:00
* ( & gBattleStruct - > turnEffectsBattlerId ) = 0 ;
2017-12-02 14:08:55 +01:00
* ( & gBattleStruct - > wishPerishSongState ) = 0 ;
2018-02-07 22:53:40 +01:00
* ( & gBattleStruct - > wishPerishSongBattlerId ) = 0 ;
2019-08-23 14:46:21 +02:00
gBattleScripting . moveendState = 0 ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState = 0 ;
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnCountersTracker = 0 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-10-02 23:32:39 +02:00
gRandomTurnNumber = Random ( ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_ARENA )
{
StopCryAndClearCrySongs ( ) ;
2018-08-25 21:04:12 +02:00
BattleScriptExecute ( BattleScript_ArenaTurnBeginning ) ;
2017-10-02 23:32:39 +02:00
}
}
2017-10-06 19:09:37 +02:00
static void HandleEndTurn_ContinueBattle ( void )
2017-10-02 23:32:39 +02:00
{
s32 i ;
2018-02-06 20:48:02 +01:00
if ( gBattleControllerExecFlags = = 0 )
2017-10-02 23:32:39 +02:00
{
gBattleMainFunc = BattleTurnPassed ;
for ( i = 0 ; i < BATTLE_COMMUNICATION_ENTRIES_COUNT ; i + + )
gBattleCommunication [ i ] = 0 ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-02 23:32:39 +02:00
{
gBattleMons [ i ] . status2 & = ~ ( STATUS2_FLINCHED ) ;
2018-01-16 22:12:38 +01:00
if ( ( gBattleMons [ i ] . status1 & STATUS1_SLEEP ) & & ( gBattleMons [ i ] . status2 & STATUS2_MULTIPLETURNS ) )
2017-10-02 23:32:39 +02:00
CancelMultiTurnMoves ( i ) ;
}
gBattleStruct - > turnEffectsTracker = 0 ;
2018-02-07 22:53:40 +01:00
gBattleStruct - > turnEffectsBattlerId = 0 ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > wishPerishSongState = 0 ;
2018-02-07 22:53:40 +01:00
gBattleStruct - > wishPerishSongBattlerId = 0 ;
gBattleStruct - > turnCountersTracker = 0 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-10-02 23:32:39 +02:00
}
}
void BattleTurnPassed ( void )
{
s32 i ;
2017-10-06 00:12:01 +02:00
TurnValuesCleanUp ( TRUE ) ;
2017-10-02 23:32:39 +02:00
if ( gBattleOutcome = = 0 )
{
2018-07-21 12:10:08 +02:00
if ( DoFieldEndTurnEffects ( ) )
2017-10-02 23:32:39 +02:00
return ;
2018-07-18 22:07:48 +02:00
if ( DoBattlerEndTurnEffects ( ) )
2017-10-02 23:32:39 +02:00
return ;
}
2018-06-28 21:06:32 +02:00
if ( HandleFaintedMonActions ( ) )
2017-10-02 23:32:39 +02:00
return ;
2017-12-02 14:08:55 +01:00
gBattleStruct - > faintedActionsState = 0 ;
2018-06-28 21:06:32 +02:00
if ( HandleWishPerishSongOnTurnEnd ( ) )
2017-10-02 23:32:39 +02:00
return ;
2017-10-06 00:12:01 +02:00
TurnValuesCleanUp ( FALSE ) ;
2017-10-02 23:32:39 +02:00
gHitMarker & = ~ ( HITMARKER_NO_ATTACKSTRING ) ;
gHitMarker & = ~ ( HITMARKER_UNABLE_TO_USE_MOVE ) ;
gHitMarker & = ~ ( HITMARKER_x400000 ) ;
gHitMarker & = ~ ( HITMARKER_x100000 ) ;
gBattleScripting . animTurn = 0 ;
gBattleScripting . animTargetsHit = 0 ;
2019-08-23 14:46:21 +02:00
gBattleScripting . moveendState = 0 ;
2017-10-02 23:32:39 +02:00
gBattleMoveDamage = 0 ;
2018-01-16 22:12:38 +01:00
gMoveResultFlags = 0 ;
2017-10-02 23:32:39 +02:00
for ( i = 0 ; i < 5 ; i + + )
gBattleCommunication [ i ] = 0 ;
if ( gBattleOutcome ! = 0 )
{
2019-09-03 21:08:25 +02:00
gCurrentActionFuncId = B_ACTION_FINISHED ;
2017-10-06 00:12:01 +02:00
gBattleMainFunc = RunTurnActionsFunctions ;
2017-10-02 23:32:39 +02:00
return ;
}
if ( gBattleResults . battleTurnCounter < 0xFF )
{
gBattleResults . battleTurnCounter + + ;
2018-12-07 23:50:56 +01:00
gBattleStruct - > arenaTurnCounter + + ;
2017-10-02 23:32:39 +02:00
}
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-02 23:32:39 +02:00
{
2018-02-06 23:09:39 +01:00
gChosenActionByBattler [ i ] = B_ACTION_NONE ;
gChosenMoveByBattler [ i ] = MOVE_NONE ;
2017-10-02 23:32:39 +02:00
}
2018-07-21 12:10:08 +02:00
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
2018-06-28 21:06:32 +02:00
* ( gBattleStruct - > monToSwitchIntoId + i ) = PARTY_SIZE ;
2017-10-02 23:32:39 +02:00
2018-02-06 02:46:59 +01:00
* ( & gBattleStruct - > field_91 ) = gAbsentBattlerFlags ;
2018-06-17 16:48:58 +02:00
BattlePutTextOnWindow ( gText_EmptyString3 , 0 ) ;
2017-10-04 19:25:14 +02:00
gBattleMainFunc = HandleTurnActionSelectionState ;
2017-10-02 23:32:39 +02:00
gRandomTurnNumber = Random ( ) ;
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
2020-07-17 02:12:12 +02:00
BattleScriptExecute ( BattleScript_PalacePrintFlavorText ) ;
2018-12-07 23:50:56 +01:00
else if ( gBattleTypeFlags & BATTLE_TYPE_ARENA & & gBattleStruct - > arenaTurnCounter = = 0 )
2018-08-25 21:04:12 +02:00
BattleScriptExecute ( BattleScript_ArenaTurnBeginning ) ;
2018-11-03 01:17:16 +01:00
else if ( ShouldDoTrainerSlide ( GetBattlerAtPosition ( B_POSITION_OPPONENT_LEFT ) , gTrainerBattleOpponent_A , TRAINER_SLIDE_LAST_LOW_HP ) )
BattleScriptExecute ( BattleScript_TrainerSlideMsgEnd2 ) ;
2017-10-02 23:32:39 +02:00
}
u8 IsRunningFromBattleImpossible ( void )
{
2020-02-08 14:20:02 +01:00
u32 holdEffect , i ;
2017-10-02 23:32:39 +02:00
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ gActiveBattler ] . item = = ITEM_ENIGMA_BERRY )
holdEffect = gEnigmaBerries [ gActiveBattler ] . holdEffect ;
2017-10-02 23:32:39 +02:00
else
2018-02-06 02:46:59 +01:00
holdEffect = ItemId_GetHoldEffect ( gBattleMons [ gActiveBattler ] . item ) ;
2017-10-02 23:32:39 +02:00
2018-02-08 12:13:29 +01:00
gPotentialItemEffectBattler = gActiveBattler ;
2017-10-02 23:32:39 +02:00
2018-10-15 21:19:52 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE ) // Cannot ever run from saving Birch's battle.
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_DONT_LEAVE_BIRCH ;
2018-10-15 21:19:52 +02:00
return 1 ;
}
2020-02-16 13:24:50 +01:00
if ( GetBattlerPosition ( gActiveBattler ) = = B_POSITION_PLAYER_RIGHT & & WILD_DOUBLE_BATTLE
& & IsBattlerAlive ( GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ) ) // The second pokemon cannot run from a double wild battle, unless it's the only alive mon.
2018-10-15 21:19:52 +02:00
{
2021-04-28 03:36:37 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_CANT_ESCAPE ;
2018-10-15 21:19:52 +02:00
return 1 ;
}
2017-10-02 23:32:39 +02:00
if ( holdEffect = = HOLD_EFFECT_CAN_ALWAYS_RUN )
return 0 ;
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
return 0 ;
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ gActiveBattler ] . ability = = ABILITY_RUN_AWAY )
2017-10-02 23:32:39 +02:00
return 0 ;
2020-02-08 14:20:02 +01:00
if ( ( i = IsAbilityPreventingEscape ( gActiveBattler ) ) )
2017-10-02 23:32:39 +02:00
{
2018-02-06 02:46:59 +01:00
gBattleScripting . battler = i - 1 ;
2017-10-02 23:32:39 +02:00
gLastUsedAbility = gBattleMons [ i - 1 ] . ability ;
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_PREVENTS_ESCAPE ;
2017-10-02 23:32:39 +02:00
return 2 ;
}
2020-02-08 14:20:02 +01:00
2020-04-28 11:14:20 +02:00
if ( ! CanBattlerEscape ( gActiveBattler ) )
2017-10-02 23:32:39 +02:00
{
2021-04-02 08:27:12 +02:00
gBattleCommunication [ MULTISTRING_CHOOSER ] = B_MSG_CANT_ESCAPE ;
2017-10-02 23:32:39 +02:00
return 1 ;
}
return 0 ;
}
2017-10-03 21:35:27 +02:00
2019-10-26 03:55:01 +02:00
void SwitchPartyOrder ( u8 battler )
2017-10-03 21:35:27 +02:00
{
s32 i ;
2019-10-26 03:55:01 +02:00
u8 partyId1 ;
u8 partyId2 ;
2017-10-03 21:35:27 +02:00
2018-02-06 23:09:39 +01:00
// gBattleStruct->field_60[battler][i]
2017-10-03 21:35:27 +02:00
2019-10-18 01:22:03 +02:00
for ( i = 0 ; i < ( int ) ARRAY_COUNT ( gBattlePartyCurrentOrder ) ; i + + )
gBattlePartyCurrentOrder [ i ] = * ( battler * 3 + i + ( u8 * ) ( gBattleStruct - > field_60 ) ) ;
2017-10-03 21:35:27 +02:00
2019-10-26 03:55:01 +02:00
partyId1 = GetPartyIdFromBattlePartyId ( gBattlerPartyIndexes [ battler ] ) ;
partyId2 = GetPartyIdFromBattlePartyId ( * ( gBattleStruct - > monToSwitchIntoId + battler ) ) ;
SwitchPartyMonSlots ( partyId1 , partyId2 ) ;
2017-10-03 21:35:27 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE )
{
2019-10-18 01:22:03 +02:00
for ( i = 0 ; i < ( int ) ARRAY_COUNT ( gBattlePartyCurrentOrder ) ; i + + )
2017-10-03 21:35:27 +02:00
{
2019-10-18 01:22:03 +02:00
* ( battler * 3 + i + ( u8 * ) ( gBattleStruct - > field_60 ) ) = gBattlePartyCurrentOrder [ i ] ;
* ( BATTLE_PARTNER ( battler ) * 3 + i + ( u8 * ) ( gBattleStruct - > field_60 ) ) = gBattlePartyCurrentOrder [ i ] ;
2017-10-03 21:35:27 +02:00
}
}
else
{
2019-10-18 01:22:03 +02:00
for ( i = 0 ; i < ( int ) ARRAY_COUNT ( gBattlePartyCurrentOrder ) ; i + + )
2017-10-03 21:35:27 +02:00
{
2019-10-18 01:22:03 +02:00
* ( battler * 3 + i + ( u8 * ) ( gBattleStruct - > field_60 ) ) = gBattlePartyCurrentOrder [ i ] ;
2017-10-03 21:35:27 +02:00
}
}
}
2017-10-06 17:06:45 +02:00
enum
{
STATE_TURN_START_RECORD ,
STATE_BEFORE_ACTION_CHOSEN ,
STATE_WAIT_ACTION_CHOSEN ,
STATE_WAIT_ACTION_CASE_CHOSEN ,
STATE_WAIT_ACTION_CONFIRMED_STANDBY ,
STATE_WAIT_ACTION_CONFIRMED ,
STATE_SELECTION_SCRIPT ,
STATE_WAIT_SET_BEFORE_ACTION ,
STATE_SELECTION_SCRIPT_MAY_RUN
} ;
2017-10-04 19:25:14 +02:00
2017-10-06 19:09:37 +02:00
static void HandleTurnActionSelectionState ( void )
2017-10-03 21:35:27 +02:00
{
s32 i ;
2017-10-04 19:25:14 +02:00
gBattleCommunication [ ACTIONS_CONFIRMED_COUNT ] = 0 ;
2018-02-06 02:46:59 +01:00
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
2017-10-03 21:35:27 +02:00
{
2018-02-06 02:46:59 +01:00
u8 position = GetBattlerPosition ( gActiveBattler ) ;
switch ( gBattleCommunication [ gActiveBattler ] )
2017-10-03 21:35:27 +02:00
{
2018-07-07 19:57:09 +02:00
case STATE_TURN_START_RECORD : // Recorded battle related action on start of every turn.
2018-02-08 11:17:41 +01:00
RecordedBattle_CopyBattlerMoves ( ) ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] = STATE_BEFORE_ACTION_CHOSEN ;
2017-10-03 21:35:27 +02:00
break ;
2018-07-07 19:57:09 +02:00
case STATE_BEFORE_ACTION_CHOSEN : // Choose an action.
2018-06-28 21:06:32 +02:00
* ( gBattleStruct - > monToSwitchIntoId + gActiveBattler ) = PARTY_SIZE ;
2017-10-03 21:35:27 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_MULTI
2018-06-28 21:06:32 +02:00
| | ( position & BIT_FLANK ) = = B_FLANK_LEFT
2018-02-06 23:09:39 +01:00
| | gBattleStruct - > field_91 & gBitTable [ GetBattlerAtPosition ( BATTLE_PARTNER ( position ) ) ]
2018-06-28 21:06:32 +02:00
| | gBattleCommunication [ GetBattlerAtPosition ( BATTLE_PARTNER ( position ) ) ] = = STATE_WAIT_ACTION_CONFIRMED )
2017-10-03 21:35:27 +02:00
{
2018-02-06 02:46:59 +01:00
if ( gBattleStruct - > field_91 & gBitTable [ gActiveBattler ] )
2017-10-03 21:35:27 +02:00
{
2018-02-06 23:09:39 +01:00
gChosenActionByBattler [ gActiveBattler ] = B_ACTION_NOTHING_FAINTED ;
2017-10-03 21:35:27 +02:00
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_MULTI ) )
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] = STATE_WAIT_ACTION_CONFIRMED ;
2017-10-03 21:35:27 +02:00
else
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] = STATE_WAIT_ACTION_CONFIRMED_STANDBY ;
2017-10-03 21:35:27 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
if ( gBattleMons [ gActiveBattler ] . status2 & STATUS2_MULTIPLETURNS
| | gBattleMons [ gActiveBattler ] . status2 & STATUS2_RECHARGE )
2017-10-03 21:35:27 +02:00
{
2018-02-06 23:09:39 +01:00
gChosenActionByBattler [ gActiveBattler ] = B_ACTION_USE_MOVE ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] = STATE_WAIT_ACTION_CONFIRMED_STANDBY ;
2017-10-03 21:35:27 +02:00
}
2018-10-16 22:19:53 +02:00
else if ( WILD_DOUBLE_BATTLE
& & position = = B_POSITION_PLAYER_RIGHT
2018-10-15 21:19:52 +02:00
& & ( gBattleStruct - > throwingPokeBall | | gChosenActionByBattler [ GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ] = = B_ACTION_RUN ) )
{
gBattleStruct - > throwingPokeBall = FALSE ;
gChosenActionByBattler [ gActiveBattler ] = B_ACTION_NOTHING_FAINTED ; // Not fainted, but it cannot move, because of the throwing ball.
gBattleCommunication [ gActiveBattler ] = STATE_WAIT_ACTION_CONFIRMED_STANDBY ;
}
2017-10-03 21:35:27 +02:00
else
{
2019-01-05 16:00:57 +01:00
BtlController_EmitChooseAction ( 0 , gChosenActionByBattler [ 0 ] , gBattleResources - > bufferB [ 0 ] [ 1 ] | ( gBattleResources - > bufferB [ 0 ] [ 2 ] < < 8 ) ) ;
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
}
}
}
break ;
2018-07-07 19:57:09 +02:00
case STATE_WAIT_ACTION_CHOSEN : // Try to perform an action.
2021-03-30 23:38:09 +02:00
if ( ! ( gBattleControllerExecFlags & ( ( gBitTable [ gActiveBattler ] ) | ( 0xF < < 28 ) | ( gBitTable [ gActiveBattler ] < < 4 ) | ( gBitTable [ gActiveBattler ] < < 8 ) | ( gBitTable [ gActiveBattler ] < < 12 ) ) ) )
2017-10-03 21:35:27 +02:00
{
2019-01-05 16:00:57 +01:00
RecordedBattle_SetBattlerAction ( gActiveBattler , gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] ) ;
gChosenActionByBattler [ gActiveBattler ] = gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] ;
2017-10-03 21:35:27 +02:00
2019-01-05 16:00:57 +01:00
switch ( gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] )
2017-10-03 21:35:27 +02:00
{
2018-02-06 23:09:39 +01:00
case B_ACTION_USE_MOVE :
2017-10-03 21:35:27 +02:00
if ( AreAllMovesUnusable ( ) )
{
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] = STATE_SELECTION_SCRIPT ;
* ( gBattleStruct - > selectionScriptFinished + gActiveBattler ) = FALSE ;
* ( gBattleStruct - > stateIdAfterSelScript + gActiveBattler ) = STATE_WAIT_ACTION_CONFIRMED_STANDBY ;
2019-01-05 16:00:57 +01:00
* ( gBattleStruct - > moveTarget + gActiveBattler ) = gBattleResources - > bufferB [ gActiveBattler ] [ 3 ] ;
2017-10-03 21:35:27 +02:00
return ;
}
2018-02-06 02:46:59 +01:00
else if ( gDisableStructs [ gActiveBattler ] . encoredMove ! = 0 )
2017-10-03 21:35:27 +02:00
{
2018-02-06 23:09:39 +01:00
gChosenMoveByBattler [ gActiveBattler ] = gDisableStructs [ gActiveBattler ] . encoredMove ;
2018-02-06 02:46:59 +01:00
* ( gBattleStruct - > chosenMovePositions + gActiveBattler ) = gDisableStructs [ gActiveBattler ] . encoredMovePos ;
gBattleCommunication [ gActiveBattler ] = STATE_WAIT_ACTION_CONFIRMED_STANDBY ;
2017-10-03 21:35:27 +02:00
return ;
}
else
{
struct ChooseMoveStruct moveInfo ;
2018-09-20 17:59:17 +02:00
moveInfo . mega = gBattleStruct - > mega ;
2018-02-06 02:46:59 +01:00
moveInfo . species = gBattleMons [ gActiveBattler ] . species ;
moveInfo . monType1 = gBattleMons [ gActiveBattler ] . type1 ;
moveInfo . monType2 = gBattleMons [ gActiveBattler ] . type2 ;
2018-11-17 12:10:24 +01:00
moveInfo . monType3 = gBattleMons [ gActiveBattler ] . type3 ;
2017-10-03 21:35:27 +02:00
2019-09-08 18:21:24 +02:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-10-03 21:35:27 +02:00
{
2018-02-06 02:46:59 +01:00
moveInfo . moves [ i ] = gBattleMons [ gActiveBattler ] . moves [ i ] ;
moveInfo . currentPp [ i ] = gBattleMons [ gActiveBattler ] . pp [ i ] ;
2017-10-08 14:54:51 +02:00
moveInfo . maxPp [ i ] = CalculatePPWithBonus (
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . moves [ i ] ,
gBattleMons [ gActiveBattler ] . ppBonuses ,
2017-10-03 21:35:27 +02:00
i ) ;
}
2018-02-06 20:48:02 +01:00
BtlController_EmitChooseMove ( 0 , ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE ) ! = 0 , FALSE , & moveInfo ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-03 21:35:27 +02:00
}
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_USE_ITEM :
2017-10-03 21:35:27 +02:00
if ( gBattleTypeFlags & ( BATTLE_TYPE_LINK
| BATTLE_TYPE_FRONTIER_NO_PYRAMID
| BATTLE_TYPE_EREADER_TRAINER
2021-01-13 21:17:32 +01:00
| BATTLE_TYPE_RECORDED_LINK ) )
2017-10-03 21:35:27 +02:00
{
2018-02-06 20:48:02 +01:00
RecordedBattle_ClearBattlerAction ( gActiveBattler , 1 ) ;
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_ActionSelectionItemsCantBeUsed ;
gBattleCommunication [ gActiveBattler ] = STATE_SELECTION_SCRIPT ;
* ( gBattleStruct - > selectionScriptFinished + gActiveBattler ) = FALSE ;
* ( gBattleStruct - > stateIdAfterSelScript + gActiveBattler ) = STATE_BEFORE_ACTION_CHOSEN ;
2017-10-03 21:35:27 +02:00
return ;
}
else
{
2018-02-06 20:48:02 +01:00
BtlController_EmitChooseItem ( 0 , gBattleStruct - > field_60 [ gActiveBattler ] ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-03 21:35:27 +02:00
}
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_SWITCH :
2018-02-06 20:48:02 +01:00
* ( gBattleStruct - > field_58 + gActiveBattler ) = gBattlerPartyIndexes [ gActiveBattler ] ;
2020-04-28 11:14:20 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_ARENA
| | ! CanBattlerEscape ( gActiveBattler ) )
2017-10-03 21:35:27 +02:00
{
2019-10-18 01:22:03 +02:00
BtlController_EmitChoosePokemon ( 0 , PARTY_ACTION_CANT_SWITCH , PARTY_SIZE , ABILITY_NONE , gBattleStruct - > field_60 [ gActiveBattler ] ) ;
2017-10-03 21:35:27 +02:00
}
2020-02-08 14:20:02 +01:00
else if ( ( i = IsAbilityPreventingEscape ( gActiveBattler ) ) )
2017-10-03 21:35:27 +02:00
{
2020-02-09 11:02:22 +01:00
BtlController_EmitChoosePokemon ( 0 , ( ( i - 1 ) < < 4 ) | PARTY_ACTION_ABILITY_PREVENTS , PARTY_SIZE , gBattleMons [ i - 1 ] . ability , gBattleStruct - > field_60 [ gActiveBattler ] ) ;
2017-10-03 21:35:27 +02:00
}
else
{
2018-02-06 23:09:39 +01:00
if ( gActiveBattler = = 2 & & gChosenActionByBattler [ 0 ] = = B_ACTION_SWITCH )
2019-10-18 01:22:03 +02:00
BtlController_EmitChoosePokemon ( 0 , PARTY_ACTION_CHOOSE_MON , * ( gBattleStruct - > monToSwitchIntoId + 0 ) , ABILITY_NONE , gBattleStruct - > field_60 [ gActiveBattler ] ) ;
2018-02-06 23:09:39 +01:00
else if ( gActiveBattler = = 3 & & gChosenActionByBattler [ 1 ] = = B_ACTION_SWITCH )
2019-10-18 01:22:03 +02:00
BtlController_EmitChoosePokemon ( 0 , PARTY_ACTION_CHOOSE_MON , * ( gBattleStruct - > monToSwitchIntoId + 1 ) , ABILITY_NONE , gBattleStruct - > field_60 [ gActiveBattler ] ) ;
2017-10-03 21:35:27 +02:00
else
2019-10-18 01:22:03 +02:00
BtlController_EmitChoosePokemon ( 0 , PARTY_ACTION_CHOOSE_MON , PARTY_SIZE , ABILITY_NONE , gBattleStruct - > field_60 [ gActiveBattler ] ) ;
2017-10-03 21:35:27 +02:00
}
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-03 21:35:27 +02:00
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_SAFARI_BALL :
2017-10-03 21:35:27 +02:00
if ( IsPlayerPartyAndPokemonStorageFull ( ) )
{
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_PrintFullBox ;
gBattleCommunication [ gActiveBattler ] = STATE_SELECTION_SCRIPT ;
* ( gBattleStruct - > selectionScriptFinished + gActiveBattler ) = FALSE ;
* ( gBattleStruct - > stateIdAfterSelScript + gActiveBattler ) = STATE_BEFORE_ACTION_CHOSEN ;
2017-10-03 21:35:27 +02:00
return ;
}
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_SAFARI_POKEBLOCK :
2018-02-06 20:48:02 +01:00
BtlController_EmitChooseItem ( 0 , gBattleStruct - > field_60 [ gActiveBattler ] ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-03 21:35:27 +02:00
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_CANCEL_PARTNER :
2018-07-07 21:14:41 +02:00
gBattleCommunication [ gActiveBattler ] = STATE_WAIT_SET_BEFORE_ACTION ;
gBattleCommunication [ GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) ] = STATE_BEFORE_ACTION_CHOSEN ;
2018-02-06 20:48:02 +01:00
RecordedBattle_ClearBattlerAction ( gActiveBattler , 1 ) ;
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) ] . status2 & STATUS2_MULTIPLETURNS
| | gBattleMons [ GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) ] . status2 & STATUS2_RECHARGE )
2017-10-03 21:35:27 +02:00
{
2018-06-20 23:07:51 +02:00
BtlController_EmitEndBounceEffect ( 0 ) ;
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-03 21:35:27 +02:00
return ;
}
2018-02-06 23:09:39 +01:00
else if ( gChosenActionByBattler [ GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) ] = = B_ACTION_SWITCH )
2017-10-03 21:35:27 +02:00
{
2018-02-06 23:09:39 +01:00
RecordedBattle_ClearBattlerAction ( GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) , 2 ) ;
2017-10-03 21:35:27 +02:00
}
2018-02-06 23:09:39 +01:00
else if ( gChosenActionByBattler [ GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) ] = = B_ACTION_RUN )
2017-10-03 21:35:27 +02:00
{
2018-02-06 23:09:39 +01:00
RecordedBattle_ClearBattlerAction ( GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) , 1 ) ;
2017-10-03 21:35:27 +02:00
}
2018-02-06 23:09:39 +01:00
else if ( gChosenActionByBattler [ GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) ] = = B_ACTION_USE_MOVE
2018-07-07 19:57:09 +02:00
& & ( gProtectStructs [ GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) ] . noValidMoves
2018-02-06 23:09:39 +01:00
| | gDisableStructs [ GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) ] . encoredMove ) )
2017-10-03 21:35:27 +02:00
{
2018-02-06 23:09:39 +01:00
RecordedBattle_ClearBattlerAction ( GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) , 1 ) ;
2017-10-03 21:35:27 +02:00
}
else if ( gBattleTypeFlags & BATTLE_TYPE_PALACE
2018-02-06 23:09:39 +01:00
& & gChosenActionByBattler [ GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) ] = = B_ACTION_USE_MOVE )
2017-10-03 21:35:27 +02:00
{
gRngValue = gBattlePalaceMoveSelectionRngValue ;
2018-02-06 23:09:39 +01:00
RecordedBattle_ClearBattlerAction ( GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) , 1 ) ;
2017-10-03 21:35:27 +02:00
}
else
{
2018-02-06 23:09:39 +01:00
RecordedBattle_ClearBattlerAction ( GetBattlerAtPosition ( BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ) , 3 ) ;
2017-10-03 21:35:27 +02:00
}
2018-09-20 12:55:12 +02:00
2018-09-20 17:33:27 +02:00
gBattleStruct - > mega . toEvolve & = ~ ( gBitTable [ BATTLE_PARTNER ( GetBattlerPosition ( gActiveBattler ) ) ] ) ;
2018-06-20 23:07:51 +02:00
BtlController_EmitEndBounceEffect ( 0 ) ;
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2017-10-03 21:35:27 +02:00
return ;
2018-07-13 23:00:56 +02:00
case B_ACTION_DEBUG :
BtlController_EmitDebugMenu ( 0 ) ;
MarkBattlerForControllerExec ( gActiveBattler ) ;
break ;
2017-10-03 21:35:27 +02:00
}
if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER
2018-09-20 22:00:00 +02:00
& & gBattleTypeFlags & ( BATTLE_TYPE_FRONTIER | BATTLE_TYPE_TRAINER_HILL )
2019-01-05 16:00:57 +01:00
& & gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] = = B_ACTION_RUN )
2017-10-03 21:35:27 +02:00
{
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_AskIfWantsToForfeitMatch ;
2018-07-07 21:14:41 +02:00
gBattleCommunication [ gActiveBattler ] = STATE_SELECTION_SCRIPT_MAY_RUN ;
2018-02-06 02:46:59 +01:00
* ( gBattleStruct - > selectionScriptFinished + gActiveBattler ) = FALSE ;
* ( gBattleStruct - > stateIdAfterSelScript + gActiveBattler ) = STATE_BEFORE_ACTION_CHOSEN ;
2017-10-03 21:35:27 +02:00
return ;
}
else if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER
2021-01-13 21:17:32 +01:00
& & ! ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK ) )
2019-01-05 16:00:57 +01:00
& & gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] = = B_ACTION_RUN )
2017-10-03 21:35:27 +02:00
{
2017-11-26 17:26:11 +01:00
BattleScriptExecute ( BattleScript_PrintCantRunFromTrainer ) ;
2018-07-07 21:14:41 +02:00
gBattleCommunication [ gActiveBattler ] = STATE_BEFORE_ACTION_CHOSEN ;
2017-10-03 21:35:27 +02:00
}
2017-11-26 17:26:11 +01:00
else if ( IsRunningFromBattleImpossible ( )
2019-01-05 16:00:57 +01:00
& & gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] = = B_ACTION_RUN )
2017-10-03 21:35:27 +02:00
{
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = BattleScript_PrintCantEscapeFromBattle ;
gBattleCommunication [ gActiveBattler ] = STATE_SELECTION_SCRIPT ;
* ( gBattleStruct - > selectionScriptFinished + gActiveBattler ) = FALSE ;
* ( gBattleStruct - > stateIdAfterSelScript + gActiveBattler ) = STATE_BEFORE_ACTION_CHOSEN ;
2017-10-03 21:35:27 +02:00
return ;
}
else
{
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
}
}
break ;
2017-10-04 19:25:14 +02:00
case STATE_WAIT_ACTION_CASE_CHOSEN :
2021-03-30 23:38:09 +02:00
if ( ! ( gBattleControllerExecFlags & ( ( gBitTable [ gActiveBattler ] ) | ( 0xF < < 28 ) | ( gBitTable [ gActiveBattler ] < < 4 ) | ( gBitTable [ gActiveBattler ] < < 8 ) | ( gBitTable [ gActiveBattler ] < < 12 ) ) ) )
2017-10-03 21:35:27 +02:00
{
2018-02-06 23:09:39 +01:00
switch ( gChosenActionByBattler [ gActiveBattler ] )
2017-10-03 21:35:27 +02:00
{
2018-02-06 23:09:39 +01:00
case B_ACTION_USE_MOVE :
2019-01-05 16:00:57 +01:00
switch ( gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] )
2017-10-03 21:35:27 +02:00
{
case 3 :
case 4 :
case 5 :
case 6 :
case 7 :
case 8 :
case 9 :
2019-01-05 16:00:57 +01:00
gChosenActionByBattler [ gActiveBattler ] = gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] ;
2017-10-03 21:35:27 +02:00
return ;
case 15 :
2018-02-06 23:09:39 +01:00
gChosenActionByBattler [ gActiveBattler ] = B_ACTION_SWITCH ;
2017-10-03 21:35:27 +02:00
sub_803CDF8 ( ) ;
return ;
default :
sub_818603C ( 2 ) ;
2019-01-05 16:00:57 +01:00
if ( ( gBattleResources - > bufferB [ gActiveBattler ] [ 2 ] | ( gBattleResources - > bufferB [ gActiveBattler ] [ 3 ] < < 8 ) ) = = 0xFFFF )
2017-10-03 21:35:27 +02:00
{
2018-07-07 21:14:41 +02:00
gBattleCommunication [ gActiveBattler ] = STATE_BEFORE_ACTION_CHOSEN ;
2018-02-06 20:48:02 +01:00
RecordedBattle_ClearBattlerAction ( gActiveBattler , 1 ) ;
2017-10-03 21:35:27 +02:00
}
else if ( TrySetCantSelectMoveBattleScript ( ) )
{
2018-02-06 20:48:02 +01:00
RecordedBattle_ClearBattlerAction ( gActiveBattler , 1 ) ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] = STATE_SELECTION_SCRIPT ;
* ( gBattleStruct - > selectionScriptFinished + gActiveBattler ) = FALSE ;
2020-04-11 19:48:24 +02:00
gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] = B_ACTION_USE_MOVE ;
2018-02-06 02:46:59 +01:00
* ( gBattleStruct - > stateIdAfterSelScript + gActiveBattler ) = STATE_WAIT_ACTION_CHOSEN ;
2017-10-03 21:35:27 +02:00
return ;
}
else
{
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_PALACE ) )
{
2019-01-05 16:00:57 +01:00
RecordedBattle_SetBattlerAction ( gActiveBattler , gBattleResources - > bufferB [ gActiveBattler ] [ 2 ] ) ;
RecordedBattle_SetBattlerAction ( gActiveBattler , gBattleResources - > bufferB [ gActiveBattler ] [ 3 ] ) ;
2017-10-03 21:35:27 +02:00
}
2019-01-05 16:00:57 +01:00
* ( gBattleStruct - > chosenMovePositions + gActiveBattler ) = gBattleResources - > bufferB [ gActiveBattler ] [ 2 ] & ~ ( RET_MEGA_EVOLUTION ) ;
2018-02-06 23:09:39 +01:00
gChosenMoveByBattler [ gActiveBattler ] = gBattleMons [ gActiveBattler ] . moves [ * ( gBattleStruct - > chosenMovePositions + gActiveBattler ) ] ;
2019-01-05 16:00:57 +01:00
* ( gBattleStruct - > moveTarget + gActiveBattler ) = gBattleResources - > bufferB [ gActiveBattler ] [ 3 ] ;
if ( gBattleResources - > bufferB [ gActiveBattler ] [ 2 ] & RET_MEGA_EVOLUTION )
2018-09-20 17:33:27 +02:00
gBattleStruct - > mega . toEvolve | = gBitTable [ gActiveBattler ] ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
}
break ;
}
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_USE_ITEM :
2019-01-05 16:00:57 +01:00
if ( ( gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] | ( gBattleResources - > bufferB [ gActiveBattler ] [ 2 ] < < 8 ) ) = = 0 )
2017-10-03 21:35:27 +02:00
{
2018-07-07 21:14:41 +02:00
gBattleCommunication [ gActiveBattler ] = STATE_BEFORE_ACTION_CHOSEN ;
2017-10-03 21:35:27 +02:00
}
else
{
2019-01-05 16:00:57 +01:00
gLastUsedItem = ( gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] | ( gBattleResources - > bufferB [ gActiveBattler ] [ 2 ] < < 8 ) ) ;
2018-10-15 21:19:52 +02:00
if ( ItemId_GetPocket ( gLastUsedItem ) = = POCKET_POKE_BALLS )
gBattleStruct - > throwingPokeBall = TRUE ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
}
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_SWITCH :
2019-01-05 16:00:57 +01:00
if ( gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] = = PARTY_SIZE )
2017-10-03 21:35:27 +02:00
{
2018-07-07 21:14:41 +02:00
gBattleCommunication [ gActiveBattler ] = STATE_BEFORE_ACTION_CHOSEN ;
2018-02-06 20:48:02 +01:00
RecordedBattle_ClearBattlerAction ( gActiveBattler , 1 ) ;
2017-10-03 21:35:27 +02:00
}
else
{
sub_803CDF8 ( ) ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
}
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_RUN :
2017-10-06 17:06:45 +02:00
gHitMarker | = HITMARKER_RUN ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_SAFARI_WATCH_CAREFULLY :
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_SAFARI_BALL :
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_SAFARI_POKEBLOCK :
2019-01-05 16:00:57 +01:00
if ( ( gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] | ( gBattleResources - > bufferB [ gActiveBattler ] [ 2 ] < < 8 ) ) ! = 0 )
2017-10-03 21:35:27 +02:00
{
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
}
else
{
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] = STATE_BEFORE_ACTION_CHOSEN ;
2017-10-03 21:35:27 +02:00
}
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_SAFARI_GO_NEAR :
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
break ;
2018-02-06 23:09:39 +01:00
case B_ACTION_SAFARI_RUN :
2017-10-06 17:06:45 +02:00
gHitMarker | = HITMARKER_RUN ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
break ;
2018-06-20 23:07:51 +02:00
case B_ACTION_WALLY_THROW :
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
break ;
2018-07-13 23:00:56 +02:00
case B_ACTION_DEBUG :
gBattleCommunication [ gActiveBattler ] = STATE_BEFORE_ACTION_CHOSEN ;
break ;
2017-10-03 21:35:27 +02:00
}
}
break ;
2017-10-04 19:25:14 +02:00
case STATE_WAIT_ACTION_CONFIRMED_STANDBY :
2021-06-08 16:40:47 +02:00
if ( ! ( gBattleControllerExecFlags & ( ( gBitTable [ gActiveBattler ] )
2021-03-30 23:38:09 +02:00
| ( 0xF < < 28 )
2021-06-08 16:40:47 +02:00
| ( gBitTable [ gActiveBattler ] < < 4 )
| ( gBitTable [ gActiveBattler ] < < 8 )
2021-01-22 08:48:22 +01:00
| ( gBitTable [ gActiveBattler ] < < 12 ) ) ) )
2017-10-03 21:35:27 +02:00
{
2018-07-07 21:14:41 +02:00
if ( AllAtActionConfirmed ( ) )
i = TRUE ;
else
i = FALSE ;
2017-10-03 21:35:27 +02:00
if ( ( ( gBattleTypeFlags & ( BATTLE_TYPE_MULTI | BATTLE_TYPE_DOUBLE ) ) ! = BATTLE_TYPE_DOUBLE )
2018-07-07 21:14:41 +02:00
| | ( position & BIT_FLANK ) ! = B_FLANK_LEFT
2018-02-06 02:46:59 +01:00
| | ( * ( & gBattleStruct - > field_91 ) & gBitTable [ GetBattlerAtPosition ( position ^ BIT_FLANK ) ] ) )
2017-10-03 21:35:27 +02:00
{
2018-02-06 20:48:02 +01:00
BtlController_EmitLinkStandbyMsg ( 0 , 0 , i ) ;
2017-10-03 21:35:27 +02:00
}
else
{
2018-02-06 20:48:02 +01:00
BtlController_EmitLinkStandbyMsg ( 0 , 1 , i ) ;
2017-10-03 21:35:27 +02:00
}
2018-02-06 20:48:02 +01:00
MarkBattlerForControllerExec ( gActiveBattler ) ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] + + ;
2017-10-03 21:35:27 +02:00
}
break ;
2017-10-04 19:25:14 +02:00
case STATE_WAIT_ACTION_CONFIRMED :
2021-03-30 23:38:09 +02:00
if ( ! ( gBattleControllerExecFlags & ( ( gBitTable [ gActiveBattler ] ) | ( 0xF < < 28 ) | ( gBitTable [ gActiveBattler ] < < 4 ) | ( gBitTable [ gActiveBattler ] < < 8 ) | ( gBitTable [ gActiveBattler ] < < 12 ) ) ) )
2017-10-03 21:35:27 +02:00
{
2017-10-04 19:25:14 +02:00
gBattleCommunication [ ACTIONS_CONFIRMED_COUNT ] + + ;
2017-10-03 21:35:27 +02:00
}
break ;
2017-10-04 19:25:14 +02:00
case STATE_SELECTION_SCRIPT :
2018-02-06 02:46:59 +01:00
if ( * ( gBattleStruct - > selectionScriptFinished + gActiveBattler ) )
2017-10-03 21:35:27 +02:00
{
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] = * ( gBattleStruct - > stateIdAfterSelScript + gActiveBattler ) ;
2017-10-03 21:35:27 +02:00
}
else
{
2018-02-06 23:09:39 +01:00
gBattlerAttacker = gActiveBattler ;
2018-02-06 02:46:59 +01:00
gBattlescriptCurrInstr = gSelectionBattleScripts [ gActiveBattler ] ;
2021-03-30 23:38:09 +02:00
if ( ! ( gBattleControllerExecFlags & ( ( gBitTable [ gActiveBattler ] ) | ( 0xF < < 28 ) | ( gBitTable [ gActiveBattler ] < < 4 ) | ( gBitTable [ gActiveBattler ] < < 8 ) | ( gBitTable [ gActiveBattler ] < < 12 ) ) ) )
2017-10-03 21:35:27 +02:00
{
gBattleScriptingCommandsTable [ gBattlescriptCurrInstr [ 0 ] ] ( ) ;
}
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = gBattlescriptCurrInstr ;
2017-10-03 21:35:27 +02:00
}
break ;
2017-10-04 19:25:14 +02:00
case STATE_WAIT_SET_BEFORE_ACTION :
2021-03-30 23:38:09 +02:00
if ( ! ( gBattleControllerExecFlags & ( ( gBitTable [ gActiveBattler ] ) | ( 0xF < < 28 ) | ( gBitTable [ gActiveBattler ] < < 4 ) | ( gBitTable [ gActiveBattler ] < < 8 ) | ( gBitTable [ gActiveBattler ] < < 12 ) ) ) )
2017-10-03 21:35:27 +02:00
{
2018-07-07 21:14:41 +02:00
gBattleCommunication [ gActiveBattler ] = STATE_BEFORE_ACTION_CHOSEN ;
2017-10-03 21:35:27 +02:00
}
break ;
2017-10-04 19:25:14 +02:00
case STATE_SELECTION_SCRIPT_MAY_RUN :
2018-02-06 02:46:59 +01:00
if ( * ( gBattleStruct - > selectionScriptFinished + gActiveBattler ) )
2017-10-03 21:35:27 +02:00
{
2020-04-11 19:48:24 +02:00
if ( gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] = = B_ACTION_NOTHING_FAINTED )
2017-10-03 21:35:27 +02:00
{
2017-10-06 17:06:45 +02:00
gHitMarker | = HITMARKER_RUN ;
2018-02-06 23:09:39 +01:00
gChosenActionByBattler [ gActiveBattler ] = B_ACTION_RUN ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] = STATE_WAIT_ACTION_CONFIRMED_STANDBY ;
2017-10-03 21:35:27 +02:00
}
else
{
2018-02-06 20:48:02 +01:00
RecordedBattle_ClearBattlerAction ( gActiveBattler , 1 ) ;
2018-02-06 02:46:59 +01:00
gBattleCommunication [ gActiveBattler ] = * ( gBattleStruct - > stateIdAfterSelScript + gActiveBattler ) ;
2017-10-03 21:35:27 +02:00
}
}
else
{
2018-02-06 23:09:39 +01:00
gBattlerAttacker = gActiveBattler ;
2018-02-06 02:46:59 +01:00
gBattlescriptCurrInstr = gSelectionBattleScripts [ gActiveBattler ] ;
2021-03-30 23:38:09 +02:00
if ( ! ( gBattleControllerExecFlags & ( ( gBitTable [ gActiveBattler ] ) | ( 0xF < < 28 ) | ( gBitTable [ gActiveBattler ] < < 4 ) | ( gBitTable [ gActiveBattler ] < < 8 ) | ( gBitTable [ gActiveBattler ] < < 12 ) ) ) )
2017-10-03 21:35:27 +02:00
{
gBattleScriptingCommandsTable [ gBattlescriptCurrInstr [ 0 ] ] ( ) ;
}
2018-02-06 02:46:59 +01:00
gSelectionBattleScripts [ gActiveBattler ] = gBattlescriptCurrInstr ;
2017-10-03 21:35:27 +02:00
}
break ;
}
}
2018-07-07 21:14:41 +02:00
// Check if everyone chose actions.
2018-02-06 02:46:59 +01:00
if ( gBattleCommunication [ ACTIONS_CONFIRMED_COUNT ] = = gBattlersCount )
2017-10-03 21:35:27 +02:00
{
sub_818603C ( 1 ) ;
2018-02-08 11:17:41 +01:00
gBattleMainFunc = SetActionsAndBattlersTurnOrder ;
2017-10-03 21:35:27 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER )
{
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-03 21:35:27 +02:00
{
2018-02-06 23:09:39 +01:00
if ( gChosenActionByBattler [ i ] = = B_ACTION_SWITCH )
2019-10-26 03:55:01 +02:00
SwitchPartyOrderInGameMulti ( i , * ( gBattleStruct - > monToSwitchIntoId + i ) ) ;
2017-10-03 21:35:27 +02:00
}
}
}
}
2017-10-04 19:25:14 +02:00
2018-07-07 21:14:41 +02:00
static bool8 AllAtActionConfirmed ( void )
2017-10-04 19:25:14 +02:00
{
2018-07-07 21:14:41 +02:00
s32 i , count ;
2017-10-04 19:25:14 +02:00
2018-07-07 21:14:41 +02:00
for ( count = 0 , i = 0 ; i < gBattlersCount ; i + + )
2017-10-04 19:25:14 +02:00
{
2018-07-07 21:14:41 +02:00
if ( gBattleCommunication [ i ] = = STATE_WAIT_ACTION_CONFIRMED )
count + + ;
2017-10-04 19:25:14 +02:00
}
2018-07-07 21:14:41 +02:00
if ( count + 1 = = gBattlersCount )
2017-10-04 19:25:14 +02:00
return TRUE ;
else
return FALSE ;
}
2017-10-06 19:09:37 +02:00
static void sub_803CDF8 ( void )
2017-10-04 19:25:14 +02:00
{
2019-01-05 16:00:57 +01:00
* ( gBattleStruct - > monToSwitchIntoId + gActiveBattler ) = gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] ;
RecordedBattle_SetBattlerAction ( gActiveBattler , gBattleResources - > bufferB [ gActiveBattler ] [ 1 ] ) ;
2017-10-04 19:25:14 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_LINK & & gBattleTypeFlags & BATTLE_TYPE_MULTI )
{
2018-02-06 02:46:59 +01:00
* ( gActiveBattler * 3 + ( u8 * ) ( gBattleStruct - > field_60 ) + 0 ) & = 0xF ;
2019-01-05 16:00:57 +01:00
* ( gActiveBattler * 3 + ( u8 * ) ( gBattleStruct - > field_60 ) + 0 ) | = ( gBattleResources - > bufferB [ gActiveBattler ] [ 2 ] & 0xF0 ) ;
* ( gActiveBattler * 3 + ( u8 * ) ( gBattleStruct - > field_60 ) + 1 ) = gBattleResources - > bufferB [ gActiveBattler ] [ 3 ] ;
2017-10-04 19:25:14 +02:00
2018-02-06 02:46:59 +01:00
* ( ( gActiveBattler ^ BIT_FLANK ) * 3 + ( u8 * ) ( gBattleStruct - > field_60 ) + 0 ) & = ( 0xF0 ) ;
2019-01-05 16:00:57 +01:00
* ( ( gActiveBattler ^ BIT_FLANK ) * 3 + ( u8 * ) ( gBattleStruct - > field_60 ) + 0 ) | = ( gBattleResources - > bufferB [ gActiveBattler ] [ 2 ] & 0xF0 ) > > 4 ;
* ( ( gActiveBattler ^ BIT_FLANK ) * 3 + ( u8 * ) ( gBattleStruct - > field_60 ) + 2 ) = gBattleResources - > bufferB [ gActiveBattler ] [ 3 ] ;
2017-10-04 19:25:14 +02:00
}
}
void SwapTurnOrder ( u8 id1 , u8 id2 )
{
2018-12-05 15:31:01 +01:00
u32 temp ;
2018-09-16 10:18:35 +02:00
2018-12-05 15:31:01 +01:00
SWAP ( gActionsByTurnOrder [ id1 ] , gActionsByTurnOrder [ id2 ] , temp ) ;
SWAP ( gBattlerByTurnOrder [ id1 ] , gBattlerByTurnOrder [ id2 ] , temp ) ;
2017-10-04 19:25:14 +02:00
}
2018-07-14 22:56:03 +02:00
u32 GetBattlerTotalSpeedStat ( u8 battlerId )
2017-10-04 19:25:14 +02:00
{
2018-07-14 22:56:03 +02:00
u32 speed = gBattleMons [ battlerId ] . speed ;
u32 ability = GetBattlerAbility ( battlerId ) ;
u32 holdEffect = GetBattlerHoldEffect ( battlerId , TRUE ) ;
2017-10-04 19:25:14 +02:00
2018-07-14 22:56:03 +02:00
// weather abilities
2017-10-04 19:25:14 +02:00
if ( WEATHER_HAS_EFFECT )
{
2018-07-14 22:56:03 +02:00
if ( ability = = ABILITY_SWIFT_SWIM & & gBattleWeather & WEATHER_RAIN_ANY )
speed * = 2 ;
else if ( ability = = ABILITY_CHLOROPHYLL & & gBattleWeather & WEATHER_SUN_ANY )
speed * = 2 ;
else if ( ability = = ABILITY_SAND_RUSH & & gBattleWeather & WEATHER_SANDSTORM_ANY )
speed * = 2 ;
else if ( ability = = ABILITY_SLUSH_RUSH & & gBattleWeather & WEATHER_HAIL_ANY )
speed * = 2 ;
2017-10-04 19:25:14 +02:00
}
2018-07-14 22:56:03 +02:00
// other abilities
if ( ability = = ABILITY_QUICK_FEET & & gBattleMons [ battlerId ] . status1 & STATUS1_ANY )
speed = ( speed * 150 ) / 100 ;
else if ( ability = = ABILITY_SURGE_SURFER & & gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN )
speed * = 2 ;
2020-04-18 12:52:15 +02:00
else if ( ability = = ABILITY_SLOW_START & & gDisableStructs [ battlerId ] . slowStartTimer ! = 0 )
speed / = 2 ;
2017-10-04 19:25:14 +02:00
2018-07-14 22:56:03 +02:00
// stat stages
speed * = gStatStageRatios [ gBattleMons [ battlerId ] . statStages [ STAT_SPEED ] ] [ 0 ] ;
speed / = gStatStageRatios [ gBattleMons [ battlerId ] . statStages [ STAT_SPEED ] ] [ 1 ] ;
2017-10-04 19:25:14 +02:00
2018-07-14 22:56:03 +02:00
// player's badge boost
2021-01-29 07:45:58 +01:00
if ( ! ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_FRONTIER ) )
2020-10-21 20:01:53 +02:00
& & ShouldGetStatBadgeBoost ( FLAG_BADGE03_GET , battlerId )
2018-07-14 22:56:03 +02:00
& & GetBattlerSide ( battlerId ) = = B_SIDE_PLAYER )
2017-10-04 19:25:14 +02:00
{
2018-07-14 22:56:03 +02:00
speed = ( speed * 110 ) / 100 ;
2017-10-04 19:25:14 +02:00
}
2018-07-14 22:56:03 +02:00
// item effects
2021-01-11 00:57:27 +01:00
if ( holdEffect = = HOLD_EFFECT_MACHO_BRACE | | holdEffect = = HOLD_EFFECT_POWER_ITEM )
2018-07-14 22:56:03 +02:00
speed / = 2 ;
else if ( holdEffect = = HOLD_EFFECT_IRON_BALL )
speed / = 2 ;
else if ( holdEffect = = HOLD_EFFECT_CHOICE_SCARF )
speed = ( speed * 150 ) / 100 ;
else if ( holdEffect = = HOLD_EFFECT_QUICK_POWDER & & gBattleMons [ battlerId ] . species = = SPECIES_DITTO & & ! ( gBattleMons [ battlerId ] . status2 & STATUS2_TRANSFORMED ) )
speed * = 2 ;
// various effects
if ( gSideStatuses [ GET_BATTLER_SIDE ( battlerId ) ] & SIDE_STATUS_TAILWIND )
speed * = 2 ;
2018-12-08 16:19:50 +01:00
if ( gBattleResources - > flags - > flags [ battlerId ] & RESOURCE_FLAG_UNBURDEN )
2018-07-14 22:56:03 +02:00
speed * = 2 ;
// paralysis drop
if ( gBattleMons [ battlerId ] . status1 & STATUS1_PARALYSIS & & ability ! = ABILITY_QUICK_FEET )
2020-02-08 09:51:55 +01:00
speed / = ( B_PARALYSIS_SPEED > = GEN_7 ? 2 : 4 ) ;
2018-07-14 22:56:03 +02:00
return speed ;
}
2017-10-04 19:25:14 +02:00
2019-02-16 14:54:17 +01:00
s8 GetChosenMovePriority ( u32 battlerId )
2018-07-28 00:25:02 +02:00
{
u16 move ;
2021-09-22 14:06:42 +02:00
gProtectStructs [ battlerId ] . pranksterElevated = 0 ;
2018-07-28 00:25:02 +02:00
if ( gProtectStructs [ battlerId ] . noValidMoves )
move = MOVE_STRUGGLE ;
else
move = gBattleMons [ battlerId ] . moves [ * ( gBattleStruct - > chosenMovePositions + battlerId ) ] ;
2019-02-16 14:54:17 +01:00
return GetMovePriority ( battlerId , move ) ;
}
s8 GetMovePriority ( u32 battlerId , u16 move )
{
s8 priority ;
2018-12-22 15:10:24 +01:00
priority = gBattleMoves [ move ] . priority ;
2018-07-28 00:25:02 +02:00
if ( GetBattlerAbility ( battlerId ) = = ABILITY_GALE_WINGS
& & gBattleMoves [ move ] . type = = TYPE_FLYING
2020-04-20 14:11:28 +02:00
& & ( B_GALE_WINGS < = GEN_6 | | BATTLER_MAX_HP ( battlerId ) ) )
2018-07-28 00:25:02 +02:00
{
2018-12-22 15:10:24 +01:00
priority + + ;
2018-07-28 00:25:02 +02:00
}
2020-10-16 01:15:44 +02:00
else if ( GetBattlerAbility ( battlerId ) = = ABILITY_PRANKSTER & & IS_MOVE_STATUS ( move ) )
2018-07-28 00:25:02 +02:00
{
2021-09-22 14:06:42 +02:00
gProtectStructs [ battlerId ] . pranksterElevated = 1 ;
2018-12-22 15:10:24 +01:00
priority + + ;
2018-07-28 00:25:02 +02:00
}
2018-11-30 21:42:30 +01:00
else if ( GetBattlerAbility ( battlerId ) = = ABILITY_TRIAGE )
{
switch ( gBattleMoves [ move ] . effect )
{
case EFFECT_RESTORE_HP :
case EFFECT_REST :
case EFFECT_MORNING_SUN :
case EFFECT_MOONLIGHT :
case EFFECT_SYNTHESIS :
case EFFECT_HEAL_PULSE :
case EFFECT_HEALING_WISH :
case EFFECT_SWALLOW :
case EFFECT_WISH :
case EFFECT_SOFTBOILED :
case EFFECT_ABSORB :
case EFFECT_ROOST :
2018-12-22 15:10:24 +01:00
priority + = 3 ;
2018-11-30 21:42:30 +01:00
break ;
}
}
2018-07-28 00:25:02 +02:00
2018-12-22 15:10:24 +01:00
return priority ;
2018-07-28 00:25:02 +02:00
}
2018-07-14 22:56:03 +02:00
u8 GetWhoStrikesFirst ( u8 battler1 , u8 battler2 , bool8 ignoreChosenMoves )
{
u8 strikesFirst = 0 ;
u32 speedBattler1 = 0 , speedBattler2 = 0 ;
2018-07-22 19:02:41 +02:00
u32 holdEffectBattler1 = 0 , holdEffectBattler2 = 0 ;
2018-07-28 00:25:02 +02:00
s8 priority1 = 0 , priority2 = 0 ;
2017-10-04 19:25:14 +02:00
2018-07-14 22:56:03 +02:00
speedBattler1 = GetBattlerTotalSpeedStat ( battler1 ) ;
2018-07-22 19:02:41 +02:00
holdEffectBattler1 = GetBattlerHoldEffect ( battler1 , TRUE ) ;
2021-01-06 17:37:31 +01:00
if ( ( holdEffectBattler1 = = HOLD_EFFECT_QUICK_CLAW & & gRandomTurnNumber < ( 0xFFFF * GetBattlerHoldEffectParam ( battler1 ) ) / 100 )
| | ( ! IsAbilityOnOpposingSide ( battler1 , ABILITY_UNNERVE )
& & holdEffectBattler1 = = HOLD_EFFECT_CUSTAP_BERRY
& & HasEnoughHpToEatBerry ( battler1 , 4 , gBattleMons [ battler1 ] . item ) ) )
2021-02-01 07:31:27 +01:00
gProtectStructs [ battler1 ] . custap = TRUE ;
2017-10-04 19:25:14 +02:00
2018-07-14 22:56:03 +02:00
speedBattler2 = GetBattlerTotalSpeedStat ( battler2 ) ;
2018-07-22 19:02:41 +02:00
holdEffectBattler2 = GetBattlerHoldEffect ( battler2 , TRUE ) ;
2021-01-06 17:37:31 +01:00
if ( ( holdEffectBattler2 = = HOLD_EFFECT_QUICK_CLAW & & gRandomTurnNumber < ( 0xFFFF * GetBattlerHoldEffectParam ( battler2 ) ) / 100 )
| | ( ! IsAbilityOnOpposingSide ( battler2 , ABILITY_UNNERVE )
& & holdEffectBattler2 = = HOLD_EFFECT_CUSTAP_BERRY
& & HasEnoughHpToEatBerry ( battler2 , 4 , gBattleMons [ battler2 ] . item ) ) )
2021-02-01 07:31:27 +01:00
gProtectStructs [ battler2 ] . custap = TRUE ;
2017-10-04 19:25:14 +02:00
2018-07-28 00:25:02 +02:00
if ( ! ignoreChosenMoves )
2017-10-04 19:25:14 +02:00
{
2018-02-08 11:17:41 +01:00
if ( gChosenActionByBattler [ battler1 ] = = B_ACTION_USE_MOVE )
2019-02-16 14:54:17 +01:00
priority1 = GetChosenMovePriority ( battler1 ) ;
2018-02-08 11:17:41 +01:00
if ( gChosenActionByBattler [ battler2 ] = = B_ACTION_USE_MOVE )
2019-02-16 14:54:17 +01:00
priority2 = GetChosenMovePriority ( battler2 ) ;
2017-10-04 19:25:14 +02:00
}
2018-07-28 00:25:02 +02:00
if ( priority1 = = priority2 )
2017-10-04 19:25:14 +02:00
{
2021-01-06 17:37:31 +01:00
// QUICK CLAW / CUSTAP - always first
2018-07-22 19:02:41 +02:00
// LAGGING TAIL - always last
// STALL - always last
2021-02-01 07:31:27 +01:00
if ( gProtectStructs [ battler1 ] . custap & & ! gProtectStructs [ battler2 ] . custap )
2018-07-22 19:02:41 +02:00
strikesFirst = 0 ;
2021-02-01 07:31:27 +01:00
else if ( gProtectStructs [ battler2 ] . custap & & ! gProtectStructs [ battler1 ] . custap )
2018-07-22 19:02:41 +02:00
strikesFirst = 1 ;
else if ( holdEffectBattler1 = = HOLD_EFFECT_LAGGING_TAIL & & holdEffectBattler2 ! = HOLD_EFFECT_LAGGING_TAIL )
strikesFirst = 1 ;
else if ( holdEffectBattler2 = = HOLD_EFFECT_LAGGING_TAIL & & holdEffectBattler1 ! = HOLD_EFFECT_LAGGING_TAIL )
strikesFirst = 0 ;
else if ( GetBattlerAbility ( battler1 ) = = ABILITY_STALL & & GetBattlerAbility ( battler2 ) ! = ABILITY_STALL )
strikesFirst = 1 ;
else if ( GetBattlerAbility ( battler2 ) = = ABILITY_STALL & & GetBattlerAbility ( battler1 ) ! = ABILITY_STALL )
strikesFirst = 0 ;
else
2017-10-04 19:25:14 +02:00
{
2018-02-08 11:17:41 +01:00
if ( speedBattler1 = = speedBattler2 & & Random ( ) & 1 )
2018-07-22 19:02:41 +02:00
{
2017-10-04 19:25:14 +02:00
strikesFirst = 2 ; // same speeds, same priorities
2018-07-22 19:02:41 +02:00
}
2018-02-08 11:17:41 +01:00
else if ( speedBattler1 < speedBattler2 )
2018-07-22 19:02:41 +02:00
{
// battler2 has more speed
if ( gFieldStatuses & STATUS_FIELD_TRICK_ROOM )
strikesFirst = 0 ;
else
strikesFirst = 1 ;
}
else
{
// battler1 has more speed
if ( gFieldStatuses & STATUS_FIELD_TRICK_ROOM )
strikesFirst = 1 ;
else
strikesFirst = 0 ;
}
2017-10-04 19:25:14 +02:00
}
}
2018-07-28 00:25:02 +02:00
else if ( priority1 < priority2 )
2018-07-22 19:02:41 +02:00
{
strikesFirst = 1 ; // battler2's move has greater priority
}
2017-10-04 19:25:14 +02:00
else
{
2018-07-22 19:02:41 +02:00
strikesFirst = 0 ; // battler1's move has greater priority
2017-10-04 19:25:14 +02:00
}
return strikesFirst ;
}
2018-02-08 11:17:41 +01:00
static void SetActionsAndBattlersTurnOrder ( void )
2017-10-04 19:25:14 +02:00
{
2018-06-28 21:06:32 +02:00
s32 turnOrderId = 0 ;
2017-10-04 19:25:14 +02:00
s32 i , j ;
if ( gBattleTypeFlags & BATTLE_TYPE_SAFARI )
{
2018-02-06 02:46:59 +01:00
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
2017-10-04 19:25:14 +02:00
{
2018-06-28 21:06:32 +02:00
gActionsByTurnOrder [ turnOrderId ] = gChosenActionByBattler [ gActiveBattler ] ;
gBattlerByTurnOrder [ turnOrderId ] = gActiveBattler ;
turnOrderId + + ;
2017-10-04 19:25:14 +02:00
}
}
else
{
if ( gBattleTypeFlags & BATTLE_TYPE_LINK )
{
2018-02-06 02:46:59 +01:00
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
2017-10-04 19:25:14 +02:00
{
2018-02-06 23:09:39 +01:00
if ( gChosenActionByBattler [ gActiveBattler ] = = B_ACTION_RUN )
2017-10-04 19:25:14 +02:00
{
2018-06-28 21:06:32 +02:00
turnOrderId = 5 ;
2017-10-04 19:25:14 +02:00
break ;
}
}
}
else
{
2018-02-06 23:09:39 +01:00
if ( gChosenActionByBattler [ 0 ] = = B_ACTION_RUN )
2017-10-04 19:25:14 +02:00
{
2018-02-06 02:46:59 +01:00
gActiveBattler = 0 ;
2018-06-28 21:06:32 +02:00
turnOrderId = 5 ;
2017-10-04 19:25:14 +02:00
}
2018-02-06 23:09:39 +01:00
if ( gChosenActionByBattler [ 2 ] = = B_ACTION_RUN )
2017-10-04 19:25:14 +02:00
{
2018-02-06 02:46:59 +01:00
gActiveBattler = 2 ;
2018-06-28 21:06:32 +02:00
turnOrderId = 5 ;
2017-10-04 19:25:14 +02:00
}
}
2018-06-28 21:06:32 +02:00
if ( turnOrderId = = 5 ) // One of battlers wants to run.
2017-10-04 19:25:14 +02:00
{
2018-02-06 23:09:39 +01:00
gActionsByTurnOrder [ 0 ] = gChosenActionByBattler [ gActiveBattler ] ;
2018-06-28 21:06:32 +02:00
gBattlerByTurnOrder [ 0 ] = gActiveBattler ;
turnOrderId = 1 ;
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount ; i + + )
2017-10-04 19:25:14 +02:00
{
2018-02-06 02:46:59 +01:00
if ( i ! = gActiveBattler )
2017-10-04 19:25:14 +02:00
{
2018-06-28 21:06:32 +02:00
gActionsByTurnOrder [ turnOrderId ] = gChosenActionByBattler [ i ] ;
gBattlerByTurnOrder [ turnOrderId ] = i ;
turnOrderId + + ;
2017-10-04 19:25:14 +02:00
}
}
2018-09-16 18:55:32 +02:00
gBattleMainFunc = CheckMegaEvolutionBeforeTurn ;
2018-09-20 17:33:27 +02:00
gBattleStruct - > mega . battlerId = 0 ;
2017-10-04 19:25:14 +02:00
return ;
}
else
{
2018-02-06 02:46:59 +01:00
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
2017-10-04 19:25:14 +02:00
{
2018-02-06 23:09:39 +01:00
if ( gChosenActionByBattler [ gActiveBattler ] = = B_ACTION_USE_ITEM | | gChosenActionByBattler [ gActiveBattler ] = = B_ACTION_SWITCH )
2017-10-04 19:25:14 +02:00
{
2018-06-28 21:06:32 +02:00
gActionsByTurnOrder [ turnOrderId ] = gChosenActionByBattler [ gActiveBattler ] ;
gBattlerByTurnOrder [ turnOrderId ] = gActiveBattler ;
turnOrderId + + ;
2017-10-04 19:25:14 +02:00
}
}
2018-02-06 02:46:59 +01:00
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
2017-10-04 19:25:14 +02:00
{
2018-02-06 23:09:39 +01:00
if ( gChosenActionByBattler [ gActiveBattler ] ! = B_ACTION_USE_ITEM & & gChosenActionByBattler [ gActiveBattler ] ! = B_ACTION_SWITCH )
2017-10-04 19:25:14 +02:00
{
2018-06-28 21:06:32 +02:00
gActionsByTurnOrder [ turnOrderId ] = gChosenActionByBattler [ gActiveBattler ] ;
gBattlerByTurnOrder [ turnOrderId ] = gActiveBattler ;
turnOrderId + + ;
2017-10-04 19:25:14 +02:00
}
}
2018-02-06 02:46:59 +01:00
for ( i = 0 ; i < gBattlersCount - 1 ; i + + )
2017-10-04 19:25:14 +02:00
{
2018-02-06 02:46:59 +01:00
for ( j = i + 1 ; j < gBattlersCount ; j + + )
2017-10-04 19:25:14 +02:00
{
2018-06-28 21:06:32 +02:00
u8 battler1 = gBattlerByTurnOrder [ i ] ;
u8 battler2 = gBattlerByTurnOrder [ j ] ;
2018-02-06 23:09:39 +01:00
if ( gActionsByTurnOrder [ i ] ! = B_ACTION_USE_ITEM
& & gActionsByTurnOrder [ j ] ! = B_ACTION_USE_ITEM
& & gActionsByTurnOrder [ i ] ! = B_ACTION_SWITCH
& & gActionsByTurnOrder [ j ] ! = B_ACTION_SWITCH )
2017-10-04 19:25:14 +02:00
{
2018-02-08 11:17:41 +01:00
if ( GetWhoStrikesFirst ( battler1 , battler2 , FALSE ) )
2017-10-04 19:25:14 +02:00
SwapTurnOrder ( i , j ) ;
}
}
}
}
}
2018-09-16 18:55:32 +02:00
gBattleMainFunc = CheckMegaEvolutionBeforeTurn ;
2018-09-20 17:33:27 +02:00
gBattleStruct - > mega . battlerId = 0 ;
2017-10-06 00:12:01 +02:00
}
2017-10-06 19:09:37 +02:00
static void TurnValuesCleanUp ( bool8 var0 )
2017-10-06 00:12:01 +02:00
{
s32 i ;
2018-02-06 02:46:59 +01:00
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
2017-10-06 00:12:01 +02:00
{
if ( var0 )
{
2018-02-06 02:46:59 +01:00
gProtectStructs [ gActiveBattler ] . protected = 0 ;
2018-10-06 15:50:35 +02:00
gProtectStructs [ gActiveBattler ] . spikyShielded = 0 ;
gProtectStructs [ gActiveBattler ] . kingsShielded = 0 ;
gProtectStructs [ gActiveBattler ] . banefulBunkered = 0 ;
2017-10-06 00:12:01 +02:00
}
else
{
2019-01-27 13:52:02 +01:00
memset ( & gProtectStructs [ gActiveBattler ] , 0 , sizeof ( struct ProtectStruct ) ) ;
2017-10-06 00:12:01 +02:00
2018-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . isFirstTurn )
gDisableStructs [ gActiveBattler ] . isFirstTurn - - ;
2017-10-06 00:12:01 +02:00
2018-10-14 18:10:54 +02:00
if ( gDisableStructs [ gActiveBattler ] . rechargeTimer )
2017-10-06 00:12:01 +02:00
{
2018-10-14 18:10:54 +02:00
gDisableStructs [ gActiveBattler ] . rechargeTimer - - ;
if ( gDisableStructs [ gActiveBattler ] . rechargeTimer = = 0 )
2018-02-06 02:46:59 +01:00
gBattleMons [ gActiveBattler ] . status2 & = ~ ( STATUS2_RECHARGE ) ;
2017-10-06 00:12:01 +02:00
}
}
2018-02-06 02:46:59 +01:00
if ( gDisableStructs [ gActiveBattler ] . substituteHP = = 0 )
2018-06-28 21:06:32 +02:00
gBattleMons [ gActiveBattler ] . status2 & = ~ ( STATUS2_SUBSTITUTE ) ;
2017-10-06 00:12:01 +02:00
}
2019-03-31 18:17:13 +02:00
gSideStatuses [ 0 ] & = ~ ( SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK ) ;
gSideStatuses [ 1 ] & = ~ ( SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK ) ;
2017-10-06 00:12:01 +02:00
gSideTimers [ 0 ] . followmeTimer = 0 ;
gSideTimers [ 1 ] . followmeTimer = 0 ;
}
2020-09-08 22:44:04 +02:00
void SpecialStatusesClear ( void )
2017-10-06 00:12:01 +02:00
{
2019-01-27 13:52:02 +01:00
memset ( & gSpecialStatuses , 0 , sizeof ( gSpecialStatuses ) ) ;
2017-10-06 00:12:01 +02:00
}
2018-09-16 18:55:32 +02:00
static void CheckMegaEvolutionBeforeTurn ( void )
{
if ( ! ( gHitMarker & HITMARKER_RUN ) )
{
2018-09-20 17:33:27 +02:00
while ( gBattleStruct - > mega . battlerId < gBattlersCount )
2018-09-16 18:55:32 +02:00
{
2018-09-20 17:33:27 +02:00
gActiveBattler = gBattlerAttacker = gBattleStruct - > mega . battlerId ;
gBattleStruct - > mega . battlerId + + ;
if ( gBattleStruct - > mega . toEvolve & gBitTable [ gActiveBattler ]
2018-09-16 18:55:32 +02:00
& & ! ( gProtectStructs [ gActiveBattler ] . noValidMoves ) )
{
2018-09-20 17:33:27 +02:00
gBattleStruct - > mega . toEvolve & = ~ ( gBitTable [ gActiveBattler ] ) ;
2018-09-16 18:55:32 +02:00
gLastUsedItem = gBattleMons [ gActiveBattler ] . item ;
2020-11-07 13:53:34 +01:00
if ( gBattleStruct - > mega . isWishMegaEvo = = TRUE )
BattleScriptExecute ( BattleScript_WishMegaEvolution ) ;
else
BattleScriptExecute ( BattleScript_MegaEvolution ) ;
2018-09-16 18:55:32 +02:00
return ;
}
}
}
gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts ;
gBattleStruct - > focusPunchBattlerId = 0 ;
}
2017-10-06 00:12:01 +02:00
static void CheckFocusPunch_ClearVarsBeforeTurnStarts ( void )
{
2018-07-29 11:32:40 +02:00
u32 i ;
2017-10-06 17:06:45 +02:00
if ( ! ( gHitMarker & HITMARKER_RUN ) )
2017-10-06 00:12:01 +02:00
{
2018-02-07 22:53:40 +01:00
while ( gBattleStruct - > focusPunchBattlerId < gBattlersCount )
2017-10-06 00:12:01 +02:00
{
2018-02-07 22:53:40 +01:00
gActiveBattler = gBattlerAttacker = gBattleStruct - > focusPunchBattlerId ;
gBattleStruct - > focusPunchBattlerId + + ;
2018-02-06 23:09:39 +01:00
if ( gChosenMoveByBattler [ gActiveBattler ] = = MOVE_FOCUS_PUNCH
2018-02-06 02:46:59 +01:00
& & ! ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_SLEEP )
2018-02-06 23:09:39 +01:00
& & ! ( gDisableStructs [ gBattlerAttacker ] . truantCounter )
2018-07-07 19:57:09 +02:00
& & ! ( gProtectStructs [ gActiveBattler ] . noValidMoves ) )
2017-10-06 00:12:01 +02:00
{
BattleScriptExecute ( BattleScript_FocusPunchSetUp ) ;
return ;
}
}
}
2021-01-06 17:37:31 +01:00
gBattleMainFunc = CheckQuickClaw_CustapBerryActivation ;
gBattleStruct - > quickClawBattlerId = 0 ;
}
static void CheckQuickClaw_CustapBerryActivation ( void )
{
u32 i ;
if ( ! ( gHitMarker & HITMARKER_RUN ) )
{
while ( gBattleStruct - > quickClawBattlerId < gBattlersCount )
{
gActiveBattler = gBattlerAttacker = gBattleStruct - > quickClawBattlerId ;
gBattleStruct - > quickClawBattlerId + + ;
2021-02-01 07:31:27 +01:00
if ( gChosenActionByBattler [ gActiveBattler ] = = B_ACTION_USE_MOVE
2021-03-03 17:14:00 +01:00
& & gChosenMoveByBattler [ gActiveBattler ] ! = MOVE_FOCUS_PUNCH // quick claw message doesn't need to activate here
& & gProtectStructs [ gActiveBattler ] . custap
& & ! ( gBattleMons [ gActiveBattler ] . status1 & STATUS1_SLEEP )
& & ! ( gDisableStructs [ gBattlerAttacker ] . truantCounter )
& & ! ( gProtectStructs [ gActiveBattler ] . noValidMoves ) )
2021-01-06 17:37:31 +01:00
{
2021-02-01 07:31:27 +01:00
gProtectStructs [ gActiveBattler ] . custap = FALSE ;
2021-01-06 17:37:31 +01:00
gLastUsedItem = gBattleMons [ gActiveBattler ] . item ;
if ( GetBattlerHoldEffect ( gActiveBattler , FALSE ) = = HOLD_EFFECT_CUSTAP_BERRY )
{
// don't record berry since its gone now
BattleScriptExecute ( BattleScript_CustapBerryActivation ) ;
}
else
{
RecordItemEffectBattle ( gActiveBattler , GetBattlerHoldEffect ( gActiveBattler , FALSE ) ) ;
BattleScriptExecute ( BattleScript_QuickClawActivation ) ;
}
return ;
}
}
}
2021-06-08 16:40:47 +02:00
2021-01-06 17:37:31 +01:00
// setup stuff before turns/actions
2018-08-11 12:16:00 +02:00
TryClearRageAndFuryCutter ( ) ;
2017-10-06 00:12:01 +02:00
gCurrentTurnActionNumber = 0 ;
2018-07-16 21:42:03 +02:00
gCurrentActionFuncId = gActionsByTurnOrder [ 0 ] ;
2017-10-06 00:12:01 +02:00
gBattleStruct - > dynamicMoveType = 0 ;
2018-07-29 11:32:40 +02:00
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
2020-04-29 11:53:03 +02:00
{
2018-07-29 11:32:40 +02:00
gBattleStruct - > ateBoost [ i ] = FALSE ;
2020-04-29 11:53:03 +02:00
gSpecialStatuses [ i ] . gemBoost = FALSE ;
}
2017-10-06 00:12:01 +02:00
gBattleMainFunc = RunTurnActionsFunctions ;
gBattleCommunication [ 3 ] = 0 ;
gBattleCommunication [ 4 ] = 0 ;
2017-12-02 23:31:58 +01:00
gBattleScripting . multihitMoveEffect = 0 ;
2017-10-06 00:12:01 +02:00
gBattleResources - > battleScriptsStack - > size = 0 ;
}
static void RunTurnActionsFunctions ( void )
{
if ( gBattleOutcome ! = 0 )
2019-09-03 21:08:25 +02:00
gCurrentActionFuncId = B_ACTION_FINISHED ;
2017-10-06 00:12:01 +02:00
2017-12-02 23:31:58 +01:00
* ( & gBattleStruct - > savedTurnActionNumber ) = gCurrentTurnActionNumber ;
2017-10-06 19:09:37 +02:00
sTurnActionsFuncsTable [ gCurrentActionFuncId ] ( ) ;
2017-10-06 00:12:01 +02:00
2018-02-06 02:46:59 +01:00
if ( gCurrentTurnActionNumber > = gBattlersCount ) // everyone did their actions, turn finished
2017-10-06 00:12:01 +02:00
{
gHitMarker & = ~ ( HITMARKER_x100000 ) ;
2017-10-06 19:09:37 +02:00
gBattleMainFunc = sEndTurnFuncsTable [ gBattleOutcome & 0x7F ] ;
2017-10-06 00:12:01 +02:00
}
else
{
2018-02-08 11:17:41 +01:00
if ( gBattleStruct - > savedTurnActionNumber ! = gCurrentTurnActionNumber ) // action turn has been done, clear hitmarker bits for another battlerId
2017-10-06 00:12:01 +02:00
{
gHitMarker & = ~ ( HITMARKER_NO_ATTACKSTRING ) ;
gHitMarker & = ~ ( HITMARKER_UNABLE_TO_USE_MOVE ) ;
}
}
}
2017-10-06 19:09:37 +02:00
static void HandleEndTurn_BattleWon ( void )
2017-10-06 00:12:01 +02:00
{
gCurrentActionFuncId = 0 ;
2021-01-13 21:17:32 +01:00
if ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK ) )
2017-10-06 00:12:01 +02:00
{
2017-11-11 01:12:18 +01:00
gSpecialVar_Result = gBattleOutcome ;
2017-10-06 00:12:01 +02:00
gBattleTextBuff1 [ 0 ] = gBattleOutcome ;
2018-02-06 23:09:39 +01:00
gBattlerAttacker = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
2017-10-06 00:12:01 +02:00
gBattlescriptCurrInstr = BattleScript_LinkBattleWonOrLost ;
2018-01-16 22:12:38 +01:00
gBattleOutcome & = ~ ( B_OUTCOME_LINK_BATTLE_RAN ) ;
2017-10-06 00:12:01 +02:00
}
else if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER
2018-09-20 22:00:00 +02:00
& & gBattleTypeFlags & ( BATTLE_TYPE_FRONTIER | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_EREADER_TRAINER ) )
2017-10-06 00:12:01 +02:00
{
2017-11-04 16:11:13 +01:00
BattleStopLowHpSound ( ) ;
2017-10-06 00:12:01 +02:00
gBattlescriptCurrInstr = BattleScript_FrontierTrainerBattleWon ;
2018-06-30 18:55:34 +02:00
if ( gTrainerBattleOpponent_A = = TRAINER_FRONTIER_BRAIN )
2020-08-21 00:02:00 +02:00
PlayBGM ( MUS_VICTORY_GYM_LEADER ) ;
2017-10-06 00:12:01 +02:00
else
2020-08-21 00:02:00 +02:00
PlayBGM ( MUS_VICTORY_TRAINER ) ;
2017-10-06 00:12:01 +02:00
}
else if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER & & ! ( gBattleTypeFlags & BATTLE_TYPE_LINK ) )
{
2017-11-04 16:11:13 +01:00
BattleStopLowHpSound ( ) ;
2017-10-06 00:12:01 +02:00
gBattlescriptCurrInstr = BattleScript_LocalTrainerBattleWon ;
switch ( gTrainers [ gTrainerBattleOpponent_A ] . trainerClass )
{
2017-12-17 21:19:08 +01:00
case TRAINER_CLASS_ELITE_FOUR :
case TRAINER_CLASS_CHAMPION :
2020-08-21 00:02:00 +02:00
PlayBGM ( MUS_VICTORY_LEAGUE ) ;
2017-10-06 00:12:01 +02:00
break ;
2017-12-17 21:19:08 +01:00
case TRAINER_CLASS_TEAM_AQUA :
case TRAINER_CLASS_TEAM_MAGMA :
case TRAINER_CLASS_AQUA_ADMIN :
case TRAINER_CLASS_AQUA_LEADER :
case TRAINER_CLASS_MAGMA_ADMIN :
case TRAINER_CLASS_MAGMA_LEADER :
2020-08-21 00:02:00 +02:00
PlayBGM ( MUS_VICTORY_AQUA_MAGMA ) ;
2017-10-06 00:12:01 +02:00
break ;
2017-12-17 21:19:08 +01:00
case TRAINER_CLASS_LEADER :
2020-08-21 00:02:00 +02:00
PlayBGM ( MUS_VICTORY_GYM_LEADER ) ;
2017-10-06 00:12:01 +02:00
break ;
default :
2020-08-21 00:02:00 +02:00
PlayBGM ( MUS_VICTORY_TRAINER ) ;
2017-10-06 00:12:01 +02:00
break ;
}
}
else
{
gBattlescriptCurrInstr = BattleScript_PayDayMoneyAndPickUpItems ;
}
gBattleMainFunc = HandleEndTurn_FinishBattle ;
}
2017-10-06 19:09:37 +02:00
static void HandleEndTurn_BattleLost ( void )
2017-10-06 00:12:01 +02:00
{
gCurrentActionFuncId = 0 ;
2021-01-13 21:17:32 +01:00
if ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK ) )
2017-10-06 00:12:01 +02:00
{
if ( gBattleTypeFlags & BATTLE_TYPE_FRONTIER )
{
2018-01-16 22:12:38 +01:00
if ( gBattleOutcome & B_OUTCOME_LINK_BATTLE_RAN )
2017-10-06 00:12:01 +02:00
{
2017-12-03 00:47:21 +01:00
gBattlescriptCurrInstr = BattleScript_PrintPlayerForfeitedLinkBattle ;
2018-01-16 22:12:38 +01:00
gBattleOutcome & = ~ ( B_OUTCOME_LINK_BATTLE_RAN ) ;
2019-12-14 09:58:20 +01:00
gSaveBlock2Ptr - > frontier . disableRecordBattle = TRUE ;
2017-10-06 00:12:01 +02:00
}
else
{
2021-01-22 08:48:22 +01:00
gBattlescriptCurrInstr = BattleScript_FrontierLinkBattleLost ;
2018-01-16 22:12:38 +01:00
gBattleOutcome & = ~ ( B_OUTCOME_LINK_BATTLE_RAN ) ;
2017-10-06 00:12:01 +02:00
}
}
else
{
gBattleTextBuff1 [ 0 ] = gBattleOutcome ;
2018-02-06 23:09:39 +01:00
gBattlerAttacker = GetBattlerAtPosition ( B_POSITION_PLAYER_LEFT ) ;
2017-10-06 00:12:01 +02:00
gBattlescriptCurrInstr = BattleScript_LinkBattleWonOrLost ;
2018-01-16 22:12:38 +01:00
gBattleOutcome & = ~ ( B_OUTCOME_LINK_BATTLE_RAN ) ;
2017-10-06 00:12:01 +02:00
}
}
else
{
gBattlescriptCurrInstr = BattleScript_LocalBattleLost ;
}
gBattleMainFunc = HandleEndTurn_FinishBattle ;
}
2017-10-06 19:09:37 +02:00
static void HandleEndTurn_RanFromBattle ( void )
2017-10-06 00:12:01 +02:00
{
gCurrentActionFuncId = 0 ;
if ( gBattleTypeFlags & BATTLE_TYPE_FRONTIER & & gBattleTypeFlags & BATTLE_TYPE_TRAINER )
{
2017-12-03 00:47:21 +01:00
gBattlescriptCurrInstr = BattleScript_PrintPlayerForfeited ;
2018-01-16 22:12:38 +01:00
gBattleOutcome = B_OUTCOME_FORFEITED ;
2019-12-14 09:58:20 +01:00
gSaveBlock2Ptr - > frontier . disableRecordBattle = TRUE ;
2017-10-06 00:12:01 +02:00
}
2018-09-20 22:00:00 +02:00
else if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER_HILL )
2017-10-06 00:12:01 +02:00
{
2017-12-03 00:47:21 +01:00
gBattlescriptCurrInstr = BattleScript_PrintPlayerForfeited ;
2018-01-16 22:12:38 +01:00
gBattleOutcome = B_OUTCOME_FORFEITED ;
2017-10-06 00:12:01 +02:00
}
else
{
2018-02-06 23:09:39 +01:00
switch ( gProtectStructs [ gBattlerAttacker ] . fleeFlag )
2017-10-06 00:12:01 +02:00
{
default :
gBattlescriptCurrInstr = BattleScript_GotAwaySafely ;
break ;
case 1 :
gBattlescriptCurrInstr = BattleScript_SmokeBallEscape ;
break ;
case 2 :
gBattlescriptCurrInstr = BattleScript_RanAwayUsingMonAbility ;
break ;
}
}
gBattleMainFunc = HandleEndTurn_FinishBattle ;
}
2017-10-06 19:09:37 +02:00
static void HandleEndTurn_MonFled ( void )
2017-10-06 00:12:01 +02:00
{
gCurrentActionFuncId = 0 ;
2018-02-06 23:09:39 +01:00
PREPARE_MON_NICK_BUFFER ( gBattleTextBuff1 , gBattlerAttacker , gBattlerPartyIndexes [ gBattlerAttacker ] ) ;
2017-10-06 00:12:01 +02:00
gBattlescriptCurrInstr = BattleScript_WildMonFled ;
gBattleMainFunc = HandleEndTurn_FinishBattle ;
}
2017-10-06 19:09:37 +02:00
static void HandleEndTurn_FinishBattle ( void )
2017-10-06 00:12:01 +02:00
{
2018-09-16 21:08:49 +02:00
u32 i ;
2019-09-03 21:08:25 +02:00
if ( gCurrentActionFuncId = = B_ACTION_TRY_FINISH | | gCurrentActionFuncId = = B_ACTION_FINISHED )
2017-10-06 00:12:01 +02:00
{
if ( ! ( gBattleTypeFlags & ( BATTLE_TYPE_LINK
2021-01-13 21:17:32 +01:00
| BATTLE_TYPE_RECORDED_LINK
2017-10-06 00:12:01 +02:00
| BATTLE_TYPE_FIRST_BATTLE
| BATTLE_TYPE_SAFARI
| BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_WALLY_TUTORIAL
| BATTLE_TYPE_FRONTIER ) ) )
{
2018-02-06 02:46:59 +01:00
for ( gActiveBattler = 0 ; gActiveBattler < gBattlersCount ; gActiveBattler + + )
2017-10-06 00:12:01 +02:00
{
2018-02-06 02:46:59 +01:00
if ( GetBattlerSide ( gActiveBattler ) = = B_SIDE_PLAYER )
2017-10-06 00:12:01 +02:00
{
if ( gBattleResults . playerMon1Species = = SPECIES_NONE )
{
2018-02-06 20:48:02 +01:00
gBattleResults . playerMon1Species = GetMonData ( & gPlayerParty [ gBattlerPartyIndexes [ gActiveBattler ] ] , MON_DATA_SPECIES , NULL ) ;
GetMonData ( & gPlayerParty [ gBattlerPartyIndexes [ gActiveBattler ] ] , MON_DATA_NICKNAME , gBattleResults . playerMon1Name ) ;
2017-10-06 00:12:01 +02:00
}
else
{
2018-02-06 20:48:02 +01:00
gBattleResults . playerMon2Species = GetMonData ( & gPlayerParty [ gBattlerPartyIndexes [ gActiveBattler ] ] , MON_DATA_SPECIES , NULL ) ;
GetMonData ( & gPlayerParty [ gBattlerPartyIndexes [ gActiveBattler ] ] , MON_DATA_NICKNAME , gBattleResults . playerMon2Name ) ;
2017-10-06 00:12:01 +02:00
}
}
}
2021-04-25 23:22:45 +02:00
TryPutPokemonTodayOnAir ( ) ;
2017-10-06 00:12:01 +02:00
}
if ( ! ( gBattleTypeFlags & ( BATTLE_TYPE_LINK
2021-01-13 21:17:32 +01:00
| BATTLE_TYPE_RECORDED_LINK
2017-10-06 00:12:01 +02:00
| BATTLE_TYPE_TRAINER
| BATTLE_TYPE_FIRST_BATTLE
| BATTLE_TYPE_SAFARI
| BATTLE_TYPE_FRONTIER
| BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_WALLY_TUTORIAL ) )
2018-06-28 21:06:32 +02:00
& & gBattleResults . shinyWildMon )
2017-10-06 00:12:01 +02:00
{
2021-04-25 23:22:45 +02:00
TryPutBreakingNewsOnAir ( ) ;
2017-10-06 00:12:01 +02:00
}
sub_8186444 ( ) ;
BeginFastPaletteFade ( 3 ) ;
FadeOutMapMusic ( 5 ) ;
2020-12-03 14:42:12 +01:00
# if B_TRAINERS_KNOCK_OFF_ITEMS
2020-11-13 19:00:44 +01:00
if ( gBattleTypeFlags & BATTLE_TYPE_TRAINER )
TryRestoreStolenItems ( ) ;
# endif
2018-09-16 21:08:49 +02:00
for ( i = 0 ; i < PARTY_SIZE ; i + + )
2019-12-31 19:11:53 +01:00
{
2018-09-16 21:08:49 +02:00
UndoMegaEvolution ( i ) ;
2021-07-16 07:56:53 +02:00
UndoFormChange ( i , B_SIDE_PLAYER , FALSE ) ;
2021-08-07 10:56:10 +02:00
DoBurmyFormChange ( i ) ;
2019-12-31 19:11:53 +01:00
}
2017-10-06 00:12:01 +02:00
gBattleMainFunc = FreeResetData_ReturnToOvOrDoEvolutions ;
2017-10-29 16:15:23 +01:00
gCB2_AfterEvolution = BattleMainCB2 ;
2017-10-06 00:12:01 +02:00
}
else
{
2018-02-06 20:48:02 +01:00
if ( gBattleControllerExecFlags = = 0 )
2017-10-06 00:12:01 +02:00
gBattleScriptingCommandsTable [ gBattlescriptCurrInstr [ 0 ] ] ( ) ;
}
}
static void FreeResetData_ReturnToOvOrDoEvolutions ( void )
{
if ( ! gPaletteFade . active )
{
ResetSpriteData ( ) ;
2019-07-08 13:26:21 +02:00
if ( gLeveledUpInBattle & & ( gBattleOutcome = = B_OUTCOME_WON | | gBattleOutcome = = B_OUTCOME_CAUGHT ) )
2017-10-06 00:12:01 +02:00
{
2019-07-08 13:26:21 +02:00
gBattleMainFunc = TryEvolvePokemon ;
2017-10-06 00:12:01 +02:00
}
else
{
2019-07-08 13:26:21 +02:00
gBattleMainFunc = ReturnFromBattleToOverworld ;
return ;
2017-10-06 00:12:01 +02:00
}
}
FreeAllWindowBuffers ( ) ;
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_LINK ) )
{
FreeMonSpritesGfx ( ) ;
FreeBattleResources ( ) ;
FreeBattleSpritesData ( ) ;
}
}
static void TryEvolvePokemon ( void )
{
s32 i ;
while ( gLeveledUpInBattle ! = 0 )
{
2018-02-08 11:17:41 +01:00
for ( i = 0 ; i < PARTY_SIZE ; i + + )
2017-10-06 00:12:01 +02:00
{
if ( gLeveledUpInBattle & gBitTable [ i ] )
{
u16 species ;
u8 levelUpBits = gLeveledUpInBattle ;
levelUpBits & = ~ ( gBitTable [ i ] ) ;
gLeveledUpInBattle = levelUpBits ;
2021-02-12 20:54:11 +01:00
species = GetEvolutionTargetSpecies ( & gPlayerParty [ i ] , EVO_MODE_NORMAL , levelUpBits ) ;
2017-10-06 00:12:01 +02:00
if ( species ! = SPECIES_NONE )
{
FreeAllWindowBuffers ( ) ;
gBattleMainFunc = WaitForEvoSceneToFinish ;
EvolutionScene ( & gPlayerParty [ i ] , species , TRUE , i ) ;
return ;
}
}
}
}
gBattleMainFunc = ReturnFromBattleToOverworld ;
}
static void WaitForEvoSceneToFinish ( void )
{
if ( gMain . callback2 = = BattleMainCB2 )
gBattleMainFunc = TryEvolvePokemon ;
}
static void ReturnFromBattleToOverworld ( void )
{
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_LINK ) )
{
RandomlyGivePartyPokerus ( gPlayerParty ) ;
PartySpreadPokerus ( gPlayerParty ) ;
}
if ( gBattleTypeFlags & BATTLE_TYPE_LINK & & gReceivedRemoteLinkPlayers ! = 0 )
return ;
2017-11-11 01:12:18 +01:00
gSpecialVar_Result = gBattleOutcome ;
2017-10-06 00:12:01 +02:00
gMain . inBattle = 0 ;
gMain . callback1 = gPreBattleCallback1 ;
if ( gBattleTypeFlags & BATTLE_TYPE_ROAMER )
{
UpdateRoamerHPStatus ( & gEnemyParty [ 0 ] ) ;
2021-05-12 21:23:14 +02:00
# ifndef BUGFIX
2018-02-08 00:35:13 +01:00
if ( ( gBattleOutcome & B_OUTCOME_WON ) | | gBattleOutcome = = B_OUTCOME_CAUGHT )
2021-05-12 21:23:14 +02:00
# else
if ( ( gBattleOutcome = = B_OUTCOME_WON ) | | gBattleOutcome = = B_OUTCOME_CAUGHT ) // Bug: When Roar is used by roamer, gBattleOutcome is B_OUTCOME_PLAYER_TELEPORTED (5).
# endif // & with B_OUTCOME_WON (1) will return TRUE and deactivates the roamer.
2017-10-06 00:12:01 +02:00
SetRoamerInactive ( ) ;
}
2020-08-21 00:02:00 +02:00
m4aSongNumStop ( SE_LOW_HEALTH ) ;
2017-10-06 00:12:01 +02:00
SetMainCallback2 ( gMain . savedCallback ) ;
}
void RunBattleScriptCommands_PopCallbacksStack ( void )
{
2019-09-03 21:08:25 +02:00
if ( gCurrentActionFuncId = = B_ACTION_TRY_FINISH | | gCurrentActionFuncId = = B_ACTION_FINISHED )
2017-10-06 00:12:01 +02:00
{
2018-02-06 23:09:39 +01:00
if ( gBattleResources - > battleCallbackStack - > size ! = 0 )
gBattleResources - > battleCallbackStack - > size - - ;
gBattleMainFunc = gBattleResources - > battleCallbackStack - > function [ gBattleResources - > battleCallbackStack - > size ] ;
2017-10-06 00:12:01 +02:00
}
else
{
2018-02-06 20:48:02 +01:00
if ( gBattleControllerExecFlags = = 0 )
2017-10-06 00:12:01 +02:00
gBattleScriptingCommandsTable [ gBattlescriptCurrInstr [ 0 ] ] ( ) ;
}
}
void RunBattleScriptCommands ( void )
{
2018-02-06 20:48:02 +01:00
if ( gBattleControllerExecFlags = = 0 )
2017-10-06 00:12:01 +02:00
gBattleScriptingCommandsTable [ gBattlescriptCurrInstr [ 0 ] ] ( ) ;
}
2018-07-29 11:32:40 +02:00
void SetTypeBeforeUsingMove ( u16 move , u8 battlerAtk )
{
u32 moveType , ateType , attackerAbility ;
if ( move = = MOVE_STRUGGLE )
return ;
2020-04-29 11:53:03 +02:00
gBattleStruct - > dynamicMoveType = 0 ;
gBattleStruct - > ateBoost [ battlerAtk ] = 0 ;
gSpecialStatuses [ battlerAtk ] . gemBoost = 0 ;
2018-07-29 11:32:40 +02:00
if ( gBattleMoves [ move ] . effect = = EFFECT_WEATHER_BALL )
{
if ( WEATHER_HAS_EFFECT )
{
if ( gBattleWeather & WEATHER_RAIN_ANY )
2020-04-29 11:53:03 +02:00
gBattleStruct - > dynamicMoveType = TYPE_WATER | 0x80 ;
2018-07-29 11:32:40 +02:00
else if ( gBattleWeather & WEATHER_SANDSTORM_ANY )
2020-04-29 11:53:03 +02:00
gBattleStruct - > dynamicMoveType = TYPE_ROCK | 0x80 ;
2018-07-29 11:32:40 +02:00
else if ( gBattleWeather & WEATHER_SUN_ANY )
2020-04-29 11:53:03 +02:00
gBattleStruct - > dynamicMoveType = TYPE_FIRE | 0x80 ;
2018-07-29 11:32:40 +02:00
else if ( gBattleWeather & WEATHER_HAIL_ANY )
2020-04-29 11:53:03 +02:00
gBattleStruct - > dynamicMoveType = TYPE_ICE | 0x80 ;
2018-07-29 11:32:40 +02:00
else
2020-04-29 11:53:03 +02:00
gBattleStruct - > dynamicMoveType = TYPE_NORMAL | 0x80 ;
2018-07-29 11:32:40 +02:00
}
}
else if ( gBattleMoves [ move ] . effect = = EFFECT_HIDDEN_POWER )
{
u8 typeBits = ( ( gBattleMons [ battlerAtk ] . hpIV & 1 ) < < 0 )
| ( ( gBattleMons [ battlerAtk ] . attackIV & 1 ) < < 1 )
| ( ( gBattleMons [ battlerAtk ] . defenseIV & 1 ) < < 2 )
| ( ( gBattleMons [ battlerAtk ] . speedIV & 1 ) < < 3 )
| ( ( gBattleMons [ battlerAtk ] . spAttackIV & 1 ) < < 4 )
| ( ( gBattleMons [ battlerAtk ] . spDefenseIV & 1 ) < < 5 ) ;
gBattleStruct - > dynamicMoveType = ( 15 * typeBits ) / 63 + 1 ;
if ( gBattleStruct - > dynamicMoveType > = TYPE_MYSTERY )
gBattleStruct - > dynamicMoveType + + ;
gBattleStruct - > dynamicMoveType | = 0xC0 ;
}
2020-11-08 05:53:26 +01:00
else if ( gBattleMoves [ move ] . effect = = EFFECT_CHANGE_TYPE_ON_ITEM )
2019-05-07 15:26:58 +02:00
{
2020-11-08 05:53:26 +01:00
if ( GetBattlerHoldEffect ( battlerAtk , TRUE ) = = gBattleMoves [ move ] . argument )
2019-05-07 15:26:58 +02:00
gBattleStruct - > dynamicMoveType = ItemId_GetSecondaryId ( gBattleMons [ battlerAtk ] . item ) | 0x80 ;
}
2018-11-03 14:35:45 +01:00
else if ( gBattleMoves [ move ] . effect = = EFFECT_REVELATION_DANCE )
{
if ( gBattleMons [ battlerAtk ] . type1 ! = TYPE_MYSTERY )
gBattleStruct - > dynamicMoveType = gBattleMons [ battlerAtk ] . type1 | 0x80 ;
else if ( gBattleMons [ battlerAtk ] . type2 ! = TYPE_MYSTERY )
gBattleStruct - > dynamicMoveType = gBattleMons [ battlerAtk ] . type2 | 0x80 ;
2018-11-17 12:10:24 +01:00
else if ( gBattleMons [ battlerAtk ] . type3 ! = TYPE_MYSTERY )
gBattleStruct - > dynamicMoveType = gBattleMons [ battlerAtk ] . type3 | 0x80 ;
2018-11-03 14:35:45 +01:00
}
2019-05-20 12:03:00 +02:00
else if ( gBattleMoves [ move ] . effect = = EFFECT_NATURAL_GIFT )
{
if ( ItemId_GetPocket ( gBattleMons [ battlerAtk ] . item ) = = POCKET_BERRIES )
gBattleStruct - > dynamicMoveType = gNaturalGiftTable [ ITEM_TO_BERRY ( gBattleMons [ battlerAtk ] . item ) ] . type ;
}
2018-07-29 11:32:40 +02:00
attackerAbility = GetBattlerAbility ( battlerAtk ) ;
GET_MOVE_TYPE ( move , moveType ) ;
if ( ( gFieldStatuses & STATUS_FIELD_ION_DELUGE & & moveType = = TYPE_NORMAL )
| | gStatuses3 [ battlerAtk ] & STATUS3_ELECTRIFIED )
{
gBattleStruct - > dynamicMoveType = 0x80 | TYPE_ELECTRIC ;
}
else if ( gBattleMoves [ move ] . type = = TYPE_NORMAL
& & gBattleMoves [ move ] . effect ! = EFFECT_HIDDEN_POWER
& & gBattleMoves [ move ] . effect ! = EFFECT_WEATHER_BALL
2020-11-08 05:53:26 +01:00
& & gBattleMoves [ move ] . effect ! = EFFECT_CHANGE_TYPE_ON_ITEM
2019-05-20 12:03:00 +02:00
& & gBattleMoves [ move ] . effect ! = EFFECT_NATURAL_GIFT
2018-07-29 11:32:40 +02:00
& & ( ( attackerAbility = = ABILITY_PIXILATE & & ( ateType = TYPE_FAIRY ) )
| | ( attackerAbility = = ABILITY_REFRIGERATE & & ( ateType = TYPE_ICE ) )
| | ( attackerAbility = = ABILITY_AERILATE & & ( ateType = TYPE_FLYING ) )
| | ( ( attackerAbility = = ABILITY_GALVANIZE ) & & ( ateType = TYPE_ELECTRIC ) )
)
)
{
gBattleStruct - > dynamicMoveType = 0x80 | ateType ;
gBattleStruct - > ateBoost [ battlerAtk ] = 1 ;
}
else if ( gBattleMoves [ move ] . type ! = TYPE_NORMAL
& & gBattleMoves [ move ] . effect ! = EFFECT_HIDDEN_POWER
& & gBattleMoves [ move ] . effect ! = EFFECT_WEATHER_BALL
& & attackerAbility = = ABILITY_NORMALIZE )
{
gBattleStruct - > dynamicMoveType = 0x80 | TYPE_NORMAL ;
gBattleStruct - > ateBoost [ battlerAtk ] = 1 ;
}
2020-04-15 09:37:12 +02:00
else if ( gBattleMoves [ move ] . flags & FLAG_SOUND
& & attackerAbility = = ABILITY_LIQUID_VOICE )
{
gBattleStruct - > dynamicMoveType = 0x80 | TYPE_WATER ;
}
2019-05-07 15:26:58 +02:00
// Check if a gem should activate.
GET_MOVE_TYPE ( move , moveType ) ;
if ( GetBattlerHoldEffect ( battlerAtk , TRUE ) = = HOLD_EFFECT_GEMS
& & moveType = = ItemId_GetSecondaryId ( gBattleMons [ battlerAtk ] . item ) )
{
gSpecialStatuses [ battlerAtk ] . gemParam = GetBattlerHoldEffectParam ( battlerAtk ) ;
gSpecialStatuses [ battlerAtk ] . gemBoost = 1 ;
}
2018-07-29 11:32:40 +02:00
}
2020-11-19 18:35:37 +01:00
// special to set a field's totem boost(s)
// inputs:
2021-01-29 07:45:58 +01:00
// var8000: battlerId
2020-11-19 18:35:37 +01:00
// var8001 - var8007: stat changes
void SetTotemBoost ( void )
{
u8 battlerId = gSpecialVar_0x8000 ;
u8 i ;
2021-01-29 07:45:58 +01:00
2020-11-19 18:35:37 +01:00
for ( i = 0 ; i < ( NUM_BATTLE_STATS - 1 ) ; i + + )
{
if ( * ( & gSpecialVar_0x8001 + i ) )
{
gTotemBoosts [ battlerId ] . stats | = ( 1 < < i ) ;
gTotemBoosts [ battlerId ] . statChanges [ i ] = * ( & gSpecialVar_0x8001 + i ) ;
2020-12-06 05:00:51 +01:00
gTotemBoosts [ battlerId ] . stats | = 0x80 ; // used as a flag for the "totem flared to life" script
2020-11-19 18:35:37 +01:00
}
}
}