mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-04-25 16:28:25 -05:00
30/01/26 Master to upcoming merge
This commit is contained in:
commit
396c64c22a
|
|
@ -3165,6 +3165,7 @@ BattleScript_EffectMeanLookGen5:
|
|||
BattleScript_EffectNightmare::
|
||||
attackcanceler
|
||||
jumpifsubstituteblocks BattleScript_ButItFailed
|
||||
accuracycheck BattleScript_MoveMissedPause
|
||||
jumpifvolatile BS_TARGET, VOLATILE_NIGHTMARE, BattleScript_ButItFailed
|
||||
jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_NightmareWorked
|
||||
jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_NightmareWorked
|
||||
|
|
@ -3465,6 +3466,7 @@ BattleScript_EffectBellyDrum::
|
|||
|
||||
BattleScript_EffectPsychUp::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_MoveMissedPause
|
||||
copyfoestats
|
||||
attackanimation
|
||||
waitanimation
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ will NOT be merged until after the next Minor Release.
|
|||
---
|
||||
|
||||
## What is a "Big Feature"?
|
||||
* If the original owner of the PR thinks a feature should be labeled a Big Feature, it is, no questions asked
|
||||
* If a reviewer thinks a PR is a Big Feature, then it is
|
||||
* If the two disagree, it can be discussed in a PR thread, and can ultimately be resolved with a Maintainer vote.
|
||||
* If any maintainer thinks a PR is a Big Feature, then it is, no question asked
|
||||
* If there is disagreement, it can be discussed in a PR thread, and can ultimately be resolved with a Maintainer vote.
|
||||
* If you believe your PR should have this feature, please let a maintainer know.
|
||||
|
||||
### How To Identify a Big Feature
|
||||
* **Big diffs**: It's easy for something to go unnoticed in review when it's a tiny part of a massive diff.
|
||||
|
|
|
|||
|
|
@ -93,6 +93,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.
|
||||
|
|
|
|||
|
|
@ -86,6 +86,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 */ \
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ enum RandomTag
|
|||
RNG_QUICK_DRAW,
|
||||
RNG_QUICK_CLAW,
|
||||
RNG_TRACE,
|
||||
RNG_FOREWARN,
|
||||
RNG_FICKLE_BEAM,
|
||||
RNG_AI_ABILITY,
|
||||
RNG_AI_SCORE_TIE_DOUBLES_MOVE,
|
||||
|
|
|
|||
|
|
@ -3831,24 +3831,21 @@ bool32 HasChoiceEffect(u32 battler)
|
|||
}
|
||||
}
|
||||
|
||||
static u32 FindMoveUsedXTurnsAgo(u32 battlerId, u32 x)
|
||||
{
|
||||
s32 index = gBattleHistory->moveHistoryIndex[battlerId];
|
||||
for (u32 turnsAgo = 0; turnsAgo < x; turnsAgo++)
|
||||
{
|
||||
if (--index < 0)
|
||||
index = AI_MOVE_HISTORY_COUNT - 1;
|
||||
}
|
||||
return gBattleHistory->moveHistory[battlerId][index];
|
||||
}
|
||||
|
||||
bool32 IsWakeupTurn(u32 battler)
|
||||
{
|
||||
// Check if rest was used 2 turns ago
|
||||
if ((gBattleMons[battler].status1 & STATUS1_SLEEP) == 1 && GetMoveEffect(FindMoveUsedXTurnsAgo(battler, 2)) == EFFECT_REST)
|
||||
return TRUE;
|
||||
else // no way to know
|
||||
u32 sleepTurns = gBattleMons[battler].status1 & STATUS1_SLEEP;
|
||||
u32 toSub;
|
||||
|
||||
if (sleepTurns == 0)
|
||||
return FALSE;
|
||||
|
||||
// Early Bird reduces the sleep timer twice as fast.
|
||||
if (gAiLogicData->abilities[battler] == ABILITY_EARLY_BIRD)
|
||||
toSub = 2;
|
||||
else
|
||||
toSub = 1;
|
||||
|
||||
return sleepTurns <= toSub;
|
||||
}
|
||||
|
||||
bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
|
||||
|
|
|
|||
|
|
@ -837,8 +837,8 @@ static enum CancelerResult CancelerMoveFailure(struct BattleContext *ctx)
|
|||
bool32 canUseWideGuard = (GetConfig(CONFIG_WIDE_GUARD) >= GEN_6 && protectMethod == PROTECT_WIDE_GUARD);
|
||||
bool32 canUseQuickGuard = (GetConfig(CONFIG_QUICK_GUARD) >= GEN_6 && protectMethod == PROTECT_QUICK_GUARD);
|
||||
|
||||
if (!canUseProtectSecondTime
|
||||
&& !canUseWideGuard
|
||||
if (!canUseProtectSecondTime
|
||||
&& !canUseWideGuard
|
||||
&& !canUseQuickGuard
|
||||
&& protectMethod != PROTECT_CRAFTY_SHIELD)
|
||||
battleScript = BattleScript_ButItFailed;
|
||||
|
|
@ -2884,7 +2884,9 @@ static enum MoveEndResult MoveEndEmergencyExit(void)
|
|||
// we check if EE can be activated and count how many.
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (IsBattlerTurnDamaged(i) && EmergencyExitCanBeTriggered(i))
|
||||
if (!IsBattleMoveStatus(gCurrentMove)
|
||||
&& !gBattleStruct->unableToUseMove
|
||||
&& EmergencyExitCanBeTriggered(i))
|
||||
{
|
||||
emergencyExitBattlers |= 1u << i;
|
||||
numEmergencyExitBattlers++;
|
||||
|
|
@ -3075,29 +3077,28 @@ static enum MoveEndResult MoveEndPickpocket(void)
|
|||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item
|
||||
&& !GetBattlerPartyState(gBattlerAttacker)->isKnockedOff // But not knocked off
|
||||
&& IsMoveMakingContact(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove) // Pickpocket requires contact
|
||||
&& !IsBattlerUnaffectedByMove(gBattlerTarget)) // Obviously attack needs to have worked
|
||||
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE
|
||||
&& !GetBattlerPartyState(gBattlerAttacker)->isKnockedOff) // Gen3 edge case where the knocked of item was not removed
|
||||
{
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
SortBattlersBySpeed(battlers, FALSE); // Pickpocket activates for fastest mon without item
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
u8 battler = battlers[i];
|
||||
// Attacker is mon who made contact, battler is mon with pickpocket
|
||||
if (battler != gBattlerAttacker // Cannot pickpocket yourself
|
||||
&& GetBattlerAbility(battler) == ABILITY_PICKPOCKET // Target must have pickpocket ability
|
||||
&& IsBattlerTurnDamaged(battler) // Target needs to have been damaged
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) // Subsitute unaffected
|
||||
&& IsBattlerAlive(battler) // Battler must be alive to pickpocket
|
||||
&& gBattleMons[battler].item == ITEM_NONE // Pickpocketer can't have an item already
|
||||
&& CanStealItem(battler, gBattlerAttacker, gBattleMons[gBattlerAttacker].item)) // Cannot steal plates, mega stones, etc
|
||||
u8 battlerDef = battlers[i];
|
||||
if (battlerDef != gBattlerAttacker
|
||||
&& !IsBattlerUnaffectedByMove(battlerDef)
|
||||
&& GetBattlerAbility(battlerDef) == ABILITY_PICKPOCKET
|
||||
&& IsMoveMakingContact(gBattlerAttacker, battlerDef, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove)
|
||||
&& IsBattlerTurnDamaged(battlerDef)
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove)
|
||||
&& IsBattlerAlive(battlerDef)
|
||||
&& gBattleMons[battlerDef].item == ITEM_NONE
|
||||
&& CanStealItem(battlerDef, gBattlerAttacker, gBattleMons[gBattlerAttacker].item))
|
||||
{
|
||||
gBattlerTarget = gBattlerAbility = battler;
|
||||
gBattlerTarget = gBattlerAbility = battlerDef;
|
||||
// Battle scripting is super brittle so we shall do the item exchange now (if possible)
|
||||
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_STICKY_HOLD)
|
||||
StealTargetItem(gBattlerTarget, gBattlerAttacker); // Target takes attacker's item
|
||||
StealTargetItem(battlerDef, gBattlerAttacker); // Target takes attacker's item
|
||||
|
||||
gEffectBattler = gBattlerAttacker;
|
||||
BattleScriptCall(BattleScript_Pickpocket); // Includes sticky hold check to print separate string
|
||||
|
|
|
|||
|
|
@ -2211,7 +2211,7 @@ static void Cmd_printfromtable(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;
|
||||
|
|
@ -9468,7 +9468,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2295,12 +2295,43 @@ static void ForewarnChooseMove(u32 battler)
|
|||
}
|
||||
}
|
||||
|
||||
for (bestId = 0, i = 1; i < count; i++)
|
||||
if (count == 0)
|
||||
{
|
||||
if (data[i].power > data[bestId].power)
|
||||
bestId = i;
|
||||
else if (data[i].power == data[bestId].power && Random() & 1)
|
||||
Free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
u32 tieCount = 1;
|
||||
u8 bestPower = data[0].power;
|
||||
|
||||
bestId = 0;
|
||||
for (i = 1; i < count; i++)
|
||||
{
|
||||
if (data[i].power > bestPower)
|
||||
{
|
||||
bestPower = data[i].power;
|
||||
bestId = i;
|
||||
tieCount = 1;
|
||||
}
|
||||
else if (data[i].power == bestPower)
|
||||
{
|
||||
tieCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (tieCount > 1)
|
||||
{
|
||||
u32 tieIndex = RandomUniform(RNG_FOREWARN, 0, tieCount - 1);
|
||||
for (i = 0, bestId = 0; i < count; i++)
|
||||
{
|
||||
if (data[i].power != bestPower)
|
||||
continue;
|
||||
if (tieIndex-- == 0)
|
||||
{
|
||||
bestId = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gEffectBattler = data[bestId].battler;
|
||||
|
|
@ -3286,7 +3317,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||
}
|
||||
return effect; // Note: It returns effect as to not record the ability if Frisk does not activate.
|
||||
case ABILITY_FOREWARN:
|
||||
if (shouldAbilityTrigger)
|
||||
if (shouldAbilityTrigger && !IsOpposingSideEmpty(battler))
|
||||
{
|
||||
ForewarnChooseMove(battler);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_FOREWARN;
|
||||
|
|
@ -4810,6 +4841,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);
|
||||
|
|
@ -8984,19 +9016,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;
|
||||
|
|
@ -9361,6 +9397,7 @@ bool32 CanFling(u32 battlerAtk, u32 battlerDef)
|
|||
|| (GetConfig(CONFIG_KLUTZ_FLING_INTERACTION) >= GEN_5 && GetBattlerAbility(battlerAtk) == ABILITY_KLUTZ)
|
||||
|| gFieldStatuses & STATUS_FIELD_MAGIC_ROOM
|
||||
|| gBattleMons[battlerAtk].volatiles.embargo
|
||||
|| (GetItemTMHMIndex(item) != 0 && GetItemImportance(item) == 1) // don't fling reusable TMs
|
||||
|| GetFlingPowerFromItemId(item) == 0
|
||||
|| !CanBattlerGetOrLoseItem(battlerAtk, battlerDef, item))
|
||||
return FALSE;
|
||||
|
|
@ -9466,6 +9503,7 @@ bool32 CanStealItem(u32 battlerStealing, u32 battlerItem, enum Item item)
|
|||
}
|
||||
|
||||
// It's supposed to pop before trying to steal but this also works
|
||||
// Now that the order is correct this is redundant. The question is whether Trick can steal it.
|
||||
if (GetItemHoldEffect(item) == HOLD_EFFECT_AIR_BALLOON)
|
||||
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);
|
||||
|
|
@ -1965,8 +1966,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);
|
||||
|
|
@ -2098,6 +2106,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;
|
||||
|
|
@ -2335,7 +2354,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)},
|
||||
|
|
|
|||
|
|
@ -9248,8 +9248,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,
|
||||
},
|
||||
|
|
@ -13550,8 +13550,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,
|
||||
},
|
||||
|
||||
|
|
@ -19403,8 +19403,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
|||
{
|
||||
.name = COMPOUND_STRING("Stone Axe"),
|
||||
.description = COMPOUND_STRING(
|
||||
"High critical hit ratio. Sets\n"
|
||||
"Splinters that hurt the foe."),
|
||||
"Sets sharp rocks that hurt\n"
|
||||
"the foe."),
|
||||
.effect = EFFECT_STONE_AXE,
|
||||
.power = 65,
|
||||
.type = TYPE_ROCK,
|
||||
|
|
@ -19740,8 +19740,8 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
|||
{
|
||||
.name = COMPOUND_STRING("Ceaseless Edge"),
|
||||
.description = COMPOUND_STRING(
|
||||
"High critical hit ratio. Sets\n"
|
||||
"Splinters that hurt the foe."),
|
||||
"Sets Spikes that hurt the\n"
|
||||
"foe."),
|
||||
.effect = EFFECT_CEASELESS_EDGE,
|
||||
.power = 65,
|
||||
.type = TYPE_DARK,
|
||||
|
|
|
|||
35986
src/data/trainers_frlg.h
Normal file
35986
src/data/trainers_frlg.h
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -1968,7 +1968,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")
|
||||
{
|
||||
enum Move move;
|
||||
PARAMETRIZE { move = MOVE_TOXIC; }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,49 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Early Bird (Ability) test titles")
|
||||
SINGLE_BATTLE_TEST("Early Bird wakes up if 1 sleep turn is preset")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DODUO) { Ability(ABILITY_EARLY_BIRD); Status1(STATUS1_SLEEP_TURN(1)); Moves(MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
MESSAGE("Doduo woke up!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
MESSAGE("Doduo used Celebrate!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Early Bird turns a 3-turn sleep into one missed turn")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DODUO) { Ability(ABILITY_EARLY_BIRD); Status1(STATUS1_SLEEP_TURN(3)); Moves(MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
MESSAGE("Doduo is fast asleep.");
|
||||
MESSAGE("Doduo woke up!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
MESSAGE("Doduo used Celebrate!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Early Bird reduces Rest sleep to one turn")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DODUO) { Ability(ABILITY_EARLY_BIRD); MaxHP(99); HP(66); Moves(MOVE_REST, MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_REST); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); }
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
MESSAGE("Doduo is fast asleep.");
|
||||
MESSAGE("Doduo woke up!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
MESSAGE("Doduo used Celebrate!");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,84 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Forewarn (Ability) test titles")
|
||||
DOUBLE_BATTLE_TEST("Forewarn warns about the highest power move among all opposing battlers")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_MUSHARNA) { Ability(ABILITY_FOREWARN); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_ZUBAT) { Moves(MOVE_CRUNCH, MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_EXCADRILL) { Moves(MOVE_FISSURE, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ABILITY_POPUP(playerLeft, ABILITY_FOREWARN);
|
||||
MESSAGE("Forewarn alerted Musharna to the opposing Excadrill's Fissure!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Forewarn randomly chooses between same-power moves on one opponent")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 3, RNG_FOREWARN);
|
||||
GIVEN {
|
||||
ASSUME(GetMovePower(MOVE_TACKLE) == GetMovePower(MOVE_POUND));
|
||||
ASSUME(GetMovePower(MOVE_TACKLE) == GetMovePower(MOVE_SCRATCH));
|
||||
PLAYER(SPECIES_MUSHARNA) { Ability(ABILITY_FOREWARN); }
|
||||
OPPONENT(SPECIES_ZUBAT) { Moves(MOVE_TACKLE, MOVE_POUND, MOVE_SCRATCH, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_FOREWARN);
|
||||
MESSAGE("Forewarn alerted Musharna to the opposing Zubat's Tackle!");
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Forewarn randomly chooses between opponents with same-power moves")
|
||||
{
|
||||
PASSES_RANDOMLY(1, 4, RNG_FOREWARN);
|
||||
GIVEN {
|
||||
ASSUME(GetMovePower(MOVE_TACKLE) == GetMovePower(MOVE_POUND));
|
||||
ASSUME(GetMovePower(MOVE_TACKLE) == GetMovePower(MOVE_SCRATCH));
|
||||
ASSUME(GetMovePower(MOVE_TACKLE) == GetMovePower(MOVE_QUICK_ATTACK));
|
||||
PLAYER(SPECIES_MUSHARNA) { Ability(ABILITY_FOREWARN); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_ZUBAT) { Moves(MOVE_TACKLE, MOVE_POUND, MOVE_PECK, MOVE_CELEBRATE); }
|
||||
OPPONENT(SPECIES_EXCADRILL) { Moves(MOVE_SCRATCH, MOVE_QUICK_ATTACK, MOVE_ABSORB, MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN {}
|
||||
} SCENE {
|
||||
ABILITY_POPUP(playerLeft, ABILITY_FOREWARN);
|
||||
MESSAGE("Forewarn alerted Musharna to the opposing Zubat's Tackle!");
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Forewarn does not trigger if a mon switches in while the opposing field is empty")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_U_TURN) == EFFECT_HIT_ESCAPE);
|
||||
ASSUME(GetMoveEffect(MOVE_HEALING_WISH) == EFFECT_HEALING_WISH);
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_MUSHARNA) { Ability(ABILITY_FOREWARN); }
|
||||
OPPONENT(SPECIES_WYNAUT) { HP(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_TREECKO);
|
||||
OPPONENT(SPECIES_TORCHIC);
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentRight, MOVE_HEALING_WISH);
|
||||
MOVE(playerLeft, MOVE_U_TURN, target: opponentLeft);
|
||||
SEND_OUT(playerLeft, 2);
|
||||
SEND_OUT(opponentLeft, 2);
|
||||
SEND_OUT(opponentRight, 3);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_HEALING_WISH, opponentRight);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, playerLeft);
|
||||
HP_BAR(opponentLeft);
|
||||
NOT ABILITY_POPUP(playerLeft, ABILITY_FOREWARN);
|
||||
MESSAGE("2 sent out Treecko!");
|
||||
MESSAGE("2 sent out Torchic!");
|
||||
NOT ABILITY_POPUP(playerLeft, ABILITY_FOREWARN);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,313 @@
|
|||
#include "global.h"
|
||||
#include "test/battle.h"
|
||||
|
||||
TO_DO_BATTLE_TEST("TODO: Write Pickpocket (Ability) test titles")
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(MoveMakesContact(MOVE_BREAKING_SWIPE));
|
||||
ASSUME(MoveMakesContact(MOVE_SCRATCH));
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Pickpocket checks contact/effect per target for spread moves")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetSpeciesType(SPECIES_CLEFAIRY, 0) == TYPE_FAIRY);
|
||||
ASSUME(GetMoveType(MOVE_BREAKING_SWIPE) == TYPE_DRAGON);
|
||||
ASSUME(GetMoveTarget(MOVE_BREAKING_SWIPE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
OPPONENT(SPECIES_CLEFAIRY);
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_BREAKING_SWIPE); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponentLeft->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(playerLeft->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Pickpocket activates for the fastest itemless target when both are hit by a contact spread move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_BREAKING_SWIPE) == TARGET_BOTH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(20); Item(ITEM_MAGOST_BERRY); }
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(10); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Speed(40); Ability(ABILITY_PICKPOCKET); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Speed(30); Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(playerLeft, MOVE_BREAKING_SWIPE); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponentLeft->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(opponentRight->item == ITEM_NONE);
|
||||
EXPECT(playerLeft->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket steals the attacker's item unless it already has one")
|
||||
{
|
||||
bool32 targetHasItem;
|
||||
PARAMETRIZE { targetHasItem = FALSE; }
|
||||
PARAMETRIZE { targetHasItem = TRUE; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(targetHasItem ? ITEM_EVIOLITE : ITEM_NONE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
if (targetHasItem) {
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
}
|
||||
} else {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
}
|
||||
} THEN {
|
||||
if (targetHasItem) {
|
||||
EXPECT(opponent->item == ITEM_EVIOLITE);
|
||||
EXPECT(player->item == ITEM_MAGOST_BERRY);
|
||||
} else {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket does not activate if the user faints")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); HP(1); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
}
|
||||
MESSAGE("The opposing Sneasel fainted!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
EXPECT(player->item == ITEM_MAGOST_BERRY);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket cannot steal from Sticky Hold")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_GRIMER) { Ability(ABILITY_STICKY_HOLD); Item(ITEM_MAGOST_BERRY); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
ABILITY_POPUP(player, ABILITY_STICKY_HOLD);
|
||||
MESSAGE("Grimer's item cannot be removed!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
EXPECT(player->item == ITEM_MAGOST_BERRY);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket cannot steal restricted held items")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_NORMALIUM_Z].holdEffect == HOLD_EFFECT_Z_CRYSTAL);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_NORMALIUM_Z); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
}
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_NONE);
|
||||
EXPECT(player->item == ITEM_NORMALIUM_Z);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after the final hit of a multi-strike move")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(IsMultiHitMove(MOVE_FURY_SWIPES));
|
||||
ASSUME(MoveMakesContact(MOVE_FURY_SWIPES));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_FURY_SWIPES, WITH_RNG(RNG_HITS, 3)); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FURY_SWIPES, player);
|
||||
MESSAGE("The Pokémon was hit 3 time(s)!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after Magician steals an item")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_DELPHOX) { Ability(ABILITY_MAGICIAN); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_MAGOST_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_MAGICIAN);
|
||||
MESSAGE("Delphox stole the opposing Sneasel's Magost Berry!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Delphox's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after Sticky Barb transfers")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_STICKY_BARB].holdEffect == HOLD_EFFECT_STICKY_BARB);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_STICKY_BARB); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
MESSAGE("The Sticky Barb attached itself to Wobbuffet!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Sticky Barb!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_STICKY_BARB);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after Thief or Covet steals an item")
|
||||
{
|
||||
u16 move;
|
||||
KNOWN_FAILING;
|
||||
PARAMETRIZE { move = MOVE_THIEF; }
|
||||
PARAMETRIZE { move = MOVE_COVET; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(move) == EFFECT_STEAL_ITEM);
|
||||
ASSUME(MoveMakesContact(move));
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_MAGOST_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, move); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet stole the opposing Sneasel's Magost Berry!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after Focus Sash is consumed")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(MoveMakesContact(MOVE_SEISMIC_TOSS));
|
||||
ASSUME(gItemsInfo[ITEM_FOCUS_SASH].holdEffect == HOLD_EFFECT_FOCUS_SASH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); Level(100); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_FOCUS_SASH); MaxHP(6); HP(6); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SEISMIC_TOSS); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SEISMIC_TOSS, player);
|
||||
MESSAGE("The opposing Sneasel hung on using its Focus Sash!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket activates after Knock Off, Bug Bite, or Pluck")
|
||||
{
|
||||
u16 move;
|
||||
PARAMETRIZE { move = MOVE_KNOCK_OFF; }
|
||||
PARAMETRIZE { move = MOVE_BUG_BITE; }
|
||||
PARAMETRIZE { move = MOVE_PLUCK; }
|
||||
GIVEN {
|
||||
ASSUME(MoveMakesContact(move));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MAGOST_BERRY); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_ORAN_BERRY); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, move); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Magost Berry!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_MAGOST_BERRY);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket steals Life Orb after it activates")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
MESSAGE("Wobbuffet was hurt by the Life Orb!");
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Life Orb!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_LIFE_ORB);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket steals Shell Bell after it heals the user")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_SHELL_BELL].holdEffect == HOLD_EFFECT_SHELL_BELL);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SHELL_BELL); MaxHP(100); HP(66); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player);
|
||||
HP_BAR(opponent);
|
||||
HP_BAR(player);
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's Shell Bell!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_SHELL_BELL);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Pickpocket does not prevent King's Rock or Razor Fang flinches")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_KINGS_ROCK].holdEffect == HOLD_EFFECT_FLINCH);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(20); Item(ITEM_KINGS_ROCK); }
|
||||
OPPONENT(SPECIES_SNEASEL) { Speed(10); Ability(ABILITY_PICKPOCKET); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_SCRATCH, WITH_RNG(RNG_HOLD_EFFECT_FLINCH, 1)); MOVE(opponent, MOVE_SCRATCH); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponent, ABILITY_PICKPOCKET);
|
||||
MESSAGE("The opposing Sneasel stole Wobbuffet's King's Rock!");
|
||||
MESSAGE("The opposing Sneasel flinched and couldn't move!");
|
||||
} THEN {
|
||||
EXPECT(opponent->item == ITEM_KINGS_ROCK);
|
||||
EXPECT(player->item == ITEM_NONE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,6 +135,25 @@ AI_SINGLE_BATTLE_TEST("AI will only use Dream Eater if target is asleep")
|
|||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI chooses Sleep Talk only when it will not wake up with Early Bird")
|
||||
{
|
||||
enum Ability ability;
|
||||
|
||||
PARAMETRIZE { ability = ABILITY_RUN_AWAY; }
|
||||
PARAMETRIZE { ability = ABILITY_EARLY_BIRD; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_DODRIO) { Ability(ability); Status1(STATUS1_SLEEP_TURN(2)); Moves(MOVE_SLEEP_TALK, MOVE_TACKLE); }
|
||||
} WHEN {
|
||||
if (ability == ABILITY_EARLY_BIRD)
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_TACKLE); }
|
||||
else
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_SLEEP_TALK); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI sees increased base power of Spit Up")
|
||||
{
|
||||
GIVEN {
|
||||
|
|
|
|||
|
|
@ -514,7 +514,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];
|
||||
|
||||
|
|
@ -527,33 +527,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 {
|
||||
|
|
@ -73,4 +84,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…
Reference in New Issue
Block a user