commit
b8615b61f0
@ -3393,6 +3393,7 @@ BattleScript_EffectMeanLookGen5:
|
||||
BattleScript_EffectNightmare::
|
||||
attackcanceler
|
||||
jumpifsubstituteblocks BattleScript_ButItFailed
|
||||
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
|
||||
jumpifvolatile BS_TARGET, VOLATILE_NIGHTMARE, BattleScript_ButItFailed
|
||||
jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_NightmareWorked
|
||||
jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_NightmareWorked
|
||||
@ -3767,6 +3768,7 @@ BattleScript_EffectBellyDrum::
|
||||
|
||||
BattleScript_EffectPsychUp::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_MoveMissedPause, ACC_CURR_MOVE
|
||||
copyfoestats
|
||||
attackanimation
|
||||
waitanimation
|
||||
|
||||
@ -90,6 +90,7 @@
|
||||
#define B_MINIMIZE_EVASION GEN_LATEST // In Gen5+, Minimize raises evasion by 2 stages instead of 1.
|
||||
#define B_GROWTH_STAT_RAISE GEN_LATEST // In Gen5+, Growth raises Attack in addition to Special Attack by 1 stage each. Under the effects of the sun, it raises them by 2 stages each instead.
|
||||
#define B_FOCUS_ENERGY_CRIT_RATIO GEN_LATEST // In Gen3+, Focus Energy increases critical hit ratio by 2 instead of 1.
|
||||
#define B_PSYCH_UP_CRIT_RATIO GEN_LATEST // In Gen6+, Psych Up also copies the target's critical hit ratio.
|
||||
|
||||
// Other move settings
|
||||
#define B_INCINERATE_GEMS GEN_LATEST // In Gen6+, Incinerate can destroy Gems.
|
||||
|
||||
@ -84,6 +84,7 @@
|
||||
F(MINIMIZE_EVASION, minimizeEvasion, (u32, GEN_COUNT - 1)) \
|
||||
F(GROWTH_STAT_RAISE, growthStatRaise, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(FOCUS_ENERGY_CRIT_RATIO, focusEnergyCritRatio, (u32, GEN_COUNT - 1)) \
|
||||
F(PSYCH_UP_CRIT_RATIO, psychUpCritRatio, (u32, GEN_COUNT - 1)) \
|
||||
/* Other move settings */ \
|
||||
F(INCINERATE_GEMS, incinerateGems, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
F(CAN_SPITE_FAIL, canSpiteFail, (u32, GEN_COUNT - 1)) /* TODO: use in tests */ \
|
||||
|
||||
@ -2851,7 +2851,7 @@ static void Cmd_printselectionstringfromtable(void)
|
||||
bool32 HasBattlerActedThisTurn(u32 battler)
|
||||
{
|
||||
u32 i;
|
||||
for (i = 0; i < gCurrentTurnActionNumber; i++)
|
||||
for (i = 0; i <= gCurrentTurnActionNumber; i++)
|
||||
{
|
||||
if (gBattlerByTurnOrder[i] == battler)
|
||||
return TRUE;
|
||||
@ -6848,7 +6848,9 @@ static void Cmd_moveend(void)
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (IsBattlerTurnDamaged(i) && EmergencyExitCanBeTriggered(i))
|
||||
if (!IsBattleMoveStatus(gCurrentMove)
|
||||
&& !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE)
|
||||
&& EmergencyExitCanBeTriggered(i))
|
||||
{
|
||||
emergencyExitBattlers |= 1u << i;
|
||||
numEmergencyExitBattlers++;
|
||||
@ -12288,7 +12290,15 @@ static void Cmd_copyfoestats(void)
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].statStages[i] = gBattleMons[gBattlerTarget].statStages[i];
|
||||
}
|
||||
gBattleScripting.battler = gBattlerTarget;
|
||||
if (GetConfig(CONFIG_PSYCH_UP_CRIT_RATIO) >= GEN_6)
|
||||
{
|
||||
// Copy crit boosts (Focus Energy, Dragon Cheer, G-Max Chi Strike)
|
||||
gBattleMons[gBattlerAttacker].volatiles.focusEnergy = gBattleMons[gBattlerTarget].volatiles.focusEnergy;
|
||||
gBattleMons[gBattlerAttacker].volatiles.dragonCheer = gBattleMons[gBattlerTarget].volatiles.dragonCheer;
|
||||
gBattleMons[gBattlerAttacker].volatiles.bonusCritStages = gBattleMons[gBattlerTarget].volatiles.bonusCritStages;
|
||||
}
|
||||
gEffectBattler = gBattlerTarget;
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
@ -4602,6 +4602,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
||||
&& IsBattlerAlive(battler)
|
||||
&& gBattleStruct->battlerState[partner].commanderSpecies == SPECIES_NONE
|
||||
&& gBattleMons[partner].species == SPECIES_DONDOZO
|
||||
&& (gChosenActionByBattler[partner] != B_ACTION_SWITCH || HasBattlerActedThisTurn(partner))
|
||||
&& GET_BASE_SPECIES_ID(GetMonData(GetBattlerMon(battler), MON_DATA_SPECIES)) == SPECIES_TATSUGIRI)
|
||||
{
|
||||
SaveBattlerAttacker(gBattlerAttacker);
|
||||
@ -9409,19 +9410,23 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method)
|
||||
bool32 DoBattlersShareType(u32 battler1, u32 battler2)
|
||||
{
|
||||
s32 i;
|
||||
s32 j;
|
||||
enum Type types1[3], types2[3];
|
||||
GetBattlerTypes(battler1, FALSE, types1);
|
||||
GetBattlerTypes(battler2, FALSE, types2);
|
||||
|
||||
if (types1[2] == TYPE_MYSTERY)
|
||||
types1[2] = types1[0];
|
||||
if (types2[2] == TYPE_MYSTERY)
|
||||
types2[2] = types2[0];
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (types1[i] == types2[0] || types1[i] == types2[1] || types1[i] == types2[2])
|
||||
return TRUE;
|
||||
if (types1[i] == TYPE_MYSTERY)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
if (types2[j] == TYPE_MYSTERY)
|
||||
continue;
|
||||
if (types1[i] == types2[j])
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@ -9805,6 +9810,7 @@ bool32 CanFling(u32 battler)
|
||||
|| (GetConfig(CONFIG_KLUTZ_FLING_INTERACTION) >= GEN_5 && GetBattlerAbility(battler) == ABILITY_KLUTZ)
|
||||
|| gFieldStatuses & STATUS_FIELD_MAGIC_ROOM
|
||||
|| gBattleMons[battler].volatiles.embargo
|
||||
|| (GetItemTMHMIndex(item) != 0 && GetItemImportance(item) == 1) // don't fling reusable TMs
|
||||
|| GetFlingPowerFromItemId(item) == 0
|
||||
|| !CanBattlerGetOrLoseItem(battler, item))
|
||||
return FALSE;
|
||||
|
||||
24
src/berry.c
24
src/berry.c
@ -20,6 +20,7 @@ static u8 BerryTreeGetNumStagesWatered(struct BerryTree *tree);
|
||||
static u8 GetNumStagesWateredByBerryTreeId(u8 id);
|
||||
static u8 CalcBerryYieldInternal(u16 max, u16 min, u8 water);
|
||||
static u8 CalcBerryYield(struct BerryTree *tree);
|
||||
static u32 GetBerryTreeAge(u8 id, u8 stage);
|
||||
static u8 GetBerryCountByBerryTreeId(u8 id);
|
||||
static u16 GetStageDurationByBerryType(u8);
|
||||
static u8 GetDrainRateByBerryType(u8);
|
||||
@ -1961,8 +1962,15 @@ void PlantBerryTree(u8 id, u8 berry, u8 stage, bool8 allowGrowth)
|
||||
tree->stage = stage;
|
||||
tree->moistureLevel = 100;
|
||||
if (OW_BERRY_ALWAYS_WATERABLE)
|
||||
tree->berryYield = GetBerryInfo(berry)->maxYield;
|
||||
if (stage == BERRY_STAGE_BERRIES)
|
||||
{
|
||||
// We simulate a tree having grown without water
|
||||
u32 berryTreeAge = GetBerryTreeAge(id, stage);
|
||||
if (GetBerryInfo(berry)->maxYield - berryTreeAge * GetBerryInfo(berry)->maxYield / 5 < GetBerryInfo(berry)->minYield)
|
||||
tree->berryYield = GetBerryInfo(berry)->minYield;
|
||||
else
|
||||
tree->berryYield = GetBerryInfo(berry)->maxYield - berryTreeAge * GetBerryInfo(berry)->maxYield / 5;
|
||||
}
|
||||
else if (stage == BERRY_STAGE_BERRIES)
|
||||
{
|
||||
tree->berryYield = CalcBerryYield(tree);
|
||||
tree->minutesUntilNextStage *= ((tree->mulch == ITEM_TO_MULCH(ITEM_STABLE_MULCH)) ? 6 : 4);
|
||||
@ -2094,6 +2102,17 @@ static u8 CalcBerryYield(struct BerryTree *tree)
|
||||
return result;
|
||||
}
|
||||
|
||||
static u32 GetBerryTreeAge(u8 id, u8 stage)
|
||||
{
|
||||
if (stage == BERRY_STAGE_TRUNK)
|
||||
stage = 5;
|
||||
else if (stage == BERRY_STAGE_BUDDING)
|
||||
stage = 6;
|
||||
else if (stage > 0)
|
||||
stage -= 1;
|
||||
return GetBerryInfo(id)->growthDuration * stage / (OW_BERRY_SIX_STAGES ? 6 : 4);
|
||||
}
|
||||
|
||||
static u8 GetBerryCountByBerryTreeId(u8 id)
|
||||
{
|
||||
return gSaveBlock1Ptr->berryTrees[id].berryYield;
|
||||
@ -2331,7 +2350,6 @@ static const u8 sBerryMutations[][3] = {
|
||||
{ITEM_TO_BERRY(ITEM_IAPAPA_BERRY), ITEM_TO_BERRY(ITEM_MAGO_BERRY), ITEM_TO_BERRY(ITEM_POMEG_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_CHESTO_BERRY), ITEM_TO_BERRY(ITEM_PERSIM_BERRY), ITEM_TO_BERRY(ITEM_KELPSY_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_ORAN_BERRY), ITEM_TO_BERRY(ITEM_PECHA_BERRY), ITEM_TO_BERRY(ITEM_QUALOT_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_CHESTO_BERRY), ITEM_TO_BERRY(ITEM_PERSIM_BERRY), ITEM_TO_BERRY(ITEM_KELPSY_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_ASPEAR_BERRY), ITEM_TO_BERRY(ITEM_LEPPA_BERRY), ITEM_TO_BERRY(ITEM_HONDEW_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_AGUAV_BERRY), ITEM_TO_BERRY(ITEM_FIGY_BERRY), ITEM_TO_BERRY(ITEM_GREPA_BERRY)},
|
||||
{ITEM_TO_BERRY(ITEM_LUM_BERRY), ITEM_TO_BERRY(ITEM_SITRUS_BERRY), ITEM_TO_BERRY(ITEM_TAMATO_BERRY)},
|
||||
|
||||
@ -9064,8 +9064,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
#endif
|
||||
.contestEffect = CONTEST_EFFECT_USER_MORE_EASILY_STARTLED,
|
||||
.contestCategory = CONTEST_CATEGORY_COOL,
|
||||
.contestComboStarterId = COMBO_STARTER_CHARGE,
|
||||
.contestComboMoves = {0},
|
||||
.contestComboStarterId = 0,
|
||||
.contestComboMoves = {COMBO_STARTER_CHARGE},
|
||||
.battleAnimScript = gBattleAnimMove_VoltTackle,
|
||||
.validApprenticeMove = TRUE,
|
||||
},
|
||||
@ -13351,8 +13351,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.category = DAMAGE_CATEGORY_SPECIAL,
|
||||
.contestEffect = CONTEST_EFFECT_AVOID_STARTLE, //CONTEST_EFFECT_QUICKLY_GROW_BORED
|
||||
.contestCategory = CONTEST_CATEGORY_COOL,
|
||||
.contestComboStarterId = COMBO_STARTER_CHARGE,
|
||||
.contestComboMoves = {0},
|
||||
.contestComboStarterId = 0,
|
||||
.contestComboMoves = {COMBO_STARTER_CHARGE},
|
||||
.battleAnimScript = gBattleAnimMove_VoltSwitch,
|
||||
},
|
||||
|
||||
|
||||
@ -1971,7 +1971,11 @@ struct Pokemon *GetFirstLiveMon(void)
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
struct Pokemon *mon = &gPlayerParty[i];
|
||||
if ((OW_FOLLOWERS_ALLOWED_SPECIES && GetMonData(mon, MON_DATA_SPECIES_OR_EGG) != VarGet(OW_FOLLOWERS_ALLOWED_SPECIES))
|
||||
u32 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG);
|
||||
if (species == SPECIES_NONE)
|
||||
continue;
|
||||
|
||||
if ((OW_FOLLOWERS_ALLOWED_SPECIES && species != VarGet(OW_FOLLOWERS_ALLOWED_SPECIES))
|
||||
|| (OW_FOLLOWERS_ALLOWED_MET_LVL && GetMonData(mon, MON_DATA_MET_LEVEL) != VarGet(OW_FOLLOWERS_ALLOWED_MET_LVL))
|
||||
|| (OW_FOLLOWERS_ALLOWED_MET_LOC && GetMonData(mon, MON_DATA_MET_LOCATION) != VarGet(OW_FOLLOWERS_ALLOWED_MET_LOC)))
|
||||
continue;
|
||||
|
||||
@ -119,7 +119,7 @@ SINGLE_BATTLE_TEST("Cheek Pouch doesn't activate when using Natural Gift")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Cheek Pouch doesn't activate when using Fling")
|
||||
SINGLE_BATTLE_TEST("Cheek Pouch doesn't activate when user uses Fling")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_FLING) == EFFECT_FLING);
|
||||
|
||||
@ -455,3 +455,22 @@ DOUBLE_BATTLE_TEST("Commander prevent Dondozo from switch out by Dragon Tail")
|
||||
NOT MESSAGE("Wobbuffet was dragged out!");
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Commander will not activate if partner Dondozo is about to switch out")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_DONDOZO);
|
||||
PLAYER(SPECIES_TATSUGIRI) { Ability(ABILITY_COMMANDER); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
SWITCH(playerLeft, 2);
|
||||
SWITCH(playerRight, 3);
|
||||
}
|
||||
} SCENE {
|
||||
NOT ABILITY_POPUP(playerRight, ABILITY_COMMANDER);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,34 +66,7 @@ SINGLE_BATTLE_TEST("Corrosion does not effect poison type damaging moves if the
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Corrosion can poison Poison- and Steel-type targets if it uses Fling while holding a Toxic Orb or a Poison Barb")
|
||||
{
|
||||
u16 heldItem;
|
||||
|
||||
PARAMETRIZE { heldItem = ITEM_POISON_BARB; }
|
||||
PARAMETRIZE { heldItem = ITEM_TOXIC_ORB; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_FLING) == EFFECT_FLING);
|
||||
ASSUME(gItemsInfo[ITEM_POISON_BARB].holdEffect == HOLD_EFFECT_TYPE_POWER);
|
||||
ASSUME(gItemsInfo[ITEM_POISON_BARB].secondaryId == TYPE_POISON);
|
||||
ASSUME(gItemsInfo[ITEM_TOXIC_ORB].holdEffect == HOLD_EFFECT_TOXIC_ORB);
|
||||
PLAYER(SPECIES_SALANDIT) { Ability(ABILITY_CORROSION); Item(heldItem); }
|
||||
OPPONENT(SPECIES_ODDISH);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FLING); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
|
||||
HP_BAR(opponent);
|
||||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent);
|
||||
if (heldItem == ITEM_POISON_BARB)
|
||||
STATUS_ICON(opponent, poison: TRUE);
|
||||
else
|
||||
STATUS_ICON(opponent, badPoison: TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("If a Poison- or Steel-type Pokémon with Corrosion holds a Toxic Orb, it will badly poison itself")
|
||||
SINGLE_BATTLE_TEST("Corrosion badly poisons its Poison/Steel-type user who holds a Toxic Orb")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_TOXIC_ORB].holdEffect == HOLD_EFFECT_TOXIC_ORB);
|
||||
@ -107,7 +80,7 @@ SINGLE_BATTLE_TEST("If a Poison- or Steel-type Pokémon with Corrosion holds a T
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("If a Poison- or Steel-type Pokémon with Corrosion poisons a target with Synchronize, Synchronize will not poison Poison- or Steel-type Pokémon")
|
||||
SINGLE_BATTLE_TEST("Corrosion can poison a target with Synchronize and Synchronize will not poison Poison- or Steel-type Pokémon")
|
||||
{
|
||||
u16 move;
|
||||
PARAMETRIZE { move = MOVE_TOXIC; }
|
||||
|
||||
@ -209,3 +209,73 @@ WILD_BATTLE_TEST("Emergency Exit activates when taking residual damage and falli
|
||||
EXPECT_EQ(gBattleOutcome, B_OUTCOME_PLAYER_TELEPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Emergency Exit will trigger due to recoil damage")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_MIND_BLOWN) == EFFECT_MAX_HP_50_RECOIL);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(262); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_MIND_BLOWN); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_MIND_BLOWN, opponent);
|
||||
HP_BAR(player);
|
||||
HP_BAR(opponent);
|
||||
ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Emergency Exit will trigger due to confusion damage")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_CONFUSE_RAY) == EFFECT_CONFUSE);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(133); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(player, MOVE_CONFUSE_RAY);
|
||||
MOVE(opponent, MOVE_POUND);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CONFUSE_RAY, player);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, opponent);
|
||||
HP_BAR(opponent);
|
||||
NOT ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Emergency Exit is not triggered by Pain Split")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_PAIN_SPLIT) == EFFECT_PAIN_SPLIT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(133); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_PAIN_SPLIT); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PAIN_SPLIT, player);
|
||||
HP_BAR(opponent);
|
||||
NOT ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Emergency Exit will trigger due to Jump Kick recoil")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_JUMP_KICK) == EFFECT_RECOIL_IF_MISS);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_GOLISOPOD) { Ability(ABILITY_EMERGENCY_EXIT); MaxHP(263); HP(262); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_JUMP_KICK, hit: FALSE); SEND_OUT(opponent, 1); }
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_JUMP_KICK, opponent);
|
||||
HP_BAR(opponent);
|
||||
ABILITY_POPUP(opponent, ABILITY_EMERGENCY_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -507,7 +507,7 @@ SINGLE_BATTLE_TEST("Fling deals damage based on items fling power")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Fling deals damage based on a TM's move power")
|
||||
SINGLE_BATTLE_TEST("Fling deals damage based on a TM's move power if reusable or fails if breakable")
|
||||
{
|
||||
s16 damage[2];
|
||||
|
||||
@ -520,33 +520,17 @@ SINGLE_BATTLE_TEST("Fling deals damage based on a TM's move power")
|
||||
TURN { MOVE(player, MOVE_FLING); }
|
||||
TURN { MOVE(player, MOVE_EGG_BOMB); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[0]);
|
||||
if (GetItemImportance(ITEM_TM_EARTHQUAKE) == 0) {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[0]);
|
||||
} else {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
|
||||
MESSAGE("But it failed!");
|
||||
}
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EGG_BOMB, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[1]);
|
||||
} THEN {
|
||||
EXPECT_EQ(damage[0], damage[1]);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Fling deals damage based on a TM's move power")
|
||||
{
|
||||
s16 damage[2];
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMovePower(MOVE_EARTHQUAKE) == GetMovePower(MOVE_EGG_BOMB));
|
||||
ASSUME(!IsSpeciesOfType(SPECIES_WOBBUFFET, TYPE_DARK));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_TM_EARTHQUAKE); }
|
||||
OPPONENT(SPECIES_HIPPOWDON);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FLING); }
|
||||
TURN { MOVE(player, MOVE_EGG_BOMB); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[0]);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EGG_BOMB, player);
|
||||
HP_BAR(opponent, captureDamage: &damage[1]);
|
||||
} THEN {
|
||||
EXPECT_EQ(damage[0], damage[1]);
|
||||
if (GetItemImportance(ITEM_TM_EARTHQUAKE) == 0)
|
||||
EXPECT_EQ(damage[0], damage[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,122 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Psych Up (Move Effect) test titles")
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_PSYCH_UP) == EFFECT_PSYCH_UP);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Psych Up displays the correct battlers when used by the player")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2);
|
||||
PLAYER(SPECIES_TORNADUS) { Speed(66); }
|
||||
OPPONENT(SPECIES_LANDORUS) { Speed(99); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SWORDS_DANCE); MOVE(player, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_PSYCH_UP); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, opponent);
|
||||
MESSAGE("Tornadus copied the opposing Landorus's stat changes!");
|
||||
} THEN {
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], opponent->statStages[STAT_ATK]);
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Psych Up displays the correct battlers when used by the opponent")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2);
|
||||
PLAYER(SPECIES_TORNADUS) { Speed(66); }
|
||||
OPPONENT(SPECIES_LANDORUS) { Speed(99); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SWORDS_DANCE); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(opponent, MOVE_PSYCH_UP); MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SWORDS_DANCE, player);
|
||||
MESSAGE("The opposing Landorus copied Tornadus's stat changes!");
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], player->statStages[STAT_ATK]);
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Psych Up ignores Spiky Shield and Baneful Bunker but fails against Crafty Shield")
|
||||
{
|
||||
u32 protectMove = MOVE_NONE;
|
||||
bool32 shouldFail = FALSE;
|
||||
|
||||
PARAMETRIZE { protectMove = MOVE_SPIKY_SHIELD; shouldFail = FALSE; }
|
||||
PARAMETRIZE { protectMove = MOVE_BANEFUL_BUNKER; shouldFail = FALSE; }
|
||||
PARAMETRIZE { protectMove = MOVE_CRAFTY_SHIELD; shouldFail = TRUE; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2);
|
||||
ASSUME(GetMoveEffect(MOVE_SPIKY_SHIELD) == EFFECT_PROTECT);
|
||||
ASSUME(GetMoveEffect(MOVE_BANEFUL_BUNKER) == EFFECT_PROTECT);
|
||||
ASSUME(GetMoveEffect(MOVE_CRAFTY_SHIELD) == EFFECT_PROTECT);
|
||||
PLAYER(SPECIES_TORNADUS) { Speed(66); }
|
||||
OPPONENT(SPECIES_LANDORUS) { Speed(99); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SWORDS_DANCE); MOVE(player, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(opponent, protectMove); MOVE(player, MOVE_PSYCH_UP); }
|
||||
} SCENE {
|
||||
if (shouldFail) {
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCH_UP, player);
|
||||
MESSAGE("Tornadus copied the opposing Landorus's stat changes!");
|
||||
}
|
||||
} else {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCH_UP, player);
|
||||
MESSAGE("Tornadus copied the opposing Landorus's stat changes!");
|
||||
}
|
||||
} THEN {
|
||||
if (shouldFail) {
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE);
|
||||
} else {
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], opponent->statStages[STAT_ATK]);
|
||||
EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Psych Up does not copy the target's critical hit ratio (Gen5)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_FOCUS_ENERGY) == EFFECT_FOCUS_ENERGY);
|
||||
WITH_CONFIG(CONFIG_PSYCH_UP_CRIT_RATIO, GEN_5);
|
||||
WITH_CONFIG(CONFIG_FOCUS_ENERGY_CRIT_RATIO, GEN_9);
|
||||
PLAYER(SPECIES_TORNADUS) { Speed(66); }
|
||||
OPPONENT(SPECIES_LANDORUS) { Speed(99); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_FOCUS_ENERGY); MOVE(player, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_PSYCH_UP); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCH_UP, player);
|
||||
MESSAGE("Tornadus copied the opposing Landorus's stat changes!");
|
||||
} THEN {
|
||||
EXPECT(opponent->volatiles.focusEnergy);
|
||||
EXPECT(!player->volatiles.focusEnergy);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Psych Up copies the target's critical hit ratio (Gen6+)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_FOCUS_ENERGY) == EFFECT_FOCUS_ENERGY);
|
||||
WITH_CONFIG(CONFIG_PSYCH_UP_CRIT_RATIO, GEN_6);
|
||||
WITH_CONFIG(CONFIG_FOCUS_ENERGY_CRIT_RATIO, GEN_9);
|
||||
PLAYER(SPECIES_TORNADUS) { Speed(66); }
|
||||
OPPONENT(SPECIES_LANDORUS) { Speed(99); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_FOCUS_ENERGY); MOVE(player, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_PSYCH_UP); MOVE(opponent, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_PSYCH_UP, player);
|
||||
MESSAGE("Tornadus copied the opposing Landorus's stat changes!");
|
||||
} THEN {
|
||||
EXPECT(opponent->volatiles.focusEnergy);
|
||||
EXPECT(player->volatiles.focusEnergy);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,17 @@
|
||||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_SYNCHRONOISE) == EFFECT_SYNCHRONOISE);
|
||||
ASSUME(GetSpeciesType(SPECIES_WOBBUFFET, 0) == TYPE_PSYCHIC);
|
||||
ASSUME(GetSpeciesType(SPECIES_WOBBUFFET, 1) == TYPE_PSYCHIC);
|
||||
ASSUME(GetSpeciesType(SPECIES_BULBASAUR, 0) == TYPE_GRASS);
|
||||
ASSUME(GetSpeciesType(SPECIES_BULBASAUR, 1) == TYPE_POISON);
|
||||
ASSUME(GetSpeciesType(SPECIES_ARCANINE, 0) == TYPE_FIRE);
|
||||
ASSUME(GetSpeciesType(SPECIES_ARCANINE, 1) == TYPE_FIRE);
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Synchronoise hits all Pokemon that share a type with the attacker")
|
||||
{
|
||||
GIVEN {
|
||||
@ -71,4 +82,35 @@ DOUBLE_BATTLE_TEST("Synchronoise will fail if the corresponding typing mon prote
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Synchronoise will fail for a typeless user even if a target is typeless")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_BURN_UP) == EFFECT_FAIL_IF_NOT_ARG_TYPE);
|
||||
PLAYER(SPECIES_ARCANINE) { Moves(MOVE_BURN_UP, MOVE_SYNCHRONOISE); }
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_ARCANINE) { Moves(MOVE_BURN_UP, MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(playerLeft, MOVE_BURN_UP, target: opponentRight);
|
||||
MOVE(opponentLeft, MOVE_BURN_UP, target: playerRight);
|
||||
MOVE(playerRight, MOVE_CELEBRATE);
|
||||
MOVE(opponentRight, MOVE_CELEBRATE);
|
||||
}
|
||||
TURN {
|
||||
MOVE(playerLeft, MOVE_SYNCHRONOISE);
|
||||
MOVE(opponentLeft, MOVE_CELEBRATE);
|
||||
MOVE(playerRight, MOVE_CELEBRATE);
|
||||
MOVE(opponentRight, MOVE_CELEBRATE);
|
||||
}
|
||||
} SCENE {
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SYNCHRONOISE, playerLeft);
|
||||
MESSAGE("Arcanine used Synchronoise!");
|
||||
MESSAGE("It doesn't affect the opposing Arcanine…");
|
||||
MESSAGE("It doesn't affect Wobbuffet…");
|
||||
MESSAGE("It doesn't affect the opposing Wobbuffet…");
|
||||
NOT MESSAGE("But it failed!");
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Synchronoise (Move Effect) test titles")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user