Fixes Intimidate / Eject Pack interaction (#6645)
Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
This commit is contained in:
parent
4e7fa359ef
commit
d220459a01
@ -1367,6 +1367,10 @@
|
||||
callnative BS_RestoreAttacker
|
||||
.endm
|
||||
|
||||
.macro jumpifintimidateabilityprevented
|
||||
callnative BS_JumpIfIntimidateAbilityPrevented
|
||||
.endm
|
||||
|
||||
.macro metalburstdamagecalculator failInstr:req
|
||||
callnative BS_CalcMetalBurstDmg
|
||||
.4byte \failInstr
|
||||
@ -1383,6 +1387,10 @@
|
||||
.byte \battler
|
||||
.endm
|
||||
|
||||
.macro tryintimidatejectpack
|
||||
callnative BS_TryIntimidatEjectpack
|
||||
.endm
|
||||
|
||||
.macro allyswitchswapbattlers
|
||||
callnative BS_AllySwitchSwapBattler
|
||||
.endm
|
||||
|
||||
@ -7735,13 +7735,7 @@ BattleScript_IntimidateLoop:
|
||||
jumpiftargetally BattleScript_IntimidateLoopIncrement
|
||||
jumpifabsent BS_TARGET, BattleScript_IntimidateLoopIncrement
|
||||
jumpifstatus2 BS_TARGET, STATUS2_SUBSTITUTE, BattleScript_IntimidateLoopIncrement
|
||||
.if B_UPDATED_INTIMIDATE >= GEN_8 @These abilties specifically prevent just intimidate, without blocking stat decreases
|
||||
jumpifability BS_TARGET, ABILITY_INNER_FOCUS, BattleScript_IntimidatePrevented
|
||||
jumpifability BS_TARGET, ABILITY_SCRAPPY, BattleScript_IntimidatePrevented
|
||||
jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_IntimidatePrevented
|
||||
jumpifability BS_TARGET, ABILITY_OBLIVIOUS, BattleScript_IntimidatePrevented
|
||||
.endif
|
||||
jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_IntimidateInReverse
|
||||
jumpifintimidateabilityprevented
|
||||
BattleScript_IntimidateEffect:
|
||||
copybyte sBATTLER, gBattlerAttacker
|
||||
setstatchanger STAT_ATK, 1, TRUE
|
||||
@ -7766,9 +7760,10 @@ BattleScript_IntimidateLoopIncrement:
|
||||
destroyabilitypopup
|
||||
restoretarget
|
||||
pause B_WAIT_TIME_MED
|
||||
tryintimidatejectpack
|
||||
end3
|
||||
|
||||
BattleScript_IntimidatePrevented:
|
||||
BattleScript_IntimidatePrevented::
|
||||
copybyte sBATTLER, gBattlerTarget
|
||||
call BattleScript_AbilityPopUp
|
||||
printstring STRINGID_PKMNPREVENTSSTATLOSSWITH
|
||||
@ -7788,7 +7783,7 @@ BattleScript_IntimidateContrary_WontIncrease:
|
||||
printstring STRINGID_TARGETSTATWONTGOHIGHER
|
||||
goto BattleScript_IntimidateEffect_WaitString
|
||||
|
||||
BattleScript_IntimidateInReverse:
|
||||
BattleScript_IntimidateInReverse::
|
||||
copybyte sBATTLER, gBattlerTarget
|
||||
call BattleScript_AbilityPopUpTarget
|
||||
pause B_WAIT_TIME_SHORT
|
||||
@ -9533,7 +9528,7 @@ BattleScript_EjectButtonActivates::
|
||||
printstring STRINGID_EJECTBUTTONACTIVATE
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
removeitem BS_SCRIPTING
|
||||
undodynamax BS_SCRIPTING
|
||||
undodynamax BS_SCRIPTING
|
||||
makeinvisible BS_SCRIPTING
|
||||
openpartyscreen BS_SCRIPTING, BattleScript_EjectButtonEnd
|
||||
copybyte sSAVED_BATTLER, sBATTLER
|
||||
|
||||
@ -183,7 +183,8 @@ struct ProtectStruct
|
||||
u16 eatMirrorHerb:1;
|
||||
u16 activateOpportunist:2; // 2 - to copy stats. 1 - stats copied (do not repeat). 0 - no stats to copy
|
||||
u16 usedAllySwitch:1;
|
||||
u16 padding:2;
|
||||
u16 lashOutAffected:1;
|
||||
u16 padding:1;
|
||||
// End of 16-bit bitfield
|
||||
u32 physicalDmg;
|
||||
u32 specialDmg;
|
||||
|
||||
@ -170,6 +170,8 @@ extern const u8 BattleScript_RainDishActivates[];
|
||||
extern const u8 BattleScript_SandstreamActivates[];
|
||||
extern const u8 BattleScript_ShedSkinActivates[];
|
||||
extern const u8 BattleScript_IntimidateActivates[];
|
||||
extern const u8 BattleScript_IntimidatePrevented[];
|
||||
extern const u8 BattleScript_IntimidateInReverse[];
|
||||
extern const u8 BattleScript_DroughtActivates[];
|
||||
extern const u8 BattleScript_TookAttack[];
|
||||
extern const u8 BattleScript_SturdyPreventsOHKO[];
|
||||
|
||||
@ -3751,6 +3751,7 @@ static void TryDoEventsBeforeFirstTurn(void)
|
||||
{
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
gBattleStruct->monToSwitchIntoId[i] = PARTY_SIZE; // Included here because switches can happen before during set ups (eg. eject pack)
|
||||
struct Pokemon *party = GetBattlerParty(i);
|
||||
struct Pokemon *mon = &party[gBattlerPartyIndexes[i]];
|
||||
if (!IsBattlerAlive(i) || gBattleMons[i].species == SPECIES_NONE || GetMonData(mon, MON_DATA_IS_EGG))
|
||||
@ -4846,7 +4847,6 @@ s8 GetBattleMovePriority(u32 battler, u16 move)
|
||||
return priority;
|
||||
}
|
||||
|
||||
// Function for AI with variables provided as arguments to speed the computation time
|
||||
s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2,
|
||||
u32 holdEffectBattler1, u32 holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2)
|
||||
{
|
||||
@ -5135,6 +5135,7 @@ static void TurnValuesCleanUp(bool8 var0)
|
||||
|
||||
gSpecialStatuses[i].parentalBondState = PARENTAL_BOND_OFF;
|
||||
gBattleStruct->battlerState[i].usedEjectItem = FALSE;
|
||||
gProtectStructs[i].lashOutAffected = FALSE;
|
||||
}
|
||||
|
||||
gSideStatuses[B_SIDE_PLAYER] &= ~(SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK);
|
||||
|
||||
@ -7149,6 +7149,9 @@ static void Cmd_moveend(void)
|
||||
if (numEjectPackBattlers > 1)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].statFell = FALSE; // restore for every possible eject pack battler
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
u32 battler = battlers[i];
|
||||
@ -7167,7 +7170,6 @@ static void Cmd_moveend(void)
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectPackActivates;
|
||||
AI_DATA->ejectPackSwitch = TRUE;
|
||||
gProtectStructs[battler].statFell = FALSE;
|
||||
break; // Only the fastest Eject item activates
|
||||
}
|
||||
}
|
||||
@ -12588,7 +12590,8 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
|
||||
}
|
||||
else
|
||||
{
|
||||
gProtectStructs[battler].statFell = TRUE; // Eject pack, lash out
|
||||
gProtectStructs[battler].statFell = TRUE;
|
||||
gProtectStructs[battler].lashOutAffected = TRUE;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL
|
||||
}
|
||||
}
|
||||
@ -18811,3 +18814,87 @@ void BS_SetSteelsurge(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
|
||||
void BS_JumpIfIntimidateAbilityPrevented(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
|
||||
u32 hasAbility = FALSE;
|
||||
u32 ability = GetBattlerAbility(gBattlerTarget);
|
||||
|
||||
switch (ability)
|
||||
{
|
||||
case ABILITY_INNER_FOCUS:
|
||||
case ABILITY_SCRAPPY:
|
||||
case ABILITY_OWN_TEMPO:
|
||||
case ABILITY_OBLIVIOUS:
|
||||
if (B_UPDATED_INTIMIDATE >= GEN_8)
|
||||
{
|
||||
hasAbility = TRUE;
|
||||
gBattlescriptCurrInstr = BattleScript_IntimidatePrevented;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
break;
|
||||
case ABILITY_GUARD_DOG:
|
||||
hasAbility = TRUE;
|
||||
gBattlescriptCurrInstr = BattleScript_IntimidateInReverse;
|
||||
break;
|
||||
default:
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hasAbility)
|
||||
{
|
||||
gLastUsedAbility = ability;
|
||||
gBattlerAbility = gBattlerTarget;
|
||||
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
|
||||
}
|
||||
}
|
||||
|
||||
void BS_TryIntimidatEjectpack(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
|
||||
u32 affectedBattler = 0xFF;
|
||||
u32 battler = BATTLE_OPPOSITE(gBattlerAttacker);
|
||||
u32 partnerBattler = BATTLE_PARTNER(battler);
|
||||
|
||||
bool32 ejectPackBattler = CanEjectPackTrigger(gBattlerAttacker, battler, MOVE_NONE);
|
||||
bool32 ejectPackPartnerBattler = CanEjectPackTrigger(gBattlerAttacker, partnerBattler, MOVE_NONE);
|
||||
|
||||
if (ejectPackBattler && ejectPackPartnerBattler)
|
||||
{
|
||||
u32 battlerSpeed = GetBattlerTotalSpeedStat(battler);
|
||||
u32 partnerbattlerSpeed = GetBattlerTotalSpeedStat(partnerBattler);
|
||||
|
||||
if (battlerSpeed >= partnerbattlerSpeed)
|
||||
affectedBattler = battler;
|
||||
else
|
||||
affectedBattler = partnerBattler;
|
||||
}
|
||||
else if (ejectPackBattler)
|
||||
{
|
||||
affectedBattler = battler;
|
||||
}
|
||||
else if (ejectPackPartnerBattler)
|
||||
{
|
||||
affectedBattler = partnerBattler;
|
||||
}
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
if (affectedBattler != 0xFF)
|
||||
{
|
||||
gProtectStructs[battler].statFell = FALSE;
|
||||
gProtectStructs[partnerBattler].statFell = FALSE;
|
||||
AI_DATA->ejectPackSwitch = TRUE;
|
||||
gBattleScripting.battler = affectedBattler;
|
||||
gLastUsedItem = gBattleMons[affectedBattler].item;
|
||||
RecordItemEffectBattle(affectedBattler, HOLD_EFFECT_EJECT_PACK);
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8449,9 +8449,6 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
|
||||
gBattlescriptCurrInstr = BattleScript_WhiteHerbRet;
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_EJECT_PACK:
|
||||
effect = TryEjectPack(battler, ITEMEFFECT_ON_SWITCH_IN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -9229,7 +9226,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData
|
||||
basePower *= 2;
|
||||
break;
|
||||
case EFFECT_LASH_OUT:
|
||||
if (gProtectStructs[battlerAtk].statFell)
|
||||
if (gProtectStructs[battlerAtk].lashOutAffected)
|
||||
basePower *= 2;
|
||||
break;
|
||||
case EFFECT_EXPLOSION:
|
||||
|
||||
@ -104,7 +104,7 @@ DOUBLE_BATTLE_TEST("Intimidate doesn't activate on an empty field in a double ba
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Intimidate and Eject Button force the opponent to Attack")
|
||||
SINGLE_BATTLE_TEST("Intimidate and Eject Button don't force the opponent to Attack")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gItemsInfo[ITEM_EJECT_BUTTON].holdEffect == HOLD_EFFECT_EJECT_BUTTON);
|
||||
@ -365,6 +365,7 @@ DOUBLE_BATTLE_TEST("Intimidate will correctly decrease the attack of the second
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
ABILITY_POPUP(playerLeft, ABILITY_PROTOSYNTHESIS);
|
||||
@ -372,7 +373,6 @@ DOUBLE_BATTLE_TEST("Intimidate will correctly decrease the attack of the second
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
|
||||
}
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
}
|
||||
}
|
||||
|
||||
@ -390,3 +390,48 @@ SINGLE_BATTLE_TEST("Intimdate does not lose timing after mega evolution and swit
|
||||
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Intimidate drop down both opposing atk before eject pack has the chance to activate")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_WYNAUT);
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
} WHEN {
|
||||
TURN { SWITCH(opponentLeft, 2); SEND_OUT(playerLeft, 2); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Intimidate will not miss timing for competitive")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_MILOTIC) { Ability(ABILITY_COMPETITIVE); }
|
||||
PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
OPPONENT(SPECIES_WYNAUT);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); }
|
||||
} WHEN {
|
||||
TURN { SWITCH(opponentLeft, 2); SEND_OUT(playerLeft, 2); }
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
ABILITY_POPUP(playerRight, ABILITY_COMPETITIVE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
ABILITY_POPUP(playerLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight);
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,3 +160,74 @@ SINGLE_BATTLE_TEST("Eject Pack will miss timing to switch out user if Eject Butt
|
||||
EXPECT(opponent->species == SPECIES_WYNAUT);
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after intimidate")
|
||||
{
|
||||
u32 speed;
|
||||
|
||||
PARAMETRIZE { speed = 1; }
|
||||
PARAMETRIZE { speed = 11; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(speed); Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(3); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(4); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
OPPONENT(SPECIES_EKANS) { Speed(6); Ability(ABILITY_INTIMIDATE); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
SWITCH(opponentLeft, 2);
|
||||
if (speed == 11)
|
||||
SEND_OUT(playerRight, 2);
|
||||
else
|
||||
SEND_OUT(playerLeft, 2);
|
||||
}
|
||||
} SCENE {
|
||||
ABILITY_POPUP(opponentLeft, ABILITY_INTIMIDATE);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
if (speed == 11) {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
} else {
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after a move stat drop")
|
||||
{
|
||||
u32 speed;
|
||||
|
||||
PARAMETRIZE { speed = 1; }
|
||||
PARAMETRIZE { speed = 11; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(10); Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_WYNAUT) { Speed(speed); Item(ITEM_EJECT_PACK); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(3); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(4); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(opponentLeft, MOVE_BUBBLE);
|
||||
if (speed == 11)
|
||||
SEND_OUT(playerRight, 2);
|
||||
else
|
||||
SEND_OUT(playerLeft, 2);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_BUBBLE, opponentLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight);
|
||||
if (speed == 11) {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
} else {
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerRight);
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user