Add abilities Tera Shift, Tera Shell, and Teraform Zero (#4418)

* Add abilities Tera Shift, Tera Shell, and Teraform Zero

* Address reviews

* Tests and misc cleanup

* Fix alignments

* Update battle_script_commands.c

* New tests and fix behavior

* Address more reviews

* Update battle_util.c
This commit is contained in:
kittenchilly 2024-04-27 12:52:31 -05:00 committed by GitHub
parent 64b28124fb
commit d58e6517f8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 307 additions and 8 deletions

View file

@ -1638,6 +1638,10 @@
.4byte \failInstr
.endm
.macro removeweather
callnative BS_RemoveWeather
.endm
@ various command changed to more readable macros
.macro cancelmultiturnmoves battler:req
various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES

View file

@ -7078,6 +7078,29 @@ BattleScript_AttackerFormChangeEnd3NoPopup::
call BattleScript_AttackerFormChangeNoPopup
end3
BattleScript_AttackerFormChangeWithString::
pause 5
copybyte gBattlerAbility, gBattlerAttacker
call BattleScript_AbilityPopUp
flushtextbox
BattleScript_AttackerFormChangeWithStringNoPopup::
handleformchange BS_ATTACKER, 0
handleformchange BS_ATTACKER, 1
playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE
waitanimation
handleformchange BS_ATTACKER, 2
printstring STRINGID_PKMNTRANSFORMED
waitmessage B_WAIT_TIME_LONG
return
BattleScript_AttackerFormChangeWithStringEnd3::
call BattleScript_AttackerFormChangeWithString
end3
BattleScript_AttackerFormChangeWithStringEnd3NoPopup::
call BattleScript_AttackerFormChangeWithStringNoPopup
end3
BattleScript_AttackerFormChangeMoveEffect::
waitmessage 1
handleformchange BS_ATTACKER, 0
@ -8356,6 +8379,13 @@ BattleScript_ProteanActivates::
waitmessage B_WAIT_TIME_LONG
return
BattleScript_TeraShellDistortingTypeMatchups::
pause B_WAIT_TIME_SHORTEST
call BattleScript_AbilityPopUp
printstring STRINGID_PKMNMADESHELLGLEAM
waitmessage B_WAIT_TIME_LONG
return
BattleScript_CursedBodyActivates::
call BattleScript_AbilityPopUp
printstring STRINGID_CUSEDBODYDISABLED
@ -9261,6 +9291,25 @@ BattleScript_AnnounceAirLockCloudNine::
call BattleScript_ActivateWeatherAbilities
end3
BattleScript_ActivateTeraformZero::
call BattleScript_AbilityPopUp
waitmessage B_WAIT_TIME_LONG
jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_ANY, BattleScript_ActivateTeraformZero_RemoveWeather
jumpifhalfword CMP_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_ActivateTeraformZero_RemoveTerrain
goto BattleScript_ActivateTeraformZero_End
BattleScript_ActivateTeraformZero_RemoveWeather:
removeweather
printfromtable gWeatherEndsStringIds
waitmessage B_WAIT_TIME_LONG
jumpifhalfword CMP_NO_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_ActivateTeraformZero_End
BattleScript_ActivateTeraformZero_RemoveTerrain:
removeterrain
playanimation BS_ATTACKER, B_ANIM_RESTORE_BG
printfromtable gTerrainStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_ActivateTeraformZero_End:
end3
BattleScript_QuickClawActivation::
flushtextbox
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT

View file

@ -816,6 +816,7 @@ struct BattleStruct
u8 quickClawRandom[MAX_BATTLERS_COUNT];
u8 quickDrawRandom[MAX_BATTLERS_COUNT];
u8 boosterEnergyActivates;
u8 distortedTypeMatchups;
};
// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,

View file

@ -52,6 +52,7 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem);
u8 GetCatchingBattler(void);
u32 GetHighestStatId(u32 battlerId);
bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType);
bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef);
bool32 IsMoveNotAllowedInSkyBattles(u32 move);
bool32 DoSwitchInAbilities(u32 battlerId);
u8 GetFirstFaintedPartyIndex(u8 battlerId);

View file

@ -364,6 +364,8 @@ extern const u8 BattleScript_DancerActivates[];
extern const u8 BattleScript_AftermathDmg[];
extern const u8 BattleScript_AttackerFormChange[];
extern const u8 BattleScript_AttackerFormChangeEnd3[];
extern const u8 BattleScript_AttackerFormChangeWithString[];
extern const u8 BattleScript_AttackerFormChangeWithStringEnd3[];
extern const u8 BattleScript_TargetFormChange[];
extern const u8 BattleScript_AnticipationActivates[];
extern const u8 BattleScript_SlowStartEnds[];
@ -382,6 +384,7 @@ extern const u8 BattleScript_CheekPouchActivates[];
extern const u8 BattleScript_TotemVar[];
extern const u8 BattleScript_TotemFlaredToLife[];
extern const u8 BattleScript_AnnounceAirLockCloudNine[];
extern const u8 BattleScript_ActivateTeraformZero[];
extern const u8 BattleScript_BattlerAbilityStatRaiseOnSwitchIn[];
extern const u8 BattleScript_CottonDownActivates[];
extern const u8 BattleScript_BallFetch[];
@ -436,6 +439,7 @@ extern const u8 BattleScript_PastelVeilActivates[];
extern const u8 BattleScript_MimicryActivatesEnd3[];
extern const u8 BattleScript_ApplyMimicry[];
extern const u8 BattleScript_AttackerFormChangeEnd3NoPopup[];
extern const u8 BattleScript_AttackerFormChangeWithStringEnd3NoPopup[];
extern const u8 BattleScript_AttackerFormChangeMoveEffect[];
extern const u8 BattleScript_BothCanNoLongerEscape[];
extern const u8 BattleScript_OctolockEndTurn[];
@ -502,6 +506,7 @@ extern const u8 BattleScript_AromaVeilProtectsRet[];
extern const u8 BattleScript_LowerAtkSpAtk[];
extern const u8 BattleScript_Terastallization[];
extern const u8 BattleScript_BoosterEnergyEnd2[];
extern const u8 BattleScript_TeraShellDistortingTypeMatchups[];
// zmoves
extern const u8 BattleScript_ZMoveActivateDamaging[];

View file

@ -299,7 +299,7 @@
#define B_WEATHER_HAIL_PERMANENT (1 << 10)
#define B_WEATHER_HAIL (B_WEATHER_HAIL_TEMPORARY | B_WEATHER_HAIL_PERMANENT)
#define B_WEATHER_STRONG_WINDS (1 << 11)
#define B_WEATHER_ANY (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_SUN | B_WEATHER_HAIL | B_WEATHER_STRONG_WINDS | B_WEATHER_SNOW)
#define B_WEATHER_ANY (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_SUN | B_WEATHER_HAIL | B_WEATHER_STRONG_WINDS | B_WEATHER_SNOW | B_WEATHER_FOG)
#define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS)
#define B_WEATHER_SNOW_TEMPORARY (1 << 12)
#define B_WEATHER_SNOW_PERMANENT (1 << 13)

View file

@ -712,8 +712,9 @@
#define STRINGID_FOGCREPTUP 710
#define STRINGID_FOGISDEEP 711
#define STRINGID_FOGLIFTED 712
#define STRINGID_PKMNMADESHELLGLEAM 713
#define BATTLESTRINGS_COUNT 713
#define BATTLESTRINGS_COUNT 714
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
@ -767,6 +768,16 @@
#define B_MSG_STARTED_SNOW 6
#define B_MSG_STARTED_FOG 7
// gWeatherEndsStringIds
#define B_MSG_WEATHER_END_RAIN 0
#define B_MSG_WEATHER_END_SANDSTORM 1
#define B_MSG_WEATHER_END_SUN 2
#define B_MSG_WEATHER_END_HAIL 3
#define B_MSG_WEATHER_END_STRONG_WINDS 4
#define B_MSG_WEATHER_END_SNOW 5
#define B_MSG_WEATHER_END_FOG 6
#define B_MSG_WEATHER_END_COUNT 7
// gRainContinuesStringIds
#define B_MSG_RAIN_CONTINUES 0
#define B_MSG_DOWNPOUR_CONTINUES 1

View file

@ -61,7 +61,7 @@
#define FORM_CHANGE_END_BATTLE_TERRAIN 8
// Form change that activates when the Pokémon is switched out in battle.
// - No parameters.
// param1: ability to check, optional
#define FORM_CHANGE_BATTLE_SWITCH 9
// Form change that activates when the Pokémon's HP % passes a certain threshold.

View file

@ -724,6 +724,7 @@ static const u8 sText_ASandstormKickedUp[] = _("A sandstorm kicked up!");
static const u8 sText_PkmnsWillPerishIn3Turns[] = _("Both Pokémon will perish\nin three turns!");
static const u8 sText_AbilityRaisedStatDrastically[] = _("{B_DEF_ABILITY} raised {B_DEF_NAME_WITH_PREFIX}'s\n{B_BUFF1} drastically!");
static const u8 sText_AsOneEnters[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} has two Abilities!");
static const u8 sText_PkmnMadeShellGleam[] = _("{B_DEF_NAME_WITH_PREFIX} made its shell gleam!\nIt's distorting type matchups!");
static const u8 sText_CuriousMedicineEnters[] = _("{B_EFF_NAME_WITH_PREFIX}'s\nstat changes were reset!");
static const u8 sText_CanActFaster[] = _("{B_ATK_NAME_WITH_PREFIX} can act faster,\nthanks to {B_BUFF1}!");
static const u8 sText_MicleBerryActivates[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} boosted the accuracy of its\nnext move using {B_LAST_ITEM}!");
@ -964,6 +965,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_CANACTFASTERTHANKSTO - BATTLESTRINGS_TABLE_START] = sText_CanActFaster,
[STRINGID_CURIOUSMEDICINEENTERS - BATTLESTRINGS_TABLE_START] = sText_CuriousMedicineEnters,
[STRINGID_ASONEENTERS - BATTLESTRINGS_TABLE_START] = sText_AsOneEnters,
[STRINGID_PKMNMADESHELLGLEAM - BATTLESTRINGS_TABLE_START] = sText_PkmnMadeShellGleam,
[STRINGID_ABILITYRAISEDSTATDRASTICALLY - BATTLESTRINGS_TABLE_START] = sText_AbilityRaisedStatDrastically,
[STRINGID_PKMNSWILLPERISHIN3TURNS - BATTLESTRINGS_TABLE_START] = sText_PkmnsWillPerishIn3Turns,
[STRINGID_ASANDSTORMKICKEDUP - BATTLESTRINGS_TABLE_START] = sText_ASandstormKickedUp,
@ -1684,6 +1686,17 @@ const u16 gMoveWeatherChangeStringIds[] =
[B_MSG_STARTED_FOG] = STRINGID_FOGCREPTUP, // Unused, can use for custom moves that set fog
};
const u16 gWeatherEndsStringIds[B_MSG_WEATHER_END_COUNT] =
{
[B_MSG_WEATHER_END_RAIN] = STRINGID_RAINSTOPPED,
[B_MSG_WEATHER_END_SANDSTORM] = STRINGID_SANDSTORMSUBSIDED,
[B_MSG_WEATHER_END_SUN] = STRINGID_SUNLIGHTFADED,
[B_MSG_WEATHER_END_HAIL] = STRINGID_HAILSTOPPED,
[B_MSG_WEATHER_END_STRONG_WINDS] = STRINGID_STRONGWINDSDISSIPATED,
[B_MSG_WEATHER_END_SNOW] = STRINGID_SNOWSTOPPED,
[B_MSG_WEATHER_END_FOG] = STRINGID_FOGLIFTED,
};
const u16 gSandStormHailSnowContinuesStringIds[] =
{
[B_MSG_SANDSTORM] = STRINGID_SANDSTORMRAGES,

View file

@ -330,6 +330,7 @@ static bool8 IsFinalStrikeEffect(u16 move);
static void TryUpdateRoundTurnOrder(void);
static bool32 ChangeOrderTargetAfterAttacker(void);
void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler);
static void RemoveAllWeather(void);
static void RemoveAllTerrains(void);
static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 isIntimidate);
static bool8 CanBurnHitThaw(u16 move);
@ -1233,6 +1234,19 @@ bool32 ProteanTryChangeType(u32 battler, u32 ability, u32 move, u32 moveType)
return FALSE;
}
bool32 ShouldTeraShellDistortTypeMatchups(u32 move, u32 battlerDef)
{
if (!(gBattleStruct->distortedTypeMatchups & gBitTable[battlerDef])
&& GetBattlerAbility(battlerDef) == ABILITY_TERA_SHELL
&& gBattleMons[battlerDef].species == SPECIES_TERAPAGOS_TERASTAL
&& !IS_MOVE_STATUS(move)
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& gBattleMons[battlerDef].hp == gBattleMons[battlerDef].maxHP)
return TRUE;
return FALSE;
}
bool32 IsMoveNotAllowedInSkyBattles(u32 move)
{
return ((gBattleStruct->isSkyBattle) && (gMovesInfo[gCurrentMove].skyBattleBanned));
@ -1859,6 +1873,14 @@ static void Cmd_ppreduce(void)
gHitMarker &= ~HITMARKER_NO_PPDEDUCT;
gBattlescriptCurrInstr = cmd->nextInstr;
if (ShouldTeraShellDistortTypeMatchups(gCurrentMove, gBattlerTarget))
{
gBattleStruct->distortedTypeMatchups |= gBitTable[gBattlerTarget];
gBattlerAbility = gBattlerTarget;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_TeraShellDistortingTypeMatchups;
}
}
// The chance is 1/N for each stage.
@ -6326,6 +6348,7 @@ static void Cmd_moveend(void)
gBattleStruct->enduredDamage = 0;
gBattleStruct->additionalEffectsCounter = 0;
gBattleStruct->poisonPuppeteerConfusion = FALSE;
gBattleStruct->distortedTypeMatchups = 0;
gBattleScripting.moveendState++;
break;
case MOVEEND_COUNT:
@ -8397,6 +8420,30 @@ bool32 CanUseLastResort(u8 battler)
return (knownMovesCount >= 2 && usedMovesCount >= knownMovesCount - 1);
}
static void RemoveAllWeather(void)
{
gWishFutureKnock.weatherDuration = 0;
if (gBattleWeather & B_WEATHER_RAIN)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_RAIN;
else if(gBattleWeather & B_WEATHER_SANDSTORM)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_SANDSTORM;
else if(gBattleWeather & B_WEATHER_SUN)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_SUN;
else if(gBattleWeather & B_WEATHER_HAIL)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_HAIL;
else if(gBattleWeather & B_WEATHER_STRONG_WINDS)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_STRONG_WINDS;
else if(gBattleWeather & B_WEATHER_SNOW)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_SNOW;
else if(gBattleWeather & B_WEATHER_FOG)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_FOG;
else
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_END_COUNT; // failsafe
gBattleWeather = 0; // remove the weather
}
static void RemoveAllTerrains(void)
{
gFieldTimers.terrainTimer = 0;
@ -16825,7 +16872,6 @@ void BS_TryGulpMissile(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_TryQuash(void)
{
NATIVE_ARGS(const u8 *failInstr);
@ -16857,3 +16903,10 @@ void BS_TryQuash(void)
}
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_RemoveWeather(void)
{
NATIVE_ARGS();
RemoveAllWeather();
gBattlescriptCurrInstr = cmd->nextInstr;
}

View file

@ -4619,6 +4619,14 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
effect++;
}
break;
case ABILITY_TERAFORM_ZERO:
if (!gSpecialStatuses[battler].switchInAbilityDone
&& gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR)
{
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
BattleScriptPushCursorAndCallback(BattleScript_ActivateTeraformZero);
effect++;
}
case ABILITY_SCHOOLING:
if (gBattleMons[battler].level < 20)
break;
@ -4805,6 +4813,18 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
effect++;
}
break;
case ABILITY_TERA_SHIFT:
if (!gSpecialStatuses[battler].switchInAbilityDone
&& gBattleMons[battler].species == SPECIES_TERAPAGOS_NORMAL
&& TryBattleFormChange(battler, FORM_CHANGE_BATTLE_SWITCH))
{
gBattlerAttacker = battler;
gBattleScripting.abilityPopupOverwrite = gLastUsedAbility = ABILITY_TERA_SHIFT;
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeWithStringEnd3);
effect++;
}
break;
}
break;
case ABILITYEFFECT_ENDTURN: // 1
@ -10110,6 +10130,13 @@ static inline void MulByTypeEffectiveness(uq4_12_t *modifier, u32 move, u32 move
mod = UQ_4_12(1.0);
}
if (gBattleStruct->distortedTypeMatchups & gBitTable[battlerDef])
{
mod = UQ_4_12(0.5);
if (recordAbilities)
RecordAbilityBattle(battlerDef, GetBattlerAbility(battlerDef));
}
*modifier = uq4_12_multiply(*modifier, mod);
}
@ -10537,7 +10564,8 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method)
targetSpecies = formChanges[i].targetSpecies;
break;
case FORM_CHANGE_BATTLE_SWITCH:
targetSpecies = formChanges[i].targetSpecies;
if (formChanges[i].param1 == GetBattlerAbility(battler) || formChanges[i].param1 == ABILITY_NONE)
targetSpecies = formChanges[i].targetSpecies;
break;
case FORM_CHANGE_BATTLE_HP_PERCENT:
if (formChanges[i].param1 == GetBattlerAbility(battler))

View file

@ -1268,7 +1268,7 @@ static const struct FormChange sOgerponFormChangeTable[] = {
#if P_FAMILY_TERAPAGOS
static const struct FormChange sTerapagosFormChangeTable[] = {
{FORM_CHANGE_BEGIN_BATTLE, SPECIES_TERAPAGOS_TERASTAL}, //needs to be tied to the ability
{FORM_CHANGE_BATTLE_SWITCH, SPECIES_TERAPAGOS_TERASTAL, ABILITY_TERA_SHIFT},
#if P_TERA_FORMS
//{FORM_CHANGE_TERASTALLIZATION, SPECIES_TERAPAGOS_STELLAR},
#endif

View file

@ -23,7 +23,7 @@ SINGLE_BATTLE_TEST("Gastro Acid fails if target has a banned ability")
PARAMETRIZE { species = SPECIES_CRAMORANT; ability = ABILITY_GULP_MISSILE; }
PARAMETRIZE { species = SPECIES_PALAFIN_ZERO; ability = ABILITY_ZERO_TO_HERO; }
PARAMETRIZE { species = SPECIES_TATSUGIRI; ability = ABILITY_COMMANDER; }
// Needs confirmation since those abilities can be surpressed by Neutralizing Gas
// Needs confirmation since those abilities can be suppressed by Neutralizing Gas
// PARAMETRIZE { species = SPECIES_IRON_MOTH; ability = ABILITY_QUARK_DRIVE; }
// PARAMETRIZE { species = SPECIES_WALKING_WAKE; ability = ABILITY_PROTOSYNTHESIS; }
PARAMETRIZE { species = SPECIES_CALYREX_SHADOW_RIDER; ability = ABILITY_AS_ONE_SHADOW_RIDER; }

View file

@ -0,0 +1,99 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Tera Shell makes all moves against Terapagos not very effective when at full HP")
{
u16 hp;
PARAMETRIZE { hp = 100; }
PARAMETRIZE { hp = 99; }
GIVEN {
PLAYER(SPECIES_TERAPAGOS_TERASTAL) { Ability(ABILITY_TERA_SHELL); HP(hp); MaxHP(100);}
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
if (hp == 100) {
MESSAGE("Foe Wobbuffet used Tackle!");
ABILITY_POPUP(player, ABILITY_TERA_SHELL);
MESSAGE("Terapagos made its shell gleam! It's distorting type matchups!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent);
HP_BAR(player);
MESSAGE("It's not very effective…");
}
else {
NONE_OF {
ABILITY_POPUP(player, ABILITY_TERA_SHELL);
MESSAGE("Terapagos made its shell gleam! It's distorting type matchups!");
MESSAGE("It's not very effective…");
}
}
}
}
SINGLE_BATTLE_TEST("Tera Shell makes all hits of multi-hit moves against Terapagos not very effective")
{
s16 firstHit;
s16 secondHit;
GIVEN {
PLAYER(SPECIES_TERAPAGOS_TERASTAL) { Ability(ABILITY_TERA_SHELL); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_DOUBLE_HIT); }
} SCENE {
MESSAGE("Foe Wobbuffet used Double Hit!");
ABILITY_POPUP(player, ABILITY_TERA_SHELL);
MESSAGE("Terapagos made its shell gleam! It's distorting type matchups!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_HIT, opponent);
HP_BAR(player, captureDamage: &firstHit);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DOUBLE_HIT, opponent);
HP_BAR(player, captureDamage: &secondHit);
MESSAGE("It's not very effective…");
} THEN {
EXPECT_EQ(firstHit, secondHit);
}
}
DOUBLE_BATTLE_TEST("Tera Shell only makes the first hit of a double battle turn not very effective")
{
s16 firstHit;
s16 secondHit;
GIVEN {
PLAYER(SPECIES_TERAPAGOS_TERASTAL) { Ability(ABILITY_TERA_SHELL); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_TACKLE, target: playerLeft); MOVE(opponentRight, MOVE_TACKLE, target: playerLeft); }
} SCENE {
ABILITY_POPUP(playerLeft, ABILITY_TERA_SHELL);
MESSAGE("Terapagos made its shell gleam! It's distorting type matchups!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentLeft);
HP_BAR(playerLeft, captureDamage: &firstHit);
MESSAGE("It's not very effective…");
ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentRight);
HP_BAR(playerLeft, captureDamage: &secondHit);
NOT MESSAGE("It's not very effective…");
} THEN {
EXPECT_MUL_EQ(firstHit, Q_4_12(2.0), secondHit);
}
}
DOUBLE_BATTLE_TEST("Tera Shell only makes the first hit against Terapagos from a multi-target move not very effective")
{
GIVEN {
PLAYER(SPECIES_TERAPAGOS_TERASTAL) { Ability(ABILITY_TERA_SHELL); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_BLIZZARD); }
} SCENE {
ABILITY_POPUP(playerLeft, ABILITY_TERA_SHELL);
MESSAGE("Terapagos made its shell gleam! It's distorting type matchups!");
ANIMATION(ANIM_TYPE_MOVE, MOVE_BLIZZARD, opponentLeft);
HP_BAR(playerLeft);
MESSAGE("It's not very effective…");
HP_BAR(playerRight);
NOT MESSAGE("It's not very effective…");
}
}

View file

@ -0,0 +1,35 @@
#include "global.h"
#include "test/battle.h"
SINGLE_BATTLE_TEST("Tera Shift transforms Terapagos into its Terastal form on switch in")
{
GIVEN {
PLAYER(SPECIES_TERAPAGOS_NORMAL) { Ability(ABILITY_TERA_SHIFT); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { ; }
} SCENE {
ABILITY_POPUP(player, ABILITY_TERA_SHIFT);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
MESSAGE("Terapagos transformed!");
} THEN {
EXPECT_EQ(player->species, SPECIES_TERAPAGOS_TERASTAL);
}
}
SINGLE_BATTLE_TEST("Tera Shift can't be suppressed by Neutralizing Gas")
{
GIVEN {
PLAYER(SPECIES_TERAPAGOS_NORMAL) { Ability(ABILITY_TERA_SHIFT); }
OPPONENT(SPECIES_KOFFING) { Ability(ABILITY_NEUTRALIZING_GAS); }
} WHEN {
TURN { ; }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
ABILITY_POPUP(player, ABILITY_TERA_SHIFT);
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player);
MESSAGE("Terapagos transformed!");
} THEN {
EXPECT_EQ(player->species, SPECIES_TERAPAGOS_TERASTAL);
}
}

View file

@ -20,7 +20,7 @@ SINGLE_BATTLE_TEST("Zero to Hero transforms Palafin when it switches out")
} THEN { EXPECT_EQ(player->species, SPECIES_PALAFIN_HERO); }
}
SINGLE_BATTLE_TEST("Zero to Hero can't be surpressed by Neutralizing Gas")
SINGLE_BATTLE_TEST("Zero to Hero can't be suppressed by Neutralizing Gas")
{
GIVEN {
PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }