Fixes Eject Pack not resolving correctly during switch in effects (#7002)
This commit is contained in:
parent
c6221fa50e
commit
2531613a52
@ -1401,10 +1401,6 @@
|
||||
.byte \battler
|
||||
.endm
|
||||
|
||||
.macro tryintimidateejectpack
|
||||
callnative BS_TryIntimidateEjectPack
|
||||
.endm
|
||||
|
||||
.macro allyswitchswapbattlers
|
||||
callnative BS_AllySwitchSwapBattler
|
||||
.endm
|
||||
|
||||
@ -7462,7 +7462,6 @@ BattleScript_IntimidateLoopIncrement:
|
||||
destroyabilitypopup
|
||||
restoretarget
|
||||
pause B_WAIT_TIME_MED
|
||||
tryintimidateejectpack
|
||||
end3
|
||||
|
||||
BattleScript_IntimidatePrevented::
|
||||
@ -7520,7 +7519,6 @@ BattleScript_SupersweetSyrupLoopIncrement:
|
||||
destroyabilitypopup
|
||||
restoretarget
|
||||
pause B_WAIT_TIME_MED
|
||||
tryintimidateejectpack
|
||||
end3
|
||||
|
||||
BattleScript_SupersweetSyrupWontDecrease:
|
||||
@ -9215,6 +9213,10 @@ BattleScript_EjectPackActivate_End2::
|
||||
call BattleScript_EjectPackActivate_Ret
|
||||
end2
|
||||
|
||||
BattleScript_EjectPackActivate_End3::
|
||||
call BattleScript_EjectPackActivate_Ret
|
||||
end3
|
||||
|
||||
BattleScript_EjectPackActivates::
|
||||
jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd
|
||||
goto BattleScript_EjectPackActivate_Ret
|
||||
|
||||
@ -160,7 +160,7 @@ struct ProtectStruct
|
||||
u32 unused:8;
|
||||
// End of 32-bit bitfield
|
||||
u16 disableEjectPack:1;
|
||||
u16 statFell:1;
|
||||
u16 tryEjectPack:1;
|
||||
u16 pranksterElevated:1;
|
||||
u16 quickDraw:1;
|
||||
u16 beakBlastCharge:1;
|
||||
|
||||
@ -60,6 +60,7 @@ enum FirstTurnEventsStates
|
||||
FIRST_TURN_EVENTS_OPPORTUNIST_1,
|
||||
FIRST_TURN_EVENTS_ITEM_EFFECTS,
|
||||
FIRST_TURN_EVENTS_OPPORTUNIST_2,
|
||||
FIRST_TURN_EVENTS_EJECT_PACK,
|
||||
FIRST_TURN_EVENTS_END,
|
||||
};
|
||||
|
||||
|
||||
@ -420,6 +420,7 @@ extern const u8 BattleScript_RedCardActivates[];
|
||||
extern const u8 BattleScript_EjectButtonActivates[];
|
||||
extern const u8 BattleScript_EjectPackActivate_Ret[];
|
||||
extern const u8 BattleScript_EjectPackActivate_End2[];
|
||||
extern const u8 BattleScript_EjectPackActivate_End3[];
|
||||
extern const u8 BattleScript_EjectPackActivates[];
|
||||
extern const u8 BattleScript_MentalHerbCureRet[];
|
||||
extern const u8 BattleScript_MentalHerbCureEnd2[];
|
||||
|
||||
@ -394,6 +394,7 @@ bool32 IsFutureSightAttackerInParty(u32 battlerAtk, u32 battlerDef, u32 move);
|
||||
bool32 HadMoreThanHalfHpNowDoesnt(u32 battler);
|
||||
void UpdateStallMons(void);
|
||||
bool32 TryRestoreHPBerries(u32 battler, enum ItemCaseId caseId);
|
||||
bool32 TrySwitchInEjectPack(enum ItemCaseId caseID);
|
||||
u32 GetMonVolatile(u32 battler, enum Volatile volatile);
|
||||
void SetMonVolatile(u32 battler, enum Volatile volatile, u32 newValue);
|
||||
u32 TryBoosterEnergy(u32 battler, u32 ability, enum ItemCaseId caseID);
|
||||
|
||||
@ -3325,7 +3325,7 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gProtectStructs[battler].fleeType = 0;
|
||||
gProtectStructs[battler].notFirstStrike = FALSE;
|
||||
gProtectStructs[battler].statRaised = FALSE;
|
||||
gProtectStructs[battler].statFell = FALSE;
|
||||
gProtectStructs[battler].tryEjectPack = FALSE;
|
||||
gProtectStructs[battler].pranksterElevated = FALSE;
|
||||
|
||||
gDisableStructs[battler].isFirstTurn = 2;
|
||||
@ -3880,6 +3880,11 @@ static void TryDoEventsBeforeFirstTurn(void)
|
||||
return;
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_EJECT_PACK:
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
if (TrySwitchInEjectPack(ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN))
|
||||
return;
|
||||
break;
|
||||
case FIRST_TURN_EVENTS_END:
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
{
|
||||
|
||||
@ -5999,7 +5999,7 @@ static inline bool32 CanEjectButtonTrigger(u32 battlerAtk, u32 battlerDef, enum
|
||||
|
||||
static inline bool32 CanEjectPackTrigger(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect)
|
||||
{
|
||||
if (gProtectStructs[battlerDef].statFell
|
||||
if (gProtectStructs[battlerDef].tryEjectPack
|
||||
&& GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_EJECT_PACK
|
||||
&& IsBattlerAlive(battlerDef)
|
||||
&& CountUsablePartyMons(battlerDef) > 0
|
||||
@ -6901,6 +6901,9 @@ static void Cmd_moveend(void)
|
||||
break;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
if (numEjectButtonBattlers > 1)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
@ -6952,7 +6955,7 @@ static void Cmd_moveend(void)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].statFell = FALSE; // restore for every possible eject pack battler
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
@ -7024,6 +7027,8 @@ static void Cmd_moveend(void)
|
||||
&& CanBattlerSwitch(gBattlerAttacker)
|
||||
&& !(moveEffect == EFFECT_HIT_SWITCH_TARGET && CanBattlerSwitch(battler)))
|
||||
{
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
effect = TRUE;
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
SaveBattlerTarget(battler); // save battler with red card
|
||||
@ -7116,6 +7121,9 @@ static void Cmd_moveend(void)
|
||||
break;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
if (numEmergencyExitBattlers > 1)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
@ -7261,6 +7269,7 @@ static void Cmd_moveend(void)
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
gBattleStruct->battlerState[gBattlerAttacker].targetsDone[i] = FALSE;
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
if (gBattleStruct->commanderActive[i] != SPECIES_NONE && !IsBattlerAlive(i))
|
||||
{
|
||||
@ -8236,6 +8245,8 @@ static void Cmd_switchineffects(void)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (TrySwitchInEjectPack(ITEMEFFECT_NONE))
|
||||
return;
|
||||
// All battlers done, end
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
gBattleStruct->battlerState[i].multipleSwitchInBattlers = FALSE;
|
||||
@ -8246,7 +8257,7 @@ static void Cmd_switchineffects(void)
|
||||
break;
|
||||
default:
|
||||
UpdateSentMonFlags(battler);
|
||||
if (!DoSwitchInEffectsForBattler(battler))
|
||||
if (!DoSwitchInEffectsForBattler(battler) && !TrySwitchInEjectPack(ITEMEFFECT_NONE))
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
break;
|
||||
}
|
||||
@ -12272,7 +12283,7 @@ static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChan
|
||||
}
|
||||
else if (!flags.onlyChecking)
|
||||
{
|
||||
gProtectStructs[battler].statFell = TRUE;
|
||||
gProtectStructs[battler].tryEjectPack = TRUE;
|
||||
gProtectStructs[battler].lashOutAffected = TRUE;
|
||||
}
|
||||
}
|
||||
@ -18526,49 +18537,6 @@ void BS_JumpIfIntimidateAbilityPrevented(void)
|
||||
}
|
||||
}
|
||||
|
||||
void BS_TryIntimidateEjectPack(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;
|
||||
gAiLogicData->ejectPackSwitch = TRUE;
|
||||
gBattleScripting.battler = affectedBattler;
|
||||
gLastUsedItem = gBattleMons[affectedBattler].item;
|
||||
RecordItemEffectBattle(affectedBattler, HOLD_EFFECT_EJECT_PACK);
|
||||
BattleScriptCall(BattleScript_EjectPackActivate_Ret);
|
||||
}
|
||||
}
|
||||
|
||||
void BS_JumpIfCanGigantamax(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler, const u8 *jumpInstr);
|
||||
|
||||
@ -6073,12 +6073,12 @@ enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 item
|
||||
|
||||
static enum ItemEffect TryEjectPack(u32 battler, enum ItemCaseId caseID)
|
||||
{
|
||||
if (gProtectStructs[battler].statFell
|
||||
if (gProtectStructs[battler].tryEjectPack
|
||||
&& !gProtectStructs[battler].disableEjectPack
|
||||
&& CountUsablePartyMons(battler) > 0
|
||||
&& !(GetMoveEffect(gCurrentMove) == EFFECT_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out
|
||||
{
|
||||
gProtectStructs[battler].statFell = FALSE;
|
||||
gProtectStructs[battler].tryEjectPack = FALSE;
|
||||
gBattleScripting.battler = battler;
|
||||
gAiLogicData->ejectPackSwitch = TRUE;
|
||||
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN)
|
||||
@ -11380,6 +11380,59 @@ bool32 TryRestoreHPBerries(u32 battler, enum ItemCaseId caseId)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 TrySwitchInEjectPack(enum ItemCaseId caseID)
|
||||
{
|
||||
// Because sorting the battlers by speed takes lots of cycles, it's better to just check if any of the battlers has the Eject items.
|
||||
u32 ejectPackBattlers = 0;
|
||||
u32 numEjectPackBattlers = 0;
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (gProtectStructs[i].tryEjectPack
|
||||
&& GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_EJECT_PACK
|
||||
&& IsBattlerAlive(i)
|
||||
&& CountUsablePartyMons(i) > 0)
|
||||
{
|
||||
ejectPackBattlers |= 1u << i;
|
||||
numEjectPackBattlers++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numEjectPackBattlers == 0)
|
||||
return FALSE;
|
||||
|
||||
u8 battlers[4] = {0, 1, 2, 3};
|
||||
if (numEjectPackBattlers > 1)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
gProtectStructs[i].tryEjectPack = FALSE;
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
u32 battler = battlers[i];
|
||||
|
||||
if (!(ejectPackBattlers & 1u << battler))
|
||||
continue;
|
||||
|
||||
gBattleScripting.battler = battler;
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN)
|
||||
{
|
||||
BattleScriptPushCursorAndCallback(BattleScript_EjectPackActivate_End3);
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_EjectPackActivate_Ret;
|
||||
}
|
||||
gAiLogicData->ejectPackSwitch = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define UNPACK_VOLATILE_GETTERS(_enum, _fieldName, _typeBitSize, ...) case _enum: return gBattleMons[battler].volatiles._fieldName;
|
||||
|
||||
// Gets the value of a volatile status flag for a certain battler
|
||||
|
||||
@ -239,3 +239,81 @@ DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUBLE_BATTLE_TEST("Eject Pack: Only the fastest Eject Pack will activate after intimidate (switch in after fainting)")
|
||||
{
|
||||
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) { HP(1); Speed(4); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
OPPONENT(SPECIES_EKANS) { Speed(6); Ability(ABILITY_INTIMIDATE); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(playerLeft, MOVE_POUND, target: opponentLeft);
|
||||
SEND_OUT(opponentLeft, 2);
|
||||
if (speed == 11)
|
||||
SEND_OUT(playerRight, 2);
|
||||
else
|
||||
SEND_OUT(playerLeft, 2);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_POUND, playerLeft);
|
||||
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 intimidate (switch in after 2 mons fainted)")
|
||||
{
|
||||
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(1); }
|
||||
OPPONENT(SPECIES_WYNAUT) { HP(1); Speed(4); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(5); }
|
||||
OPPONENT(SPECIES_WYNAUT) { Speed(4); }
|
||||
OPPONENT(SPECIES_EKANS) { Speed(6); Ability(ABILITY_INTIMIDATE); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
MOVE(playerLeft, MOVE_HYPER_VOICE);
|
||||
SEND_OUT(opponentLeft, 3);
|
||||
SEND_OUT(opponentRight, 2);
|
||||
if (speed == 11)
|
||||
SEND_OUT(playerRight, 2);
|
||||
else
|
||||
SEND_OUT(playerLeft, 2);
|
||||
}
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_HYPER_VOICE, playerLeft);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user