Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Master to upcoming, 2024-12-29 #5903

Merged
merged 9 commits into from
Dec 29, 2024
11 changes: 3 additions & 8 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -415,13 +415,13 @@ BattleScript_SaltCureExtraDamage::
call BattleScript_HurtTarget_NoString
printstring STRINGID_TARGETISHURTBYSALTCURE
waitmessage B_WAIT_TIME_LONG
tryfaintmon BS_TARGET
end2

BattleScript_HurtTarget_NoString:
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE
healthbarupdate BS_TARGET
datahpupdate BS_TARGET
tryfaintmon BS_TARGET
return

BattleScript_EffectCorrosiveGas::
Expand Down Expand Up @@ -7560,13 +7560,8 @@ BattleScript_AbilityPopUp:
return

BattleScript_AbilityPopUpScripting:
.if B_ABILITY_POP_UP == TRUE
showabilitypopup BS_SCRIPTING
pause 40
.endif
recordability BS_SCRIPTING
sethword sABILITY_OVERWRITE, 0
return
copybyte gBattlerAbility, sBATTLER
goto BattleScript_AbilityPopUp

BattleScript_AbilityPopUpOverwriteThenNormal:
setbyte sFIXED_ABILITY_POPUP, TRUE
Expand Down
18 changes: 18 additions & 0 deletions docs/tutorials/how_to_new_pokemon_1_10_0.md
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,24 @@ static const u16 sPecharuntTeachableLearnset[] = {
#endif
```

_NOTE: At the top of this file, you will probably see this warning:_
```
//
// DO NOT MODIFY THIS FILE! It is auto-generated from tools/learnset_helpers/teachable.py`
//
```
The expansion includes a tool called the learnset helper, which aims to automate the generation of valid teachable moves. At the time of writing, this tool only supports generating TM and Tutor learnsets. However, in the future it may be expanded to deal with level up learnsets and egg moves.

Ignore the warning shown above the first time you're adding your teachable moves (as otherwise the compiler will complain about the array not existing), but in the future (if you're using the learnset helper) simply edit what teachable moves your Pokémon can learn in one of the JSON files found in `tools/learnset_helpers/porymoves_files`. It doesn't really matter which one you add your new Pokémon to, as the tool pulls from all of the files in this folder.

The learnset helper is useful if you plan on changing and/or increasing the available TMs and Tutor moves in your game. As an example, Bulbasaur learns Rage by TM in Red/Blue/Yellow, but in Emerald this TM does not exist. But since `tools/learnset_helpers/porymoves_files/rby.json` defines "MOVE_RAGE" as a TM move for Bulbasaur, that move would automatically be added to the `sBulbasaurTeachableLearnset` array if you were to add a Rage TM at any point.

The learnset helper can be toggled on/off in `include/config/pokemon.h`:
```
// Learnset helper toggles
#define P_LEARNSET_HELPER_TEACHABLE TRUE // If TRUE, teachable_learnsets.h will be populated by tools/learnset_helpers/teachable.py using the included JSON files based on available TMs and tutors.
```

Once more, we need to register the learnset in `gSpeciesInfo`:

```diff
Expand Down
18 changes: 18 additions & 0 deletions docs/tutorials/how_to_new_pokemon_1_9_0.md
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,24 @@ static const u16 sPecharuntTeachableLearnset[] = {
#endif
```

_NOTE: At the top of this file, you will probably see this warning:_
```
//
// DO NOT MODIFY THIS FILE! It is auto-generated from tools/learnset_helpers/teachable.py`
//
```
The expansion includes a tool called the learnset helper, which aims to automate the generation of valid teachable moves. At the time of writing, this tool only supports generating TM and Tutor learnsets. However, in the future it may be expanded to deal with level up learnsets and egg moves.

Ignore the warning shown above the first time you're adding your teachable moves (as otherwise the compiler will complain about the array not existing), but in the future (if you're using the learnset helper) simply edit what teachable moves your Pokémon can learn in one of the JSON files found in `tools/learnset_helpers/porymoves_files`. It doesn't really matter which one you add your new Pokémon to, as the tool pulls from all of the files in this folder.

The learnset helper is useful if you plan on changing and/or increasing the available TMs and Tutor moves in your game. As an example, Bulbasaur learns Rage by TM in Red/Blue/Yellow, but in Emerald this TM does not exist. But since `tools/learnset_helpers/porymoves_files/rby.json` defines "MOVE_RAGE" as a TM move for Bulbasaur, that move would automatically be added to the `sBulbasaurTeachableLearnset` array if you were to add a Rage TM at any point.

The learnset helper can be toggled on/off in `include/config/pokemon.h`:
```
// Learnset helper toggles
#define P_LEARNSET_HELPER_TEACHABLE TRUE // If TRUE, teachable_learnsets.h will be populated by tools/learnset_helpers/teachable.py using the included JSON files based on available TMs and tutors.
```

Once more, we need to register the learnset in `gSpeciesInfo`:

```diff
Expand Down
2 changes: 1 addition & 1 deletion include/test/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ extern struct BattleTestRunnerState *const gBattleTestRunnerState;
/* Test */

#define TO_DO_BATTLE_TEST(_name) \
TEST("TODO: " _name) \
TEST(_name) \
{ \
TO_DO; \
}
Expand Down
14 changes: 7 additions & 7 deletions src/battle_gfx_sfx_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1185,7 +1185,7 @@ void CreateEnemyShadowSprite(u32 battler)
{
gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary = CreateSprite(&gSpriteTemplate_EnemyShadow,
GetBattlerSpriteCoord(battler, BATTLER_COORD_X),
GetBattlerSpriteCoord(battler, BATTLER_COORD_Y),
GetBattlerSpriteCoord(battler, BATTLER_COORD_Y) + 29,
0xC8);
if (gBattleSpritesDataPtr->healthBoxesData[battler].shadowSpriteIdPrimary < MAX_SPRITES)
{
Expand Down Expand Up @@ -1247,9 +1247,11 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite)
return;
}

s8 xOffset = 0, yOffset = 0, size = SHADOW_SIZE_S;
s8 xOffset = 0, UNUSED yOffset = 0, size = SHADOW_SIZE_S;
if (gAnimScriptActive || battlerSprite->invisible)
{
invisible = TRUE;
}
else if (transformSpecies != SPECIES_NONE)
{
xOffset = gSpeciesInfo[transformSpecies].enemyShadowXOffset;
Expand All @@ -1267,21 +1269,19 @@ void SpriteCB_EnemyShadow(struct Sprite *shadowSprite)
yOffset = gSpeciesInfo[species].enemyShadowYOffset + 16;
size = gSpeciesInfo[species].enemyShadowSize;
}
else
{
yOffset = 29;
}

if (gBattleSpritesDataPtr->battlerData[battler].behindSubstitute)
invisible = TRUE;

shadowSprite->x = battlerSprite->x + xOffset;
shadowSprite->x2 = battlerSprite->x2;
shadowSprite->y = battlerSprite->y + yOffset;
shadowSprite->invisible = invisible;

if (B_ENEMY_MON_SHADOW_STYLE >= GEN_4 && P_GBA_STYLE_SPECIES_GFX == FALSE)
{
shadowSprite->oam.tileNum = shadowSprite->tBaseTileNum + (8 * size);
shadowSprite->y = battlerSprite->y + yOffset;
}
}

#undef tBattlerId
Expand Down
112 changes: 112 additions & 0 deletions test/battle/ability/liquid_ooze.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include "global.h"
#include "test/battle.h"

SINGLE_BATTLE_TEST("Liquid Ooze causes Absorb users to lose HP instead of heal")
{
s16 damage;
s16 healed;
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
} WHEN {
TURN { MOVE(player, MOVE_ABSORB); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ABSORB, player);
HP_BAR(opponent, captureDamage: &damage);
HP_BAR(player, captureDamage: &healed);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
} THEN {
EXPECT_MUL_EQ(damage, Q_4_12(0.5), healed);
}
}

SINGLE_BATTLE_TEST("Liquid Ooze causes Leech Seed users to lose HP instead of heal")
{
s16 damage;
s16 healed;

GIVEN {
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
} WHEN {
TURN { MOVE(player, MOVE_LEECH_SEED); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, player);
HP_BAR(opponent, captureDamage: &damage);
HP_BAR(player, captureDamage: &healed);
} THEN {
EXPECT_EQ(damage, healed);
}
}

DOUBLE_BATTLE_TEST("Liquid Ooze causes Matcha Gatcha users to lose HP instead of heal")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_MATCHA_GOTCHA].effect == EFFECT_ABSORB);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(playerLeft);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
MESSAGE("Wobbuffet fainted!");
}
}

DOUBLE_BATTLE_TEST("Liquid Ooze will faint Matcha Gatcha users if it deals enough damage")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_MATCHA_GOTCHA].effect == EFFECT_ABSORB);
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_TENTACOOL) { Ability(ABILITY_LIQUID_OOZE); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_MATCHA_GOTCHA); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_MATCHA_GOTCHA, playerLeft);
HP_BAR(opponentLeft);
HP_BAR(playerLeft);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
MESSAGE("Wobbuffet fainted!");
}
}

SINGLE_BATTLE_TEST("Liquid Ooze causes Strength Sap users to lose HP instead of heal")
{
s16 lostHp;
s32 atkStat;

PARAMETRIZE { atkStat = 100; }
PARAMETRIZE { atkStat = 490; } // Checks that attacker can faint with no problems.

GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { Attack(atkStat); Ability(ABILITY_LIQUID_OOZE); }
} WHEN {
TURN { MOVE(player, MOVE_STRENGTH_SAP); if (atkStat == 490) { SEND_OUT(player, 1); } }
} SCENE {
MESSAGE("Wobbuffet used Strength Sap!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_STRENGTH_SAP, player);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("The opposing Wobbuffet's Attack fell!");
ABILITY_POPUP(opponent, ABILITY_LIQUID_OOZE);
HP_BAR(player, captureDamage: &lostHp);
MESSAGE("Wobbuffet sucked up the liquid ooze!");
if (atkStat >= 490) {
MESSAGE("Wobbuffet fainted!");
SEND_IN_MESSAGE("Wobbuffet");
}
} THEN {
EXPECT_EQ(lostHp, atkStat);
}
}

TO_DO_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4");
TO_DO_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+");
73 changes: 0 additions & 73 deletions test/battle/crit_chance.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,76 +271,3 @@ SINGLE_BATTLE_TEST("Crit Chance: Focus Energy increases critical hit ratio by tw
MESSAGE("A critical hit!");
}
}

SINGLE_BATTLE_TEST("Crit Chance: Dragon Cheer fails in a single battle")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_DRAGON_CHEER); }
} SCENE {
MESSAGE("But it failed!");
}
}

DOUBLE_BATTLE_TEST("Crit Chance: Dragon Cheer increases critical hit ratio by one on non Dragon types")
{
PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT);
GIVEN {
ASSUME(B_CRIT_CHANCE >= GEN_7);
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WYNAUT);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_CHEER, target: playerRight); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerLeft);
MESSAGE("Wynaut is getting pumped!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
MESSAGE("A critical hit!");
}
}

DOUBLE_BATTLE_TEST("Crit Chance: Dragon Cheer increases critical hit ratio by two on Dragon types")
{
PASSES_RANDOMLY(1, 2, RNG_CRITICAL_HIT);
GIVEN {
ASSUME(B_CRIT_CHANCE >= GEN_7);
ASSUME(gMovesInfo[MOVE_TACKLE].criticalHitStage == 0);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_DRATINI);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_DRAGON_CHEER, target: playerRight); MOVE(playerRight, MOVE_TACKLE, target: opponentLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CHEER, playerLeft);
MESSAGE("Dratini is getting pumped!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerRight);
MESSAGE("A critical hit!");
}
}

DOUBLE_BATTLE_TEST("Crit Chance: Dragon Cheer fails if critical hit stage was already increased by Focus Energy")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_SLASH].criticalHitStage == 1);
ASSUME(gMovesInfo[MOVE_FOCUS_ENERGY].effect == EFFECT_FOCUS_ENERGY);
ASSUME(gMovesInfo[MOVE_DRAGON_CHEER].effect == EFFECT_DRAGON_CHEER);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(playerLeft, MOVE_FOCUS_ENERGY); MOVE(playerRight, MOVE_DRAGON_CHEER, target: playerLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FOCUS_ENERGY, playerLeft);
MESSAGE("But it failed!");
}
}
34 changes: 0 additions & 34 deletions test/battle/gimmick/dynamax.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,6 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon cannot be hit by OHKO moves")
}
}

// can't be used at all in Raid, see "Documenting Dynamax"
SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon are not affected by Destiny Bond")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET) { Speed(50); };
OPPONENT(SPECIES_WOBBUFFET) { HP(1); Speed(100); }
} WHEN {
TURN { MOVE(opponent, MOVE_DESTINY_BOND); MOVE(player, MOVE_TACKLE, gimmick: GIMMICK_DYNAMAX); }
} SCENE {
MESSAGE("The opposing Wobbuffet used Destiny Bond!");
MESSAGE("Wobbuffet used Max Strike!");
MESSAGE("The opposing Wobbuffet fainted!");
NONE_OF { HP_BAR(player); }
}
}

SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon are affected by Grudge")
{
GIVEN {
Expand Down Expand Up @@ -362,24 +346,6 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon lose their substitutes")
}
}

SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon take double damage from Dynamax Cannon", s16 damage)
{
u32 dynamax;
PARAMETRIZE { dynamax = GIMMICK_NONE; }
PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; }
GIVEN {
ASSUME(gMovesInfo[MOVE_DYNAMAX_CANNON].effect == EFFECT_DYNAMAX_DOUBLE_DMG);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_TACKLE, gimmick: dynamax); MOVE(opponent, MOVE_DYNAMAX_CANNON); }
} SCENE {
HP_BAR(player, captureDamage: &results[i].damage);
} FINALLY {
EXPECT_MUL_EQ(results[0].damage, UQ_4_12(2.0), results[1].damage);
}
}

SINGLE_BATTLE_TEST("(DYNAMAX) Max Moves deal 1/4 damage through protect", s16 damage)
{
bool32 protected;
Expand Down
Loading
Loading