From e64da065e8016643d21c2fe95897c57d2a951e71 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:24:09 +0100 Subject: [PATCH 1/9] Fixes Eject Pack / Intimidate issue (#5902) --- src/battle_util.c | 12 ++++++++++++ test/battle/hold_effect/eject_pack.c | 16 ++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/battle_util.c b/src/battle_util.c index 1e0341f33738..a9956615a18b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8322,6 +8322,18 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) gBattlescriptCurrInstr = BattleScript_WhiteHerbRet; } break; + case HOLD_EFFECT_EJECT_PACK: + if (gProtectStructs[battler].statFell + && gProtectStructs[battler].disableEjectPack == 0 + && CountUsablePartyMons(battler) > 0) + { + gBattleScripting.battler = battler; + gPotentialItemEffectBattler = battler; + effect = ITEM_STATS_CHANGE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_EjectPackActivates; + } + break; } break; } diff --git a/test/battle/hold_effect/eject_pack.c b/test/battle/hold_effect/eject_pack.c index 9272a23a7cd7..b3a2d34b631f 100644 --- a/test/battle/hold_effect/eject_pack.c +++ b/test/battle/hold_effect/eject_pack.c @@ -85,3 +85,19 @@ SINGLE_BATTLE_TEST("Eject Pack will miss timing to switch out user if Emergency EXPECT(opponent->species == SPECIES_WYNAUT); } } + +SINGLE_BATTLE_TEST("Eject Pack activates once intimidate mon switches in") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN { SWITCH(opponent, 1); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet is switched out with the Eject Pack!"); + } +} From 009de5c98cb83d6f2b63d65880ffd2a19cdd01ee Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 29 Dec 2024 19:28:39 -0300 Subject: [PATCH 2/9] Setting Battle configs during tests (#5803) Co-authored-by: sbird --- Makefile | 2 ++ include/constants/generational_changes.h | 10 ++++++ include/generational_changes.h | 41 ++++++++++++++++++++++++ include/test/battle.h | 13 ++++++++ src/battle_main.c | 3 +- src/generational_changes.c | 19 +++++++++++ test/battle/ability/gale_wings.c | 16 ++++----- test/test_runner_battle.c | 8 +++++ 8 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 include/constants/generational_changes.h create mode 100644 include/generational_changes.h create mode 100644 src/generational_changes.c diff --git a/Makefile b/Makefile index 71d2a48af9a3..656b0847dd3d 100644 --- a/Makefile +++ b/Makefile @@ -350,6 +350,8 @@ $(C_BUILDDIR)/pokedex_plus_hgss.o: CFLAGS := -mthumb -mthumb-interwork -O2 -mabi # Annoyingly we can't turn this on just for src/data/trainers.h $(C_BUILDDIR)/data.o: CFLAGS += -fno-show-column -fno-diagnostics-show-caret +$(TEST_BUILDDIR)/%.o: CFLAGS := -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -Wno-pointer-to-int-cast -Werror -Wall -Wno-strict-aliasing -Wno-attribute-alias -Woverride-init + # Dependency rules (for the *.c & *.s sources to .o files) # Have to be explicit or else missing files won't be reported. diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h new file mode 100644 index 000000000000..557b34b6537e --- /dev/null +++ b/include/constants/generational_changes.h @@ -0,0 +1,10 @@ +#ifndef GUARD_CONSTANTS_GENERATIONAL_CHANGES_H +#define GUARD_CONSTANTS_GENERATIONAL_CHANGES_H + +enum GenConfigTag +{ + GEN_CONFIG_GALE_WINGS, + GEN_CONFIG_COUNT +}; + +#endif // GUARD_CONSTANTS_GENERATIONAL_CHANGES_H diff --git a/include/generational_changes.h b/include/generational_changes.h new file mode 100644 index 000000000000..5a726007c36e --- /dev/null +++ b/include/generational_changes.h @@ -0,0 +1,41 @@ +#ifndef GUARD_GENERATIONAL_CHANGES_H +#define GUARD_GENERATIONAL_CHANGES_H + +#include "constants/generational_changes.h" +#include "config/battle.h" + +static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = +{ + [GEN_CONFIG_GALE_WINGS] = B_GALE_WINGS, +}; + +#if TESTING +extern u8 *gGenerationalChangesTestOverride; +#endif + +static inline u32 GetGenConfig(enum GenConfigTag configTag) +{ + if (configTag >= GEN_CONFIG_COUNT) return GEN_LATEST; +#if TESTING + if (gGenerationalChangesTestOverride == NULL) return sGenerationalChanges[configTag]; + return gGenerationalChangesTestOverride[configTag]; +#else + return sGenerationalChanges[configTag]; +#endif +} + +static inline void SetGenConfig(enum GenConfigTag configTag, u32 value) +{ +#if TESTING + if (configTag >= GEN_CONFIG_COUNT) return; + if (gGenerationalChangesTestOverride == NULL) return; + gGenerationalChangesTestOverride[configTag] = value; +#endif +} + +#if TESTING +void TestInitConfigData(void); +void TestFreeConfigData(void); +#endif + +#endif // GUARD_GENERATIONAL_CHANGES_H diff --git a/include/test/battle.h b/include/test/battle.h index d73443c30d68..c8ab519ba05b 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -287,6 +287,16 @@ * GIVEN { * FLAG_SET(FLAG_SYS_EXAMPLE_FLAG); * + * WITH_CONFIG(configTag, value) + * Runs the test with a specified config override. `configTag` must be + * of `enum GenConfigTag` + * Example: + * GIVEN { + * WITH_CONFIG(GEN_CONFIG_GALE_WINGS, GEN_6); + * } + * The `value` may be inferred from a local variable, e.g. set by + * PARAMETRIZE. + * * PLAYER(species) and OPPONENT(species) * Adds the species to the player's or opponent's party respectively. * The Pokémon can be further customized with the following functions: @@ -488,6 +498,7 @@ #include "battle.h" #include "battle_anim.h" #include "data.h" +#include "generational_changes.h" #include "item.h" #include "random.h" #include "recorded_battle.h" @@ -822,6 +833,7 @@ struct moveWithPP { #define AI_LOG AILogScores(__LINE__) #define FLAG_SET(flagId) SetFlagForTest(__LINE__, flagId) +#define WITH_CONFIG(configTag, value) TestSetConfig(__LINE__, configTag, value) #define PLAYER(species) for (OpenPokemon(__LINE__, B_SIDE_PLAYER, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__)) #define OPPONENT(species) for (OpenPokemon(__LINE__, B_SIDE_OPPONENT, species); gBattleTestRunnerState->data.currentMon; ClosePokemon(__LINE__)) @@ -855,6 +867,7 @@ struct moveWithPP { #define Shadow(isShadow) Shadow_(__LINE__, shadow) void SetFlagForTest(u32 sourceLine, u16 flagId); +void TestSetConfig(u32 sourceLine, enum GenConfigTag configTag, u32 value); void ClearFlagAfterTest(void); void OpenPokemon(u32 sourceLine, u32 side, u32 species); void ClosePokemon(u32 sourceLine); diff --git a/src/battle_main.c b/src/battle_main.c index 7508c6cb3a3a..3dad2c67d628 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -24,6 +24,7 @@ #include "event_data.h" #include "evolution_scene.h" #include "field_weather.h" +#include "generational_changes.h" #include "graphics.h" #include "gpu_regs.h" #include "international_string_util.h" @@ -4851,7 +4852,7 @@ s8 GetMovePriority(u32 battler, u16 move) return gMovesInfo[MOVE_MAX_GUARD].priority; if (ability == ABILITY_GALE_WINGS - && (B_GALE_WINGS < GEN_7 || BATTLER_MAX_HP(battler)) + && (GetGenConfig(GEN_CONFIG_GALE_WINGS) < GEN_7 || BATTLER_MAX_HP(battler)) && gMovesInfo[move].type == TYPE_FLYING) { priority++; diff --git a/src/generational_changes.c b/src/generational_changes.c new file mode 100644 index 000000000000..1ad29aa675e7 --- /dev/null +++ b/src/generational_changes.c @@ -0,0 +1,19 @@ +#include "global.h" +#include "generational_changes.h" +#include "malloc.h" +#include "constants/generational_changes.h" + +#if TESTING +EWRAM_DATA u8 *gGenerationalChangesTestOverride = NULL; + +void TestInitConfigData(void) +{ + gGenerationalChangesTestOverride = Alloc(sizeof(sGenerationalChanges)); + memcpy(gGenerationalChangesTestOverride, sGenerationalChanges, sizeof(sGenerationalChanges)); +} + +void TestFreeConfigData(void) +{ + TRY_FREE_AND_SET_NULL(gGenerationalChangesTestOverride) +} +#endif diff --git a/test/battle/ability/gale_wings.c b/test/battle/ability/gale_wings.c index eff458964927..c7a03d09148b 100644 --- a/test/battle/ability/gale_wings.c +++ b/test/battle/ability/gale_wings.c @@ -1,20 +1,22 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Gale Wings only grants priority at full HP") +SINGLE_BATTLE_TEST("Gale Wings only grants priority at full HP (Gen 7+)") { - u16 hp; - PARAMETRIZE { hp = 100; } - PARAMETRIZE { hp = 99; } + u32 hp, config; + PARAMETRIZE { hp = 100; config = GEN_7; } + PARAMETRIZE { hp = 99; config = GEN_7; } + PARAMETRIZE { hp = 100; config = GEN_6; } + PARAMETRIZE { hp = 99; config = GEN_6; } GIVEN { - ASSUME(B_GALE_WINGS >= GEN_7); + WITH_CONFIG(GEN_CONFIG_GALE_WINGS, config); ASSUME(gMovesInfo[MOVE_AERIAL_ACE].type == TYPE_FLYING); PLAYER(SPECIES_TALONFLAME) { Ability(ABILITY_GALE_WINGS); HP(hp); MaxHP(100); Speed(1);} OPPONENT(SPECIES_WOBBUFFET) { Speed(100);}; } WHEN { TURN { MOVE(player, MOVE_AERIAL_ACE); } } SCENE { - if (hp == 100) { + if (hp == 100 || config <= GEN_6) { MESSAGE("Talonflame used Aerial Ace!"); MESSAGE("The opposing Wobbuffet used Celebrate!"); } @@ -31,7 +33,6 @@ SINGLE_BATTLE_TEST("Gale Wings only grants priority to Flying-type moves") PARAMETRIZE { move = MOVE_AERIAL_ACE; } PARAMETRIZE { move = MOVE_FLARE_BLITZ; } GIVEN { - ASSUME(B_GALE_WINGS >= GEN_7); ASSUME(gMovesInfo[MOVE_AERIAL_ACE].type == TYPE_FLYING); ASSUME(gMovesInfo[MOVE_FLARE_BLITZ].type == TYPE_FIRE); PLAYER(SPECIES_TALONFLAME) { Ability(ABILITY_GALE_WINGS); HP(100); MaxHP(100); Speed(1);} @@ -58,7 +59,6 @@ SINGLE_BATTLE_TEST("Gale Wings doesn't increase priority of Flying-type Natural PARAMETRIZE { move = MOVE_JUDGMENT; heldItem = ITEM_SKY_PLATE; } PARAMETRIZE { move = MOVE_HIDDEN_POWER; heldItem = ITEM_NONE; } GIVEN { - ASSUME(B_GALE_WINGS >= GEN_7); ASSUME(gMovesInfo[MOVE_NATURAL_GIFT].effect == EFFECT_NATURAL_GIFT); ASSUME(gMovesInfo[MOVE_JUDGMENT].effect == EFFECT_CHANGE_TYPE_ON_ITEM); // IV combinations sourced from https://www.smogon.com/forums/threads/hidden-power-iv-combinations.78083/ diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index c55ef489b3e3..9484e6df6cf4 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -160,6 +160,7 @@ static void BattleTest_SetUp(void *data) { const struct BattleTest *test = data; memset(STATE, 0, sizeof(*STATE)); + TestInitConfigData(); InvokeTestFunction(test); STATE->parameters = STATE->parametersCount; if (STATE->parametersCount == 0 && test->resultsSize > 0) @@ -1417,6 +1418,7 @@ static void BattleTest_TearDown(void *data) // Free resources that aren't cleaned up when the battle was // aborted unexpectedly. ClearFlagAfterTest(); + TestFreeConfigData(); if (STATE->tearDownBattle) TearDownBattle(); } @@ -1513,6 +1515,12 @@ void SetFlagForTest(u32 sourceLine, u16 flagId) FlagSet(flagId); } +void TestSetConfig(u32 sourceLine, enum GenConfigTag configTag, u32 value) +{ + INVALID_IF(!STATE->runGiven, "WITH_CONFIG outside of GIVEN"); + SetGenConfig(configTag, value); +} + void ClearFlagAfterTest(void) { if (DATA.flagId != 0) From f864bf8b707e342cdd4771a564d89d852435f0df Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 30 Dec 2024 09:01:20 +0100 Subject: [PATCH 3/9] Adds Generational config for Magic Guard (Fix for Gen4+) (#5893) --- include/config/battle.h | 1 + src/battle_util.c | 5 ++++- test/battle/ability/magic_guard.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/include/config/battle.h b/include/config/battle.h index db3e6dcc77ff..f1ba1944dc62 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -155,6 +155,7 @@ // In Gen3, Effect Spore has a 10% chance to sleep, poison or paralyze, with an equal chance. // In Gen4, it's 30%. In Gen5+ it has 11% to sleep, 9% chance to poison and 10% chance to paralyze. #define B_PICKUP_WILD GEN_LATEST // In Gen9+, Pickup allows its user to pickup its own used item at the end of the turn in wild battles. +#define B_MAGIC_GUARD GEN_LATEST // In Gen4+, Magic Guard ignores immobilization caused by paralysis // Item settings #define B_HP_BERRIES GEN_LATEST // In Gen4+, berries which restore HP activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn. diff --git a/src/battle_util.c b/src/battle_util.c index a9956615a18b..66e219fff5aa 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3484,7 +3484,10 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) gBattleStruct->atkCancellerTracker++; break; case CANCELLER_PARALYSED: // paralysis - if (!gBattleStruct->isAtkCancelerForCalledMove && (gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && !RandomPercentage(RNG_PARALYSIS, 75)) + if (!gBattleStruct->isAtkCancelerForCalledMove + && gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS + && (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD && B_MAGIC_GUARD >= GEN_4) + && !RandomPercentage(RNG_PARALYSIS, 75)) { gProtectStructs[gBattlerAttacker].prlzImmobility = TRUE; // This is removed in FRLG and Emerald for some reason diff --git a/test/battle/ability/magic_guard.c b/test/battle/ability/magic_guard.c index 5579652265eb..20e8eb779c34 100644 --- a/test/battle/ability/magic_guard.c +++ b/test/battle/ability/magic_guard.c @@ -15,3 +15,32 @@ SINGLE_BATTLE_TEST("Magic Guard prevents recoil damage to the user") NOT HP_BAR(player); } } + +SINGLE_BATTLE_TEST("Magic Guard ignores immobilization that can be caused by paralysis") +{ + if (B_MAGIC_GUARD >= GEN_4) + PASSES_RANDOMLY(1, 1, RNG_PARALYSIS); + else + PASSES_RANDOMLY(75, 100, RNG_PARALYSIS); + GIVEN { + PLAYER(SPECIES_CLEFABLE) { Ability(ABILITY_MAGIC_GUARD); Status1(STATUS1_PARALYSIS);} + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + } +} + +SINGLE_BATTLE_TEST("Magic Guard does not ignore speed stat changes caused by paralysis") +{ + GIVEN { + PLAYER(SPECIES_CLEFABLE) { Speed(100); Ability(ABILITY_MAGIC_GUARD); Status1(STATUS1_PARALYSIS);} + OPPONENT(SPECIES_WOBBUFFET) { Speed(99); } + } WHEN { + TURN { } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + } +} From 07a7f87bac4d8b659276a3a61aa91efed027c314 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 30 Dec 2024 18:19:09 -0300 Subject: [PATCH 4/9] Improve README.md (#5640) --- README.md | 89 ++++++++++++++++++++++++++----------------------------- 1 file changed, 42 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 277dae2be785..4c6dff9fdd45 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # pokeemerald-expansion -### Important: DO NOT use GitHub's "Download Zip" option. Using this option will not download the commit history required to update your expansion version or merge other feature branches. Instead, please read [this guide](https://github.com/Pawkkie/Team-Aquas-Asset-Repo/wiki/The-Basics-of-GitHub) to learn how to fork the repository and clone locally from there. +pokeemerald-expansion is ***a romhack base*** based off pret's [pokeemerald](https://github.com/pret/pokeemerald) decompilation project. ***It is NOT a playable romhack,*** but it has multiple features available to romhackers so that they can create their own games, so it's not meant to be played on its own. -## What is pokeemerald-expansion? - -pokeemerald-expansion is a decomp hack base project based off pret's [pokeemerald](https://github.com/pret/pokeemerald) decompilation project. It's recommended that any new projects that plan on using it, to clone this repository instead of pret's vanilla repository, as we regurlarly incorporate pret's documentation changes. This is ***NOT*** a standalone romhack, and as such, most features will be unavailable and/or unbalanced if played as is. +## Should I use this or vanilla pokeemerald for my hack? +The main advantage of using vanilla pokeemerald as a base is being able to link with other official GBA Pokémon games for battles and trading, pokeemerald-expansion can battle and trade with itself out of the box. If you don't mind losing full vanilla compatiblitity, we recommend using pokeemerald-expansion. Otherwise, use pret's pokeemerald. You'll still receive documentation improvements from pret, as we regurlarly incorporate pret's documentation changes. ## Using pokeemerald-expansion @@ -14,8 +13,46 @@ You can phrase it as the following: Based off RHH's pokeemerald-expansion 1.10.0 https://github.com/rh-hideout/pokeemerald-expansion/ ``` +#### Important: DO NOT use GitHub's "Download Zip" option. Using this option will not download the commit history required to update your expansion version or merge other feature branches. Instead, please read [this guide](https://github.com/Pawkkie/Team-Aquas-Asset-Repo/wiki/The-Basics-of-GitHub) to learn how to fork the repository and clone locally from there. + Please follow the instructions in `INSTALL.md` to get pokeemerald-expansion set up on your machine. +### If I already have a project based on regular pokeemerald, can I use pokeemerald-expansion? +Yes! Keep in mind that we keep up with pret's documentation of pokeemerald, which means that if your project a bit old, you might get merge conflicts that you need to solve manually. +- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`. +- Once you have your remote set up, run the command `git pull RHH master`. + +With this, you'll get the latest version of pokeemerald-expansion, plus a couple of bugfixes that haven't yet been released into the next patch version :) + +## Documentation +[Please click here to visit our documentation page.](https://rh-hideout.github.io/pokeemerald-expansion/) + +## **How do I update my version of pokeemerald-expansion?** +- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`. +- Check your current version. + - You can check in the debug menu's `Utilities -> Expansion Version` option. + - If the option is not available, you possibly have version 1.6.2 or older. In that case, please check the [changelogs](docs/CHANGELOG.md) to determine your version based on the features available on your repository. +- ***Important:*** If you are several versions behind, we recommend updating one minor version at a time, skipping directly to the latest patch version (eg, 1.5.3 -> 1.6.2 -> 1.7.4 and so on. Check the [online documentation site](https://rh-hideout.github.io/pokeemerald-expansion/CHANGELOG.html) to see the latest versions of each step.) +- Once you have your remote set up, run the command `git pull RHH expansion/X.Y.Z`, replacing X, Y and Z with the digits of the respective version you want to update to (eg, to update to 1.9.3, use `git pull RHH expansion/1.9.3`). + - ***Important:*** If you are several versions behind, we recommend updating one minor version at a time, skipping directly to the latest patch version (eg, 1.5.3 -> 1.6.2 -> 1.7.4 and so on) +- Alternatively, you can update to unreleased versions of the expansion. + - ***master (stable):*** It contains unreleased **bugfixes** that will come in the next patch version. To merge, use `git pull RHH master`. + - ***upcoming (unstable, with potential bugs):*** It contains unreleased **features** that will come in the next minor version. To merge, use `git pull RHH upcoming`. + +### Please consider crediting the entire [list of contributors](https://github.com/rh-hideout/pokeemerald-expansion/wiki/Credits) in your project, as they have all worked hard to develop this project :) + +## Who maintains the project? +The project was originally started by DizzyEgg alongside other contributors. Now it is maintained by a team in the ROM Hacking Hideout's community called the "Expansion Senate". ROM Hacking Hideout (RHH for short) is a Discord-based ROM hacking community specialized in Pokémon romhacks. A lot of the discussion in regards of the development of the project happens there. + +[Click here to join the RHH Discord Server!](https://discord.gg/6CzjAG6GZk) + +## There's a bug in the project. How do I let you guys know? +Please submit any issues with the project [here](https://github.com/rh-hideout/pokeemerald-expansion/issues) and make sure that the issue wasn't reported by someone else by searching using the filters. You may also join the Discord server to try getting more in-depth support from the team and other members of the server. + +## Can I contribute even if I'm not a member of ROM Hacking Hideout? +Yes! Contributions are welcome via Pull Requests and they will be reviewed by maintainers in due time. +Also, *please follow the Pull Request template and feel free to discuss how the reviews are being handled. **Communication is key!*** Don't feel discouraged if we take a bit to review your PR, we'll get to it. + ## What features are included? - ***IMPORTANT*❗❗ Read through these to learn what features you can toggle**: - [Battle configurations](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/include/config/battle.h) @@ -160,46 +197,4 @@ Please follow the instructions in `INSTALL.md` to get pokeemerald-expansion set - All bugfixes from pret included. - Fixed overworld snow effect. -There are some mechanics, moves and abilities that are missing and being developed. Check [the project's milestones](https://github.com/rh-hideout/pokeemerald-expansion/milestones) to see which ones. - - -### [Documentation on features can be found here](https://github.com/rh-hideout/pokeemerald-expansion/wiki) - -## If I already have a project based on regular pokeemerald, can I use pokeemerald-expansion? -Yes! Keep in mind that we keep up with pret's documentation of pokeemerald, which means that if your project a bit old, you might get merge conflicts that you need to solve manually. -- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`. -- Once you have your remote set up, run the command `git pull RHH master`. - -With this, you'll get the latest version of pokeemerald-expansion, plus a couple of bugfixes that haven't been released into the next patch version :) - -## **How do I update my version of pokeemerald-expansion?** -- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`. -- Check your current version. - - You can check in the debug menu's `Utilities -> Expansion Version` option. - - If the option is not available, you possibly have version 1.6.2 or older. In that case, please check the [changelogs](CHANGELOG.md) to determine your version based on the features available on your repository. -- Once you have your remote set up, run the command `git pull RHH expansion/X.Y.Z`, replacing X, Y and Z with the digits of the respective version you want to update to (eg, to update to 1.10.0, use `git pull RHH expansion/1.10.0`). - - ***Important:*** If you are several versions behind, we recommend updating one minor version at a time, skipping directly to the latest patch version (eg, 1.5.3 -> 1.6.2 -> 1.7.4 and so on) -- Alternatively, you can update to unreleased versions of the expansion. - - ***master (stable):*** It contains unreleased **bugfixes** that will come in the next patch version. To merge, use `git pull RHH master`. - - ***upcoming (unstable, with potential bugs):*** It contains unreleased **features** that will come in the next minor version. To merge, use `git pull RHH upcoming`. - -### Please consider crediting the entire [list of contributors](https://github.com/rh-hideout/pokeemerald-expansion/wiki/Credits) in your project, as they have all worked hard to develop this project :) - -## There's a bug in the project. How do I let you guys know? -Please submit any issues with the project [here](https://github.com/rh-hideout/pokeemerald-expansion/issues). Make sure that the issue wasn't reported by someone else by searching using the filters. - -## Can I contribute even if I'm not a member of ROM Hacking Hideout? - -Yes! Contributions are welcome via Pull Requests and they will be reviewed by maintainers. Don't feel discouraged if we take a bit to review your PR, we'll get to it. - -## Who maintains the project? - -The project was originally started by DizzyEgg alongside other contributors. - -The project has now gotten larger and DizzyEgg is now maintaining the project as part of the ROM Hacking Hideout community. Some members of this community are taking on larger roles to help maintain the project. - -## What is the ROM Hacking Hideout? - -A Discord-based ROM hacking community that has many members who hack using the disassembly and decompilation projects for Pokémon. Quite a few contributors to the original feature branches by DizzyEgg were members of ROM Hacking Hideout. You can call it RHH for short! - -[Click here to join the RHH Discord Server!](https://discord.gg/6CzjAG6GZk) +There are some mechanics, moves and abilities that are missing and being developed. Check [the project's milestones](https://github.com/rh-hideout/pokeemerald-expansion/milestones) and our [issues page](https://github.com/rh-hideout/pokeemerald-expansion/issues) to see which ones. From bf125c8f5e249d960c18bb946f7b60a6ebb77678 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Mon, 30 Dec 2024 23:51:48 +0100 Subject: [PATCH 5/9] Fix wrong value for NUM_MOVE_EFFECTS (#5913) --- include/constants/battle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index a7300e65170e..bdabd816d5d5 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -418,7 +418,7 @@ #define MOVE_EFFECT_SALT_CURE 87 #define MOVE_EFFECT_EERIE_SPELL 88 -#define NUM_MOVE_EFFECTS 88 +#define NUM_MOVE_EFFECTS 89 #define MOVE_EFFECT_AFFECTS_USER 0x2000 #define MOVE_EFFECT_CERTAIN 0x4000 From 7e0c1f932314f71c7d4da69ded47ef1b165fa44f Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 31 Dec 2024 00:36:07 +0100 Subject: [PATCH 6/9] New U-turn animation to fix visibility (#5910) --- data/battle_anim_scripts.s | 37 +++++++++++++++---------------------- src/battle_anim_new.c | 23 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 80d50710baa7..ae8642feb483 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -350,34 +350,27 @@ gBattleAnimMove_MetalBurst:: waitforvisualfinish end +@Credits: Skeli gBattleAnimMove_UTurn:: - loadspritegfx ANIM_TAG_ROUND_SHADOW + loadspritegfx ANIM_TAG_SMALL_BUBBLES + loadspritegfx ANIM_TAG_RAZOR_LEAF loadspritegfx ANIM_TAG_IMPACT monbg ANIM_DEF_PARTNER - setalpha 12, 8 - playsewithpan SE_M_FLY, SOUND_PAN_ATTACKER - createsprite gFlyBallUpSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 13, 336 - playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_ATTACKER - createvisualtask AnimTask_CanBattlerSwitch, 1, ANIM_ATTACKER - jumpretfalse UTurnVisible - createsprite gFlyBallAttackSpriteTemplate, ANIM_ATTACKER, 2, 20, TRUE -UTurnContinue: - delay 20 - createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 1, 0 - createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 6, 0, 8, 1 - playsewithpan SE_M_RAZOR_WIND, SOUND_PAN_TARGET - waitforvisualfinish - clearmonbg ANIM_DEF_PARTNER - createvisualtask AnimTask_CanBattlerSwitch, 1, ANIM_ATTACKER - jumpretfalse UTurnLast + splitbgprio ANIM_TARGET + setalpha 8, 8 invisible ANIM_ATTACKER -UTurnLast: - blendoff + playsewithpan SE_M_JUMP_KICK, SOUND_PAN_ATTACKER + createsprite gUTurnBallSpriteTemplate, ANIM_TARGET, 2, 0, 0, 21 + waitforvisualfinish + playsewithpan SE_M_TAIL_WHIP, SOUND_PAN_ATTACKER + createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 1, 2 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 + createsprite gUTurnBallBackSpriteTemplate, ANIM_ATTACKER, 3, 4, 0, -16, 36 waitforvisualfinish + visible ANIM_ATTACKER + clearmonbg ANIM_TARGET + blendoff end -UTurnVisible: - createsprite gFlyBallAttackSpriteTemplate, ANIM_ATTACKER, 2, 20, FALSE - goto UTurnContinue gBattleAnimMove_CloseCombat:: loadspritegfx ANIM_TAG_IMPACT diff --git a/src/battle_anim_new.c b/src/battle_anim_new.c index 50bb83305f3a..2d1ad3e80715 100644 --- a/src/battle_anim_new.c +++ b/src/battle_anim_new.c @@ -4380,6 +4380,29 @@ const struct SpriteTemplate gSpriteTemplate_FlipTurnBack = { .callback = AnimAbsorptionOrb }; +// U-Turn +const struct SpriteTemplate gUTurnBallSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_RAZOR_LEAF, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_ShadowBall, + .callback = AnimShadowBall, +}; + +const struct SpriteTemplate gUTurnBallBackSpriteTemplate = +{ + .tileTag = ANIM_TAG_SMALL_BUBBLES, + .paletteTag = ANIM_TAG_RAZOR_LEAF, + .oam = &gOamData_AffineOff_ObjNormal_16x16, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_ShadowBall, + .callback = AnimAbsorptionOrb, +}; + // wicked blow static const union AffineAnimCmd sSpriteAffineAnim_DrainPunchFist[] = { AFFINEANIMCMD_FRAME(256, 256, 0, 1), //Double sprite size From 9d30299148134f02b69852b1191792d56afd76af Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 31 Dec 2024 00:38:01 +0100 Subject: [PATCH 7/9] Fixes Stance Change, Sleep Talk interaction (#5909) --- include/battle_util.h | 2 ++ src/battle_script_commands.c | 17 ----------------- src/battle_util.c | 23 +++++++++++++++++++++++ test/battle/ability/stance_change.c | 1 - 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 82f4ed2ce126..fc3840e800a6 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -101,6 +101,7 @@ enum { CANCELLER_FLAGS, CANCELLER_SKY_DROP, + CANCELLER_STANCE_CHANGE_1, CANCELLER_ASLEEP, CANCELLER_FROZEN, CANCELLER_OBEDIENCE, @@ -117,6 +118,7 @@ enum CANCELLER_IN_LOVE, CANCELLER_BIDE, CANCELLER_THAW, + CANCELLER_STANCE_CHANGE_2, CANCELLER_POWDER_MOVE, CANCELLER_POWDER_STATUS, CANCELLER_THROAT_CHOP, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 40f9db64c615..055f9e9c3b2d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1125,19 +1125,6 @@ static bool32 NoTargetPresent(u8 battler, u32 move) return FALSE; } -static bool32 TryFormChangeBeforeMove(void) -{ - bool32 result = TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_BEFORE_MOVE); - if (!result) - result = TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_BEFORE_MOVE_CATEGORY); - if (!result) - return FALSE; - - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_AttackerFormChange; - return TRUE; -} - bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType) { if ((ability == ABILITY_PROTEAN || ability == ABILITY_LIBERO) @@ -1206,8 +1193,6 @@ static void Cmd_attackcanceler(void) gBattlescriptCurrInstr = BattleScript_MoveEnd; return; } - if (B_STANCE_CHANGE_FAIL < GEN_7 && TryFormChangeBeforeMove()) - return; if (AtkCanceller_UnableToUseMove(moveType)) return; @@ -1267,8 +1252,6 @@ static void Cmd_attackcanceler(void) gMoveResultFlags |= MOVE_RESULT_MISSED; return; } - if (B_STANCE_CHANGE_FAIL >= GEN_7 && TryFormChangeBeforeMove()) - return; gHitMarker &= ~HITMARKER_ALLOW_NO_PP; diff --git a/src/battle_util.c b/src/battle_util.c index 66e219fff5aa..535c026145af 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3209,6 +3209,19 @@ void SetAtkCancellerForCalledMove(void) gBattleStruct->isAtkCancelerForCalledMove = TRUE; } +static inline bool32 TryFormChangeBeforeMove(void) +{ + bool32 result = TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_BEFORE_MOVE); + if (!result) + result = TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_BEFORE_MOVE_CATEGORY); + if (!result) + return FALSE; + + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AttackerFormChange; + return TRUE; +} + u8 AtkCanceller_UnableToUseMove(u32 moveType) { u32 effect = 0; @@ -3233,6 +3246,11 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) } gBattleStruct->atkCancellerTracker++; break; + case CANCELLER_STANCE_CHANGE_1: + if (B_STANCE_CHANGE_FAIL < GEN_7 && TryFormChangeBeforeMove()) + effect = 1; + gBattleStruct->atkCancellerTracker++; + break; case CANCELLER_ASLEEP: // check being asleep if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) { @@ -3573,6 +3591,11 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) } gBattleStruct->atkCancellerTracker++; break; + case CANCELLER_STANCE_CHANGE_2: + if (B_STANCE_CHANGE_FAIL >= GEN_7 && TryFormChangeBeforeMove()) + effect = 1; + gBattleStruct->atkCancellerTracker++; + break; case CANCELLER_POWDER_MOVE: if ((gMovesInfo[gCurrentMove].powderMove) && (gBattlerAttacker != gBattlerTarget)) { diff --git a/test/battle/ability/stance_change.c b/test/battle/ability/stance_change.c index 8221e16385b4..f8a0c70b3e48 100644 --- a/test/battle/ability/stance_change.c +++ b/test/battle/ability/stance_change.c @@ -63,7 +63,6 @@ SINGLE_BATTLE_TEST("Stance Change changes Aegislash from Blade to Shield when us SINGLE_BATTLE_TEST("Stance Change doesn't change Aegislash to Shield if King's Shield is called by a different move - Sleep Talk") { - KNOWN_FAILING; // Currently does change form GIVEN { ASSUME(gMovesInfo[MOVE_SLEEP_TALK].effect == EFFECT_SLEEP_TALK); PLAYER(SPECIES_AEGISLASH_BLADE) { Moves(MOVE_KINGS_SHIELD, MOVE_SLEEP_TALK); Status1(STATUS1_SLEEP_TURN(3)); } From 13dcd35db01faedc859f582ebfe7d0e11b68e5fb Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 31 Dec 2024 00:39:13 +0100 Subject: [PATCH 8/9] Fixes Round doubling it's BP if previous Round failed (#5907) --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index 535c026145af..2625a4b7cf15 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9121,7 +9121,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData case EFFECT_ROUND: for (i = 0; i < gBattlersCount; i++) { - if (i != battlerAtk && IsBattlerAlive(i) && gLastMoves[i] == MOVE_ROUND) + if (i != battlerAtk && IsBattlerAlive(i) && gMovesInfo[gLastUsedMove].effect == EFFECT_ROUND) { basePower *= 2; break; From e1275594c5492d0a63e23618905ae3f915d58163 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 31 Dec 2024 18:55:42 -0300 Subject: [PATCH 9/9] Renamed OW type effectiveness function for clarity (#5917) --- include/battle_util.h | 2 +- src/battle_util.c | 2 +- src/event_object_movement.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index fc3840e800a6..5c151665b969 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -237,7 +237,7 @@ s32 CalculateMoveDamageVars(struct DamageCalculationData *damageCalcData, u32 fi uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, u32 defAbility, bool32 recordAbilities); uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); uq4_12_t GetTypeModifier(u32 atkType, u32 defType); -uq4_12_t GetTypeEffectiveness(struct Pokemon *mon, u8 moveType); +uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType); s32 GetStealthHazardDamage(u8 hazardType, u32 battler); s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp); bool32 CanMegaEvolve(u32 battler); diff --git a/src/battle_util.c b/src/battle_util.c index 2625a4b7cf15..4dfb39dc66f8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10670,7 +10670,7 @@ static uq4_12_t GetInverseTypeMultiplier(uq4_12_t multiplier) } } -uq4_12_t GetTypeEffectiveness(struct Pokemon *mon, u8 moveType) +uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType) { uq4_12_t modifier = UQ_4_12(1.0); u16 abilityDef = GetMonAbility(mon); diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 47640b8f4ed1..0645d7073a02 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -2520,7 +2520,7 @@ void GetFollowerAction(struct ScriptContext *ctx) // Essentially a big switch fo } if (multi < NUMBER_OF_MON_TYPES) { - multi = GetTypeEffectiveness(mon, multi); + multi = GetOverworldTypeEffectiveness(mon, multi); if (multi <= UQ_4_12(0.5)) condEmotes[condCount++] = (struct SpecialEmote) {.emotion = FOLLOWER_EMOTION_HAPPY, .index = 32}; else if (multi >= UQ_4_12(2.0))