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:
parent
64b28124fb
commit
d58e6517f8
16 changed files with 307 additions and 8 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
99
test/battle/ability/tera_shell.c
Normal file
99
test/battle/ability/tera_shell.c
Normal 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…");
|
||||
}
|
||||
}
|
35
test/battle/ability/tera_shift.c
Normal file
35
test/battle/ability/tera_shift.c
Normal 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);
|
||||
}
|
||||
}
|
|
@ -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); }
|
||||
|
|
Loading…
Reference in a new issue