mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-26 11:44:17 +01:00
Fix Stamina/Wind Power/Electromorphosis/Rattled issues with targets (#3143)
This commit is contained in:
commit
87050d8c08
@ -1053,8 +1053,9 @@
|
|||||||
.byte 0xca
|
.byte 0xca
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro setcharge
|
.macro setcharge battler:req
|
||||||
.byte 0xcb
|
.byte 0xcb
|
||||||
|
.byte \battler
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro callterrainattack
|
.macro callterrainattack
|
||||||
|
@ -3079,12 +3079,9 @@ BattleScript_TryTailwindAbilitiesLoop_WindRider:
|
|||||||
|
|
||||||
BattleScript_TryTailwindAbilitiesLoop_WindPower:
|
BattleScript_TryTailwindAbilitiesLoop_WindPower:
|
||||||
call BattleScript_AbilityPopUp
|
call BattleScript_AbilityPopUp
|
||||||
copybyte sSAVED_BATTLER, gBattlerAttacker
|
setcharge BS_TARGET
|
||||||
copybyte gBattlerAttacker, gBattlerTarget
|
|
||||||
setcharge
|
|
||||||
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
|
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
|
||||||
waitmessage B_WAIT_TIME_LONG
|
waitmessage B_WAIT_TIME_LONG
|
||||||
copybyte gBattlerAttacker, sSAVED_BATTLER
|
|
||||||
goto BattleScript_TryTailwindAbilitiesLoop_Increment
|
goto BattleScript_TryTailwindAbilitiesLoop_Increment
|
||||||
|
|
||||||
BattleScript_EffectMircleEye:
|
BattleScript_EffectMircleEye:
|
||||||
@ -5872,7 +5869,7 @@ BattleScript_EffectCharge::
|
|||||||
attackcanceler
|
attackcanceler
|
||||||
attackstring
|
attackstring
|
||||||
ppreduce
|
ppreduce
|
||||||
setcharge
|
setcharge BS_ATTACKER
|
||||||
attackanimation
|
attackanimation
|
||||||
waitanimation
|
waitanimation
|
||||||
.if B_CHARGE_SPDEF_RAISE >= GEN_5
|
.if B_CHARGE_SPDEF_RAISE >= GEN_5
|
||||||
@ -6937,27 +6934,6 @@ BattleScript_TailwindEnds::
|
|||||||
waitmessage B_WAIT_TIME_LONG
|
waitmessage B_WAIT_TIME_LONG
|
||||||
end2
|
end2
|
||||||
|
|
||||||
BattleScript_WindPowerActivatesEnd2::
|
|
||||||
setbyte gBattlerAttacker, 0
|
|
||||||
BattleScript_WindPowerLoop:
|
|
||||||
printstring STRINGID_EMPTYSTRING3
|
|
||||||
jumpifability BS_ATTACKER, ABILITY_WIND_POWER, BattleScript_WindPowerLoop_Cont
|
|
||||||
goto BattleScript_WindPowerIncrement
|
|
||||||
BattleScript_WindPowerLoop_Cont:
|
|
||||||
jumpifstatus3 BS_ATTACKER, STATUS3_CHARGED_UP, BattleScript_WindPowerIncrement
|
|
||||||
goto BattleScript_WindPower_Activate
|
|
||||||
BattleScript_WindPower_Activate:
|
|
||||||
call BattleScript_AbilityPopUp
|
|
||||||
setcharge
|
|
||||||
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
|
|
||||||
waitmessage B_WAIT_TIME_LONG
|
|
||||||
BattleScript_WindPowerIncrement:
|
|
||||||
addbyte gBattlerAttacker, 1
|
|
||||||
jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_WindPowerLoop
|
|
||||||
BattleScript_WindPowerEnd:
|
|
||||||
destroyabilitypopup
|
|
||||||
end2
|
|
||||||
|
|
||||||
BattleScript_TrickRoomEnds::
|
BattleScript_TrickRoomEnds::
|
||||||
printstring STRINGID_TRICKROOMENDS
|
printstring STRINGID_TRICKROOMENDS
|
||||||
waitmessage B_WAIT_TIME_LONG
|
waitmessage B_WAIT_TIME_LONG
|
||||||
@ -7419,11 +7395,8 @@ BattleScript_AngerShellRet:
|
|||||||
return
|
return
|
||||||
|
|
||||||
BattleScript_WindPowerActivates::
|
BattleScript_WindPowerActivates::
|
||||||
.if B_CHECK_IF_CHARGED_UP == TRUE
|
|
||||||
jumpifstatus3 BS_ATTACKER, STATUS3_CHARGED_UP, BattleScript_WindPowerActivates_Ret
|
|
||||||
.endif
|
|
||||||
call BattleScript_AbilityPopUp
|
call BattleScript_AbilityPopUp
|
||||||
setcharge
|
setcharge BS_TARGET
|
||||||
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
|
printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER
|
||||||
waitmessage B_WAIT_TIME_LONG
|
waitmessage B_WAIT_TIME_LONG
|
||||||
BattleScript_WindPowerActivates_Ret:
|
BattleScript_WindPowerActivates_Ret:
|
||||||
@ -10449,6 +10422,7 @@ BattleScript_SymbiosisActivates::
|
|||||||
return
|
return
|
||||||
|
|
||||||
BattleScript_TargetAbilityStatRaiseRet::
|
BattleScript_TargetAbilityStatRaiseRet::
|
||||||
|
copybyte sSAVED_BATTLER, gBattlerAttacker
|
||||||
copybyte gBattlerAbility, gEffectBattler
|
copybyte gBattlerAbility, gEffectBattler
|
||||||
copybyte gBattlerAttacker, gBattlerTarget
|
copybyte gBattlerAttacker, gBattlerTarget
|
||||||
call BattleScript_AbilityPopUp
|
call BattleScript_AbilityPopUp
|
||||||
@ -10456,6 +10430,7 @@ BattleScript_TargetAbilityStatRaiseRet::
|
|||||||
setgraphicalstatchangevalues
|
setgraphicalstatchangevalues
|
||||||
call BattleScript_StatUp
|
call BattleScript_StatUp
|
||||||
BattleScript_TargetAbilityStatRaiseRet_End:
|
BattleScript_TargetAbilityStatRaiseRet_End:
|
||||||
|
copybyte gBattlerAttacker, sSAVED_BATTLER
|
||||||
return
|
return
|
||||||
|
|
||||||
BattleScript_PokemonCantUseTheMove::
|
BattleScript_PokemonCantUseTheMove::
|
||||||
|
@ -118,7 +118,6 @@
|
|||||||
#define B_PLUS_MINUS_INTERACTION GEN_LATEST // In Gen5+, Plus and Minus can be activated with themselves and the opposite ability. Before, only the opposing ability could activate it.
|
#define B_PLUS_MINUS_INTERACTION GEN_LATEST // In Gen5+, Plus and Minus can be activated with themselves and the opposite ability. Before, only the opposing ability could activate it.
|
||||||
#define B_WEATHER_FORMS GEN_LATEST // In Gen5+, Castform and Cherrim revert to their base form upon losing their respective ability. Cherrim needs Flower Gift to swap forms.
|
#define B_WEATHER_FORMS GEN_LATEST // In Gen5+, Castform and Cherrim revert to their base form upon losing their respective ability. Cherrim needs Flower Gift to swap forms.
|
||||||
#define B_SYMBIOSIS_GEMS GEN_LATEST // In Gen7+, Symbiosis passes an item after a gem-boosted attack. Previously, items are passed before the gem-boosted attack hits, making the item effect apply.
|
#define B_SYMBIOSIS_GEMS GEN_LATEST // In Gen7+, Symbiosis passes an item after a gem-boosted attack. Previously, items are passed before the gem-boosted attack hits, making the item effect apply.
|
||||||
#define B_CHECK_IF_CHARGED_UP TRUE // If set to TRUE, certain abilities such as Electromorphosis WILL check if the STATUS3_CHARGED_UP status flag is applied.
|
|
||||||
#define B_ABSORBING_ABILITY_STRING GEN_LATEST // In Gen5+, the abilities that absorb moves of a certain type use a generic string for stat increases and decreases.
|
#define B_ABSORBING_ABILITY_STRING GEN_LATEST // In Gen5+, the abilities that absorb moves of a certain type use a generic string for stat increases and decreases.
|
||||||
#define B_LEAF_GUARD_PREVENTS_REST GEN_LATEST // In Gen5+, Leaf Guard prevents the use of Rest in harsh sunlight.
|
#define B_LEAF_GUARD_PREVENTS_REST GEN_LATEST // In Gen5+, Leaf Guard prevents the use of Rest in harsh sunlight.
|
||||||
#define B_SNOW_WARNING GEN_LATEST // In Gen9+, Snow Warning will summon snow instead of hail.
|
#define B_SNOW_WARNING GEN_LATEST // In Gen9+, Snow Warning will summon snow instead of hail.
|
||||||
|
@ -783,7 +783,7 @@ static const u8 sText_AttackerMeltedTheIce[] = _("{B_ATK_NAME_WITH_PREFIX} melte
|
|||||||
static const u8 sText_TargetToughedItOut[] = _("{B_DEF_NAME_WITH_PREFIX} toughed it out\nto show you its best side!");
|
static const u8 sText_TargetToughedItOut[] = _("{B_DEF_NAME_WITH_PREFIX} toughed it out\nto show you its best side!");
|
||||||
static const u8 sText_AttackerLostElectricType[] = _("{B_ATK_NAME_WITH_PREFIX} used up all\nof its electricity!");
|
static const u8 sText_AttackerLostElectricType[] = _("{B_ATK_NAME_WITH_PREFIX} used up all\nof its electricity!");
|
||||||
static const u8 sText_AttackerSwitchedStatWithTarget[] = _("{B_ATK_NAME_WITH_PREFIX} switched {B_BUFF1}\nwith its target!");
|
static const u8 sText_AttackerSwitchedStatWithTarget[] = _("{B_ATK_NAME_WITH_PREFIX} switched {B_BUFF1}\nwith its target!");
|
||||||
static const u8 sText_BeingHitChargedPkmnWithPower[] = _("Being hit by {B_CURRENT_MOVE}\ncharged {B_ATK_NAME_WITH_PREFIX} with power!");
|
static const u8 sText_BeingHitChargedPkmnWithPower[] = _("Being hit by {B_CURRENT_MOVE}\ncharged {B_DEF_NAME_WITH_PREFIX} with power!");
|
||||||
static const u8 sText_SunlightActivatedAbility[] = _("The harsh sunlight activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!");
|
static const u8 sText_SunlightActivatedAbility[] = _("The harsh sunlight activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!");
|
||||||
static const u8 sText_StatWasHeightened[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_BUFF1} was heightened!");
|
static const u8 sText_StatWasHeightened[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_BUFF1} was heightened!");
|
||||||
static const u8 sText_ElectricTerrainActivatedAbility[] = _("The Electric Terrain activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!");
|
static const u8 sText_ElectricTerrainActivatedAbility[] = _("The Electric Terrain activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!");
|
||||||
|
@ -14255,10 +14255,11 @@ static void Cmd_setforcedtarget(void)
|
|||||||
|
|
||||||
static void Cmd_setcharge(void)
|
static void Cmd_setcharge(void)
|
||||||
{
|
{
|
||||||
CMD_ARGS();
|
CMD_ARGS(u8 battler);
|
||||||
|
|
||||||
gStatuses3[gBattlerAttacker] |= STATUS3_CHARGED_UP;
|
u8 battler = GetBattlerForBattleScript(cmd->battler);
|
||||||
gDisableStructs[gBattlerAttacker].chargeTimer = 2;
|
gStatuses3[battler] |= STATUS3_CHARGED_UP;
|
||||||
|
gDisableStructs[battler].chargeTimer = 2;
|
||||||
gBattlescriptCurrInstr++;
|
gBattlescriptCurrInstr++;
|
||||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||||
}
|
}
|
||||||
|
@ -5688,7 +5688,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
|||||||
&& TARGET_TURN_DAMAGED
|
&& TARGET_TURN_DAMAGED
|
||||||
&& IsBattlerAlive(gBattlerTarget))
|
&& IsBattlerAlive(gBattlerTarget))
|
||||||
{
|
{
|
||||||
gBattlerAttacker = gBattlerTarget;
|
|
||||||
BattleScriptPushCursor();
|
BattleScriptPushCursor();
|
||||||
gBattlescriptCurrInstr = BattleScript_WindPowerActivates;
|
gBattlescriptCurrInstr = BattleScript_WindPowerActivates;
|
||||||
effect++;
|
effect++;
|
||||||
|
56
test/ability_electromorphosis.c
Normal file
56
test/ability_electromorphosis.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "global.h"
|
||||||
|
#include "test_battle.h"
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Electromorphosis sets up Charge when hit by any move")
|
||||||
|
{
|
||||||
|
s16 dmgBefore, dmgAfter;
|
||||||
|
u16 move;
|
||||||
|
|
||||||
|
PARAMETRIZE {move = MOVE_TACKLE; }
|
||||||
|
PARAMETRIZE {move = MOVE_GUST; }
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gBattleMoves[MOVE_TACKLE].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_GUST].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_GUST].split == SPLIT_SPECIAL);
|
||||||
|
ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL);
|
||||||
|
ASSUME(gBattleMoves[MOVE_THUNDERBOLT].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC);
|
||||||
|
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_ELECTROMORPHOSIS); Speed(10); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed.
|
||||||
|
}
|
||||||
|
WHEN {
|
||||||
|
TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); }
|
||||||
|
TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
|
||||||
|
HP_BAR(opponent, captureDamage: &dmgBefore);
|
||||||
|
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
|
||||||
|
HP_BAR(player);
|
||||||
|
ABILITY_POPUP(player, ABILITY_ELECTROMORPHOSIS);
|
||||||
|
if (move == MOVE_TACKLE) {
|
||||||
|
MESSAGE("Being hit by Tackle charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MESSAGE("Being hit by Gust charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
|
||||||
|
HP_BAR(opponent, captureDamage: &dmgAfter);
|
||||||
|
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
|
||||||
|
HP_BAR(player);
|
||||||
|
ABILITY_POPUP(player, ABILITY_ELECTROMORPHOSIS);
|
||||||
|
if (move == MOVE_TACKLE) {
|
||||||
|
MESSAGE("Being hit by Tackle charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MESSAGE("Being hit by Gust charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
THEN {
|
||||||
|
EXPECT_MUL_EQ(dmgBefore, Q_4_12(2.0), dmgAfter);
|
||||||
|
}
|
||||||
|
}
|
93
test/ability_rattled.c
Normal file
93
test/ability_rattled.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#include "global.h"
|
||||||
|
#include "test_battle.h"
|
||||||
|
|
||||||
|
ASSUMPTIONS
|
||||||
|
{
|
||||||
|
ASSUME(gBattleMoves[MOVE_FURY_CUTTER].type == TYPE_BUG);
|
||||||
|
ASSUME(gBattleMoves[MOVE_FURY_CUTTER].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_FEINT_ATTACK].type == TYPE_DARK);
|
||||||
|
ASSUME(gBattleMoves[MOVE_FEINT_ATTACK].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_SHADOW_PUNCH].type == TYPE_GHOST);
|
||||||
|
ASSUME(gBattleMoves[MOVE_SHADOW_PUNCH].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_TACKLE].type == TYPE_NORMAL);
|
||||||
|
ASSUME(gBattleMoves[MOVE_TACKLE].power != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when hit by Bug, Dark or Ghost type move")
|
||||||
|
{
|
||||||
|
u16 move;
|
||||||
|
PARAMETRIZE { move = MOVE_FURY_CUTTER; }
|
||||||
|
PARAMETRIZE { move = MOVE_FEINT_ATTACK; }
|
||||||
|
PARAMETRIZE { move = MOVE_SHADOW_PUNCH; }
|
||||||
|
PARAMETRIZE { move = MOVE_TACKLE; }
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) {Speed(42) ;}
|
||||||
|
OPPONENT(SPECIES_SUDOWOODO) {Speed(40); Ability(ABILITY_RATTLED);}
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(player, move); }
|
||||||
|
TURN { MOVE(player, move); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
if (move != MOVE_TACKLE) {
|
||||||
|
ABILITY_POPUP(opponent, ABILITY_RATTLED);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||||
|
MESSAGE("Foe Sudowoodo's Speed rose!");
|
||||||
|
}
|
||||||
|
MESSAGE("Foe Sudowoodo used Celebrate!");
|
||||||
|
// Sudowoodo is now faster
|
||||||
|
if (move != MOVE_TACKLE){
|
||||||
|
MESSAGE("Foe Sudowoodo used Celebrate!");
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
ABILITY_POPUP(opponent, ABILITY_RATTLED);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||||
|
MESSAGE("Foe Sudowoodo's Speed rose!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
MESSAGE("Foe Sudowoodo used Celebrate!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when affected by Intimidate")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(B_UPDATED_INTIMIDATE >= GEN_8);
|
||||||
|
PLAYER(SPECIES_GYARADOS) {Ability(ABILITY_INTIMIDATE); }
|
||||||
|
OPPONENT(SPECIES_SUDOWOODO) {Ability(ABILITY_RATTLED); }
|
||||||
|
} WHEN {
|
||||||
|
TURN {}
|
||||||
|
} SCENE {
|
||||||
|
ABILITY_POPUP(player, ABILITY_INTIMIDATE);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||||
|
MESSAGE("Gyarados's Intimidate cuts Foe Sudowoodo's attack!");
|
||||||
|
ABILITY_POPUP(opponent, ABILITY_RATTLED);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||||
|
MESSAGE("Foe Sudowoodo's Speed rose!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Rattled triggers correctly when hit by U-Turn") // Specific test here, because of #3124
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gBattleMoves[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE);
|
||||||
|
ASSUME(gBattleMoves[MOVE_U_TURN].type == TYPE_BUG);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WYNAUT);
|
||||||
|
OPPONENT(SPECIES_SUDOWOODO) {Ability(ABILITY_RATTLED); }
|
||||||
|
OPPONENT(SPECIES_SUDOWOODO);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(player, MOVE_U_TURN); SEND_OUT(player, 1); }
|
||||||
|
} SCENE {
|
||||||
|
MESSAGE("Wobbuffet used U-turn!");
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
ABILITY_POPUP(opponent, ABILITY_RATTLED);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||||
|
MESSAGE("Foe Sudowoodo's Speed rose!");
|
||||||
|
MESSAGE("Go! Wynaut!");
|
||||||
|
}
|
||||||
|
}
|
89
test/ability_stamina.c
Normal file
89
test/ability_stamina.c
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include "global.h"
|
||||||
|
#include "test_battle.h"
|
||||||
|
|
||||||
|
#define STAMINA_STAT_RAISE(target, msg) \
|
||||||
|
{ \
|
||||||
|
ABILITY_POPUP(target, ABILITY_STAMINA); \
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, target); \
|
||||||
|
MESSAGE(msg); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STAMINA_HIT(attacker, target, move, msg, dmgVar) \
|
||||||
|
{ \
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, attacker); \
|
||||||
|
HP_BAR(target, captureDamage: &dmgVar); \
|
||||||
|
STAMINA_STAT_RAISE(target, msg); \
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Stamina raises Defense by 1 when hit by a move")
|
||||||
|
{
|
||||||
|
s16 turnOneHit, turnTwoHit;
|
||||||
|
u16 move;
|
||||||
|
|
||||||
|
PARAMETRIZE {move = MOVE_TACKLE; }
|
||||||
|
PARAMETRIZE {move = MOVE_GUST; }
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gBattleMoves[MOVE_TACKLE].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_GUST].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_GUST].split == SPLIT_SPECIAL);
|
||||||
|
ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_STAMINA); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, move); }
|
||||||
|
TURN { MOVE(opponent, move); }
|
||||||
|
} SCENE {
|
||||||
|
STAMINA_HIT(opponent, player, move, "Wobbuffet's Defense rose!", turnOneHit);
|
||||||
|
STAMINA_HIT(opponent, player, move, "Wobbuffet's Defense rose!", turnTwoHit);
|
||||||
|
}
|
||||||
|
THEN {
|
||||||
|
if (move == MOVE_TACKLE) {
|
||||||
|
EXPECT_MUL_EQ(turnTwoHit, Q_4_12(1.5), turnOneHit);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EXPECT_EQ(turnTwoHit, turnOneHit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Stamina activates correctly for every battler with the ability when hit by a multi target move")
|
||||||
|
{
|
||||||
|
u16 abilityLeft, abilityRight;
|
||||||
|
|
||||||
|
PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_STAMINA; }
|
||||||
|
PARAMETRIZE {abilityLeft = ABILITY_STAMINA, abilityRight = ABILITY_NONE; }
|
||||||
|
PARAMETRIZE {abilityLeft = ABILITY_STAMINA, abilityRight = ABILITY_STAMINA; }
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gBattleMoves[MOVE_EARTHQUAKE].target == MOVE_TARGET_FOES_AND_ALLY);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(abilityLeft); Speed(10); }
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(abilityRight); Speed(5); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) {Speed(20); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) {Speed(15); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentLeft, MOVE_EARTHQUAKE);}
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponentLeft);
|
||||||
|
|
||||||
|
HP_BAR(playerLeft);
|
||||||
|
if (abilityLeft == ABILITY_STAMINA) {
|
||||||
|
STAMINA_STAT_RAISE(playerLeft, "Wobbuffet's Defense rose!");
|
||||||
|
}
|
||||||
|
NOT HP_BAR(opponentLeft); // We need to check the attacker itself does NOT get damaged. There was an issue when the targets would get overwritten by the Stamina's stat raise.
|
||||||
|
|
||||||
|
HP_BAR(playerRight);
|
||||||
|
if (abilityRight == ABILITY_STAMINA) {
|
||||||
|
STAMINA_STAT_RAISE(playerRight, "Wobbuffet's Defense rose!");
|
||||||
|
}
|
||||||
|
NOT HP_BAR(opponentLeft); // We need to check the attacker itself does NOT get damaged. There was an issue when the targets would get overwritten by the Stamina's stat raise.
|
||||||
|
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
}
|
||||||
|
THEN {
|
||||||
|
EXPECT_NE(playerLeft->hp, playerLeft->maxHP);
|
||||||
|
EXPECT_NE(playerRight->hp, playerRight->maxHP);
|
||||||
|
EXPECT_NE(opponentRight->hp, opponentRight->maxHP);
|
||||||
|
EXPECT_EQ(opponentLeft->hp, opponentLeft->maxHP);
|
||||||
|
}
|
||||||
|
}
|
221
test/ability_wind_power.c
Normal file
221
test/ability_wind_power.c
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
#include "global.h"
|
||||||
|
#include "test_battle.h"
|
||||||
|
|
||||||
|
ASSUMPTIONS
|
||||||
|
{
|
||||||
|
ASSUME(gBattleMoves[MOVE_THUNDERBOLT].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC);
|
||||||
|
ASSUME(gBattleMoves[MOVE_TACKLE].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_AIR_CUTTER].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_AIR_CUTTER].target == MOVE_TARGET_BOTH);
|
||||||
|
ASSUME(gBattleMoves[MOVE_AIR_CUTTER].flags & FLAG_WIND_MOVE);
|
||||||
|
ASSUME(gBattleMoves[MOVE_PETAL_BLIZZARD].power != 0);
|
||||||
|
ASSUME(gBattleMoves[MOVE_PETAL_BLIZZARD].target == MOVE_TARGET_FOES_AND_ALLY);
|
||||||
|
ASSUME(gBattleMoves[MOVE_PETAL_BLIZZARD].flags & FLAG_WIND_MOVE);
|
||||||
|
ASSUME(!(gBattleMoves[MOVE_TACKLE].flags & FLAG_WIND_MOVE));
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Wind Power sets up Charge for player when hit by a wind move")
|
||||||
|
{
|
||||||
|
s16 dmgBefore, dmgAfter;
|
||||||
|
u16 move;
|
||||||
|
|
||||||
|
PARAMETRIZE {move = MOVE_TACKLE; }
|
||||||
|
PARAMETRIZE {move = MOVE_AIR_CUTTER; }
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(10); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed.
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); }
|
||||||
|
TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
|
||||||
|
HP_BAR(opponent, captureDamage: &dmgBefore);
|
||||||
|
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
|
||||||
|
HP_BAR(player);
|
||||||
|
if (move == MOVE_AIR_CUTTER) {
|
||||||
|
ABILITY_POPUP(player, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by Air Cutter charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
|
||||||
|
HP_BAR(opponent, captureDamage: &dmgAfter);
|
||||||
|
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, opponent);
|
||||||
|
HP_BAR(player);
|
||||||
|
if (move == MOVE_AIR_CUTTER) {
|
||||||
|
ABILITY_POPUP(player, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by Air Cutter charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
THEN {
|
||||||
|
if (move == MOVE_AIR_CUTTER) {
|
||||||
|
EXPECT_MUL_EQ(dmgBefore, Q_4_12(2.0), dmgAfter);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EXPECT_EQ(dmgAfter, dmgBefore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Wind Power sets up Charge for opponent when hit by a wind move")
|
||||||
|
{
|
||||||
|
s16 dmgBefore, dmgAfter;
|
||||||
|
u16 move;
|
||||||
|
|
||||||
|
PARAMETRIZE {move = MOVE_TACKLE; }
|
||||||
|
PARAMETRIZE {move = MOVE_AIR_CUTTER; }
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed.
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(10); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_THUNDERBOLT), MOVE(player, move); }
|
||||||
|
TURN { MOVE(opponent, MOVE_THUNDERBOLT), MOVE(player, move); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, opponent);
|
||||||
|
HP_BAR(player, captureDamage: &dmgBefore);
|
||||||
|
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
if (move == MOVE_AIR_CUTTER) {
|
||||||
|
ABILITY_POPUP(opponent, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by Air Cutter charged Foe Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, opponent);
|
||||||
|
HP_BAR(player, captureDamage: &dmgAfter);
|
||||||
|
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
||||||
|
HP_BAR(opponent);
|
||||||
|
if (move == MOVE_AIR_CUTTER) {
|
||||||
|
ABILITY_POPUP(opponent, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by Air Cutter charged Foe Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
THEN {
|
||||||
|
if (move == MOVE_AIR_CUTTER) {
|
||||||
|
EXPECT_MUL_EQ(dmgBefore, Q_4_12(2.0), dmgAfter);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EXPECT_EQ(dmgAfter, dmgBefore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ability when hit by a 2/3 target move")
|
||||||
|
{
|
||||||
|
u16 move, abilityLeft, abilityRight;
|
||||||
|
|
||||||
|
PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_WIND_POWER;}
|
||||||
|
PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_NONE; }
|
||||||
|
PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_WIND_POWER; }
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(abilityLeft); Speed(10); }
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(abilityRight); Speed(5); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(20); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(15); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentLeft, MOVE_AIR_CUTTER); MOVE(opponentRight, MOVE_AIR_CUTTER);}
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_AIR_CUTTER, opponentLeft);
|
||||||
|
|
||||||
|
HP_BAR(playerLeft);
|
||||||
|
if (abilityLeft == ABILITY_WIND_POWER) {
|
||||||
|
ABILITY_POPUP(playerLeft, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by Air Cutter charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
HP_BAR(playerRight);
|
||||||
|
if (abilityRight == ABILITY_WIND_POWER) {
|
||||||
|
ABILITY_POPUP(playerRight, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by Air Cutter charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
NOT HP_BAR(opponentLeft);
|
||||||
|
NOT HP_BAR(opponentRight);
|
||||||
|
}
|
||||||
|
THEN {
|
||||||
|
EXPECT_NE(playerLeft->hp, playerLeft->maxHP);
|
||||||
|
EXPECT_NE(playerRight->hp, playerRight->maxHP);
|
||||||
|
EXPECT_EQ(opponentRight->hp, opponentRight->maxHP);
|
||||||
|
EXPECT_EQ(opponentLeft->hp, opponentLeft->maxHP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ability when hit by a 3 target move")
|
||||||
|
{
|
||||||
|
u16 abilityLeft, abilityRight;
|
||||||
|
|
||||||
|
PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_WIND_POWER; }
|
||||||
|
PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_NONE; }
|
||||||
|
PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_WIND_POWER; }
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(abilityLeft); Speed(10); }
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(abilityRight); Speed(5); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(20); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(15); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponentLeft, MOVE_PETAL_BLIZZARD);}
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_BLIZZARD, opponentLeft);
|
||||||
|
|
||||||
|
HP_BAR(playerLeft);
|
||||||
|
if (abilityLeft == ABILITY_WIND_POWER) {
|
||||||
|
ABILITY_POPUP(playerLeft, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by PetalBlizzrd charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
HP_BAR(playerRight);
|
||||||
|
if (abilityRight == ABILITY_WIND_POWER) {
|
||||||
|
ABILITY_POPUP(playerRight, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by PetalBlizzrd charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
HP_BAR(opponentRight);
|
||||||
|
NOT HP_BAR(opponentLeft);
|
||||||
|
}
|
||||||
|
THEN {
|
||||||
|
EXPECT_NE(playerLeft->hp, playerLeft->maxHP);
|
||||||
|
EXPECT_NE(playerRight->hp, playerRight->maxHP);
|
||||||
|
EXPECT_NE(opponentRight->hp, opponentRight->maxHP);
|
||||||
|
EXPECT_EQ(opponentLeft->hp, opponentLeft->maxHP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_BATTLE_TEST("Wind Power activates correctly when Tailwind is used")
|
||||||
|
{
|
||||||
|
bool8 opponentSide;
|
||||||
|
|
||||||
|
PARAMETRIZE {opponentSide = TRUE;}
|
||||||
|
PARAMETRIZE {opponentSide = FALSE;}
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
ASSUME(gBattleMoves[MOVE_TAILWIND].effect == EFFECT_TAILWIND);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(10); }
|
||||||
|
PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(5); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(20); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(15); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE((opponentSide == TRUE) ? opponentLeft : playerLeft, MOVE_TAILWIND);}
|
||||||
|
} SCENE {
|
||||||
|
if (opponentSide) {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_TAILWIND, opponentLeft);
|
||||||
|
|
||||||
|
ABILITY_POPUP(opponentLeft, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by Tailwind charged Foe Wobbuffet with power!");
|
||||||
|
|
||||||
|
ABILITY_POPUP(opponentRight, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by Tailwind charged Foe Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_TAILWIND, playerLeft);
|
||||||
|
|
||||||
|
ABILITY_POPUP(playerLeft, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by Tailwind charged Wobbuffet with power!");
|
||||||
|
|
||||||
|
ABILITY_POPUP(playerRight, ABILITY_WIND_POWER);
|
||||||
|
MESSAGE("Being hit by Tailwind charged Wobbuffet with power!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user