From 4935b2b3ad4363e0589ea2e5ea4e90cee12d5a3f Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Thu, 25 Apr 2024 23:24:10 +0200 Subject: [PATCH 01/15] Update pokedex_plus_hgss.c (#4445) --- src/pokedex_plus_hgss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c index debf4d7fe0..abc1ba410a 100644 --- a/src/pokedex_plus_hgss.c +++ b/src/pokedex_plus_hgss.c @@ -385,7 +385,7 @@ struct PokemonStats u8 eggGroup1; u8 eggGroup2; u8 eggCycles; - u16 expYield; + u16 expYield; u8 friendship; u16 ability0; u16 ability1; From ec37b2170f1fa1e2b27f2329592c1275484398a0 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:29:26 +0200 Subject: [PATCH 02/15] Fixes Hospitality triggering on a fainted mon (#4450) --- src/battle_util.c | 5 ++++- test/battle/ability/hospitality.c | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index c68959a8ff..498c8c0abb 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4724,7 +4724,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_HOSPITALITY: partner = BATTLE_PARTNER(battler); - if (!gSpecialStatuses[battler].switchInAbilityDone && IsDoubleBattle() && gBattleMons[partner].hp < gBattleMons[partner].maxHP) + if (!gSpecialStatuses[battler].switchInAbilityDone + && IsDoubleBattle() + && gBattleMons[partner].hp < gBattleMons[partner].maxHP + && IsBattlerAlive(partner)) { gBattlerTarget = partner; gBattlerAttacker = battler; diff --git a/test/battle/ability/hospitality.c b/test/battle/ability/hospitality.c index 74648b0c9a..c40512d5be 100644 --- a/test/battle/ability/hospitality.c +++ b/test/battle/ability/hospitality.c @@ -68,3 +68,24 @@ DOUBLE_BATTLE_TEST("Hospitality ignores Substitute") MESSAGE("Wobbuffet drank down all the matcha that Ptchageist made!"); } } + +DOUBLE_BATTLE_TEST("Hospitality does not trigger if there is no ally on the field") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_POLTCHAGEIST) { Ability(ABILITY_HOSPITALITY); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_BLIZZARD); SEND_OUT(playerLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BLIZZARD, opponentLeft); + HP_BAR(playerLeft); + MESSAGE("Wobbuffet fainted!"); + HP_BAR(playerRight); + MESSAGE("Wobbuffet fainted!"); + MESSAGE("Go! Ptchageist!"); + NOT ABILITY_POPUP(playerLeft, ABILITY_HOSPITALITY); + } +} From 7355eb99a5bca70aa7e724a341d54bf8e4f8adc4 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 27 Apr 2024 13:36:29 +0200 Subject: [PATCH 03/15] Fix infinite loop caused by leftovers with AI_FLAG_SMART_CHOICES (#4453) --- src/battle_ai_switch_items.c | 2 +- test/battle/ai.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index f08251e2a5..273fb2c998 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1535,7 +1535,7 @@ static u32 GetSwitchinHitsToKO(s32 damageTaken, u32 battler) s32 currentHP = startingHP; // No damage being dealt - if ((damageTaken + statusDamage + recurringDamage < recurringHealing) || damageTaken + statusDamage + recurringDamage == 0) + if ((damageTaken + statusDamage + recurringDamage <= recurringHealing) || damageTaken + statusDamage + recurringDamage == 0) return startingHP; // Mon fainted to hazards diff --git a/test/battle/ai.c b/test/battle/ai.c index 0597925356..0d890da466 100644 --- a/test/battle/ai.c +++ b/test/battle/ai.c @@ -548,6 +548,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Number of hits to KO calculati AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Number of hits to KO calculation checks whether incoming damage is zero to avoid an infinite loop") { GIVEN { + ASSUME(gItemsInfo[ITEM_LEFTOVERS].holdEffect == HOLD_EFFECT_LEFTOVERS); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES); PLAYER(SPECIES_BULBASAUR) { Level(5); Moves(MOVE_SWORDS_DANCE, MOVE_WHIRLWIND, MOVE_SAND_ATTACK, MOVE_TAIL_WHIP); } // Scenario courtesy of Duke, who triggered the bug in the first place @@ -561,6 +562,23 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Number of hits to KO calculati } } +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Avoid infinite loop if damage taken is equal to recurring healing") +{ + GIVEN { + ASSUME(gItemsInfo[ITEM_LEFTOVERS].holdEffect == HOLD_EFFECT_LEFTOVERS); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES); + PLAYER(SPECIES_MEOWTH_GALARIAN) { Level(100); Moves(MOVE_GROWL, MOVE_FAKE_OUT, MOVE_HONE_CLAWS); } + // Scenario courtesy of Duke, who triggered the bug in the first place + OPPONENT(SPECIES_MEOWTH_GALARIAN) { Level(5); Moves(MOVE_GROWL, MOVE_FAKE_OUT, MOVE_HONE_CLAWS); } + OPPONENT(SPECIES_GEODUDE) { Level(5); Moves(MOVE_DOUBLE_EDGE); } + OPPONENT(SPECIES_GEODUDE) { Level(5); Moves(MOVE_DOUBLE_EDGE); } + OPPONENT(SPECIES_NOSEPASS) { Level(5); Moves(MOVE_DOUBLE_EDGE); } + OPPONENT(SPECIES_HOUNDSTONE) { Level(5); Moves(MOVE_NIGHT_SHADE, MOVE_BODY_PRESS, MOVE_WILL_O_WISP, MOVE_PROTECT); Item(ITEM_LEFTOVERS); } + } WHEN { + TURN { MOVE(player, MOVE_FAKE_OUT); EXPECT_MOVES(opponent, MOVE_FAKE_OUT); } + } +} + AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI will not switch in a Pokemon which is slower and gets 1HKOed after fainting") { bool32 alakazamFirst; From fc9d5c289a8a042d3ec34672ad41f8903ea661f0 Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Sat, 27 Apr 2024 12:35:42 -0500 Subject: [PATCH 04/15] Embody Aspect fixes (#4439) * Embody Aspect fixes * Fix tests * Update battle_util.c --- include/constants/abilities.h | 8 ++-- src/battle_util.c | 20 +++++----- src/data/abilities.h | 8 ++-- .../pokemon/species_info/gen_9_families.h | 8 ++-- test/battle/ability/embody_aspect.c | 38 +++++++++---------- 5 files changed, 41 insertions(+), 41 deletions(-) diff --git a/include/constants/abilities.h b/include/constants/abilities.h index 3cced68bb1..8568206137 100644 --- a/include/constants/abilities.h +++ b/include/constants/abilities.h @@ -326,10 +326,10 @@ #define ABILITY_MYCELIUM_MIGHT 298 #define ABILITY_HOSPITALITY 299 #define ABILITY_MINDS_EYE 300 -#define ABILITY_EMBODY_ASPECT_TEAL 301 -#define ABILITY_EMBODY_ASPECT_HEARTHFLAME 302 -#define ABILITY_EMBODY_ASPECT_WELLSPRING 303 -#define ABILITY_EMBODY_ASPECT_CORNERSTONE 304 +#define ABILITY_EMBODY_ASPECT_TEAL_MASK 301 +#define ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK 302 +#define ABILITY_EMBODY_ASPECT_WELLSPRING_MASK 303 +#define ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK 304 #define ABILITY_TOXIC_CHAIN 305 #define ABILITY_SUPERSWEET_SYRUP 306 #define ABILITY_TERA_SHIFT 307 diff --git a/src/battle_util.c b/src/battle_util.c index 498c8c0abb..e4885c665b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4737,22 +4737,22 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 effect++; } break; - case ABILITY_EMBODY_ASPECT_TEAL: - case ABILITY_EMBODY_ASPECT_HEARTHFLAME: - case ABILITY_EMBODY_ASPECT_WELLSPRING: - case ABILITY_EMBODY_ASPECT_CORNERSTONE: + case ABILITY_EMBODY_ASPECT_TEAL_MASK: + case ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK: + case ABILITY_EMBODY_ASPECT_WELLSPRING_MASK: + case ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK: if (!gSpecialStatuses[battler].switchInAbilityDone) { - u32 stat = STAT_SPATK; + u32 stat; - if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_TEAL) - stat = STAT_SPATK; - else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_HEARTHFLAME) + if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK) stat = STAT_ATK; - else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_WELLSPRING) + else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_WELLSPRING_MASK) stat = STAT_SPDEF; - else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_CORNERSTONE) + else if (gLastUsedAbility == ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK) stat = STAT_DEF; + else //ABILITY_EMBODY_ASPECT_TEAL_MASK + stat = STAT_SPEED; if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_EQUAL)) break; diff --git a/src/data/abilities.h b/src/data/abilities.h index 8c26934d9a..6905d67617 100644 --- a/src/data/abilities.h +++ b/src/data/abilities.h @@ -2472,7 +2472,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = .breakable = TRUE, }, - [ABILITY_EMBODY_ASPECT_TEAL] = + [ABILITY_EMBODY_ASPECT_TEAL_MASK] = { #if B_EXPANDED_ABILITY_NAMES == TRUE .name = _("Embody Aspect"), @@ -2487,7 +2487,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = .failsOnImposter = TRUE, }, - [ABILITY_EMBODY_ASPECT_HEARTHFLAME] = + [ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK] = { #if B_EXPANDED_ABILITY_NAMES == TRUE .name = _("Embody Aspect"), @@ -2502,7 +2502,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = .failsOnImposter = TRUE, }, - [ABILITY_EMBODY_ASPECT_WELLSPRING] = + [ABILITY_EMBODY_ASPECT_WELLSPRING_MASK] = { #if B_EXPANDED_ABILITY_NAMES == TRUE .name = _("Embody Aspect"), @@ -2517,7 +2517,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = .failsOnImposter = TRUE, }, - [ABILITY_EMBODY_ASPECT_CORNERSTONE] = + [ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK] = { #if B_EXPANDED_ABILITY_NAMES == TRUE .name = _("Embody Aspect"), diff --git a/src/data/pokemon/species_info/gen_9_families.h b/src/data/pokemon/species_info/gen_9_families.h index d858ec352c..98ae37e90b 100644 --- a/src/data/pokemon/species_info/gen_9_families.h +++ b/src/data/pokemon/species_info/gen_9_families.h @@ -6314,10 +6314,10 @@ const struct SpeciesInfo gSpeciesInfoGen9[] = [SPECIES_OGERPON_HEARTHFLAME_MASK] = OGERPON_SPECIES_INFO(HearthflameMask, TYPE_FIRE, ABILITY_MOLD_BREAKER, BODY_COLOR_RED, 0), [SPECIES_OGERPON_CORNERSTONE_MASK] = OGERPON_SPECIES_INFO(CornerstoneMask, TYPE_ROCK, ABILITY_STURDY, BODY_COLOR_GRAY, 0), #if P_TERA_FORMS - [SPECIES_OGERPON_TEAL_MASK_TERA] = OGERPON_SPECIES_INFO(TealMask, TYPE_GRASS, ABILITY_EMBODY_ASPECT_TEAL, BODY_COLOR_GREEN, 1), - [SPECIES_OGERPON_WELLSPRING_MASK_TERA] = OGERPON_SPECIES_INFO(WellspringMask, TYPE_WATER, ABILITY_EMBODY_ASPECT_WELLSPRING, BODY_COLOR_BLUE, 0), - [SPECIES_OGERPON_HEARTHFLAME_MASK_TERA] = OGERPON_SPECIES_INFO(HearthflameMask, TYPE_FIRE, ABILITY_EMBODY_ASPECT_HEARTHFLAME, BODY_COLOR_RED, 0), - [SPECIES_OGERPON_CORNERSTONE_MASK_TERA] = OGERPON_SPECIES_INFO(CornerstoneMask, TYPE_ROCK, ABILITY_EMBODY_ASPECT_CORNERSTONE, BODY_COLOR_GRAY, 0), + [SPECIES_OGERPON_TEAL_MASK_TERA] = OGERPON_SPECIES_INFO(TealMask, TYPE_GRASS, ABILITY_EMBODY_ASPECT_TEAL_MASK, BODY_COLOR_GREEN, 1), + [SPECIES_OGERPON_WELLSPRING_MASK_TERA] = OGERPON_SPECIES_INFO(WellspringMask, TYPE_WATER, ABILITY_EMBODY_ASPECT_WELLSPRING_MASK, BODY_COLOR_BLUE, 0), + [SPECIES_OGERPON_HEARTHFLAME_MASK_TERA] = OGERPON_SPECIES_INFO(HearthflameMask, TYPE_FIRE, ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK, BODY_COLOR_RED, 0), + [SPECIES_OGERPON_CORNERSTONE_MASK_TERA] = OGERPON_SPECIES_INFO(CornerstoneMask, TYPE_ROCK, ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK, BODY_COLOR_GRAY, 0), #endif //P_TERA_FORMS #endif //P_FAMILY_OGERPON diff --git a/test/battle/ability/embody_aspect.c b/test/battle/ability/embody_aspect.c index 8b37dd1a74..728ba8cb94 100644 --- a/test/battle/ability/embody_aspect.c +++ b/test/battle/ability/embody_aspect.c @@ -2,14 +2,14 @@ #include "test/battle.h" -SINGLE_BATTLE_TEST("Embodoy Aspect raises a stat depending on the users form by one stage") +SINGLE_BATTLE_TEST("Embody Aspect raises a stat depending on the users form by one stage") { u16 species, ability; - PARAMETRIZE { species = SPECIES_OGERPON_TEAL_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_TEAL; } - PARAMETRIZE { species = SPECIES_OGERPON_HEARTHFLAME_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_HEARTHFLAME; } - PARAMETRIZE { species = SPECIES_OGERPON_WELLSPRING_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_WELLSPRING; } - PARAMETRIZE { species = SPECIES_OGERPON_CORNERSTONE_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_CORNERSTONE; } + PARAMETRIZE { species = SPECIES_OGERPON_TEAL_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_TEAL_MASK; } + PARAMETRIZE { species = SPECIES_OGERPON_HEARTHFLAME_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK; } + PARAMETRIZE { species = SPECIES_OGERPON_WELLSPRING_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_WELLSPRING_MASK; } + PARAMETRIZE { species = SPECIES_OGERPON_CORNERSTONE_MASK_TERA; ability = ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK; } GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -19,32 +19,32 @@ SINGLE_BATTLE_TEST("Embodoy Aspect raises a stat depending on the users form by } SCENE { ABILITY_POPUP(opponent, ability); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - if (ability == ABILITY_EMBODY_ASPECT_TEAL) - MESSAGE("Foe Ogerpon's Embody Aspect raised its Sp. Atk!"); - else if (ability == ABILITY_EMBODY_ASPECT_HEARTHFLAME) + if (ability == ABILITY_EMBODY_ASPECT_TEAL_MASK) + MESSAGE("Foe Ogerpon's Embody Aspect raised its Speed!"); + else if (ability == ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK) MESSAGE("Foe Ogerpon's Embody Aspect raised its Attack!"); - else if (ability == ABILITY_EMBODY_ASPECT_WELLSPRING) + else if (ability == ABILITY_EMBODY_ASPECT_WELLSPRING_MASK) MESSAGE("Foe Ogerpon's Embody Aspect raised its Sp. Def!"); - else if (ability == ABILITY_EMBODY_ASPECT_CORNERSTONE) + else if (ability == ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK) MESSAGE("Foe Ogerpon's Embody Aspect raised its Defense!"); } THEN { - if (ability == ABILITY_EMBODY_ASPECT_TEAL) - EXPECT_EQ(opponent->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 1); - else if (ability == ABILITY_EMBODY_ASPECT_HEARTHFLAME) + if (ability == ABILITY_EMBODY_ASPECT_TEAL_MASK) + EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 1); + else if (ability == ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK) EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 1); - else if (ability == ABILITY_EMBODY_ASPECT_WELLSPRING) + else if (ability == ABILITY_EMBODY_ASPECT_WELLSPRING_MASK) EXPECT_EQ(opponent->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); - else if (ability == ABILITY_EMBODY_ASPECT_CORNERSTONE) + else if (ability == ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK) EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); } } -SINGLE_BATTLE_TEST("Embodoy Aspect activates when it's no longer effected by Neutralizing Gas") +SINGLE_BATTLE_TEST("Embody Aspect activates when it's no longer effected by Neutralizing Gas") { GIVEN { PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); } PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_OGERPON_TEAL_MASK_TERA) { Ability(ABILITY_EMBODY_ASPECT_TEAL); } + OPPONENT(SPECIES_OGERPON_TEAL_MASK_TERA) { Ability(ABILITY_EMBODY_ASPECT_TEAL_MASK); } } WHEN { TURN { SWITCH(player, 1); } } SCENE { @@ -52,8 +52,8 @@ SINGLE_BATTLE_TEST("Embodoy Aspect activates when it's no longer effected by Neu MESSAGE("Neutralizing Gas filled the area!"); MESSAGE("Weezing, that's enough! Come back!"); MESSAGE("The effects of Neutralizing Gas wore off!"); - ABILITY_POPUP(opponent, ABILITY_EMBODY_ASPECT_TEAL); + ABILITY_POPUP(opponent, ABILITY_EMBODY_ASPECT_TEAL_MASK); ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); - MESSAGE("Foe Ogerpon's Embody Aspect raised its Sp. Atk!"); + MESSAGE("Foe Ogerpon's Embody Aspect raised its Speed!"); } } From 3ac67acc63742147b74ec1b14a6ef4221323150d Mon Sep 17 00:00:00 2001 From: Cafei <46283144+cafei-uh@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:05:23 +0400 Subject: [PATCH 05/15] Fix Tatsugiri Droopy back sprite (#4455) --- graphics/pokemon/tatsugiri/droopy/back.png | Bin 400 -> 386 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/tatsugiri/droopy/back.png b/graphics/pokemon/tatsugiri/droopy/back.png index 6d998537f2036c86d1014d091d32d4a1d7167089..381ae4278ee9426eb96a914a3680c0c83a528afa 100644 GIT binary patch delta 313 zcmV-90mlB21A+sPBnkm@Qb$4nuFf3kks&gF0Srk*K~z|U?Uca|gdhw=x7Z5x|37$J zKqbOb)a;Epn#^-L6h5D+si~>IYZblmQ()#72ns<7{FtDCNPt84{R%*IyAbg%An<8- zZdn|{C?f+(e~vLU39Uc;I?wtXH2vDjYK+A&{ehJVQm<9Cx zWcd35z_hmkaM*+Sz}0?rlNKA-!&`(lzyU#APyYab6nBW!?M*6(Clhhj4Nv%kBbbT`vTClcuJorXK4Hy-E)G;FN7e00000 LNkvXXu0mjff0Ka; delta 329 zcmZo-p1?doWul>eJp)fkkYDhBBw&A6(V2mPk>AtBF(jh(?UaLjM-(_*#2J%+{g>af zV4LYx(OYTx=aza-uH@^evGWFk`f!oGAB&xih;#UPa{idHpuwlX`TJik1+Lv4FZ2{1 zX7V!{3RFmnUig*G6Rs*#|6{8H`@&o7&y}k=OzZ2qY8g^qc8Lpgu4`f1z|p&3K#DJK z$4o&k1+fF`jGGv4uqsFiaG0}wVp#Xjm}yqSitQC&)0^rT)&wR!a%>3u%uvL1RJ@MU zKwP4Z*TDAPhx5!0nexmJHmDaL{90Ff`b~$ezC^bH8%x3p?RRz!7Uu<~^JX);$zG^$ zUBK9*$79cMY1bzK23gZD3^)639rBtW^-TOGW6|quK}LnUtOa#5bq~&4vJ?o8|6+O` W$miRd^I#PN5O})!xvX Date: Sun, 28 Apr 2024 18:06:39 +0300 Subject: [PATCH 06/15] Fix lingering long ability popup names (#4456) --- src/battle_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_interface.c b/src/battle_interface.c index 59f89ae30c..4e32fcf5a6 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -3114,6 +3114,7 @@ static void PrintBattlerOnAbilityPopUp(u8 battlerId, u8 spriteId1, u8 spriteId2) static void PrintAbilityOnAbilityPopUp(u32 ability, u8 spriteId1, u8 spriteId2) { + ClearAbilityName(spriteId1, spriteId2); PrintOnAbilityPopUp(gAbilitiesInfo[ability].name, (void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32) + 256, (void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32) + 256, @@ -3320,7 +3321,6 @@ void UpdateAbilityPopup(u8 battlerId) u8 spriteId2 = gBattleStruct->abilityPopUpSpriteIds[battlerId][1]; u16 ability = (gBattleScripting.abilityPopupOverwrite != 0) ? gBattleScripting.abilityPopupOverwrite : gBattleMons[battlerId].ability; - ClearAbilityName(spriteId1, spriteId2); PrintAbilityOnAbilityPopUp(ability, spriteId1, spriteId2); RestoreOverwrittenPixels((void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32)); } From c7797dff814f2d929af2a8859ab14129960ec02b Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sun, 28 Apr 2024 22:48:34 +0200 Subject: [PATCH 07/15] Make Fur Coat breakable (#4459) --- src/data/abilities.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data/abilities.h b/src/data/abilities.h index 6905d67617..a65d4e8c24 100644 --- a/src/data/abilities.h +++ b/src/data/abilities.h @@ -1276,6 +1276,7 @@ const struct Ability gAbilitiesInfo[ABILITIES_COUNT] = .name = _("Fur Coat"), .description = COMPOUND_STRING("Raises Defense."), .aiRating = 7, + .breakable = TRUE, }, [ABILITY_MAGICIAN] = From c1f92b088eb80d0147b0663dab269523826658c4 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 29 Apr 2024 13:21:33 +0200 Subject: [PATCH 08/15] Eject Pack fix (#4463) --- src/battle_script_commands.c | 4 +--- test/battle/hold_effect/eject_pack.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f65ed39037..94a85dfad0 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6040,8 +6040,6 @@ static void Cmd_moveend(void) for (i = 0; i < gBattlersCount; i++) { u32 holdEffect; - if (i == gBattlerAttacker) - continue; holdEffect = GetBattlerHoldEffect(i, TRUE); if (holdEffect == HOLD_EFFECT_EJECT_BUTTON) ejectButtonBattlers |= gBitTable[i]; @@ -6057,7 +6055,7 @@ static void Cmd_moveend(void) { u32 battler = battlers[i]; - if (ejectButtonBattlers & gBitTable[battler]) + if (battler != gBattlerAttacker && ejectButtonBattlers & gBitTable[battler]) { if (TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)) // Apparently Sheer Force blocks Eject Button, but not Eject Pack continue; diff --git a/test/battle/hold_effect/eject_pack.c b/test/battle/hold_effect/eject_pack.c index 1a54d5a2e9..6757b11db9 100644 --- a/test/battle/hold_effect/eject_pack.c +++ b/test/battle/hold_effect/eject_pack.c @@ -22,6 +22,7 @@ SINGLE_BATTLE_TEST("Eject Pack does not cause the new pokemon to lose hp due to MESSAGE("Wobbuffet is switched out with the Eject Pack!"); MESSAGE("Go! Wynaut!"); NOT MESSAGE("Wynaut was hurt by its Life Orb!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); } } @@ -41,3 +42,24 @@ SINGLE_BATTLE_TEST("Eject Pack does not activate if there are no pokemon left to } } } + +SINGLE_BATTLE_TEST("Eject Pack triggers on the correct pokemon") +{ + GIVEN { + ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_OVERHEAT); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_OVERHEAT, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet is switched out with the Eject Pack!"); + MESSAGE("Go! Wynaut!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } +} From 6ad443c9a80b32b67ce1187e9a7deeca4d0e2418 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Mon, 29 Apr 2024 22:16:58 +0100 Subject: [PATCH 09/15] Fixes Eject Items causing wrong pokemon to take damage from entry hazards (#4465) * Fix hazards damaging the wrong pokemon using eject items * Added Stealth Rock test as requested * Added Stealth Rock double battle test --- data/battle_scripts_1.s | 15 +++++++++ include/battle_scripts.h | 1 + src/battle_script_commands.c | 2 ++ test/battle/move_effect/stealth_rock.c | 43 ++++++++++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index b815c04d6d..2fae7c9e19 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6281,6 +6281,21 @@ BattleScript_DmgHazardsOnTargetFainted:: moveendall goto BattleScript_HandleFaintedMon +BattleScript_DmgHazardsOnBattlerScripting:: + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE + healthbarupdate BS_SCRIPTING + datahpupdate BS_SCRIPTING + call BattleScript_PrintHurtByDmgHazards + tryfaintmon BS_SCRIPTING + tryfaintmon_spikes BS_SCRIPTING, BattleScript_DmgHazardsOnBattlerScriptingFainted + return + +BattleScript_DmgHazardsOnBattlerScriptingFainted:: + setbyte sGIVEEXP_STATE, 0 + getexp BS_SCRIPTING + moveendall + goto BattleScript_HandleFaintedMon + BattleScript_DmgHazardsOnFaintedBattler:: orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE healthbarupdate BS_FAINTED diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 0cf14c0fc0..878389da98 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -77,6 +77,7 @@ extern const u8 BattleScript_EncoredNoMore[]; extern const u8 BattleScript_DestinyBondTakesLife[]; extern const u8 BattleScript_DmgHazardsOnAttacker[]; extern const u8 BattleScript_DmgHazardsOnTarget[]; +extern const u8 BattleScript_DmgHazardsOnBattlerScripting[]; extern const u8 BattleScript_DmgHazardsOnFaintedBattler[]; extern const u8 BattleScript_PerishSongTakesLife[]; extern const u8 BattleScript_PerishSongCountGoesDown[]; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 94a85dfad0..4b4e3faf5a 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7040,6 +7040,8 @@ static void SetDmgHazardsBattlescript(u8 battler, u8 multistringId) gBattlescriptCurrInstr = BattleScript_DmgHazardsOnTarget; else if (gBattlescriptCurrInstr[1] == BS_ATTACKER) gBattlescriptCurrInstr = BattleScript_DmgHazardsOnAttacker; + else if (gBattlescriptCurrInstr[1] == BS_SCRIPTING) + gBattlescriptCurrInstr = BattleScript_DmgHazardsOnBattlerScripting; else gBattlescriptCurrInstr = BattleScript_DmgHazardsOnFaintedBattler; } diff --git a/test/battle/move_effect/stealth_rock.c b/test/battle/move_effect/stealth_rock.c index 23a773f8e8..f8c7a6369e 100644 --- a/test/battle/move_effect/stealth_rock.c +++ b/test/battle/move_effect/stealth_rock.c @@ -30,3 +30,46 @@ SINGLE_BATTLE_TEST("Stealth Rock damage on switch in based on typing") HP_BAR(opponent, damage: maxHP / divisor); } } + +SINGLE_BATTLE_TEST("Stealth Rock damages the correct pokemon when Eject Button is triggered") +{ + GIVEN { + PLAYER(SPECIES_METAPOD) { Item(ITEM_EJECT_BUTTON); } + PLAYER(SPECIES_METAPOD); + OPPONENT(SPECIES_JOLTEON); + } WHEN { + TURN { MOVE(opponent, MOVE_STEALTH_ROCK); MOVE(player, MOVE_HARDEN); } + TURN { MOVE(opponent, MOVE_QUICK_ATTACK); MOVE(player, MOVE_HARDEN); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_HARDEN, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, opponent); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_HARDEN, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Go! Metapod!"); + HP_BAR(player); + } THEN { + EXPECT_EQ(opponent->hp, opponent->maxHP); + } +} + +DOUBLE_BATTLE_TEST("Stealth Rock damages the correct pokemon when Eject Button is triggered in double battle") +{ + GIVEN { + PLAYER(SPECIES_METAPOD) { Item(ITEM_EJECT_BUTTON); } + PLAYER(SPECIES_METAPOD) { Item(ITEM_EJECT_BUTTON); } + PLAYER(SPECIES_METAPOD); + OPPONENT(SPECIES_JOLTEON); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_STEALTH_ROCK); MOVE(opponentRight, MOVE_TACKLE, target: playerLeft); SEND_OUT(playerLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentRight); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + MESSAGE("Go! Metapod!"); + HP_BAR(playerLeft); + } THEN { + EXPECT_EQ(opponentLeft->hp, opponentLeft->maxHP); + } +} From 48d71b0de1fa1d418baeffc87390cf69c4d729df Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 30 Apr 2024 13:59:02 +0200 Subject: [PATCH 10/15] Hard Level Caps issues (#4420) * Fix 1 exp gain on hard level caps * Level Cap issues * fix compile * brackets --- src/battle_script_commands.c | 11 ++++++++++- src/pokemon.c | 11 ++++++++++- tools/trainerproc/trainerproc | Bin 0 -> 50320 bytes 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100755 tools/trainerproc/trainerproc diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4b4e3faf5a..f07c560877 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4416,7 +4416,15 @@ static void Cmd_getexp(void) gBattleMoveDamage += GetSoftLevelCapExpValue(gPlayerParty[*expMonId].level, gBattleStruct->expShareExpValue);; } - ApplyExperienceMultipliers(&gBattleMoveDamage, *expMonId, gBattlerFainted); + if (EXP_CAP_HARD && gBattleMoveDamage != 0) + { + u32 growthRate = gSpeciesInfo[GetMonData(&gPlayerParty[*expMonId], MON_DATA_SPECIES)].growthRate; + if (gExperienceTables[growthRate][GetCurrentLevelCap()] < gExperienceTables[growthRate][GetMonData(&gPlayerParty[*expMonId], MON_DATA_LEVEL)] + gBattleMoveDamage) + gBattleMoveDamage = gExperienceTables[growthRate][GetCurrentLevelCap()]; + } + + if (!EXP_CAP_HARD || gBattleMoveDamage != 0) // Edge case for hard level caps. Prevents mons from getting 1 exp + ApplyExperienceMultipliers(&gBattleMoveDamage, *expMonId, gBattlerFainted); if (IsTradedMon(&gPlayerParty[*expMonId])) { @@ -15987,6 +15995,7 @@ void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBat value *= sExperienceScalingFactors[(faintedLevel * 2) + 10]; value /= sExperienceScalingFactors[faintedLevel + expGetterLevel + 10]; + *expAmount = value + 1; } } diff --git a/src/pokemon.c b/src/pokemon.c index 5b1a10a908..f1e8207470 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -3530,8 +3530,17 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov { u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); dataUnsigned = sExpCandyExperienceTable[param - 1] + GetMonData(mon, MON_DATA_EXP, NULL); - if (dataUnsigned > gExperienceTables[gSpeciesInfo[species].growthRate][MAX_LEVEL]) + + if (B_RARE_CANDY_CAP && EXP_CAP_HARD) + { + u32 currentLevelCap = GetCurrentLevelCap(); + if (dataUnsigned > gExperienceTables[gSpeciesInfo[species].growthRate][currentLevelCap]) + dataUnsigned = gExperienceTables[gSpeciesInfo[species].growthRate][currentLevelCap]; + } + else if (dataUnsigned > gExperienceTables[gSpeciesInfo[species].growthRate][MAX_LEVEL]) + { dataUnsigned = gExperienceTables[gSpeciesInfo[species].growthRate][MAX_LEVEL]; + } } if (dataUnsigned != 0) // Failsafe diff --git a/tools/trainerproc/trainerproc b/tools/trainerproc/trainerproc new file mode 100755 index 0000000000000000000000000000000000000000..903e822d1bdea8722889b3a105eabd820962b08f GIT binary patch literal 50320 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 literal 0 HcmV?d00001 From 77e17247cded9028336fe0da8f19096fb8b0c9b5 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Wed, 1 May 2024 23:23:37 +0200 Subject: [PATCH 11/15] Color change fixes (#4472) * Fixed forseen moves not triggering Color Change and added tests for Color Change * Added issue number to Known Failing test --------- Co-authored-by: Hedara --- data/battle_scripts_1.s | 1 + test/battle/ability/color_change.c | 148 +++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 test/battle/ability/color_change.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 2fae7c9e19..9a1609d963 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6637,6 +6637,7 @@ BattleScript_DoFutureAttackResult: checkteamslost BattleScript_FutureAttackEnd BattleScript_FutureAttackEnd:: moveendcase MOVEEND_RAGE + moveendcase MOVEEND_ABILITIES moveendfromto MOVEEND_ITEM_EFFECTS_ALL, MOVEEND_UPDATE_LAST_MOVES setbyte gMoveResultFlags, 0 end2 diff --git a/test/battle/ability/color_change.c b/test/battle/ability/color_change.c new file mode 100644 index 0000000000..b7828bb978 --- /dev/null +++ b/test/battle/ability/color_change.c @@ -0,0 +1,148 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Color Change changes the type of a Pokemon being hit by a move if the type of the move and the Pokemon are different") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_COLOR_CHANGE); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ABILITY_POPUP(opponent, ABILITY_COLOR_CHANGE); + MESSAGE("Foe Wobbuffet's Color Change made it the Normal type!"); + } +} + +SINGLE_BATTLE_TEST("Color Change does not change the type when hit by a move that's the same type as itself") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_COLOR_CHANGE); } + } WHEN { + TURN { MOVE(player, MOVE_PSYCHO_CUT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHO_CUT, player); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_COLOR_CHANGE); + MESSAGE("Foe Wobbuffet's Color Change made it the Normal type!"); + } + } +} + +SINGLE_BATTLE_TEST("Color Change does not change the type of a dual-type Pokemon when hit by a move that shares its primary type") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_XATU) { Ability(ABILITY_COLOR_CHANGE); } + } WHEN { + TURN { MOVE(player, MOVE_PSYCHO_CUT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHO_CUT, player); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_COLOR_CHANGE); + MESSAGE("Foe Xatu's Color Change made it the Psychic type!"); + } + } +} + +SINGLE_BATTLE_TEST("Color Change does not change the type of a dual-type Pokemon when hit by a move that shares its secondary type") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SLOWBRO) { Ability(ABILITY_COLOR_CHANGE); } + } WHEN { + TURN { MOVE(player, MOVE_PSYCHO_CUT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHO_CUT, player); + NONE_OF { + ABILITY_POPUP(opponent, ABILITY_COLOR_CHANGE); + MESSAGE("Foe Slowbro's Color Change made it the Psychic type!"); + } + } +} + +SINGLE_BATTLE_TEST("Color Change changes the user to Electric type if hit by a move while the opponent is under the effect of Electrify") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_COLOR_CHANGE); } + } WHEN { + TURN { MOVE(opponent, MOVE_ELECTRIFY); MOVE(player, MOVE_PSYCHO_CUT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCHO_CUT, player); + ABILITY_POPUP(opponent, ABILITY_COLOR_CHANGE); + MESSAGE("Foe Wobbuffet's Color Change made it the Electr type!"); + } +} + +SINGLE_BATTLE_TEST("Color Change changes the type when a Pokemon is hit by Future Sight") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SNORLAX) { Ability(ABILITY_COLOR_CHANGE); } + } WHEN { + TURN { MOVE(player, MOVE_FUTURE_SIGHT); } + TURN { } + TURN { } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player); + MESSAGE("Foe Snorlax took the Future Sight attack!"); + ABILITY_POPUP(opponent, ABILITY_COLOR_CHANGE); + MESSAGE("Foe Snorlax's Color Change made it the Psychc type!"); + } +} + +SINGLE_BATTLE_TEST("Color Change changes the type when a Pokemon is hit by Doom Desire") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_COLOR_CHANGE); } + } WHEN { + TURN { MOVE(player, MOVE_DOOM_DESIRE); } + TURN { } + TURN { } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOOM_DESIRE, player); + MESSAGE("Foe Wobbuffet took the Doom Desire attack!"); + ABILITY_POPUP(opponent, ABILITY_COLOR_CHANGE); + MESSAGE("Foe Wobbuffet's Color Change made it the Steel type!"); + } +} + +SINGLE_BATTLE_TEST("Color Change changes the type to Electric when a Pokemon is hit by a forseen attack under the effect of Electrify") +{ + KNOWN_FAILING; // #4471. + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BLASTOISE) { Ability(ABILITY_COLOR_CHANGE); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_FUTURE_SIGHT); } + TURN { } + TURN { MOVE(opponent, MOVE_ELECTRIFY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player); + MESSAGE("Foe Blastoise took the Future Sight attack!"); + MESSAGE("It's super effective!"); + ABILITY_POPUP(opponent, ABILITY_COLOR_CHANGE); + MESSAGE("Foe Blastoise's Color Change made it the Electr type!"); + } +} + +SINGLE_BATTLE_TEST("Color Change changes the type to Normal when a Pokemon is hit by a forseen attack under the effect of Normalize") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_NORMALIZE); } + OPPONENT(SPECIES_BLASTOISE) { Ability(ABILITY_COLOR_CHANGE); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_FUTURE_SIGHT); } + TURN { } + TURN { } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player); + MESSAGE("Foe Blastoise took the Future Sight attack!"); + ABILITY_POPUP(opponent, ABILITY_COLOR_CHANGE); + MESSAGE("Foe Blastoise's Color Change made it the Normal type!"); + } +} From d59ef3710a3abe24dda6fd44aeb3d94536b95a41 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 1 May 2024 18:15:56 -0400 Subject: [PATCH 12/15] Fixed Future Sight script whitespace (#4475) --- data/battle_scripts_1.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 9a1609d963..31b0619118 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6637,7 +6637,7 @@ BattleScript_DoFutureAttackResult: checkteamslost BattleScript_FutureAttackEnd BattleScript_FutureAttackEnd:: moveendcase MOVEEND_RAGE - moveendcase MOVEEND_ABILITIES + moveendcase MOVEEND_ABILITIES moveendfromto MOVEEND_ITEM_EFFECTS_ALL, MOVEEND_UPDATE_LAST_MOVES setbyte gMoveResultFlags, 0 end2 From 2aed78ebbb762720e064c09c62cf806751cb139b Mon Sep 17 00:00:00 2001 From: WillKolada <57021938+WillKolada@users.noreply.github.com> Date: Thu, 2 May 2024 01:42:08 -0500 Subject: [PATCH 13/15] Update IsDamageMoveUsable to check for Steel Roller viability (#4476) * Update IsDamageMoveUsable to check for Steel Roller viability * Condense terrain flag checks and renamed IsDamageMoveUsable IsDamageMoveUsable is now named IsDamageMoveUnusable to more accurately reflect the boolean it returns. --- src/battle_ai_util.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 40f3da2b5a..2dc9946e3d 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -366,7 +366,7 @@ static inline s32 LowestRollDmg(s32 dmg) return dmg; } -bool32 IsDamageMoveUsable(u32 move, u32 battlerAtk, u32 battlerDef) +bool32 IsDamageMoveUnusable(u32 move, u32 battlerAtk, u32 battlerDef) { s32 moveType; struct AiLogicData *aiData = AI_DATA; @@ -438,6 +438,10 @@ bool32 IsDamageMoveUsable(u32 move, u32 battlerAtk, u32 battlerDef) if (!IS_BATTLER_OF_TYPE(battlerAtk, gMovesInfo[move].argument)) return TRUE; break; + case EFFECT_HIT_SET_REMOVE_TERRAIN: + if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) + return TRUE; + break; } return FALSE; @@ -472,7 +476,7 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes GET_MOVE_TYPE(move, moveType); if (gMovesInfo[move].power) - isDamageMoveUnusable = IsDamageMoveUsable(move, battlerAtk, battlerDef); + isDamageMoveUnusable = IsDamageMoveUnusable(move, battlerAtk, battlerDef); effectivenessMultiplier = CalcTypeEffectivenessMultiplier(move, moveType, battlerAtk, battlerDef, aiData->abilities[battlerDef], FALSE); if (gMovesInfo[move].power && !isDamageMoveUnusable) From 6d397f9867a9c899a1afe7ecad73ed0bdab57d26 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 2 May 2024 14:23:46 +0200 Subject: [PATCH 14/15] Fixes Magic Bounce in double battles (#4464) * Fixes Magic Bounce in double battles * Add Double Battle check --- include/battle.h | 4 +-- src/battle_main.c | 1 - src/battle_script_commands.c | 48 ++++++++++++++++++---------- src/battle_util.c | 5 +-- test/battle/ability/magic_bounce.c | 51 ++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 23 deletions(-) diff --git a/include/battle.h b/include/battle.h index b537be776e..dc771a5d77 100644 --- a/include/battle.h +++ b/include/battle.h @@ -157,7 +157,6 @@ struct ProtectStruct u32 flinchImmobility:1; u32 notFirstStrike:1; u32 palaceUnableToUseMove:1; - u32 usesBouncedMove:1; u32 usedHealBlockedMove:1; u32 usedGravityPreventedMove:1; u32 powderSelfDmg:1; @@ -736,9 +735,10 @@ struct BattleStruct u8 quickClawBattlerId; struct LostItem itemLost[PARTY_SIZE]; // Player's team that had items consumed or stolen (two bytes per party member) u8 forcedSwitch:4; // For each battler + u8 additionalEffectsCounter:4; // A counter for the additionalEffects applied by the current move in Cmd_setadditionaleffects u8 blunderPolicy:1; // should blunder policy activate u8 swapDamageCategory:1; // Photon Geyser, Shell Side Arm, Light That Burns the Sky - u8 additionalEffectsCounter:4; // A counter for the additionalEffects applied by the current move in Cmd_setadditionaleffects + u8 bouncedMoveIsUsed:1; u8 ballSpriteIds[2]; // item gfx, window gfx u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle. diff --git a/src/battle_main.c b/src/battle_main.c index e45b43d099..e8f825676c 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3581,7 +3581,6 @@ const u8* FaintClearSetData(u32 battler) gProtectStructs[battler].flinchImmobility = FALSE; gProtectStructs[battler].notFirstStrike = FALSE; gProtectStructs[battler].usedHealBlockedMove = FALSE; - gProtectStructs[battler].usesBouncedMove = FALSE; gProtectStructs[battler].usedGravityPreventedMove = FALSE; gProtectStructs[battler].usedThroatChopPreventedMove = FALSE; gProtectStructs[battler].statRaised = FALSE; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f07c560877..53b9cbb024 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1394,9 +1394,9 @@ static void Cmd_attackcanceler(void) if (gProtectStructs[gBattlerTarget].bounceMove && gMovesInfo[gCurrentMove].magicCoatAffected - && !gProtectStructs[gBattlerAttacker].usesBouncedMove) + && !gBattleStruct->bouncedMoveIsUsed) { - gProtectStructs[gBattlerTarget].usesBouncedMove = TRUE; + gBattleStruct->bouncedMoveIsUsed = TRUE; gBattleCommunication[MULTISTRING_CHOOSER] = 0; // Edge case for bouncing a powder move against a grass type pokemon. SetAtkCancellerForCalledMove(); @@ -1413,18 +1413,33 @@ static void Cmd_attackcanceler(void) } return; } - else if (GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE - && gMovesInfo[gCurrentMove].magicCoatAffected - && !gProtectStructs[gBattlerAttacker].usesBouncedMove) + else if (gMovesInfo[gCurrentMove].magicCoatAffected && !gBattleStruct->bouncedMoveIsUsed) { - gProtectStructs[gBattlerTarget].usesBouncedMove = TRUE; - gBattleCommunication[MULTISTRING_CHOOSER] = 1; - // Edge case for bouncing a powder move against a grass type pokemon. - SetAtkCancellerForCalledMove(); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_MagicCoatBounce; - gBattlerAbility = gBattlerTarget; - return; + u32 battler = gBattlerTarget; + + if (GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE) + { + battler = gBattlerTarget; + gBattleStruct->bouncedMoveIsUsed = TRUE; + } + else if (IsDoubleBattle() + && gMovesInfo[gCurrentMove].target == MOVE_TARGET_OPPONENTS_FIELD + && GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) == ABILITY_MAGIC_BOUNCE) + { + gBattlerTarget = battler = BATTLE_PARTNER(gBattlerTarget); + gBattleStruct->bouncedMoveIsUsed = TRUE; + } + + if (gBattleStruct->bouncedMoveIsUsed) + { + gBattleCommunication[MULTISTRING_CHOOSER] = 1; + // Edge case for bouncing a powder move against a grass type pokemon. + SetAtkCancellerForCalledMove(); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MagicCoatBounce; + gBattlerAbility = battler; + return; + } } // Z-moves and Max Moves bypass protection, but deal reduced damage (factored in AccumulateOtherModifiers) @@ -5920,9 +5935,10 @@ static void Cmd_moveend(void) return; } // Check if the move used was actually a bounced move. If so, we need to go back to the original attacker and make sure, its move hits all 2 or 3 pokemon. - else if (gProtectStructs[gBattlerAttacker].usesBouncedMove) + else if (gBattleStruct->bouncedMoveIsUsed) { u8 originalBounceTarget = gBattlerAttacker; + gBattleStruct->bouncedMoveIsUsed = FALSE; gBattlerAttacker = gBattleStruct->attackerBeforeBounce; gBattleStruct->targetsDone[gBattlerAttacker] |= gBitTable[originalBounceTarget]; gBattleStruct->targetsDone[originalBounceTarget] = 0; @@ -6221,7 +6237,7 @@ static void Cmd_moveend(void) if (!(gBattleStruct->lastMoveFailed & gBitTable[gBattlerAttacker] || (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove - && gProtectStructs[gBattlerAttacker].usesBouncedMove))) + && gBattleStruct->bouncedMoveIsUsed))) { // Dance move succeeds // Set target for other Dancer mons; set bit so that mon cannot activate Dancer off of its own move if (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove) @@ -6316,7 +6332,6 @@ static void Cmd_moveend(void) CancelMultiTurnMoves(gBattlerAttacker); // Cancel it gBattleStruct->targetsDone[gBattlerAttacker] = 0; - gProtectStructs[gBattlerAttacker].usesBouncedMove = FALSE; gProtectStructs[gBattlerAttacker].targetAffected = FALSE; gProtectStructs[gBattlerAttacker].shellTrap = FALSE; gBattleStruct->ateBoost[gBattlerAttacker] = 0; @@ -6333,6 +6348,7 @@ static void Cmd_moveend(void) gBattleStruct->hitSwitchTargetFailed = FALSE; gBattleStruct->isAtkCancelerForCalledMove = FALSE; gBattleStruct->swapDamageCategory = FALSE; + gBattleStruct->bouncedMoveIsUsed = FALSE; gBattleStruct->enduredDamage = 0; gBattleStruct->additionalEffectsCounter = 0; gBattleScripting.moveendState++; diff --git a/src/battle_util.c b/src/battle_util.c index e4885c665b..ecdd8db266 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3489,10 +3489,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) if (effect != 0) gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; } - if (gProtectStructs[gBattlerAttacker].usesBouncedMove) // Edge case for bouncing a powder move against a grass type pokemon. - gBattleStruct->atkCancellerTracker = CANCELLER_END; - else - gBattleStruct->atkCancellerTracker++; + gBattleStruct->atkCancellerTracker++; break; case CANCELLER_POWDER_STATUS: if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER) diff --git a/test/battle/ability/magic_bounce.c b/test/battle/ability/magic_bounce.c index 95eaf382e6..8d583b154d 100644 --- a/test/battle/ability/magic_bounce.c +++ b/test/battle/ability/magic_bounce.c @@ -81,3 +81,54 @@ DOUBLE_BATTLE_TEST("Magic Bounce bounces back moves hitting both foes at two foe MESSAGE("Foe Wynaut's Defense fell!"); } } + +DOUBLE_BATTLE_TEST("Magic Bounce bounces back moves hitting foes field") +{ + u32 battlerOne, battlerTwo, abilityBattlerOne, abilityBattlerTwo; + + PARAMETRIZE { battlerOne = SPECIES_NATU; abilityBattlerOne = ABILITY_MAGIC_BOUNCE; + battlerTwo = SPECIES_ESPEON; abilityBattlerTwo = ABILITY_SYNCHRONIZE; } + PARAMETRIZE { battlerOne = SPECIES_NATU; abilityBattlerOne = ABILITY_KEEN_EYE; + battlerTwo = SPECIES_ESPEON; abilityBattlerTwo = ABILITY_MAGIC_BOUNCE; } + + GIVEN { + ASSUME(gMovesInfo[MOVE_STEALTH_ROCK].target == MOVE_TARGET_OPPONENTS_FIELD); + PLAYER(SPECIES_ABRA); + PLAYER(SPECIES_KADABRA); + OPPONENT(battlerOne) { Ability(abilityBattlerOne); } + OPPONENT(battlerTwo) { Ability(abilityBattlerTwo); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_STEALTH_ROCK); } + } SCENE { + if (abilityBattlerOne == ABILITY_MAGIC_BOUNCE) + ABILITY_POPUP(opponentLeft, ABILITY_MAGIC_BOUNCE); + else + ABILITY_POPUP(opponentRight, ABILITY_MAGIC_BOUNCE); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, playerLeft); + if (abilityBattlerOne == ABILITY_MAGIC_BOUNCE) { + MESSAGE("Abra's Stealth Rock was bounced back by Foe Natu's Magic Bounce!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponentLeft); + } else { + MESSAGE("Abra's Stealth Rock was bounced back by Foe Espeon's Magic Bounce!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponentRight); + } + } +} + +SINGLE_BATTLE_TEST("Magic Bounce bounced back status moves can not be bounced back by Magic Bounce") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_TOXIC].effect == EFFECT_TOXIC); + PLAYER(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE); } + OPPONENT(SPECIES_ESPEON) { Ability(ABILITY_MAGIC_BOUNCE); } + } WHEN { + TURN { MOVE(player, MOVE_TOXIC); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_MAGIC_BOUNCE); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, player); + MESSAGE("Espeon's Toxic was bounced back by Foe Espeon's Magic Bounce!"); + NOT ABILITY_POPUP(player, ABILITY_MAGIC_BOUNCE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, opponent); + STATUS_ICON(player, badPoison: TRUE); + } +} From 22f9eee5094f4bdf017cfdb06465ea4068690d17 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 2 May 2024 14:01:22 -0400 Subject: [PATCH 15/15] Added trainerproc to .gitignore --- .gitignore | 1 + tools/trainerproc/trainerproc | Bin 50320 -> 0 bytes 2 files changed, 1 insertion(+) delete mode 100755 tools/trainerproc/trainerproc diff --git a/.gitignore b/.gitignore index af9009dd01..ba80433cf7 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ prefabs.json *.sym *.js src/data/map_group_count.h +tools/trainerproc/trainerproc diff --git a/tools/trainerproc/trainerproc b/tools/trainerproc/trainerproc deleted file mode 100755 index 903e822d1bdea8722889b3a105eabd820962b08f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50320 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