diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index 3e482c839104..573b60d457c2 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -95,6 +95,19 @@ Debug_BoxFilledMessage:: Debug_BoxFilledMessage_Text: .string "Storage boxes filled!$" +Debug_FlagsAndVarNotSetBattleConfigMessage:: + lockall + message Debug_FlagsAndVarNotSetBattleConfigMessage_Text + waitmessage + waitbuttonpress + releaseall + end + +Debug_FlagsAndVarNotSetBattleConfigMessage_Text: + .string "Feature unavailable! Please define a\n" + .string "usable flag and a usable var in:\l" + .string "'include/config/battle.h'!$" + Debug_EventScript_Script_1:: end diff --git a/data/specials.inc b/data/specials.inc index 91ba7cac13fe..34e86cad29f9 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -539,3 +539,4 @@ gSpecials:: def_special GetNumberSprayStrength def_special GetSprayId def_special GetLastUsedSprayType + def_special TrySkyBattle diff --git a/include/battle.h b/include/battle.h index 5d603399b70b..9d83e0d9f881 100644 --- a/include/battle.h +++ b/include/battle.h @@ -731,6 +731,7 @@ struct BattleStruct u32 aiDelayFrames; // Number of frames it took to choose an action. bool8 transformZeroToHero[PARTY_SIZE][NUM_BATTLE_SIDES]; u8 pledgeMove:1; + bool8 isSkyBattle:1; }; // The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider, diff --git a/include/battle_script_commands.h b/include/battle_script_commands.h index e78b57e4d1dd..a4e8a166edc8 100644 --- a/include/battle_script_commands.h +++ b/include/battle_script_commands.h @@ -27,6 +27,7 @@ s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordA s32 GetCritHitChance(s32 critChanceIndex); u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); u8 GetBattlerTurnOrderNum(u8 battlerId); +bool32 NoAliveMonsForPlayer(void); bool32 NoAliveMonsForEitherParty(void); void SetMoveEffect(bool32 primary, u32 certain); bool32 CanBattlerSwitch(u32 battlerId); @@ -52,6 +53,7 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem); u8 GetCatchingBattler(void); u32 GetHighestStatId(u32 battlerId); bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType); +bool32 IsMoveNotAllowedInSkyBattles(u32 move); bool32 DoSwitchInAbilitiesItems(u32 battlerId); u8 GetFirstFaintedPartyIndex(u8 battlerId); bool32 IsMoveAffectedByParentalBond(u32 move, u32 battler); diff --git a/include/battle_util.h b/include/battle_util.h index 20c458fc9490..f58a5a15436f 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -249,5 +249,7 @@ bool32 AreBattlersOfOppositeGender(u32 battler1, u32 battler2); bool32 AreBattlersOfSameGender(u32 battler1, u32 battler2); u32 CalcSecondaryEffectChance(u32 battler, u8 secondaryEffectChance, u16 moveEffect); u8 GetBattlerType(u32 battler, u8 typeIndex); +bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon); +bool8 IsMonBannedFromSkyBattles(u16 species); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/config/battle.h b/include/config/battle.h index cc82096e15a5..622054ab2854 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -170,6 +170,12 @@ #define VAR_TERRAIN 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active #define B_VAR_WILD_AI_FLAGS 0 // If not 0, you can use this var to add to default wild AI flags. NOT usable with flags above (1 << 15) +// Sky Battles +#define B_FLAG_SKY_BATTLE 0 // If this flag has a value, the player will be able to engage in scripted Sky Battles. +#define B_VAR_SKY_BATTLE 0 // If this var has a value, the game will remember the positions of Pokémon used in Sky Battles. + +#define B_SKY_BATTLE_STRICT_ELIGIBILITY FALSE //If TRUE, Sky Battles will use the eligibility from Pokémon XY. If FALSE, all Flying-types or Pokémon with Levitate are allowed. + // Flag and Var settings #define B_RESET_FLAGS_VARS_AFTER_WHITEOUT TRUE // If TRUE, Overworld_ResetBattleFlagsAndVars will reset battle-related Flags and Vars when the player whites out. diff --git a/include/debug.h b/include/debug.h index d89c7994b860..e25392091b16 100644 --- a/include/debug.h +++ b/include/debug.h @@ -2,6 +2,7 @@ #define GUARD_DEBUG_H void Debug_ShowMainMenu(void); +extern const u8 Debug_FlagsAndVarNotSetBattleConfigMessage[]; extern EWRAM_DATA bool8 gIsDebugBattle; extern EWRAM_DATA u32 gDebugAIFlags; diff --git a/include/field_specials.h b/include/field_specials.h index faf71e9c0877..d36f2686c286 100644 --- a/include/field_specials.h +++ b/include/field_specials.h @@ -31,5 +31,6 @@ bool8 UsedPokemonCenterWarp(void); void ResetFanClub(void); bool8 ShouldShowBoxWasFullMessage(void); void SetPCBoxToSendMon(u8 boxId); +void PreparePartyForSkyBattle(void); #endif // GUARD_FIELD_SPECIALS_H diff --git a/include/pokemon.h b/include/pokemon.h index ff78373fa55e..5efa6a97a31d 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -393,6 +393,7 @@ struct BattleMove u32 instructBanned:1; u32 encoreBanned:1; u32 parentalBondBanned:1; + u32 skyBattleBanned:1; }; #define SPINDA_SPOT_WIDTH 16 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 780f630ed82e..9fd43a3d1e5e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1256,6 +1256,11 @@ bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType) return FALSE; } +bool32 IsMoveNotAllowedInSkyBattles(u32 move) +{ + return ((gBattleStruct->isSkyBattle) && (gBattleMoves[gCurrentMove].skyBattleBanned)); +} + static void Cmd_attackcanceler(void) { CMD_ARGS(); @@ -1363,9 +1368,10 @@ static void Cmd_attackcanceler(void) } gHitMarker |= HITMARKER_OBEYS; - // Check if no available target present on the field. - if (NoTargetPresent(gBattlerAttacker, gCurrentMove) + // Check if no available target present on the field or if Sky Battles ban the move + if ((NoTargetPresent(gBattlerAttacker, gCurrentMove) && (!gBattleMoves[gCurrentMove].twoTurnMove || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))) + || (IsMoveNotAllowedInSkyBattles(gCurrentMove))) { if (gBattleMoves[gCurrentMove].effect == EFFECT_FLING) // Edge case for removing a mon's item when there is no target available after using Fling. gBattlescriptCurrInstr = BattleScript_FlingFailConsumeItem; @@ -3595,7 +3601,11 @@ void SetMoveEffect(bool32 primary, u32 certain) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SPIKESSCATTERED; BattleScriptPush(gBattlescriptCurrInstr + 1); - gBattlescriptCurrInstr = BattleScript_SpikesActivates; + + if (gBattleStruct->isSkyBattle) + gBattlescriptCurrInstr++; + else + gBattlescriptCurrInstr = BattleScript_SpikesActivates; } break; case MOVE_EFFECT_TRIPLE_ARROWS: @@ -4324,7 +4334,7 @@ static bool32 NoAliveMonsForPlayerAndPartner(void) return (HP_count == 0); } -static bool32 NoAliveMonsForPlayer(void) +bool32 NoAliveMonsForPlayer(void) { u32 i; u32 HP_count = 0; diff --git a/src/battle_setup.c b/src/battle_setup.c index e8ffcd8908a5..72a41aca9ce2 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1,5 +1,6 @@ #include "global.h" #include "battle.h" +#include "load_save.h" #include "battle_setup.h" #include "battle_transition.h" #include "main.h" @@ -81,6 +82,8 @@ static void TryUpdateGymLeaderRematchFromTrainer(void); static void CB2_GiveStarter(void); static void CB2_StartFirstBattle(void); static void CB2_EndFirstBattle(void); +static void SaveChangesToPlayerParty(void); +static void HandleBattleVariantEndParty(void); static void CB2_EndTrainerBattle(void); static bool32 IsPlayerDefeated(u32 battleOutcome); static u16 GetRematchTrainerId(u16 trainerId); @@ -1380,15 +1383,40 @@ void BattleSetup_StartTrainerBattle_Debug(void) ScriptContext_Stop(); } +static void SaveChangesToPlayerParty(void) +{ + u8 i = 0, j = 0; + u8 participatedPokemon = VarGet(B_VAR_SKY_BATTLE); + for (i = 0; i < PARTY_SIZE; i++) + { + if ((participatedPokemon >> i & 1) == 1) + { + gSaveBlock1Ptr->playerParty[i] = gPlayerParty[j]; + j++; + } + } +} + +static void HandleBattleVariantEndParty(void) +{ + if (B_FLAG_SKY_BATTLE == 0 || !FlagGet(B_FLAG_SKY_BATTLE)) + return; + SaveChangesToPlayerParty(); + LoadPlayerParty(); + FlagClear(B_FLAG_SKY_BATTLE); +} + static void CB2_EndTrainerBattle(void) { + HandleBattleVariantEndParty(); + if (gTrainerBattleOpponent_A == TRAINER_SECRET_BASE) { SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); } else if (IsPlayerDefeated(gBattleOutcome) == TRUE) { - if (InBattlePyramid() || InTrainerHillChallenge()) + if (InBattlePyramid() || InTrainerHillChallenge() || (!NoAliveMonsForPlayer())) SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); else SetMainCallback2(CB2_WhiteOut); diff --git a/src/battle_util.c b/src/battle_util.c index 833277b9ef19..475b38c78b4b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4095,7 +4095,7 @@ bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility) static bool32 TryChangeBattleTerrain(u32 battler, u32 statusFlag, u8 *timer) { - if (!(gFieldStatuses & statusFlag)) + if ((!(gFieldStatuses & statusFlag) && (!gBattleStruct->isSkyBattle))) { gFieldStatuses &= ~(STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN); gFieldStatuses |= statusFlag; @@ -5756,6 +5756,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_TOXIC_DEBRIS: if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) + && (!gBattleStruct->isSkyBattle) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IS_MOVE_PHYSICAL(gCurrentMove) && TARGET_TURN_DAMAGED @@ -11267,6 +11268,56 @@ bool32 IsGen6ExpShareEnabled(void) #endif } +bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon) +{ + u16 species = GetMonData(mon, MON_DATA_SPECIES); + u16 monAbilityNum = GetMonData(mon, MON_DATA_ABILITY_NUM, NULL); + + bool8 hasLevitateAbility = gSpeciesInfo[species].abilities[monAbilityNum] == ABILITY_LEVITATE; + bool8 isFlyingType = gSpeciesInfo[species].types[0] == TYPE_FLYING || gSpeciesInfo[species].types[1] == TYPE_FLYING; + bool8 monIsValidAndNotEgg = GetMonData(mon, MON_DATA_SANITY_HAS_SPECIES) && !GetMonData(mon, MON_DATA_IS_EGG); + + if (monIsValidAndNotEgg) + { + if ((hasLevitateAbility || isFlyingType) && !IsMonBannedFromSkyBattles(species)) + return TRUE; + } + return FALSE; +} + +bool8 IsMonBannedFromSkyBattles(u16 species) +{ + switch (species) + { +#if B_SKY_BATTLE_STRICT_ELIGIBILITY == TRUE + case SPECIES_SPEAROW: + case SPECIES_FARFETCHD: + case SPECIES_DODUO: + case SPECIES_DODRIO: + case SPECIES_HOOTHOOT: + case SPECIES_NATU: + case SPECIES_MURKROW: + case SPECIES_DELIBIRD: + case SPECIES_TAILLOW: + case SPECIES_STARLY: + case SPECIES_CHATOT: + case SPECIES_SHAYMIN: + case SPECIES_PIDOVE: + case SPECIES_ARCHEN: + case SPECIES_DUCKLETT: + case SPECIES_RUFFLET: + case SPECIES_VULLABY: + case SPECIES_FLETCHLING: + case SPECIES_HAWLUCHA: + case SPECIES_ROWLET: + case SPECIES_PIKIPEK: +#endif + case SPECIES_EGG: + return TRUE; + default: + return FALSE; + } +} u8 GetBattlerType(u32 battler, u8 typeIndex) { diff --git a/src/battle_util2.c b/src/battle_util2.c index 8dda3004c057..2c333978d240 100644 --- a/src/battle_util2.c +++ b/src/battle_util2.c @@ -19,6 +19,10 @@ void AllocateBattleResources(void) gBattleStruct = AllocZeroed(sizeof(*gBattleStruct)); +#if B_FLAG_SKY_BATTLE + gBattleStruct->isSkyBattle = FlagGet(B_FLAG_SKY_BATTLE); +#endif + gBattleResources = AllocZeroed(sizeof(*gBattleResources)); gBattleResources->secretBase = AllocZeroed(sizeof(*gBattleResources->secretBase)); gBattleResources->flags = AllocZeroed(sizeof(*gBattleResources->flags)); diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index cc33db08db61..a5ef4960a710 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -376,6 +376,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_VINE_WHIP] = @@ -416,6 +417,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .makesContact = TRUE, .sheerForceBoost = TRUE, .minimizeDoubleDamage = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_DOUBLE_KICK] = @@ -604,6 +606,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .makesContact = TRUE, .sheerForceBoost = TRUE, .minimizeDoubleDamage = B_UPDATED_MOVE_FLAGS >= GEN_6, + .skyBattleBanned = TRUE, }, [MOVE_WRAP] = @@ -1008,6 +1011,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .damagesUnderwater = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_ICE_BEAM] = @@ -1216,6 +1220,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_STRENGTH] = @@ -1574,6 +1579,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_NONE, .ignoresKingsRock = B_UPDATED_MOVE_FLAGS < GEN_3, .damagesUnderground = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_FISSURE] = @@ -1589,6 +1595,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .damagesUnderground = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_DIG] = @@ -1612,6 +1619,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_TOXIC] = @@ -2913,6 +2921,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_STRUGGLE] = @@ -3416,6 +3425,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .mirrorMoveBanned = TRUE, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .forcePressure = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_ZAP_CANNON] = @@ -3986,6 +3996,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .damagesUnderground = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_DYNAMIC_PUNCH] = @@ -4952,6 +4963,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .snatchAffected = TRUE, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_SUPERPOWER] = @@ -5219,6 +5231,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .sleepTalkBanned = TRUE, .instructBanned = TRUE, .assistBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_ARM_THRUST] = @@ -5368,6 +5381,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_SPDEF_UP_1, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_ICE_BALL] = @@ -5891,6 +5905,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .sheerForceBoost = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_BULLET_SEED] = @@ -6028,6 +6043,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, + .skyBattleBanned = TRUE, }, [MOVE_BULK_UP] = @@ -6182,6 +6198,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_SPDEF_UP_1, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_CALM_MIND] = @@ -6360,6 +6377,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_SPATK_UP_1, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_MIRACLE_EYE] = @@ -6934,6 +6952,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .mirrorMoveBanned = TRUE, .magicCoatAffected = B_UPDATED_MOVE_FLAGS >= GEN_5, .forcePressure = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_HEART_SWAP] = @@ -7343,6 +7362,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .sheerForceBoost = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_SWITCHEROO] = @@ -7878,6 +7898,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_CHATTER] = @@ -8428,6 +8449,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .damagesAirborne = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_STORM_THROW] = @@ -8510,6 +8532,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, .minimizeDoubleDamage = B_UPDATED_MOVE_FLAGS >= GEN_7, + .skyBattleBanned = TRUE, }, [MOVE_SYNCHRONOISE] = @@ -9077,6 +9100,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, + .skyBattleBanned = TRUE, }, [MOVE_FIRE_PLEDGE] = @@ -9095,6 +9119,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, + .skyBattleBanned = TRUE, }, [MOVE_GRASS_PLEDGE] = @@ -9113,6 +9138,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .priority = 0, .split = SPLIT_SPECIAL, .zMoveEffect = Z_EFFECT_NONE, + .skyBattleBanned = TRUE, }, [MOVE_VOLT_SWITCH] = @@ -9161,6 +9187,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .sheerForceBoost = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_FROST_BREATH] = @@ -9779,6 +9806,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .makesContact = TRUE, .minimizeDoubleDamage = TRUE, .gravityBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_MAT_BLOCK] = @@ -9800,6 +9828,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .metronomeBanned = TRUE, .copycatBanned = TRUE, .assistBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_BELCH] = @@ -9838,6 +9867,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_ATK_UP_1, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_STICKY_WEB] = @@ -9855,6 +9885,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .magicCoatAffected = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_FELL_STINGER] = @@ -10129,6 +10160,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_DEF_UP_1, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_MISTY_TERRAIN] = @@ -10145,6 +10177,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_SPDEF_UP_1, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_ELECTRIFY] = @@ -10485,6 +10518,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .twoTurnMove = TRUE, .sleepTalkBanned = TRUE, .instructBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_MAGNETIC_FLUX] = @@ -10535,6 +10569,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_SPD_UP_1, .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_DAZZLING_GLEAM] = @@ -10704,6 +10739,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .damagesAirborne = TRUE, .ignoreTypeIfFlyingAndUngrounded = TRUE, .metronomeBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_THOUSAND_WAVES] = @@ -10719,6 +10755,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .metronomeBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_LANDS_WRATH] = @@ -10733,6 +10770,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .priority = 0, .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, + .skyBattleBanned = TRUE, }, [MOVE_LIGHT_OF_RUIN] = @@ -11470,6 +11508,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_SHADOW_BONE] = @@ -12232,6 +12271,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, .metronomeBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_DECORATE] = @@ -12281,6 +12321,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, .metronomeBanned = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_PYRO_BALL] = @@ -12599,6 +12640,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, .argument = ARG_TRY_REMOVE_TERRAIN_FAIL, // Remove a field terrain if there is one and hit, otherwise fail. + .skyBattleBanned = TRUE, }, [MOVE_SCALE_SHOT] = @@ -12678,6 +12720,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_RISING_VOLTAGE] = @@ -13199,6 +13242,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_CHLOROBLAST] = @@ -13644,6 +13688,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .split = SPLIT_PHYSICAL, .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, + .skyBattleBanned = TRUE, }, [MOVE_POPULATION_BOMB] = @@ -13678,6 +13723,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .zMoveEffect = Z_EFFECT_NONE, .makesContact = TRUE, .argument = ARG_TRY_REMOVE_TERRAIN_HIT, // Remove the active field terrain if there is one. + .skyBattleBanned = TRUE, }, [MOVE_GLAIVE_RUSH] = @@ -14479,6 +14525,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .priority = 0, .split = SPLIT_PHYSICAL, .zMoveEffect = 0, + .skyBattleBanned = TRUE, }, [MOVE_CONTINENTAL_CRUSH] = { diff --git a/src/debug.c b/src/debug.c index 9db4862120e6..23c21f76f03b 100644 --- a/src/debug.c +++ b/src/debug.c @@ -402,6 +402,7 @@ static void DebugAction_Sound_MUS_SelectId(u8 taskId); extern const u8 Debug_FlagsNotSetOverworldConfigMessage[]; extern const u8 Debug_FlagsNotSetBattleConfigMessage[]; +extern const u8 Debug_FlagsAndVarNotSetBattleConfigMessage[]; extern const u8 Debug_EventScript_Script_1[]; extern const u8 Debug_EventScript_Script_2[]; extern const u8 Debug_EventScript_Script_3[]; diff --git a/src/field_specials.c b/src/field_specials.c index 13b8ae9daf48..c4968a6cc827 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -1,4 +1,5 @@ #include "global.h" +#include "debug.h" #include "malloc.h" #include "battle.h" #include "battle_tower.h" @@ -20,6 +21,7 @@ #include "international_string_util.h" #include "item_icon.h" #include "link.h" +#include "load_save.h" #include "list_menu.h" #include "main.h" #include "mystery_gift.h" @@ -4207,3 +4209,47 @@ u8 Script_TryGainNewFanFromCounter(void) { return TryGainNewFanFromCounter(gSpecialVar_0x8004); } + +void TrySkyBattle(void) +{ + int i; + + if (B_VAR_SKY_BATTLE == 0 || B_FLAG_SKY_BATTLE == 0) + { + LockPlayerFieldControls(); + ScriptContext_SetupScript(Debug_FlagsAndVarNotSetBattleConfigMessage); + return; + } + for (i = 0; i < CalculatePlayerPartyCount(); i++) + { + struct Pokemon* pokemon = &gPlayerParty[i]; + if (CanMonParticipateInSkyBattle(pokemon) && GetMonData(pokemon, MON_DATA_HP, NULL) > 0) + { + PreparePartyForSkyBattle(); + gSpecialVar_Result = TRUE; + return; + } + } + gSpecialVar_Result = FALSE; +} + +void PreparePartyForSkyBattle(void) +{ + int i, participatingPokemonSlot = 0; + u8 partyCount = CalculatePlayerPartyCount(); + + FlagSet(B_FLAG_SKY_BATTLE); + SavePlayerParty(); + + for (i = 0; i < partyCount; i++) + { + struct Pokemon* pokemon = &gPlayerParty[i]; + + if (CanMonParticipateInSkyBattle(pokemon)) + participatingPokemonSlot += 1 << i; + else + ZeroMonData(pokemon); + } + VarSet(B_VAR_SKY_BATTLE,participatingPokemonSlot); + CompactPartySlots(); +} diff --git a/src/load_save.c b/src/load_save.c index 44e08b5e9c46..4f706180c4e6 100644 --- a/src/load_save.c +++ b/src/load_save.c @@ -13,6 +13,7 @@ #include "gba/flash_internal.h" #include "decoration_inventory.h" #include "agb_flash.h" +#include "event_data.h" static void ApplyNewEncryptionKeyToAllEncryptedData(u32 encryptionKey);