From 1f1d24b3e41fa69dacd446f0f438704c3df106e5 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Sun, 16 Jul 2023 13:26:54 +0200 Subject: [PATCH 01/19] Fix Primal Reversion not activating when switching in after fainting (#3141) * Fixed Primal Reversion not activating when switching in after a fainting * add tests for primal reversion Co-authored-by: Eduardo Quezada --- data/battle_scripts_1.s | 21 ++-- include/battle_scripts.h | 1 + include/battle_util.h | 1 + src/battle_main.c | 9 +- src/battle_script_commands.c | 3 +- src/battle_util.c | 21 ++++ test/primal_reversion.c | 216 +++++++++++++++++++++++++++++++++++ 7 files changed, 250 insertions(+), 22 deletions(-) create mode 100644 test/primal_reversion.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 28a4a33cdb..39712db735 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6768,9 +6768,6 @@ BattleScript_DoSwitchOut:: hidepartystatussummary BS_ATTACKER switchinanim BS_ATTACKER, FALSE waitstate - jumpifcantreverttoprimal BattleScript_DoSwitchOut2 - call BattleScript_PrimalReversionRet -BattleScript_DoSwitchOut2: switchineffects BS_ATTACKER moveendcase MOVEEND_STATUS_IMMUNITY_ABILITIES moveendcase MOVEEND_MIRROR_MOVE @@ -7925,17 +7922,12 @@ BattleScript_WishMegaEvolution:: goto BattleScript_MegaEvolutionAfterString BattleScript_PrimalReversion:: - printstring STRINGID_EMPTYSTRING3 - waitmessage 1 - setbyte gIsCriticalHit, 0 - handleprimalreversion BS_ATTACKER, 0 - handleprimalreversion BS_ATTACKER, 1 - playanimation BS_ATTACKER, B_ANIM_PRIMAL_REVERSION - waitanimation - handleprimalreversion BS_ATTACKER, 2 - printstring STRINGID_PKMNREVERTEDTOPRIMAL - waitmessage B_WAIT_TIME_LONG - switchinabilities BS_ATTACKER + call BattleScript_PrimalReversionRet + end2 + +BattleScript_PrimalReversionRestoreAttacker:: + call BattleScript_PrimalReversionRet + copybyte gBattlerAttacker, sSAVED_BATTLER end2 BattleScript_PrimalReversionRet:: @@ -7949,6 +7941,7 @@ BattleScript_PrimalReversionRet:: handleprimalreversion BS_ATTACKER, 2 printstring STRINGID_PKMNREVERTEDTOPRIMAL waitmessage B_WAIT_TIME_LONG + switchinabilities BS_ATTACKER return BattleScript_AttackerFormChange:: diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 0033b011e4..b20ac35dd5 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -418,6 +418,7 @@ extern const u8 BattleScript_AttackWeakenedByStrongWinds[]; extern const u8 BattleScript_BlockedByPrimalWeatherEnd3[]; extern const u8 BattleScript_BlockedByPrimalWeatherRet[]; extern const u8 BattleScript_PrimalReversion[]; +extern const u8 BattleScript_PrimalReversionRestoreAttacker[]; extern const u8 BattleScript_HyperspaceFuryRemoveProtect[]; extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTactics[]; extern const u8 BattleScript_SelectingNotAllowedMoveGorillaTacticsInPalace[]; diff --git a/include/battle_util.h b/include/battle_util.h index bd3bad8e2d..aba215c129 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -142,6 +142,7 @@ u8 AtkCanceller_UnableToUseMove2(void); bool8 HasNoMonsToSwitch(u8 battlerId, u8 r1, u8 r2); bool32 TryChangeBattleWeather(u8 battler, u32 weatherEnumId, bool32 viaAbility); u8 AbilityBattleEffects(u8 caseID, u8 battlerId, u16 ability, u8 special, u16 moveArg); +bool32 TryPrimalReversion(u8 battlerId); bool32 IsNeutralizingGasOnField(void); u32 GetBattlerAbility(u8 battlerId); u32 IsAbilityOnSide(u32 battlerId, u32 ability); diff --git a/src/battle_main.c b/src/battle_main.c index f082fb210f..3e19f247e6 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3861,14 +3861,9 @@ static void TryDoEventsBeforeFirstTurn(void) while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount) { gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->switchInAbilitiesCounter++]; - - // Primal Reversion - if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_PRIMAL_ORB - && GetBattleFormChangeTargetSpecies(gBattlerAttacker, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE) - { - BattleScriptExecute(BattleScript_PrimalReversion); + + if (TryPrimalReversion(gBattlerAttacker)) return; - } if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBattlerAttacker, 0, 0, 0) != 0) return; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b77f929642..74e13b6d87 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7042,7 +7042,8 @@ static void SetDmgHazardsBattlescript(u8 battlerId, u8 multistringId) bool32 DoSwitchInAbilitiesItems(u32 battlerId) { - return (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battlerId, 0, 0, 0) + return (TryPrimalReversion(battlerId) + || AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battlerId, 0, 0, 0) || (gBattleWeather & B_WEATHER_ANY && WEATHER_HAS_EFFECT && AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battlerId, 0, 0, 0)) || (gFieldStatuses & STATUS_FIELD_TERRAIN_ANY && AbilityBattleEffects(ABILITYEFFECT_ON_TERRAIN, battlerId, 0, 0, 0)) || ItemBattleEffects(ITEMEFFECT_ON_SWITCH_IN, battlerId, FALSE) diff --git a/src/battle_util.c b/src/battle_util.c index c9dcab3db3..105b29cacf 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6092,6 +6092,27 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move return effect; } +bool32 TryPrimalReversion(u8 battlerId) +{ + if (GetBattlerHoldEffect(battlerId, FALSE) == HOLD_EFFECT_PRIMAL_ORB + && GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE) + { + if (gBattlerAttacker == battlerId) + { + BattleScriptExecute(BattleScript_PrimalReversion); + } + else + { + // edge case for scenarios like a switch-in after activated eject button + gBattleScripting.savedBattler = gBattlerAttacker; + gBattlerAttacker = battlerId; + BattleScriptExecute(BattleScript_PrimalReversionRestoreAttacker); + } + return TRUE; + } + return FALSE; +} + bool32 IsNeutralizingGasBannedAbility(u32 ability) { switch (ability) diff --git a/test/primal_reversion.c b/test/primal_reversion.c new file mode 100644 index 0000000000..f888d17f7e --- /dev/null +++ b/test/primal_reversion.c @@ -0,0 +1,216 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Primal reversion happens for Groudon only when holding Red Orb") +{ + u16 heldItem; + PARAMETRIZE { heldItem = ITEM_NONE;} + PARAMETRIZE { heldItem = ITEM_RED_ORB;} + PARAMETRIZE { heldItem = ITEM_BLUE_ORB;} + GIVEN { + PLAYER(SPECIES_GROUDON) { Item(heldItem); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } SCENE { + if (heldItem == ITEM_RED_ORB) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player); + MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!"); + } + else { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player); + MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!"); + } + } + } THEN { + if (heldItem == ITEM_RED_ORB) { + EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL); + } + else { + EXPECT_EQ(player->species, SPECIES_GROUDON); + } + } +} + +SINGLE_BATTLE_TEST("Primal reversion happens for Kyogre only when holding Blue Orb") +{ + u16 heldItem; + PARAMETRIZE { heldItem = ITEM_NONE;} + PARAMETRIZE { heldItem = ITEM_RED_ORB;} + PARAMETRIZE { heldItem = ITEM_BLUE_ORB;} + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KYOGRE) { Item(heldItem); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + if (heldItem == ITEM_BLUE_ORB) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponent); + MESSAGE("Foe Kyogre's Primal Reversion! It reverted to its primal form!"); + } + else { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponent); + MESSAGE("Foe Kyogre's Primal Reversion! It reverted to its primal form!"); + } + } + } THEN { + if (heldItem == ITEM_BLUE_ORB) { + EXPECT_EQ(opponent->species, SPECIES_KYOGRE_PRIMAL); + } + else { + EXPECT_EQ(opponent->species, SPECIES_KYOGRE); + } + } +} + +DOUBLE_BATTLE_TEST("Primal reversion's order is determined by Speed - opponent faster") +{ + GIVEN { + PLAYER(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); Speed(5); }; + PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); Speed(15); }; + OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); Speed(10); } + OPPONENT(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); Speed(20); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponentRight); + MESSAGE("Foe Kyogre's Primal Reversion! It reverted to its primal form!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, playerRight); + MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponentLeft); + MESSAGE("Foe Groudon's Primal Reversion! It reverted to its primal form!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, playerLeft); + MESSAGE("Kyogre's Primal Reversion! It reverted to its primal form!"); + } THEN { + EXPECT_EQ(playerLeft->species, SPECIES_KYOGRE_PRIMAL); + EXPECT_EQ(opponentLeft->species, SPECIES_GROUDON_PRIMAL); + EXPECT_EQ(opponentRight->species, SPECIES_KYOGRE_PRIMAL); + EXPECT_EQ(playerRight->species, SPECIES_GROUDON_PRIMAL); + } +} + +DOUBLE_BATTLE_TEST("Primal reversion's order is determined by Speed - player faster") +{ + GIVEN { + PLAYER(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); Speed(20); }; + PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); Speed(30); }; + OPPONENT(SPECIES_GROUDON) { Item(ITEM_RED_ORB); Speed(10); } + OPPONENT(SPECIES_KYOGRE) { Item(ITEM_BLUE_ORB); Speed(2); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, playerRight); + MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, playerLeft); + MESSAGE("Kyogre's Primal Reversion! It reverted to its primal form!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponentLeft); + MESSAGE("Foe Groudon's Primal Reversion! It reverted to its primal form!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, opponentRight); + MESSAGE("Foe Kyogre's Primal Reversion! It reverted to its primal form!"); + } THEN { + EXPECT_EQ(playerLeft->species, SPECIES_KYOGRE_PRIMAL); + EXPECT_EQ(opponentLeft->species, SPECIES_GROUDON_PRIMAL); + EXPECT_EQ(opponentRight->species, SPECIES_KYOGRE_PRIMAL); + EXPECT_EQ(playerRight->species, SPECIES_GROUDON_PRIMAL); + } +} + +SINGLE_BATTLE_TEST("Primal reversion happens after a mon is sent out after a mon is fainted") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].power != 0); + PLAYER(SPECIES_WOBBUFFET) {HP(1); } + PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); } + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + MESSAGE("Wobbuffet fainted!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player); + MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!"); + } THEN { + EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL); + } +} + +SINGLE_BATTLE_TEST("Primal reversion happens after a mon is switched in") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player); + MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!"); + } THEN { + EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL); + } +} + +SINGLE_BATTLE_TEST("Primal reversion happens after a switch-in caused by Eject Button") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].power != 0); + ASSUME(gItems[ITEM_EJECT_BUTTON].holdEffect == HOLD_EFFECT_EJECT_BUTTON); + PLAYER(SPECIES_WOBBUFFET) {Item(ITEM_EJECT_BUTTON); } + PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); } + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + MESSAGE("Wobbuffet is switched out with the Eject Button!"); + MESSAGE("Go! Groudon!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player); + MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!"); + } THEN { + EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL); + } +} + +SINGLE_BATTLE_TEST("Primal reversion happens after a switch-in caused by Red Card") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].power != 0); + ASSUME(gItems[ITEM_RED_CARD].holdEffect == HOLD_EFFECT_RED_CARD); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } + OPPONENT(SPECIES_WOBBUFFET) {Item(ITEM_RED_CARD); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + MESSAGE("Foe Wobbuffet held up its Red Card against Wobbuffet!"); + MESSAGE("Groudon was dragged out!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player); + MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!"); + } THEN { + EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL); + } +} + +SINGLE_BATTLE_TEST("Primal reversion happens after the entry hazards damage") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SPIKES].effect == EFFECT_SPIKES); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_GROUDON) { Item(ITEM_RED_ORB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SPIKES); } + TURN { MOVE(opponent, MOVE_SPIKES); SWITCH(player, 1);} + } SCENE { + MESSAGE("Go! Groudon!"); + HP_BAR(player); + MESSAGE("Groudon is hurt by spikes!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_PRIMAL_REVERSION, player); + MESSAGE("Groudon's Primal Reversion! It reverted to its primal form!"); + } THEN { + EXPECT_EQ(player->species, SPECIES_GROUDON_PRIMAL); + } +} From 330e20b9e992a65667747f942bf5302aadcc3f5b Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 17 Jul 2023 11:10:13 +0200 Subject: [PATCH 02/19] Fix Protosynthesis and Quark Drive boosts (#3139) * Fix Protosynthesis and Quark Drive boosts * Added Tests + fix newly introduced bug in the PR Add unintentionally deletet break new line --- src/battle_util.c | 12 +++-- test/ability_protosynthesis.c | 87 +++++++++++++++++++++++++++++++++++ test/ability_quark_drive.c | 87 +++++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 test/ability_protosynthesis.c create mode 100644 test/ability_quark_drive.c diff --git a/src/battle_util.c b/src/battle_util.c index 105b29cacf..bcd446ce66 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8867,14 +8867,16 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe case ABILITY_PROTOSYNTHESIS: { u8 atkHighestStat = GetHighestStatId(battlerAtk); - if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT && (atkHighestStat == STAT_ATK || atkHighestStat == STAT_SPATK)) + if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT + && ((IS_MOVE_PHYSICAL(move) && atkHighestStat == STAT_ATK) || (IS_MOVE_SPECIAL(move) && atkHighestStat == STAT_SPATK))) MulModifier(&modifier, UQ_4_12(1.3)); } break; case ABILITY_QUARK_DRIVE: { u8 atkHighestStat = GetHighestStatId(battlerAtk); - if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && (atkHighestStat == STAT_ATK || atkHighestStat == STAT_SPATK)) + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN + && ((IS_MOVE_PHYSICAL(move) && atkHighestStat == STAT_ATK) || (IS_MOVE_SPECIAL(move) && atkHighestStat == STAT_SPATK))) MulModifier(&modifier, UQ_4_12(1.3)); } break; @@ -8965,14 +8967,16 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe case ABILITY_PROTOSYNTHESIS: { u8 defHighestStat = GetHighestStatId(battlerDef); - if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT && (defHighestStat == STAT_DEF || defHighestStat == STAT_SPDEF)) + if (gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT + && ((IS_MOVE_PHYSICAL(move) && defHighestStat == STAT_DEF) || (IS_MOVE_SPECIAL(move) && defHighestStat == STAT_SPDEF))) MulModifier(&modifier, UQ_4_12(0.7)); } break; case ABILITY_QUARK_DRIVE: { u8 defHighestStat = GetHighestStatId(battlerDef); - if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && (defHighestStat == STAT_DEF || defHighestStat == STAT_SPDEF)) + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN + && ((IS_MOVE_PHYSICAL(move) && defHighestStat == STAT_DEF) || (IS_MOVE_SPECIAL(move) && defHighestStat == STAT_SPDEF))) MulModifier(&modifier, UQ_4_12(0.7)); } break; diff --git a/test/ability_protosynthesis.c b/test/ability_protosynthesis.c new file mode 100644 index 0000000000..9f794e00a7 --- /dev/null +++ b/test/ability_protosynthesis.c @@ -0,0 +1,87 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + ASSUME(gBattleMoves[MOVE_ROUND].split == SPLIT_SPECIAL); +} + +SINGLE_BATTLE_TEST("Protosynthesis boosts the highest stat") +{ + GIVEN { + PLAYER(SPECIES_ABRA) { Ability(ABILITY_PROTOSYNTHESIS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player); + ABILITY_POPUP(player, ABILITY_PROTOSYNTHESIS); + MESSAGE("The harsh sunlight activated Abra's Protosynthesis!"); + MESSAGE("Abra's Sp. Atk was heightened!"); + } +} + +SINGLE_BATTLE_TEST("Protosynthesis boosts either Attack or Special Attack, not both") +{ + u16 species; + u32 move; + u16 damage[2]; + + PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_TACKLE; } + PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_ROUND; } + + PARAMETRIZE { species = SPECIES_ABRA; move = MOVE_TACKLE; } + PARAMETRIZE { species = SPECIES_ABRA; move = MOVE_ROUND; } + + GIVEN { + PLAYER(species) { Ability(ABILITY_PROTOSYNTHESIS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + TURN { MOVE(opponent, MOVE_SUNNY_DAY); MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, opponent); + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + if ((move == MOVE_TACKLE && species == SPECIES_BELLSPROUT) || (move == MOVE_ROUND && species == SPECIES_ABRA)) + EXPECT_MUL_EQ(damage[0], Q_4_12(1.3), damage[1]); + else + EXPECT_EQ(damage[0], damage[1]); + } +} + +SINGLE_BATTLE_TEST("Protosynthesis either boosts Defense or Special Defense, not both") +{ + u16 species; + u32 move; + u16 damage[2]; + + PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_TACKLE; } + PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_ROUND; } + + PARAMETRIZE { species = SPECIES_BLASTOISE; move = MOVE_TACKLE; } + PARAMETRIZE { species = SPECIES_BLASTOISE; move = MOVE_ROUND; } + + GIVEN { + PLAYER(species) { Ability(ABILITY_PROTOSYNTHESIS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + TURN { MOVE(player, MOVE_SUNNY_DAY); MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUNNY_DAY, player); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player, captureDamage: &damage[1]); + } THEN { + if ((move == MOVE_TACKLE && species == SPECIES_ONIX) || (move == MOVE_ROUND && species == SPECIES_BLASTOISE)) + EXPECT_MUL_EQ(damage[0], Q_4_12(0.7), damage[1]); + else + EXPECT_EQ(damage[0], damage[1]); + } +} diff --git a/test/ability_quark_drive.c b/test/ability_quark_drive.c new file mode 100644 index 0000000000..b004c760c4 --- /dev/null +++ b/test/ability_quark_drive.c @@ -0,0 +1,87 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + ASSUME(gBattleMoves[MOVE_ROUND].split == SPLIT_SPECIAL); +} + +SINGLE_BATTLE_TEST("Quark Drive boosts the highest stat") +{ + GIVEN { + PLAYER(SPECIES_ABRA) { Ability(ABILITY_QUARK_DRIVE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player); + ABILITY_POPUP(player, ABILITY_QUARK_DRIVE); + MESSAGE("The Electric Terrain activated Abra's Quark Drive!"); + MESSAGE("Abra's Sp. Atk was heightened!"); + } +} + +SINGLE_BATTLE_TEST("Quark Drive boosts either Attack or Special Attack, not both") +{ + u16 species; + u32 move; + u16 damage[2]; + + PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_TACKLE; } + PARAMETRIZE { species = SPECIES_BELLSPROUT; move = MOVE_ROUND; } + + PARAMETRIZE { species = SPECIES_ABRA; move = MOVE_TACKLE; } + PARAMETRIZE { species = SPECIES_ABRA; move = MOVE_ROUND; } + + GIVEN { + PLAYER(species) { Ability(ABILITY_QUARK_DRIVE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + TURN { MOVE(opponent, MOVE_ELECTRIC_TERRAIN); MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, opponent); + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent, captureDamage: &damage[1]); + } THEN { + if ((move == MOVE_TACKLE && species == SPECIES_BELLSPROUT) || (move == MOVE_ROUND && species == SPECIES_ABRA)) + EXPECT_MUL_EQ(damage[0], Q_4_12(1.3), damage[1]); + else + EXPECT_EQ(damage[0], damage[1]); + } +} + +SINGLE_BATTLE_TEST("Quark Drive either boosts Defense or Special Defense, not both") +{ + u16 species; + u32 move; + u16 damage[2]; + + PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_TACKLE; } + PARAMETRIZE { species = SPECIES_ONIX; move = MOVE_ROUND; } + + PARAMETRIZE { species = SPECIES_BLASTOISE; move = MOVE_TACKLE; } + PARAMETRIZE { species = SPECIES_BLASTOISE; move = MOVE_ROUND; } + + GIVEN { + PLAYER(species) { Ability(ABILITY_QUARK_DRIVE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player, captureDamage: &damage[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player, captureDamage: &damage[1]); + } THEN { + if ((move == MOVE_TACKLE && species == SPECIES_ONIX) || (move == MOVE_ROUND && species == SPECIES_BLASTOISE)) + EXPECT_MUL_EQ(damage[0], Q_4_12(0.7), damage[1]); + else + EXPECT_EQ(damage[0], damage[1]); + } +} From 38655b9d1f59e07f223f01125a62526351fb1ccd Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 18 Jul 2023 07:11:54 +0200 Subject: [PATCH 03/19] Fix gem boost on multi hit moves and config for gem param (#3144) --- include/config/item.h | 1 + src/battle_util.c | 6 +-- src/data/items.h | 42 ++++++++++--------- test/hold_effect_gems.c | 89 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 22 deletions(-) create mode 100644 test/hold_effect_gems.c diff --git a/include/config/item.h b/include/config/item.h index 1e174b5ff4..ad205f0034 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -10,6 +10,7 @@ #define I_VITAMIN_EV_CAP GEN_LATEST // In Gen8+, the Vitamins no longer have a cap of 100 EV per stat. #define I_BERRY_EV_JUMP GEN_LATEST // In Gen4 only, EV-lowering Berries lower a stat's EV to 100 if it is above 100. #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. // TM config diff --git a/src/battle_util.c b/src/battle_util.c index bcd446ce66..9ffb4031b8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9020,10 +9020,6 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe #endif MulModifier(&modifier, holdEffectModifier); break; - case HOLD_EFFECT_GEMS: - if (gSpecialStatuses[battlerAtk].gemBoost && gBattleMons[battlerAtk].item) - MulModifier(&modifier, UQ_4_12(1.0) + sPercentToModifier[gSpecialStatuses[battlerAtk].gemParam]); - break; case HOLD_EFFECT_BUG_POWER: case HOLD_EFFECT_STEEL_POWER: case HOLD_EFFECT_GROUND_POWER: @@ -9114,6 +9110,8 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe // various effects if (gProtectStructs[battlerAtk].helpingHand) MulModifier(&modifier, UQ_4_12(1.5)); + if (gSpecialStatuses[battlerAtk].gemBoost) + MulModifier(&modifier, UQ_4_12(1.0) + sPercentToModifier[gSpecialStatuses[battlerAtk].gemParam]); if (gStatuses3[battlerAtk] & STATUS3_CHARGED_UP && moveType == TYPE_ELECTRIC) MulModifier(&modifier, UQ_4_12(2.0)); if (gStatuses3[battlerAtk] & STATUS3_ME_FIRST) diff --git a/src/data/items.h b/src/data/items.h index a309925aad..802cd325da 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -6,6 +6,12 @@ #define EVO_HELD_ITEM_FIELD_FUNC ItemUseOutOfBattle_CannotUse #endif +#if I_GEM_BOOST_POWER >= GEN_5 + #define GEM_BOOST_PARAM 30 +#else + #define GEM_BOOST_PARAM 50 +#endif + const struct Item gItems[] = { [ITEM_NONE] = @@ -4416,7 +4422,7 @@ const struct Item gItems[] = .itemId = ITEM_NORMAL_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sNormalGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4430,7 +4436,7 @@ const struct Item gItems[] = .itemId = ITEM_FIRE_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sFireGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4444,7 +4450,7 @@ const struct Item gItems[] = .itemId = ITEM_WATER_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sWaterGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4458,7 +4464,7 @@ const struct Item gItems[] = .itemId = ITEM_ELECTRIC_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sElectricGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4472,7 +4478,7 @@ const struct Item gItems[] = .itemId = ITEM_GRASS_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sGrassGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4486,7 +4492,7 @@ const struct Item gItems[] = .itemId = ITEM_ICE_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sIceGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4500,7 +4506,7 @@ const struct Item gItems[] = .itemId = ITEM_FIGHTING_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sFightingGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4514,7 +4520,7 @@ const struct Item gItems[] = .itemId = ITEM_POISON_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sPoisonGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4528,7 +4534,7 @@ const struct Item gItems[] = .itemId = ITEM_GROUND_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sGroundGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4542,7 +4548,7 @@ const struct Item gItems[] = .itemId = ITEM_FLYING_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sFlyingGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4556,7 +4562,7 @@ const struct Item gItems[] = .itemId = ITEM_PSYCHIC_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sPsychicGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4570,7 +4576,7 @@ const struct Item gItems[] = .itemId = ITEM_BUG_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sBugGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4584,7 +4590,7 @@ const struct Item gItems[] = .itemId = ITEM_ROCK_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sRockGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4598,7 +4604,7 @@ const struct Item gItems[] = .itemId = ITEM_GHOST_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sGhostGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4612,7 +4618,7 @@ const struct Item gItems[] = .itemId = ITEM_DRAGON_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sDragonGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4626,7 +4632,7 @@ const struct Item gItems[] = .itemId = ITEM_DARK_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sDarkGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4640,7 +4646,7 @@ const struct Item gItems[] = .itemId = ITEM_STEEL_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sSteelGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -4654,7 +4660,7 @@ const struct Item gItems[] = .itemId = ITEM_FAIRY_GEM, .price = 4000, .holdEffect = HOLD_EFFECT_GEMS, - .holdEffectParam = 30, + .holdEffectParam = GEM_BOOST_PARAM, .description = sFairyGemDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, diff --git a/test/hold_effect_gems.c b/test/hold_effect_gems.c new file mode 100644 index 0000000000..9a90b81f9d --- /dev/null +++ b/test/hold_effect_gems.c @@ -0,0 +1,89 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_NORMAL_GEM].holdEffect == HOLD_EFFECT_GEMS); +} + +SINGLE_BATTLE_TEST("Gem is consumed when it corresponds to the type of a move") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMAL_GEM); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_EMBER); } + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Fire Gem strengthened Wobbuffet's power!"); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Normal Gem strengthened Wobbuffet's power!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + } +} + +SINGLE_BATTLE_TEST("Gem boost is only applied once") +{ + s16 boostedHit; + s16 normalHit; + + GIVEN { + ASSUME(I_GEM_BOOST_POWER >= GEN_5); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMAL_GEM); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Normal Gem strengthened Wobbuffet's power!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &boostedHit); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &normalHit); + } THEN { + EXPECT_MUL_EQ(normalHit, Q_4_12(1.3), boostedHit); + } +} + +SINGLE_BATTLE_TEST("Gem modifier is used for all hits of Multi Hit Moves") +{ + s16 firstHit; + s16 secondHit; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMAL_GEM); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(player, MOVE_DOUBLE_HIT); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_HIT, player); + HP_BAR(opponent, captureDamage: &firstHit); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_HIT, player); + HP_BAR(opponent, captureDamage: &secondHit); + } THEN { + EXPECT_EQ(firstHit, secondHit); + } +} + +SINGLE_BATTLE_TEST("Gem is consumed if the move type is changed") +{ + GIVEN { + PLAYER(SPECIES_DELCATTY) { Ability(ABILITY_NORMALIZE); Item(ITEM_NORMAL_GEM); }; + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { + MOVE(player, MOVE_FEINT_ATTACK); + } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Normal Gem strengthened Delcatty's power!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FEINT_ATTACK, player); + } +} From b08c8f85fc7803c32cae70048d9eec3adaf91d1f Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Tue, 18 Jul 2023 03:22:05 -0400 Subject: [PATCH 04/19] Fixed Utility Umbrella damage calculations (#2835) * Fixed Utility Umbrella holders not receiving regular damage when being hurt by what would've been weakened rain/sun attacks * Fixed reading move incorrectly * Tests: Sun, Rain, Utility Umbrella and Hydro Steam * [STASH] Skeli changes, needs to remake tests * Fixed tests * Removed redundant tests * Removed unused variable * Removed Primal Todo tests --- include/battle_util.h | 1 + src/battle_util.c | 53 ++++++++++++++++++---------- test/hold_effect_utility_umbrella.c | 54 +++++++++++++++++++++++++++++ test/move_effect_hydro_steam.c | 50 ++++++++++++++++++++++++++ test/weather_rain.c | 47 +++++++++++++++++++++++++ test/weather_sunlight.c | 47 +++++++++++++++++++++++++ 6 files changed, 234 insertions(+), 18 deletions(-) create mode 100644 test/hold_effect_utility_umbrella.c create mode 100644 test/move_effect_hydro_steam.c create mode 100644 test/weather_rain.c create mode 100644 test/weather_sunlight.c diff --git a/include/battle_util.h b/include/battle_util.h index aba215c129..15fbe2432d 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -210,6 +210,7 @@ void BufferStatChange(u8 battlerId, u8 statId, u8 stringId); bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef, bool32 checkTarget); u16 GetUsedHeldItem(u8 battler); bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags); +u32 ApplyWeatherDamageMultiplier(u8 battlerAtk, u16 move, u8 moveType, u32 dmg, u16 holdEffectAtk, u16 holdEffectDef); u32 GetBattlerMoveTargetType(u8 battlerId, u16 move); bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move); bool8 IsMoveAffectedByParentalBond(u16 move, u8 battlerId); diff --git a/src/battle_util.c b/src/battle_util.c index 9ffb4031b8..495f26cd50 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9508,6 +9508,8 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move u32 defSide = GET_BATTLER_SIDE(battlerDef); u16 finalModifier = UQ_4_12(1.0); u16 itemDef = gBattleMons[battlerDef].item; + u16 holdEffectAtk = GetBattlerHoldEffect(battlerAtk, TRUE); + u16 holdEffectDef = GetBattlerHoldEffect(battlerDef, TRUE); // check multiple targets in double battle if (GetMoveTargetCount(move, battlerAtk, battlerDef) >= 2) @@ -9537,28 +9539,15 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move dmg = ApplyModifier(UQ_4_12(0.5), dmg); // check frostbite - if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && !IS_MOVE_PHYSICAL(move) + if (gBattleMons[battlerAtk].status1 & STATUS1_FROSTBITE && IS_MOVE_SPECIAL(move) #if B_BURN_FACADE_DMG >= GEN_6 && gBattleMoves[move].effect != EFFECT_FACADE #endif && abilityAtk != ABILITY_GUTS) dmg = ApplyModifier(UQ_4_12(0.5), dmg); - // check sunny/rain weather - if (IsBattlerWeatherAffected(battlerAtk, B_WEATHER_RAIN)) - { - if (moveType == TYPE_FIRE) - dmg = ApplyModifier(UQ_4_12(0.5), dmg); - else if (moveType == TYPE_WATER) - dmg = ApplyModifier(UQ_4_12(1.5), dmg); - } - else if (IsBattlerWeatherAffected(battlerAtk, B_WEATHER_SUN)) - { - if (moveType == TYPE_FIRE || gBattleMoves[move].effect == EFFECT_HYDRO_STEAM) - dmg = ApplyModifier(UQ_4_12(1.5), dmg); - else if (moveType == TYPE_WATER) - dmg = ApplyModifier(UQ_4_12(0.5), dmg); - } + // check weather + dmg = ApplyWeatherDamageMultiplier(battlerAtk, move, moveType, dmg, holdEffectAtk, holdEffectDef); // check stab if (IS_BATTLER_OF_TYPE(battlerAtk, moveType) && move != MOVE_STRUGGLE && move != MOVE_NONE) @@ -9643,7 +9632,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move } // attacker's hold effect - switch (GetBattlerHoldEffect(battlerAtk, TRUE)) + switch (holdEffectAtk) { case HOLD_EFFECT_METRONOME: percentBoost = min((gBattleStruct->sameMoveTurns[battlerAtk] * GetBattlerHoldEffectParam(battlerAtk)), 100); @@ -9659,7 +9648,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move } // target's hold effect - switch (GetBattlerHoldEffect(battlerDef, TRUE)) + switch (holdEffectDef) { // berries reducing dmg case HOLD_EFFECT_RESIST_BERRY: @@ -10858,6 +10847,34 @@ bool32 IsBattlerWeatherAffected(u8 battlerId, u32 weatherFlags) return FALSE; } +// Utility Umbrella holders take normal damage from what would be rain- and sun-weakened attacks. +u32 ApplyWeatherDamageMultiplier(u8 battlerAtk, u16 move, u8 moveType, u32 dmg, u16 holdEffectAtk, u16 holdEffectDef) +{ + if (WEATHER_HAS_EFFECT) + { + if (gBattleMoves[move].effect == EFFECT_HYDRO_STEAM && (gBattleWeather & B_WEATHER_SUN) && holdEffectAtk != HOLD_EFFECT_UTILITY_UMBRELLA) + dmg = ApplyModifier(UQ_4_12(1.5), dmg); + else if (holdEffectDef != HOLD_EFFECT_UTILITY_UMBRELLA) + { + if (gBattleWeather & B_WEATHER_RAIN) + { + if (moveType == TYPE_FIRE) + dmg = ApplyModifier(UQ_4_12(0.5), dmg); + else if (moveType == TYPE_WATER) + dmg = ApplyModifier(UQ_4_12(1.5), dmg); + } + else if (gBattleWeather & B_WEATHER_SUN) + { + if (moveType == TYPE_FIRE) + dmg = ApplyModifier(UQ_4_12(1.5), dmg); + else if (moveType == TYPE_WATER) + dmg = ApplyModifier(UQ_4_12(0.5), dmg); + } + } + } + return dmg; +} + // Gets move target before redirection effects etc. are applied // Possible return values are defined in battle.h following MOVE_TARGET_SELECTED u32 GetBattlerMoveTargetType(u8 battlerId, u16 move) diff --git a/test/hold_effect_utility_umbrella.c b/test/hold_effect_utility_umbrella.c new file mode 100644 index 0000000000..6716ee72fd --- /dev/null +++ b/test/hold_effect_utility_umbrella.c @@ -0,0 +1,54 @@ +#include "global.h" +#include "test_battle.h" + +// Please add Utility Umbrella interactions with move, item and ability effects on their respective files. +ASSUMPTIONS +{ + ASSUME(gItems[ITEM_UTILITY_UMBRELLA].holdEffect == HOLD_EFFECT_UTILITY_UMBRELLA); + ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE); + ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER); +} + +SINGLE_BATTLE_TEST("Utility Umbrella blocks Sun damage modifiers", s16 damage) +{ + u16 setupMove, attackingMove, heldItem; + PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_EMBER; heldItem = ITEM_UTILITY_UMBRELLA; } + PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_EMBER; heldItem = ITEM_NONE; } + PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_UTILITY_UMBRELLA; } + PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_NONE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(heldItem); }; + } WHEN { + TURN { MOVE(opponent, setupMove); } + TURN { MOVE(player, attackingMove); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, attackingMove, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[3].damage); + } +} + +SINGLE_BATTLE_TEST("Utility Umbrella blocks Rain damage modifiers", s16 damage) +{ + u16 setupMove, attackingMove, heldItem; + PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_EMBER; heldItem = ITEM_UTILITY_UMBRELLA; } + PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_EMBER; heldItem = ITEM_NONE; } + PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_UTILITY_UMBRELLA; } + PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; attackingMove = MOVE_WATER_GUN; heldItem = ITEM_NONE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(heldItem); }; + } WHEN { + TURN { MOVE(opponent, setupMove); } + TURN { MOVE(player, attackingMove); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, attackingMove, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); + } +} diff --git a/test/move_effect_hydro_steam.c b/test/move_effect_hydro_steam.c new file mode 100644 index 0000000000..4874491594 --- /dev/null +++ b/test/move_effect_hydro_steam.c @@ -0,0 +1,50 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_HYDRO_STEAM].effect == EFFECT_HYDRO_STEAM); +} + +SINGLE_BATTLE_TEST("Hydro Steam deals 1.5x damage under both Sunlight and Rain", s16 damage) +{ + u16 setupMove; + PARAMETRIZE { setupMove = MOVE_CELEBRATE; } + PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; } + PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, setupMove); } + TURN { MOVE(player, MOVE_HYDRO_STEAM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HYDRO_STEAM, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[2].damage); + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Hydro Steam is affected by Utility Umbrella", s16 damage) +{ + u32 itemPlayer; + u32 itemOpponent; + PARAMETRIZE { itemPlayer = ITEM_UTILITY_UMBRELLA; itemOpponent = ITEM_NONE; } + PARAMETRIZE { itemPlayer = ITEM_NONE; itemOpponent = ITEM_UTILITY_UMBRELLA; } + PARAMETRIZE { itemPlayer = ITEM_UTILITY_UMBRELLA; itemOpponent = ITEM_UTILITY_UMBRELLA; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(itemPlayer); }; + OPPONENT(SPECIES_WOBBUFFET) {Item(itemOpponent); }; + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); } + TURN { MOVE(player, MOVE_HYDRO_STEAM); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HYDRO_STEAM, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(0.5), results[0].damage); + } +} diff --git a/test/weather_rain.c b/test/weather_rain.c new file mode 100644 index 0000000000..b996814951 --- /dev/null +++ b/test/weather_rain.c @@ -0,0 +1,47 @@ +#include "global.h" +#include "test_battle.h" + +// Please add Rain interactions with move, item and ability effects on their respective files. +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE); + ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER); +} + +SINGLE_BATTLE_TEST("Rain multiplies the power of Fire-type moves by 0.5x", s16 damage) +{ + u32 setupMove; + PARAMETRIZE { setupMove = MOVE_CELEBRATE; } + PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, setupMove); } + TURN { MOVE(player, MOVE_EMBER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Rain multiplies the power of Water-type moves by 1.5x", s16 damage) +{ + u32 setupMove; + PARAMETRIZE { setupMove = MOVE_CELEBRATE; } + PARAMETRIZE { setupMove = MOVE_RAIN_DANCE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, setupMove); } + TURN { MOVE(player, MOVE_WATER_GUN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} diff --git a/test/weather_sunlight.c b/test/weather_sunlight.c new file mode 100644 index 0000000000..beba0e9b6b --- /dev/null +++ b/test/weather_sunlight.c @@ -0,0 +1,47 @@ +#include "global.h" +#include "test_battle.h" + +// Please add Sunlight interactions with move, item and ability effects on their respective files. +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE); + ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER); +} + +SINGLE_BATTLE_TEST("Sunlight multiplies the power of Fire-type moves by 1.5x", s16 damage) +{ + u32 setupMove; + PARAMETRIZE { setupMove = MOVE_CELEBRATE; } + PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, setupMove); } + TURN { MOVE(player, MOVE_EMBER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Sunlight multiplies the power of Water-type moves by 0.5x", s16 damage) +{ + u32 setupMove; + PARAMETRIZE { setupMove = MOVE_CELEBRATE; } + PARAMETRIZE { setupMove = MOVE_SUNNY_DAY; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, setupMove); } + TURN { MOVE(player, MOVE_WATER_GUN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + } +} From 219ac7830c86ca5e1473ac61ec83d10b45d18cd4 Mon Sep 17 00:00:00 2001 From: CyanSMP64 <48017633+CyanSMP64@users.noreply.github.com> Date: Wed, 19 Jul 2023 04:56:15 +1200 Subject: [PATCH 05/19] Update female Alakazam's front sprite design (#3149) --- graphics/pokemon/alakazam/anim_frontf.png | Bin 1143 -> 1270 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/graphics/pokemon/alakazam/anim_frontf.png b/graphics/pokemon/alakazam/anim_frontf.png index 123b8f9304caaba15c3d7230571d0e075aa1bc95..f7de540512fd3eee531e7ed16f20d7016f317526 100644 GIT binary patch delta 1191 zcmV;Y1X%m`2=)n(Bv%J?Nliru=LZrGEH?#pO9B7@02g#cSaefwW^{L9a%BKVOhiyl zM<8}(av(DOV1ZP1_K>z@;j|==^1(6{> ze*ghuOGiWihy@);000CUNklSp5FtHo8Gz(Y(_{l^9Ov1E1PGHW0svP@LjL&OzNY;#oF0Y} z41E?$2Sl>B!ce7L5+-*!V%}jOe+jV3xqK6k0MT zh99Oh!!hU6?A&)Ayh?K5*b)qpX%X$F*)GLZA*NJwFDy!NyvV;kP}?zBe^K0I%p==W z+ok~YqGH;oQ8Z+FLIp>@LlZN(h#TuQiJl2&&8Xgi+_3={+z#q~%3&C2sycN3CJ{2} zVspzN222NKg6YvVlU^3Ew&^1USOKHXI`#mTkO~lm2RnX^1BLKtkZxaPgFm>3-du|s&g*8}|dfAT=6+^AZ(io5>7cQ5yfp{bmGz$#5vR|OCzNly;5WVR|s zmSR?I>B?;6b^*}o?iqop9gw%HdUtE2ZZHn{$eJp5cL;Uzi_83ne8Jj;vAO)V&ed|X z?>QsCyYgQ7ih9s|FDLu3vZqMP6l0T~zXNz@h>$In_0kot3U+qp{RKT6U`1=J03vU+~1l%q# z^85E@fsxxS0;4bulW%_P6&R)8g7D~~E-+eUcnk2^*<~p()brX5Fu0ye?|7*Id-Nd@ zv232R>vZ4Vp1#g7z9DsBs|UIP z>~ro9aU76FNJGBV z%ycI>Rstig%a_XNnVFOVqb^@+K!&Bj@cQHnd#4rXIik0}MI&D-%LN8n9r?1EODQmV zjFdX7Z{a($OT3>!kvC7+x|WM@E3E8!o5vHIHLdn002ovPDHLk FV1gO%AtV3* delta 1066 zcmV+_1l9ZY3HJz)B$0kQe*^+aL_t(o!|j&8Z`(!`$0?M^phe;j1xOnp;8FPlPVc6+ zKq>KsfD;9R0_Z;=4sjR#4c(H_fDn|EQ`G3tcrohD?O;HY!E70={~<^Wp`O%tBrTED z+1`Qx^#O({z7Ox-eedqw*D$_hYqW0zyxRc3+=Zn9m?-_=I$-m%f6)_~F?xQmj;|lf z&Gw7W8a4whP`su%(~Y12(XiSo?rVW>7+5y*D6SuYrr|xFFy`F=u*u{Fg|8WbqN(1b%H2^!w$2xFH88D?0 z^FRUnwfLVh8Tb$?f50W6o7B2!{{4rHLwKf^;TWLD>Rr71XD(&ze0RjWAC9(xRrCE~ zjzskOj3566;9`=z*=S)U7wP#NhzL1zEIAX0f0*>DIQ<#YuX>( z;XxFFWsa=S10knNj8w|j)jskWV)lXM69C@*c<~|b1FTk8e_NFa9>o-A-O%UAyyqw9 zf$?ZnXkq(9M*sn|Uv_3(Bm<^^mP#~MfWzESAmvQCT+T@3S+BcD1M30JG%ik@8A+r8 zSg=gg3I>JDTPhND5)^4J{qiK=mJj$gwoM-Q2i9I!Y%d|Lr};85}VF@I_Dw2u$ZD)r+C>DU7nnW?RUPb&Z#Pfwi9~4RU9?UrI446l5!x2@0YB8SS Date: Wed, 19 Jul 2023 03:31:22 +0200 Subject: [PATCH 06/19] Gender differences sprites, final part (#3122) * The last survivors * Tweaked Numel, Milotic and Relicanth Updated their sprites according to their current depictions. --------- Co-authored-by: Eduardo Quezada D'Ottone --- graphics/pokemon/abomasnow/anim_frontf.png | Bin 0 -> 1688 bytes graphics/pokemon/bibarel/anim_front.png | Bin 1175 -> 1143 bytes graphics/pokemon/bibarel/anim_frontf.png | Bin 0 -> 1138 bytes graphics/pokemon/bibarel/normal.pal | 2 +- graphics/pokemon/bidoof/anim_frontf.png | Bin 781 -> 741 bytes graphics/pokemon/bidoof/backf.png | Bin 504 -> 466 bytes graphics/pokemon/buizel/backf.png | Bin 0 -> 596 bytes graphics/pokemon/cacturne/anim_frontf.png | Bin 0 -> 1440 bytes graphics/pokemon/camerupt/anim_front.png | Bin 1464 -> 1409 bytes graphics/pokemon/camerupt/anim_frontf.png | Bin 0 -> 1424 bytes graphics/pokemon/camerupt/back.png | Bin 652 -> 602 bytes graphics/pokemon/camerupt/backf.png | Bin 0 -> 652 bytes graphics/pokemon/croagunk/anim_frontf.png | Bin 0 -> 798 bytes graphics/pokemon/croagunk/backf.png | Bin 0 -> 520 bytes graphics/pokemon/finneon/anim_frontf.png | Bin 0 -> 686 bytes graphics/pokemon/finneon/backf.png | Bin 0 -> 647 bytes graphics/pokemon/floatzel/anim_front.png | Bin 1484 -> 1430 bytes graphics/pokemon/floatzel/backf.png | Bin 0 -> 641 bytes graphics/pokemon/gulpin/anim_frontf.png | Bin 0 -> 612 bytes graphics/pokemon/gulpin/backf.png | Bin 0 -> 431 bytes graphics/pokemon/kricketot/anim_front.png | Bin 963 -> 928 bytes graphics/pokemon/kricketot/anim_frontf.png | Bin 974 -> 941 bytes graphics/pokemon/kricketot/backf.png | Bin 562 -> 519 bytes graphics/pokemon/kricketune/backf.png | Bin 759 -> 722 bytes graphics/pokemon/lumineon/anim_frontf.png | Bin 0 -> 1148 bytes graphics/pokemon/lumineon/backf.png | Bin 0 -> 696 bytes graphics/pokemon/luxio/anim_front.png | Bin 1179 -> 1138 bytes graphics/pokemon/luxio/anim_frontf.png | Bin 0 -> 1111 bytes graphics/pokemon/luxio/backf.png | Bin 0 -> 658 bytes graphics/pokemon/luxray/anim_front.png | Bin 1521 -> 1489 bytes graphics/pokemon/luxray/anim_frontf.png | Bin 0 -> 1450 bytes graphics/pokemon/luxray/backf.png | Bin 0 -> 768 bytes graphics/pokemon/luxray/normal.pal | 2 +- graphics/pokemon/milotic/anim_front.png | Bin 1673 -> 1601 bytes graphics/pokemon/milotic/anim_frontf.png | Bin 0 -> 1651 bytes graphics/pokemon/milotic/back.png | Bin 712 -> 696 bytes graphics/pokemon/milotic/backf.png | Bin 0 -> 672 bytes graphics/pokemon/numel/anim_front.png | Bin 794 -> 748 bytes graphics/pokemon/numel/anim_frontf.png | Bin 0 -> 763 bytes graphics/pokemon/numel/back.png | Bin 601 -> 554 bytes graphics/pokemon/numel/backf.png | Bin 0 -> 601 bytes graphics/pokemon/pachirisu/anim_frontf.png | Bin 0 -> 811 bytes graphics/pokemon/relicanth/anim_front.png | Bin 1257 -> 1236 bytes graphics/pokemon/relicanth/anim_frontf.png | Bin 0 -> 1257 bytes graphics/pokemon/relicanth/backf.png | Bin 0 -> 649 bytes graphics/pokemon/roselia/anim_front.png | Bin 1150 -> 1094 bytes graphics/pokemon/roselia/anim_frontf.png | Bin 0 -> 1095 bytes graphics/pokemon/roselia/backf.png | Bin 0 -> 736 bytes graphics/pokemon/roserade/anim_front.png | Bin 1288 -> 1248 bytes graphics/pokemon/roserade/anim_frontf.png | Bin 0 -> 1264 bytes graphics/pokemon/roserade/backf.png | Bin 0 -> 789 bytes graphics/pokemon/shinx/anim_front.png | Bin 906 -> 860 bytes graphics/pokemon/shinx/anim_frontf.png | Bin 901 -> 853 bytes graphics/pokemon/shinx/back.png | Bin 669 -> 633 bytes graphics/pokemon/shinx/backf.png | Bin 666 -> 626 bytes graphics/pokemon/snover/anim_frontf.png | Bin 0 -> 987 bytes graphics/pokemon/snover/backf.png | Bin 0 -> 583 bytes graphics/pokemon/staraptor/anim_frontf.png | Bin 1322 -> 1282 bytes graphics/pokemon/staravia/anim_frontf.png | Bin 1018 -> 978 bytes graphics/pokemon/staravia/backf.png | Bin 707 -> 667 bytes graphics/pokemon/starly/anim_front.png | Bin 926 -> 889 bytes graphics/pokemon/starly/anim_frontf.png | Bin 915 -> 890 bytes graphics/pokemon/starly/back.png | Bin 630 -> 592 bytes graphics/pokemon/starly/backf.png | Bin 629 -> 586 bytes graphics/pokemon/starly/shiny.pal | 4 +- graphics/pokemon/swalot/anim_frontf.png | Bin 0 -> 1108 bytes graphics/pokemon/swalot/backf.png | Bin 0 -> 582 bytes graphics/pokemon/toxicroak/anim_frontf.png | Bin 0 -> 1266 bytes graphics/pokemon/toxicroak/backf.png | Bin 0 -> 622 bytes include/graphics.h | 36 ++++++++++++++++++ src/data/graphics/pokemon.h | 36 ++++++++++++++++++ .../pokemon_graphics/back_pic_coordinates.h | 2 +- src/data/pokemon_graphics/back_pic_table.h | 27 ++++++++----- src/data/pokemon_graphics/front_pic_table.h | 20 +++++++++- 74 files changed, 113 insertions(+), 16 deletions(-) create mode 100644 graphics/pokemon/abomasnow/anim_frontf.png create mode 100644 graphics/pokemon/bibarel/anim_frontf.png create mode 100644 graphics/pokemon/buizel/backf.png create mode 100644 graphics/pokemon/cacturne/anim_frontf.png create mode 100644 graphics/pokemon/camerupt/anim_frontf.png create mode 100644 graphics/pokemon/camerupt/backf.png create mode 100644 graphics/pokemon/croagunk/anim_frontf.png create mode 100644 graphics/pokemon/croagunk/backf.png create mode 100644 graphics/pokemon/finneon/anim_frontf.png create mode 100644 graphics/pokemon/finneon/backf.png create mode 100644 graphics/pokemon/floatzel/backf.png create mode 100644 graphics/pokemon/gulpin/anim_frontf.png create mode 100644 graphics/pokemon/gulpin/backf.png create mode 100644 graphics/pokemon/lumineon/anim_frontf.png create mode 100644 graphics/pokemon/lumineon/backf.png create mode 100644 graphics/pokemon/luxio/anim_frontf.png create mode 100644 graphics/pokemon/luxio/backf.png create mode 100644 graphics/pokemon/luxray/anim_frontf.png create mode 100644 graphics/pokemon/luxray/backf.png create mode 100644 graphics/pokemon/milotic/anim_frontf.png create mode 100644 graphics/pokemon/milotic/backf.png create mode 100644 graphics/pokemon/numel/anim_frontf.png create mode 100644 graphics/pokemon/numel/backf.png create mode 100644 graphics/pokemon/pachirisu/anim_frontf.png create mode 100644 graphics/pokemon/relicanth/anim_frontf.png create mode 100644 graphics/pokemon/relicanth/backf.png create mode 100644 graphics/pokemon/roselia/anim_frontf.png create mode 100644 graphics/pokemon/roselia/backf.png create mode 100644 graphics/pokemon/roserade/anim_frontf.png create mode 100644 graphics/pokemon/roserade/backf.png create mode 100644 graphics/pokemon/snover/anim_frontf.png create mode 100644 graphics/pokemon/snover/backf.png create mode 100644 graphics/pokemon/swalot/anim_frontf.png create mode 100644 graphics/pokemon/swalot/backf.png create mode 100644 graphics/pokemon/toxicroak/anim_frontf.png create mode 100644 graphics/pokemon/toxicroak/backf.png diff --git a/graphics/pokemon/abomasnow/anim_frontf.png b/graphics/pokemon/abomasnow/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..49fdfb706a5f44176f82ccb8870e1c70a90e85de GIT binary patch literal 1688 zcmV;J250$+P)y>Ht%7>8{L+AG_`tppzrw(lLNRDRT{xZpJ7Qb7PT<^5ILGU+>fF;R|}NfBm0dtbNlI2VwLQuv6Fe z!*Rq~h;RE($4L`_Gfsf8|4)xm8YI(@yI#{BKBBU}v;pK&EPI17fH!W0(TMYz=%o#S z(sX>#5!`-9l$TOw4cTpruxVMV++_; zEQd0{8Gv(&{2}D$Nr9zYujP6rSNLmYc{b+S05Uu}PjnH@WV#{%F|KvQcJ=rOAZ;(# zI>xZGT;@{X-&$vy$+!Xbf6?@n@v>UTnbcXPOYCW;&$R=j1<)_9nATaTOKe9@mF7Hn zss_rqyu@&&7WgHlb^)-)_7iatmsbc=ib|SJr90INW&kBl3@|&n)}3}jVqK(CZ>~-@ zLZDqLq02@4x_OMz5?^faX|v*jb?%`ja9&pS=Tv6J)vR-0X8^E@M40_pJpnwiK>u9U z-wLZP7EeaVX&+7F8s#Mu?MZqIja^6`fT2=36QVsvtS{0Az)&Z+;q4&+l=T!$f0SA0 zS1^55<w^Hki z%YgGB+5+4Fba)l6z1Ew{&K&eP=b=69U^ze95HQ?s*a3h;cR>hvzu8QJ_J$t(M%@s2 zV}N}co*>aob9=&ROUlA z@6G|MGGX<6n1}xCSvIa~Jcc0A57PbKj{vXtuYKaRMql*AvSk?0fhPTvVfe?-0h|6! zY3ZjgECi+hV;}2@NU7`sfdeErY_g+4)YLN3Vmms6`+ zN#jwTxWw-x03wk|)c{VDyf`a?oCu7Ad?9tw1z4;lQoGm?Ah4tkI8U5M!4GWmzY+^U zegI$>4LWfirS(24jUE_3K-!t^!n6o*9%XV3h-)hVc{bH&+-Q#VD60p``T-^QvZw*$ zQAM?KiPt9AT+(tJS%A95RjmgmQYzysoBL`_inZAUo0_daG=Psh$xQaoYyBW<7B?!! z7@NhU4>t4W))1D9M#YSRWUDP;#*hprZ+nGjTf@rTwN iUiJs}zd!u9{NW$Cds9yrOsuT{0000 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 diff --git a/graphics/pokemon/bibarel/anim_frontf.png b/graphics/pokemon/bibarel/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..a15a6b5f895fb7772688a6318c894338390a6869 GIT binary patch literal 1138 zcmV-&1daQNP)zi-<{6vriSD&Qfc90LWq@KG5Ic%XT58v$A*UWbgTam=D6jd^hP7V#dS z*3hX+UA&h6L8p#ImLQ4+5V$`o?~amqq)u}8`T>M~ybtf*{rrAAoyTZJ*MD+2A3*5u zPczB`q-@{YJ;8wU=ps9JcN1I)Aw`x8aT&UZE<6?MxP-_Jyu1}cKYM`5)9ZOI^z#Zr zR|zn_eog>A0X%W_0O9pqDQY1L`i_x$0R36{_rJwTOldM=M+pEg@Grzd=-F~qIRHQt z@4*dt916q|i{ENMDP<7}Ap7p^`A`ErQ-h-RlntCM<~Q%~696+SdSrV1XpLi#5}>Hs z0oN^*1}Lo6_W8}tPkam!*Fe>P4RiuOWt{Wgzy_>7x*&Yc$G#*e+Vs#U;+YV>eCrIAgKYhs(}$MG{8QE`lIT@8bqfvESP>1D{dF)o-vac zjv7F09~~3y%#;FYyN3Xpk+vFe1Ixy?cL4EzfNOxY&K~`(qxzDz^7`ymdCn*LOWMj4 z(2U;BB{9&iF~*K7VCRbPD97}_71G;1{{F7)X@c9K;NrBKcLe7!lmuUG)0L2Al^^G z=^wlaoFe*ktS4@uGnkx~=Wlz%67~QdoGzZ<&PPK^hpxjtSpZS>Ccc4w zBG#fu70P-ddX&)ifYr*}1e(HF*@N;<%33^Kz)IF0q}x>1wfb8o#d8Ddb?3hVfy*A) z0^d~k{svff9suG80M_yc+dNO(`DzrEJJ27!cHTA+IvCZ*cKtye@vguRjICJvht#Fm z6bJl6XINrc`v=Djz{-Mc(86-d7Qrm^ut8w#Q92#*1w?f(bnuk=*8l(j07*qoM6N<$ Ef<8A9`~Uy| literal 0 HcmV?d00001 diff --git a/graphics/pokemon/bibarel/normal.pal b/graphics/pokemon/bibarel/normal.pal index 71a5f280ae..cc531ec662 100644 --- a/graphics/pokemon/bibarel/normal.pal +++ b/graphics/pokemon/bibarel/normal.pal @@ -10,7 +10,7 @@ JASC-PAL 168 144 120 192 192 176 248 248 248 -56 48 40 +98 82 57 232 64 32 176 24 16 64 56 48 diff --git a/graphics/pokemon/bidoof/anim_frontf.png b/graphics/pokemon/bidoof/anim_frontf.png index c5e7b97c113913e26ec319db63098e4335c83c1a..16f873bc2d815cba1a6a42ab33bb3291914b4205 100644 GIT binary patch delta 707 zcmV;!0zCbV2IU2iE`Jc1U@*XlKwwBP5D*Z^xPbWRxcK<^SU@P~SV+jYfXKkWfPjDi z0000003~?_+W-Ipa7jc#R9M69ma&f0KoEx4Qru@9QbeM_YZ+>1E|(TvLZ3LdIi*DC zeD&!>%nKkv#}(0OOIqH7f-Vnm1rNhaOycv-BuLOuc$$?mzkg@`9Xt9)sW#g9*U6Ef0$Sn5H=OT|jK2VYoAMo{DjgeC zRGydRdVB|?o_{QORg@U(o5~~@-^9iEGYLLC07N@M?B8K*N$~y(J>c6Mn$)*=Ufw$Q zP_8SRf&gv@4&#odj2(P|%3=wA7cUj$H+~( z{rQ9PdEW+X3^?qI^wZ-aNXId*AGp{J#O0voBCZgU zqUNHOpnuokVoxIPQ!e6up;?J07c({ukBbSrtj|S&7bm%xF@eWLSg;liE@BrSISnq7 zz`tgLiwkL#4KAX9jk3W-zCSd%X!v^2%qhv&gIx)& zQ?1|9EshBA(Xc4c=2F-nC{}K!mMBOIVSk_sc0BV%f0) pGqXzCA8LZDKM`ED1aIT-;}^Ae>0qjFkV60f002ovPDHLkV1i)KPTBwf delta 725 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 delta 1326 zcmV+}1=0F}3%CoAUpW8?a7bBm001r{001r{0eGc9b^rhX2XskIMF-~w2LUP!vK^+k z000FWNklzi#6;7{Fzba1;S-k%cdRPQ?vJ12(Mh$4?(Aiu@_cr`9x0lRwAe zCbm0{(!yBNP8;Ga(-@d`M`Ru8%p_0Qk_==D@_Xn=*8LABr$q$RA^j zoMQkQAd>@wL!dpGm=JN{KK$ok9Ibxe&H)pjYx*I8@fZND1Eu2bcZ5twm-4jFJGDyo6M_WN74PUW%%RHcly`U8FG8md0dIVSSmV3$n|YB znl5g_-s@fxI5nWv`w6B%LueGzlrCNeX;cH~Fr6l-J=W1EqLd?)Rd2DN9t}g|%(twR z$`(;}y${C##Bk-toD^|rthh(&Ea(z{uFT4ygCEs;ulK+Sj4MrHW}ERgY7QXei45=+@ZS8NSaPbx<2Ew>mJ!ic#`87VX=6-aXY^zU zf-pl~r3hC?#sDE}MtF!{CPb0BWCj(9=3Og9c7%Q}M6w{C2*TqXu{cJ5R01lSL!9hi z974zd5(@wbzR&Vg1xFuLk z0wToXR7ZUdoE`%#NW%d`Y4Qiy2P|#};7LZ4fS?>O&wYG2&^GRKf6!c{8LmG$090af zL+Sc24SeDDu{FGY>OjPXDen9Bu;*H6-mB?>;>hrbXEFZ^a|^bG)VL5Rx3U+f$sx|o9JxL$eu zmPJUxNJG7ESK<`|$ps^vnpJ`M)<2$6@Yh#f)S6719id3_{nxB271D`)~AB8 z%CZ9BqdpLf)tUo;TLJLPxnRu8^lSJ;TgLY*byNrjoiB>?D*=cqRj&{X8ZP$fB`}jK zr4$VQj6`}4uq~5IVlNoHT+jm%%mJ}$mx95B9_)cP+f5SG1%n7Z*aNrQP0Z?oAy0n+ ztg{W=Ar77hMggqWcT66h@u6S{;7%Oyj_NfC1|KF9egXMqg+DwI3|?Y>zB`4}R|R90 z75?Bf3&wWy-vlH1H^K0p5sXAS!coECKe1O9aUd9wJr@k8SunuqYW|Q5#xSl3M%^Ez kU_9p!TrfWS!>8Z=0ZwzEff+uW7XSbN07*qoM6N<$f&_nHk^lez diff --git a/graphics/pokemon/camerupt/anim_frontf.png b/graphics/pokemon/camerupt/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..b746a2d18721466ee6f30b80f8cbfef7d3941b86 GIT binary patch literal 1424 zcmV;B1#kL^P)zi#6;7{FyfIAn}uyIs17Qrs>bBA(mf7Fi)|O#y00V}ZmqY)u6YHAMMt zD+Gy1AHb(Pf#J14Gu+hS`UG8XGcx8G`jM3NCzjJr#SKRTHmvW*Pai3Y{3*(()-+9% zKgZ%GwmXi}!dTNz8{#d~7?^fPX(5CRs|nCC^tF_(k2%)>_|Vnnz{IqhGIV_(iZEKp zA7hN1V*nZ;lLLc8pgozG5OLu?{O4dCt$yFm0TZ8V`XPYv7yzvUrQ+`7{Gd$YVubOz zKXDDcbLJlaE&uAm)U>ugvDzb*V7qtd((MbiN9DXI!4I# zZ8VxLZo=N{UJ^Jppw;^cra(hz6w;I~UI%GZ1L!cFCa68u(I}#nBa~Hdv7jCeL*vZ1 ztdz#YP>Ow&kKQKZk{4y%p0#|eW_3WFcjdaw7u35+XEVP>Lv*_&n% zUcV6l#KX7ua6O^(vUdib_3b8xA|P?{{$7S8A$n5*@G4a=4)%Z`WN!&1d>HCt@m|h7 zv<06ZDuH(Zh+&KZ8Ta5jtOKzGMBkLpB|NeMpxZ4Ii%R_~`b7W{VQf?a5dfa3@+$qE zeh*nfMhMM;Y<0(A5W^h6_pbm*7)x^ikPU-I_^MJr{DxoQKPbELBmn(sw&g&qc)W-K zyiVAjU;XJZmQPf4yJZ4U9r?;Z`-=Qv<-natF96YW0etKK2tW$YP4+H|Y#0 z$N&-x00_R&yj>8?ikJ72JU+}W`IF^KOQaa?E*~DNz~kdiY!m#g7mI*g?ntqHr~ruj zkvLk0fhX27sqR23k$=^Xv!BVs%sF}_sULTjk2~j?LyG`Fo;}uJ#LDOPzqMAQ8_0+V zwc%K8R1B^M20SYr*0A36%yqk?W5a3r6B~Y-4F#X;0Qh#J9Vp!~9P7x@&$uO6O#&js z;#5a{4xAnXEJ(uvLuv8{*as|b2jEFYlYpQcFwcE_IM6okbAQlWq#3S1IRI2*azp9* zFAaR*_OUg*e(FHPhAHm*_ORz#Xx^*of#S5zeB^e0>hrbXEFZ^a|^bG)VL5Rx3U+f$sx|o9JxL$eumPJUx zNJG7ESK<`|$ps^vnpJ`M)<2$6@Yh#f)S6719id3_{nxB271D`)~AB8%CZ9B zqdpLf)tUoa0r1PYV9d+(YxqQ4#`i0AR0sy0FN*Xl0f;J9uMi9xF81jqFq12#6b$~1 zM0yUeEt5-PFBrUB&;t?70kLbBg299y?14AiO%l`vg9ts?1Gn2v%<6(6Pk#ZdvklxK z4xR``0j$<{Odg)`pNN-kA0`ui0r`bLJP{0DVt&3mh0|9BW0e*D;4}-y zcJto^Bl$PM@SYKjL^{Gz!Qel!R~B&~7?3>|45wKz!0BrKkPF5zt_VimAEaPB=MP*k eKKsL`-~ItkbD)74KAaZ-0000CqUFEWXm2%CO{yZqLqjpu=M;<0)NU8A{Lng_|kj*G4yAd z>w(2$^#>s4A;b4Qi^Vg5IbY7G83H-yVd#MQ!U4$?umj@JJV@q&D2k*cHP|D7YXdlo zL=Xx*kqxcmfkBsjAzvhW*#oTt2EylO9grNbUzVG{CKyl|Pm zSLu7}SAE9o8-I$6mFptmXC3}N}?W^skUCDZ#$`U zEn9*E0oa_UsC3=%^@_7}{T*+qS9uBWe5I658zz~2qn6GA0IRA8Y5=O%lH|p6Qh0EL z-&vqjbfd0Q4WR10gVimdwL)fR&x7s)NU(cQdu{=3YJM6as%eX&xB}hCKben)?5O=7 zpwEPzIoOLi=+Xi+WGQ`HYmT%v#;EeA1IB{2r|n^9)F!zP98Y_~G9Q~5!!Cy24&gh4 za!{7Z7dY%ux^=-AqU{tw>*k2}bOrDO4FMFN_G93o|3|+8oM|}h!vmc;00000NkvXX Hu0mjflNIxd delta 568 zcmV-80>}N@1dIicUw;4za7bBm000id000id0mpBsWB>pF2XskIMF-~w2LUP((HqKc z0005+Nkl?81aU4f z$u0ZYCNueafU5I^g5dr9@nS?2ebs+i66MZJN^!TZP%Mg`rhhn>xBYKw%2=Yl2f$}H zAVD8u62%^*Hy{oP)7c}yl&^TMk_QP`ju4d(;ARN!XAml%dLU=f_@X~b5-y}nm0Fy@ z%dZO{CFcN%nmaJL2bkN+g~}HJjHo>a1rh?7_6+q0tiN>R@M7FM z&}+J=zSk{KJv_nHB``)Kvv==pF2XskIMF-~w2LUP((HqKc0005+Nkl?81aU4f$u0ZYCNueafU5I^g5dr9 z@nS?2ebs+i66MZJN^!TZP%Mg`rZ|_k{cmc@SfaiMz-KogK_6lg#U7+LAPx!B*(1P| zuXwJK2MJh?5S0($W(e+Q5GtQ~AZO9|qCZL!E~HGATAaYkuL~e0=KzVCJ21HinA^&Q z$`=8Qs67V-5(1dy9;6RIJYngCsj^Hf(r3?LYycuwj4NCfIrSgl&yzyigH$4ZivPot z>Jyk)Ng>>N{sW+pnXHAZyHme5JOIH{E)(@Eo9wO5-nwxeGG1P>xSabbQkfN1Myqv) zqtRi*t9F^CXbBIRqIo9MQC~Gg0gQCFT4HXu*V(e^2ptr_de}v6R;^slrO1{)ahF0> zr+{dzwKiER8qvH`M?(N$T?eoN&@0nWbL#ohxbR}!JJ4&osJ_=NP(3`s)g>@SBeQq! zgYE((xMxr|jDRr>T@l@OWm$fJ{;Gep?=88l9tS|530u2&KXz{_2S&)!=5nn)(8gM; ztKS}67g{^o?6+30)BE6X+z}4@zD}^&<#}(5@U6viC})ZsFZ(Lpbzv;g<`!Udd%%7A m0Qi8;0Tv&3*Wj!Eo%#!)Qa=_Lfo%Z*0000v5wO~5I}t^k@BQn3>AgFv3)uT(Kvj7!zxl*lMOAg>;bNzK!W=Nz93NK z10r4c1G>A~LAn#AeFZh=Z(w#Ent0cJq)ZV-nx~zyXV?22=NN|=C)9B$_w2yq5v4+m ztpthVSYV88zz~6vB5X@Mc^$_u^U2J%#G^9=CSTv@BJnK1EEbbbm$|LRo6lH&a;X4w zjWel$cVF`9(p)3T-9!igvAQzX2t*sxA3vAI8oprMRqx3L4A}GPj*Id6X0tTbAc9ua zH49V^<|cfRP*r2Pv;gFPn0fXFqEgDfIY@eo+% z6~POgFK;Ye`WdO4rmo6AW`Iye9_qR-n=&vC6cR@65opS-u?c)p-s$$f`CFE^;j9Zl zA%z!ICB`k2@@*$CrA)m*)aCZKJI4R}!+1K9K~h{Z2<0^*7cz@iVl z6%dGQ4ugJy06=B~z|#iu(P9UV4<1qZsx&JK`h}wnq-;!f;6RWdpbVtBG1$QXI1f}1!HTpgVndxQ$tsR(Y1qt)OO(P1fy#Q1FaYMAgy3@?EnFN5$*)T zUjMa5 z${=Kv(gF5>F5Hz8o+ZFn4d93ly*tzu({Xc;z5yUhaUg;pm=V+-DG5c;U>uA9;pIIJ zMNr`30En+~D5I*!c_^c**;5#_XU{kc77ic{u)v`q6qttroY_-=CLrM{VH+O+$cfP6 zs!ZS?pxrSb4S?yBg9={gCyafQp)#QAY?D_ljwd$rcD6&nXKxyoF!(?jM<$u z#1t|c0EnbC1@eGZs_M298Dqpg$lhk6TkEuZaGvnY2B*9A*OPLI2I$oZR{AGXzzoqf zGj62Jmx(A+#&QjS7U=K%32gyof9nB@gNMTa0000< KMNUMnLSTa9Q0MUg literal 0 HcmV?d00001 diff --git a/graphics/pokemon/finneon/anim_frontf.png b/graphics/pokemon/finneon/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..26a385af4634839be096b5a9e0639918fbd64319 GIT binary patch literal 686 zcmV;f0#W^mP)F>BjE6vq_~kAcK)#|(OQKrR@>U2Eu>E{Q&XFr-VTBCJeZ)!kDyRzuOz zIg3n|8WZ9}AE29?LLr2Fm)^-V)4ivuP>SB5<^A-3&wfvLf6wdUpN->|`~e)92SG6i zJ?~j`gaUov2t-kg0z8e40N}thjSoiPqxoK%#q10K?V)#>#T@b_0eoEWKovd#BrsMb z4dhCl;!U;#9F!_izTrHgd3!54o0;GbxGK`pV06>5ZlUI7JP2OFh+Q@37 zwE^72WUGzT2Dte)E{ASlUFmlQ;A7<+mH}1`urR}NPE&4e1p~~HaZ70hbhco~M$H-l z19-wI!1O*cYz}N&+5Al^LIkL)l>u&({<#~NRgJ=zK16Pb+13aM@flFSyuSV}`~e>k z!2KLzCXgmApyv2CT0p%bK3n!xs{&4m!{xQf`!NL+@SMtfy^D+P4DX_gzZHi&K?A=M z1jU4E;XNOhByh}g1v~0T*qfOK%-!Cm&;pFx zN(5w+-cNuM0UG~c0YLr-d2RiJ;5bk-dENL2q(W88s1MA94&Z{^7y; zhkO}&n18T95)|%*F#f@|KmgJT=q%w&>}IVSd+l+!;th337pgZfupzolYbbs z_y>V}-GBVU3AQPF|8R$I)80SaO=$n{hFHhFf0(rShaK%7PIlzk^7z=D@&9@J24zYU U&7-B16aWAK07*qoM6N<$f}^Q5+W-In literal 0 HcmV?d00001 diff --git a/graphics/pokemon/finneon/backf.png b/graphics/pokemon/finneon/backf.png new file mode 100644 index 0000000000000000000000000000000000000000..2e05aecb68cf1f51d2fb4579c0e90947c64836b0 GIT binary patch literal 647 zcmV;20(kw2P)B*66vtgU3t|o&I(YCKOga<{f*eiocR71dxj{>Zh`?p(*0sZ>8Zvcr zC=_mL?n^i}q!doyrBAZmlSH%MK_6Hkzn}i^=}AvP@M-^}?W5zqFbo1xrlVv2lMP)027iJ7{MQK9FJv zlLVo=>ZzSScsT%v$$gh)OLvbg-P$o4nEaf=t-MJ(fYO#$E^sRwkn*m}(g1drB$`Os z;CG*9y+liAwFR*6a#Nm5DM9~LDsOX29pFlCpa+P;2)UwmDG3wH9*Buf5lwl(x&v-5 zdOxL^r?4`>-NoRaZ(Tt6z^r=u2)O2}Ax8D+16T*KU}K?riC-QNrBWbJh~>H$u?jI2 zLNuk&04vU*h(p=|hS(^2`6G9MJ;Q-%D?&_Hz5cO)Q=LQyL>dXt#iPuT~O!{CP004qz;PS%>y{qL-VcY%snuS9mamE0qK2X0kgMy&MDa zK16}{xUi2a8ZVemBo8~FNua200o)>waF?|*5*(7Wbs7V!h|r>_iBeM(fJ8Z+6=9VT zT5vo#j!fx21$b)(A7dfE;C^b;iiHbc;20yY`n}t0?|ovi!W`rGR!cMQjX`0AvcL0> h9wJqLKK1{!y#WcI59z3{Ihg6Lq_EaZ6%V+4DS<9Z4 zcI85QD4m1BJ3qbm=FOY;{+9LcFZZT>$gSMB!CMK~>t21O{eN{}d4H9E@Tx2uuzLVy zw!+1Br_zCZHn4_(Pr2Obc>Ulp2}z%BypV>e$N zjnfb6UrvXcKWp86-e?U{LvH7WoMvnp#`|kALY5A**2&nZT{7;+@M7#vx<% zSu~xRF-|{H9u+W99vJuA`qLFKoB0Zuhfv5-VrFNCi-`Vl<}nUgRsAN4ez_*-L{6Lq z9b;9UJenrU=0F=zX^H^~A_0&CGGG9dT)HyX1YTSLs{V@Y$ajqkYmFvo0X?0y2AGCIXFA;X-DmEF~+EBnYX#nLYP_?dS3%e4OxGTS6%;E>LCHEbFQ(vs|tU)%c(Ko zaBaN6Q@S9Jt#VzFXzVOP$w(Jg?fIg#D$hOD*=0*9@VNKx1Z9pTM^`% z>J8=lKV%y~=qYiLMXZs)LD;HG`7BGn!0`jvWThUdGKom6h%Lwq9T8wfbKS`vyz?>hJhGx6oBD(AA~satvw+OaiBF$3_Ne2e-PxN zA)Y9`X98cSQ{sRm*O~Uv=hw5{(Q@Vf93Xk*G#Y(#__xnZ;P)JLd~s~5hxVCP&6hx^ zf$fC6P_~LnU_2g9r@U%YW$pGbnSXM71LM!s2j;SfS7=m*lX(JZ~8Q z)rDwPWl&fe-cIdGVQjHd5H17k;#z{J>7F7FcCI8yJ)a^Ew8GfY2DE_iQ$h4Ym2-BX zBnYKCt)m94;PY5~WatOwm*-j4&(aUtFL(2q`hovF{lNd1`r$91TP&j;H$4LY0000< KMNUMnLSTY@Vtt|j delta 1406 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 Z`~cVO0Z0v7I|2Xz002ovPDHLkV1lb&w}Sux literal 0 HcmV?d00001 diff --git a/graphics/pokemon/kricketot/anim_front.png b/graphics/pokemon/kricketot/anim_front.png index 1b23ff111a981f4177f16efd0f3c97ad71f54dbb..e9a485ef0c91643c4fc3998dea56b75c9b186d8c 100644 GIT binary patch delta 846 zcmV-U1F`(W2cQR#Uw;EDNkll&X5XX&Vl%+$T>qJ#M*|iwh0$;$ko*Y9M zhy*l^I>L*@)Bz{Vccu@V54cqrpmpo;Zs=LR|wnvTndiost;S0j+8}UHyn& z!1jY4B;oxk)_=wg@qslvBOxaIw21*dF=j3C=|&8?AE#&lac*wCx%>7v==QM)p%BC- zt-IMZ|&;q~Uu-fdJzn924=ukb}CdN89!xt(5Qox1y(wA6`32;s~86#5S05m{c zwAkL>RlD|1!@oi_SS^Zz+7P|3Ar}{nX0gLEMN2_smP^bisILyO3Su zoA2PeK5GScZDL>y Y1Ey3gbZayibpQYW07*qoM6N<$f{twJg@3@dPL3fAL;{*d9pNG|b%+um zQzcR#QI<$V;-oCGXj)y@Y;?AYHe1q7+u>pn_JtTfzmZdDhv8trt`K5-R=x5J3|M2V z0zfU9d&KnZyMKkQwOD1?7iWn_sB0is)(cqWpd!X}Nb8zT?-tPy*ly5=Abe2A+PEf8 zSo>fk#Du?_VnAPvSx1OuH0+(W(F4S}x$)}q)32a6z<^K)Vw2A0?1u6^EC*Vnw9DIbCOrNPmd~&;W7KVLLlgHr{A>6{5u& zaU3)v^m`1sxL~YUj48(fo%3VXEf)98rwSnC$1;xNJ%gYrXkHj4w*X9S2L*IuMoCgE z76H%{z*YkGtw$BFpSl_a;0GUOyj)s4;zKv{ZBv@**Wm4&nE}CXr`5u)HU|2_HxWa0tNIOaU|p zou%4i+~&NB16uI$b~cZ;_)yh{VE;EL2OdF$F@6`&hcNZaiVEn^tt0SLArvtfgEqgX zBQ?;j$}6)6&BAy0A*(u!SgG7YlgNeDLLu-=DS+-?Vtp?Z8jBMqDBzcZLZLOKsn$aQ z&uU5mCQ_~E;#>PP1xA8%9MJTWPA6tP8Y=Zc_%)7S(~=Xamh=1!^aVU`s(KiYLIA#C zg8N?wn3PhG)G7ePhnuP)We9VrE$C|0KaBkWA3!Tp*+l}j00000NkvXX Hu0mjfFzc6d diff --git a/graphics/pokemon/kricketot/anim_frontf.png b/graphics/pokemon/kricketot/anim_frontf.png index 6cc750f273bfea9ae12a100aa5ae8887d3739128..ef0ca6d8797d8203d8f04342208d08006b8c74f8 100644 GIT binary patch delta 911 zcmV;A191G#2dxK?EPqf)KzMLqn3#|d5D9rzSReqfNI2kVVBo-LkWd(CKp+4B z0000000017!lNtz00THlL_t(o!|j(bZ_`i^#~sO07luA#Dg=`sR)%aOU%<8=t`j=6 zQfi=Lbgoh+hN`6PgcQhY)umF9`Xm;tw4le@tt_Adh5AErZhyP=o;xuh<(3Th)7`y$ zes}*^*3AB6W9%0HqgEwh^LCrhR|1~Hy-L9GDuLCA`&GayWTC@@3O_)`-OJNZmDbS@ zk)L7&yZx8|(klR_mKC*I0S!Eh7C;A9#ED95^bggFhfe|PN=+V~=p%vcAc5yf zsi&vikD=r6n}5I@KnH=P;w)rt#Bbi&Tne4hmf9~uCIW}JvSAFJjgFd#k(gSxxOvL0 z7@o&lm_%+)sXouCw~%e@Ds?FLG78vI6X>fC=V~;3Hzfn819#!Y#h2glaGQ#dD8)GI zU!0x@xwcFI*n+6#L+|uNzR|=**;qY(O#mC`;|C@HQ-1*TKW%HO#u7LX_W+pIG=L3I z@B6T_ay;n0vglK&6nc3c_r~N0n@IH@pxMlYqybyX9T+s5YwmpmkjNdK=lPn$$P%nD z85e&Lm~x*4Z03%OqSj^%UiY5T?4@~#LpKvT>}q{XE^aH$*we3qEn_w)L@ICMDEhcj*il+t?7H zj{0U)F1|5F2uNTBm-pfDP;P4ju!+FLEdlZrHf-z{=aWpzE)7`m=Rc=s<3%~5Ga#^z z(n88HW|+`-fqh6yzwVfTzF2&XexZ~h2S9mIV%H30UH#D=VzcPoy$M|(m{-a@vWQyJ zZGSZ4s8s^w?q%N3Mx%Eb;gAHPR@`W$Q&DO?5(vE#099(efZp1BC9tccqyfu*+wbQv z6p2wEB;WJ=rD*wyX*r+mqrSlBEleZiPJ+NU&oOUzd#NZ!jQK`?=n5fFQkwu2ALaiB lW=!E;X$vtM_5a5H0v+W#O&p$<_y7O^00>D%PDHLkV1jHAx0L_@ delta 944 zcmV;h15f;|2hInOEPp^iNN8wqh>(~N5D<8HIQZzWSReqfKq%mFSlGCDm{2HyFc<&; z000000001EBcDeA000SaNLh0L04^f{04^f|c%?sf00007bV*G`2j>O{1seek_;q9e z00S{eL_t(o!|j*9Z_`i^#~sO07luA#Dg=`sR)%aO|A1{hTz@C+&`PN(6{B;NIx$p` zmI)~(FBJ(=0^N_p>rv8hCAv_5i$`t#FY(V=xle?L=45$vc>f(cVbwNcQA?E&8R-ksXfTH z$4VW_*Ha4EQ4{DZRg8y&{frEt-nt7-K9>EHeQE`F5l=~!LGj~)J&1Mq; z%K$7EXn$V^!tnYFsK|bLR9)KeEV)CAb88G9&$IOnAyx`_HXou zQ9INwcUZ0M8Hn1|5_4K6ZE(ANIlFKp)8e4kW`6)iD;Vb?cS?utUHx7MIFACWzSctl zGf!(9p9l36<%bZa(Ze61e8_x#vSJv3UX1b~^nbOH2p0ghLKhd(3F)tgZYFft)%qQ| zm#s8oOP>T=#0Xntjudc|hpyVy@AL{Op|-}$=eXELh6r`kH^XxAjW9w$0;{;Z4+n>G zR~vxm2u$1(Agi#U)E<*e$}SC9@rR4E^Uybd{l>n$x>jm`I-Y`&=m;*5OoB*I6aDY6|lN9E?0Dw}Qf`14br3X0__*~j>f`E&t zM!l4Kt#vOOF$&15)I-=L1PYG8a<6^ZBmja(J&>)w3E8|rNkmjZMhSSL+b z@C88}EVv-R1Al;bo1#Ihz6CDDBvHHZ1y3HVJSbyOc~D(} c_)GtUKjY#se%|Z1uK)l507*qoM6N<$f=n{N%K!iX delta 477 zcmV<30V4i~1hNE>Uw;4za7bBm001r{001r{0eGc9b^rhX2XskIMF-~w2L&4=*qAhc z0004%Nkl{Xjh9qh!y0ibA2I^w2}#g2@~dQ!TLK|=v; zk$_&8a}lsbJAVJg~F^e6lVjVC1h TMb3|300000NkvXXu0mjfv8Kpl diff --git a/graphics/pokemon/kricketune/backf.png b/graphics/pokemon/kricketune/backf.png index 4f7f225d2b747dc4fa13db16d3c7c2e66494af47..b07e1451b97529d39c50d64aacd23339c9dcc770 100644 GIT binary patch delta 638 zcmV-^0)hSa1=0nOUw;B!Nkl?kn#JI>2Xr6Zg)(BaY_`m@U`z2IL*G{R1J%10><=0M|NnY;@kN{B7 zb-p8TL|x{@HE76p1Uj++CDdDiio6N%&^!k)jOq^C=Gi9M@&gdMa`{B3}VK-2W^9O}BE%RcrxG z{7iw#LIjLu3V%!!76B#!_y({hsdKV$ucGc%T*hqS4uDR9dB~SW;cdhKU*3YnM41B1 zkS{sDogM&AqDFz+Nz1KA1YXbuj%5G(CkDbJ&6(=02Km7#W_N(%Q$KpZ{peqZHINB$ zv3KA)N;79>{vm6`$KF~V0A@$ojL9qf1kJIxFK`FMbAJNxb`WPfVwwK$&PXA~WF+bg z;ESFBrYo5)A_^@T;0*YYIWbyP@@uk)I1b2gwz{=vC`}`TQ6||l98M&=Sbec}z%-R1 zip2oFQYV5zjg?-p5;d=a$Ro)t7U6)w$MNn}oS}6BV{7qDT~2@jS`@(UIN%yqSPaks zaul#S0C#>DFdhNeqbIun_InkkD*-NV0vu`wj1T~ygMmyuS`V}V__YPRg$`UF5V&EE z4&t#57G}WyaBDjPvdIEnfZu5wwg8$)0dGN3n9I1SRi6TY<=%m~h^+P(;kQ`72mIgj Y7mF>Hq)$07*qoM6N<$f_HBs8~^|S delta 676 zcmV;V0$csk1@{GzUw;4za7bBm001r{001r{0eGc9b^rhX2XskIMF-~w2L&DzgEsJK z00077NklPaN_$;sT&@@#gpjA%6;hjxp{3?;Qg!BoILD z#!HGrPC)ax3y20(QPPJ*JnWZHb-H#+HST%fF28o#LdkkxfCYe~uJav%Bk2k!u2EyY zBXD91P-49msMx!J49#tBx(}4 z{n2Xck+J@nT+m4NuL%%7IlW42HL6dh6ZUBf6rU%+OMkr%YajzS_jkaK%FLOC|HvB1 z36KF01T0ZmWF+bg@vEKyp(~XxB91K^@PhQG za%MDC>RYmiBn`-LvAVSvEKLJoI+N@fiD#Bwt-e}2P@2lHPQ(B`sWYRXrb=I^l5SoF zkw=zUDu2QOgOAhQcX5W+35>0!Gj%xu25d=yy5oSCu)<=1515mH)dBFkK*$K79zECv zus^CWT?ue~7m!#xV8j6U90FD1(R!c_z^^UfEu7Hxfq)z3IAJ`t!NLsKC%3jEAe$`k z1^At|VGEFn6z~>0j&m8eZq=s%P`P&?E+VV_MIHDp*6#ryd;S7K0nPRS>a+U*0000< KMNUMnLSTZPT`Rc& diff --git a/graphics/pokemon/lumineon/anim_frontf.png b/graphics/pokemon/lumineon/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..ac511018d4a8244061f2bae3ff43728925d191b2 GIT binary patch literal 1148 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 R-0=Va002ovPDHLkV1i5|{Yd}- diff --git a/graphics/pokemon/luxio/anim_frontf.png b/graphics/pokemon/luxio/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..30ec79e6cd8b3169936e8125d42983704ad0f525 GIT binary patch literal 1111 zcmV-d1gQIoP)l*O6vr9h2xyEn1V}rXDmr*`qz0%a);`h^yBIC+1abB8sU|wgBD#4< zP*>eusRQK1y;Sktb;=Iu!5?g2eaZ{~jOj?)_yL_v2rU z`YxbxumgBt)$0$p1D3TFXjs-~I|Q2cHh|D(dq?UTwib4{ZiRsgm}(>36-_~@;P z@>PJ$F7RWp2AHt&vnyW}K)4+^9t?^sYU3(Eq?8wA5XYkvqxMrVT?GL7yf;E%h+^`h zk|eom3cNp#2Lp;?iyCvW0$f|Xh>u{@MKQaQBe`xukpaMW<7w-$ZJro}!|KcOzW4zK z7zd$F5#Tm)K&(Eq_ef$C&ZY?LNe8II{I$1T>vxN|lp=ewcgum6;s)ve1`x?r(v5ds|I*oDv)<<;i9L6#}SfX73C(4m@j?iFzenG3*t-A(|; zKsbXT=Ai{lmlwAdLZKe;@%bIbRHPVVnr#>OocoILD9Riyz&UkMKIN%TLY`D-umbfQ z3#HP)CQ4O-{>%Mailq`NNNO5@Te6j4F{t6m8O~JB!OU;=e_dQWw7&GlFUmky&N}pN z549+*RJxn1<+Y>z)PH8gsDX0O(=M4fS#Je6fdHF6br95zbw^G>#n5OYj01 zOPkod3|wB!1xCJ6lX6n(yz|2g4Fc=MG1%i=2Vm2;NzuMzG0vh%*`myWNiUvvc<=Ne z(E{>#0f-F%+yU_I0$6Ws-K$pg;~W5(E0mM0UA3Mj7({{Syo0fFDap9;Gyz$-gvbkQ zgI4;Mcl~*K=E^Dd-4DJ^t6hnxN7>o$uFT-{0~d~_@lnO|w+G!B{DE!H@ihyEf_&G= z<(t3K!BBf3Gss_er2IvtJ*V1I&?3appXG9j7C=xC)kYA`Cy{(2l`z>9CQfb7QhUB1U!|68-ReJKjDE&eXYYV zOdbYF=&LB)00fY!L^wgp9F2b{9E3u9;zmqSoqsS)bPx(1grBNsTHqUW5Y(VPF5jf; zA8-xJo6h1N#bI+&^$&$@n6>TYx3=bGlbKw~l1@wa--O)WIgAYk!uUtEyTd>jI}HT6 dHxU2P_!|LNl^beG#>@Z!002ovPDHLkV1me+69E7K literal 0 HcmV?d00001 diff --git a/graphics/pokemon/luxio/backf.png b/graphics/pokemon/luxio/backf.png new file mode 100644 index 0000000000000000000000000000000000000000..e1b5e4bb9a3b3fbc6628ccd1fe581e27e5b9b4ce GIT binary patch literal 658 zcmV;D0&V??P)PeIWKn+=6rODX{jVd!skn zBi7EjJ_R=3yWc`I);9RvFM+}bU}vmF&EKgH2F6}mYr6nU{^A_?N1*c-$wLO95Ik6W z1AGP;(B3>`0cnDL2FACv3||?g>DBG%a=`t(*yP?qUx~mlT>Gd0<6ZN+l=2 zX8ZKqNd*KY2F#&ehn&)K=B0X s&r1(soj!yh@3%qmPGF$?m;PV>0Pw!0xA^Rc*8l(j07*qoM6N<$g6B3MI{*Lx literal 0 HcmV?d00001 diff --git a/graphics/pokemon/luxray/anim_front.png b/graphics/pokemon/luxray/anim_front.png index 989470b19b26fc0a3b201c6f4a0db9b70d0cfecc..b2de7e12e63c66a151db25040992c27e45e9ab3a 100644 GIT binary patch delta 1424 zcmV;B1#kNC3(*UZQ-A;e{{R303eaCU000GCNklZ^0ZGm|;UgRtnV*s$k*c2A znVt{e5=B|@x&3T)b#+a>ZxH-{Un`Fu0M;G=RtCKNmhhJ!uYYxb@Tl?m!9X;LumJ>X zgTX7~#|-uq0c`oHmE+kgn)t+ClHj7M!miJR&@l3V2?C*wD`1N8B2%X@CqP3DP%H*j z#BeeJ&Y%XE`x!NWIP!qvRqqi_60pz#!Wu{tzyP)%P2W%l%;Dg8u(8}hF>SnT zGXxSi`0$Mb7$1d(d8a{Ok0RhPFKCB|tI#y+6^s!`?0+BcPg4p2Tx;6}!2X#l8FS3u z0oZ^w6Jkfg?j;^l##9|VwB(^Seoq7JZ&8^P0!&1p@Y_ohyV1V<>5u@xTgTqP?(hNx zOoJWgsRInq7kG7Yg@JMYF_lWuwNmqGXf>DqHD3s~LlFSKRSWodBHX&gJY5vi0G@q1 zK41fNzjYCkHf@%n^HHH@NH#Xg|!(41DGCEGoyMT;AQ|DxFl~Qrf;F4ou>G>2H z0$062N=4>!h`^$|1ykdUQzyz8fvgu;=OK(aL*Otw=>dM3;!zK<9-OrEab=jPU$ctlnHS0TJ2aSwesv-twE%yaC`%>*9K%*L&jnnlJL3lLlaHIRYbV zxDdhfY|%(E6mii244*+arbSComj7?h=fLk1vu&;K2bk94emxZ8zm#wOki0*6NZz|Z zIDd*g`5ttDaPP&DFV0UMwbv)}qlUh3di_|4?}Rt>eO84Ct&>htUk{kgrqz70Bz&a4 zHLx?ARyR(ng~~Ze{Gsvf%p3P4Yjc>>SXv4K+nIV344kauU=tEbKpO9mT4^`F+>k4U zDDt;cS*pwR|Ew+TjU?=EUH?tSD5koW&UBq0d<7R?0pGp?fCZ#@_#UB zbLt!_;MrgKo2@)OIB%@8TD87M;m@_(UzGmBrCx6~JiWM0X}NqWcI)14tp5FZfzd@_ zj?rHPOg5$W^QThC1hpj^5ZO|-A;}c&L7qTs(_Y7^=K$?G4jWW&&BYXQUP?Y zEnpeKq?kn|LDPlzIKjpEPyfyiD6c^9yQV=c0|GaxgYZkhXt_ zsu4UK^XG?g(Dn~eq)P(=nv=I|`-fOcQ4YLf7PtKaD>a=ZNn-AG2QMt#3k1@d`z4zR e{;!*ae*n4zI`I4h&R_rl00{s|MNUMnLSTY^xUg0L delta 1456 zcmV;h1yB0X3-Jq(Q-1&e00000`gJvk00009a7bBm001r{001r{0eGc9b^rhX2XskI zMF-~w2L?JNzalyh000G4NkleB{J`+O2$O9$_gf^~#DaMOTox+>|4K+Zq7*r9%$pkoq8er~s z)Bxhh1B$EOBY&JEV4(wqHIO8L0c<~@@DOtsz^YzAj{;3Qh)Ags^Q)sB5Q4=60+`ba zrG$)o02mSQEYGEq$^*ip4hUERPV@Xksk+)hs4D;vFnOL|_yCK*1P$PE{?-F<-SWWO z!ko`GE>)F6y^gtBHAxbCKHJQfKpaRg)n2zbm(+9Bd9G>v)%V+0cW;q7Tk0f1|5y8zgaxsox*>>Yp&STiAZBXbCWQbK5h(n4X<|3pSFa8U0DS7$JJ=mwfPiVR<2-eM0r~;2 zPOdO8&VS#hQYm_@)O;FR&82_K7sBmO1i+7K0q;+QTep~}i((qU^FPlxD>eXwe{ACr zl%}8>7T3_?^Nr)~*kLZV6&W2T=3PL>ps91R-<4850RlM|mfla1A#l|Tq*P=shX^dX zTQD`wICY|o5y*OhbsoZ)GXxH^lOEvLDIWCz>wh770jXwRAh0{d|AfrWI(x{SjEc4U zbs!H%EbAtrzMs<6`Q_(;9bN^C&K@jw_e2&GxxETjJAmAG#S8683AFZLDs^*}VTA2l zv3hga1Y8MAfF0iQo721jFblc>qSt%k`kF8Do0A4$tSzQjWDOT0*v=M>BtsDwEy(a4 zbbn)72;QqzTk|>a`^0QZ>-zzwwYXmoh4?S!n?EG)Pacx@E)b4lPre5oAl!R#6srqvTC)k5W*B>vR- zZsv`9lC?R^X)G-Tf$dDa2?kD9aj*$l_J3|5jdw_`v>RV;$dy7A`P->1)#dtf0<%V6 zjWZ3^754!OPl)#ls0=_8P*fw*W*k6Et!m`JCKLgs_rg}f8iCiGTNogL*XJ7-p0I*P zY?0`}v-O{HPy7YUE0vy82KMv~0d;Nyj_PQXeohf$Z$?MU5R9r|f6Ui6F@iV6S$_q5 zg}~0IeC;XuhdPU@7VITvy#6tNx8Z;~LS^>81hsbj;gUQI+MGIv3V8lU{^r{}J-BGB zvs$%&aKi8Q7p1>&sn?qgPcIiKEtg-#ZrytttABr9V02NKWAqmRlTGRU{8uStg4z-d zh-|6aFe_6aPoTAFujABnfOZ{+4Sy=TswfL@fSHr=Y8sGom=^&sRg^~6G$2J;oN`NT zPJ0qL<1%!xmPedjOKq6ZkB1f_kzN51InA!9cne~7d#f#H~MAI3r3KSYr(o*x6v z$y>JlLoDT}9C*bnzRN$bBq>SEz3$+Jg?oWOT64c-Gr|9LlkgAQj5+{cI+7Lu0000< KMNUMnLSTYdu${jE diff --git a/graphics/pokemon/luxray/anim_frontf.png b/graphics/pokemon/luxray/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..49d83d6b758a755a2bc76f572571ae99763d4693 GIT binary patch literal 1450 zcmV;b1y%ZqP)?uKNJwy~I8gup{{R303eaCU000Fw zNklf0;6vxltjUF1eP~p)^QFvrQx~HZdWFKY9sJ8TQbF4x^*OKZ>$3lnn z1b7J?1UeuepzYkr8SOzv{89QL`p7%!$U9kHilTDt#Ntnn?;aoD|DPcE|GsuUc?8&d z1lZ})t;=XTq3-e*MNkT423zXB-41 zQVuXM09(J)F(`pL(ZMvO0fRL_?9XTogh`Sz1`zv+*LxrU0$M;=18E8ofEM&2Uw(l+lBW9C$w9H&Ar3gG`XGi`l1$B2g@7RVWg8t*}Jj2gnmq@AG0O&sp z!DEWqTYv^(&4dF?;q)3GlE2_oaaCV4g5&{9jA`tlPq)D(9Ui>&R0N|-( z?_hU00Rn>69u}De6qrBY)X5eGhQ<4g3t^7cG#{4VZ%_G4v1E3KG5~&y2Jn8y?7GH0 zZ4~7J&pupIQf>eW|I*$=m^7KGp?OK@X{kl5+CzcZ*qY_$apDd0gU29EYvsQQr?XsO z$Z%_jS&qQXMj$gqro4y1vb_Zn!(|L-T%WkqsLe^@ z&5W-m&bY^kB_Z)A zofk&_*X<3{H9R#L==o~|oVX00*U?P+1xD~LWV8xFOcnHZMdzU4u@i!3?t_69C8F#LWcl*AHA#1bu8Hl}$-xtQixGE5>foFdeuMdmt{K}INQuoKVDEx&q zs#&ENm#NowrZ->QXZ5-PaNRkL-M>FB%{sNt75zm(xG%jQKV;<&#&V*+AiSY!JtI?w zFma_+&2^l5B>*J=yse77T*u6@$H6xs)iAfxuLMKoL+SGjNLd!E+?YJJHYnB9?jWj~ zT5~9`QB%8D0JB#>)<$lfz%SO9N`;P{2&Pd5XRUNHU;aDrnk(uFl3 z8|(wI;!ohr`U|n#0Q6=-Wgqa!m#sZ`YzJpF%#gjOZTrA0`+yMw6!(@pK>IK*#Xqw^ z%YhI+wD*>j281^K17T3zTRx#24M@{JpaH8|s5hj?qc~{#hbWSj0Rc&kw`}@{m{;TL zC@KFl*7Ogg8sa2PQ?=C{e6L|E5OA%wOEzKjUpEQ=0J7vG8u2a7)Bpeg07*qoM6N<$ Eg1}<3fB*mh literal 0 HcmV?d00001 diff --git a/graphics/pokemon/luxray/backf.png b/graphics/pokemon/luxray/backf.png new file mode 100644 index 0000000000000000000000000000000000000000..ce0fe29e44d92ba7be2bed257efe9797779e107b GIT binary patch literal 768 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 diff --git a/graphics/pokemon/milotic/anim_frontf.png b/graphics/pokemon/milotic/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..a7c8fe0c2b9153a5a69a254ffa817cfcf8613faa GIT binary patch literal 1651 zcmV-(28{WMP) zsKFV^4CatQwb3}L+tG{ADYOTJC?F_^-4-+u8%Wck{9pRs9VPyd>}2TBGfaqlAHMg< zJKp!JD4!l*Xg59)CrdZd6KxE*Ad0#)jL(s3FfQvN2w3oT1&bXdWFs-ybJjzQY zCV_IAp#8M%>q=XfNq;(I`~en7J819tzCP^_fu7C3Q>IX7e}=g469R`b zpsJM-u)-LNYV?O&5b}w?LyVWc1}z|vOa$Bb^*-GtZGXohh6~8=8dUHy!0o*neNBk# zIx!r4Z{vHdQuRD-1lWYr*HE93_|kA)kDbRA4*)r#$~?0*4+PQ-x2 zXl}T!VQdfQj&>vPYXqpGMoTgJqY4z}!=k&3 zNzb-uA_G`v4p8PXMGiOtU@b7Wvw%GyqaMQ(c-uvQ51bS*OY1oRo8V{ZLxi1D@9^&C(i2Ojo%?11jeOYh)I#UA=&fO$P&QBypaYBK>uX^(*b)&jZ<)2+@Y zKtBcGJ@pO|*mt)h!kPkTDMbJt!*m_OaO40BfpxeFU6Oe=87Se^y&(8e#_fCyp(z2& zvdqaqM*?d>n4~CF002K=wibpV9Rnc25MT!hk*fd+0su;O0)+Ppuc?a<0YJ0a#2V0s zNRWL^0#ItU-CPT;(Cpf|1OQl_;aYDV1XduHTbck?v;@TGau77SJfA@6!k_#aPC4I_ z_op+R8?!)kuZaT@$@psZmBLVc@g6PV&_0L)JLg2)03+E8?p6jR4Nn+A8K z0f7P@gtZh<{`%^eHNwk_n|cEHL<4b8?Z$`4$INCeE z91H0Of1#^xW+zc!2%!5<6iEQ2U3IbmU4|`=ns7<(Q{3(=WHAL6=(5clfr-CQWeor_ zO%Mu;HUXqVL4T0~>N5a9)XdJvp`gD=yHsB+3%Q`9U0e8z3_y>@0J~382clZ_!xWG; z_<)e~Ijx61R6S~D4Tzh05#a>jEHfEXM?H|{)tTfu>sJG!iJ<|>%!MU^XA*eVyaHgx zfoLKD2AK-s(KotHo>vm~wXh~bN3UxG=QPo%k}=K(R+5`U1F zUew+McoayBQBY2h_hkvN1CZu1K=^}t0)V>TD^{>F09uUT-kAD>fe`jV0%4G^FtdmL zK-dRa!wT<@^>`xeg8;x_bYJCKP^4yLS literal 0 HcmV?d00001 diff --git a/graphics/pokemon/milotic/back.png b/graphics/pokemon/milotic/back.png index 77cc96ab14efc264f618fc55e7d7706baa5b399e..98dadef06adfffe28d4f76166cae13ec0e599360 100644 GIT binary patch delta 612 zcmV-q0-OEF1-J!}Uw;BaNklY{-_9>!o&nCKC%a~0Nw92tRO$un5}p=Y?6S^eEz<(gYaV0V80zHdg$2EqSbw{`t- zz0&$aqS8U2ukEgO-BdJ3oKH`XNT(a0t_rTaU0V1zL0VRAJ*R!^cz!L+%#?#p`fOYW|o+JT-YlExcdS(Xc0faH2 z!C(^xfQ46pGF}{DAb=5o@C=rI0RaYxmwo|?V1S7Pb%W)m_-OZRi^*3j%}%M17yJW&kYUwF7cNz0M;DBagrLxMkYt1>hF|0000pr z0006jNklxjvPS z+|@7o{isgie;ryxvG3BP7M_Oz^L&iDCsChn+EVEQek|HrcJ=^bdEL79fGUzmuC2i= zJ&`O1fGV@N>xAe5qH@eTA$mZN@l<&-1c=d@frUQsZaFYO!N}+fe?mhkW1^}Lw+686d5m>L)j(}7} zW#J0^Tq{Mu<8&%tvQRsJf5m`VEM4pK((o70z4rE;Q=2GDWj_VJl$ zTqFTG{O$KQbsvEz1Kjtw^K1a@i$Cxr3FurKd=93+;eSPX0Ko>d7#xBD7<&aMwt-U{fi5(}HwIV@Z3$p*DqCNKBLk;C&~8Cc1W4w>1MrIiGsMi4)T#$W^^iEk z*p#L#cWnsc5Z_wBp#eAoeqI>Zy0_8vVZngx1N%AxPFYRv0_>2?t6Duq0|*PKQnrh% zBDBEP+SBn85H%5izJP4YAsT=$6PT~8_5yb;z(w|GfcGlGAaHa5Mzm?a)5LpheeBGH#yRMD>t3#MqRkD|ZOv z5Z_wBp#eAoeqI>Zy0_8vVZngx1N%AxPFYRv0_>2?t6Duq0|*PKQnrh%BDBEP+SBn8 z5H%5izJP4YAsT=$6PT~8_5yb;z(w|GfcGlGAaHa5F>l&H6vr_V%v?cKrAx4#q21^+k~`XdNGMYR zUMh7+)yiS*QfD_MH@98PNZTRz75e4+&Tb3A&u4YZz+bR%Kixa-&VIjE>y$?rab_O3 zAn4g9zyY+qo(b?mfS`W7jYz=62sq{$gzbQ74FVvYy_`w12CeLTZ@P%?& zV3aEta7O29b0zvPQHmbmQ0)ZrfH&Ida}Z)cfAfraNq=D|G|+23;Wx^~u~hY9K4y4&yi|Fe(kC(suqh4kaqbD}9L?Np$EJT;p<}5%B&8U<9N8z%RJo z{XkKwKwIlWGZ2@f7fkoJfE48mZ3ZzUAOZ7uPwuzm5BO549iq(uFd_jVQB-4>wIrHW z^)(=LSbZQjsWHj@G}z!5R3|j+0bl);=KKa4=@J^a6`Olp00000NkvXXu0mjf0VzAp delta 711 zcmV;&0yzEb1)2tsUw;4za7bBm000ie000ie0hKEb8vpF>ljA6vyLA&731q5MgO-cYrNCM>3=B7b)u0CSH&jia>5w7Tnz- zy&1YVV}POe75H+zvja)v=d)N4L;gyZ+)wu|cW1v}t98tO7=LkQ9=9Oq*e1XMw7rfA z@Iru~e*6THfRPb!%rgkv0n-`;K!{g{3C3euq^ZJuPK(6)60z$}+*v(v8ojce@p()& z+DUTF06+<20@^p?>8eW1^EJQ>&x7_NeRq>qi5EE$_H#Q}$h$O^a>W4ow-P8)nc^7% z%KmBh%W*k91b+rpLT%o0zzZ5BqA7fhVJBCdY@@N$Jdj4;cV`eCZwD zzkvpN0qXtGWh&=t5g`zJ5dks-S>1F?&^U$#Kwo4I_B1Ap4K?e?@fTS4}9kUcz=`UlVbQnxhycql?ynbbG5k= zT^K1v4{)e90(rn2Z1gz@(WAe4#=N936dLHXp70yx;?ODqx*Xh7O21kWAe!D}tsZ|9 zcA@G+^Xrtae#|k)93AK1I8KrzM#o7$ird8CILY0oep)5|I8Iy2G`*Gby3TRhTfs=` z9A|4N%YRj!VNL#kFF=*rAleK70}>DtMKyF;OQLC2R|7(a t)dzBu8k5{jgAIN`bwaZq@YRoL&MzQxBU%Yh+SvdA002ovPDHLkV1lwNKFa_A diff --git a/graphics/pokemon/numel/anim_frontf.png b/graphics/pokemon/numel/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..6ef4e79541108fdcf0cefeb6c792b6e97985899e GIT binary patch literal 763 zcmV|r5aKK>j@SxDpkofrc(8$F>l&X5P)qYn0W_2+IcD8U#RqSDFH&5iL^JVK$>hVs(qiamLP60j)T`F6W!!8_OP@N50Xz z5zkj;q6rj1M8G`xaFeV`z${+_O!3@rWw%L^Wu+3Yaw4pkmOsymSTR8U;{Yg?ctL=) zep|g=esT=-sfFCUcY0pvDFD76@6-KS%3s#iJOwukCuuf1zD`ob)c=$M(8tT%^SgnS*UcL=-&$Tn;d7d>~xp0T=hd01c=G zpayuG>j5**4|)VF@cp1f`Tm-tJipTc_95_-1K?erkBjt$bXcIDO9yaF=W1~+Ixv)y z9^gQ31oD8}->7pCqDz1CjCo06AQaFxp79&y;K1AhbUC=kn0_@wK-9g-j4po@_CehT z`qwGn{S>D-#mRC0iQ~j^taY6DvslC$$7$Vu=_QNnYR8#pNwO&W#iQf2D*WQnaUOtG zmE-ITWx1+yoR3RTKTnCZrdIK?J+F3}(f5B-80TsG7K?%x26V051N1vk5&C`uV< zD1E30qHXqqnf@k_qI{#xAch3QXCCk2{hIs%UrV_`v={*TBp@V;a^SF*L}g`10YU|< t59B5lCb=(zHGV;T0=*va-A_>;e*h~#DcnSaneqSt002ovPDHLkV1hixUNZmy literal 0 HcmV?d00001 diff --git a/graphics/pokemon/numel/back.png b/graphics/pokemon/numel/back.png index e895fefbb02da33f3dc75eaccec0f6d33284f33f..a631f1c2a9e2646441bdd97d742639dc2c205d6e 100644 GIT binary patch delta 469 zcmV;`0V@941gZp(Uw;9$NklTO~*Z;j|YB_G5HW<#s&!VrNG2teE>P20ssQQIuf9P;(rL6qx}?6+8Hpa1BTLd zHo$aEfbKxLP6GgeW4TqRVihLc4l;s#V3q_pgPiEgSCPiF25>E_BXu&J-hX}wdMm=968M+_*%@~Q;33+@l7LvO(Aw?+(Y<~iuXSO7OTMQsUKCvy zb@h?w1U(k7r6aA9MN}p27pw%F@?9Xox+Ne%g&K9&5xXkxu?ZgM)To0B0Da*JHtG_< z4}ew#FcTrn=GmFoikFE}y#%xAr3|$50yG8zwp{|ed`<>lTEcO(s=JU*F$>$M0pF2XskIMF-~w2MY!P_zE;~ z0005JNkl15j)sR!L_{?a0%4@Sj0i06c<m>?9ew-2dXcOQ^jx*MQ(6K6pprecpR_-+PxD#(%&4s*QR(g4Lc;rNNH) zpxtW_qAxKZq>VsJ3k)e~0q6k}01yCD(*P9=cG0QzQ@}V#fo>Vl(VnvcZr}pc+uCzF z00K@LI@p*rvXkNBU<`XNE?*^f#=n`im@o-U8H;3zvwp1H_#Q*U76>p| zqVFvf;GTV3Bqk!bepd>tHUKsja>n&dpvgCZI|O2-gZaQSLRO0G(|BPkLx2)-5tH1E zS+=djjbpwx#AX+_d672&L6DdH4K)*t2p7v`0gyn*xqWc403+uGcgz!Xu_QnX0L(-P zvw1qOR{pJs)G)zp@dIbx$`5MVK-3U`?{5KNwu4Z%pwucFb-BgV{6ZkjPAfRYuW4<5 z82}Bd1W?auI{A24ecNVd3!sYF?iS!unE3ek(8$<8c*p<%00000TT(hm00009 za7bBm000id000id0mpBsWB>pF2XskIMF-~w2MY!P_zE;~0005JNkl15j)sR!L_{?a0%4@Sj0i06c<m>?9ew-2dXc zOQ^jx*MQ(6K6pprecpR_-+PxD#=rflje0wR)t*tM!H)Q#-D?n{FEJpbjX+Ba3@K>= z=m8S|5CBrs02K^&(W&)Qz&J>OZW++gp0fgO-~!a!+H*Pp2psCA!YFnj+UpQP2px#0 z0Zt$zTKZE+8;5aN`U@0u+KUFbTi;;InOJ>SJUbAc`{Cc4`-g+ z1ZS_0_R$lIBoW*!V-=V%2}~J_WQntWtlan>L&FvbFj=DSEfnCMeOn|ZBDj863amB& zHWqTm^-ZA3H-S3@Vx@!mz%xQtitN*PVJky`5^)ie+>BYat;CIEzBa^W7q@wlHvmD9 zm;4Pi6O0HK%VhzOK*+gpu>d3I1$WF7bg?8r3joYS2(x)QuvY%9h}1B_Z1DqU-pUVZ z+CbD0fbVYsVYY)%wxHB18g;qF)cisq%}y&g#jj~?ei;A_s{~NbX*&6MSAE-NXA7W; n*zOkKQsqNh006Q6(%;(`1*-zw+WRDS00000NkvXXu0mjfrZoa| literal 0 HcmV?d00001 diff --git a/graphics/pokemon/pachirisu/anim_frontf.png b/graphics/pokemon/pachirisu/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..55d20e4922e272762fc31f7d65dabdb1f31fe9bd GIT binary patch literal 811 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 T_o7jh00000NkvXXu0mjfIx-3U diff --git a/graphics/pokemon/relicanth/anim_frontf.png b/graphics/pokemon/relicanth/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..1ff9f7ba30dfb1ec39d739a2dd9aacb122cf101c GIT binary patch literal 1257 zcmV=P)vk#J~u00009 za7bBm001r{001r{0eGc9b^rhX2XskIMF-~w2M#DYM9mhF000C`NklF>fMA z6vuaqr9mkcf^?Ee!His3P6Hz%qfL>Iu*RB|PRP27L4gn8+ai^#Ye6>JlN?bPkn!0Y1TMA!fort{Z;LmSRROpUDhEA00_Pe~szVFV z!}1<}4jqVrVQ~HrP|wYn1mynMVPeY1q&!6cTI}Ny=glV9Uq{MLaE{Bs_k9|Mb5DqP z1(Q&QgRDmV{?+eJ7&h?`u`(usDN11ZQ`8ANbJuGR#b}@b@+q7~qJx)UdF@eb3lq;c zwxNv~ZaskNmM2D|C*TDDWo&}&%i@B&hQ(t$@uCfy+^tsRn*IYS4@Y&ML{>!Uox_r>N4uaDSvpa&8I8J<=H z<3Ho~-bevR0kR7Tph09(9R=eb4Fes;PjeKA|CNHII|{_V1TNlfa1@At*Z9g0et9d- zP(jul1=8IPul>vA<(X2D1Yj#a2(AL9APGk??GQibRYFz@l5iAr?@(q^T^UAY%~6We z8%P}G6bMm*f$O~*{G}O& zRXUW>tk&@mklz}Rqbi!C`xP+P9R{Mex&rQc1kOMc29i?%_`%P2U2-5h)Y2XFKna8z z0VqnFb1#^q}AGcPpSMdaAs5O#i}5-;Y>`hQW11Ia;OvtRH=W zb%BZ!1D?X2?MJtr`LA={9**MKXFi6z@&_;=P?UBoo=pt*l^%$JP>M2)2eAF>FHC=! zFt`IufFlv#;nl-Kp5OhHBtm(MjXs-BzQ`$H$qO-d%z=}9{v3BHQ<}RU(a6f?>>J6lvftA T_o7jh00000NkvXXu0mjfSAi@o literal 0 HcmV?d00001 diff --git a/graphics/pokemon/relicanth/backf.png b/graphics/pokemon/relicanth/backf.png new file mode 100644 index 0000000000000000000000000000000000000000..f900aa794f4f2bdec40f2495e20ca19102b0e2d6 GIT binary patch literal 649 zcmV;40(Sk0P)5ANcR}11z>#wWCx3dRhama(a|SS&{_0 z0C>`>1-*k&(ewMjW}BJ3VqoEa!sXcnfu@AF4v#U>Z@&S)q&h*MDKQ@DbvdT*pI&FAz+b>iJr}~yPaUB3%?+gi5L0OQn~7!4 z`EdXUBsK7riNC$`Q(fCT2Momr5m$bGd#~SK3!rL1=lcRuQV3PB3j*!z@P0w>k6;gI z-_wl6wTnZWf&hwu^!9vyaR3ZC3r^D+w~4UK0RtA8SNz(PGwQm7mVd1Ue zHqE73T!n#RK&sDe#+~aXeZi1$A=7=}LV!wwNCrGdOBo>sDshD4fI+Av<}pZRLT08m jiV1xTReb;daF^^q(~L|GAn?`*00000NkvXXu0mjfGS?hZ literal 0 HcmV?d00001 diff --git a/graphics/pokemon/roselia/anim_front.png b/graphics/pokemon/roselia/anim_front.png index 814568e648db05d734c15d46b413e3378fb7e0dc..218bac70d9ab7b3a90447d81d14eab41a61fe819 100644 GIT binary patch delta 1013 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 D(Xkqn delta 1155 zcmV-}1bqA835W`iUnT$va7bBm001r{001r{0eGc9b^rhX2XskIMF-~w2M#JKYfNN! zkzE=jt%)8?)kZr?wB1#TDJg>o7vht>6d)anj$Ow_fk<33#);Nuk((obkS*;&lkVf) z>GA3QpX0v7z&JWTCkXh_3_w_ZG#5c6fJi4;MdmQ}fRw-j5*fh*gbZua`P5g!Bp5v& zh?%`9!03U*4IvVEdIv0rs0xoWq9|sj z`Bdl(qWEn|6urEd4nHSBXyuO&01zur#cihj znZ#;(1|ZBYMs@J4!}{j}sl^bp)_Qk0gNVhAK)zv}-{!@6KM-#<+HGsvBPDu(;?t6@ z)oOI-#c5g;6TSlNMx)WSJKCm~OcPm5`3iI(-?mNlluSZSXM6x`aR^fd=RkH(Nh$5` zFv)k$VqY77WVgOfHWwBD2$1fWXR(bcslQ#9Ntt`tzb|R=ZVMV%8h2PFtM8>vLX^Si z<{lBZI_-`H>r*ANB>k~o){z6my%sI2(K*9dK_DhPB?|Y@8T3bY7UG9?*EY{F&T=}% zl)yedajpjA@!z+=ilCV&GD;1)oQj%g`+ z1@jX3?9~KtJ$o>^zFp3y35}6PDcP@kiyFB=^v56X*7sCKbwFNtGsHmNhr`jwkVSuF zctCFHYCIg?ge>)Z&hSJxhu!he83citY#22Vq#j-xJA(Dfd;j|xM%!5&e1fs?pEOmWY_n}(;KF@aB+nE+y&lP_6I{{=e= V?sBXn;HLlp002ovPDHLkV1mq08$bX6 diff --git a/graphics/pokemon/roserade/anim_frontf.png b/graphics/pokemon/roserade/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..b6bcee6a9bbd7ff98f536f712154109ac564ecf7 GIT binary patch literal 1264 zcmVF>Kpb5Qb@h;UFMDo@{HP2UE4tjuLHmwPH%j;K8l=WG@9shoocIu~8rr zmyB_uwHXYMLV*}43P{>A6qPusaGm81ojO(WmQB>=%~Fq4VH@Im)Q~OhLC~Q4cz1ew zy8q|6&oK~+&(BB_dNc))79Y*T5J@01Nmh{=gaRNfv4CV&3IHj~nshe(g%k#(#{)UL zHwG9z1bI!01)kmki?lr6miJOHi zok5nr-j?McFK6iIB(K;&1hK+6s1^HPVx0kO>{M+G&nxsFQ&`z9epM}FjOhh9Q&m@f z`Rz@4_mlw$W`42o{!Q6gW?e|Z`nI#PQ{L0qch)4GBL1$+282BMLp}DpqY;a+a+lA2 zf8Y=PWB^7%>-j<4Fj`a#!Wif?Dm;1J^{EvSjd6wI@es0up+7N0qUnWSo+l>*$lr`2 z1w8N9puo|^@d)DY>&Y)scRcSMr)-k_%GGEjlE_&eHXQF~MI=Viu2|1E$z=p^>Rua( zR>`(sipE?NIH=catshgkqyUgI&}5559RTm##3fP$K(HbQ=)w%%PbOB$MF-`gKeymG zHP1OK<4rYS4yp45~G8h1y4qw3~l;ZO1%sZ`_1wF;_>+EZ92(MmG zQ50($z-iq7@!yD#+K%Kzg2H)*A2bW{{D*7RlG#^V_^UI|(EjwPw>D_ejeDpiO8=+ild^ zv+_7C%gKoX&04M2_FBe9kj!9JPEQnQLB8oZ`Y8@W&15G4*y0e54$cAZp5pDyWQQ={ zI^(~z@ose$Z_I0xBS5<4obhXATz$K$;u80;dtcHL?FKY(4eqdvm)|QJ7;C-3%{?OF zwwf&$)~AkDMfrWTWC=bH_gXaETI&oUO#m?w3D&rWey=;Yvk>1m+n#fd&^l)kL@=n; ziGS4_4*$9Z!b3o44t6L}3h>FvupbcGohY{)>l=i?I|+&w0zNo^TR^C_99OeUBr4pq zS0OM8?7`srb~!r^G!_g(@P0K|)WQge?(pN?`X0-u1;~qF1|H!|O-~-mZLjNkl`nLWzt{P_%UdfNs(?QBiFBh=?5ksKO1; z+ZB;?z`!w5 literal 0 HcmV?d00001 diff --git a/graphics/pokemon/roserade/backf.png b/graphics/pokemon/roserade/backf.png new file mode 100644 index 0000000000000000000000000000000000000000..1b037aada617a761151d4d6f08e1c066f676cabd GIT binary patch literal 789 zcmV+w1M2*VP)l&H6vq##@(>A$b5W))7^xcr9LiRy!FCvu(PvhZVAB$sEI9WC+K3NO zMRHg=Atha_s)?r#&BTBh*l3rkBUviOrtgd$8{05febV`W|L^|q9e#HR{bP~aEN8~0 z4Jt-R#L{d%Fv%gYByAujg^a{wHcpkZGf~1GAeF`_lf&_Hvm!_VfhJf=_)NHjMUQwR ziHYrGmx~Lc|0u*unMffa2Bkzokb)>l1#d2rl`OMIpg8di2q8ukI1GWZukWCAfRsId zLSiK-fdLVh2CEqasqPbmJY5>Z0McePzP?Dxq~hr>#&MumlPZ-80Lxgd5gnO~Dx?Sw zRe23SDU~aPRO_jL;sF}`uG#=7FjgDKls!NuRZc1FEVc?SrRRCyw6Ocpo0R?7Ljb#8p9551Rz9oz1BC9 zfEoq9BmvZl0n@1d3|Vx& zjI#6lXn)3_?Jl zXN)mEn%F?Xm6P8+2K_SZX{v&#!)QH&Rh{?S__gCW!_YueDb&b;(H(r>#aOX`Fdhx~ z$!kCfw%NTyPY%A~yk~Lk|BG~axcS5Ej+BGZ2;)5H&P8Al0rU|Mj6H`7^xwo^EaEzi-n(6oAhtW@1Qeg#oenE)GcT;(Ij&b*XC0 zUC&9c49NnxPG?AJ<{*{-ft8IFWx5Qg$W#1B@tmYcsn20Vf;@T3`+V=+kKAWM_OXw@ z7p)yR2a|?ZpEnq95(}EOfCbl{&9){aB+};?| z&l%^PYwqGN(d0fbLEw4@(fB=eNf>1(+cjh_dG!^}W;ox3ibj^*2Mj2Ch-SQ#hS7c)6n|m`Vh%4-aUWnf1)!M6%urpVm)j*c@D{E%#k?sBl_zq01Ou~xdABXd zP^x)US*r)JRlZMcVXEO=gw^e6KFa0jwmsm*LjKU7no&{Y0|2#DLJ!E>!zDJN=CbD8 z_4^bD;3}^>+1Mh0eOwEe)N$~@94rb^2hbQ`v?ywU(|-;EmlEfq2Og)Xh_a~|)d8{N zk^%U{%xeG>x2MnXL`zZsCpKGRe+%woAODoPSC^Q#E7>GF)s41o-l=F%n<0bkUZ znV~)NnH{4KJkbEG8`x{W20p2p*`VFi-|Fs8s0N7cBix)wyJF^8w)H6@#^Tt3wPv2l)0!#zRVVx3THm1Yh9j zilLVDN{h=LUC;0{YB8V7#)goqAGVA5xTn(rioVncK{(_dZPKlpa{r~{UZ%< zP95;%M%@h!aFHhCOzcp1OlA4myF=~LWb6-ikK6l;^nZ?D+Rxq($^v1d00000NkvXX It^-0~f^}hd`~Uy| delta 824 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 delta 585 zcmV-P0=E761f2ztUw;4za7bBm001r{001r{0eGc9b^rhX2XskIMF-~w2M#qQHmP@b z00062Nklq4}dj$&ver5m4!MzkZa%tGUdH8M`F{gxCbiazZ_i=R5y?)|cQ0+iBvVt;sF_A>#Q1IpzP8xBC8 zmkieH^#V|EK|l{cZ%f{Wg&{7y+zq_iyb4q~wGHo@J|uDTTTj zfjIU3{M9PQzf&z)2yAKXE2^JUglz!OE~BdR8>$un9kH-oqou0>2#3xYy~`!wzRh&Q zw{|?E+cLmYB^=V*O)U^B*uHYM#@|xp^%WOLseaDn~&FrU$q$< z)VB^ztf7pvlS5UgDGpw|P6vdp&bZ;xA4WPdBZ>Mi%@|h-b$`_ZQR?U6#X85oLoayATp^O>TxV#NeJ-`dJNPnv_=V}vE_IhE8UOl1EAVq_! zIN34pFL%FcS{u~Y21%=Hf`7TuEL4ZQcvXr^%IG z!b5dzhr}jfEA_mCP>|=x%zr*GjD6bwS+wjwES>;+;XF}3?|q`UzUg){X#Y#%2=l8~w001N+B4;AW5(}Ik0Qr;r(!8DEL$e8h zG*8JTR)Vt0!f2?^?8|mD0ARnH2ph}*ylS>@%?M=1FA{^MJy18z`48W_Cs?TF5_h||NaHvWgd$og|5CK369suwxUofr|>Usd8 z%=g2KRgQngUh)uFo3pQ|evA>;0br_RW$O=A%>bJ5a9o3BiyjD<&Y5}c=YV^eSqy8p zp0{}bGUe8j$}ED#_xn`*1IXM7UgvW_;s9#IlMqRNet*QP%T@3q=v5zpdhH0Vxh;t1 zM_!ui9bg?1%7{^|^IHQo0K7ztbQ%k;b_scJSElGS5DE=awy4UB9rN+}@T;b^L49kH zV)bpD+#ISzZQ|g?n{+_v5`AELN0qvBgtv}ih$DJHI=!R%40k|0is0CyFG5ZL)qM<% zDK2&)(?9GP&^iFVPc-Pxc1jbVUg6tm8o;$m)2!I9?b{517TB3K)2(v){Oj}VFR&5r UJdu$KXaE2J07*qoM6N<$g24g}aR2}S diff --git a/graphics/pokemon/snover/anim_frontf.png b/graphics/pokemon/snover/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..64606881f88c8acd4dc9336a2dcf102158a88c95 GIT binary patch literal 987 zcmV<110?*3P);000AK zNklF>l&H7=|6mLRB_H=-h;`bPHFjQYSaL5G!=S@KqHPYLMXvq(1MV$#w2f zbq*|nF;ko|6Y-DgcRpjzaFD4|D{&+d%J=SRp1Q38qd*%OrHiBIuO#;p`(C?-JSe*lfuJOvxfFKRPDrQLF+8Bgs z#{vt|0BiyflPK^yTL7#p14v6S5(sXn1PXp%0wpY$Z2VIeV-#4Axd~wMz!#IifYK2; zLM8$F0poQ!f;+qka2+LbL?qA@WAs_bsRT^!-rzLLEi4KE1c3A6*TeLI@FBkemSNeEo=Xf(hC9fvb`{m0f2bk`;XQhr3hgFz@@rf7~ZPZ$iB6Ag&D6; zu-?w^>ES6<@i;Y$2w8Znmg{1eWFN?ZW#MqEb;H<|fY>Ymx>`4O38_fHhC|(XJRr3U zXzPGVrBWj@r3$)}k7WdE;@1Ps6pWLkyLeThx(-PC*8seAKsp0hH^i-6!y3ROA7=Bq z9%xPDTVjs^I%Dl~Fz=#xW_M-)(+4eJG@>XPPor_?IT|_ZfCv1UM3LLm5xY^^Mh$l` z)DYA2v_84#*XfDR1;kGYaW{I5T^%rae7>i5*cx&Cq#NSX?3v<6fYL_%Fw&hUlg>Y@ zjreKvm#s;i?Ul4`Tfz7j1jBeqFtPweF!TY6VCVxB!O#aNf}ssi1w$L43WhEqCm5?O zFBrP7uAE@#h@4<(m!SxT4k&z81VdN9s4WCT6X0KvgPZ138 zyGn20XX3i-sDc5X{RO~819+g6J+H`WWD-g3)f_I6*fvTE_7X z%LxYF^uJi(&jUC`tIG)n{V80IC5!2Yl!{9*FBoTNgMqZcLP$LKA1>=m-3^3(AeXaE}wUAd-UI2-KouRCeGTdWx=SxDG*ky;4 zT1U>$-*9m4NAxU9544zK3dqi25+}f4h;Irw ViTQI|U3UNg002ovPDHLkV1l`7_uBvf literal 0 HcmV?d00001 diff --git a/graphics/pokemon/staraptor/anim_frontf.png b/graphics/pokemon/staraptor/anim_frontf.png index 62715651bb0b81726a8800d212fe0f5fc97972da..37e8b5cfe139a18d5b747f5ff77bc09f53bdd5ae 100644 GIT binary patch delta 60 zcmZ3*)xR P7=YlG)t$hNtxH(|t3((^ delta 100 zcmZqTTE#U%C(=MeqaYzdKtLeC!(oMm#)}9C2Lp=<1q~Sy5j!@l`0(OIL4d}O6%hw2 zEEpIVir>yR2U45`9+AZi40_5S%viD1z6>bHUgGKN%Kn^hS&W9(8E0JFUw A_5c6? diff --git a/graphics/pokemon/staravia/anim_frontf.png b/graphics/pokemon/staravia/anim_frontf.png index 8658532ac74d206dd61553617fba98c0d3c942e8..40de79a60864749339cf574cb6842471ed7d368b 100644 GIT binary patch delta 55 zcmeyxeu;g8p-zN=fWVA~jt?I`Y}l}2M*_o-2^tj+3I!1f78VviA{-cC;E0~x*Nv^E F%m99<6r%tD delta 95 zcmcb_{)>HrVTgx-fWU%=h7TV;tk`kjK!U=929E{@iGqj-3j>SE$@vU0kR0^370Bi+ p@Q5sCV9-+rVaAH3_GLgp_7YEDSN7*@?EG9T%6HUtH^!DS0{|*o98CZK diff --git a/graphics/pokemon/staravia/backf.png b/graphics/pokemon/staravia/backf.png index 36e2f2169d51bfa7bbc8602193432ea9bba3dab5..51fec5992db383f7230a982cb44b459afe6cea52 100644 GIT binary patch delta 583 zcmV-N0=WId1)BwsUw;B7NklsSsffNDw2i zUfy3Tjw60f%p}Fz!yi;F`Dg< zo7*D-?YEyYnq=#jK=<_fQpD=(o0mZM;d@NbG>_vI1fV!}mkL%*)401#=#ZdL@20?` z(=h@^z^5w*pMOHorc{9dp{KxJW@vbtooeVmHn#^5t@5n`AS)(gX9@?9ziUT&RT_U0 zJj8~Jq$dIJdIT~IfKLGuM*u-3YjcKYrbP)c{*NeC+h0iNhDK(4HSqN5CwO5}Ou z1iKx?rZyG8w(ATqzzabs`hK{45poiw1FFgaSPv9e8_$qN9w04N3;^qYuJ&%`JRCqx zL+kZ=7(mXGojZC+>6eRu^TXt$lo?K8B=v%FTkBkXoSqIY#fj#za!oHyEf@b&`~~sV VoTV|jtSA5g002ovPDHLkV1h^S28{p! delta 623 zcmV-#0+9Wi1;Yi9Uw;4za7bBm001r{001r{0eGc9b^rhX2XskIMF-~w2M-Dhvtv5E z0006eNkl4l z)RUjGq+}`aT_R6iN(6{)e&$b!q`X-C8-wMHA61$1XNV|MfPY14b;6$`mN}Nm3@A#O zQqYt}nMzSFa-B?pfP{izAic<$Z6W|?0X+xcat=^4r9y-`AVG}4dU?NAY{&KI#7>gE zJ=W#jQjm$_fK>ueO11m_9e^c-fYp9`TO$X7KvsO&{JJS(V62ygvdN z2Ec~^i6a1^12pHzRc1ng4S*@bdEf!fiK!UiCZH9s@PB>%$!U4u6-C@cfYxaHdITy5 z@aj2BI|7pY4p1;E@bhb+eg;&}022ThfgGuiH*ITCS)~j-c%a`!z>;fwI9L=$zzC2H z5RPL?Lddo~(d+b+xOV>CHK3I4x|0xA2m(COUw~X$0Yyg@LI$gT#@kdHJ#TC5lV_W!w>-OOn?fSQKt^?Df2lgS-5 zr1a$?;QTQ8C}oC27)iaL+-RMvkJHn^g*eeZR<7x#spaB-vcI+roXI@90g(Uz002ov JPDHLkV1oAK90~vc diff --git a/graphics/pokemon/starly/anim_front.png b/graphics/pokemon/starly/anim_front.png index 0e834f3bd3c84bfa760759e0285385afc3534cb9..b897ef874ac25bdbeb61699a38d18f24a401aee8 100644 GIT binary patch delta 807 zcmV+?1K9kY2l)n&Uw;DxNklzfT)66vuO?42;+TIz&jZ$uBqsi8@<^)C-`N zZdAQ=$^Zg0Acj^d8M;&vLL4LNkgSM-vNeb3VD*nUBv2Rco%%QQ`3`kC+gYiaCnd}K z=Dp`UKYv~>H?e=!99kNqn7&=K)uB8gfu@?ogG*AgES3$2)US=X7rUg+@@T zpQM7gl;^t|fgcV!_{|)DkIFKyTs+5LKo}u{JRwFi*&1^NEJ)4A zBP@hqM04>9ML~~tJwb$sRteP#j-VUjn}`@{>m%?)z!+OWntnM+gnbdMfnPTq&PwY$ z=LZp6Lm<$#8?)B!eyhcr@K zS0=$?cy{r5X)~n8*&Wc*)L?L7c^u$VK0mj=FmAh)o7lwuE5qaNyz>Om9%HM!A@3{! z+)7{tw<5QV%a7c(gm63Dz8v^GjbO~71l{`}6==Yl-+}-gRVU=ofY+q}ZVq32AfOuX zy6EQ#-+!*cQDvN$I`Go@t4=DwdHKM9WV=ego^DqN-$&S=4|HUHMTaM}rpQeYtSMRW z;@`*59?3l$#M!R9%fALM6F;J}T@8}R^6)rF$?k2$n!8KFK1tjdc{jRil|LpZQFv5D zZCx+C8~gzz1lS)nb%NqejnfZ!R0Q_3X*Zjs2!Gh+2c9Sb+gGV(Jt*EPfe=L?E5kTj zr=uc#5()g(VY2^J3)m0KN0Y4-KtQrZ6od-E0RAd~W`GtL91z&v^tBlv2V*T*4uI{x zf&P!|H`D*`c3_;(bUVOx^LX}??ZCVqoGRba^_6KoaA7m3yO&|#Si)kzlncW%^Bba0 lM<6#B$2?E`4wLirRAAqr5v0?xK002ovPDHLkV1oHrc_sh= delta 844 zcmV-S1GD`32A&6yUw;4za7bBm001r{001r{0eGc9b^rhX2XskIMF-~w2M-Dtr($OF z00094NklJx?1!5Qcpx7nJN8NO6kf9e=_JB(n~RNU^`dNGY#RmEVxrJCx>j&n;0rl7HRI>vv|oAJ61+llWJ| zg5ns()BAB2(HIMBG)BNkroaY|X60cqipp7ee>;kzX|w;F5GWX#`x8QBT2xT*Aw!@l z#15kj!G45&ngo@O5WY}-8fpM0cR^J#2&z>f=pK_2qayB|-^d#FcV5lkPEBppw-*I;2uc&NK(F;7B;$ zb0w29 zEbNZR9)AuzkvJG@D8cqmKM`oao8Lr(j_MO@XuxX&f?MF%J_>dK&V&nb!2`8gHxy}ax>y@X~0W=pFDXW_pIMY@4CJ8 ztN$|26PVr7Ac-vvPW*)I?s`LWc3IG4ahekMR)2S_@+XYM3KwM9*6oFROOH^(ko{p( zCva|S0*>g=LH6@$J6*&`10XvPEQP6?!RkgS~2bf1=T_$*`itHq@MsTQ&y zhmR(26i~p@O%$Xu;0S+Zpt(RLjtfM#H$80yHAwLm4hP6~&p`hN_M7SdcRDcM&ty8F zbw%^_?8Vc8c|15%xrLi+(|BOxWKg%Sf}XL3`Cc&>1n1^AM6C`s=Epo^WtiaP(Z(P6 WUJx!wcvC$90000ofm4vEvqea~0BY$* z)udAf5SRfmv{K2?rHT;Z7*U60MGTa!IYbAmf5ahyy4>EWe}6-tFR07e&PvrhDYv|D z-h2M>{CSQuv47QERve=!+>Hy7j0xe!V+0gi1&9U2=4Z7eDcSsqvT1YtLMn*O_1(AZ zA!(3+<{NWBq*1KAUktV=(Mx`LL;bDPey{c zm=n7iK@j%a4`a7)K-NLndC?>ng>fj6RcDo-jCJ(Tb%&FIs-s{V* z3V=y@FDpO^TX?(i4*n0u4wJj=RlzfOWOB$lnv3TK^O#^vu`lItCR?MECz4hIG9*$; zPBj-V?@4yF>q{zSv`U#)a0I6zzsZQ>rapp51)TF0tbaK#H;u3_qc!mBn!{abd>7&% z;%gWLy5lCial7AW@H%XTwtL)p$R0(UQ%v;jhm->Bx$%uaRQa36?wvZlVC#%sUzr4p z;n~IKrOl8Td$-SuQ~myh<#B*t>HOUO!k}i+nb^esD`$;_RuTIah&6YYhCQ0P3HEPv*D7~RajNi{ zjGDT$@NdWmkWgTMRM!c-n~Go`$j}4!^J$b#;sJKWfiFE^`zq6n2i~m`Na+DtIU(6P zT@~SzOyREIm>>A={Zqv?QD&F$GsrvvkNaH@Pu*H@U|<*+Ah@uo`1ttX*wA=L81R5NuvjRVfPipVSa4uq zkYH#40037(y%GQb010qNS#tmYE+YT{E+YYWr9XB6000McNliru=LQE43LQtckL>^e z0`^HnK~z}7?Up@H8$l3;eJdA~>>iN9jd#x2hLe!aYfvONIe!C6NJktyHD60X6{O&T zCbAIXC{YT#MHGZCK17QBL#gr`GJ8g8Zg<@h#UuHec|EfqGy6=TFtdNvJSb05_>E~H z#FP+TG)2IvQ$QeQExiy{Bipe{vQnvL?d4+ zbb(GxjiF;GJTDF?qmYXWGi`kedr35z=o_}9baCR6fu2d>G7zJl|8|nx8 zY1o9H(+hZnVeN_mosO^O23bu-a=I&QT@6OY2!Jsx(ANK+v= zW#;xHL00vmVSOVA*Z#J(d*`lhVGH2l-X>T{u5Z7t?j&IC-653chQnLO5#vkW z(F24Q7{FWHMfCUd0D(CS;3a_ImiReB0T{qb=<7?lSLL|Ss3=U}1^>P`5wN1zkZJx_ z;rrFzGMC4c#eUaB=65i9Ho^l#NTselbt- zNlJ)ac@nA;vONOBcu;!M0;NhwR>4?)ot} z;cTx17#b)LxItulGd5<>gOq6DaDZ%&E%bk8zn%Vnrvqz$PNoA^x3}jYn-1*b!Ik!{ zKHS^J1A>!5o!lh@>k?K5vC-DIT#@N?-=*&))s}6YymiVOynoz}_fHS(dC$=l9WiNr z_h-!zRQ=C}>(Uw3RbY94L*Aw4Z2Ek_CtX^G8nT*n8oUv(U(*!ZgYQPr+X1~Y3($yF< zhB1)DWD92IT*~)`rRh&ZBoiP;SnJ_+3Cvk3Fq_)nNq-&W761Vh0`a0`wH2HEO1_PO zrQc~4LZpYloG%s@ya7Q2ruH3IUcJVk0B94Cz~vtBb?{@65wKgLPqu{JChaj^EH29o zWe^B=FCmy-!WdVg0?WZJ@J6&<3*es^>>cC@C1;d3-UzmT3`4N{TMe7Ob}>jMis>Uq r0?)@PN+Q7y4{ll)EPVdg`v374L%`7v!xDSn00000NkvXXu0mjfU<3lW delta 591 zcmV-V0e4Kcntyg-K|;q|33O5?#5X`J z@C~YtpiX8<pP)c}xEw2c}8mlN$4O4_(~3V&9BiPnxjA}$00(bMmpLvSttp!c!s zm_gWQiZ_eK7Jr}$eq%m0SE%B~fSI-cZf;NeVbe8Kpl5Dho&EUYZlO;Z&VGIi8iv?_ zsQ>W&ZRi3$W8m)LKAO4!H^$t34V^s#5HR=d9&Hom^I?K?v=tMx*a4m5%uRRh`l%?aG&2yV3NLXG2z9KL?AAkSN)?>^WCO{I?Etts*tv^VX zWq%NnOn?|+t%sK-kgrRD`P}|a>marO2%u7kmnEyMSjN}-T>>ooO{-8UI|TA#xwPOM z6b+c!cU*h*8iN9$O+W%yd%zdL<1!~;w?v<81-nh!W4v5ml^Mz)5bj<=Fu#H^u2ltA zgI(Z_Xh^#jz>^s49pnimXOuVD2)2I=L$Lc>51YPrF-We8=_5x1&&MiC!43~@UKcEU d{@42d@eeaQu!IczQ*{6U002ovPDHLkV1klA4cGtx diff --git a/graphics/pokemon/starly/backf.png b/graphics/pokemon/starly/backf.png index 3851350df0c515475de75c32304a63b73abce968..f1c45a7bc69c3fc40efb99eed736f7c11e354813 100644 GIT binary patch delta 547 zcmV+;0^I%e1j+=EGJm9VQaBhG*vO#x`1s)9$e3Ut_`o30m;k_-fS_ftwEQ#8Kl^7f3hXQd8q}-^IJOLV;e{oO}bz{qp|xC4U&kf8<4pbqe3h11L`5 zh#d)NSe#&wM!P_`s{};Fq5(95N>L2}A;O|jZJ)}@4LQQ69 zJ>Hu+Lo9(^dw+fsmJU=ohw1ao?&tvJoKNp8ZI1vF@R`0x)dauUPT)3I;)@U0Kq)>m z7wi>*EGX@J!-~OPNC4(?-6UJx^E|idyX}DV1C_>fNRR<#Cc)sd{oya#7!Y(oN_1CX zAiAD+A&Bq4Bce1WqK%mzjuRk`5`jTq{dTe-QUD}C#(xld3CpZlL}TyF0ph>PRWRmn z1JNCg6gUAU2lUlDE{trAdJIq{kOJo$pd6ZSqd)?+CHcwbu->FP#@^^O$&iEu*7_xw z{ZnY;f~8L74?mS+>^Nkk8 zwBI1g*s7DefV}m6sJycsFyJ#=r@VpXetQ4>Bs}je>Y}B_jqmLVG$)AVo&;PpCph5I zJ|Om$fT&pvfJe}2ssSLSXc{#HE~Rt}CG*hWTx0<*wWE)a3qkLqt8bh`a4rC#d)sl$ zAnY^6$60L)P=5x$GGFQ|lyPOij2i$qcSpUT?ixzaHFw7+KfbwJ=uw7~pAUY`5GxS& zo*zF2F3>dw?w_B+u?uix%>DPk*&_e}^W^T)HetT*CP;>B@xjbCKr2791j03eDrg<* zS;teqSO)%T-K<(&Yn=?!WR$UKX4CjF%POF)2uw~#|9{fu2s4H;ki=vSCh|<{&yuC- zUqmG1BZgS%;avgb`$AwgwZG#kh%5jCs1)LP!73}3(WSnQfu+A`6-uSMK%UL#7My~j z0aN>qORrj^p98cBNZ?`%w1xj?o)NHHqEEJf%_i+Jp3g6e3`GzKHZQ@SUcd;KssxMv zCh&%|T}KPxRrI$G@_>>v${Vi)+dhT?*!?XBbzeIlBvbkHp(BCU#xe@Qb`Ne^6)brB c*ZTkQ0>Zzr8dTNh(f|Me07*qoM6N<$f*&9c(EtDd diff --git a/graphics/pokemon/starly/shiny.pal b/graphics/pokemon/starly/shiny.pal index f077f79746..c49fb7aed3 100644 --- a/graphics/pokemon/starly/shiny.pal +++ b/graphics/pokemon/starly/shiny.pal @@ -4,7 +4,7 @@ JASC-PAL 152 208 160 96 64 48 16 16 16 -136 104 80 +164 115 82 56 24 24 216 200 160 248 248 248 @@ -14,6 +14,6 @@ JASC-PAL 208 152 0 192 152 128 160 112 80 -112 96 96 +139 98 74 247 82 66 0 0 0 diff --git a/graphics/pokemon/swalot/anim_frontf.png b/graphics/pokemon/swalot/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..da17817ece8f61d09a06ee4952097be98c7d51e3 GIT binary patch literal 1108 zcmV-a1grarP)ziZq`6vw@Vg3Cy2lhSAuB?n3tG%td{R=M5u>yf8Oj=TRMXJ*W1KJ8TU{ePo^)}qF0enyf{m3r^F?7Wr zjXo-`#70~K8}aQy3_guc6<~)hpH|pGz=x1T(|Qw(K?;2duq426NXVpK!wJI_X8+3j zCkz-)olKM(e1yP4rr;s}h*Kw%iF%{k{Vcl>KtG$#&kcZsfJ|{8f%%C5PE}x*Wtr$= zCIFElQd3CaLR1jIoQS2S_&bv|`q^S$0%T+WU^c<{Spg_V`d85dj<9G!tooDbM6>J! zwNtH;J+1nSg=J+Jym&K4B&b2q=9}@B!(EJWMd?Y&w z#Sgbg2F_C^=T^~iT4KM~x2=xbqVD2rhF_Yv#Uglx^t$%=QhO~`I$zQMnn5t9kPhSf z>c1<7)S~~L;lK}8`fmgj!D#BgrYHu30Mrjw`riQdU3V+@TJ---lIQuCmHz9%`g;ld zQR%-K$kR&yb!|S}7r^d+mHzAMez+g!`85JhEWnY2z%Bxn{*N^IN8nllrT%M!c!|KS z04n|0CshHqSv&r<0#FU;q+1BQ2%u{LyaIr@Jap|-*(repwO?2Pa$nUvchKF+B@lQ+ z=*E<&{-E=?06wGqdqdi#UIPexKfiu~GfEiHlrplID)$(&Z5;I%c?dy5&>u_`hq1;u zhb=s8@#J$Z4TdJ&JWbK22(Q&&%(*ZaiUq-yG8_&Q+Psj`tJ{OM^faKGP^$Zh0Mr^V z+vGyLXA(GT`Uf-)(m+UqQOLhi!-=w`fmlq9{=p%$rGc2p78?G6k!WQg&J6wm0bwA7 zY)_5;0sk!x1hM#sm4WzS{R69n-{K#zNbj=EKRB0!vsV9rJ7lZ8%|CE4yH@|e`RJ$A a>i+?=U?JBhT^9iW0000rfKX6SFfcG^XlOuSn3*?r-T&|50005e zNklq?`_NL6tIK{fVN#II|WdE4h}G|0!jeeN7E@a z?oclUI)99P2dx{7GeGB!_X;TO@s3r)tVgFh?SNaCmlFEpK)p%twv2^a^D95vPX{4- UZqPjh?*IS*07*qoM6N<$g5W&z$N&HU literal 0 HcmV?d00001 diff --git a/graphics/pokemon/toxicroak/anim_frontf.png b/graphics/pokemon/toxicroak/anim_frontf.png new file mode 100644 index 0000000000000000000000000000000000000000..40f86c45eccaaa26909bf5906cae5304e72b3172 GIT binary patch literal 1266 zcmVOP*|8aIIyt5`1trZI8gYQpm=zQwaG~S000Di zNklzl+>P6vx*CY7Pt;DQZFtnh`2?;V{y(3a8!u16ERA5+?x{#(zQ}b(*A& zj0>sDx>`YsT)PJ$7+1T^U4Q>VinKOd-poka)vmN^6YvzbC-l*q_iN^TCzJordhp2z zz`_xN!3e=%gm~bL5k3$hMu4+~2F?+DZU}G4$@zj_$1fln06tw15PzLP7%T^XIlN4N zNdSbq?9CGy_~xgdF@uP^1BpcZ@drc)B=0d{WiDcZ2rkAbdm@=47Qa#$PXRGo^hC0H z{Y*}aS5IG&i6;w?r&~<(>nmC0KE$|K%zM)1Ute#xlJczpfK!0+?T)Kl$M}Sj-s8nx z$g4^fgHi!~CML6@C`#G`Q&rgb6j&2bKumBbKru_)p8K|h$VG5-E7#Ew2c ze&-Zr8n+;PzT3Ss)$|W*${hVb7~VI4(*Y{=U?~Uxy#Ggag>8jj{2ng%NqR%|RY3H9 zb7cTN%Wv8vG%b8^Cy4_gm+v>U6Sot0nu``#mp(ltD$iU>L7WDx=8RoXqfm`CKu5x& zADac!ob7=XPgR<^tB(xT{C2`VD?Hiu!llk*z*9@*i{0GWlUuuNqr50Dg)+v3o#^y3 z!7p7|?Grg$vHJK3lmCaDLY%GkwKSVaY6h&U&)p^Ko?#0m-4AtrSY6%2mDt7WuU?q0 zm=KF6z_ao}o&jIwcdRL-=90P{*MXO;Ta+l{d z%zy&fYZ!=xdq%^M03l*|M#Er2qp0WHH5w+Pn}w`I-k^pdiIUK6(XfVz@ykAivDYv_ zz+CB!<$#8vJr-c3NWX@m>1OJ7R2TO7cK1j9CCyG-N(j3*<=ytL`b$K8KlzB=;?wA^ z)E1;4)NrTK>qIB=K+6a2>T8-Ei6tXZw0_`bb3g7lG1GvSD2|!?f!V5w;@iDMse!H& z!qyU{wvaXj^bX|1Oc}_LW+Rwc!8*g6f>#p7qgmuo;nNzhn~G$VHm33;RkE{23s4I; z`l8-WqDrMXL77tl-vioV3Ah7DKtCq-`jXr2sfi5de%S3Y12DS~x3!nEHyWTf@$(NF zP}5HqP4}{O88*Oo_xFAcu%d~Q6?sffTAYN#A(fo6)A40p;4{5J{NW4}*$X@**NA!dI cs2_&bzZyP*Hh!co=Kufz07*qoM6N<$g8I8*7XSbN literal 0 HcmV?d00001 diff --git a/graphics/pokemon/toxicroak/backf.png b/graphics/pokemon/toxicroak/backf.png new file mode 100644 index 0000000000000000000000000000000000000000..dde6b0be22486ed80849b3a90675dc77cd8d2f98 GIT binary patch literal 622 zcmV-!0+IcRP)eXsD<_c%Y!r`1trZI8gYo;9zK&x2b|U0005` zNkl5d{2)>`sXPl;0uF`DPk8Ja9E80m``nR%BY=Ol%^IE34lEWcI32z6FHL8}t>B_yD=( z;Ewlq99T39)Lpf{&hgR(AY=UHdWpYX;5$6{K*%?%lhF&<(&mc?e3A*W0EX@7%mczo z7HDO4__obDClev9HWt9p;IBUbEU-A}B(2Q+t_EnpR^wDV0B$MBYr{lq0ILiplQ55r)A Date: Wed, 19 Jul 2023 02:46:57 -0400 Subject: [PATCH 07/19] Fixed enemy parties not reverting to their original form post-battle (#3150) --- include/battle.h | 2 +- src/battle_main.c | 3 ++- src/battle_script_commands.c | 2 +- src/battle_util.c | 8 ++++---- src/pokemon.c | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/battle.h b/include/battle.h index 0219ebd721..b27062c120 100644 --- a/include/battle.h +++ b/include/battle.h @@ -636,7 +636,7 @@ struct BattleStruct bool8 friskedAbility; // If identifies two mons, show the ability pop-up only once. u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used. u16 moveEffect2; // For Knock Off - u16 changedSpecies[PARTY_SIZE]; // For Zygarde or future forms when multiple mons can change into the same pokemon. + u16 changedSpecies[NUM_BATTLE_SIDES][PARTY_SIZE]; // For forms when multiple mons can change into the same pokemon. u8 quickClawBattlerId; struct LostItem itemLost[PARTY_SIZE]; // Player's team that had items consumed or stolen (two bytes per party member) u8 blunderPolicy:1; // should blunder policy activate diff --git a/src/battle_main.c b/src/battle_main.c index 3e19f247e6..f6d822e3f2 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5434,7 +5434,8 @@ static void HandleEndTurn_FinishBattle(void) changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE); // Clear original species field - gBattleStruct->changedSpecies[i] = SPECIES_NONE; + gBattleStruct->changedSpecies[B_SIDE_PLAYER][i] = SPECIES_NONE; + gBattleStruct->changedSpecies[B_SIDE_OPPONENT][i] = SPECIES_NONE; #if B_RECALCULATE_STATS >= GEN_5 // Recalculate the stats of every party member before the end diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 74e13b6d87..bc85f371cc 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10669,7 +10669,7 @@ static void Cmd_various(void) { gBattleStruct->battleBondTransformed[GET_BATTLER_SIDE2(gBattlerAttacker)] |= gBitTable[gBattlerPartyIndexes[gBattlerAttacker]]; PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].species); - gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species; + gBattleStruct->changedSpecies[GET_BATTLER_SIDE2(gBattlerAttacker)][gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species; gBattleMons[gBattlerAttacker].species = SPECIES_GRENINJA_ASH; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_BattleBondActivatesOnMoveEndAttacker; diff --git a/src/battle_util.c b/src/battle_util.c index 495f26cd50..baa365a0e8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10227,8 +10227,8 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method) if (targetSpecies != SPECIES_NONE) { // Saves the original species on the first form change for the player. - if (side == B_SIDE_PLAYER && gBattleStruct->changedSpecies[monId] == SPECIES_NONE) - gBattleStruct->changedSpecies[monId] = gBattleMons[battlerId].species; + if (gBattleStruct->changedSpecies[side][monId] == SPECIES_NONE) + gBattleStruct->changedSpecies[side][monId] = gBattleMons[battlerId].species; TryToSetBattleFormChangeMoves(&party[monId], method); SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); @@ -10236,7 +10236,7 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method) RecalcBattlerStats(battlerId, &party[monId]); return TRUE; } - else if (gBattleStruct->changedSpecies[monId] != SPECIES_NONE) + else if (gBattleStruct->changedSpecies[side][monId] != SPECIES_NONE) { bool8 restoreSpecies = FALSE; @@ -10252,7 +10252,7 @@ bool32 TryBattleFormChange(u8 battlerId, u16 method) { // Reverts the original species TryToSetBattleFormChangeMoves(&party[monId], method); - SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[monId]); + SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[side][monId]); RecalcBattlerStats(battlerId, &party[monId]); return TRUE; } diff --git a/src/pokemon.c b/src/pokemon.c index 6d5b3d35eb..b06abb6b5b 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -8507,7 +8507,7 @@ bool32 TryFormChange(u32 monId, u32 side, u16 method) targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); if (targetSpecies == SPECIES_NONE && gBattleStruct != NULL) - targetSpecies = gBattleStruct->changedSpecies[monId]; + targetSpecies = gBattleStruct->changedSpecies[side][monId]; if (targetSpecies != SPECIES_NONE) { From 6b5d1e7577eb7249f37f74aace054f7729ffe58d Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 19 Jul 2023 13:25:20 +0200 Subject: [PATCH 08/19] Adds some gen9 moves (#3147) * Adds some gen9 moves * Fix Test + Tabs * Collision Course boost changed to 1.3333 --- data/battle_scripts_1.s | 286 +++++------------------- include/constants/battle_move_effects.h | 5 +- src/battle_ai_main.c | 4 +- src/battle_ai_util.c | 1 + src/battle_util.c | 4 + src/data/battle_moves.h | 10 +- test/move_effect_collision_course.c | 47 ++++ test/move_effect_make_it_rain.c | 34 +++ test/move_effect_spin_out.c | 21 ++ 9 files changed, 169 insertions(+), 243 deletions(-) create mode 100644 test/move_effect_collision_course.c create mode 100644 test/move_effect_make_it_rain.c create mode 100644 test/move_effect_spin_out.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 2b747c3294..3c0950dc34 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -432,6 +432,22 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectInfernalParade @ EFFECT_INFERNAL_PARADE .4byte BattleScript_EffectTakeHeart @ EFFECT_TAKE_HEART .4byte BattleScript_EffectAxeKick @ EFFECT_AXE_KICK + .4byte BattleScript_EffectHit @ EFFECT_COLLISION_COURSE + .4byte BattleScript_EffectSpinOut @ EFFECT_SPIN_OUT + .4byte BattleScript_EffectMakeItRain @ EFFECT_MAKE_IT_RAIN + +BattleScript_EffectMakeItRain: + setmoveeffect MOVE_EFFECT_PAYDAY + call BattleScript_EffectHit_Ret + seteffectwithchance + tryfaintmon BS_TARGET + setmoveeffect MOVE_EFFECT_SP_ATK_MINUS_1 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN + seteffectprimary + goto BattleScript_MoveEnd + +BattleScript_EffectSpinOut:: + setmoveeffect MOVE_EFFECT_SPD_MINUS_2 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN + goto BattleScript_EffectHit BattleScript_EffectAxeKick:: setmoveeffect MOVE_EFFECT_CONFUSION @@ -1121,24 +1137,7 @@ BattleScript_HyperspaceFuryRemoveProtect:: return BattleScript_EffectPlasmaFists: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret seteffectwithchance tryfaintmon BS_TARGET applyplasmafists @@ -1147,24 +1146,7 @@ BattleScript_EffectPlasmaFists: goto BattleScript_MoveEnd BattleScript_EffectSparklySwirl: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret tryfaintmon BS_TARGET healpartystatus waitstate @@ -1173,24 +1155,7 @@ BattleScript_EffectSparklySwirl: goto BattleScript_MoveEnd BattleScript_EffectFreezyFrost: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret tryfaintmon BS_TARGET normalisebuffs printstring STRINGID_STATCHANGESGONE @@ -1199,24 +1164,7 @@ BattleScript_EffectFreezyFrost: BattleScript_EffectSappySeed: jumpifstatus3 BS_TARGET, STATUS3_LEECHSEED, BattleScript_EffectHit - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret tryfaintmon BS_TARGET jumpifhasnohp BS_TARGET, BattleScript_MoveEnd setseeded @@ -1226,24 +1174,7 @@ BattleScript_EffectSappySeed: BattleScript_EffectBaddyBad: jumpifsideaffecting BS_ATTACKER, SIDE_STATUS_REFLECT, BattleScript_EffectHit - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret tryfaintmon BS_TARGET setreflect printfromtable gReflectLightScreenSafeguardStringIds @@ -1252,24 +1183,7 @@ BattleScript_EffectBaddyBad: BattleScript_EffectGlitzyGlow: jumpifsideaffecting BS_ATTACKER, SIDE_STATUS_LIGHTSCREEN, BattleScript_EffectHit - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret tryfaintmon BS_TARGET setlightscreen printfromtable gReflectLightScreenSafeguardStringIds @@ -1430,24 +1344,7 @@ BattleScript_NoMoveEffect: BattleScript_EffectRelicSong: setmoveeffect MOVE_EFFECT_RELIC_SONG | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret seteffectwithchance argumentstatuseffect tryfaintmon BS_TARGET @@ -2214,24 +2111,7 @@ BattleScript_EffectFinalGambit: goto BattleScript_MoveEnd BattleScript_EffectHitSwitchTarget: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret tryfaintmon BS_TARGET moveendall jumpifability BS_TARGET, ABILITY_SUCTION_CUPS, BattleScript_AbilityPreventsPhasingOut @@ -3191,24 +3071,7 @@ BattleScript_EffectThroatChop: goto BattleScript_EffectHit BattleScript_EffectHitEscape: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret jumpifmovehadnoeffect BattleScript_MoveEnd jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_MoveEnd seteffectwithchance @@ -3280,6 +3143,27 @@ BattleScript_MoveEnd:: moveendall end +BattleScript_EffectHit_Ret:: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + critcalc + damagecalc + adjustdamage + attackanimation + waitanimation + effectivenesssound + hitanimation BS_TARGET + waitstate + healthbarupdate BS_TARGET + datahpupdate BS_TARGET + critmessage + waitmessage B_WAIT_TIME_LONG + resultmessage + waitmessage B_WAIT_TIME_LONG + return + BattleScript_EffectNaturalGift: attackcanceler attackstring @@ -3471,24 +3355,7 @@ BattleScript_EffectPoisonHit: goto BattleScript_EffectHit BattleScript_EffectAbsorb:: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_AbsorbHealBlock setdrainedhp manipulatedamage DMG_BIG_ROOT @@ -3917,24 +3784,7 @@ BattleScript_EffectFlinchHit:: BattleScript_EffectFlinchStatus: setmoveeffect MOVE_EFFECT_FLINCH - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret seteffectwithchance argumentstatuseffect tryfaintmon BS_TARGET @@ -5167,24 +5017,7 @@ BattleScript_EffectBatonPass:: BattleScript_EffectRapidSpin:: .if B_SPEED_BUFFING_RAPID_SPIN == GEN_8 - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret jumpifhalfword CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_MoveEnd setmoveeffect MOVE_EFFECT_RAPIDSPIN | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN seteffectwithchance @@ -9023,7 +8856,7 @@ BattleScript_BadDreams_ShowPopUp: goto BattleScript_BadDreams_DmgAfterPopUp BattleScript_BadDreams_HidePopUp: destroyabilitypopup - tryfaintmon BS_TARGET + tryfaintmon BS_TARGET goto BattleScript_BadDreamsIncrement BattleScript_TookAttack:: @@ -10301,24 +10134,7 @@ BattleScript_ExtremeEvoboostEnd:: goto BattleScript_MoveEnd BattleScript_EffectHitSetRemoveTerrain: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG + call BattleScript_EffectHit_Ret setterrain BattleScript_TryFaint playanimation BS_ATTACKER, B_ANIM_RESTORE_BG printfromtable gTerrainStringIds diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index c10f6d942a..bb38d86599 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -409,7 +409,10 @@ #define EFFECT_INFERNAL_PARADE 403 #define EFFECT_TAKE_HEART 404 #define EFFECT_AXE_KICK 405 +#define EFFECT_COLLISION_COURSE 406 +#define EFFECT_SPIN_OUT 407 +#define EFFECT_MAKE_IT_RAIN 408 -#define NUM_BATTLE_MOVE_EFFECTS 406 +#define NUM_BATTLE_MOVE_EFFECTS 409 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 290b713b6c..9243bacb9c 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4389,8 +4389,9 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) break; case EFFECT_SUPERPOWER: case EFFECT_OVERHEAT: + case EFFECT_MAKE_IT_RAIN: if (AI_DATA->abilities[battlerAtk] == ABILITY_CONTRARY) - score += 10; + score += 3; break; case EFFECT_MAGIC_COAT: if (IS_MOVE_STATUS(predictedMove) && AI_GetBattlerMoveTargetType(battlerDef, predictedMove) & (MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH)) @@ -5197,7 +5198,6 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) case EFFECT_ROOST: case EFFECT_MEMENTO: case EFFECT_GRUDGE: - case EFFECT_OVERHEAT: score -= 2; break; default: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 3e8c5ae87b..c18209314b 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -378,6 +378,7 @@ static const u16 sIgnoredPowerfulMoveEffects[] = EFFECT_ERUPTION, EFFECT_OVERHEAT, EFFECT_MIND_BLOWN, + EFFECT_MAKE_IT_RAIN, IGNORED_MOVES_END }; diff --git a/src/battle_util.c b/src/battle_util.c index 0f1613cb9c..e7687b6aa5 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9484,6 +9484,10 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(1.5)); } + // Collision Course, Electro Drift + if (gBattleMoves[move].effect == EFFECT_COLLISION_COURSE && typeEffectivenessModifier >= UQ_4_12(2.0)) + finalModifier = uq4_12_multiply(finalModifier, UQ_4_12(1.3333)); + // reflect, light screen, aurora veil if (((gSideStatuses[defSide] & SIDE_STATUS_REFLECT && IS_MOVE_PHYSICAL(move)) || (gSideStatuses[defSide] & SIDE_STATUS_LIGHTSCREEN && IS_MOVE_SPECIAL(move)) diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 00082d6ec4..bb1db2f7de 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -13137,7 +13137,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_SPIN_OUT] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_SPIN_OUT + .effect = EFFECT_SPIN_OUT, .power = 100, .type = TYPE_STEEL, .accuracy = 100, @@ -13371,12 +13371,12 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_MAKE_IT_RAIN] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_MAKE_IT_RAIN + .effect = EFFECT_MAKE_IT_RAIN, .power = 120, .type = TYPE_STEEL, .accuracy = 100, .pp = 5, - .secondaryEffectChance = 0, + .secondaryEffectChance = 100, .target = MOVE_TARGET_BOTH, .priority = 0, .split = SPLIT_SPECIAL, @@ -13401,7 +13401,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_COLLISION_COURSE] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_COLLISION_COURSE + .effect = EFFECT_COLLISION_COURSE, .power = 100, .type = TYPE_FIGHTING, .accuracy = 100, @@ -13417,7 +13417,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_ELECTRO_DRIFT] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_COLLISION_COURSE + .effect = EFFECT_COLLISION_COURSE, .power = 100, .type = TYPE_ELECTRIC, .accuracy = 100, diff --git a/test/move_effect_collision_course.c b/test/move_effect_collision_course.c new file mode 100644 index 0000000000..bcf3cdd724 --- /dev/null +++ b/test/move_effect_collision_course.c @@ -0,0 +1,47 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_COLLISION_COURSE].effect == EFFECT_COLLISION_COURSE); +} + +SINGLE_BATTLE_TEST("Collision Course damage is increased by 33 Percent if super effective", s16 damage) +{ + u32 move; + + PARAMETRIZE { move = MOVE_HAMMER_ARM; } + PARAMETRIZE { move = MOVE_COLLISION_COURSE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KANGASKHAN); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3333), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Collision Course does normal damage if not super effective", s16 damage) +{ + u32 move; + + PARAMETRIZE { move = MOVE_HAMMER_ARM; } + PARAMETRIZE { move = MOVE_COLLISION_COURSE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} diff --git a/test/move_effect_make_it_rain.c b/test/move_effect_make_it_rain.c new file mode 100644 index 0000000000..ae8149b198 --- /dev/null +++ b/test/move_effect_make_it_rain.c @@ -0,0 +1,34 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_MAKE_IT_RAIN].effect == EFFECT_MAKE_IT_RAIN); +} + +SINGLE_BATTLE_TEST("Make It Rain lowers special attack by one stage") +{ + s16 damage[2]; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_MAKE_IT_RAIN); } + TURN { MOVE(player, MOVE_MAKE_IT_RAIN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAKE_IT_RAIN, player); + HP_BAR(opponent, captureDamage: &damage[0]); + MESSAGE("Coins scattered everywhere!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet's Sp. Atk fell!"); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAKE_IT_RAIN, player); + HP_BAR(opponent, captureDamage: &damage[1]); + MESSAGE("Coins scattered everywhere!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet's Sp. Atk fell!"); + } THEN { + EXPECT_MUL_EQ(damage[0], Q_4_12(0.66), damage[1]); + } +} diff --git a/test/move_effect_spin_out.c b/test/move_effect_spin_out.c new file mode 100644 index 0000000000..060f3545ec --- /dev/null +++ b/test/move_effect_spin_out.c @@ -0,0 +1,21 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_SPIN_OUT].effect == EFFECT_SPIN_OUT); +} + +SINGLE_BATTLE_TEST("Spin Out lowers speed by 2 stages") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SPIN_OUT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIN_OUT, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet's Speed harshly fell!"); + } +} From 2860ac9c809be439acdb5b7bb5168bc85277b2f5 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Wed, 19 Jul 2023 13:29:36 -0300 Subject: [PATCH 09/19] Added a debug feature to hatch eggs --- data/scripts/debug.inc | 31 +++++++++++++++++++++++++++++++ src/debug.c | 10 ++++++++++ 2 files changed, 41 insertions(+) diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index d7f486907d..64b7e1dd01 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -112,4 +112,35 @@ Debug_SaveBlock2Size:: Debug_PokemonStorageSize:: .string "{PKMN}Storage size: {STR_VAR_1}/{STR_VAR_2}.$" +Debug_HatchAnEgg:: + lockall + getpartysize + goto_if_eq VAR_RESULT, 0, Debug_HatchAnEgg_NoPokemon + special ChoosePartyMon + waitstate + goto_if_ge VAR_0x8004, PARTY_SIZE, Debug_HatchAnEgg_End + specialvar VAR_RESULT, ScriptGetPartyMonSpecies + goto_if_ne VAR_RESULT, SPECIES_EGG, DebugScript_HatchAnEgg_CantForceHatch + special EggHatch + waitstate +Debug_HatchAnEgg_End:: + releaseall + end + +Debug_HatchAnEgg_NoPokemon:: + msgbox DebugScript_HatchAnEgg_Text_EmptyParty, MSGBOX_DEFAULT + releaseall + end + +DebugScript_HatchAnEgg_CantForceHatch:: + msgbox DebugScript_HatchAnEgg_Text_NotAnEgg, MSGBOX_DEFAULT + releaseall + end + +DebugScript_HatchAnEgg_Text_EmptyParty:: + .string "You have no Pokémon nor Eggs.$" + +DebugScript_HatchAnEgg_Text_NotAnEgg:: + .string "That's not a Pokémon Egg.$" + .endif diff --git a/src/debug.c b/src/debug.c index ffacba9daf..141fbf49a8 100644 --- a/src/debug.c +++ b/src/debug.c @@ -91,6 +91,7 @@ enum { // Util DEBUG_UTIL_MENU_ITEM_TRAINER_ID, DEBUG_UTIL_MENU_ITEM_CLEAR_BOXES, DEBUG_UTIL_MENU_ITEM_CHEAT, + DEBUG_UTIL_MENU_ITEM_HATCH_AN_EGG, }; enum { // Scripts DEBUG_UTIL_MENU_ITEM_SCRIPT_1, @@ -312,6 +313,7 @@ static void DebugAction_Util_Trainer_Gender(u8 taskId); static void DebugAction_Util_Trainer_Id(u8 taskId); static void DebugAction_Util_Clear_Boxes(u8 taskId); static void DebugAction_Util_CheatStart(u8 taskId); +static void DebugAction_Util_HatchAnEgg(u8 taskId); static void DebugAction_FlagsVars_Flags(u8 taskId); static void DebugAction_FlagsVars_FlagsSelect(u8 taskId); @@ -381,6 +383,7 @@ extern u8 Debug_Script_8[]; 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[]; @@ -436,6 +439,7 @@ static const u8 sDebugText_Util_Trainer_Gender[] = _("Toggle T. Gender" static const u8 sDebugText_Util_Trainer_Id[] = _("New Trainer Id"); static const u8 sDebugText_Util_Clear_Boxes[] = _("Clear Storage Boxes"); static const u8 sDebugText_Util_CheatStart[] = _("CHEAT Start"); +static const u8 sDebugText_Util_HatchAnEgg[] = _("Hatch an Egg"); // Flags/Vars Menu static const u8 sDebugText_FlagsVars_Flags[] = _("Set Flag XYZ…{CLEAR_TO 110}{RIGHT_ARROW}"); static const u8 sDebugText_FlagsVars_Flag[] = _("Flag: {STR_VAR_1}{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}\n{STR_VAR_3}"); @@ -597,6 +601,7 @@ static const struct ListMenuItem sDebugMenu_Items_Utilities[] = [DEBUG_UTIL_MENU_ITEM_TRAINER_ID] = {sDebugText_Util_Trainer_Id, DEBUG_UTIL_MENU_ITEM_TRAINER_ID}, [DEBUG_UTIL_MENU_ITEM_CLEAR_BOXES] = {sDebugText_Util_Clear_Boxes, DEBUG_UTIL_MENU_ITEM_CLEAR_BOXES}, [DEBUG_UTIL_MENU_ITEM_CHEAT] = {sDebugText_Util_CheatStart, DEBUG_UTIL_MENU_ITEM_CHEAT}, + [DEBUG_UTIL_MENU_ITEM_HATCH_AN_EGG] = {sDebugText_Util_HatchAnEgg, DEBUG_UTIL_MENU_ITEM_HATCH_AN_EGG}, }; static const struct ListMenuItem sDebugMenu_Items_Scripts[] = { @@ -729,6 +734,7 @@ static void (*const sDebugMenu_Actions_Utilities[])(u8) = [DEBUG_UTIL_MENU_ITEM_TRAINER_ID] = DebugAction_Util_Trainer_Id, [DEBUG_UTIL_MENU_ITEM_CLEAR_BOXES] = DebugAction_Util_Clear_Boxes, [DEBUG_UTIL_MENU_ITEM_CHEAT] = DebugAction_Util_CheatStart, + [DEBUG_UTIL_MENU_ITEM_HATCH_AN_EGG] = DebugAction_Util_HatchAnEgg, }; static void (*const sDebugMenu_Actions_Scripts[])(u8) = { @@ -1976,6 +1982,10 @@ static void DebugAction_Util_CheatStart(u8 taskId) { Debug_DestroyMenu_Full_Script(taskId, Debug_CheatStart); } +static void DebugAction_Util_HatchAnEgg(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_HatchAnEgg); +} // ******************************* // Actions Scripts From 6d7d7f109ec9ea8637d8750d514b34fdf4136c73 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Wed, 19 Jul 2023 23:38:09 +0200 Subject: [PATCH 10/19] Fix debug menu memory overflow (#3154) --- src/debug.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/debug.c b/src/debug.c index ffacba9daf..58f1364920 100644 --- a/src/debug.c +++ b/src/debug.c @@ -211,6 +211,8 @@ enum { //Sound #define DEBUG_NUMBER_ICON_X 210 #define DEBUG_NUMBER_ICON_Y 50 +#define DEBUG_MAX_MENU_ITEMS 50 + // ******************************* struct DebugMonData { @@ -234,7 +236,7 @@ struct DebugMonData struct DebugMenuListData { struct ListMenuItem listItems[20 + 1]; - u8 itemNames[PC_ITEMS_COUNT + 1][26]; + u8 itemNames[DEBUG_MAX_MENU_ITEMS + 1][26]; u8 listId; }; @@ -1132,6 +1134,8 @@ static void Debug_RefreshListMenu(u8 taskId) totalItems = 7; } + // Failsafe to prevent memory corruption + totalItems = min(totalItems, DEBUG_MAX_MENU_ITEMS); // Copy item names for all entries but the last (which is Cancel) for(i = 0; i < totalItems; i++) { From 89f368db128b52de57a08386a7de4eb71aedab12 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 19 Jul 2023 23:05:07 -0400 Subject: [PATCH 11/19] Fixed missing versions --- .github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 3 ++- .github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml | 3 ++- .github/ISSUE_TEMPLATE/04_other_errors.yaml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 7a04bf3294..55d4fada45 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -23,8 +23,9 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.5.0 (Default) + - 1.5.1 (Default) - upcoming (Edge) + - 1.5.0 - 1.4.3 - 1.4.2 - 1.4.1 diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index ef03b5547a..8c28b39421 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -23,8 +23,9 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.5.0 (Default) + - 1.5.1 (Default) - upcoming (Edge) + - 1.5.0 - 1.4.3 - 1.4.2 - 1.4.1 diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index a1ff7e0c4f..6f11d5b9ad 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -23,8 +23,9 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.5.0 (Default) + - 1.5.1 (Default) - upcoming (Edge) + - 1.5.0 - 1.4.3 - 1.4.2 - 1.4.1 From b406a9c1bdd4c33cfdf01d0532d1f280bfe74bb6 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Wed, 19 Jul 2023 16:44:21 +0100 Subject: [PATCH 12/19] RandomUniformExcept and RNG_METRONOME --- include/random.h | 7 ++++++ src/battle_script_commands.c | 40 ++++++++++++++++------------------ src/random.c | 13 +++++++++++ test/move_effect_metronome.c | 20 ++++++----------- test/random.c | 42 ++++++++++++++++++++++++++++++++++++ test/test_battle.h | 5 +++-- test/test_runner_battle.c | 38 +++++++++++++++++++++++++++++++- 7 files changed, 126 insertions(+), 39 deletions(-) diff --git a/include/random.h b/include/random.h index e7c2a3e284..7770880053 100644 --- a/include/random.h +++ b/include/random.h @@ -32,6 +32,10 @@ void SeedRng2(u16 seed); * RandomUniform(tag, lo, hi) returns a number from lo to hi inclusive * with uniform probability. * + * RandomUniformExcept(tag, lo, hi, reject) returns a number from lo to + * hi inclusive with uniform probability, excluding those for which + * reject returns TRUE. + * * RandomElement(tag, array) returns an element in array with uniform * probability. The array must be known at compile-time (e.g. a global * const array). @@ -58,6 +62,7 @@ enum RandomTag RNG_FROZEN, RNG_HOLD_EFFECT_FLINCH, RNG_INFATUATION, + RNG_METRONOME, RNG_PARALYSIS, RNG_POISON_POINT, RNG_RAMPAGE_TURNS, @@ -103,10 +108,12 @@ enum RandomTag }) u32 RandomUniform(enum RandomTag, u32 lo, u32 hi); +u32 RandomUniformExcept(enum RandomTag, u32 lo, u32 hi, bool32 (*reject)(u32)); u32 RandomWeightedArray(enum RandomTag, u32 sum, u32 n, const u8 *weights); const void *RandomElementArray(enum RandomTag, const void *array, size_t size, size_t count); u32 RandomUniformDefault(enum RandomTag, u32 lo, u32 hi); +u32 RandomUniformExceptDefault(enum RandomTag, u32 lo, u32 hi, bool32 (*reject)(u32)); u32 RandomWeightedArrayDefault(enum RandomTag, u32 sum, u32 n, const u8 *weights); const void *RandomElementArrayDefault(enum RandomTag, const void *array, size_t size, size_t count); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 74e13b6d87..9a9a3c3ae8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12977,41 +12977,37 @@ static void Cmd_mimicattackcopy(void) } } +static bool32 InvalidMetronomeMove(u32 move) +{ + return gBattleMoves[move].effect == EFFECT_PLACEHOLDER + || sForbiddenMoves[move] & FORBIDDEN_METRONOME; +} + static void Cmd_metronome(void) { CMD_ARGS(); #if B_METRONOME_MOVES >= GEN_9 - u16 moveCount = MOVES_COUNT_GEN9; + u32 moveCount = MOVES_COUNT_GEN9; #elif B_METRONOME_MOVES >= GEN_8 - u16 moveCount = MOVES_COUNT_GEN8; + u32 moveCount = MOVES_COUNT_GEN8; #elif B_METRONOME_MOVES >= GEN_7 - u16 moveCount = MOVES_COUNT_GEN7; + u32 moveCount = MOVES_COUNT_GEN7; #elif B_METRONOME_MOVES >= GEN_6 - u16 moveCount = MOVES_COUNT_GEN6; + u32 moveCount = MOVES_COUNT_GEN6; #elif B_METRONOME_MOVES >= GEN_5 - u16 moveCount = MOVES_COUNT_GEN5; + u32 moveCount = MOVES_COUNT_GEN5; #elif B_METRONOME_MOVES >= GEN_4 - u16 moveCount = MOVES_COUNT_GEN4; + u32 moveCount = MOVES_COUNT_GEN4; #elif B_METRONOME_MOVES >= GEN_3 - u16 moveCount = MOVES_COUNT_GEN3; + u32 moveCount = MOVES_COUNT_GEN3; #endif - while (TRUE) - { - gCurrentMove = (Random() % (moveCount - 1)) + 1; - if (gBattleMoves[gCurrentMove].effect == EFFECT_PLACEHOLDER) - continue; - - if (!(sForbiddenMoves[gCurrentMove] & FORBIDDEN_METRONOME)) - { - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; - SetAtkCancellerForCalledMove(); - gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]; - gBattlerTarget = GetMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); - return; - } - } + gCurrentMove = RandomUniformExcept(RNG_METRONOME, 1, moveCount - 1, InvalidMetronomeMove); + gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; + SetAtkCancellerForCalledMove(); + gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]; + gBattlerTarget = GetMoveTarget(gCurrentMove, NO_TARGET_OVERRIDE); } static void Cmd_dmgtolevel(void) diff --git a/src/random.c b/src/random.c index 14983e7764..0c2509bd94 100644 --- a/src/random.c +++ b/src/random.c @@ -35,6 +35,9 @@ u16 Random2(void) __attribute__((weak, alias("RandomUniformDefault"))) u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi); +__attribute__((weak, alias("RandomUniformExceptDefault"))) +u32 RandomUniformExcept(enum RandomTag, u32 lo, u32 hi, bool32 (*reject)(u32)); + __attribute__((weak, alias("RandomWeightedArrayDefault"))) u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights); @@ -46,6 +49,16 @@ u32 RandomUniformDefault(enum RandomTag tag, u32 lo, u32 hi) return lo + (((hi - lo + 1) * Random()) >> 16); } +u32 RandomUniformExceptDefault(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32)) +{ + while (TRUE) + { + u32 n = RandomUniformDefault(tag, lo, hi); + if (!reject(n)) + return n; + } +} + u32 RandomWeightedArrayDefault(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) { s32 i, targetSum; diff --git a/test/move_effect_metronome.c b/test/move_effect_metronome.c index 11a906f941..7265d5aa8a 100644 --- a/test/move_effect_metronome.c +++ b/test/move_effect_metronome.c @@ -6,19 +6,13 @@ ASSUMPTIONS ASSUME(gBattleMoves[MOVE_METRONOME].effect == EFFECT_METRONOME); } -// To do: Turn the seeds to work with WITH_RNG for Metronome. -#define RNG_METRONOME_SCRATCH 0x118 -#define RNG_METRONOME_PSN_POWDER 0x119 -#define RNG_METRONOME_ROCK_BLAST 0x1F5 - SINGLE_BATTLE_TEST("Metronome picks a random move") { GIVEN { - RNGSeed(RNG_METRONOME_SCRATCH); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_METRONOME); } + TURN { MOVE(player, MOVE_METRONOME, WITH_RNG(RNG_METRONOME, MOVE_SCRATCH)); } } SCENE { MESSAGE("Wobbuffet used Metronome!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_METRONOME, player); @@ -34,11 +28,10 @@ SINGLE_BATTLE_TEST("Metronome's called powder move fails against Grass Types") ASSUME(gBattleMoves[MOVE_POISON_POWDER].flags & FLAG_POWDER); ASSUME(gSpeciesInfo[SPECIES_TANGELA].types[0] == TYPE_GRASS); ASSUME(gBattleMoves[MOVE_POISON_POWDER].effect == EFFECT_POISON); - RNGSeed(RNG_METRONOME_PSN_POWDER); - PLAYER(SPECIES_WOBBUFFET) {Speed(5);} - OPPONENT(SPECIES_TANGELA) {Speed(2);} + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_TANGELA); } WHEN { - TURN { MOVE(player, MOVE_METRONOME); } + TURN { MOVE(player, MOVE_METRONOME, WITH_RNG(RNG_METRONOME, MOVE_POISON_POWDER)); } } SCENE { MESSAGE("Wobbuffet used Metronome!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_METRONOME, player); @@ -53,17 +46,16 @@ SINGLE_BATTLE_TEST("Metronome's called multi-hit move hits multiple times") { GIVEN { ASSUME(gBattleMoves[MOVE_ROCK_BLAST].effect == EFFECT_MULTI_HIT); - RNGSeed(RNG_METRONOME_ROCK_BLAST); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_METRONOME); } + TURN { MOVE(player, MOVE_METRONOME, WITH_RNG(RNG_METRONOME, MOVE_ROCK_BLAST)); } } SCENE { MESSAGE("Wobbuffet used Metronome!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_METRONOME, player); MESSAGE("Wobbuffet used Rock Blast!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_BLAST, player); HP_BAR(opponent); - MESSAGE("Hit 4 time(s)!"); + MESSAGE("Hit 2 time(s)!"); } } diff --git a/test/random.c b/test/random.c index 39f587c062..a56e91a10d 100644 --- a/test/random.c +++ b/test/random.c @@ -16,6 +16,25 @@ TEST("RandomUniform generates lo..hi") } } +static bool32 InvalidEven(u32 n) +{ + return n % 2 == 0; +} + +TEST("RandomUniformExcept generates lo..hi") +{ + u32 lo, hi, i; + PARAMETRIZE { lo = 0; hi = 1; } + PARAMETRIZE { lo = 0; hi = 2; } + PARAMETRIZE { lo = 0; hi = 3; } + PARAMETRIZE { lo = 2; hi = 4; } + for (i = 0; i < 1024; i++) + { + u32 r = RandomUniformExceptDefault(RNG_NONE, lo, hi, InvalidEven); + EXPECT(lo <= r && r <= hi && r % 2 != 0); + } +} + TEST("RandomWeighted generates 0..n-1") { u32 n, sum, i; @@ -65,6 +84,29 @@ TEST("RandomUniform generates uniform distribution") EXPECT_LT(error, UQ_4_12(0.025)); } +TEST("RandomUniformExcept generates uniform distribution") +{ + u32 i, error; + u16 distribution[4]; + + memset(distribution, 0, sizeof(distribution)); + for (i = 0; i < 4096; i++) + { + u32 r = RandomUniformExceptDefault(RNG_NONE, 0, ARRAY_COUNT(distribution) - 1, InvalidEven); + EXPECT(0 <= r && r < ARRAY_COUNT(distribution)); + distribution[r]++; + } + + error = 0; + for (i = 0; i < ARRAY_COUNT(distribution); i++) + { + if (i % 2 != 0) + error += abs(UQ_4_12(0.5) - distribution[i]); + } + + EXPECT_LT(error, UQ_4_12(0.05)); +} + TEST("RandomWeighted generates distribution in proportion to the weights") { u32 i, sum, error; diff --git a/test/test_battle.h b/test/test_battle.h index 039506c1bd..b4f38ed91a 100644 --- a/test/test_battle.h +++ b/test/test_battle.h @@ -603,8 +603,9 @@ struct BattleTestRunnerState u8 parameters; u8 runParameter; u16 rngTag; - u8 trials; - u8 runTrial; + u16 rngTrialOffset; + u16 trials; + u16 runTrial; u16 expectedRatio; u16 observedRatio; u16 trialRatio; diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 592d0db980..a2375aef88 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -332,7 +332,42 @@ u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi) { Test_ExitWithResult(TEST_RESULT_ERROR, "RandomUniform called with inconsistent trials %d and %d", STATE->trials, n); } - STATE->trialRatio = Q_4_12(1) / n; + STATE->trialRatio = Q_4_12(1) / STATE->trials; + return STATE->runTrial + lo; + } + + return hi; +} + +u32 RandomUniformExcept(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32)) +{ + const struct BattlerTurn *turn = NULL; + u32 default_; + + if (gCurrentTurnActionNumber < gBattlersCount) + { + u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; + turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; + if (turn && turn->rng.tag == tag) + { + if (reject(turn->rng.value)) + Test_ExitWithResult(TEST_RESULT_INVALID, "WITH_RNG specified a rejected value (%d)", turn->rng.value); + return turn->rng.value; + } + } + + if (tag == STATE->rngTag) + { + if (STATE->trials == 1) + { + u32 n = 0, i; + for (i = lo; i < hi; i++) + if (!reject(i)) + n++; + STATE->trials = n; + PrintTestName(); + } + STATE->trialRatio = Q_4_12(1) / STATE->trials; return STATE->runTrial + lo; } @@ -962,6 +997,7 @@ void Randomly(u32 sourceLine, u32 passes, u32 trials, struct RandomlyContext ctx INVALID_IF(test->resultsSize > 0, "PASSES_RANDOMLY is incompatible with results"); INVALID_IF(passes > trials, "%d passes specified, but only %d trials", passes, trials); STATE->rngTag = ctx.tag; + STATE->rngTrialOffset = 0; STATE->runTrial = 0; STATE->expectedRatio = Q_4_12(passes) / trials; STATE->observedRatio = 0; From fc37345c29c558a75dad4cb2638caf553e844259 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Fri, 21 Jul 2023 10:42:39 +0200 Subject: [PATCH 13/19] Fix wrong color in stat move animation --- include/battle_anim.h | 9 +++--- include/constants/battle.h | 60 +++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/include/battle_anim.h b/include/battle_anim.h index a3677bd98f..28096d603e 100644 --- a/include/battle_anim.h +++ b/include/battle_anim.h @@ -2,6 +2,7 @@ #define GUARD_BATTLE_ANIM_H #include "battle.h" +#include "constants/battle.h" #include "constants/battle_anim.h" #include "task.h" @@ -204,10 +205,10 @@ u8 GetBattlerSpriteDefault_Y(u8 battlerId); u8 GetSubstituteSpriteDefault_Y(u8 battlerId); // battle_anim_status_effects.c -#define STAT_ANIM_PLUS1 15 -#define STAT_ANIM_PLUS2 39 -#define STAT_ANIM_MINUS1 22 -#define STAT_ANIM_MINUS2 46 +#define STAT_ANIM_PLUS1 MOVE_EFFECT_ATK_PLUS_1 +#define STAT_ANIM_PLUS2 MOVE_EFFECT_ATK_PLUS_2 +#define STAT_ANIM_MINUS1 MOVE_EFFECT_ATK_MINUS_1 +#define STAT_ANIM_MINUS2 MOVE_EFFECT_ATK_MINUS_2 #define STAT_ANIM_MULTIPLE_PLUS1 55 #define STAT_ANIM_MULTIPLE_PLUS2 56 #define STAT_ANIM_MULTIPLE_MINUS1 57 diff --git a/include/constants/battle.h b/include/constants/battle.h index 814d1bfa57..80810498c1 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -321,21 +321,21 @@ #define MOVE_EFFECT_PAYDAY 12 #define MOVE_EFFECT_CHARGING 13 #define MOVE_EFFECT_WRAP 14 -#define MOVE_EFFECT_BURN_UP 15 // MOVE_EFFECT_BURN_UP replaces unused MOVE_EFFECT_RECOIL_25 so that stat change animations don't break -#define MOVE_EFFECT_ATK_PLUS_1 16 -#define MOVE_EFFECT_DEF_PLUS_1 17 -#define MOVE_EFFECT_SPD_PLUS_1 18 -#define MOVE_EFFECT_SP_ATK_PLUS_1 19 -#define MOVE_EFFECT_SP_DEF_PLUS_1 20 -#define MOVE_EFFECT_ACC_PLUS_1 21 -#define MOVE_EFFECT_EVS_PLUS_1 22 -#define MOVE_EFFECT_ATK_MINUS_1 23 -#define MOVE_EFFECT_DEF_MINUS_1 24 -#define MOVE_EFFECT_SPD_MINUS_1 25 -#define MOVE_EFFECT_SP_ATK_MINUS_1 26 -#define MOVE_EFFECT_SP_DEF_MINUS_1 27 -#define MOVE_EFFECT_ACC_MINUS_1 28 -#define MOVE_EFFECT_EVS_MINUS_1 29 +#define MOVE_EFFECT_ATK_PLUS_1 15 +#define MOVE_EFFECT_DEF_PLUS_1 16 +#define MOVE_EFFECT_SPD_PLUS_1 17 +#define MOVE_EFFECT_SP_ATK_PLUS_1 18 +#define MOVE_EFFECT_SP_DEF_PLUS_1 19 +#define MOVE_EFFECT_ACC_PLUS_1 20 +#define MOVE_EFFECT_EVS_PLUS_1 21 +#define MOVE_EFFECT_ATK_MINUS_1 22 +#define MOVE_EFFECT_DEF_MINUS_1 23 +#define MOVE_EFFECT_SPD_MINUS_1 24 +#define MOVE_EFFECT_SP_ATK_MINUS_1 25 +#define MOVE_EFFECT_SP_DEF_MINUS_1 26 +#define MOVE_EFFECT_ACC_MINUS_1 27 +#define MOVE_EFFECT_EVS_MINUS_1 28 +#define MOVE_EFFECT_BURN_UP 29 #define MOVE_EFFECT_RECHARGE 30 #define MOVE_EFFECT_RAGE 31 #define MOVE_EFFECT_STEAL_ITEM 32 @@ -345,21 +345,21 @@ #define MOVE_EFFECT_RAPIDSPIN 36 #define MOVE_EFFECT_REMOVE_STATUS 37 #define MOVE_EFFECT_ATK_DEF_DOWN 38 -#define MOVE_EFFECT_SCALE_SHOT 39 // MOVE_EFFECT_SCALE_SHOT replaces unused MOVE_EFFECT_RECOIL_33 so that stat change animations don't break -#define MOVE_EFFECT_ATK_PLUS_2 40 -#define MOVE_EFFECT_DEF_PLUS_2 41 -#define MOVE_EFFECT_SPD_PLUS_2 42 -#define MOVE_EFFECT_SP_ATK_PLUS_2 43 -#define MOVE_EFFECT_SP_DEF_PLUS_2 44 -#define MOVE_EFFECT_ACC_PLUS_2 45 -#define MOVE_EFFECT_EVS_PLUS_2 46 -#define MOVE_EFFECT_ATK_MINUS_2 47 -#define MOVE_EFFECT_DEF_MINUS_2 48 -#define MOVE_EFFECT_SPD_MINUS_2 49 -#define MOVE_EFFECT_SP_ATK_MINUS_2 50 -#define MOVE_EFFECT_SP_DEF_MINUS_2 51 -#define MOVE_EFFECT_ACC_MINUS_2 52 -#define MOVE_EFFECT_EVS_MINUS_2 53 +#define MOVE_EFFECT_ATK_PLUS_2 39 +#define MOVE_EFFECT_DEF_PLUS_2 40 +#define MOVE_EFFECT_SPD_PLUS_2 41 +#define MOVE_EFFECT_SP_ATK_PLUS_2 42 +#define MOVE_EFFECT_SP_DEF_PLUS_2 43 +#define MOVE_EFFECT_ACC_PLUS_2 44 +#define MOVE_EFFECT_EVS_PLUS_2 45 +#define MOVE_EFFECT_ATK_MINUS_2 46 +#define MOVE_EFFECT_DEF_MINUS_2 47 +#define MOVE_EFFECT_SPD_MINUS_2 48 +#define MOVE_EFFECT_SP_ATK_MINUS_2 49 +#define MOVE_EFFECT_SP_DEF_MINUS_2 50 +#define MOVE_EFFECT_ACC_MINUS_2 51 +#define MOVE_EFFECT_EVS_MINUS_2 52 +#define MOVE_EFFECT_SCALE_SHOT 53 #define MOVE_EFFECT_THRASH 54 #define MOVE_EFFECT_KNOCK_OFF 55 #define MOVE_EFFECT_DEF_SPDEF_DOWN 56 From e0271a92e9983284c81c94e666ec8d922618fb58 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Fri, 21 Jul 2023 11:40:15 +0200 Subject: [PATCH 14/19] Fix trainer messages appearing for frontier trainers --- src/battle_message.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/battle_message.c b/src/battle_message.c index d2ca9dfd7a..1585f8c477 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3935,6 +3935,7 @@ u8 GetCurrentPpToMaxPpState(u8 currentPp, u8 maxPp) struct TrainerSlide { u16 trainerId; + bool8 isFrontierTrainer; const u8 *msgLastSwitchIn; const u8 *msgLastLowHp; const u8 *msgFirstDown; @@ -3954,6 +3955,7 @@ static const struct TrainerSlide sTrainerSlides[] = Example: { .trainerId = TRAINER_WALLY_VR_2, + .isFrontierTrainer = FALSE, .msgLastSwitchIn = sText_AarghAlmostHadIt, .msgLastLowHp = sText_BoxIsFull, .msgFirstDown = sText_123Poof, @@ -4046,7 +4048,9 @@ u32 ShouldDoTrainerSlide(u32 battlerId, u32 which) for (i = 0; i < ARRAY_COUNT(sTrainerSlides); i++) { - if (trainerId == sTrainerSlides[i].trainerId) + if (trainerId == sTrainerSlides[i].trainerId + && (((gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && sTrainerSlides[i].isFrontierTrainer) + || (!(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && !sTrainerSlides[i].isFrontierTrainer))) { gBattleScripting.battler = battlerId; switch (which) From cd5f997ee30b001c58be5b8e098769d60b88f313 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Fri, 21 Jul 2023 07:06:05 -0300 Subject: [PATCH 15/19] Added a debug feature to hatch eggs (#3155) --- data/scripts/debug.inc | 31 +++++++++++++++++++++++++++++++ src/debug.c | 10 ++++++++++ 2 files changed, 41 insertions(+) diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index d7f486907d..64b7e1dd01 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -112,4 +112,35 @@ Debug_SaveBlock2Size:: Debug_PokemonStorageSize:: .string "{PKMN}Storage size: {STR_VAR_1}/{STR_VAR_2}.$" +Debug_HatchAnEgg:: + lockall + getpartysize + goto_if_eq VAR_RESULT, 0, Debug_HatchAnEgg_NoPokemon + special ChoosePartyMon + waitstate + goto_if_ge VAR_0x8004, PARTY_SIZE, Debug_HatchAnEgg_End + specialvar VAR_RESULT, ScriptGetPartyMonSpecies + goto_if_ne VAR_RESULT, SPECIES_EGG, DebugScript_HatchAnEgg_CantForceHatch + special EggHatch + waitstate +Debug_HatchAnEgg_End:: + releaseall + end + +Debug_HatchAnEgg_NoPokemon:: + msgbox DebugScript_HatchAnEgg_Text_EmptyParty, MSGBOX_DEFAULT + releaseall + end + +DebugScript_HatchAnEgg_CantForceHatch:: + msgbox DebugScript_HatchAnEgg_Text_NotAnEgg, MSGBOX_DEFAULT + releaseall + end + +DebugScript_HatchAnEgg_Text_EmptyParty:: + .string "You have no Pokémon nor Eggs.$" + +DebugScript_HatchAnEgg_Text_NotAnEgg:: + .string "That's not a Pokémon Egg.$" + .endif diff --git a/src/debug.c b/src/debug.c index 58f1364920..a46122baba 100644 --- a/src/debug.c +++ b/src/debug.c @@ -91,6 +91,7 @@ enum { // Util DEBUG_UTIL_MENU_ITEM_TRAINER_ID, DEBUG_UTIL_MENU_ITEM_CLEAR_BOXES, DEBUG_UTIL_MENU_ITEM_CHEAT, + DEBUG_UTIL_MENU_ITEM_HATCH_AN_EGG, }; enum { // Scripts DEBUG_UTIL_MENU_ITEM_SCRIPT_1, @@ -314,6 +315,7 @@ static void DebugAction_Util_Trainer_Gender(u8 taskId); static void DebugAction_Util_Trainer_Id(u8 taskId); static void DebugAction_Util_Clear_Boxes(u8 taskId); static void DebugAction_Util_CheatStart(u8 taskId); +static void DebugAction_Util_HatchAnEgg(u8 taskId); static void DebugAction_FlagsVars_Flags(u8 taskId); static void DebugAction_FlagsVars_FlagsSelect(u8 taskId); @@ -383,6 +385,7 @@ extern u8 Debug_Script_8[]; 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[]; @@ -438,6 +441,7 @@ static const u8 sDebugText_Util_Trainer_Gender[] = _("Toggle T. Gender" static const u8 sDebugText_Util_Trainer_Id[] = _("New Trainer Id"); static const u8 sDebugText_Util_Clear_Boxes[] = _("Clear Storage Boxes"); static const u8 sDebugText_Util_CheatStart[] = _("CHEAT Start"); +static const u8 sDebugText_Util_HatchAnEgg[] = _("Hatch an Egg"); // Flags/Vars Menu static const u8 sDebugText_FlagsVars_Flags[] = _("Set Flag XYZ…{CLEAR_TO 110}{RIGHT_ARROW}"); static const u8 sDebugText_FlagsVars_Flag[] = _("Flag: {STR_VAR_1}{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}\n{STR_VAR_3}"); @@ -599,6 +603,7 @@ static const struct ListMenuItem sDebugMenu_Items_Utilities[] = [DEBUG_UTIL_MENU_ITEM_TRAINER_ID] = {sDebugText_Util_Trainer_Id, DEBUG_UTIL_MENU_ITEM_TRAINER_ID}, [DEBUG_UTIL_MENU_ITEM_CLEAR_BOXES] = {sDebugText_Util_Clear_Boxes, DEBUG_UTIL_MENU_ITEM_CLEAR_BOXES}, [DEBUG_UTIL_MENU_ITEM_CHEAT] = {sDebugText_Util_CheatStart, DEBUG_UTIL_MENU_ITEM_CHEAT}, + [DEBUG_UTIL_MENU_ITEM_HATCH_AN_EGG] = {sDebugText_Util_HatchAnEgg, DEBUG_UTIL_MENU_ITEM_HATCH_AN_EGG}, }; static const struct ListMenuItem sDebugMenu_Items_Scripts[] = { @@ -731,6 +736,7 @@ static void (*const sDebugMenu_Actions_Utilities[])(u8) = [DEBUG_UTIL_MENU_ITEM_TRAINER_ID] = DebugAction_Util_Trainer_Id, [DEBUG_UTIL_MENU_ITEM_CLEAR_BOXES] = DebugAction_Util_Clear_Boxes, [DEBUG_UTIL_MENU_ITEM_CHEAT] = DebugAction_Util_CheatStart, + [DEBUG_UTIL_MENU_ITEM_HATCH_AN_EGG] = DebugAction_Util_HatchAnEgg, }; static void (*const sDebugMenu_Actions_Scripts[])(u8) = { @@ -1980,6 +1986,10 @@ static void DebugAction_Util_CheatStart(u8 taskId) { Debug_DestroyMenu_Full_Script(taskId, Debug_CheatStart); } +static void DebugAction_Util_HatchAnEgg(u8 taskId) +{ + Debug_DestroyMenu_Full_Script(taskId, Debug_HatchAnEgg); +} // ******************************* // Actions Scripts From ad25dfe1e9970ef0d6383c7ce0f354ccd0b659ad Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 21 Jul 2023 20:43:39 +0200 Subject: [PATCH 16/19] Set otGender + Moves in FillPartnerParty (#3163) --- include/battle_main.h | 1 + src/battle_main.c | 5 ++--- src/battle_tower.c | 9 +++------ 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/include/battle_main.h b/include/battle_main.h index 4f20e4c17a..5f603654bc 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -72,6 +72,7 @@ bool32 IsWildMonSmart(void); u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer *trainer, bool32 firstTrainer, u32 battleTypeFlags); void ModifyPersonalityForNature(u32 *personality, u32 newNature); u32 GeneratePersonalityForGender(u32 gender, u32 species); +void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMonCustomized *partyEntry); extern struct MultiPartnerMenuPokemon gMultiPartnerParty[MULTI_PARTY_SIZE]; diff --git a/src/battle_main.c b/src/battle_main.c index f6d822e3f2..5841f8f615 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -120,7 +120,6 @@ static void SpriteCB_UnusedBattleInit_Main(struct Sprite *sprite); static void TrySpecialEvolution(void); static u32 Crc32B (const u8 *data, u32 size); static u32 GeneratePartyHash(const struct Trainer *trainer, u32 i); -static void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMonCustomized *partyEntry); EWRAM_DATA u16 gBattle_BG0_X = 0; EWRAM_DATA u16 gBattle_BG0_Y = 0; @@ -1936,7 +1935,7 @@ u32 GeneratePersonalityForGender(u32 gender, u32 species) return speciesInfo->genderRatio / 2; } -static void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMonCustomized *partyEntry) +void CustomTrainerPartyAssignMoves(struct Pokemon *mon, const struct TrainerMonCustomized *partyEntry) { bool32 noMoveSet = TRUE; u32 j; @@ -3861,7 +3860,7 @@ static void TryDoEventsBeforeFirstTurn(void) while (gBattleStruct->switchInAbilitiesCounter < gBattlersCount) { gBattlerAttacker = gBattlerByTurnOrder[gBattleStruct->switchInAbilitiesCounter++]; - + if (TryPrimalReversion(gBattlerAttacker)) return; if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gBattlerAttacker, 0, 0, 0) != 0) diff --git a/src/battle_tower.c b/src/battle_tower.c index 4e16467f04..51d7e16b33 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -3119,13 +3119,8 @@ static void FillPartnerParty(u16 trainerId) CreateMon(&gPlayerParty[i + 3], partyData[i].species, partyData[i].lvl, 0, TRUE, j, otIdType, otID); SetMonData(&gPlayerParty[i + 3], MON_DATA_HELD_ITEM, &partyData[i].heldItem); + CustomTrainerPartyAssignMoves(&gPlayerParty[i+3], &partyData[i]); - // TODO: Figure out a default strategy when moves are not set, to generate a good moveset - for (j = 0; j < MAX_MON_MOVES; ++j) - { - SetMonData(&gPlayerParty[i+3], MON_DATA_MOVE1 + j, &partyData[i].moves[j]); - SetMonData(&gPlayerParty[i+3], MON_DATA_PP1 + j, &gBattleMoves[partyData[i].moves[j]].pp); - } SetMonData(&gPlayerParty[i+3], MON_DATA_IVS, &(partyData[i].iv)); if (partyData[i].ev != NULL) { @@ -3164,6 +3159,8 @@ static void FillPartnerParty(u16 trainerId) StringCopy(trainerName, gTrainers[trainerId - TRAINER_CUSTOM_PARTNER].trainerName); SetMonData(&gPlayerParty[i + 3], MON_DATA_OT_NAME, trainerName); + j = gTrainers[trainerId - TRAINER_CUSTOM_PARTNER].encounterMusic_gender >> 7; + SetMonData(&gPlayerParty[i+3], MON_DATA_OT_GENDER, &j); } } else if (trainerId == TRAINER_EREADER) From fc321965a9fcf718e53bb68bc934f4d6f9bd20ee Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Thu, 20 Jul 2023 10:14:12 +0100 Subject: [PATCH 17/19] RNG_HITS and RNG_LOADED_DICE --- include/random.h | 2 + src/battle_script_commands.c | 32 ++++--------- src/battle_util.c | 40 +++++----------- test/move_effect_metronome.c | 2 +- test/move_effect_mirror_move.c | 21 ++++---- test/test_runner_battle.c | 87 +++++++++++++++++++++------------- 6 files changed, 86 insertions(+), 98 deletions(-) diff --git a/include/random.h b/include/random.h index 7770880053..83bc3e0d56 100644 --- a/include/random.h +++ b/include/random.h @@ -60,8 +60,10 @@ enum RandomTag RNG_FLAME_BODY, RNG_FORCE_RANDOM_SWITCH, RNG_FROZEN, + RNG_HITS, RNG_HOLD_EFFECT_FLINCH, RNG_INFATUATION, + RNG_LOADED_DICE, RNG_METRONOME, RNG_PARALYSIS, RNG_POISON_POINT, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 9a9a3c3ae8..532a131cc7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12206,30 +12206,14 @@ static void Cmd_setmultihitcounter(void) } else { - #if B_MULTI_HIT_CHANCE >= GEN_5 - // Based on Gen 5's odds - // 35% for 2 hits - // 35% for 3 hits - // 15% for 4 hits - // 15% for 5 hits - gMultiHitCounter = Random() % 100; - if (gMultiHitCounter < 35) - gMultiHitCounter = 2; - else if (gMultiHitCounter < 35 + 35) - gMultiHitCounter = 3; - else if (gMultiHitCounter < 35 + 35 + 15) - gMultiHitCounter = 4; - else - gMultiHitCounter = 5; - #else - // 2 and 3 hits: 37.5% - // 4 and 5 hits: 12.5% - gMultiHitCounter = Random() % 4; - if (gMultiHitCounter > 1) - gMultiHitCounter = (Random() % 4) + 2; - else - gMultiHitCounter += 2; - #endif + // WARNING: These seem to be unused, see SetRandomMultiHitCounter. + #if B_MULTI_HIT_CHANCE >= GEN_5 + // 35%: 2 hits, 35%: 3 hits, 15% 4 hits, 15% 5 hits. + gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 7, 7, 3, 3); + #else + // 37.5%: 2 hits, 37.5%: 3 hits, 12.5% 4 hits, 12.5% 5 hits. + gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 3, 3, 1, 1); + #endif } } diff --git a/src/battle_util.c b/src/battle_util.c index 495f26cd50..d229bd0728 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10899,35 +10899,19 @@ bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move) static void SetRandomMultiHitCounter() { -#if (B_MULTI_HIT_CHANCE >= GEN_5) - // Based on Gen 5's odds - // 35% for 2 hits - // 35% for 3 hits - // 15% for 4 hits - // 15% for 5 hits - gMultiHitCounter = Random() % 100; - if (gMultiHitCounter < 35) - gMultiHitCounter = 2; - else if (gMultiHitCounter < 35 + 35) - gMultiHitCounter = 3; - else if (gMultiHitCounter < 35 + 35 + 15) - gMultiHitCounter = 4; - else - gMultiHitCounter = 5; -#else - // 2 and 3 hits: 37.5% - // 4 and 5 hits: 12.5% - gMultiHitCounter = Random() % 4; - if (gMultiHitCounter > 1) - gMultiHitCounter = (Random() % 4) + 2; - else - gMultiHitCounter += 2; -#endif - - if (gMultiHitCounter < 4 && GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LOADED_DICE) + if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_LOADED_DICE) { - // If roll 4 or 5 Loaded Dice doesn't do anything. Otherwise it rolls the number of hits as 5 minus a random integer from 0 to 1 inclusive. - gMultiHitCounter = 5 - (Random() & 1); + gMultiHitCounter = RandomUniform(RNG_LOADED_DICE, 4, 5); + } + else + { +#if B_MULTI_HIT_CHANCE >= GEN_5 + // 35%: 2 hits, 35%: 3 hits, 15% 4 hits, 15% 5 hits. + gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 7, 7, 3, 3); +#else + // 37.5%: 2 hits, 37.5%: 3 hits, 12.5% 4 hits, 12.5% 5 hits. + gMultiHitCounter = RandomWeighted(RNG_HITS, 0, 0, 3, 3, 1, 1); +#endif } } diff --git a/test/move_effect_metronome.c b/test/move_effect_metronome.c index 7265d5aa8a..1e68603e63 100644 --- a/test/move_effect_metronome.c +++ b/test/move_effect_metronome.c @@ -56,6 +56,6 @@ SINGLE_BATTLE_TEST("Metronome's called multi-hit move hits multiple times") MESSAGE("Wobbuffet used Rock Blast!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_BLAST, player); HP_BAR(opponent); - MESSAGE("Hit 2 time(s)!"); + MESSAGE("Hit 5 time(s)!"); } } diff --git a/test/move_effect_mirror_move.c b/test/move_effect_mirror_move.c index 2b8b9dbe90..ff21c0efa7 100644 --- a/test/move_effect_mirror_move.c +++ b/test/move_effect_mirror_move.c @@ -9,8 +9,8 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Mirror Move copies the last used move by the target") { GIVEN { - PLAYER(SPECIES_WOBBUFFET) {Speed(2);} - OPPONENT(SPECIES_WOBBUFFET) {Speed(5);} + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_MIRROR_MOVE); } } SCENE { @@ -26,10 +26,10 @@ SINGLE_BATTLE_TEST("Mirror Move copies the last used move by the target") SINGLE_BATTLE_TEST("Mirror Move fails if no move was used before") { GIVEN { - PLAYER(SPECIES_WOBBUFFET) {Speed(5);} - OPPONENT(SPECIES_WOBBUFFET) {Speed(2);} + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_MIRROR_MOVE); } + TURN { MOVE(player, MOVE_MIRROR_MOVE); MOVE(opponent, MOVE_TACKLE); } } SCENE { MESSAGE("Wobbuffet used Mirror Move!"); MESSAGE("The Mirror Move failed!"); @@ -44,8 +44,8 @@ SINGLE_BATTLE_TEST("Mirror Move's called powder move fails against Grass Types") ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER); ASSUME(gSpeciesInfo[SPECIES_ODDISH].types[0] == TYPE_GRASS); ASSUME(gBattleMoves[MOVE_STUN_SPORE].effect == EFFECT_PARALYZE); - PLAYER(SPECIES_ODDISH) {Speed(5);} - OPPONENT(SPECIES_WOBBUFFET) {Speed(2);} + PLAYER(SPECIES_ODDISH); + OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_STUN_SPORE); MOVE(opponent, MOVE_MIRROR_MOVE); } } SCENE { @@ -59,19 +59,18 @@ SINGLE_BATTLE_TEST("Mirror Move's called powder move fails against Grass Types") } } -// It hits first 2 times, then 5 times with the default rng seed. SINGLE_BATTLE_TEST("Mirror Move's called multi-hit move hits multiple times") { GIVEN { ASSUME(gBattleMoves[MOVE_BULLET_SEED].effect == EFFECT_MULTI_HIT); - PLAYER(SPECIES_WOBBUFFET) {Speed(5);} - OPPONENT(SPECIES_WOBBUFFET) {Speed(2);} + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_BULLET_SEED); MOVE(opponent, MOVE_MIRROR_MOVE); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_BULLET_SEED, player); HP_BAR(opponent); - MESSAGE("Hit 2 time(s)!"); + MESSAGE("Hit 5 time(s)!"); MESSAGE("Foe Wobbuffet used Mirror Move!"); MESSAGE("Foe Wobbuffet used Bullet Seed!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_BULLET_SEED, opponent); diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index a2375aef88..9111207c8d 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -368,52 +368,40 @@ u32 RandomUniformExcept(enum RandomTag tag, u32 lo, u32 hi, bool32 (*reject)(u32 PrintTestName(); } STATE->trialRatio = Q_4_12(1) / STATE->trials; - return STATE->runTrial + lo; + + while (reject(STATE->runTrial + lo + STATE->rngTrialOffset)) + { + if (STATE->runTrial + lo + STATE->rngTrialOffset > hi) + Test_ExitWithResult(TEST_RESULT_INVALID, "RandomUniformExcept called with inconsistent reject"); + STATE->rngTrialOffset++; + } + + return STATE->runTrial + lo + STATE->rngTrialOffset; } + default_ = hi; + while (reject(default_)) + { + if (default_ == lo) + Test_ExitWithResult(TEST_RESULT_INVALID, "RandomUniformExcept rejected all values"); + default_--; + } return default_; } u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) { const struct BattlerTurn *turn = NULL; - u32 default_ = n-1; + + if (sum == 0) + Test_ExitWithResult(TEST_RESULT_ERROR, "RandomWeightedArray called with zero sum"); if (gCurrentTurnActionNumber < gBattlersCount) { u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; - } - - if (turn && turn->rng.tag == tag) - { - default_ = turn->rng.value; - } - else - { - switch (tag) - { - case RNG_ACCURACY: - ASSUME(n == 2); - if (turn && turn->hit) - return turn->hit - 1; - default_ = TRUE; - break; - - case RNG_CRITICAL_HIT: - ASSUME(n == 2); - if (turn && turn->criticalHit) - return turn->criticalHit - 1; - default_ = FALSE; - break; - - case RNG_SECONDARY_EFFECT: - ASSUME(n == 2); - if (turn && turn->secondaryEffect) - return turn->secondaryEffect - 1; - default_ = TRUE; - break; - } + if (turn && turn->rng.tag == tag) + return turn->rng.value; } if (tag == STATE->rngTag) @@ -432,7 +420,38 @@ u32 RandomWeightedArray(enum RandomTag tag, u32 sum, u32 n, const u8 *weights) return STATE->runTrial; } - return default_; + switch (tag) + { + case RNG_ACCURACY: + ASSUME(n == 2); + if (turn && turn->hit) + return turn->hit - 1; + else + return TRUE; + + case RNG_CRITICAL_HIT: + ASSUME(n == 2); + if (turn && turn->criticalHit) + return turn->criticalHit - 1; + else + return FALSE; + + case RNG_SECONDARY_EFFECT: + ASSUME(n == 2); + if (turn && turn->secondaryEffect) + return turn->secondaryEffect - 1; + else + return TRUE; + + default: + while (weights[n-1] == 0) + { + if (n == 1) + Test_ExitWithResult(TEST_RESULT_ERROR, "RandomWeightedArray called with all zero weights"); + n--; + } + return n-1; + } } const void *RandomElementArray(enum RandomTag tag, const void *array, size_t size, size_t count) From 6f40d44a23963e1fd089be96fead956d4b34ab7f Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Thu, 20 Jul 2023 10:14:25 +0100 Subject: [PATCH 18/19] Cleanup RandomUniform and RandomElementArray --- test/test_runner_battle.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 9111207c8d..4de144c38a 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -307,17 +307,13 @@ static void BattleTest_Run(void *data) u32 RandomUniform(enum RandomTag tag, u32 lo, u32 hi) { const struct BattlerTurn *turn = NULL; - u32 default_ = hi; if (gCurrentTurnActionNumber < gBattlersCount) { u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; - } - - if (turn && turn->rng.tag == tag) - { - default_ = turn->rng.value; + if (turn && turn->rng.tag == tag) + return turn->rng.value; } if (tag == STATE->rngTag) @@ -463,22 +459,17 @@ const void *RandomElementArray(enum RandomTag tag, const void *array, size_t siz { u32 battlerId = gBattlerByTurnOrder[gCurrentTurnActionNumber]; turn = &DATA.battleRecordTurns[gBattleResults.battleTurnCounter][battlerId]; - } - - if (turn && turn->rng.tag == tag) - { - u32 element = 0; - for (index = 0; index < count; index++) - { - memcpy(&element, (const u8 *)array + size * index, size); - if (element == turn->rng.value) - break; - } - if (index == count) + if (turn && turn->rng.tag == tag) { + u32 element = 0; + for (index = 0; index < count; index++) + { + memcpy(&element, (const u8 *)array + size * index, size); + if (element == turn->rng.value) + return (const u8 *)array + size * index; + } // TODO: Incorporate the line number. - const char *filename = gTestRunnerState.test->filename; - Test_ExitWithResult(TEST_RESULT_ERROR, "%s: RandomElement illegal value requested: %d", filename, turn->rng.value); + Test_ExitWithResult(TEST_RESULT_ERROR, "%s: RandomElement illegal value requested: %d", gTestRunnerState.test->filename, turn->rng.value); } } @@ -494,10 +485,8 @@ const void *RandomElementArray(enum RandomTag tag, const void *array, size_t siz Test_ExitWithResult(TEST_RESULT_ERROR, "RandomElement called with inconsistent trials %d and %d", STATE->trials, count); } STATE->trialRatio = Q_4_12(1) / count; - index = STATE->runTrial; + return (const u8 *)array + size * STATE->runTrial; } - - return (const u8 *)array + size * index; } static s32 TryAbilityPopUp(s32 i, s32 n, u32 battlerId, u32 ability) From da9b421ae1df86345dc3bb7f5e1ea82b13e35c76 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 25 Jul 2023 09:59:26 +0200 Subject: [PATCH 19/19] Fix Ruin ability calcs (#3171) --- src/battle_util.c | 8 ++--- test/ability_beads_of_ruin.c | 53 ++++++++++++++++++++++++++++++++++ test/ability_sword_of_ruin.c | 53 ++++++++++++++++++++++++++++++++++ test/ability_tablets_of_ruin.c | 53 ++++++++++++++++++++++++++++++++++ test/ability_vessel_of_ruin.c | 53 ++++++++++++++++++++++++++++++++++ 5 files changed, 216 insertions(+), 4 deletions(-) create mode 100644 test/ability_beads_of_ruin.c create mode 100644 test/ability_sword_of_ruin.c create mode 100644 test/ability_tablets_of_ruin.c create mode 100644 test/ability_vessel_of_ruin.c diff --git a/src/battle_util.c b/src/battle_util.c index 0a2a99447b..d549b71b95 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8908,16 +8908,16 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe } if (IsAbilityOnField(ABILITY_VESSEL_OF_RUIN) && atkAbility != ABILITY_VESSEL_OF_RUIN && IS_MOVE_SPECIAL(gCurrentMove)) - MulModifier(&modifier, UQ_4_12(0.25)); + MulModifier(&modifier, UQ_4_12(0.75)); if (IsAbilityOnField(ABILITY_SWORD_OF_RUIN) && defAbility != ABILITY_SWORD_OF_RUIN && IS_MOVE_PHYSICAL(gCurrentMove)) - MulModifier(&modifier, UQ_4_12(0.25)); + MulModifier(&modifier, UQ_4_12(1.25)); if (IsAbilityOnField(ABILITY_TABLETS_OF_RUIN) && atkAbility != ABILITY_TABLETS_OF_RUIN && IS_MOVE_PHYSICAL(gCurrentMove)) - MulModifier(&modifier, UQ_4_12(0.25)); + MulModifier(&modifier, UQ_4_12(0.75)); if (IsAbilityOnField(ABILITY_BEADS_OF_RUIN) && defAbility != ABILITY_BEADS_OF_RUIN && IS_MOVE_SPECIAL(gCurrentMove)) - MulModifier(&modifier, UQ_4_12(0.25)); + MulModifier(&modifier, UQ_4_12(1.25)); // attacker partner's abilities if (IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) diff --git a/test/ability_beads_of_ruin.c b/test/ability_beads_of_ruin.c new file mode 100644 index 0000000000..28b39a430c --- /dev/null +++ b/test/ability_beads_of_ruin.c @@ -0,0 +1,53 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_WATER_GUN].split == SPLIT_SPECIAL); +} + +SINGLE_BATTLE_TEST("Beads of Ruin reduces Sp. Def", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_SHADOW_TAG; } + PARAMETRIZE { ability = ABILITY_BEADS_OF_RUIN; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WATER_GUN); } + } SCENE { + if (ability == ABILITY_BEADS_OF_RUIN) { + ABILITY_POPUP(player, ABILITY_BEADS_OF_RUIN); + MESSAGE("Wobbuffet's Beads of Ruin weakened the Sp. Def of all surrounding Pokémon!"); + } + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.25), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Beads of Ruin does not reduce Sp. Def if opposing mon has the same ability", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_SHADOW_TAG; } + PARAMETRIZE { ability = ABILITY_BEADS_OF_RUIN; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_BEADS_OF_RUIN); } + } WHEN { + TURN { MOVE(player, MOVE_WATER_GUN); } + } SCENE { + if (ability == ABILITY_BEADS_OF_RUIN) { + ABILITY_POPUP(player, ABILITY_BEADS_OF_RUIN); + MESSAGE("Wobbuffet's Beads of Ruin weakened the Sp. Def of all surrounding Pokémon!"); + } + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} diff --git a/test/ability_sword_of_ruin.c b/test/ability_sword_of_ruin.c new file mode 100644 index 0000000000..6ec4f8fe85 --- /dev/null +++ b/test/ability_sword_of_ruin.c @@ -0,0 +1,53 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); +} + +SINGLE_BATTLE_TEST("Sword of Ruin reduces Defense", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_SHADOW_TAG; } + PARAMETRIZE { ability = ABILITY_SWORD_OF_RUIN; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + if (ability == ABILITY_SWORD_OF_RUIN) { + ABILITY_POPUP(player, ABILITY_SWORD_OF_RUIN); + MESSAGE("Wobbuffet's Sword of Ruin weakened the Defense of all surrounding Pokémon!"); + } + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.25), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Sword of Ruin does not reduce Defense if opposing mon has the same ability", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_SHADOW_TAG; } + PARAMETRIZE { ability = ABILITY_SWORD_OF_RUIN; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_SWORD_OF_RUIN); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + if (ability == ABILITY_SWORD_OF_RUIN) { + ABILITY_POPUP(player, ABILITY_SWORD_OF_RUIN); + MESSAGE("Wobbuffet's Sword of Ruin weakened the Defense of all surrounding Pokémon!"); + } + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} diff --git a/test/ability_tablets_of_ruin.c b/test/ability_tablets_of_ruin.c new file mode 100644 index 0000000000..38dcfc8560 --- /dev/null +++ b/test/ability_tablets_of_ruin.c @@ -0,0 +1,53 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); +} + +SINGLE_BATTLE_TEST("Tablets of Ruin reduces Attack", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_SHADOW_TAG; } + PARAMETRIZE { ability = ABILITY_TABLETS_OF_RUIN; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + if (ability == ABILITY_TABLETS_OF_RUIN) { + ABILITY_POPUP(player, ABILITY_TABLETS_OF_RUIN); + MESSAGE("Wobbuffet's Tablets of Ruin weakened the Attack of all surrounding Pokémon!"); + } + HP_BAR(player, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Tablets of Ruin does not reduce Attack if an opposing mon has the same ability", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_SHADOW_TAG; } + PARAMETRIZE { ability = ABILITY_TABLETS_OF_RUIN; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_TABLETS_OF_RUIN); } + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + if (ability == ABILITY_TABLETS_OF_RUIN) { + ABILITY_POPUP(player, ABILITY_TABLETS_OF_RUIN); + MESSAGE("Wobbuffet's Tablets of Ruin weakened the Attack of all surrounding Pokémon!"); + } + HP_BAR(player, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} diff --git a/test/ability_vessel_of_ruin.c b/test/ability_vessel_of_ruin.c new file mode 100644 index 0000000000..6c7b2664f2 --- /dev/null +++ b/test/ability_vessel_of_ruin.c @@ -0,0 +1,53 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_WATER_GUN].split == SPLIT_SPECIAL); +} + +SINGLE_BATTLE_TEST("Vessel of Ruin reduces Sp. Atk", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_SHADOW_TAG; } + PARAMETRIZE { ability = ABILITY_VESSEL_OF_RUIN; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_WATER_GUN); } + } SCENE { + if (ability == ABILITY_VESSEL_OF_RUIN) { + ABILITY_POPUP(player, ABILITY_VESSEL_OF_RUIN); + MESSAGE("Wobbuffet's Vessel of Ruin weakened the Sp. Atk of all surrounding Pokémon!"); + } + HP_BAR(player, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.75), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Vessel of Ruin does not reduce Sp. Atk if opposing mon has the same ability", s16 damage) +{ + u32 ability; + + PARAMETRIZE { ability = ABILITY_SHADOW_TAG; } + PARAMETRIZE { ability = ABILITY_VESSEL_OF_RUIN; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_VESSEL_OF_RUIN); } + } WHEN { + TURN { MOVE(opponent, MOVE_WATER_GUN); } + } SCENE { + if (ability == ABILITY_VESSEL_OF_RUIN) { + ABILITY_POPUP(player, ABILITY_VESSEL_OF_RUIN); + MESSAGE("Wobbuffet's Vessel of Ruin weakened the Sp. Atk of all surrounding Pokémon!"); + } + HP_BAR(player, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +}