10/11/25 Master to upcoming merge
This commit is contained in:
commit
d4e7e7ad36
@ -189,8 +189,13 @@
|
|||||||
.4byte \jumpInstr
|
.4byte \jumpInstr
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro unused_0x21
|
.macro jumpifstatignorecontrary battler:req, comparison:req, stat:req, value:req, jumpInstr:req
|
||||||
.byte 0x21
|
.byte 0x21
|
||||||
|
.byte \battler
|
||||||
|
.byte \comparison
|
||||||
|
.byte \stat
|
||||||
|
.byte \value
|
||||||
|
.4byte \jumpInstr
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro jumpbasedontype battler:req, type:req, jumpIfType:req, jumpInstr:req
|
.macro jumpbasedontype battler:req, type:req, jumpIfType:req, jumpInstr:req
|
||||||
|
|||||||
@ -3685,7 +3685,7 @@ BattleScript_BlockedByPrimalWeatherRet::
|
|||||||
|
|
||||||
BattleScript_EffectBellyDrum::
|
BattleScript_EffectBellyDrum::
|
||||||
attackcanceler
|
attackcanceler
|
||||||
jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed
|
jumpifstatignorecontrary BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed
|
||||||
halvehp BattleScript_ButItFailed
|
halvehp BattleScript_ButItFailed
|
||||||
attackanimation
|
attackanimation
|
||||||
waitanimation
|
waitanimation
|
||||||
@ -7440,11 +7440,13 @@ BattleScript_CuteCharmActivates::
|
|||||||
return
|
return
|
||||||
|
|
||||||
BattleScript_GooeyActivates::
|
BattleScript_GooeyActivates::
|
||||||
|
statbuffchange BS_ATTACKER, STAT_CHANGE_ONLY_CHECKING, BattleScript_GooeyActivatesRet
|
||||||
waitstate
|
waitstate
|
||||||
call BattleScript_AbilityPopUp
|
call BattleScript_AbilityPopUp
|
||||||
swapattackerwithtarget @ for defiant, mirror armor
|
swapattackerwithtarget @ for defiant, mirror armor
|
||||||
seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_SPD_MINUS_1
|
seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_SPD_MINUS_1
|
||||||
swapattackerwithtarget
|
swapattackerwithtarget
|
||||||
|
BattleScript_GooeyActivatesRet:
|
||||||
return
|
return
|
||||||
|
|
||||||
BattleScript_AbilityStatusEffect::
|
BattleScript_AbilityStatusEffect::
|
||||||
|
|||||||
@ -315,6 +315,7 @@ bool32 IsBattlerMegaEvolved(u32 battler);
|
|||||||
bool32 IsBattlerPrimalReverted(u32 battler);
|
bool32 IsBattlerPrimalReverted(u32 battler);
|
||||||
bool32 IsBattlerUltraBursted(u32 battler);
|
bool32 IsBattlerUltraBursted(u32 battler);
|
||||||
u16 GetBattleFormChangeTargetSpecies(u32 battler, enum FormChanges method);
|
u16 GetBattleFormChangeTargetSpecies(u32 battler, enum FormChanges method);
|
||||||
|
bool32 TryRevertPartyMonFormChange(u32 partyIndex);
|
||||||
bool32 TryBattleFormChange(u32 battler, enum FormChanges method);
|
bool32 TryBattleFormChange(u32 battler, enum FormChanges method);
|
||||||
bool32 DoBattlersShareType(u32 battler1, u32 battler2);
|
bool32 DoBattlersShareType(u32 battler1, u32 battler2);
|
||||||
bool32 CanBattlerGetOrLoseItem(u32 battler, u16 itemId);
|
bool32 CanBattlerGetOrLoseItem(u32 battler, u16 itemId);
|
||||||
@ -346,7 +347,7 @@ void TrySaveExchangedItem(u32 battler, u16 stolenItem);
|
|||||||
bool32 IsPartnerMonFromSameTrainer(u32 battler);
|
bool32 IsPartnerMonFromSameTrainer(u32 battler);
|
||||||
bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes);
|
bool32 IsBattlerAffectedByHazards(u32 battler, bool32 toxicSpikes);
|
||||||
void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast);
|
void SortBattlersBySpeed(u8 *battlers, bool32 slowToFast);
|
||||||
bool32 CompareStat(u32 battler, enum Stat statId, u8 cmpTo, u8 cmpKind);
|
bool32 CompareStat(u32 battler, enum Stat statId, u8 cmpTo, u8 cmpKind, enum Ability ability);
|
||||||
bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget);
|
bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 checkTarget);
|
||||||
bool32 PickupHasValidTarget(u32 battler);
|
bool32 PickupHasValidTarget(u32 battler);
|
||||||
bool32 CantPickupItem(u32 battler);
|
bool32 CantPickupItem(u32 battler);
|
||||||
|
|||||||
@ -461,6 +461,7 @@ void HandleInputChooseTarget(u32 battler)
|
|||||||
gBattleStruct->zmove.viewing = TRUE;
|
gBattleStruct->zmove.viewing = TRUE;
|
||||||
ReloadMoveNames(battler);
|
ReloadMoveNames(battler);
|
||||||
}
|
}
|
||||||
|
TryToAddMoveInfoWindow();
|
||||||
DoBounceEffect(battler, BOUNCE_HEALTHBOX, 7, 1);
|
DoBounceEffect(battler, BOUNCE_HEALTHBOX, 7, 1);
|
||||||
DoBounceEffect(battler, BOUNCE_MON, 7, 1);
|
DoBounceEffect(battler, BOUNCE_MON, 7, 1);
|
||||||
EndBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX);
|
EndBounceEffect(gMultiUsePlayerCursor, BOUNCE_HEALTHBOX);
|
||||||
|
|||||||
@ -77,7 +77,7 @@ enum ItemEffect TryBoosterEnergy(u32 battler, enum Ability ability, ActivationTi
|
|||||||
|
|
||||||
static enum ItemEffect TryRoomService(u32 battler, ActivationTiming timing)
|
static enum ItemEffect TryRoomService(u32 battler, ActivationTiming timing)
|
||||||
{
|
{
|
||||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battler, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN))
|
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && CompareStat(battler, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN, GetBattlerAbility(battler)))
|
||||||
{
|
{
|
||||||
gEffectBattler = gBattleScripting.battler = battler;
|
gEffectBattler = gBattleScripting.battler = battler;
|
||||||
SET_STATCHANGER(STAT_SPEED, 1, TRUE);
|
SET_STATCHANGER(STAT_SPEED, 1, TRUE);
|
||||||
@ -97,7 +97,7 @@ static enum ItemEffect TryRoomService(u32 battler, ActivationTiming timing)
|
|||||||
|
|
||||||
enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, enum Stat statId, ActivationTiming timing)
|
enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, enum Stat statId, ActivationTiming timing)
|
||||||
{
|
{
|
||||||
if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (gFieldStatuses & terrainFlag && CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battler)))
|
||||||
{
|
{
|
||||||
gEffectBattler = gBattleScripting.battler = battler;
|
gEffectBattler = gBattleScripting.battler = battler;
|
||||||
SET_STATCHANGER(statId, 1, FALSE);
|
SET_STATCHANGER(statId, 1, FALSE);
|
||||||
@ -423,7 +423,7 @@ static enum ItemEffect TryBlunderPolicy(u32 battlerAtk)
|
|||||||
|
|
||||||
if (gBattleStruct->blunderPolicy
|
if (gBattleStruct->blunderPolicy
|
||||||
&& IsBattlerAlive(battlerAtk)
|
&& IsBattlerAlive(battlerAtk)
|
||||||
&& CompareStat(battlerAtk, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(battlerAtk, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battlerAtk)))
|
||||||
{
|
{
|
||||||
gBattleStruct->blunderPolicy = FALSE;
|
gBattleStruct->blunderPolicy = FALSE;
|
||||||
SET_STATCHANGER(STAT_SPEED, 2, FALSE);
|
SET_STATCHANGER(STAT_SPEED, 2, FALSE);
|
||||||
@ -502,7 +502,7 @@ static enum ItemEffect TryThroatSpray(u32 battlerAtk)
|
|||||||
&& gMultiHitCounter == 0
|
&& gMultiHitCounter == 0
|
||||||
&& IsBattlerAlive(battlerAtk)
|
&& IsBattlerAlive(battlerAtk)
|
||||||
&& IsAnyTargetTurnDamaged(battlerAtk)
|
&& IsAnyTargetTurnDamaged(battlerAtk)
|
||||||
&& CompareStat(battlerAtk, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN)
|
&& CompareStat(battlerAtk, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battlerAtk))
|
||||||
&& !NoAliveMonsForEitherParty()) // Don't activate if battle will end
|
&& !NoAliveMonsForEitherParty()) // Don't activate if battle will end
|
||||||
{
|
{
|
||||||
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
||||||
@ -517,7 +517,7 @@ static enum ItemEffect DamagedStatBoostBerryEffect(u32 battlerDef, u32 battlerAt
|
|||||||
{
|
{
|
||||||
enum ItemEffect effect = ITEM_NO_EFFECT;
|
enum ItemEffect effect = ITEM_NO_EFFECT;
|
||||||
|
|
||||||
if (!IsBattlerAlive(battlerDef) || !CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (!IsBattlerAlive(battlerDef) || !CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(battlerDef)))
|
||||||
return effect;
|
return effect;
|
||||||
|
|
||||||
if (gBattleScripting.overrideBerryRequirements
|
if (gBattleScripting.overrideBerryRequirements
|
||||||
@ -970,7 +970,7 @@ static enum ItemEffect StatRaiseBerry(u32 battler, u32 itemId, enum Stat statId,
|
|||||||
enum ItemEffect effect = ITEM_NO_EFFECT;
|
enum ItemEffect effect = ITEM_NO_EFFECT;
|
||||||
enum Ability ability = GetBattlerAbility(battler);
|
enum Ability ability = GetBattlerAbility(battler);
|
||||||
|
|
||||||
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN)
|
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, ability)
|
||||||
&& HasEnoughHpToEatBerry(battler, ability, GetItemHoldEffectParam(itemId), itemId))
|
&& HasEnoughHpToEatBerry(battler, ability, GetItemHoldEffectParam(itemId), itemId))
|
||||||
{
|
{
|
||||||
gEffectBattler = gBattleScripting.battler = battler;
|
gEffectBattler = gBattleScripting.battler = battler;
|
||||||
@ -1011,17 +1011,17 @@ static enum ItemEffect RandomStatRaiseBerry(u32 battler, u32 itemId, ActivationT
|
|||||||
{
|
{
|
||||||
enum ItemEffect effect = ITEM_NO_EFFECT;
|
enum ItemEffect effect = ITEM_NO_EFFECT;
|
||||||
enum Stat stat;
|
enum Stat stat;
|
||||||
|
enum Ability ability = GetBattlerAbility(battler);
|
||||||
|
|
||||||
for (stat = STAT_ATK; stat < NUM_STATS; stat++)
|
for (stat = STAT_ATK; stat < NUM_STATS; stat++)
|
||||||
{
|
{
|
||||||
if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_LESS_THAN, ability))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stat == NUM_STATS)
|
if (stat == NUM_STATS)
|
||||||
return effect;
|
return effect;
|
||||||
|
|
||||||
enum Ability ability = GetBattlerAbility(battler);
|
|
||||||
if (HasEnoughHpToEatBerry(battler, ability, GetItemHoldEffectParam(itemId), itemId))
|
if (HasEnoughHpToEatBerry(battler, ability, GetItemHoldEffectParam(itemId), itemId))
|
||||||
{
|
{
|
||||||
u32 savedAttacker = gBattlerAttacker;
|
u32 savedAttacker = gBattlerAttacker;
|
||||||
|
|||||||
@ -5642,18 +5642,7 @@ static void HandleEndTurn_FinishBattle(void)
|
|||||||
|
|
||||||
for (i = 0; i < PARTY_SIZE; i++)
|
for (i = 0; i < PARTY_SIZE; i++)
|
||||||
{
|
{
|
||||||
bool8 changedForm = FALSE;
|
bool32 changedForm = TryRevertPartyMonFormChange(i);
|
||||||
|
|
||||||
// Appeared in battle and didn't faint
|
|
||||||
if (gBattleStruct->partyState[B_SIDE_PLAYER][i].sentOut && GetMonData(&gPlayerParty[i], MON_DATA_HP, NULL) != 0)
|
|
||||||
changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE_ENVIRONMENT);
|
|
||||||
|
|
||||||
if (!changedForm)
|
|
||||||
changedForm = TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE);
|
|
||||||
|
|
||||||
// Clear original species field
|
|
||||||
gBattleStruct->partyState[B_SIDE_PLAYER][i].changedSpecies = SPECIES_NONE;
|
|
||||||
gBattleStruct->partyState[B_SIDE_OPPONENT][i].changedSpecies = SPECIES_NONE;
|
|
||||||
|
|
||||||
// Recalculate the stats of every party member before the end
|
// Recalculate the stats of every party member before the end
|
||||||
if (!changedForm && B_RECALCULATE_STATS >= GEN_5)
|
if (!changedForm && B_RECALCULATE_STATS >= GEN_5)
|
||||||
|
|||||||
@ -370,7 +370,7 @@ static void Cmd_jumpifvolatile(void);
|
|||||||
static void Cmd_jumpifability(void);
|
static void Cmd_jumpifability(void);
|
||||||
static void Cmd_jumpifsideaffecting(void);
|
static void Cmd_jumpifsideaffecting(void);
|
||||||
static void Cmd_jumpifstat(void);
|
static void Cmd_jumpifstat(void);
|
||||||
static void Cmd_unused_0x21(void);
|
static void Cmd_jumpifstatignorecontrary(void);
|
||||||
static void Cmd_jumpbasedontype(void);
|
static void Cmd_jumpbasedontype(void);
|
||||||
static void Cmd_getexp(void);
|
static void Cmd_getexp(void);
|
||||||
static void Cmd_checkteamslost(void);
|
static void Cmd_checkteamslost(void);
|
||||||
@ -629,7 +629,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
|
|||||||
Cmd_jumpifability, //0x1E
|
Cmd_jumpifability, //0x1E
|
||||||
Cmd_jumpifsideaffecting, //0x1F
|
Cmd_jumpifsideaffecting, //0x1F
|
||||||
Cmd_jumpifstat, //0x20
|
Cmd_jumpifstat, //0x20
|
||||||
Cmd_unused_0x21, //0x21
|
Cmd_jumpifstatignorecontrary, //0x21
|
||||||
Cmd_jumpbasedontype, //0x22
|
Cmd_jumpbasedontype, //0x22
|
||||||
Cmd_getexp, //0x23
|
Cmd_getexp, //0x23
|
||||||
Cmd_checkteamslost, //0x24
|
Cmd_checkteamslost, //0x24
|
||||||
@ -4384,7 +4384,7 @@ static void Cmd_jumpifstat(void)
|
|||||||
u8 value = cmd->value;
|
u8 value = cmd->value;
|
||||||
u8 comparison = cmd->comparison;
|
u8 comparison = cmd->comparison;
|
||||||
|
|
||||||
ret = CompareStat(battler, stat, value, comparison);
|
ret = CompareStat(battler, stat, value, comparison, GetBattlerAbility(battler));
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||||
@ -4392,8 +4392,22 @@ static void Cmd_jumpifstat(void)
|
|||||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Cmd_unused_0x21(void)
|
static void Cmd_jumpifstatignorecontrary(void)
|
||||||
{
|
{
|
||||||
|
CMD_ARGS(u8 battler, u8 comparison, u8 stat, u8 value, const u8 *jumpInstr);
|
||||||
|
|
||||||
|
bool32 ret = 0;
|
||||||
|
u8 battler = GetBattlerForBattleScript(cmd->battler);
|
||||||
|
u8 stat = cmd->stat;
|
||||||
|
u8 value = cmd->value;
|
||||||
|
u8 comparison = cmd->comparison;
|
||||||
|
|
||||||
|
ret = CompareStat(battler, stat, value, comparison, ABILITY_NONE);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||||
|
else
|
||||||
|
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Cmd_jumpbasedontype(void)
|
static void Cmd_jumpbasedontype(void)
|
||||||
@ -5572,7 +5586,7 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move
|
|||||||
else if (abilityAtk == ABILITY_GRIM_NEIGH || abilityAtk == ABILITY_AS_ONE_SHADOW_RIDER)
|
else if (abilityAtk == ABILITY_GRIM_NEIGH || abilityAtk == ABILITY_AS_ONE_SHADOW_RIDER)
|
||||||
stat = STAT_SPATK;
|
stat = STAT_SPATK;
|
||||||
|
|
||||||
if (numMonsFainted && CompareStat(battlerAtk, stat, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (numMonsFainted && CompareStat(battlerAtk, stat, MAX_STAT_STAGE, CMP_LESS_THAN, abilityAtk))
|
||||||
{
|
{
|
||||||
gLastUsedAbility = abilityAtk;
|
gLastUsedAbility = abilityAtk;
|
||||||
if (abilityAtk == ABILITY_AS_ONE_ICE_RIDER)
|
if (abilityAtk == ABILITY_AS_ONE_ICE_RIDER)
|
||||||
@ -5612,17 +5626,17 @@ static bool32 HandleMoveEndAbilityBlock(u32 battlerAtk, u32 battlerDef, u32 move
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 numStatBuffs = 0;
|
u32 numStatBuffs = 0;
|
||||||
if (CompareStat(battlerAtk, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (CompareStat(battlerAtk, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, abilityAtk))
|
||||||
{
|
{
|
||||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_ATK) + STAT_ANIM_PLUS1;
|
gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_ATK) + STAT_ANIM_PLUS1;
|
||||||
numStatBuffs++;
|
numStatBuffs++;
|
||||||
}
|
}
|
||||||
if (CompareStat(battlerAtk, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (CompareStat(battlerAtk, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, abilityAtk))
|
||||||
{
|
{
|
||||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_SPATK) + STAT_ANIM_PLUS1;
|
gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_SPATK) + STAT_ANIM_PLUS1;
|
||||||
numStatBuffs++;
|
numStatBuffs++;
|
||||||
}
|
}
|
||||||
if (CompareStat(battlerAtk, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (CompareStat(battlerAtk, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, abilityAtk))
|
||||||
{
|
{
|
||||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_SPEED) + STAT_ANIM_PLUS1;
|
gBattleScripting.animArg1 = GET_STAT_BUFF_ID(STAT_SPEED) + STAT_ANIM_PLUS1;
|
||||||
numStatBuffs++;
|
numStatBuffs++;
|
||||||
@ -5853,7 +5867,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect)
|
|||||||
&& !IsBattlerAlive(gBattlerTarget)
|
&& !IsBattlerAlive(gBattlerTarget)
|
||||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||||
&& !NoAliveMonsForEitherParty()
|
&& !NoAliveMonsForEitherParty()
|
||||||
&& CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(gBattlerAttacker, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerAttacker)))
|
||||||
{
|
{
|
||||||
SET_STATCHANGER(STAT_ATK, GetGenConfig(GEN_CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE);
|
SET_STATCHANGER(STAT_ATK, GetGenConfig(GEN_CONFIG_FELL_STINGER_STAT_RAISE) >= GEN_7 ? 3 : 2, FALSE);
|
||||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK);
|
PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_ATK);
|
||||||
@ -6118,7 +6132,7 @@ static void Cmd_moveend(void)
|
|||||||
&& !IsBattlerAlly(gBattlerAttacker, gBattlerTarget)
|
&& !IsBattlerAlly(gBattlerAttacker, gBattlerTarget)
|
||||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||||
&& !IsBattleMoveStatus(gCurrentMove)
|
&& !IsBattleMoveStatus(gCurrentMove)
|
||||||
&& CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget)))
|
||||||
{
|
{
|
||||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||||
BattleScriptCall(BattleScript_RageIsBuilding);
|
BattleScriptCall(BattleScript_RageIsBuilding);
|
||||||
@ -11912,7 +11926,7 @@ static void Cmd_jumpifconfusedandstatmaxed(void)
|
|||||||
CMD_ARGS(u8 stat, const u8 *jumpInstr);
|
CMD_ARGS(u8 stat, const u8 *jumpInstr);
|
||||||
|
|
||||||
if (gBattleMons[gBattlerTarget].volatiles.confusionTurns > 0
|
if (gBattleMons[gBattlerTarget].volatiles.confusionTurns > 0
|
||||||
&& !CompareStat(gBattlerTarget, cmd->stat, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& !CompareStat(gBattlerTarget, cmd->stat, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget)))
|
||||||
gBattlescriptCurrInstr = cmd->jumpInstr; // Fails if we're confused AND stat cannot be raised
|
gBattlescriptCurrInstr = cmd->jumpInstr; // Fails if we're confused AND stat cannot be raised
|
||||||
else
|
else
|
||||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||||
@ -13892,6 +13906,8 @@ static void Cmd_givecaughtmon(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
//Before sending to PC, we revert battle form
|
||||||
|
TryRevertPartyMonFormChange(gSelectedMonPartyId);
|
||||||
// Mon chosen, try to put it in the PC
|
// Mon chosen, try to put it in the PC
|
||||||
if (CopyMonToPC(&gPlayerParty[gSelectedMonPartyId]) == MON_GIVEN_TO_PC)
|
if (CopyMonToPC(&gPlayerParty[gSelectedMonPartyId]) == MON_GIVEN_TO_PC)
|
||||||
{
|
{
|
||||||
@ -15690,7 +15706,7 @@ void BS_CanTarShotWork(void)
|
|||||||
NATIVE_ARGS(const u8 *failInstr);
|
NATIVE_ARGS(const u8 *failInstr);
|
||||||
// Tar Shot will fail if it's already been used on the target or if its speed can't be lowered further
|
// Tar Shot will fail if it's already been used on the target or if its speed can't be lowered further
|
||||||
if (!gDisableStructs[gBattlerTarget].tarShot
|
if (!gDisableStructs[gBattlerTarget].tarShot
|
||||||
&& CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget)))
|
||||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||||
else
|
else
|
||||||
gBattlescriptCurrInstr = cmd->failInstr;
|
gBattlescriptCurrInstr = cmd->failInstr;
|
||||||
@ -16705,7 +16721,7 @@ void BS_TryAcupressure(void)
|
|||||||
u32 bits = 0;
|
u32 bits = 0;
|
||||||
for (enum Stat stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++)
|
for (enum Stat stat = STAT_ATK; stat < NUM_BATTLE_STATS; stat++)
|
||||||
{
|
{
|
||||||
if (CompareStat(gBattlerTarget, stat, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (CompareStat(gBattlerTarget, stat, MAX_STAT_STAGE, CMP_LESS_THAN, GetBattlerAbility(gBattlerTarget)))
|
||||||
bits |= 1u << stat;
|
bits |= 1u << stat;
|
||||||
}
|
}
|
||||||
if (bits)
|
if (bits)
|
||||||
@ -17104,10 +17120,11 @@ void BS_TryActivateSoulheart(void)
|
|||||||
while (gBattleStruct->soulheartBattlerId < gBattlersCount)
|
while (gBattleStruct->soulheartBattlerId < gBattlersCount)
|
||||||
{
|
{
|
||||||
gBattleScripting.battler = gBattleStruct->soulheartBattlerId++;
|
gBattleScripting.battler = gBattleStruct->soulheartBattlerId++;
|
||||||
if (GetBattlerAbility(gBattleScripting.battler) == ABILITY_SOUL_HEART
|
u32 ability = GetBattlerAbility(gBattleScripting.battler);
|
||||||
|
if (ability == ABILITY_SOUL_HEART
|
||||||
&& IsBattlerAlive(gBattleScripting.battler)
|
&& IsBattlerAlive(gBattleScripting.battler)
|
||||||
&& !NoAliveMonsForEitherParty()
|
&& !NoAliveMonsForEitherParty()
|
||||||
&& CompareStat(gBattleScripting.battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(gBattleScripting.battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, ability))
|
||||||
{
|
{
|
||||||
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
||||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK);
|
PREPARE_STAT_BUFFER(gBattleTextBuff1, STAT_SPATK);
|
||||||
@ -17922,11 +17939,12 @@ void BS_SetAttackerToStickyWebUser(void)
|
|||||||
void BS_CutOneThirdHpAndRaiseStats(void)
|
void BS_CutOneThirdHpAndRaiseStats(void)
|
||||||
{
|
{
|
||||||
NATIVE_ARGS(const u8 *failInstr);
|
NATIVE_ARGS(const u8 *failInstr);
|
||||||
|
|
||||||
bool32 atLeastOneStatBoosted = FALSE;
|
bool32 atLeastOneStatBoosted = FALSE;
|
||||||
|
u32 ability = GetBattlerAbility(gBattlerAttacker);
|
||||||
|
|
||||||
for (u32 stat = 1; stat < NUM_STATS; stat++)
|
for (u32 stat = 1; stat < NUM_STATS; stat++)
|
||||||
{
|
{
|
||||||
if (CompareStat(gBattlerAttacker, stat, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (CompareStat(gBattlerAttacker, stat, MAX_STAT_STAGE, CMP_LESS_THAN, ability))
|
||||||
{
|
{
|
||||||
atLeastOneStatBoosted = TRUE;
|
atLeastOneStatBoosted = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -66,6 +66,7 @@ static u32 GetFlingPowerFromItemId(u32 itemId);
|
|||||||
static void SetRandomMultiHitCounter();
|
static void SetRandomMultiHitCounter();
|
||||||
static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, enum Ability abilityDef, enum Ability abilityAffected, const u8 *battleScript, enum FunctionCallOption option);
|
static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, enum Ability abilityDef, enum Ability abilityAffected, const u8 *battleScript, enum FunctionCallOption option);
|
||||||
static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum FunctionCallOption option);
|
static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum FunctionCallOption option);
|
||||||
|
static bool32 IsOpposingSideEmpty(u32 battler);
|
||||||
|
|
||||||
// Submoves
|
// Submoves
|
||||||
static u32 GetMirrorMoveMove(void);
|
static u32 GetMirrorMoveMove(void);
|
||||||
@ -1237,7 +1238,7 @@ void PrepareStringBattle(enum StringID stringId, u32 battler)
|
|||||||
case STRINGID_PKMNCUTSATTACKWITH:
|
case STRINGID_PKMNCUTSATTACKWITH:
|
||||||
if (GetGenConfig(GEN_CONFIG_UPDATED_INTIMIDATE) >= GEN_8
|
if (GetGenConfig(GEN_CONFIG_UPDATED_INTIMIDATE) >= GEN_8
|
||||||
&& targetAbility == ABILITY_RATTLED
|
&& targetAbility == ABILITY_RATTLED
|
||||||
&& CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(gBattlerTarget, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, targetAbility))
|
||||||
{
|
{
|
||||||
gBattlerAbility = gBattlerTarget;
|
gBattlerAbility = gBattlerTarget;
|
||||||
BattleScriptCall(BattleScript_AbilityRaisesDefenderStat);
|
BattleScriptCall(BattleScript_AbilityRaisesDefenderStat);
|
||||||
@ -1763,13 +1764,13 @@ u32 GetBattlerAffectionHearts(u32 battler)
|
|||||||
// gBattlerAttacker is the battler that's trying to raise their stats and due to limitations of RandomUniformExcept, cannot be an argument
|
// gBattlerAttacker is the battler that's trying to raise their stats and due to limitations of RandomUniformExcept, cannot be an argument
|
||||||
bool32 MoodyCantRaiseStat(u32 stat)
|
bool32 MoodyCantRaiseStat(u32 stat)
|
||||||
{
|
{
|
||||||
return CompareStat(gBattlerAttacker, stat, MAX_STAT_STAGE, CMP_EQUAL);
|
return CompareStat(gBattlerAttacker, stat, MAX_STAT_STAGE, CMP_EQUAL, GetBattlerAbility(gBattlerAttacker));
|
||||||
}
|
}
|
||||||
|
|
||||||
// gBattlerAttacker is the battler that's trying to lower their stats and due to limitations of RandomUniformExcept, cannot be an argument
|
// gBattlerAttacker is the battler that's trying to lower their stats and due to limitations of RandomUniformExcept, cannot be an argument
|
||||||
bool32 MoodyCantLowerStat(u32 stat)
|
bool32 MoodyCantLowerStat(u32 stat)
|
||||||
{
|
{
|
||||||
return stat == GET_STAT_BUFF_ID(gBattleScripting.statChanger) || CompareStat(gBattlerAttacker, stat, MIN_STAT_STAGE, CMP_EQUAL);
|
return stat == GET_STAT_BUFF_ID(gBattleScripting.statChanger) || CompareStat(gBattlerAttacker, stat, MIN_STAT_STAGE, CMP_EQUAL, GetBattlerAbility(gBattlerAttacker));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TryToRevertMimicryAndFlags(void)
|
void TryToRevertMimicryAndFlags(void)
|
||||||
@ -3540,7 +3541,7 @@ bool32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, enum Ability ability
|
|||||||
break;
|
break;
|
||||||
case MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY:
|
case MOVE_ABSORBED_BY_STAT_INCREASE_ABILITY:
|
||||||
gBattleStruct->pledgeMove = FALSE;
|
gBattleStruct->pledgeMove = FALSE;
|
||||||
if (!CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (!CompareStat(battlerDef, statId, MAX_STAT_STAGE, CMP_LESS_THAN, abilityDef))
|
||||||
{
|
{
|
||||||
battleScript = BattleScript_MonMadeMoveUseless;
|
battleScript = BattleScript_MonMadeMoveUseless;
|
||||||
}
|
}
|
||||||
@ -4119,7 +4120,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
|
|
||||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||||
|
|
||||||
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (CompareStat(battler, statId, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||||
{
|
{
|
||||||
SET_STATCHANGER(statId, 1, FALSE);
|
SET_STATCHANGER(statId, 1, FALSE);
|
||||||
SaveBattlerAttacker(gBattlerAttacker);
|
SaveBattlerAttacker(gBattlerAttacker);
|
||||||
@ -4272,7 +4273,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ABILITY_INTIMIDATE:
|
case ABILITY_INTIMIDATE:
|
||||||
if (!gSpecialStatuses[battler].switchInAbilityDone)
|
if (!gSpecialStatuses[battler].switchInAbilityDone && !IsOpposingSideEmpty(battler))
|
||||||
{
|
{
|
||||||
SaveBattlerAttacker(gBattlerAttacker);
|
SaveBattlerAttacker(gBattlerAttacker);
|
||||||
gBattlerAttacker = battler;
|
gBattlerAttacker = battler;
|
||||||
@ -4284,7 +4285,8 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
break;
|
break;
|
||||||
case ABILITY_SUPERSWEET_SYRUP:
|
case ABILITY_SUPERSWEET_SYRUP:
|
||||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||||
&& !GetBattlerPartyState(battler)->supersweetSyrup)
|
&& !GetBattlerPartyState(battler)->supersweetSyrup
|
||||||
|
&& !IsOpposingSideEmpty(battler))
|
||||||
{
|
{
|
||||||
SaveBattlerAttacker(gBattlerAttacker);
|
SaveBattlerAttacker(gBattlerAttacker);
|
||||||
gBattlerAttacker = battler;
|
gBattlerAttacker = battler;
|
||||||
@ -4331,7 +4333,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
if (GetGenConfig(GEN_INTREPID_SWORD) == GEN_9)
|
if (GetGenConfig(GEN_INTREPID_SWORD) == GEN_9)
|
||||||
GetBattlerPartyState(battler)->intrepidSwordBoost = TRUE;
|
GetBattlerPartyState(battler)->intrepidSwordBoost = TRUE;
|
||||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||||
if (CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||||
{
|
{
|
||||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
||||||
@ -4346,7 +4348,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
if (GetGenConfig(GEN_DAUNTLESS_SHIELD) == GEN_9)
|
if (GetGenConfig(GEN_DAUNTLESS_SHIELD) == GEN_9)
|
||||||
GetBattlerPartyState(battler)->dauntlessShieldBoost = TRUE;
|
GetBattlerPartyState(battler)->dauntlessShieldBoost = TRUE;
|
||||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||||
if (CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||||
{
|
{
|
||||||
SET_STATCHANGER(STAT_DEF, 1, FALSE);
|
SET_STATCHANGER(STAT_DEF, 1, FALSE);
|
||||||
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
BattleScriptPushCursorAndCallback(BattleScript_BattlerAbilityStatRaiseOnSwitchIn);
|
||||||
@ -4356,7 +4358,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
break;
|
break;
|
||||||
case ABILITY_WIND_RIDER:
|
case ABILITY_WIND_RIDER:
|
||||||
if (!gSpecialStatuses[battler].switchInAbilityDone
|
if (!gSpecialStatuses[battler].switchInAbilityDone
|
||||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)
|
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)
|
||||||
&& gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TAILWIND)
|
&& gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TAILWIND)
|
||||||
{
|
{
|
||||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||||
@ -4496,7 +4498,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
else //ABILITY_EMBODY_ASPECT_TEAL_MASK
|
else //ABILITY_EMBODY_ASPECT_TEAL_MASK
|
||||||
stat = STAT_SPEED;
|
stat = STAT_SPEED;
|
||||||
|
|
||||||
if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_EQUAL))
|
if (CompareStat(battler, stat, MAX_STAT_STAGE, CMP_EQUAL, gLastUsedAbility))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
gSpecialStatuses[battler].switchInAbilityDone = TRUE;
|
||||||
@ -4646,7 +4648,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ABILITY_SPEED_BOOST:
|
case ABILITY_SPEED_BOOST:
|
||||||
if (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) && gDisableStructs[battler].isFirstTurn != 2)
|
if (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility) && gDisableStructs[battler].isFirstTurn != 2)
|
||||||
{
|
{
|
||||||
SaveBattlerAttacker(gBattlerAttacker);
|
SaveBattlerAttacker(gBattlerAttacker);
|
||||||
SET_STATCHANGER(STAT_SPEED, 1, FALSE);
|
SET_STATCHANGER(STAT_SPEED, 1, FALSE);
|
||||||
@ -4663,9 +4665,9 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
|
|
||||||
for (i = STAT_ATK; i < statsNum; i++)
|
for (i = STAT_ATK; i < statsNum; i++)
|
||||||
{
|
{
|
||||||
if (CompareStat(battler, i, MIN_STAT_STAGE, CMP_GREATER_THAN))
|
if (CompareStat(battler, i, MIN_STAT_STAGE, CMP_GREATER_THAN, gLastUsedAbility))
|
||||||
validToLower |= 1u << i;
|
validToLower |= 1u << i;
|
||||||
if (CompareStat(battler, i, MAX_STAT_STAGE, CMP_LESS_THAN))
|
if (CompareStat(battler, i, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||||
validToRaise |= 1u << i;
|
validToRaise |= 1u << i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4807,7 +4809,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
if (IsBattlerTurnDamaged(battler)
|
if (IsBattlerTurnDamaged(battler)
|
||||||
&& IsBattlerAlive(battler)
|
&& IsBattlerAlive(battler)
|
||||||
&& HadMoreThanHalfHpNowDoesnt(battler)
|
&& HadMoreThanHalfHpNowDoesnt(battler)
|
||||||
&& CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(battler, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||||
{
|
{
|
||||||
gEffectBattler = gBattlerAbility = battler;
|
gEffectBattler = gBattlerAbility = battler;
|
||||||
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
SET_STATCHANGER(STAT_SPATK, 1, FALSE);
|
||||||
@ -4836,7 +4838,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
if (IsBattlerTurnDamaged(battler)
|
if (IsBattlerTurnDamaged(battler)
|
||||||
&& IsBattlerAlive(battler)
|
&& IsBattlerAlive(battler)
|
||||||
&& moveType == TYPE_DARK
|
&& moveType == TYPE_DARK
|
||||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||||
{
|
{
|
||||||
gEffectBattler = gBattlerAbility = battler;
|
gEffectBattler = gBattlerAbility = battler;
|
||||||
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
SET_STATCHANGER(STAT_ATK, 1, FALSE);
|
||||||
@ -4848,7 +4850,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
if (IsBattlerTurnDamaged(battler)
|
if (IsBattlerTurnDamaged(battler)
|
||||||
&& IsBattlerAlive(battler)
|
&& IsBattlerAlive(battler)
|
||||||
&& (moveType == TYPE_DARK || moveType == TYPE_BUG || moveType == TYPE_GHOST)
|
&& (moveType == TYPE_DARK || moveType == TYPE_BUG || moveType == TYPE_GHOST)
|
||||||
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||||
{
|
{
|
||||||
gEffectBattler = gBattlerAbility = battler;
|
gEffectBattler = gBattlerAbility = battler;
|
||||||
SET_STATCHANGER(STAT_SPEED, 1, FALSE);
|
SET_STATCHANGER(STAT_SPEED, 1, FALSE);
|
||||||
@ -4860,7 +4862,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
if (IsBattlerTurnDamaged(battler)
|
if (IsBattlerTurnDamaged(battler)
|
||||||
&& IsBattlerAlive(battler)
|
&& IsBattlerAlive(battler)
|
||||||
&& moveType == TYPE_WATER
|
&& moveType == TYPE_WATER
|
||||||
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||||
{
|
{
|
||||||
gEffectBattler = gBattlerAbility = battler;
|
gEffectBattler = gBattlerAbility = battler;
|
||||||
SET_STATCHANGER(STAT_DEF, 2, FALSE);
|
SET_STATCHANGER(STAT_DEF, 2, FALSE);
|
||||||
@ -4872,7 +4874,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
if (gBattlerAttacker != gBattlerTarget
|
if (gBattlerAttacker != gBattlerTarget
|
||||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||||
&& IsBattlerAlive(battler)
|
&& IsBattlerAlive(battler)
|
||||||
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||||
{
|
{
|
||||||
gEffectBattler = gBattlerAbility = battler;
|
gEffectBattler = gBattlerAbility = battler;
|
||||||
SET_STATCHANGER(STAT_DEF, 1, FALSE);
|
SET_STATCHANGER(STAT_DEF, 1, FALSE);
|
||||||
@ -4884,8 +4886,8 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
if (IsBattlerTurnDamaged(battler)
|
if (IsBattlerTurnDamaged(battler)
|
||||||
&& IsBattlerAlive(battler)
|
&& IsBattlerAlive(battler)
|
||||||
&& IsBattleMovePhysical(gCurrentMove)
|
&& IsBattleMovePhysical(gCurrentMove)
|
||||||
&& (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) // Don't activate if both Speed and Defense cannot be raised.
|
&& (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility) // Don't activate if both Speed and Defense cannot be raised.
|
||||||
|| CompareStat(battler, STAT_DEF, MIN_STAT_STAGE, CMP_GREATER_THAN)))
|
|| CompareStat(battler, STAT_DEF, MIN_STAT_STAGE, CMP_GREATER_THAN, gLastUsedAbility)))
|
||||||
{
|
{
|
||||||
if (GetMoveEffect(gCurrentMove) == EFFECT_HIT_ESCAPE && CanBattlerSwitch(gBattlerAttacker))
|
if (GetMoveEffect(gCurrentMove) == EFFECT_HIT_ESCAPE && CanBattlerSwitch(gBattlerAttacker))
|
||||||
gProtectStructs[battler].disableEjectPack = TRUE; // Set flag for target
|
gProtectStructs[battler].disableEjectPack = TRUE; // Set flag for target
|
||||||
@ -4964,7 +4966,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
if (gSpecialStatuses[battler].criticalHit
|
if (gSpecialStatuses[battler].criticalHit
|
||||||
&& IsBattlerTurnDamaged(battler)
|
&& IsBattlerTurnDamaged(battler)
|
||||||
&& IsBattlerAlive(battler)
|
&& IsBattlerAlive(battler)
|
||||||
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN))
|
&& CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility))
|
||||||
{
|
{
|
||||||
SET_STATCHANGER(STAT_ATK, MAX_STAT_STAGE - gBattleMons[battler].statStages[STAT_ATK], FALSE);
|
SET_STATCHANGER(STAT_ATK, MAX_STAT_STAGE - gBattleMons[battler].statStages[STAT_ATK], FALSE);
|
||||||
BattleScriptCall(BattleScript_TargetsStatWasMaxedOut);
|
BattleScriptCall(BattleScript_TargetsStatWasMaxedOut);
|
||||||
@ -4974,7 +4976,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
case ABILITY_GOOEY:
|
case ABILITY_GOOEY:
|
||||||
case ABILITY_TANGLING_HAIR:
|
case ABILITY_TANGLING_HAIR:
|
||||||
if (IsBattlerAlive(gBattlerAttacker)
|
if (IsBattlerAlive(gBattlerAttacker)
|
||||||
&& (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR)
|
&& (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN, gLastUsedAbility) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR)
|
||||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||||
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move))
|
&& !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move))
|
||||||
@ -5178,7 +5180,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
case ABILITY_STEAM_ENGINE:
|
case ABILITY_STEAM_ENGINE:
|
||||||
if (IsBattlerTurnDamaged(gBattlerTarget)
|
if (IsBattlerTurnDamaged(gBattlerTarget)
|
||||||
&& IsBattlerAlive(battler)
|
&& IsBattlerAlive(battler)
|
||||||
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)
|
&& CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)
|
||||||
&& (moveType == TYPE_FIRE || moveType == TYPE_WATER))
|
&& (moveType == TYPE_FIRE || moveType == TYPE_WATER))
|
||||||
{
|
{
|
||||||
gEffectBattler = gBattlerAbility = battler;
|
gEffectBattler = gBattlerAbility = battler;
|
||||||
@ -5260,7 +5262,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab
|
|||||||
case ABILITY_THERMAL_EXCHANGE:
|
case ABILITY_THERMAL_EXCHANGE:
|
||||||
if (IsBattlerTurnDamaged(gBattlerTarget)
|
if (IsBattlerTurnDamaged(gBattlerTarget)
|
||||||
&& IsBattlerAlive(gBattlerTarget)
|
&& IsBattlerAlive(gBattlerTarget)
|
||||||
&& CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)
|
&& CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN, gLastUsedAbility)
|
||||||
&& moveType == TYPE_FIRE)
|
&& moveType == TYPE_FIRE)
|
||||||
{
|
{
|
||||||
gEffectBattler = gBattlerAbility = gBattlerTarget;
|
gEffectBattler = gBattlerAbility = gBattlerTarget;
|
||||||
@ -9052,17 +9054,46 @@ bool32 CanBattlerFormChange(u32 battler, enum FormChanges method)
|
|||||||
if (gBattleMons[battler].volatiles.transformed
|
if (gBattleMons[battler].volatiles.transformed
|
||||||
&& B_TRANSFORM_FORM_CHANGES >= GEN_5)
|
&& B_TRANSFORM_FORM_CHANGES >= GEN_5)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
// Mega Evolved and Ultra Bursted Pokémon should always revert to normal upon fainting or ending the battle.
|
|
||||||
if ((IsBattlerMegaEvolved(battler) || IsBattlerUltraBursted(battler) || IsBattlerInTeraForm(battler)) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE))
|
switch (method)
|
||||||
|
{
|
||||||
|
case FORM_CHANGE_END_BATTLE:
|
||||||
|
if (IsBattlerPrimalReverted(battler))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
else if (IsBattlerPrimalReverted(battler) && (method == FORM_CHANGE_END_BATTLE))
|
// Fallthrough
|
||||||
|
case FORM_CHANGE_FAINT:
|
||||||
|
if (IsBattlerMegaEvolved(battler) || IsBattlerUltraBursted(battler) || IsBattlerInTeraForm(battler) || IsGigantamaxed(battler))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
// Gigantamaxed Pokemon should revert upon fainting, switching, or ending the battle.
|
break;
|
||||||
else if (IsGigantamaxed(battler) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_BATTLE_SWITCH || method == FORM_CHANGE_END_BATTLE))
|
case FORM_CHANGE_BATTLE_SWITCH:
|
||||||
|
if (IsGigantamaxed(battler))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
else if (GetActiveGimmick(battler) == GIMMICK_TERA && GetBattlerAbility(battler) == ABILITY_HUNGER_SWITCH)
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
return DoesSpeciesHaveFormChangeMethod(gBattleMons[battler].species, method);
|
return DoesSpeciesHaveFormChangeMethod(gBattleMons[battler].species, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool32 TryRevertPartyMonFormChange(u32 partyIndex)
|
||||||
|
{
|
||||||
|
bool32 changedForm = FALSE;
|
||||||
|
|
||||||
|
// Appeared in battle and didn't faint
|
||||||
|
if (gBattleStruct->partyState[B_SIDE_PLAYER][partyIndex].sentOut && GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP, NULL) != 0)
|
||||||
|
changedForm = TryFormChange(partyIndex, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE_ENVIRONMENT);
|
||||||
|
|
||||||
|
if (!changedForm)
|
||||||
|
changedForm = TryFormChange(partyIndex, B_SIDE_PLAYER, FORM_CHANGE_END_BATTLE);
|
||||||
|
|
||||||
|
// Clear original species field
|
||||||
|
gBattleStruct->partyState[B_SIDE_PLAYER][partyIndex].changedSpecies = SPECIES_NONE;
|
||||||
|
|
||||||
|
return changedForm;
|
||||||
|
}
|
||||||
|
|
||||||
bool32 TryBattleFormChange(u32 battler, enum FormChanges method)
|
bool32 TryBattleFormChange(u32 battler, enum FormChanges method)
|
||||||
{
|
{
|
||||||
u32 monId = gBattlerPartyIndexes[battler];
|
u32 monId = gBattlerPartyIndexes[battler];
|
||||||
@ -9076,7 +9107,7 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method)
|
|||||||
targetSpecies = GetBattleFormChangeTargetSpecies(battler, method);
|
targetSpecies = GetBattleFormChangeTargetSpecies(battler, method);
|
||||||
if (targetSpecies == currentSpecies)
|
if (targetSpecies == currentSpecies)
|
||||||
targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0);
|
targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0);
|
||||||
if (targetSpecies != currentSpecies)
|
if (targetSpecies != currentSpecies && targetSpecies != SPECIES_NONE)
|
||||||
{
|
{
|
||||||
// Saves the original species on the first form change.
|
// Saves the original species on the first form change.
|
||||||
|
|
||||||
@ -9093,17 +9124,22 @@ bool32 TryBattleFormChange(u32 battler, enum FormChanges method)
|
|||||||
{
|
{
|
||||||
bool32 restoreSpecies = FALSE;
|
bool32 restoreSpecies = FALSE;
|
||||||
|
|
||||||
// Mega Evolved and Ultra Bursted Pokémon should always revert to normal upon fainting or ending the battle, so no need to add it to the form change tables.
|
switch (method)
|
||||||
if ((IsBattlerMegaEvolved(battler) || IsBattlerUltraBursted(battler) || IsBattlerInTeraForm(battler)) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_END_BATTLE))
|
{
|
||||||
|
case FORM_CHANGE_END_BATTLE:
|
||||||
restoreSpecies = TRUE;
|
restoreSpecies = TRUE;
|
||||||
|
break;
|
||||||
// Unlike Megas, Primal Reversion isn't canceled on fainting.
|
case FORM_CHANGE_FAINT:
|
||||||
else if (IsBattlerPrimalReverted(battler) && (method == FORM_CHANGE_END_BATTLE))
|
if (IsBattlerMegaEvolved(battler) || IsBattlerUltraBursted(battler) || IsBattlerInTeraForm(battler) || IsGigantamaxed(battler))
|
||||||
restoreSpecies = TRUE;
|
restoreSpecies = TRUE;
|
||||||
|
break;
|
||||||
// Gigantamax Pokemon have their forms reverted after fainting, switching, or ending the battle.
|
case FORM_CHANGE_BATTLE_SWITCH:
|
||||||
else if (IsGigantamaxed(battler) && (method == FORM_CHANGE_FAINT || method == FORM_CHANGE_BATTLE_SWITCH || method == FORM_CHANGE_END_BATTLE))
|
if (IsGigantamaxed(battler))
|
||||||
restoreSpecies = TRUE;
|
restoreSpecies = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (restoreSpecies)
|
if (restoreSpecies)
|
||||||
{
|
{
|
||||||
@ -9674,14 +9710,14 @@ bool32 TestIfSheerForceAffected(u32 battler, u16 move)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This function is the body of "jumpifstat", but can be used dynamically in a function
|
// This function is the body of "jumpifstat", but can be used dynamically in a function
|
||||||
bool32 CompareStat(u32 battler, enum Stat statId, u8 cmpTo, u8 cmpKind)
|
bool32 CompareStat(u32 battler, enum Stat statId, u8 cmpTo, u8 cmpKind, enum Ability ability)
|
||||||
{
|
{
|
||||||
bool32 ret = FALSE;
|
bool32 ret = FALSE;
|
||||||
u8 statValue = gBattleMons[battler].statStages[statId];
|
u8 statValue = gBattleMons[battler].statStages[statId];
|
||||||
|
|
||||||
// Because this command is used as a way of checking if a stat can be lowered/raised,
|
// Because this command is used as a way of checking if a stat can be lowered/raised,
|
||||||
// we need to do some modification at run-time.
|
// we need to do some modification at run-time.
|
||||||
if (GetBattlerAbility(battler) == ABILITY_CONTRARY)
|
if (ability == ABILITY_CONTRARY)
|
||||||
{
|
{
|
||||||
if (cmpKind == CMP_GREATER_THAN)
|
if (cmpKind == CMP_GREATER_THAN)
|
||||||
cmpKind = CMP_LESS_THAN;
|
cmpKind = CMP_LESS_THAN;
|
||||||
@ -10772,6 +10808,21 @@ bool32 HasPartnerTrainer(u32 battler)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool32 IsOpposingSideEmpty(u32 battler)
|
||||||
|
{
|
||||||
|
u32 oppositeBattler = BATTLE_OPPOSITE(battler);
|
||||||
|
|
||||||
|
if (IsBattlerAlive(oppositeBattler))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!IsDoubleBattle())
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (IsBattlerAlive(BATTLE_PARTNER(oppositeBattler)))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static u32 GetMirrorMoveMove(void)
|
static u32 GetMirrorMoveMove(void)
|
||||||
{
|
{
|
||||||
s32 i, validMovesCount;
|
s32 i, validMovesCount;
|
||||||
|
|||||||
@ -1306,15 +1306,18 @@ bool32 CannotUseItemsInBattle(u16 itemId, struct Pokemon *mon)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EFFECT_ITEM_INCREASE_ALL_STATS:
|
case EFFECT_ITEM_INCREASE_ALL_STATS:
|
||||||
|
{
|
||||||
|
u32 ability = GetBattlerAbility(gBattlerInMenuId);
|
||||||
for (i = STAT_ATK; i < NUM_STATS; i++)
|
for (i = STAT_ATK; i < NUM_STATS; i++)
|
||||||
{
|
{
|
||||||
if (CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL))
|
if (CompareStat(gBattlerInMenuId, i, MAX_STAT_STAGE, CMP_EQUAL, ability))
|
||||||
{
|
{
|
||||||
cannotUse = TRUE;
|
cannotUse = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case EFFECT_ITEM_RESTORE_HP:
|
case EFFECT_ITEM_RESTORE_HP:
|
||||||
if (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP))
|
if (hp == 0 || hp == GetMonData(mon, MON_DATA_MAX_HP))
|
||||||
cannotUse = TRUE;
|
cannotUse = TRUE;
|
||||||
|
|||||||
@ -1511,7 +1511,7 @@ static void HandleChooseMonSelection(u8 taskId, s8 *slotPtr)
|
|||||||
}
|
}
|
||||||
case PARTY_ACTION_SEND_MON_TO_BOX:
|
case PARTY_ACTION_SEND_MON_TO_BOX:
|
||||||
{
|
{
|
||||||
u8 partyId = GetPartyIdFromBattleSlot((u8)*slotPtr);
|
u8 partyId = (u8)*slotPtr;
|
||||||
if (partyId == 0 || ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && partyId == 1))
|
if (partyId == 0 || ((gBattleTypeFlags & BATTLE_TYPE_DOUBLE) && partyId == 1))
|
||||||
{
|
{
|
||||||
// Can't select if mon is currently on the field
|
// Can't select if mon is currently on the field
|
||||||
@ -1538,7 +1538,7 @@ static void HandleChooseMonSelection(u8 taskId, s8 *slotPtr)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PlaySE(SE_SELECT);
|
PlaySE(SE_SELECT);
|
||||||
gSelectedMonPartyId = partyId;
|
gSelectedMonPartyId = GetPartyIdFromBattleSlot(partyId);
|
||||||
Task_ClosePartyMenu(taskId);
|
Task_ClosePartyMenu(taskId);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -399,6 +399,7 @@ bool8 CheckForTrainersWantingBattle(void)
|
|||||||
if (numTrainers == 0xFF) // non-trainerbattle script
|
if (numTrainers == 0xFF) // non-trainerbattle script
|
||||||
{
|
{
|
||||||
u32 objectEventId = gApproachingTrainers[gNoOfApproachingTrainers - 1].objectEventId;
|
u32 objectEventId = gApproachingTrainers[gNoOfApproachingTrainers - 1].objectEventId;
|
||||||
|
gApproachingTrainers[gNoOfApproachingTrainers - 1].trainerScriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId);
|
||||||
gSelectedObjectEvent = objectEventId;
|
gSelectedObjectEvent = objectEventId;
|
||||||
gSpecialVar_LastTalked = gObjectEvents[objectEventId].localId;
|
gSpecialVar_LastTalked = gObjectEvents[objectEventId].localId;
|
||||||
ScriptContext_SetupScript(EventScript_ObjectApproachPlayer);
|
ScriptContext_SetupScript(EventScript_ObjectApproachPlayer);
|
||||||
|
|||||||
@ -53,7 +53,6 @@ SINGLE_BATTLE_TEST("Hunger Switch does not switch Morpeko's form when Terastalli
|
|||||||
|
|
||||||
SINGLE_BATTLE_TEST("Hunger Switch does not switch Morpeko's form after switching out while Terastallized")
|
SINGLE_BATTLE_TEST("Hunger Switch does not switch Morpeko's form after switching out while Terastallized")
|
||||||
{
|
{
|
||||||
KNOWN_FAILING; // #7062
|
|
||||||
GIVEN {
|
GIVEN {
|
||||||
ASSUME(GetMoveEffect(MOVE_ROAR) == EFFECT_ROAR);
|
ASSUME(GetMoveEffect(MOVE_ROAR) == EFFECT_ROAR);
|
||||||
PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); TeraType(TYPE_NORMAL); }
|
PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); TeraType(TYPE_NORMAL); }
|
||||||
|
|||||||
@ -240,6 +240,7 @@ DOUBLE_BATTLE_TEST("Intimidate is not going to trigger if a mon switches out thr
|
|||||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_HEALING_WISH, opponentRight);
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_HEALING_WISH, opponentRight);
|
||||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, playerLeft);
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, playerLeft);
|
||||||
HP_BAR(opponentLeft);
|
HP_BAR(opponentLeft);
|
||||||
|
NOT ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
|
||||||
MESSAGE("2 sent out Treecko!");
|
MESSAGE("2 sent out Treecko!");
|
||||||
MESSAGE("2 sent out Torchic!");
|
MESSAGE("2 sent out Torchic!");
|
||||||
NOT ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
|
NOT ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
|
||||||
@ -264,7 +265,7 @@ SINGLE_BATTLE_TEST("Intimidate activates when it's no longer effected by Neutral
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SINGLE_BATTLE_TEST("Intimidate activates when it's no longer affected by Neutralizing Gas - switching moves")
|
DOUBLE_BATTLE_TEST("Intimidate activates when it's no longer affected by Neutralizing Gas - switching moves")
|
||||||
{
|
{
|
||||||
u32 move;
|
u32 move;
|
||||||
PARAMETRIZE { move = MOVE_U_TURN; }
|
PARAMETRIZE { move = MOVE_U_TURN; }
|
||||||
@ -276,19 +277,24 @@ SINGLE_BATTLE_TEST("Intimidate activates when it's no longer affected by Neutral
|
|||||||
ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS);
|
ASSUME(GetMoveEffect(MOVE_BATON_PASS) == EFFECT_BATON_PASS);
|
||||||
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
|
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); }
|
||||||
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
PLAYER(SPECIES_WOBBUFFET) { HP(1); }
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); }
|
OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
} WHEN {
|
} WHEN {
|
||||||
TURN { MOVE(player, move); SEND_OUT(player, 1); }
|
TURN {
|
||||||
|
if (move == MOVE_U_TURN)
|
||||||
|
MOVE(playerLeft, move, target: opponentLeft);
|
||||||
|
else
|
||||||
|
MOVE(playerLeft, move);
|
||||||
|
SEND_OUT(playerLeft, 2);
|
||||||
|
}
|
||||||
} SCENE {
|
} SCENE {
|
||||||
ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS);
|
ABILITY_POPUP(playerLeft, ABILITY_NEUTRALIZING_GAS);
|
||||||
MESSAGE("Neutralizing gas filled the area!");
|
MESSAGE("Neutralizing gas filled the area!");
|
||||||
ANIMATION(ANIM_TYPE_MOVE, move, player);
|
ANIMATION(ANIM_TYPE_MOVE, move, playerLeft);
|
||||||
MESSAGE("The effects of the neutralizing gas wore off!");
|
MESSAGE("The effects of the neutralizing gas wore off!");
|
||||||
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
|
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
|
||||||
SEND_IN_MESSAGE("Wobbuffet");
|
SEND_IN_MESSAGE("Wobbuffet");
|
||||||
} THEN {
|
|
||||||
if (move == MOVE_HEALING_WISH)
|
|
||||||
EXPECT_EQ(player->hp, player->maxHP);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,23 +336,25 @@ SINGLE_BATTLE_TEST("Intimidate activates when it's no longer affected by Neutral
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SINGLE_BATTLE_TEST("Intimidate activates when it's no longer affected by Neutralizing Gas - fainted")
|
DOUBLE_BATTLE_TEST("Intimidate activates when it's no longer affected by Neutralizing Gas - fainted")
|
||||||
{
|
{
|
||||||
GIVEN {
|
GIVEN {
|
||||||
ASSUME(GetMoveEffect(MOVE_FELL_STINGER) == EFFECT_FELL_STINGER);
|
ASSUME(GetMoveEffect(MOVE_FELL_STINGER) == EFFECT_FELL_STINGER);
|
||||||
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); HP(1); }
|
PLAYER(SPECIES_WEEZING) { Ability(ABILITY_NEUTRALIZING_GAS); HP(1); }
|
||||||
PLAYER(SPECIES_WOBBUFFET);
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); }
|
OPPONENT(SPECIES_ARBOK) { Ability(ABILITY_INTIMIDATE); }
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
} WHEN {
|
} WHEN {
|
||||||
TURN { MOVE(opponent, MOVE_FELL_STINGER); SEND_OUT(player, 1); }
|
TURN { MOVE(opponentLeft, MOVE_FELL_STINGER, target: playerLeft); SEND_OUT(playerLeft, 2); }
|
||||||
} SCENE {
|
} SCENE {
|
||||||
ABILITY_POPUP(player, ABILITY_NEUTRALIZING_GAS);
|
ABILITY_POPUP(playerLeft, ABILITY_NEUTRALIZING_GAS);
|
||||||
MESSAGE("Neutralizing gas filled the area!");
|
MESSAGE("Neutralizing gas filled the area!");
|
||||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FELL_STINGER, opponent);
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_FELL_STINGER, opponentLeft);
|
||||||
MESSAGE("The effects of the neutralizing gas wore off!");
|
MESSAGE("The effects of the neutralizing gas wore off!");
|
||||||
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
|
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
|
||||||
MESSAGE("Weezing fainted!");
|
MESSAGE("Weezing fainted!");
|
||||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
|
||||||
SEND_IN_MESSAGE("Wobbuffet");
|
SEND_IN_MESSAGE("Wobbuffet");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,3 +2,56 @@
|
|||||||
#include "test/battle.h"
|
#include "test/battle.h"
|
||||||
|
|
||||||
TO_DO_BATTLE_TEST("TODO: Write Power Construct (Ability) test titles")
|
TO_DO_BATTLE_TEST("TODO: Write Power Construct (Ability) test titles")
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Power Construct switches Zygarde's form when HP is below half")
|
||||||
|
{
|
||||||
|
u16 baseSpecies;
|
||||||
|
PARAMETRIZE { baseSpecies = SPECIES_ZYGARDE_10_POWER_CONSTRUCT; }
|
||||||
|
PARAMETRIZE { baseSpecies = SPECIES_ZYGARDE_50_POWER_CONSTRUCT; }
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(baseSpecies)
|
||||||
|
{
|
||||||
|
Ability(ABILITY_POWER_CONSTRUCT);
|
||||||
|
HP((GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP) / 2) + 1);
|
||||||
|
}
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_SCRATCH); MOVE(player, MOVE_CELEBRATE); }
|
||||||
|
} SCENE {
|
||||||
|
MESSAGE("You sense the presence of many!");
|
||||||
|
ABILITY_POPUP(player, ABILITY_POWER_CONSTRUCT);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_POWER_CONSTRUCT, player);
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(player->species, SPECIES_ZYGARDE_COMPLETE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WILD_BATTLE_TEST("Power Construct Zygarde reverts to its original form upon catching")
|
||||||
|
{
|
||||||
|
u16 baseSpecies;
|
||||||
|
PARAMETRIZE { baseSpecies = SPECIES_ZYGARDE_10_POWER_CONSTRUCT; }
|
||||||
|
PARAMETRIZE { baseSpecies = SPECIES_ZYGARDE_50_POWER_CONSTRUCT; }
|
||||||
|
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(baseSpecies)
|
||||||
|
{
|
||||||
|
Ability(ABILITY_POWER_CONSTRUCT);
|
||||||
|
HP((GetMonData(&OPPONENT_PARTY[0], MON_DATA_MAX_HP) / 2) + 1);
|
||||||
|
}
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(player, MOVE_SCRATCH); }
|
||||||
|
TURN { USE_ITEM(player, ITEM_MASTER_BALL); }
|
||||||
|
} SCENE {
|
||||||
|
// Turn 1
|
||||||
|
MESSAGE("You sense the presence of many!");
|
||||||
|
ABILITY_POPUP(opponent, ABILITY_POWER_CONSTRUCT);
|
||||||
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_POWER_CONSTRUCT, opponent);
|
||||||
|
|
||||||
|
// Turn 2
|
||||||
|
ANIMATION(ANIM_TYPE_SPECIAL, B_ANIM_BALL_THROW, player);
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(GetMonData(&gPlayerParty[1], MON_DATA_SPECIES), baseSpecies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ ASSUMPTIONS
|
|||||||
ASSUME(MoveMakesContact(MOVE_SCRATCH) == TRUE);
|
ASSUME(MoveMakesContact(MOVE_SCRATCH) == TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SINGLE_BATTLE_TEST("Tangling Hair drops opposing mon's speed if ability user got hit by a contact move")
|
SINGLE_BATTLE_TEST("Tangling Hair drops opposing mon's speed if ability user got hit by a contact move")
|
||||||
{
|
{
|
||||||
u32 move;
|
u32 move;
|
||||||
@ -85,3 +84,16 @@ SINGLE_BATTLE_TEST("Tangling Hair does not activate on confusion damage")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Tangling Hair does not trigger on Clear Body")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_TANGLING_HAIR); }
|
||||||
|
OPPONENT(SPECIES_BELDUM) { Ability(ABILITY_CLEAR_BODY); };
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_SCRATCH); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent);
|
||||||
|
NOT ABILITY_POPUP(player, ABILITY_TANGLING_HAIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,9 +1,24 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "test/battle.h"
|
#include "test/battle.h"
|
||||||
|
|
||||||
SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon fainting")
|
SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon fainting (start as Shield)")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_AEGISLASH_SHIELD) { HP(1); }
|
||||||
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(player, MOVE_SCRATCH); MOVE(opponent, MOVE_GUST); SEND_OUT(player, 1); }
|
||||||
|
} SCENE {
|
||||||
|
MESSAGE("The opposing Wobbuffet used Gust!");
|
||||||
|
MESSAGE("Aegislash fainted!");
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_AEGISLASH_SHIELD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon fainting (start as Blade)")
|
||||||
{
|
{
|
||||||
KNOWN_FAILING;
|
|
||||||
GIVEN {
|
GIVEN {
|
||||||
PLAYER(SPECIES_AEGISLASH_BLADE) { HP(1); }
|
PLAYER(SPECIES_AEGISLASH_BLADE) { HP(1); }
|
||||||
PLAYER(SPECIES_WOBBUFFET);
|
PLAYER(SPECIES_WOBBUFFET);
|
||||||
@ -14,7 +29,7 @@ SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon fainting")
|
|||||||
MESSAGE("The opposing Wobbuffet used Gust!");
|
MESSAGE("The opposing Wobbuffet used Gust!");
|
||||||
MESSAGE("Aegislash fainted!");
|
MESSAGE("Aegislash fainted!");
|
||||||
} THEN {
|
} THEN {
|
||||||
EXPECT_EQ(GetMonData(&PLAYER_PARTY[0], MON_DATA_SPECIES), SPECIES_AEGISLASH_SHIELD);
|
EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_AEGISLASH_SHIELD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -159,7 +159,6 @@ SINGLE_BATTLE_TEST("Belly Drum maximizes the user's Attack stat, even when below
|
|||||||
|
|
||||||
SINGLE_BATTLE_TEST("Belly Drum fails if the user's Attack is already at +6, even with Contrary")
|
SINGLE_BATTLE_TEST("Belly Drum fails if the user's Attack is already at +6, even with Contrary")
|
||||||
{
|
{
|
||||||
KNOWN_FAILING;
|
|
||||||
GIVEN {
|
GIVEN {
|
||||||
ASSUME(GetMoveEffect(MOVE_CHARM) == EFFECT_ATTACK_DOWN_2);
|
ASSUME(GetMoveEffect(MOVE_CHARM) == EFFECT_ATTACK_DOWN_2);
|
||||||
PLAYER(SPECIES_SERPERIOR) { Ability(ABILITY_CONTRARY); }
|
PLAYER(SPECIES_SERPERIOR) { Ability(ABILITY_CONTRARY); }
|
||||||
@ -190,7 +189,6 @@ SINGLE_BATTLE_TEST("Belly Drum fails if the user's Attack is already at +6, even
|
|||||||
|
|
||||||
SINGLE_BATTLE_TEST("Belly Drum deducts HP if the user has Contrary and is at -6")
|
SINGLE_BATTLE_TEST("Belly Drum deducts HP if the user has Contrary and is at -6")
|
||||||
{
|
{
|
||||||
KNOWN_FAILING;
|
|
||||||
GIVEN {
|
GIVEN {
|
||||||
ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2);
|
ASSUME(GetMoveEffect(MOVE_SWORDS_DANCE) == EFFECT_ATTACK_UP_2);
|
||||||
PLAYER(SPECIES_SERPERIOR) { Ability(ABILITY_CONTRARY); }
|
PLAYER(SPECIES_SERPERIOR) { Ability(ABILITY_CONTRARY); }
|
||||||
@ -215,6 +213,6 @@ SINGLE_BATTLE_TEST("Belly Drum deducts HP if the user has Contrary and is at -6"
|
|||||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player);
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player);
|
||||||
s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP);
|
s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP);
|
||||||
HP_BAR(player, hp: maxHP / 2);
|
HP_BAR(player, hp: maxHP / 2);
|
||||||
MESSAGE("Wobbuffet cut its own HP and maximized its Attack!");
|
MESSAGE("Serperior cut its own HP and maximized its Attack!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -113,7 +113,7 @@ SINGLE_BATTLE_TEST("Hit Escape: U-turn switches the user out after Ice Face acti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SINGLE_BATTLE_TEST("Hit Escape: Held items are consumed immediately after a mon switched in by U-turn and Intimidate activates after it: player side")
|
SINGLE_BATTLE_TEST("Hit Escape: Held items are consumed immediately after a mon switched in by U-turn: player side")
|
||||||
{
|
{
|
||||||
GIVEN {
|
GIVEN {
|
||||||
PLAYER(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); };
|
PLAYER(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); };
|
||||||
@ -126,7 +126,6 @@ SINGLE_BATTLE_TEST("Hit Escape: Held items are consumed immediately after a mon
|
|||||||
ABILITY_POPUP(player, ABILITY_ELECTRIC_SURGE);
|
ABILITY_POPUP(player, ABILITY_ELECTRIC_SURGE);
|
||||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player);
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player);
|
||||||
HP_BAR(opponent);
|
HP_BAR(opponent);
|
||||||
ABILITY_POPUP(player, ABILITY_INTIMIDATE);
|
|
||||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
|
||||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||||
MESSAGE("2 sent out Wynaut!");
|
MESSAGE("2 sent out Wynaut!");
|
||||||
@ -136,7 +135,7 @@ SINGLE_BATTLE_TEST("Hit Escape: Held items are consumed immediately after a mon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SINGLE_BATTLE_TEST("Hit Escape: Held items are consumed immediately after a mon switched in by U-turn and Intimidate activates after it: opposing side")
|
SINGLE_BATTLE_TEST("Hit Escape: Held items are consumed immediately after a mon switched in by U-turn: opposing side")
|
||||||
{
|
{
|
||||||
GIVEN {
|
GIVEN {
|
||||||
PLAYER(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); };
|
PLAYER(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); };
|
||||||
@ -149,7 +148,6 @@ SINGLE_BATTLE_TEST("Hit Escape: Held items are consumed immediately after a mon
|
|||||||
ABILITY_POPUP(player, ABILITY_ELECTRIC_SURGE);
|
ABILITY_POPUP(player, ABILITY_ELECTRIC_SURGE);
|
||||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player);
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player);
|
||||||
HP_BAR(opponent);
|
HP_BAR(opponent);
|
||||||
ABILITY_POPUP(player, ABILITY_INTIMIDATE);
|
|
||||||
MESSAGE("2 sent out Wynaut!");
|
MESSAGE("2 sent out Wynaut!");
|
||||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent);
|
||||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user