diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index 64b7e1dd01..b29291a7f9 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -142,5 +142,29 @@ DebugScript_HatchAnEgg_Text_EmptyParty:: DebugScript_HatchAnEgg_Text_NotAnEgg:: .string "That's not a Pokémon Egg.$" + +DebugScript_ZeroDaycareMons:: + msgbox DebugText_DaycareNoPokemon, MSGBOX_DEFAULT + releaseall + end + +DebugScript_OneDaycareMons:: + msgbox DebugText_DaycareOnePokemon, MSGBOX_DEFAULT + releaseall + end + +DebugScript_DaycareMonsNotCompatible:: + msgbox DebugText_DaycarePokemonNotCompatible, MSGBOX_DEFAULT + releaseall + end + +DebugText_DaycareNoPokemon: + .string "You have no Pokémon at Daycare.$" + +DebugText_DaycareOnePokemon: + .string "You have only one Pokémon at Daycare.$" + +DebugText_DaycarePokemonNotCompatible: + .string "Your Pokémon at Daycare can't\nhave babies together!$" .endif diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index b2dbd6d843..9239f03578 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -15,6 +15,7 @@ bool32 BattlerHasAi(u32 battlerId); bool32 IsAiBattlerAware(u32 battlerId); void ClearBattlerMoveHistory(u32 battlerId); void RecordLastUsedMoveBy(u32 battlerId, u32 move); +void RecordAllMoves(u32 battler); void RecordKnownMove(u32 battlerId, u32 move); void RecordAbilityBattle(u32 battlerId, u32 abilityId); void ClearBattlerAbilityHistory(u32 battlerId); @@ -24,7 +25,6 @@ void SaveBattlerData(u32 battlerId); void SetBattlerData(u32 battlerId); void RestoreBattlerData(u32 battlerId); u16 GetAIChosenMove(u32 battlerId); - u32 GetTotalBaseStat(u32 species); bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler); bool32 AtMaxHp(u32 battler); diff --git a/include/config/item.h b/include/config/item.h index 8aaadbe842..0cd89b612d 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -12,6 +12,7 @@ #define I_GRISEOUS_ORB_FORM_CHANGE GEN_LATEST // In Gen9+, the Griseous Orb no longer changes Giratina's form when held. #define I_GEM_BOOST_POWER GEN_LATEST // In Gen5+, the Gem boost power was reduced from 50% to 30%. #define I_USE_EVO_HELD_ITEMS_FROM_BAG FALSE // If TRUE, items such as Razor Claw or Electirizer will be usable from the bag to evolve a Pokémon just like in LA. +#define I_TYPE_BOOST_POWER GEN_LATEST // In Gen4+, all regular type boosting held items had their power increased from 10% to 20%. eg. Charcoal // TM config #define I_REUSABLE_TMS FALSE // In Gen5-8, TMs are reusable. Setting this to TRUE will make all vanilla TMs reusable, though they can also be cherry-picked by setting their importance to 1. diff --git a/include/daycare.h b/include/daycare.h index 62a7918ff3..066499fd41 100644 --- a/include/daycare.h +++ b/include/daycare.h @@ -14,6 +14,7 @@ u8 *GetMonNickname2(struct Pokemon *mon, u8 *dest); u8 *GetBoxMonNickname(struct BoxPokemon *mon, u8 *dest); u8 CountPokemonInDaycare(struct DayCare *daycare); void InitDaycareMailRecordMixing(struct DayCare *daycare, struct RecordMixingDaycareMail *mixMail); +s8 Daycare_FindEmptySpot(struct DayCare *daycare); void StoreSelectedPokemonInDaycare(void); u16 TakePokemonFromDaycare(void); void GetDaycareCost(void); @@ -26,6 +27,7 @@ bool8 ShouldEggHatch(void); u16 GetSelectedMonNicknameAndSpecies(void); void GetDaycareMonNicknames(void); u8 GetDaycareState(void); +u8 GetDaycareCompatibilityScore(struct DayCare *daycare); void SetDaycareCompatibilityString(void); bool8 NameHasGenderSymbol(const u8 *name, u8 genderRatio); void ShowDaycareLevelMenu(void); diff --git a/include/test/battle.h b/include/test/battle.h index 7bffd10a6c..e1b00efbdd 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -837,7 +837,8 @@ void SendOut(u32 sourceLine, struct BattlePokemon *, u32 partyIndex); #define ABILITY_POPUP(battler, ...) QueueAbility(__LINE__, battler, (struct AbilityEventContext) { __VA_ARGS__ }) #define ANIMATION(type, id, ...) QueueAnimation(__LINE__, type, id, (struct AnimationEventContext) { __VA_ARGS__ }) #define HP_BAR(battler, ...) QueueHP(__LINE__, battler, (struct HPEventContext) { APPEND_TRUE(__VA_ARGS__) }) -#define MESSAGE(pattern) QueueMessage(__LINE__, (const u8 []) _(pattern)) +// Static const is needed to make the modern compiler put the pattern variable in the .rodata section, instead of putting it on stack(which can break the game). +#define MESSAGE(pattern) do {static const u8 msg[] = _(pattern); QueueMessage(__LINE__, msg);} while (0) #define STATUS_ICON(battler, status) QueueStatus(__LINE__, battler, (struct StatusEventContext) { status }) enum QueueGroupType diff --git a/ld_script_test.txt b/ld_script_test.txt index f7a74e0863..f4abad98ab 100644 --- a/ld_script_test.txt +++ b/ld_script_test.txt @@ -84,9 +84,9 @@ SECTIONS { .rodata : ALIGN(4) { - src/*.o(.rodata); - gflib/*.o(.rodata); - data/*.o(.rodata); + src/*.o(.rodata*); + gflib/*.o(.rodata*); + data/*.o(.rodata*); } =0 song_data : @@ -111,7 +111,7 @@ SECTIONS { test/*.o(.tests); __stop_tests = .; test/*.o(.text); - test/*.o(.rodata); + test/*.o(.rodata*); } =0 /* DWARF debug sections. diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 70eeb8a019..e75d253f3f 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -497,6 +497,11 @@ void RecordKnownMove(u32 battlerId, u32 move) } } +void RecordAllMoves(u32 battler) +{ + memcpy(AI_PARTY->mons[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].moves, gBattleMons[battler].moves, MAX_MON_MOVES * sizeof(u16)); +} + void RecordAbilityBattle(u32 battlerId, u32 abilityId) { BATTLE_HISTORY->abilities[battlerId] = abilityId; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index d59c4c55d8..a77c7aa7f2 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11438,8 +11438,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr { bool32 certain = FALSE; bool32 notProtectAffected = FALSE; - u32 index, battler; - u16 battlerAbility; + u32 index, battler, battlerAbility, battlerHoldEffect; bool32 affectsUser = (flags & MOVE_EFFECT_AFFECTS_USER); bool32 mirrorArmored = (flags & STAT_CHANGE_MIRROR_ARMOR); @@ -11449,6 +11448,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr battler = gBattlerTarget; battlerAbility = GetBattlerAbility(battler); + battlerHoldEffect = GetBattlerHoldEffect(battler, TRUE); gSpecialStatuses[battler].changedStatsBattlerId = gBattlerAttacker; @@ -11507,13 +11507,13 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr gBattlescriptCurrInstr = BattleScript_ButItFailed; return STAT_CHANGE_DIDNT_WORK; } - else if ((GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_CLEAR_AMULET + else if ((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET || battlerAbility == ABILITY_CLEAR_BODY || battlerAbility == ABILITY_FULL_METAL_BODY || battlerAbility == ABILITY_WHITE_SMOKE) && (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE) { - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_CLEAR_AMULET) + if (battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET) { RecordItemEffectBattle(battler, HOLD_EFFECT_CLEAR_AMULET); } @@ -11528,7 +11528,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr { BattleScriptPush(BS_ptr); gBattleScripting.battler = battler; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_CLEAR_AMULET) + if (battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET) { gBattlescriptCurrInstr = BattleScript_ItemNoStatLoss; } @@ -11598,7 +11598,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr RecordAbilityBattle(battler, ABILITY_SHIELD_DUST); return STAT_CHANGE_DIDNT_WORK; } - else if (flags == 0 && GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_COVERT_CLOAK) + else if (flags == 0 && battlerHoldEffect == HOLD_EFFECT_COVERT_CLOAK) { RecordItemEffectBattle(battler, HOLD_EFFECT_COVERT_CLOAK); return STAT_CHANGE_DIDNT_WORK; @@ -12446,7 +12446,7 @@ static void Cmd_transformdataexecution(void) { s32 i; u8 *battleMonAttacker, *battleMonTarget; - + gBattleMons[gBattlerAttacker].status2 |= STATUS2_TRANSFORMED; gDisableStructs[gBattlerAttacker].disabledMove = MOVE_NONE; gDisableStructs[gBattlerAttacker].disableTimer = 0; @@ -12471,7 +12471,11 @@ static void Cmd_transformdataexecution(void) else gBattleMons[gBattlerAttacker].pp[i] = 5; } - + + // update AI knowledge + RecordAllMoves(gBattlerAttacker); + RecordAbilityBattle(gBattlerAttacker, gBattleMons[gBattlerAttacker].ability); + BtlController_EmitResetActionMoveSelection(gBattlerAttacker, BUFFER_A, RESET_MOVE_SELECTION); MarkBattlerForControllerExec(gBattlerAttacker); gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TRANSFORMED; diff --git a/src/battle_util.c b/src/battle_util.c index 8177667912..f1fb11cd85 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5707,8 +5707,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IS_MOVE_PHYSICAL(gCurrentMove) && TARGET_TURN_DAMAGED - && (gSideTimers[gBattlerAttacker].toxicSpikesAmount != 2) - && IsBattlerAlive(gBattlerTarget)) + && (gSideTimers[gBattlerAttacker].toxicSpikesAmount != 2)) { SWAP(gBattlerAttacker, gBattlerTarget, i); BattleScriptPushCursor(); @@ -8289,7 +8288,9 @@ bool32 IsBattlerProtected(u32 battler, u32 move) // Only called directly when calculating damage type effectiveness static bool32 IsBattlerGrounded2(u32 battler, bool32 considerInverse) { - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_IRON_BALL) + u32 holdEffect = GetBattlerHoldEffect(battler, TRUE); + + if (holdEffect == HOLD_EFFECT_IRON_BALL) return TRUE; if (gFieldStatuses & STATUS_FIELD_GRAVITY) return TRUE; @@ -8303,7 +8304,7 @@ static bool32 IsBattlerGrounded2(u32 battler, bool32 considerInverse) return FALSE; if (gStatuses3[battler] & STATUS3_MAGNET_RISE) return FALSE; - if (GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_AIR_BALLOON) + if (holdEffect == HOLD_EFFECT_AIR_BALLOON) return FALSE; if (GetBattlerAbility(battler) == ABILITY_LEVITATE) return FALSE; @@ -8314,7 +8315,7 @@ static bool32 IsBattlerGrounded2(u32 battler, bool32 considerInverse) bool32 IsBattlerGrounded(u32 battler) { - IsBattlerGrounded2(battler, FALSE); + return IsBattlerGrounded2(battler, FALSE); } bool32 IsBattlerAlive(u32 battler) diff --git a/src/data/items.h b/src/data/items.h index 842dae6bd2..6990e7cded 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -14,6 +14,12 @@ #define GEM_BOOST_PARAM 50 #endif +#if I_TYPE_BOOST_POWER >= GEN_4 // For non Pokémon-specific type-boosting held items. + #define TYPE_BOOST_PARAM 20 +#else + #define TYPE_BOOST_PARAM 10 +#endif + const struct Item gItems[] = { [ITEM_NONE] = @@ -5169,7 +5175,7 @@ const struct Item gItems[] = .name = _("Silk Scarf"), .price = 1000, .holdEffect = HOLD_EFFECT_NORMAL_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sSilkScarfDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5182,7 +5188,7 @@ const struct Item gItems[] = .name = _("Charcoal"), .price = 1000, .holdEffect = HOLD_EFFECT_FIRE_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sCharcoalDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5195,7 +5201,7 @@ const struct Item gItems[] = .name = _("Mystic Water"), .price = 1000, .holdEffect = HOLD_EFFECT_WATER_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sMysticWaterDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5208,7 +5214,7 @@ const struct Item gItems[] = .name = _("Magnet"), .price = 1000, .holdEffect = HOLD_EFFECT_ELECTRIC_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sMagnetDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5221,7 +5227,7 @@ const struct Item gItems[] = .name = _("Miracle Seed"), .price = 1000, .holdEffect = HOLD_EFFECT_GRASS_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sMiracleSeedDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5234,7 +5240,7 @@ const struct Item gItems[] = .name = _("Never-MeltIce"), .price = 1000, .holdEffect = HOLD_EFFECT_ICE_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sNeverMeltIceDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5247,7 +5253,7 @@ const struct Item gItems[] = .name = _("Black Belt"), .price = 1000, .holdEffect = HOLD_EFFECT_FIGHTING_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sBlackBeltDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5260,7 +5266,7 @@ const struct Item gItems[] = .name = _("Poison Barb"), .price = 1000, .holdEffect = HOLD_EFFECT_POISON_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sPoisonBarbDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5273,7 +5279,7 @@ const struct Item gItems[] = .name = _("Soft Sand"), .price = 1000, .holdEffect = HOLD_EFFECT_GROUND_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sSoftSandDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5286,7 +5292,7 @@ const struct Item gItems[] = .name = _("Sharp Beak"), .price = 1000, .holdEffect = HOLD_EFFECT_FLYING_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sSharpBeakDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5299,7 +5305,7 @@ const struct Item gItems[] = .name = _("Twisted Spoon"), .price = 1000, .holdEffect = HOLD_EFFECT_PSYCHIC_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sTwistedSpoonDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5312,7 +5318,7 @@ const struct Item gItems[] = .name = _("Silver Powder"), .price = 1000, .holdEffect = HOLD_EFFECT_BUG_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sSilverPowderDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5325,7 +5331,7 @@ const struct Item gItems[] = .name = _("Hard Stone"), .price = 1000, .holdEffect = HOLD_EFFECT_ROCK_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sHardStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5338,7 +5344,7 @@ const struct Item gItems[] = .name = _("Spell Tag"), .price = 1000, .holdEffect = HOLD_EFFECT_GHOST_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sSpellTagDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5351,7 +5357,7 @@ const struct Item gItems[] = .name = _("Dragon Fang"), .price = 1000, .holdEffect = HOLD_EFFECT_DRAGON_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sDragonFangDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5364,7 +5370,7 @@ const struct Item gItems[] = .name = _("Black Glasses"), .price = 1000, .holdEffect = HOLD_EFFECT_DARK_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sBlackGlassesDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -5377,7 +5383,7 @@ const struct Item gItems[] = .name = _("Metal Coat"), .price = 2000, .holdEffect = HOLD_EFFECT_STEEL_POWER, - .holdEffectParam = 20, + .holdEffectParam = TYPE_BOOST_PARAM, .description = sMetalCoatDesc, .pocket = POCKET_ITEMS, .type = EVO_HELD_ITEM_TYPE, diff --git a/src/daycare.c b/src/daycare.c index 0d2ab7130b..6078135fd7 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -32,7 +32,6 @@ extern const struct Evolution gEvolutionTable[][EVOS_PER_MON]; static void ClearDaycareMonMail(struct DaycareMail *mail); static void SetInitialEggData(struct Pokemon *mon, u16 species, struct DayCare *daycare); -static u8 GetDaycareCompatibilityScore(struct DayCare *daycare); static void DaycarePrintMonInfo(u8 windowId, u32 daycareSlotId, u8 y); static u8 ModifyBreedingScoreForOvalCharm(u8 score); static u8 GetEggMoves(struct Pokemon *pokemon, u16 *eggMoves); @@ -151,7 +150,7 @@ void InitDaycareMailRecordMixing(struct DayCare *daycare, struct RecordMixingDay mixMail->numDaycareMons = numDaycareMons; } -static s8 Daycare_FindEmptySpot(struct DayCare *daycare) +s8 Daycare_FindEmptySpot(struct DayCare *daycare) { u8 i; @@ -193,7 +192,7 @@ static void TransferEggMoves(void) { if (k == i || !GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[k].mon, MON_DATA_SANITY_HAS_SPECIES)) continue; - + // Check if you can inherit from them if (GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[k].mon, MON_DATA_SPECIES) != GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[i].mon, MON_DATA_SPECIES) #if P_EGG_MOVE_TRANSFER >= GEN_9 @@ -493,7 +492,7 @@ static s32 GetParentToInheritNature(struct DayCare *daycare) if (ItemId_GetHoldEffect(GetBoxMonData(&daycare->mons[i].mon, MON_DATA_HELD_ITEM)) == HOLD_EFFECT_PREVENT_EVOLVE #if P_NATURE_INHERITANCE == GEN_3 && (GetBoxMonGender(&daycare->mons[i].mon) == MON_FEMALE || IS_DITTO(GetBoxMonData(&daycare->mons[i].mon, MON_DATA_SPECIES))) - #endif + #endif ) { slot = i; numWithEverstone++; @@ -603,7 +602,7 @@ static void InheritIVs(struct Pokemon *egg, struct DayCare *daycare) } start = 0; - if (ItemId_GetHoldEffect(motherItem) == HOLD_EFFECT_POWER_ITEM && + if (ItemId_GetHoldEffect(motherItem) == HOLD_EFFECT_POWER_ITEM && ItemId_GetHoldEffect(fatherItem) == HOLD_EFFECT_POWER_ITEM) { whichParents[0] = Random() % DAYCARE_MON_COUNT; @@ -612,14 +611,14 @@ static void InheritIVs(struct Pokemon *egg, struct DayCare *daycare) RemoveIVIndexFromList(availableIVs, selectedIvs[0]); start++; } - else if (ItemId_GetHoldEffect(motherItem) == HOLD_EFFECT_POWER_ITEM) + else if (ItemId_GetHoldEffect(motherItem) == HOLD_EFFECT_POWER_ITEM) { whichParents[0] = 0; selectedIvs[0] = ItemId_GetSecondaryId(motherItem); RemoveIVIndexFromList(availableIVs, selectedIvs[0]); start++; } - else if (ItemId_GetHoldEffect(fatherItem) == HOLD_EFFECT_POWER_ITEM) + else if (ItemId_GetHoldEffect(fatherItem) == HOLD_EFFECT_POWER_ITEM) { whichParents[0] = 1; selectedIvs[0] = ItemId_GetSecondaryId(fatherItem); @@ -1230,7 +1229,7 @@ static bool8 EggGroupsOverlap(u16 *eggGroups1, u16 *eggGroups2) return FALSE; } -static u8 GetDaycareCompatibilityScore(struct DayCare *daycare) +u8 GetDaycareCompatibilityScore(struct DayCare *daycare) { u32 i; u16 eggGroups[DAYCARE_MON_COUNT][EGG_GROUPS_PER_MON]; diff --git a/src/debug.c b/src/debug.c index a455dcc04a..f915235d8b 100644 --- a/src/debug.c +++ b/src/debug.c @@ -150,17 +150,17 @@ enum { // Battle 1 AI FLags DEBUG_BATTLE_1_MENU_ITEM_CONTINUE, }; enum { // Battle 2 Terrain - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_0, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_1, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_2, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_3, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_4, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_5, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_6, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_7, - DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_8, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_0, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_1, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_2, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_3, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_4, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_5, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_6, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_7, + DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_8, DEBUG_BATTLE_2_MENU_ITEM_TERRAIN_9, -}; +}; enum { // Give DEBUG_GIVE_MENU_ITEM_ITEM_X, DEBUG_GIVE_MENU_ITEM_ALLTMS, @@ -372,24 +372,27 @@ static void DebugAction_Sound_MUS(u8 taskId); static void DebugAction_Sound_MUS_SelectId(u8 taskId); -extern u8 Debug_FlagsNotSetOverworldConfigMessage[]; -extern u8 Debug_FlagsNotSetBattleConfigMessage[]; -extern u8 Debug_Script_1[]; -extern u8 Debug_Script_2[]; -extern u8 Debug_Script_3[]; -extern u8 Debug_Script_4[]; -extern u8 Debug_Script_5[]; -extern u8 Debug_Script_6[]; -extern u8 Debug_Script_7[]; -extern u8 Debug_Script_8[]; +extern const u8 Debug_FlagsNotSetOverworldConfigMessage[]; +extern const u8 Debug_FlagsNotSetBattleConfigMessage[]; +extern const u8 Debug_Script_1[]; +extern const u8 Debug_Script_2[]; +extern const u8 Debug_Script_3[]; +extern const u8 Debug_Script_4[]; +extern const u8 Debug_Script_5[]; +extern const u8 Debug_Script_6[]; +extern const u8 Debug_Script_7[]; +extern const u8 Debug_Script_8[]; +extern const u8 DebugScript_DaycareMonsNotCompatible[]; +extern const u8 DebugScript_OneDaycareMons[]; +extern const u8 DebugScript_ZeroDaycareMons[]; -extern u8 Debug_ShowFieldMessageStringVar4[]; -extern u8 Debug_CheatStart[]; -extern u8 Debug_HatchAnEgg[]; -extern u8 PlayersHouse_2F_EventScript_SetWallClock[]; -extern u8 PlayersHouse_2F_EventScript_CheckWallClock[]; -extern u8 Debug_CheckSaveBlock[]; -extern u8 Debug_BoxFilledMessage[]; +extern const u8 Debug_ShowFieldMessageStringVar4[]; +extern const u8 Debug_CheatStart[]; +extern const u8 Debug_HatchAnEgg[]; +extern const u8 PlayersHouse_2F_EventScript_SetWallClock[]; +extern const u8 PlayersHouse_2F_EventScript_CheckWallClock[]; +extern const u8 Debug_CheckSaveBlock[]; +extern const u8 Debug_BoxFilledMessage[]; #include "data/map_group_count.h" @@ -1109,7 +1112,7 @@ static void Debug_InitDebugBattleData(void) sDebugBattleData->submenu = 0; sDebugBattleData->battleType = 0xFF; sDebugBattleData->battleTerrain = 0xFF; - + for (i = 0; i < AI_FLAG_COUNT; i++) sDebugBattleData->aiFlags[i] = FALSE; } @@ -1145,7 +1148,7 @@ static void Debug_RefreshListMenu(u8 taskId) // Copy item names for all entries but the last (which is Cancel) for(i = 0; i < totalItems; i++) { - + if (sDebugMenuListData->listId == 1 && sDebugBattleData->submenu > 1) { u16 species; @@ -1179,7 +1182,7 @@ static void Debug_RefreshListMenu(u8 taskId) flagResult == 0xFF; name = sDebugMenu_Items_Battle_1[i].name; } - + if (flagResult == 0xFF) { StringCopy(&sDebugMenuListData->itemNames[i][0], name); @@ -1315,10 +1318,6 @@ static void DebugTask_HandleMenuInput_FlagsVars(u8 taskId) { PlaySE(SE_SELECT); Debug_DestroyMenu(taskId); - - ClearStdWindowAndFrame(gTasks[taskId].data[2], TRUE); - RemoveWindow(gTasks[taskId].data[2]); - Debug_ReShowMainMenu(); } } @@ -1356,7 +1355,7 @@ static void DebugTask_HandleMenuInput_Battle(u8 taskId) ListMenuGetCurrentItemArrayId(listTaskId, &idx); if (gMain.newKeys & A_BUTTON) - { + { PlaySE(SE_SELECT); switch (sDebugBattleData->submenu) @@ -1389,7 +1388,7 @@ static void DebugTask_HandleMenuInput_Battle(u8 taskId) sDebugBattleData->aiFlags[idx] = !sDebugBattleData->aiFlags[idx]; Debug_RedrawListMenu(taskId); } - + break; case 2: // Terrain sDebugBattleData->submenu++; @@ -1413,7 +1412,7 @@ static void DebugTask_HandleMenuInput_Battle(u8 taskId) Debug_ReShowMainMenu(); break; case 2: // Skip AI Flag selection if wild battle - if (sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD + if (sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD || sDebugBattleData->battleType == DEBUG_BATTLE_0_MENU_ITEM_WILD_DOUBLE) { sDebugBattleData->submenu = 0; @@ -1450,7 +1449,7 @@ static void Debug_InitializeBattle(u8 taskId) gBattleTypeFlags = (BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS | BATTLE_TYPE_TRAINER | BATTLE_TYPE_INGAME_PARTNER); break; } - + // Set terrain gBattleTerrain = sDebugBattleData->battleTerrain; @@ -2401,7 +2400,7 @@ static void DebugAction_FlagsVars_ToggleFlyFlags(u8 taskId) else { PlaySE(SE_PC_LOGIN); - + FlagSet(FLAG_VISITED_LITTLEROOT_TOWN); FlagSet(FLAG_VISITED_OLDALE_TOWN); FlagSet(FLAG_VISITED_DEWFORD_TOWN); @@ -3471,7 +3470,15 @@ static void DebugAction_Give_MaxBattlePoints(u8 taskId) static void DebugAction_Give_DayCareEgg(u8 taskId) { - TriggerPendingDaycareEgg(); + s32 emptySlot = Daycare_FindEmptySpot(&gSaveBlock1Ptr->daycare); + if (emptySlot == 0) // no daycare mons + Debug_DestroyMenu_Full_Script(taskId, DebugScript_ZeroDaycareMons); + else if (emptySlot == 1) // 1 daycare mon + Debug_DestroyMenu_Full_Script(taskId, DebugScript_OneDaycareMons); + else if (GetDaycareCompatibilityScore(&gSaveBlock1Ptr->daycare) == PARENTS_INCOMPATIBLE) // not compatible parents + Debug_DestroyMenu_Full_Script(taskId, DebugScript_DaycareMonsNotCompatible); + else // 2 pokemon which can have a pokemon baby together + TriggerPendingDaycareEgg(); } // ******************************* diff --git a/test/battle/ability/toxic_debris.c b/test/battle/ability/toxic_debris.c index 95749358a4..f3e23e5abb 100644 --- a/test/battle/ability/toxic_debris.c +++ b/test/battle/ability/toxic_debris.c @@ -80,6 +80,21 @@ SINGLE_BATTLE_TEST("Each hit of a Multi Hit move activates Toxic Debris") } } +SINGLE_BATTLE_TEST("Toxic Debris activates if user faints after physical hit") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); Ability(ABILITY_TOXIC_DEBRIS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + MESSAGE("Wobbuffet fainted!"); + ABILITY_POPUP(player, ABILITY_TOXIC_DEBRIS); + MESSAGE("Poison Spikes were scattered all around the opposing team's feet!"); + } +} + SINGLE_BATTLE_TEST("Air Balloon is popped after Toxic Debris activates") { GIVEN { diff --git a/test/battle/move_effect/stockpile.c b/test/battle/move_effect/stockpile.c index 0e540bb5d3..e5f108a16d 100644 --- a/test/battle/move_effect/stockpile.c +++ b/test/battle/move_effect/stockpile.c @@ -250,4 +250,3 @@ DOUBLE_BATTLE_TEST("Stockpile's Def and Sp. Def boost is lost after using Spit U EXPECT_MUL_EQ(results[2].dmgSpecialBefore, UQ_4_12(1.0), results[2].dmgSpecialAfter); } } -