Skip to content

Commit

Permalink
Master to upcoming, 2024-11-29 (#5735)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bassoonian authored Nov 29, 2024
2 parents 4f1dced + 320c015 commit 5da1f32
Show file tree
Hide file tree
Showing 24 changed files with 299 additions and 25 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@

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.

## Using pokeemerald-expansion

If you use pokeemerald-expansion in your hack, please add RHH (Rom Hacking Hideout) to your credits list. Optionally, you can list the version used, so it can help players know what features to expect.
You can phrase it as the following:
```
Based off RHH's pokeemerald-expansion 1.9.3 https://github.com/rh-hideout/pokeemerald-expansion/
```

Please follow the instructions in `INSTALL.md` to get pokeemerald-expansion set up on your machine.

## 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)
Expand Down
4 changes: 2 additions & 2 deletions data/battle_anim_scripts.s
Original file line number Diff line number Diff line change
Expand Up @@ -10093,14 +10093,14 @@ gBattleAnimMove_FloralHealing::
loadspritegfx ANIM_TAG_ORBS @circles
loadspritegfx ANIM_TAG_PINK_PETAL @pink particles
monbg ANIM_ATTACKER
monbg ANIM_TARGET
playsewithpan SE_M_DETECT, SOUND_PAN_ATTACKER
call CIRCLES_LEAVES
call CIRCLES_LEAVES
waitforvisualfinish
panse SE_M_COMET_PUNCH, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 0x2, 0x0
playsewithpan SE_M_TWISTER, 0x0
createsprite gSweetScentPetalSpriteTemplate, ANIM_ATTACKER, 2, 0x46, 0x1, 0x40
clearmonbg ANIM_ATTACKER
delay 0x2
createsprite gFloralHealingWindLeavesTemplate, ANIM_ATTACKER, 2, 0x3c, 0x0, 0x40
delay 0x2
Expand All @@ -10123,6 +10123,7 @@ gBattleAnimMove_FloralHealing::
createsprite gSweetScentPetalSpriteTemplate, ANIM_ATTACKER, 2, 0x55, 0x0, 0x78
delay 0x2
loopsewithpan SE_M_POISON_POWDER, SOUND_PAN_TARGET, 0x12, 0xa
monbg ANIM_TARGET
call FloralHealingSpores
call FloralHealingSpores
call FloralHealingSpores
Expand All @@ -10133,7 +10134,6 @@ gBattleAnimMove_FloralHealing::
createsprite gGrantingStarsSpriteTemplate, ANIM_ATTACKER, 16, 0xc, 0xfffb, 0x1, 0x0, 0x20, 0x3c, 0x1
waitforvisualfinish
clearmonbg ANIM_TARGET
clearmonbg ANIM_ATTACKER
end
FloralHealingSpores:
createsprite gFloralHealingFlowerTemplate, ANIM_ATTACKER, 2, 0x0, 0xffec, 0x55, 0x50, 0x0
Expand Down
7 changes: 4 additions & 3 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -2401,7 +2401,6 @@ BattleScript_EffectHealingWish::
storehealingwish BS_ATTACKER
.if B_HEALING_WISH_SWITCH <= GEN_4
openpartyscreen BS_ATTACKER, BattleScript_EffectHealingWishEnd
switchoutabilities BS_ATTACKER
waitstate
switchhandleorder BS_ATTACKER, 2
returnatktoball
Expand Down Expand Up @@ -5755,7 +5754,6 @@ BattleScript_PrintFullBox::

BattleScript_ActionSwitch::
hpthresholds2 BS_ATTACKER
saveattacker
printstring STRINGID_RETURNMON
jumpifbattletype BATTLE_TYPE_DOUBLE, BattleScript_PursuitSwitchDmgSetMultihit
setmultihit 1
Expand All @@ -5773,7 +5771,6 @@ BattleScript_DoSwitchOut::
switchoutabilities BS_ATTACKER
updatedynamax
waitstate
restoreattacker
returnatktoball
waitstate
drawpartystatussummary BS_ATTACKER
Expand Down Expand Up @@ -9633,7 +9630,9 @@ BattleScript_EjectButtonActivates::
removeitem BS_SCRIPTING
makeinvisible BS_SCRIPTING
openpartyscreen BS_SCRIPTING, BattleScript_EjectButtonEnd
copybyte sSAVED_BATTLER, sBATTLER
switchoutabilities BS_SCRIPTING
copybyte sBATTLER, sSAVED_BATTLER
waitstate
switchhandleorder BS_SCRIPTING 0x2
returntoball BS_SCRIPTING, FALSE
Expand Down Expand Up @@ -9730,6 +9729,7 @@ BattleScript_PastelVeilEnd:
end3

BattleScript_NeutralizingGasExits::
saveattacker
savetarget
pause B_WAIT_TIME_SHORT
printstring STRINGID_NEUTRALIZINGGASOVER
Expand All @@ -9739,6 +9739,7 @@ BattleScript_NeutralizingGasExitsLoop:
switchinabilities BS_TARGET
addbyte gBattlerTarget, 1
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_NeutralizingGasExitsLoop
restoreattacker
restoretarget
return

Expand Down
Binary file modified graphics/pokemon/farfetchd/overworld.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified graphics/pokemon/melmetal/overworld.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions graphics/pokemon/melmetal/overworld_normal.pal
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
JASC-PAL
0100
16
255 255 255
120 255 255
254 235 185
220 220 218
235 192 100
Expand All @@ -16,4 +16,4 @@ JASC-PAL
64 64 64
45 43 43
8 8 8
0 0 0
255 255 255
2 changes: 1 addition & 1 deletion graphics/pokemon/melmetal/overworld_shiny.pal
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ JASC-PAL
64 64 64
45 43 43
8 8 8
0 0 0
255 255 255
Binary file modified graphics/pokemon/patrat/overworld.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified graphics/pokemon/woobat/overworld.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion include/constants/battle_script_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,9 @@ enum MoveEndEffects
MOVEEND_RECOIL,
MOVEEND_ITEM_EFFECTS_ATTACKER,
MOVEEND_MAGICIAN, // Occurs after final multi-hit strike, and after other items/abilities would activate
MOVEEND_RED_CARD, // Red Card triggers before Eject Pack
MOVEEND_EJECT_ITEMS,
MOVEEND_WHITE_HERB,
MOVEEND_RED_CARD,
MOVEEND_LIFEORB_SHELLBELL, // Includes shell bell, throat spray, etc
MOVEEND_CHANGED_ITEMS,
MOVEEND_PICKPOCKET,
Expand Down
4 changes: 4 additions & 0 deletions include/constants/form_change_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,8 @@
// param1: amount of days
#define FORM_CHANGE_DAYS_PASSED 23

// Form change for Aegislash
#define FORM_CHANGE_BATTLE_ATTACK 24
#define FORM_CHANGE_BATTLE_KINGS_SHIELD 25

#endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H
26 changes: 20 additions & 6 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,6 @@ static bool32 NoTargetPresent(u8 battler, u32 move)
return FALSE;
}

// TODO: Convert this to a proper FORM_CHANGE type.
static bool32 TryAegiFormChange(void)
{
// Only Aegislash with Stance Change can transform, transformed mons cannot.
Expand All @@ -1140,12 +1139,12 @@ static bool32 TryAegiFormChange(void)
case SPECIES_AEGISLASH_SHIELD: // Shield -> Blade
if (IS_MOVE_STATUS(gCurrentMove))
return FALSE;
gBattleMons[gBattlerAttacker].species = SPECIES_AEGISLASH_BLADE;
TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_ATTACK);
break;
case SPECIES_AEGISLASH_BLADE: // Blade -> Shield
if (gCurrentMove != MOVE_KINGS_SHIELD)
return FALSE;
gBattleMons[gBattlerAttacker].species = SPECIES_AEGISLASH_SHIELD;
TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_KINGS_SHIELD);
break;
}

Expand Down Expand Up @@ -1782,8 +1781,6 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
if (!RandomPercentage(RNG_ACCURACY, accuracy))
{
gMoveResultFlags |= MOVE_RESULT_MISSED;
if (holdEffectAtk == HOLD_EFFECT_BLUNDER_POLICY)
gBattleStruct->blunderPolicy = TRUE; // Only activates from missing through acc/evasion checks

if (gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_DARTS
&& !recalcDragonDarts // So we don't jump back and forth between targets
Expand Down Expand Up @@ -2266,6 +2263,7 @@ static void Cmd_adjustdamage(void)
}
if (gSpecialStatuses[gBattlerAttacker].gemBoost
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
&& gBattleMons[gBattlerAttacker].item
&& gMovesInfo[gCurrentMove].effect != EFFECT_PLEDGE
&& gCurrentMove != MOVE_STRUGGLE)
Expand Down Expand Up @@ -2678,6 +2676,13 @@ static void Cmd_resultmessage(void)
return;
}

if (gMoveResultFlags & MOVE_RESULT_MISSED && !(gMoveResultFlags & (MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED)))
{
if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_BLUNDER_POLICY
&& !IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove))
gBattleStruct->blunderPolicy = TRUE; // Only activates from missing through acc/evasion checks
}

if (gMoveResultFlags & MOVE_RESULT_MISSED && (!(gMoveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE) || gBattleCommunication[MISS_TYPE] > B_MSG_AVOIDED_ATK))
{
if (gBattleCommunication[MISS_TYPE] > B_MSG_AVOIDED_ATK) // Wonder Guard or Levitate - show the ability pop-up
Expand Down Expand Up @@ -4157,6 +4162,15 @@ static void Cmd_tryfaintmon(void)
}
else
{
if (gBattleMons[battler].ability == ABILITY_NEUTRALIZING_GAS
&& !(gAbsentBattlerFlags & (1u << battler))
&& !IsBattlerAlive(battler))
{
gBattleMons[battler].ability = ABILITY_NONE;
BattleScriptPush(gBattlescriptCurrInstr);
gBattlescriptCurrInstr = BattleScript_NeutralizingGasExits;
return;
}
if (cmd->battler == BS_ATTACKER)
{
destinyBondBattler = gBattlerTarget;
Expand Down Expand Up @@ -14788,7 +14802,7 @@ static void Cmd_switchoutabilities(void)
MarkBattlerForControllerExec(battler);
break;
case ABILITY_REGENERATOR:
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 3;
gBattleMoveDamage = GetNonDynamaxMaxHP(battler) / 3;
gBattleMoveDamage += gBattleMons[battler].hp;
if (gBattleMoveDamage > gBattleMons[battler].maxHP)
gBattleMoveDamage = gBattleMons[battler].maxHP;
Expand Down
8 changes: 6 additions & 2 deletions src/battle_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -6889,7 +6889,7 @@ static u8 TrySetEnigmaBerry(u32 battler)
{
if (IsBattlerAlive(battler)
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
&& ((TARGET_TURN_DAMAGED && gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements)
&& ((BATTLER_TURN_DAMAGED(battler) && gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements)
&& !(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP)
&& (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)))
{
Expand All @@ -6913,7 +6913,7 @@ static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category)
|| (!DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove)
&& GetBattleMoveCategory(gCurrentMove) == category
&& battler != gBattlerAttacker
&& TARGET_TURN_DAMAGED))
&& BATTLER_TURN_DAMAGED(battler)))
)
{
BufferStatChange(battler, statId, STRINGID_STATROSE);
Expand Down Expand Up @@ -10936,6 +10936,10 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method)
if (GetBattlerTeraType(battler) == formChanges[i].param1)
targetSpecies = formChanges[i].targetSpecies;
break;
case FORM_CHANGE_BATTLE_ATTACK:
case FORM_CHANGE_BATTLE_KINGS_SHIELD:
targetSpecies = formChanges[i].targetSpecies;
break;
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/data/moves_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -12217,7 +12217,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
{
.name = COMPOUND_STRING("Coil"),
.description = COMPOUND_STRING(
"Coils up to raise Attack\n"
"Coils up to raise Attack,\n"
"Defense and Accuracy."),
.effect = EFFECT_COIL,
.power = 0,
Expand Down Expand Up @@ -17335,7 +17335,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.name = COMPOUND_STRING("Octolock"),
.description = COMPOUND_STRING(
"Traps the foe to lower Def\n"
"and Sp. Def fall each turn."),
"and Sp. Def each turn."),
.effect = EFFECT_OCTOLOCK,
.power = 0,
.type = TYPE_FIGHTING,
Expand Down Expand Up @@ -20610,6 +20610,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] =
.priority = 0,
.category = DAMAGE_CATEGORY_PHYSICAL,
.makesContact = TRUE,
.minimizeDoubleDamage = TRUE,
.battleAnimScript = gBattleAnimMove_SupercellSlam,
},

Expand Down
8 changes: 5 additions & 3 deletions src/data/pokemon/form_change_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -789,9 +789,11 @@ static const struct FormChange sFurfrouFormChangeTable[] = {

#if P_FAMILY_HONEDGE
static const struct FormChange sAegislashFormChangeTable[] = {
{FORM_CHANGE_BATTLE_SWITCH, SPECIES_AEGISLASH_SHIELD},
{FORM_CHANGE_FAINT, SPECIES_AEGISLASH_SHIELD},
{FORM_CHANGE_END_BATTLE, SPECIES_AEGISLASH_SHIELD},
{FORM_CHANGE_BATTLE_ATTACK, SPECIES_AEGISLASH_BLADE},
{FORM_CHANGE_BATTLE_KINGS_SHIELD, SPECIES_AEGISLASH_SHIELD},
{FORM_CHANGE_BATTLE_SWITCH, SPECIES_AEGISLASH_SHIELD},
{FORM_CHANGE_FAINT, SPECIES_AEGISLASH_SHIELD},
{FORM_CHANGE_END_BATTLE, SPECIES_AEGISLASH_SHIELD},
{FORM_CHANGE_TERMINATOR},
};
#endif //P_FAMILY_HONEDGE
Expand Down
2 changes: 1 addition & 1 deletion test/battle/ability/dauntless_shield.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

ASSUMPTIONS
{
ASSUME(B_PROTEAN_LIBERO == GEN_9);
ASSUME(B_DAUNTLESS_SHIELD == GEN_9);
}

SINGLE_BATTLE_TEST("Dauntless Shield raises Defense by one stage")
Expand Down
90 changes: 89 additions & 1 deletion test/battle/ability/intimidate.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ DOUBLE_BATTLE_TEST("Intimidate is not going to trigger if a mon switches out thr
}
}

SINGLE_BATTLE_TEST("Intimidate activates when it's no longer effected by Neutralizing Gas")
SINGLE_BATTLE_TEST("Intimidate activates when it's no longer effected by Neutralizing Gas - switching out")
{
GIVEN {
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
Expand All @@ -263,3 +263,91 @@ SINGLE_BATTLE_TEST("Intimidate activates when it's no longer effected by Neutral
SEND_IN_MESSAGE("Wobbuffet");
}
}

SINGLE_BATTLE_TEST("Intimidate activates when it's no longer affected by Neutralizing Gas - switching moves")
{
u32 move;
PARAMETRIZE { move = MOVE_U_TURN; }
PARAMETRIZE { move = MOVE_HEALING_WISH; }
PARAMETRIZE { move = MOVE_BATON_PASS; }
GIVEN {
ASSUME(gMovesInfo[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE);
ASSUME(gMovesInfo[MOVE_HEALING_WISH].effect == EFFECT_HEALING_WISH);
ASSUME(gMovesInfo[MOVE_BATON_PASS].effect == EFFECT_BATON_PASS);
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); }
} WHEN {
TURN { MOVE(player, move); SEND_OUT(player, 1); }
} SCENE {
ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS);
MESSAGE("Neutralizing gas filled the area!");
ANIMATION(ANIM_TYPE_MOVE, move, player);
MESSAGE("The effects of the neutralizing gas wore off!");
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
SEND_IN_MESSAGE("Wobbuffet");
} THEN {
if (move == MOVE_HEALING_WISH)
EXPECT_EQ(player->hp, player->maxHP);
}
}

SINGLE_BATTLE_TEST("Intimidate activates when it's no longer affected by Neutralizing Gas - opponent caused switches")
{
u32 move, item;
PARAMETRIZE { move = MOVE_TACKLE; item = ITEM_EJECT_BUTTON; }
PARAMETRIZE { move = MOVE_GROWL; item = ITEM_EJECT_PACK; }
PARAMETRIZE { move = MOVE_ROAR; item = ITEM_NONE; }
PARAMETRIZE { move = MOVE_DRAGON_TAIL; item = ITEM_NONE; }
GIVEN {
ASSUME(gItemsInfo[ITEM_EJECT_BUTTON].holdEffect == HOLD_EFFECT_EJECT_BUTTON);
ASSUME(gItemsInfo[ITEM_EJECT_PACK].holdEffect == HOLD_EFFECT_EJECT_PACK);
ASSUME(gMovesInfo[MOVE_GROWL].effect == EFFECT_ATTACK_DOWN);
ASSUME(gMovesInfo[MOVE_ROAR].effect == EFFECT_ROAR);
ASSUME(gMovesInfo[MOVE_DRAGON_TAIL].effect == EFFECT_HIT_SWITCH_TARGET);
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); Item(item); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); }
} WHEN {
if (item != ITEM_NONE) {
TURN { MOVE(opponent, move); SEND_OUT(player, 1); }
} else {
TURN { MOVE(opponent, move); }
}
} SCENE {
ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS);
MESSAGE("Neutralizing gas filled the area!");
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
if (item != ITEM_NONE)
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("The effects of the neutralizing gas wore off!");
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
if (item != ITEM_NONE) {
SEND_IN_MESSAGE("Wobbuffet");
} else {
MESSAGE("Wobbuffet was dragged out!");
}
}
}

SINGLE_BATTLE_TEST("Intimidate activates when it's no longer affected by Neutralizing Gas - fainted")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_FELL_STINGER].effect == EFFECT_FELL_STINGER);
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); }
} WHEN {
TURN { MOVE(opponent, MOVE_FELL_STINGER); SEND_OUT(player, 1); }
} SCENE {
ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS);
MESSAGE("Neutralizing gas filled the area!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_FELL_STINGER, opponent);
MESSAGE("The effects of the neutralizing gas wore off!");
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
MESSAGE("Weezing fainted!");
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
SEND_IN_MESSAGE("Wobbuffet");
}
}

Loading

0 comments on commit 5da1f32

Please sign in to comment.