Stat Change (Animation) Refactor (#7144)
This commit is contained in:
parent
ab1838ffd8
commit
340d815c6d
@ -408,15 +408,12 @@
|
||||
.4byte \argPtr
|
||||
.endm
|
||||
|
||||
.macro setgraphicalstatchangevalues
|
||||
.macro unused_0x47
|
||||
.byte 0x47
|
||||
.endm
|
||||
|
||||
.macro playstatchangeanimation battler:req, stats:req, flags:req
|
||||
.macro unused_0x48
|
||||
.byte 0x48
|
||||
.byte \battler
|
||||
.byte \stats
|
||||
.byte \flags
|
||||
.endm
|
||||
|
||||
.macro moveend endMode:req, endState:req
|
||||
@ -770,10 +767,11 @@
|
||||
.byte 0x88
|
||||
.endm
|
||||
|
||||
.macro statbuffchange flags:req, failInstr:req
|
||||
.macro statbuffchange flags:req, failInstr:req, stats=0
|
||||
.byte 0x89
|
||||
.2byte \flags
|
||||
.4byte \failInstr
|
||||
.byte \stats
|
||||
.endm
|
||||
|
||||
.macro normalisebuffs
|
||||
@ -2516,11 +2514,10 @@
|
||||
ANIM_ON = TRUE
|
||||
|
||||
setstatchanger \stat, \amount, \mode
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR, \script
|
||||
setgraphicalstatchangevalues
|
||||
.if \animation == TRUE
|
||||
playanimation \battler, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
|
||||
.if \animation == FALSE
|
||||
setbyte sSTAT_ANIM_PLAYED, TRUE
|
||||
.endif
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR, \script
|
||||
.ifnb \customString
|
||||
printstring \customString
|
||||
.else
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -105,8 +105,6 @@ BattleScript_ItemIncreaseStat::
|
||||
call BattleScript_UseItemMessage
|
||||
itemincreasestat
|
||||
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_ItemEnd
|
||||
setgraphicalstatchangevalues
|
||||
playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
|
||||
printfromtable gStatUpStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
end
|
||||
|
||||
@ -339,7 +339,6 @@ extern const u8 BattleScript_GrassySurgeActivates[];
|
||||
extern const u8 BattleScript_MistySurgeActivates[];
|
||||
extern const u8 BattleScript_ElectricSurgeActivates[];
|
||||
extern const u8 BattleScript_EffectSpectralThief[];
|
||||
extern const u8 BattleScript_StatUpMsg[];
|
||||
extern const u8 BattleScript_AbilityRaisesDefenderStat[];
|
||||
extern const u8 BattleScript_PowderMoveNoEffect[];
|
||||
extern const u8 BattleScript_GrassyTerrainHeals[];
|
||||
|
||||
@ -223,6 +223,7 @@ void MarkBattlerForControllerExec(u32 battler);
|
||||
void MarkBattlerReceivedLinkData(u32 battler);
|
||||
const u8 *CancelMultiTurnMoves(u32 battler, enum SkyDropState skyDropState);
|
||||
bool32 WasUnableToUseMove(u32 battler);
|
||||
bool32 ShouldDefiantCompetitiveActivate(u32 battler, u32 ability);
|
||||
void PrepareStringBattle(enum StringID stringId, u32 battler);
|
||||
void ResetSentPokesToOpponentValue(void);
|
||||
void OpponentSwitchInResetSentPokesToOpponentValue(u32 battler);
|
||||
|
||||
@ -161,6 +161,7 @@
|
||||
#define B_MAGIC_GUARD GEN_LATEST // In Gen4 only, Magic Guard ignores immobilization caused by paralysis
|
||||
#define B_BATTLE_BOND GEN_LATEST // In Gen9+, Battle Bond increases Atk, SpAtk and Speed by one stage, once per battle
|
||||
#define B_ATE_MULTIPLIER GEN_LATEST // In Gen7+, -ate abilities (Aerilate, Galvanize, Normalize, Pixilate, Refrigerate) multiply damage by 1.2. Otherwise, it's 1.3, except Normalize which has no multiplier.
|
||||
#define B_DEFIANT_STICKY_WEB GEN_LATEST // In Gen9+, Defiant activates on Sticky Web regardless of who set it up. In Gen8, Defiant does not activate on Sticky Web set up by an ally after Court Change swaps its side.
|
||||
|
||||
// Item settings
|
||||
#define B_HP_BERRIES GEN_LATEST // In Gen4+, berries which restore HP activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn.
|
||||
|
||||
@ -221,16 +221,11 @@ enum CmdVarious
|
||||
// Cmd_statbuffchange
|
||||
#define STAT_CHANGE_ALLOW_PTR (1 << 0) // If set, allow use of jumpptr. If not set and unable to raise/lower stats, jump to failInstr.
|
||||
#define STAT_CHANGE_MIRROR_ARMOR (1 << 1) // Stat change redirection caused by Mirror Armor ability.
|
||||
#define STAT_CHANGE_ONLY_CHECKING (1 << 2) // Checks if the stat change can occur. Does not change stats or play stat change animation.
|
||||
#define STAT_CHANGE_NOT_PROTECT_AFFECTED (1 << 5)
|
||||
#define STAT_CHANGE_UPDATE_MOVE_EFFECT (1 << 6)
|
||||
|
||||
// stat change flags for Cmd_playstatchangeanimation
|
||||
#define STAT_CHANGE_NEGATIVE (1 << 0)
|
||||
#define STAT_CHANGE_BY_TWO (1 << 1)
|
||||
#define STAT_CHANGE_MULTIPLE_STATS (1 << 2)
|
||||
#define STAT_CHANGE_CANT_PREVENT (1 << 3)
|
||||
|
||||
// stat flags for Cmd_playstatchangeanimation
|
||||
// stat flags for TryPlayStatChangeAnimation
|
||||
#define BIT_HP (1 << 0)
|
||||
#define BIT_ATK (1 << 1)
|
||||
#define BIT_DEF (1 << 2)
|
||||
|
||||
@ -17,6 +17,7 @@ enum GenConfigTag
|
||||
GEN_CONFIG_BATTLE_BOND,
|
||||
GEN_CONFIG_ATE_MULTIPLIER,
|
||||
GEN_CONFIG_FELL_STINGER_STAT_RAISE,
|
||||
GEN_CONFIG_DEFIANT_STICKY_WEB,
|
||||
GEN_CONFIG_COUNT
|
||||
};
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] =
|
||||
[GEN_CONFIG_BATTLE_BOND] = B_BATTLE_BOND,
|
||||
[GEN_CONFIG_FELL_STINGER_STAT_RAISE] = B_FELL_STINGER_STAT_RAISE,
|
||||
[GEN_CONFIG_ATE_MULTIPLIER] = B_ATE_MULTIPLIER,
|
||||
[GEN_CONFIG_DEFIANT_STICKY_WEB] = B_DEFIANT_STICKY_WEB,
|
||||
};
|
||||
|
||||
#if TESTING
|
||||
|
||||
@ -319,7 +319,7 @@ enum GiveCaughtMonStates
|
||||
#define TAG_LVLUP_BANNER_MON_ICON 55130
|
||||
|
||||
static void TrySetDestinyBondToHappen(void);
|
||||
static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr);
|
||||
static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const u8 *BS_ptr);
|
||||
static bool32 IsMonGettingExpSentOut(void);
|
||||
static void InitLevelUpBanner(void);
|
||||
static bool8 SlideInLevelUpBanner(void);
|
||||
@ -416,8 +416,8 @@ static void Cmd_jumpifabilitypresent(void);
|
||||
static void Cmd_endselectionscript(void);
|
||||
static void Cmd_playanimation(void);
|
||||
static void Cmd_playanimation_var(void);
|
||||
static void Cmd_setgraphicalstatchangevalues(void);
|
||||
static void Cmd_playstatchangeanimation(void);
|
||||
static void Cmd_unused_0x47(void);
|
||||
static void Cmd_unused_0x48(void);
|
||||
static void Cmd_moveend(void);
|
||||
static void Cmd_sethealblock(void);
|
||||
static void Cmd_returnatktoball(void);
|
||||
@ -675,8 +675,8 @@ void (*const gBattleScriptingCommandsTable[])(void) =
|
||||
Cmd_endselectionscript, //0x44
|
||||
Cmd_playanimation, //0x45
|
||||
Cmd_playanimation_var, //0x46
|
||||
Cmd_setgraphicalstatchangevalues, //0x47
|
||||
Cmd_playstatchangeanimation, //0x48
|
||||
Cmd_unused_0x47, //0x47
|
||||
Cmd_unused_0x48, //0x48
|
||||
Cmd_moveend, //0x49
|
||||
Cmd_sethealblock, //0x4A
|
||||
Cmd_returnatktoball, //0x4B
|
||||
@ -3499,7 +3499,8 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
if (NoAliveMonsForEitherParty()
|
||||
|| ChangeStatBuffs(SET_STAT_BUFF_VALUE(1),
|
||||
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_1 + 1,
|
||||
affectsUser | STAT_CHANGE_UPDATE_MOVE_EFFECT, 0) == STAT_CHANGE_DIDNT_WORK)
|
||||
affectsUser | STAT_CHANGE_UPDATE_MOVE_EFFECT,
|
||||
0, 0) == STAT_CHANGE_DIDNT_WORK)
|
||||
{
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
@ -3529,7 +3530,8 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
|
||||
if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE,
|
||||
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_1 + 1,
|
||||
flags, gBattlescriptCurrInstr + 1) == STAT_CHANGE_DIDNT_WORK)
|
||||
flags,
|
||||
0, gBattlescriptCurrInstr + 1) == STAT_CHANGE_DIDNT_WORK)
|
||||
{
|
||||
if (!mirrorArmorReflected)
|
||||
gBattlescriptCurrInstr++;
|
||||
@ -3552,7 +3554,8 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
if (NoAliveMonsForEitherParty()
|
||||
|| ChangeStatBuffs(SET_STAT_BUFF_VALUE(2),
|
||||
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_2 + 1,
|
||||
affectsUser | STAT_CHANGE_UPDATE_MOVE_EFFECT, 0) == STAT_CHANGE_DIDNT_WORK)
|
||||
affectsUser | STAT_CHANGE_UPDATE_MOVE_EFFECT,
|
||||
0, 0) == STAT_CHANGE_DIDNT_WORK)
|
||||
{
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
@ -3582,7 +3585,8 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
|
||||
if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE,
|
||||
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_2 + 1,
|
||||
flags, gBattlescriptCurrInstr + 1) == STAT_CHANGE_DIDNT_WORK)
|
||||
flags,
|
||||
0, gBattlescriptCurrInstr + 1) == STAT_CHANGE_DIDNT_WORK)
|
||||
{
|
||||
if (!mirrorArmorReflected)
|
||||
gBattlescriptCurrInstr++;
|
||||
@ -4003,6 +4007,7 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
|| ChangeStatBuffs(SET_STAT_BUFF_VALUE(1),
|
||||
stat,
|
||||
affectsUser | STAT_CHANGE_UPDATE_MOVE_EFFECT,
|
||||
0,
|
||||
0) == STAT_CHANGE_DIDNT_WORK)
|
||||
{
|
||||
gBattlescriptCurrInstr++;
|
||||
@ -5876,171 +5881,12 @@ static void Cmd_playanimation_var(void)
|
||||
PlayAnimation(battler, *(cmd->animIdPtr), cmd->argPtr, cmd->nextInstr);
|
||||
}
|
||||
|
||||
static void Cmd_setgraphicalstatchangevalues(void)
|
||||
static void Cmd_unused_0x47(void)
|
||||
{
|
||||
CMD_ARGS();
|
||||
|
||||
u8 value = GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger);
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case SET_STAT_BUFF_VALUE(1): // +1
|
||||
value = STAT_ANIM_PLUS1 + 1;
|
||||
break;
|
||||
case SET_STAT_BUFF_VALUE(2): // +2
|
||||
value = STAT_ANIM_PLUS2 + 1;
|
||||
break;
|
||||
case SET_STAT_BUFF_VALUE(3): // +3
|
||||
value = STAT_ANIM_PLUS2 + 1;
|
||||
break;
|
||||
case SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE: // -1
|
||||
value = STAT_ANIM_MINUS1 + 1;
|
||||
break;
|
||||
case SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE: // -2
|
||||
value = STAT_ANIM_MINUS2 + 1;
|
||||
break;
|
||||
case SET_STAT_BUFF_VALUE(3) | STAT_BUFF_NEGATIVE: // -3
|
||||
value = STAT_ANIM_MINUS2 + 1;
|
||||
break;
|
||||
default: // <-12,-4> and <4, 12>
|
||||
if (value & STAT_BUFF_NEGATIVE)
|
||||
value = STAT_ANIM_MINUS2 + 1;
|
||||
else
|
||||
value = STAT_ANIM_PLUS2 + 1;
|
||||
break;
|
||||
}
|
||||
gBattleScripting.animArg1 = GET_STAT_BUFF_ID(gBattleScripting.statChanger) + value - 1;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static void Cmd_playstatchangeanimation(void)
|
||||
static void Cmd_unused_0x48(void)
|
||||
{
|
||||
CMD_ARGS(u8 battler, u8 stats, u8 flags);
|
||||
|
||||
u32 currStat = 0;
|
||||
u32 statAnimId = 0;
|
||||
u32 changeableStatsCount = 0;
|
||||
u32 startingStatAnimId = 0;
|
||||
u32 flags = cmd->flags;
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
u32 ability = GetBattlerAbility(battler);
|
||||
u32 stats = cmd->stats;
|
||||
bool32 defiantCompetitiveAffected = FALSE;
|
||||
|
||||
if (gBattleScripting.statAnimPlayed)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Contrary and Simple
|
||||
if (ability == ABILITY_CONTRARY)
|
||||
{
|
||||
flags ^= STAT_CHANGE_NEGATIVE;
|
||||
RecordAbilityBattle(battler, ability);
|
||||
}
|
||||
else if (ability == ABILITY_SIMPLE)
|
||||
{
|
||||
flags |= STAT_CHANGE_BY_TWO;
|
||||
RecordAbilityBattle(battler, ability);
|
||||
}
|
||||
else if (ability == ABILITY_DEFIANT || ability == ABILITY_COMPETITIVE)
|
||||
{
|
||||
defiantCompetitiveAffected = TRUE;
|
||||
}
|
||||
|
||||
if (flags & STAT_CHANGE_NEGATIVE) // goes down
|
||||
{
|
||||
if (flags & STAT_CHANGE_BY_TWO)
|
||||
startingStatAnimId = STAT_ANIM_MINUS2;
|
||||
else
|
||||
startingStatAnimId = STAT_ANIM_MINUS1;
|
||||
|
||||
while (stats != 0)
|
||||
{
|
||||
if (stats & 1)
|
||||
{
|
||||
if (flags & STAT_CHANGE_CANT_PREVENT)
|
||||
{
|
||||
if (gBattleMons[battler].statStages[currStat] > MIN_STAT_STAGE)
|
||||
{
|
||||
statAnimId = startingStatAnimId + currStat;
|
||||
changeableStatsCount++;
|
||||
}
|
||||
}
|
||||
else if (!gSideTimers[GetBattlerSide(battler)].mistTimer
|
||||
&& GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_CLEAR_AMULET
|
||||
&& ability != ABILITY_CLEAR_BODY
|
||||
&& ability != ABILITY_FULL_METAL_BODY
|
||||
&& ability != ABILITY_WHITE_SMOKE
|
||||
&& !((ability == ABILITY_KEEN_EYE || ability == ABILITY_MINDS_EYE) && currStat == STAT_ACC)
|
||||
&& !(B_ILLUMINATE_EFFECT >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC)
|
||||
&& !(ability == ABILITY_HYPER_CUTTER && currStat == STAT_ATK)
|
||||
&& !(ability == ABILITY_BIG_PECKS && currStat == STAT_DEF))
|
||||
{
|
||||
if (gBattleMons[battler].statStages[currStat] > MIN_STAT_STAGE)
|
||||
{
|
||||
statAnimId = startingStatAnimId + currStat;
|
||||
changeableStatsCount++;
|
||||
if (defiantCompetitiveAffected) // Force single stat animations
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
stats >>= 1, currStat++;
|
||||
}
|
||||
|
||||
if (changeableStatsCount > 1) // more than one stat, so the color is gray
|
||||
{
|
||||
if (flags & STAT_CHANGE_BY_TWO)
|
||||
statAnimId = STAT_ANIM_MULTIPLE_MINUS2;
|
||||
else
|
||||
statAnimId = STAT_ANIM_MULTIPLE_MINUS1;
|
||||
}
|
||||
}
|
||||
else // goes up
|
||||
{
|
||||
if (flags & STAT_CHANGE_BY_TWO)
|
||||
startingStatAnimId = STAT_ANIM_PLUS2;
|
||||
else
|
||||
startingStatAnimId = STAT_ANIM_PLUS1;
|
||||
|
||||
while (stats != 0)
|
||||
{
|
||||
if (stats & 1 && gBattleMons[battler].statStages[currStat] < MAX_STAT_STAGE)
|
||||
{
|
||||
statAnimId = startingStatAnimId + currStat;
|
||||
changeableStatsCount++;
|
||||
}
|
||||
stats >>= 1, currStat++;
|
||||
}
|
||||
|
||||
if (changeableStatsCount > 1) // more than one stat, so the color is gray
|
||||
{
|
||||
if (flags & STAT_CHANGE_BY_TWO)
|
||||
statAnimId = STAT_ANIM_MULTIPLE_PLUS2;
|
||||
else
|
||||
statAnimId = STAT_ANIM_MULTIPLE_PLUS1;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & STAT_CHANGE_MULTIPLE_STATS && changeableStatsCount < 2)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else if (changeableStatsCount != 0)
|
||||
{
|
||||
BtlController_EmitBattleAnimation(battler, B_COMM_TO_CONTROLLER, B_ANIM_STATS_CHANGE, &gDisableStructs[battler], statAnimId);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
if (flags & STAT_CHANGE_MULTIPLE_STATS && changeableStatsCount > 1)
|
||||
gBattleScripting.statAnimPlayed = TRUE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
|
||||
static bool32 TryKnockOffBattleScript(u32 battlerDef)
|
||||
@ -12167,14 +12013,103 @@ static u16 ReverseStatChangeMoveEffect(u16 moveEffect)
|
||||
}
|
||||
}
|
||||
|
||||
static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr)
|
||||
static void TryPlayStatChangeAnimation(u32 battler, u32 ability, u32 stats, s32 statValue, u32 statId, bool32 certain)
|
||||
{
|
||||
u32 currStat = 0;
|
||||
u32 changeableStatsCount = 1; // current stat is counted automatically
|
||||
u32 statAnimId = statId;
|
||||
bool32 statChangeByTwo = statValue > 1 || statValue < -1;
|
||||
|
||||
if (statValue <= -1) // goes down
|
||||
{
|
||||
if (statChangeByTwo)
|
||||
statAnimId += STAT_ANIM_MINUS2;
|
||||
else
|
||||
statAnimId += STAT_ANIM_MINUS1;
|
||||
|
||||
while (stats != 0)
|
||||
{
|
||||
if (stats & 1)
|
||||
{
|
||||
if (certain)
|
||||
{
|
||||
if (gBattleMons[battler].statStages[currStat] > MIN_STAT_STAGE)
|
||||
{
|
||||
changeableStatsCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!((ability == ABILITY_KEEN_EYE || ability == ABILITY_MINDS_EYE) && currStat == STAT_ACC)
|
||||
&& !(B_ILLUMINATE_EFFECT >= GEN_9 && ability == ABILITY_ILLUMINATE && currStat == STAT_ACC)
|
||||
&& !(ability == ABILITY_HYPER_CUTTER && currStat == STAT_ATK)
|
||||
&& !(ability == ABILITY_BIG_PECKS && currStat == STAT_DEF))
|
||||
{
|
||||
if (gBattleMons[battler].statStages[currStat] > MIN_STAT_STAGE)
|
||||
{
|
||||
changeableStatsCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
stats >>= 1, currStat++;
|
||||
}
|
||||
|
||||
if (changeableStatsCount > 1) // more than one stat, so the color is gray
|
||||
{
|
||||
if (statChangeByTwo)
|
||||
statAnimId = STAT_ANIM_MULTIPLE_MINUS2;
|
||||
else
|
||||
statAnimId = STAT_ANIM_MULTIPLE_MINUS1;
|
||||
}
|
||||
}
|
||||
else // goes up
|
||||
{
|
||||
if (statChangeByTwo)
|
||||
statAnimId += STAT_ANIM_PLUS2;
|
||||
else
|
||||
statAnimId += STAT_ANIM_PLUS1;
|
||||
|
||||
while (stats != 0)
|
||||
{
|
||||
if (stats & 1 && gBattleMons[battler].statStages[currStat] < MAX_STAT_STAGE)
|
||||
{
|
||||
changeableStatsCount++;
|
||||
break;
|
||||
}
|
||||
stats >>= 1, currStat++;
|
||||
}
|
||||
|
||||
if (changeableStatsCount > 1) // more than one stat, so the color is gray
|
||||
{
|
||||
if (statChangeByTwo)
|
||||
statAnimId = STAT_ANIM_MULTIPLE_PLUS2;
|
||||
else
|
||||
statAnimId = STAT_ANIM_MULTIPLE_PLUS1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gBattleScripting.statAnimPlayed)
|
||||
{
|
||||
BtlController_EmitBattleAnimation(battler, B_COMM_TO_CONTROLLER, B_ANIM_STATS_CHANGE, &gDisableStructs[battler], statAnimId);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
if (changeableStatsCount > 1)
|
||||
gBattleScripting.statAnimPlayed = TRUE;
|
||||
}
|
||||
else if (changeableStatsCount == 1) // final stat that can be changed
|
||||
{
|
||||
gBattleScripting.statAnimPlayed = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const u8 *BS_ptr)
|
||||
{
|
||||
bool32 certain = FALSE;
|
||||
bool32 notProtectAffected = FALSE;
|
||||
u32 index, battler, battlerAbility;
|
||||
enum ItemHoldEffect battlerHoldEffect;
|
||||
bool32 certain = (flags & MOVE_EFFECT_CERTAIN);
|
||||
bool32 notProtectAffected = (flags & STAT_CHANGE_NOT_PROTECT_AFFECTED);
|
||||
bool32 affectsUser = (flags & MOVE_EFFECT_AFFECTS_USER);
|
||||
bool32 mirrorArmored = (flags & STAT_CHANGE_MIRROR_ARMOR);
|
||||
bool32 onlyChecking = (flags & STAT_CHANGE_ONLY_CHECKING);
|
||||
|
||||
if (affectsUser)
|
||||
battler = gBattlerAttacker;
|
||||
@ -12186,30 +12121,26 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
|
||||
gSpecialStatuses[battler].changedStatsBattlerId = gBattlerAttacker;
|
||||
|
||||
flags &= ~(MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_MIRROR_ARMOR);
|
||||
|
||||
if (flags & MOVE_EFFECT_CERTAIN)
|
||||
certain = TRUE;
|
||||
flags &= ~MOVE_EFFECT_CERTAIN;
|
||||
|
||||
if (flags & STAT_CHANGE_NOT_PROTECT_AFFECTED)
|
||||
notProtectAffected++;
|
||||
flags &= ~STAT_CHANGE_NOT_PROTECT_AFFECTED;
|
||||
flags &= ~(STAT_CHANGE_ONLY_CHECKING | STAT_CHANGE_MIRROR_ARMOR | STAT_CHANGE_NOT_PROTECT_AFFECTED);
|
||||
|
||||
if (battlerAbility == ABILITY_CONTRARY)
|
||||
{
|
||||
statValue ^= STAT_BUFF_NEGATIVE;
|
||||
gBattleScripting.statChanger ^= STAT_BUFF_NEGATIVE;
|
||||
RecordAbilityBattle(battler, battlerAbility);
|
||||
if (flags & STAT_CHANGE_UPDATE_MOVE_EFFECT)
|
||||
if (!onlyChecking)
|
||||
{
|
||||
flags &= ~STAT_CHANGE_UPDATE_MOVE_EFFECT;
|
||||
gBattleScripting.moveEffect = ReverseStatChangeMoveEffect(gBattleScripting.moveEffect);
|
||||
gBattleScripting.statChanger ^= STAT_BUFF_NEGATIVE;
|
||||
RecordAbilityBattle(battler, battlerAbility);
|
||||
if (flags & STAT_CHANGE_UPDATE_MOVE_EFFECT)
|
||||
{
|
||||
flags &= ~STAT_CHANGE_UPDATE_MOVE_EFFECT;
|
||||
gBattleScripting.moveEffect = ReverseStatChangeMoveEffect(gBattleScripting.moveEffect);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (battlerAbility == ABILITY_SIMPLE)
|
||||
else if (battlerAbility == ABILITY_SIMPLE && !onlyChecking)
|
||||
{
|
||||
statValue = (SET_STAT_BUFF_VALUE(GET_STAT_BUFF_VALUE(statValue) * 2)) | ((statValue <= -1) ? STAT_BUFF_NEGATIVE : 0);
|
||||
RecordAbilityBattle(battler, battlerAbility);
|
||||
}
|
||||
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
||||
@ -12220,7 +12151,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
&& !certain && gCurrentMove != MOVE_CURSE
|
||||
&& !(battler == gBattlerTarget && GetBattlerAbility(gBattlerAttacker) == ABILITY_INFILTRATOR))
|
||||
{
|
||||
if (flags == STAT_CHANGE_ALLOW_PTR)
|
||||
if (flags & STAT_CHANGE_ALLOW_PTR)
|
||||
{
|
||||
if (gSpecialStatuses[battler].statLowered)
|
||||
{
|
||||
@ -12244,7 +12175,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
else if ((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET || CanAbilityPreventStatLoss(battlerAbility))
|
||||
&& (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE)
|
||||
{
|
||||
if (flags == STAT_CHANGE_ALLOW_PTR)
|
||||
if (flags & STAT_CHANGE_ALLOW_PTR)
|
||||
{
|
||||
if (gSpecialStatuses[battler].statLowered)
|
||||
{
|
||||
@ -12275,7 +12206,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
}
|
||||
else if ((index = IsFlowerVeilProtected(battler)) && !certain)
|
||||
{
|
||||
if (flags == STAT_CHANGE_ALLOW_PTR)
|
||||
if (flags & STAT_CHANGE_ALLOW_PTR)
|
||||
{
|
||||
if (gSpecialStatuses[battler].statLowered)
|
||||
{
|
||||
@ -12299,7 +12230,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
|| (battlerAbility == ABILITY_HYPER_CUTTER && statId == STAT_ATK)
|
||||
|| (battlerAbility == ABILITY_BIG_PECKS && statId == STAT_DEF)))
|
||||
{
|
||||
if (flags == STAT_CHANGE_ALLOW_PTR)
|
||||
if (flags & STAT_CHANGE_ALLOW_PTR)
|
||||
{
|
||||
BattleScriptPush(BS_ptr);
|
||||
gBattleScripting.battler = battler;
|
||||
@ -12312,7 +12243,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
}
|
||||
else if (battlerAbility == ABILITY_MIRROR_ARMOR && !affectsUser && !mirrorArmored && gBattlerAttacker != gBattlerTarget && battler == gBattlerTarget)
|
||||
{
|
||||
if (flags == STAT_CHANGE_ALLOW_PTR)
|
||||
if (flags & STAT_CHANGE_ALLOW_PTR)
|
||||
{
|
||||
SET_STATCHANGER(statId, GET_STAT_BUFF_VALUE(statValue) | STAT_BUFF_NEGATIVE, TRUE);
|
||||
BattleScriptPush(BS_ptr);
|
||||
@ -12351,15 +12282,16 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
gBattleTextBuff2[index++] = STRINGID_STATFELL >> 8;
|
||||
gBattleTextBuff2[index] = B_BUFF_EOS;
|
||||
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL
|
||||
|
||||
if (gBattleMons[battler].statStages[statId] == MIN_STAT_STAGE)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_DECREASE;
|
||||
}
|
||||
else
|
||||
else if (!onlyChecking)
|
||||
{
|
||||
gProtectStructs[battler].statFell = TRUE;
|
||||
gProtectStructs[battler].lashOutAffected = TRUE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12391,11 +12323,13 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
gBattleTextBuff2[index++] = STRINGID_STATROSE >> 8;
|
||||
gBattleTextBuff2[index] = B_BUFF_EOS;
|
||||
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_ROSE or B_MSG_DEFENDER_STAT_ROSE
|
||||
|
||||
if (gBattleMons[battler].statStages[statId] == MAX_STAT_STAGE)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_INCREASE;
|
||||
}
|
||||
else
|
||||
else if (!onlyChecking)
|
||||
{
|
||||
u32 statIncrease;
|
||||
if ((statValue + gBattleMons[battler].statStages[statId]) > MAX_STAT_STAGE)
|
||||
@ -12403,29 +12337,31 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
else
|
||||
statIncrease = statValue;
|
||||
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler);
|
||||
gProtectStructs[battler].statRaised = TRUE;
|
||||
|
||||
// Check Mirror Herb / Opportunist
|
||||
for (index = 0; index < gBattlersCount; index++)
|
||||
if (statIncrease)
|
||||
{
|
||||
if (IsBattlerAlly(index, battler))
|
||||
continue; // Only triggers on opposing side
|
||||
// Check Mirror Herb / Opportunist
|
||||
for (index = 0; index < gBattlersCount; index++)
|
||||
{
|
||||
if (IsBattlerAlly(index, battler))
|
||||
continue; // Only triggers on opposing side
|
||||
|
||||
if (GetBattlerAbility(index) == ABILITY_OPPORTUNIST
|
||||
&& gProtectStructs[battler].activateOpportunist == 0) // don't activate opportunist on other mon's opportunist raises
|
||||
{
|
||||
gProtectStructs[index].activateOpportunist = 2; // set stats to copy
|
||||
}
|
||||
if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB)
|
||||
{
|
||||
gProtectStructs[index].eatMirrorHerb = 1;
|
||||
}
|
||||
if (GetBattlerAbility(index) == ABILITY_OPPORTUNIST
|
||||
&& gProtectStructs[battler].activateOpportunist == 0) // don't activate opportunist on other mon's opportunist raises
|
||||
{
|
||||
gProtectStructs[index].activateOpportunist = 2; // set stats to copy
|
||||
}
|
||||
if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB)
|
||||
{
|
||||
gProtectStructs[index].eatMirrorHerb = 1;
|
||||
}
|
||||
|
||||
if (gProtectStructs[index].activateOpportunist == 2 || gProtectStructs[index].eatMirrorHerb == 1)
|
||||
{
|
||||
gQueuedStatBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk
|
||||
gQueuedStatBoosts[index].statChanges[statId - 1] += statIncrease;
|
||||
if (gProtectStructs[index].activateOpportunist == 2 || gProtectStructs[index].eatMirrorHerb == 1)
|
||||
{
|
||||
gQueuedStatBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk
|
||||
gQueuedStatBoosts[index].statChanges[statId - 1] += statIncrease;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12439,26 +12375,38 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
return STAT_CHANGE_WORKED;
|
||||
}
|
||||
|
||||
if (onlyChecking)
|
||||
return STAT_CHANGE_WORKED;
|
||||
|
||||
gBattleMons[battler].statStages[statId] += statValue;
|
||||
if (gBattleMons[battler].statStages[statId] < MIN_STAT_STAGE)
|
||||
gBattleMons[battler].statStages[statId] = MIN_STAT_STAGE;
|
||||
if (gBattleMons[battler].statStages[statId] > MAX_STAT_STAGE)
|
||||
gBattleMons[battler].statStages[statId] = MAX_STAT_STAGE;
|
||||
|
||||
if (ShouldDefiantCompetitiveActivate(battler, battlerAbility))
|
||||
stats = 0; // use single stat animations when Defiant/Competitive activate
|
||||
else
|
||||
stats &= ~(1u << statId);
|
||||
|
||||
TryPlayStatChangeAnimation(battler, battlerAbility, stats, statValue, statId, certain);
|
||||
|
||||
return STAT_CHANGE_WORKED;
|
||||
}
|
||||
|
||||
static void Cmd_statbuffchange(void)
|
||||
{
|
||||
CMD_ARGS(u16 flags, const u8 *failInstr);
|
||||
CMD_ARGS(u16 flags, const u8 *failInstr, u8 stats);
|
||||
|
||||
u16 flags = cmd->flags;
|
||||
u32 stats = cmd->stats;
|
||||
const u8 *ptrBefore = gBattlescriptCurrInstr;
|
||||
const u8 *failInstr = cmd->failInstr;
|
||||
|
||||
if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger),
|
||||
GET_STAT_BUFF_ID(gBattleScripting.statChanger),
|
||||
flags,
|
||||
stats,
|
||||
failInstr) == STAT_CHANGE_WORKED)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
else if (gBattlescriptCurrInstr == ptrBefore) // Prevent infinite looping.
|
||||
@ -18234,9 +18182,10 @@ void BS_SpectralThiefPrintStats(void)
|
||||
SET_STATCHANGER(stat, gBattleStruct->stolenStats[stat], FALSE);
|
||||
if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger),
|
||||
stat,
|
||||
MOVE_EFFECT_CERTAIN | MOVE_EFFECT_AFFECTS_USER, NULL) == STAT_CHANGE_WORKED)
|
||||
MOVE_EFFECT_CERTAIN | MOVE_EFFECT_AFFECTS_USER,
|
||||
0, NULL) == STAT_CHANGE_WORKED)
|
||||
{
|
||||
BattleScriptCall(BattleScript_StatUpMsg);
|
||||
BattleScriptCall(BattleScript_StatUp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1144,9 +1144,23 @@ bool32 WasUnableToUseMove(u32 battler)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 ShouldDefiantCompetitiveActivate(u32 battler, u32 ability)
|
||||
{
|
||||
u32 side = GetBattlerSide(battler);
|
||||
if (ability != ABILITY_DEFIANT && ability != ABILITY_COMPETITIVE)
|
||||
return FALSE;
|
||||
// if an ally dropped the stats (except for Sticky Web), don't activate
|
||||
if (IsBattlerAlly(gSpecialStatuses[battler].changedStatsBattlerId, battler) && !gBattleScripting.stickyWebStatDrop)
|
||||
return FALSE;
|
||||
|
||||
if (GetGenConfig(GEN_CONFIG_DEFIANT_STICKY_WEB) >= GEN_9 || !gBattleScripting.stickyWebStatDrop)
|
||||
return TRUE;
|
||||
// only activate Defiant/Competitive if Web was setup by foe
|
||||
return gSideTimers[side].stickyWebBattlerSide != side;
|
||||
}
|
||||
|
||||
void PrepareStringBattle(enum StringID stringId, u32 battler)
|
||||
{
|
||||
u32 targetSide = GetBattlerSide(gBattlerTarget);
|
||||
u16 battlerAbility = GetBattlerAbility(battler);
|
||||
u16 targetAbility = GetBattlerAbility(gBattlerTarget);
|
||||
// Support for Contrary ability.
|
||||
@ -1164,10 +1178,7 @@ void PrepareStringBattle(enum StringID stringId, u32 battler)
|
||||
|
||||
// Check Defiant and Competitive stat raise whenever a stat is lowered.
|
||||
else if ((stringId == STRINGID_DEFENDERSSTATFELL || stringId == STRINGID_PKMNCUTSATTACKWITH)
|
||||
&& (targetAbility == ABILITY_DEFIANT || targetAbility == ABILITY_COMPETITIVE)
|
||||
&& gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != BATTLE_PARTNER(gBattlerTarget)
|
||||
&& ((gSpecialStatuses[gBattlerTarget].changedStatsBattlerId != gBattlerTarget) || gBattleScripting.stickyWebStatDrop == 1)
|
||||
&& !(gBattleScripting.stickyWebStatDrop == 1 && gSideTimers[targetSide].stickyWebBattlerSide == targetSide)) // Sticky Web must have been set by the foe
|
||||
&& ShouldDefiantCompetitiveActivate(gBattlerTarget, targetAbility))
|
||||
{
|
||||
gBattlerAbility = gBattlerTarget;
|
||||
BattleScriptCall(BattleScript_AbilityRaisesDefenderStat);
|
||||
|
||||
@ -19,13 +19,16 @@ SINGLE_BATTLE_TEST("Contrary raises Attack when Intimidated in a single battle",
|
||||
} SCENE {
|
||||
ABILITY_POPUP(player, ABILITY_INTIMIDATE);
|
||||
if (ability == ABILITY_CONTRARY) {
|
||||
ABILITY_POPUP(opponent, ABILITY_CONTRARY);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("The opposing Spinda's Attack rose!");
|
||||
} else {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("Mightyena's Intimidate cuts the opposing Spinda's Attack!");
|
||||
}
|
||||
HP_BAR(player, captureDamage: &results[i].damage);
|
||||
}
|
||||
FINALLY {
|
||||
} THEN {
|
||||
EXPECT_EQ(opponent->statStages[STAT_ATK], (ability == ABILITY_CONTRARY) ? DEFAULT_STAT_STAGE + 1 : DEFAULT_STAT_STAGE - 1);
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[1].damage, Q_4_12(2.25), results[0].damage);
|
||||
}
|
||||
}
|
||||
@ -49,7 +52,6 @@ DOUBLE_BATTLE_TEST("Contrary raises Attack when Intimidated in a double battle",
|
||||
} SCENE {
|
||||
ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
|
||||
if (abilityLeft == ABILITY_CONTRARY) {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_CONTRARY);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
|
||||
MESSAGE("The opposing Spinda's Attack rose!");
|
||||
} else {
|
||||
@ -57,7 +59,6 @@ DOUBLE_BATTLE_TEST("Contrary raises Attack when Intimidated in a double battle",
|
||||
MESSAGE("Mightyena's Intimidate cuts the opposing Spinda's Attack!");
|
||||
}
|
||||
if (abilityRight == ABILITY_CONTRARY) {
|
||||
ABILITY_POPUP(opponentRight, ABILITY_CONTRARY);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
|
||||
MESSAGE("The opposing Spinda's Attack rose!");
|
||||
} else {
|
||||
@ -69,8 +70,7 @@ DOUBLE_BATTLE_TEST("Contrary raises Attack when Intimidated in a double battle",
|
||||
} THEN {
|
||||
EXPECT_EQ(opponentLeft->statStages[STAT_ATK], (abilityLeft == ABILITY_CONTRARY) ? DEFAULT_STAT_STAGE+1 : DEFAULT_STAT_STAGE-1);
|
||||
EXPECT_EQ(opponentRight->statStages[STAT_ATK], (abilityRight == ABILITY_CONTRARY) ? DEFAULT_STAT_STAGE+1 : DEFAULT_STAT_STAGE-1);
|
||||
}
|
||||
FINALLY {
|
||||
} FINALLY {
|
||||
EXPECT_MUL_EQ(results[1].damageLeft, Q_4_12(2.25), results[0].damageLeft);
|
||||
EXPECT_MUL_EQ(results[1].damageRight, Q_4_12(2.25), results[0].damageRight);
|
||||
}
|
||||
|
||||
@ -139,15 +139,19 @@ SINGLE_BATTLE_TEST("Defiant activates after Sticky Web lowers Speed")
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Defiant doesn't activate after Sticky Web lowers Speed if Court Changed")
|
||||
SINGLE_BATTLE_TEST("Defiant doesn't activate after Sticky Web lowers Speed if Court Changed (Gen8)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_DEFIANT_STICKY_WEB, GEN_8);
|
||||
ASSUME(GetMoveEffect(MOVE_GROWL) == EFFECT_ATTACK_DOWN);
|
||||
ASSUME(GetMoveEffect(MOVE_STICKY_WEB) == EFFECT_STICKY_WEB);
|
||||
ASSUME(GetMoveEffect(MOVE_COURT_CHANGE) == EFFECT_COURT_CHANGE);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_MANKEY) { Ability(ABILITY_DEFIANT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STICKY_WEB); MOVE(opponent, MOVE_COURT_CHANGE); }
|
||||
TURN { SWITCH(player, 1); }
|
||||
TURN { SWITCH(player, 1); MOVE(opponent, MOVE_GROWL);}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_COURT_CHANGE, opponent);
|
||||
@ -162,19 +166,29 @@ SINGLE_BATTLE_TEST("Defiant doesn't activate after Sticky Web lowers Speed if Co
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Mankey's Attack sharply rose!");
|
||||
}
|
||||
// Defiant triggers correctly after Sticky Web
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Mankey's Attack fell!");
|
||||
ABILITY_POPUP(player, ABILITY_DEFIANT);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Mankey's Attack sharply rose!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Defiant correctly activates after Sticky Web lowers Speed if Court Changed")
|
||||
SINGLE_BATTLE_TEST("Defiant activates after Sticky Web lowers Speed if Court Changed (Gen9)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(GEN_CONFIG_DEFIANT_STICKY_WEB, GEN_9);
|
||||
ASSUME(GetMoveEffect(MOVE_GROWL) == EFFECT_ATTACK_DOWN);
|
||||
ASSUME(GetMoveEffect(MOVE_STICKY_WEB) == EFFECT_STICKY_WEB);
|
||||
ASSUME(GetMoveEffect(MOVE_COURT_CHANGE) == EFFECT_COURT_CHANGE);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_MANKEY) { Ability(ABILITY_DEFIANT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_STICKY_WEB); MOVE(opponent, MOVE_COURT_CHANGE); }
|
||||
TURN { SWITCH(player, 1); }
|
||||
TURN { MOVE(opponent, MOVE_GROWL);}
|
||||
TURN { SWITCH(player, 1); MOVE(opponent, MOVE_GROWL);}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, player);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_COURT_CHANGE, opponent);
|
||||
@ -183,12 +197,9 @@ SINGLE_BATTLE_TEST("Defiant correctly activates after Sticky Web lowers Speed if
|
||||
MESSAGE("Mankey was caught in a sticky web!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Mankey's Speed fell!");
|
||||
// Defiant doesn't activate
|
||||
NONE_OF {
|
||||
ABILITY_POPUP(player, ABILITY_DEFIANT);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Mankey's Attack sharply rose!");
|
||||
}
|
||||
ABILITY_POPUP(player, ABILITY_DEFIANT);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Mankey's Attack sharply rose!");
|
||||
// Defiant triggers correctly after Sticky Web
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
|
||||
@ -59,7 +59,6 @@ DOUBLE_BATTLE_TEST("Opportunist raises Attack only once when partner has Intimid
|
||||
} SCENE {
|
||||
ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
|
||||
if (abilityLeft == ABILITY_CONTRARY) {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_CONTRARY);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
|
||||
MESSAGE("The opposing Spinda's Attack rose!");
|
||||
} else {
|
||||
@ -67,7 +66,6 @@ DOUBLE_BATTLE_TEST("Opportunist raises Attack only once when partner has Intimid
|
||||
MESSAGE("Mightyena's Intimidate cuts the opposing Spinda's Attack!");
|
||||
}
|
||||
if (abilityRight == ABILITY_CONTRARY) {
|
||||
ABILITY_POPUP(opponentRight, ABILITY_CONTRARY);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
|
||||
MESSAGE("The opposing Spinda's Attack rose!");
|
||||
} else {
|
||||
|
||||
@ -77,7 +77,7 @@ SINGLE_BATTLE_TEST("Weak Armor does not trigger when brought in by Dragon Tail a
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Weak Armor still lowers boosts Speed if Defense can't go any lower")
|
||||
SINGLE_BATTLE_TEST("Weak Armor still boosts Speed if Defense can't go any lower")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SLUGMA) { Ability(ABILITY_WEAK_ARMOR); }
|
||||
|
||||
@ -1154,6 +1154,55 @@ DOUBLE_BATTLE_TEST("Move Animations don't leak when used - Doubles (opponentRigh
|
||||
}
|
||||
*/
|
||||
|
||||
SINGLE_BATTLE_TEST("Move Animations occur before their stat change animations - Singles (player to opponent)")
|
||||
{
|
||||
u32 j = ANIM_TEST_START_MOVE, move = 0, species = 0;
|
||||
u32 tempMove, tempSpecies;
|
||||
FORCE_MOVE_ANIM(TRUE);
|
||||
for (; j <= ANIM_TEST_END_MOVE; j++) {
|
||||
ParametrizeMovesAndSpecies(j, &tempMove, &tempSpecies);
|
||||
PARAMETRIZE { move = tempMove; species = tempSpecies; }
|
||||
}
|
||||
GIVEN {
|
||||
PLAYER(species) {
|
||||
HP(9997); MaxHP(9999); Item(ITEM_ORAN_BERRY);
|
||||
if (species == SPECIES_WOBBUFFET) Gender(MON_FEMALE);
|
||||
if (gMovesInfo[move].effect == EFFECT_LAST_RESORT) Moves(move, MOVE_POUND);
|
||||
if (species == SPECIES_KLINKLANG) Ability(ABILITY_PLUS);
|
||||
}
|
||||
PLAYER(SPECIES_WOBBUFFET) {
|
||||
Gender(MON_MALE); MaxHP(9999); Moves(MOVE_POUND);
|
||||
HP(gMovesInfo[move].effect == EFFECT_REVIVAL_BLESSING ? 0 : 9998);
|
||||
}
|
||||
OPPONENT(SPECIES_WOBBUFFET) {
|
||||
Gender(MON_MALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); Ability(ABILITY_TELEPATHY);
|
||||
if (gMovesInfo[move].effect != EFFECT_BESTOW)
|
||||
Item(ITEM_ORAN_BERRY);
|
||||
}
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); HP(9998); MaxHP(9999); SpDefense(9999); Defense(9999); }
|
||||
} WHEN {
|
||||
WhenSingles(move, player, opponent);
|
||||
} SCENE {
|
||||
if (!(gMovesInfo[move].effect == EFFECT_RECYCLE
|
||||
|| gMovesInfo[move].effect == EFFECT_BELCH
|
||||
|| gMovesInfo[move].effect == EFFECT_SPIT_UP
|
||||
|| gMovesInfo[move].effect == EFFECT_SWALLOW
|
||||
|| gMovesInfo[move].effect == EFFECT_TOPSY_TURVY)) // require a move that boosts stats before using this move
|
||||
{
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
}
|
||||
}
|
||||
SceneSingles(move, player);
|
||||
} THEN {
|
||||
FORCE_MOVE_ANIM(FALSE);
|
||||
if (gLoadFail)
|
||||
DebugPrintf("Move failed: %S (%u)", gMovesInfo[move].name, move);
|
||||
EXPECT_EQ(gLoadFail, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
// Z-Moves
|
||||
#define Z_MOVE_PARAMETERS PARAMETRIZE { zmove = MOVE_BREAKNECK_BLITZ; species = SPECIES_WOBBUFFET; move = MOVE_TACKLE; item = ITEM_NORMALIUM_Z; } \
|
||||
PARAMETRIZE { zmove = MOVE_INFERNO_OVERDRIVE; species = SPECIES_WOBBUFFET; move = MOVE_EMBER; item = ITEM_FIRIUM_Z; } \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user