Adds ability Zero to Hero (#3542)

This commit is contained in:
Alex 2023-11-09 12:25:46 +01:00 committed by GitHub
parent 954f67a29f
commit 4b3c96a89b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 183 additions and 2 deletions

View file

@ -8678,6 +8678,13 @@ BattleScript_CostarActivates::
waitmessage B_WAIT_TIME_LONG
end3
BattleScript_ZeroToHeroActivates::
pause B_WAIT_TIME_SHORT
call BattleScript_AbilityPopUp
printstring STRINGID_ZEROTOHEROTRANSFORMATION
waitmessage B_WAIT_TIME_LONG
end3
BattleScript_AttackWeakenedByStrongWinds::
pause B_WAIT_TIME_SHORT
printstring STRINGID_ATTACKWEAKENEDBSTRONGWINDS

View file

@ -700,7 +700,7 @@ struct BattleStruct
bool8 effectsBeforeUsingMoveDone:1; // Mega Evo and Focus Punch/Shell Trap effects.
u8 targetsDone[MAX_BATTLERS_COUNT]; // Each battler as a bit.
u16 overwrittenAbilities[MAX_BATTLERS_COUNT]; // abilities overwritten during battle (keep separate from battle history in case of switching)
bool8 allowedToChangeFormInWeather[PARTY_SIZE][2]; // For each party member and side, used by Ice Face.
bool8 allowedToChangeFormInWeather[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side, used by Ice Face.
u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party.
u8 storedHealingWish:4; // Each battler as a bit.
u8 storedLunarDance:4; // Each battler as a bit.
@ -718,6 +718,7 @@ struct BattleStruct
bool8 trainerSlideBeforeFirstTurnMsgDone;
u32 aiDelayTimer; // Counts number of frames AI takes to choose an action.
u32 aiDelayFrames; // Number of frames it took to choose an action.
bool8 transformZeroToHero[PARTY_SIZE][NUM_BATTLE_SIDES];
};
// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,

View file

@ -459,6 +459,7 @@ extern const u8 BattleScript_RuinAbilityActivates[];
extern const u8 BattleScript_CudChewActivates[];
extern const u8 BattleScript_SupremeOverlordActivates[];
extern const u8 BattleScript_CostarActivates[];
extern const u8 BattleScript_ZeroToHeroActivates[];
extern const u8 BattleScript_ToxicDebrisActivates[];
extern const u8 BattleScript_EarthEaterActivates[];
extern const u8 BattleScript_MimicryActivates_End3[];

View file

@ -685,8 +685,9 @@
#define STRINGID_TEAMSURROUNDEDBYROCKS 683
#define STRINGID_PKMNHURTBYROCKSTHROWN 684
#define STRINGID_MOVEBLOCKEDBYDYNAMAX 685
#define STRINGID_ZEROTOHEROTRANSFORMATION 686
#define BATTLESTRINGS_COUNT 686
#define BATTLESTRINGS_COUNT 687
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,

View file

@ -822,9 +822,11 @@ static const u8 sText_TargetIsBeingSaltCured[] = _("{B_DEF_NAME_WITH_PREFIX} is
static const u8 sText_TargetIsHurtBySaltCure[] = _("{B_DEF_NAME_WITH_PREFIX} is hurt by {B_BUFF1}!");
static const u8 sText_OpportunistCopied[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX} copied its\nopponent's stat changes!");
static const u8 sText_TargetCoveredInStickyCandySyrup[] = _("{B_DEF_NAME_WITH_PREFIX} got covered\nin sticky syrup!");
static const u8 sText_ZeroToHeroTransformation[] = _("{B_ATK_NAME_WITH_PREFIX} underwent a heroic\ntransformation!");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_ZEROTOHEROTRANSFORMATION - BATTLESTRINGS_TABLE_START] = sText_ZeroToHeroTransformation,
[STRINGID_MOVEBLOCKEDBYDYNAMAX - BATTLESTRINGS_TABLE_START] = sText_MoveBlockedByDynamax,
[STRINGID_OPPORTUNISTCOPIED - BATTLESTRINGS_TABLE_START] = sText_OpportunistCopied,
[STRINGID_TARGETISHURTBYSALTCURE - BATTLESTRINGS_TABLE_START] = sText_TargetIsHurtBySaltCure,

View file

@ -9151,6 +9151,7 @@ static void Cmd_various(void)
case ABILITY_SCHOOLING: case ABILITY_COMATOSE:
case ABILITY_SHIELDS_DOWN: case ABILITY_DISGUISE:
case ABILITY_RKS_SYSTEM: case ABILITY_TRACE:
case ABILITY_ZERO_TO_HERO:
break;
default:
gBattleStruct->tracedAbility[gBattlerAbility] = gBattleMons[battler].ability; // re-using the variable for trace

View file

@ -113,6 +113,7 @@ static const u16 sSkillSwapBannedAbilities[] =
ABILITY_ICE_FACE,
ABILITY_HUNGER_SWITCH,
ABILITY_GULP_MISSILE,
ABILITY_ZERO_TO_HERO,
};
static const u16 sRolePlayBannedAbilities[] =
@ -138,6 +139,7 @@ static const u16 sRolePlayBannedAbilities[] =
ABILITY_ICE_FACE,
ABILITY_HUNGER_SWITCH,
ABILITY_GULP_MISSILE,
ABILITY_ZERO_TO_HERO,
};
static const u16 sRolePlayBannedAttackerAbilities[] =
@ -154,6 +156,7 @@ static const u16 sRolePlayBannedAttackerAbilities[] =
ABILITY_POWER_CONSTRUCT,
ABILITY_ICE_FACE,
ABILITY_GULP_MISSILE,
ABILITY_ZERO_TO_HERO,
};
static const u16 sWorrySeedBannedAbilities[] =
@ -170,6 +173,7 @@ static const u16 sWorrySeedBannedAbilities[] =
ABILITY_TRUANT,
ABILITY_ICE_FACE,
ABILITY_GULP_MISSILE,
ABILITY_ZERO_TO_HERO,
};
static const u16 sGastroAcidBannedAbilities[] =
@ -188,6 +192,7 @@ static const u16 sGastroAcidBannedAbilities[] =
ABILITY_SHIELDS_DOWN,
ABILITY_STANCE_CHANGE,
ABILITY_ZEN_MODE,
ABILITY_ZERO_TO_HERO,
};
static const u16 sEntrainmentBannedAttackerAbilities[] =
@ -206,6 +211,7 @@ static const u16 sEntrainmentBannedAttackerAbilities[] =
ABILITY_ICE_FACE,
ABILITY_HUNGER_SWITCH,
ABILITY_GULP_MISSILE,
ABILITY_ZERO_TO_HERO,
};
static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
@ -221,6 +227,7 @@ static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
ABILITY_BATTLE_BOND,
ABILITY_ICE_FACE,
ABILITY_GULP_MISSILE,
ABILITY_ZERO_TO_HERO,
};
static u8 CalcBeatUpPower(void)
@ -994,6 +1001,7 @@ static const u8 sAbilitiesNotTraced[ABILITIES_COUNT] =
[ABILITY_STANCE_CHANGE] = 1,
[ABILITY_TRACE] = 1,
[ABILITY_ZEN_MODE] = 1,
[ABILITY_ZERO_TO_HERO] = 1,
};
static const u8 sHoldEffectToType[][2] =
@ -4695,6 +4703,17 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
effect++;
}
break;
case ABILITY_ZERO_TO_HERO:
if (!gSpecialStatuses[battler].switchInAbilityDone
&& gBattleMons[battler].species == SPECIES_PALAFIN_HERO
&& !gBattleStruct->transformZeroToHero[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)])
{
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
gBattleStruct->transformZeroToHero[gBattlerPartyIndexes[battler]][GetBattlerSide(battler)] = TRUE;
BattleScriptPushCursorAndCallback(BattleScript_ZeroToHeroActivates);
effect++;
}
break;
}
break;
case ABILITYEFFECT_ENDTURN: // 1
@ -6078,6 +6097,7 @@ bool32 IsNeutralizingGasBannedAbility(u32 ability)
case ABILITY_ICE_FACE:
case ABILITY_AS_ONE_ICE_RIDER:
case ABILITY_AS_ONE_SHADOW_RIDER:
case ABILITY_ZERO_TO_HERO:
return TRUE;
default:
return FALSE;

View file

@ -355,6 +355,8 @@ const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] =
[SPECIES_ENAMORUS_THERIAN] = sEnamorusFormChangeTable,
#endif
#if P_GEN_9_POKEMON == TRUE
[SPECIES_PALAFIN_ZERO] = sPalafinZeroFormChangeTable,
[SPECIES_PALAFIN_HERO] = sPalafinZeroFormChangeTable,
[SPECIES_OGERPON_TEAL_MASK] = sOgerponFormChangeTable,
[SPECIES_OGERPON_WELLSPRING_MASK] = sOgerponFormChangeTable,
[SPECIES_OGERPON_HEARTHFLAME_MASK] = sOgerponFormChangeTable,

View file

@ -800,6 +800,12 @@ static const struct FormChange sUrshifuRapidStrikeFormChangeTable[] =
{FORM_CHANGE_TERMINATOR},
};
static const struct FormChange sPalafinZeroFormChangeTable[] =
{
{FORM_CHANGE_BATTLE_SWITCH, SPECIES_PALAFIN_HERO},
{FORM_CHANGE_TERMINATOR},
};
#endif
#undef WHEN_LEARNED

View file

@ -0,0 +1,140 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(P_GEN_9_POKEMON == TRUE);
}
SINGLE_BATTLE_TEST("Zero to Hero transforms Palafin when it switches out")
{
GIVEN {
PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { SWITCH(player, 1); }
TURN { SWITCH(player, 0); }
} SCENE {
MESSAGE("Palafin, that's enough! Come back!");
MESSAGE("Go! Wobbuffet!");
MESSAGE("Wobbuffet, that's enough! Come back!");
MESSAGE("Go! Palafin!");
ABILITY_POPUP(player, ABILITY_ZERO_TO_HERO);
MESSAGE("Palafin underwent a heroic transformation!");
} THEN { EXPECT_EQ(player->species, SPECIES_PALAFIN_HERO); }
}
SINGLE_BATTLE_TEST("Zero to Hero can't be surpressed by Neutralizing Gas")
{
GIVEN {
PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_KOFFING) { Ability(ABILITY_NEUTRALIZING_GAS); }
} WHEN {
TURN { SWITCH(player, 1); }
TURN { SWITCH(player, 0); }
} SCENE {
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
ABILITY_POPUP(player, ABILITY_ZERO_TO_HERO);
MESSAGE("Palafin underwent a heroic transformation!");
} THEN { EXPECT_EQ(player->species, SPECIES_PALAFIN_HERO); }
}
SINGLE_BATTLE_TEST("Zero to Hero transforms both player and opponent")
{
GIVEN {
PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { SWITCH(player, 1); SWITCH(opponent, 1); }
TURN { SWITCH(player, 0); SWITCH(opponent, 0); }
} SCENE {
ABILITY_POPUP(player, ABILITY_ZERO_TO_HERO);
MESSAGE("Palafin underwent a heroic transformation!");
ABILITY_POPUP(opponent, ABILITY_ZERO_TO_HERO);
MESSAGE("Foe Palafin underwent a heroic transformation!");
} THEN {
EXPECT_EQ(player->species, SPECIES_PALAFIN_HERO);
EXPECT_EQ(opponent->species, SPECIES_PALAFIN_HERO);
}
}
SINGLE_BATTLE_TEST("Zero to Hero will activate if a switch move is used")
{
GIVEN {
ASSUME(gBattleMoves[MOVE_FLIP_TURN].effect == EFFECT_HIT_ESCAPE);
PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, MOVE_FLIP_TURN); SEND_OUT(player, 1); }
TURN { SWITCH(player, 0); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLIP_TURN, player);
ABILITY_POPUP(player, ABILITY_ZERO_TO_HERO);
MESSAGE("Palafin underwent a heroic transformation!");
} THEN { EXPECT_EQ(player->species, SPECIES_PALAFIN_HERO); }
}
SINGLE_BATTLE_TEST("Gastro Acid, Worry Seed, and Simple Beam fail if the target has the Ability Zero to Hero")
{
u16 move;
PARAMETRIZE { move = MOVE_GASTRO_ACID; }
PARAMETRIZE { move = MOVE_WORRY_SEED; }
PARAMETRIZE { move = MOVE_SIMPLE_BEAM; }
GIVEN {
ASSUME(gBattleMoves[MOVE_GASTRO_ACID].effect == EFFECT_GASTRO_ACID);
ASSUME(gBattleMoves[MOVE_WORRY_SEED].effect == EFFECT_WORRY_SEED);
ASSUME(gBattleMoves[MOVE_SIMPLE_BEAM].effect == EFFECT_SIMPLE_BEAM);
PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, move); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, move, player);
MESSAGE("But it failed!");
}
}
SINGLE_BATTLE_TEST("Role Play, Skill Swap, and Entrainment fail if either Pokémon has Zero to Hero")
{
u16 move;
PARAMETRIZE { move = MOVE_ROLE_PLAY; }
PARAMETRIZE { move = MOVE_SKILL_SWAP; }
PARAMETRIZE { move = MOVE_ENTRAINMENT; }
GIVEN {
ASSUME(gBattleMoves[MOVE_ROLE_PLAY].effect == EFFECT_ROLE_PLAY);
ASSUME(gBattleMoves[MOVE_SKILL_SWAP].effect == EFFECT_SKILL_SWAP);
ASSUME(gBattleMoves[MOVE_ENTRAINMENT].effect == EFFECT_ENTRAINMENT);
PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(player, move); }
} SCENE {
NOT ANIMATION(ANIM_TYPE_MOVE, move, player);
MESSAGE("But it failed!");
}
}
// Write Trace test and move this one to that file (including every other ability that can't be copied)
SINGLE_BATTLE_TEST("Zero to Hero cannot be copied by Trace")
{
GIVEN {
PLAYER(SPECIES_PALAFIN_ZERO) { Ability(ABILITY_ZERO_TO_HERO); }
OPPONENT(SPECIES_RALTS) { Ability(ABILITY_TRACE); }
} WHEN {
TURN {}
} SCENE {
NONE_OF {
ABILITY_POPUP(opponent, ABILITY_TRACE);
MESSAGE("Foe Ralts Traced Palafin's Zero to Hero!");
}
}
}