From 136ea395acf53e44ca3577b70cd6a34ab32164fd Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Tue, 19 Sep 2023 12:15:03 +0200 Subject: [PATCH 1/8] Fix tests breaking on modern (#3319) * Fix tests breaking on modern * modern tests fix - macro and rodata changes * ld script rodata modern --- include/test/battle.h | 3 ++- ld_script_test.txt | 8 ++++---- test/battle/move_effect/stockpile.c | 1 - 3 files changed, 6 insertions(+), 6 deletions(-) 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/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); } } - From 415d6e90544b189ce6e819331e8914f3b4777d46 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:54:52 +0200 Subject: [PATCH 2/8] Fix Toxic Debris after user faints (#3323) --- src/battle_util.c | 3 +-- test/battle/ability/toxic_debris.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index b13e3cb293..51e5c1abee 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5707,8 +5707,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && !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(); 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 { From d4217739e60968e2da7f67660746165886e5c9cf Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Wed, 20 Sep 2023 20:03:00 -0500 Subject: [PATCH 3/8] Add type boosting held item power config (#3326) Co-authored-by: Eduardo Quezada D'Ottone --- include/config/item.h | 1 + src/data/items.h | 40 +++++++++++++++++++++++----------------- 2 files changed, 24 insertions(+), 17 deletions(-) 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/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, From 5b498e968f513c86ba725be228420678c7da2698 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Thu, 21 Sep 2023 15:24:26 +0200 Subject: [PATCH 4/8] Fix no return in isbattlergrounded (#3328) --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index 51e5c1abee..473ef80f8e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8313,7 +8313,7 @@ static bool32 IsBattlerGrounded2(u8 battler, bool32 considerInverse) bool32 IsBattlerGrounded(u8 battler) { - IsBattlerGrounded2(battler, FALSE); + return IsBattlerGrounded2(battler, FALSE); } bool32 IsBattlerAlive(u8 battler) From 8bf8c9e7a78d21cbbda6974298d9948b8bac4ce7 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Thu, 21 Sep 2023 16:45:02 +0200 Subject: [PATCH 5/8] Fix flag debug screen corrupting subsequent message boxes (#3317) --- src/debug.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/debug.c b/src/debug.c index a455dcc04a..ff689241c4 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, @@ -1109,7 +1109,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 +1145,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 +1179,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 +1315,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 +1352,7 @@ static void DebugTask_HandleMenuInput_Battle(u8 taskId) ListMenuGetCurrentItemArrayId(listTaskId, &idx); if (gMain.newKeys & A_BUTTON) - { + { PlaySE(SE_SELECT); switch (sDebugBattleData->submenu) @@ -1389,7 +1385,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 +1409,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 +1446,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 +2397,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); From f564d4492be22fab9caeb8034241cbf77846d111 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Thu, 21 Sep 2023 16:43:52 -0300 Subject: [PATCH 6/8] GetBattlerHoldEffect usage optimizations (#3330) * GetBattlerHoldEffect optimizations * Type fix --- src/battle_script_commands.c | 12 ++++++------ src/battle_util.c | 6 ++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1183d40520..61bd528b65 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11431,8 +11431,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); @@ -11442,6 +11441,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; @@ -11500,13 +11500,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); } @@ -11521,7 +11521,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; } @@ -11591,7 +11591,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; diff --git a/src/battle_util.c b/src/battle_util.c index 473ef80f8e..0c18ceb1c8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8288,7 +8288,9 @@ bool32 IsBattlerProtected(u8 battler, u16 move) // Only called directly when calculating damage type effectiveness static bool32 IsBattlerGrounded2(u8 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; @@ -8302,7 +8304,7 @@ static bool32 IsBattlerGrounded2(u8 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; From 662dd7d2c635f3dcc018c76ff63eb839ef8473b9 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Fri, 22 Sep 2023 17:20:00 +0200 Subject: [PATCH 7/8] Fix give daycare egg option giving buggy eggs (#3335) --- data/scripts/debug.inc | 24 +++++++++++++++++++++ include/daycare.h | 2 ++ src/daycare.c | 15 +++++++------- src/debug.c | 47 ++++++++++++++++++++++++++---------------- 4 files changed, 62 insertions(+), 26 deletions(-) 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/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/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 ff689241c4..f915235d8b 100644 --- a/src/debug.c +++ b/src/debug.c @@ -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" @@ -3467,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(); } // ******************************* From b77dec123417ca057f66cf745496a592f8f7de6e Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Sat, 23 Sep 2023 04:44:30 -0400 Subject: [PATCH 8/8] Transform updates AI_PARTY data (#3295) * Cmd_transformdataexecution overwrite AI_PARTY data * remove whitespace * add RecordAllMoves --------- Co-authored-by: ghoulslash --- include/battle_ai_util.h | 1 + src/battle_ai_util.c | 5 +++++ src/battle_script_commands.c | 8 ++++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 5f077fe0cc..cec3241379 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -14,6 +14,7 @@ bool32 BattlerHasAi(u32 battlerId); bool32 IsAiBattlerAware(u32 battlerId); void ClearBattlerMoveHistory(u8 battlerId); void RecordLastUsedMoveBy(u32 battlerId, u32 move); +void RecordAllMoves(u32 battler); void RecordKnownMove(u8 battlerId, u32 move); void RecordAbilityBattle(u8 battlerId, u16 abilityId); void ClearBattlerAbilityHistory(u8 battlerId); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index ed75fbad24..10668e07dd 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -507,6 +507,11 @@ void RecordKnownMove(u8 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(u8 battlerId, u16 abilityId) { BATTLE_HISTORY->abilities[battlerId] = abilityId; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 61bd528b65..36327515c6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12439,7 +12439,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; @@ -12464,7 +12464,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;