mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-03-21 18:04:50 -05:00
Fixes Rapid Spin and target defrost not being blocked by Sheer Force (#9252)
This commit is contained in:
parent
13118676eb
commit
199d7ae2cb
|
|
@ -5660,13 +5660,13 @@ BattleScript_MoveUsedUnfrostbite::
|
|||
BattleScript_DefrostedViaFireMove::
|
||||
printstring STRINGID_PKMNWASDEFROSTED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_TARGET
|
||||
updatestatusicon BS_SCRIPTING
|
||||
return
|
||||
|
||||
BattleScript_FrostbiteHealedViaFireMove::
|
||||
printstring STRINGID_PKMNFROSTBITEHEALED
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_TARGET
|
||||
updatestatusicon BS_SCRIPTING
|
||||
return
|
||||
|
||||
BattleScript_MoveUsedIsParalyzed::
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ bool32 ProteanTryChangeType(enum BattlerId battler, enum Ability ability, enum M
|
|||
u8 GetFirstFaintedPartyIndex(enum BattlerId battler);
|
||||
void SaveBattlerTarget(enum BattlerId battler);
|
||||
void SaveBattlerAttacker(enum BattlerId battler);
|
||||
bool32 CanBurnHitThaw(enum Move move);
|
||||
bool32 CanBurnHitThaw(enum Ability abilityAtk, enum Move move);
|
||||
|
||||
extern void (*const gBattleScriptingCommandsTable[])(void);
|
||||
extern const struct StatFractions gAccuracyStageRatios[];
|
||||
|
|
|
|||
|
|
@ -101,14 +101,14 @@ enum MoveEndState
|
|||
MOVEEND_SKY_DROP_CONFUSE,
|
||||
MOVEEND_UPDATE_LAST_MOVES,
|
||||
MOVEEND_MIRROR_MOVE,
|
||||
MOVEEND_DEFROST,
|
||||
MOVEEND_NEXT_TARGET, // Everything up until here is handled for each strike of a spread move
|
||||
MOVEEND_HP_THRESHOLD_ITEMS_TARGET, // Activation only during a multi hit move / ability (Parental Bond)
|
||||
MOVEEND_MULTIHIT_MOVE,
|
||||
MOVEEND_DEFROST,
|
||||
MOVEEND_SHEER_FORCE, // If move is Sheer Force affected, skip to Hit Escape + One
|
||||
MOVEEND_MOVE_BLOCK,
|
||||
MOVEEND_ITEM_EFFECTS_ATTACKER_2,
|
||||
MOVEEND_ABILITY_EFFECT_FOES_FAINTED, // Moxie-like abilities / Battle Bond / Magician
|
||||
MOVEEND_SHEER_FORCE, // If move is Sheer Force affected, skip to Hit Escape + One
|
||||
MOVEEND_SHELL_TRAP,
|
||||
MOVEEND_COLOR_CHANGE, // Color Change / Berserk / Anger Shell
|
||||
MOVEEND_KEE_MARANGA_HP_THRESHOLD_ITEM_TARGET,
|
||||
|
|
@ -116,14 +116,14 @@ enum MoveEndState
|
|||
MOVEEND_LIFE_ORB_SHELL_BELL,
|
||||
MOVEEND_FORM_CHANGE,
|
||||
MOVEEND_EMERGENCY_EXIT,
|
||||
MOVEEND_EJECT_PACK,
|
||||
MOVEEND_HIT_ESCAPE,
|
||||
MOVEEND_PICKPOCKET,
|
||||
MOVEEND_ITEMS_EFFECTS_ALL,
|
||||
MOVEEND_WHITE_HERB,
|
||||
MOVEEND_OPPORTUNIST,
|
||||
MOVEEND_MIRROR_HERB,
|
||||
MOVEEND_THIRD_MOVE_BLOCK,
|
||||
MOVEEND_PICKPOCKET,
|
||||
MOVEEND_EJECT_PACK,
|
||||
MOVEEND_CLEAR_BITS,
|
||||
MOVEEND_DANCER,
|
||||
MOVEEND_PURSUIT_NEXT_ACTION,
|
||||
|
|
|
|||
|
|
@ -1203,13 +1203,13 @@ static s32 AI_CheckBadMove(enum BattlerId battlerAtk, enum BattlerId battlerDef,
|
|||
}
|
||||
|
||||
// Don't use anything but super effective thawing moves if target is frozen if any other attack available
|
||||
if (((GetMoveType(move) == TYPE_FIRE && GetMovePower(move) != 0) || CanBurnHitThaw(move)) && effectiveness < UQ_4_12(2.0) && (gBattleMons[battlerDef].status1 & STATUS1_ICY_ANY))
|
||||
if (((GetMoveType(move) == TYPE_FIRE && GetMovePower(move) != 0) || CanBurnHitThaw(abilityAtk, move)) && effectiveness < UQ_4_12(2.0) && (gBattleMons[battlerDef].status1 & STATUS1_ICY_ANY))
|
||||
{
|
||||
enum Move aiMove;
|
||||
for (u32 moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
|
||||
{
|
||||
aiMove = gBattleMons[battlerAtk].moves[moveIndex];
|
||||
if (GetMoveType(aiMove) != TYPE_FIRE && !CanBurnHitThaw(aiMove) && GetMovePower(gBattleMons[battlerAtk].moves[moveIndex]) != 0)
|
||||
if (GetMoveType(aiMove) != TYPE_FIRE && !CanBurnHitThaw(abilityAtk, aiMove) && GetMovePower(gBattleMons[battlerAtk].moves[moveIndex]) != 0)
|
||||
{
|
||||
ADJUST_SCORE(-1);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
|
|||
[STRINGID_PKMNWASFROZEN] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} was frozen solid!"),
|
||||
[STRINGID_PKMNFROZENBY] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_BUFF1} froze {B_EFF_NAME_WITH_PREFIX2} solid!"), //not in gen 5+, ability popup
|
||||
[STRINGID_PKMNISFROZEN] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} is frozen solid!"),
|
||||
[STRINGID_PKMNWASDEFROSTED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX} thawed out!"),
|
||||
[STRINGID_PKMNWASDEFROSTED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} thawed out!"),
|
||||
[STRINGID_PKMNWASDEFROSTED2] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} thawed out!"),
|
||||
[STRINGID_PKMNWASDEFROSTEDBY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE} melted the ice!"),
|
||||
[STRINGID_PKMNWASPARALYZED] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} is paralyzed, so it may be unable to move!"),
|
||||
|
|
@ -805,7 +805,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
|
|||
[STRINGID_PKMNGOTFROSTBITE] = COMPOUND_STRING("{B_EFF_NAME_WITH_PREFIX} got frostbite!"),
|
||||
[STRINGID_PKMNSITEMHEALEDFROSTBITE] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s {B_LAST_ITEM} cured its frostbite!"),
|
||||
[STRINGID_ATTACKERHEALEDITSFROSTBITE] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} cured its frostbite through sheer determination so you wouldn't worry!"),
|
||||
[STRINGID_PKMNFROSTBITEHEALED] = COMPOUND_STRING("{B_DEF_NAME_WITH_PREFIX}'s frostbite was cured!"),
|
||||
[STRINGID_PKMNFROSTBITEHEALED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX}'s frostbite was cured!"),
|
||||
[STRINGID_PKMNFROSTBITEHEALED2] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s frostbite was cured!"),
|
||||
[STRINGID_PKMNFROSTBITEHEALEDBY] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s {B_CURRENT_MOVE} cured its frostbite!"),
|
||||
[STRINGID_MIRRORHERBCOPIED] = COMPOUND_STRING("{B_SCR_NAME_WITH_PREFIX} used its Mirror Herb to mirror its opponent's stat changes!"),
|
||||
|
|
|
|||
|
|
@ -2679,41 +2679,6 @@ static enum MoveEndResult MoveEndMirrorMove(void)
|
|||
return MOVEEND_RESULT_CONTINUE;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndDefrost(void)
|
||||
{
|
||||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
|
||||
if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerTarget)
|
||||
&& gBattlerAttacker != gBattlerTarget
|
||||
&& (GetBattleMoveType(gCurrentMove) == TYPE_FIRE || CanBurnHitThaw(gCurrentMove))
|
||||
&& !IsBattlerUnaffectedByMove(gBattlerTarget))
|
||||
{
|
||||
gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FREEZE;
|
||||
BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1);
|
||||
MarkBattlerForControllerExec(gBattlerTarget);
|
||||
BattleScriptCall(BattleScript_DefrostedViaFireMove);
|
||||
result = MOVEEND_RESULT_RUN_SCRIPT;
|
||||
}
|
||||
else if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE
|
||||
&& IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerTarget)
|
||||
&& gBattlerAttacker != gBattlerTarget
|
||||
&& MoveThawsUser(GetOriginallyUsedMove(gChosenMove))
|
||||
&& !IsBattlerUnaffectedByMove(gBattlerTarget))
|
||||
{
|
||||
gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FROSTBITE;
|
||||
BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1);
|
||||
MarkBattlerForControllerExec(gBattlerTarget);
|
||||
BattleScriptCall(BattleScript_FrostbiteHealedViaFireMove);
|
||||
result = MOVEEND_RESULT_RUN_SCRIPT;
|
||||
}
|
||||
|
||||
gBattleScripting.moveendState++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndNextTarget(void)
|
||||
{
|
||||
enum MoveTarget moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
|
||||
|
|
@ -2859,6 +2824,70 @@ static enum MoveEndResult MoveEndMultihitMove(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void DefrostBattler(enum BattlerId battler, u32 status)
|
||||
{
|
||||
gBattleScripting.battler = battler;
|
||||
gBattleMons[battler].status1 &= ~status;
|
||||
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndDefrost(void)
|
||||
{
|
||||
enum Ability abilityAtk = GetBattlerAbility(gBattlerAttacker);
|
||||
|
||||
while (gBattleStruct->eventState.moveEndBattler < gBattlersCount)
|
||||
{
|
||||
enum BattlerId battler = gBattleStruct->eventState.moveEndBattler++;
|
||||
|
||||
if (battler == gBattlerAttacker)
|
||||
continue;
|
||||
|
||||
if (gBattleMons[battler].status1 & STATUS1_FREEZE
|
||||
&& IsBattlerTurnDamaged(battler)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& GetBattleMoveType(gCurrentMove) == TYPE_FIRE)
|
||||
{
|
||||
DefrostBattler(battler, STATUS1_FREEZE);
|
||||
BattleScriptCall(BattleScript_DefrostedViaFireMove);
|
||||
return MOVEEND_RESULT_RUN_SCRIPT;
|
||||
}
|
||||
else if (gBattleMons[battler].status1 & STATUS1_FREEZE
|
||||
&& IsBattlerTurnDamaged(battler)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& CanBurnHitThaw(abilityAtk, gCurrentMove))
|
||||
{
|
||||
DefrostBattler(battler, STATUS1_FREEZE);
|
||||
BattleScriptCall(BattleScript_DefrostedViaFireMove);
|
||||
return MOVEEND_RESULT_RUN_SCRIPT;
|
||||
}
|
||||
else if (gBattleMons[battler].status1 & STATUS1_FROSTBITE
|
||||
&& IsBattlerTurnDamaged(battler)
|
||||
&& IsBattlerAlive(battler)
|
||||
&& MoveThawsUser(GetOriginallyUsedMove(gChosenMove)))
|
||||
{
|
||||
DefrostBattler(battler, STATUS1_FROSTBITE);
|
||||
BattleScriptCall(BattleScript_FrostbiteHealedViaFireMove);
|
||||
return MOVEEND_RESULT_RUN_SCRIPT;
|
||||
}
|
||||
}
|
||||
|
||||
gBattleStruct->eventState.moveEndBattler = 0;
|
||||
gBattleScripting.moveendState++;
|
||||
return MOVEEND_RESULT_CONTINUE;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndSheerForce(void)
|
||||
{
|
||||
if (IsSheerForceAffected(gCurrentMove, GetBattlerAbility(gBattlerAttacker)))
|
||||
gBattleScripting.moveendState = MOVEEND_ITEMS_EFFECTS_ALL;
|
||||
else
|
||||
gBattleScripting.moveendState++;
|
||||
|
||||
return MOVEEND_RESULT_CONTINUE;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndMoveBlock(void)
|
||||
{
|
||||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
|
|
@ -3142,16 +3171,6 @@ static enum MoveEndResult MoveEndAbilityEffectFoesFainted(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndSheerForce(void)
|
||||
{
|
||||
if (IsSheerForceAffected(gCurrentMove, GetBattlerAbility(gBattlerAttacker)))
|
||||
gBattleScripting.moveendState = MOVEEND_EJECT_PACK;
|
||||
else
|
||||
gBattleScripting.moveendState++;
|
||||
|
||||
return MOVEEND_RESULT_CONTINUE;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndShellTrap(void)
|
||||
{
|
||||
for (enum BattlerId battlerDef = 0; battlerDef < gBattlersCount; battlerDef++)
|
||||
|
|
@ -3374,68 +3393,6 @@ static enum MoveEndResult MoveEndEmergencyExit(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
static inline bool32 CanEjectPackTrigger(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum BattleMoveEffects moveEffect)
|
||||
{
|
||||
if (gBattleMons[battlerDef].volatiles.tryEjectPack
|
||||
&& GetBattlerHoldEffect(battlerDef) == HOLD_EFFECT_EJECT_PACK
|
||||
&& IsBattlerAlive(battlerDef)
|
||||
&& CountUsablePartyMons(battlerDef) > 0
|
||||
&& !gProtectStructs[battlerDef].disableEjectPack
|
||||
&& !(moveEffect == EFFECT_HIT_SWITCH_TARGET && CanBattlerSwitch(battlerAtk))
|
||||
&& !(moveEffect == EFFECT_PARTING_SHOT && CanBattlerSwitch(battlerAtk)))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndEjectPack(void)
|
||||
{
|
||||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
u32 ejectPackBattlers = 0;
|
||||
u32 numEjectPackBattlers = 0;
|
||||
|
||||
// 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.
|
||||
for (enum BattlerId i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (CanEjectPackTrigger(gBattlerAttacker, i, GetMoveEffect(gCurrentMove)))
|
||||
{
|
||||
ejectPackBattlers |= 1u << i;
|
||||
numEjectPackBattlers++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numEjectPackBattlers == 0)
|
||||
{
|
||||
gBattleScripting.moveendState++;
|
||||
return result;
|
||||
}
|
||||
|
||||
enum BattlerId battlers[MAX_BATTLERS_COUNT] = {0, 1, 2, 3};
|
||||
if (numEjectPackBattlers > 1)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
|
||||
for (enum BattlerId i = 0; i < gBattlersCount; i++)
|
||||
gBattleMons[i].volatiles.tryEjectPack = FALSE;
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
enum BattlerId battler = battlers[i];
|
||||
|
||||
if (!(ejectPackBattlers & 1u << battler))
|
||||
continue;
|
||||
|
||||
gBattleScripting.battler = battler;
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
gBattleStruct->battlerState[battler].usedEjectItem = TRUE;
|
||||
BattleScriptCall(BattleScript_EjectPackActivates);
|
||||
gAiLogicData->ejectPackSwitch = TRUE;
|
||||
result = MOVEEND_RESULT_RUN_SCRIPT;
|
||||
break; // Only the fastest Eject item activates
|
||||
}
|
||||
|
||||
gBattleScripting.moveendState++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndHitEscape(void)
|
||||
{
|
||||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
|
|
@ -3454,6 +3411,46 @@ static enum MoveEndResult MoveEndHitEscape(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndPickpocket(void)
|
||||
{
|
||||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE
|
||||
&& !GetBattlerPartyState(gBattlerAttacker)->isKnockedOff) // Gen3 edge case where the knocked of item was not removed
|
||||
{
|
||||
enum BattlerId battlers[MAX_BATTLERS_COUNT] = {0, 1, 2, 3};
|
||||
SortBattlersBySpeed(battlers, FALSE); // Pickpocket activates for fastest mon without item
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
enum BattlerId battlerDef = battlers[i];
|
||||
if (battlerDef != gBattlerAttacker
|
||||
&& !IsBattlerUnaffectedByMove(battlerDef)
|
||||
&& GetBattlerAbility(battlerDef) == ABILITY_PICKPOCKET
|
||||
&& IsMoveMakingContact(gBattlerAttacker, battlerDef, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove)
|
||||
&& IsBattlerTurnDamaged(battlerDef)
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove)
|
||||
&& IsBattlerAlive(battlerDef)
|
||||
&& gBattleMons[battlerDef].item == ITEM_NONE
|
||||
&& CanStealItem(battlerDef, gBattlerAttacker, gBattleMons[gBattlerAttacker].item))
|
||||
{
|
||||
gBattlerTarget = gBattlerAbility = battlerDef;
|
||||
// Battle scripting is super brittle so we shall do the item exchange now (if possible)
|
||||
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_STICKY_HOLD)
|
||||
StealTargetItem(battlerDef, gBattlerAttacker); // Target takes attacker's item
|
||||
|
||||
gEffectBattler = gBattlerAttacker;
|
||||
BattleScriptCall(BattleScript_Pickpocket); // Includes sticky hold check to print separate string
|
||||
result = MOVEEND_RESULT_RUN_SCRIPT;
|
||||
break; // Pickpocket activates on fastest mon, so exit loop.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gBattleScripting.moveendState++;
|
||||
return result;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndItemsEffectsAll(void)
|
||||
{
|
||||
while (gBattleStruct->eventState.moveEndBattler < gBattlersCount)
|
||||
|
|
@ -3574,42 +3571,64 @@ static enum MoveEndResult MoveEndThirdMoveBlock(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndPickpocket(void)
|
||||
static inline bool32 CanEjectPackTrigger(enum BattlerId battlerAtk, enum BattlerId battlerDef, enum BattleMoveEffects moveEffect)
|
||||
{
|
||||
if (gBattleMons[battlerDef].volatiles.tryEjectPack
|
||||
&& GetBattlerHoldEffect(battlerDef) == HOLD_EFFECT_EJECT_PACK
|
||||
&& IsBattlerAlive(battlerDef)
|
||||
&& CountUsablePartyMons(battlerDef) > 0
|
||||
&& !gProtectStructs[battlerDef].disableEjectPack
|
||||
&& !(moveEffect == EFFECT_HIT_SWITCH_TARGET && CanBattlerSwitch(battlerAtk))
|
||||
&& !(moveEffect == EFFECT_PARTING_SHOT && CanBattlerSwitch(battlerAtk)))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static enum MoveEndResult MoveEndEjectPack(void)
|
||||
{
|
||||
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
|
||||
u32 ejectPackBattlers = 0;
|
||||
u32 numEjectPackBattlers = 0;
|
||||
|
||||
if (IsBattlerAlive(gBattlerAttacker)
|
||||
&& gBattleMons[gBattlerAttacker].item != ITEM_NONE
|
||||
&& !GetBattlerPartyState(gBattlerAttacker)->isKnockedOff) // Gen3 edge case where the knocked of item was not removed
|
||||
// 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.
|
||||
for (enum BattlerId i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
enum BattlerId battlers[MAX_BATTLERS_COUNT] = {0, 1, 2, 3};
|
||||
SortBattlersBySpeed(battlers, FALSE); // Pickpocket activates for fastest mon without item
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
if (CanEjectPackTrigger(gBattlerAttacker, i, GetMoveEffect(gCurrentMove)))
|
||||
{
|
||||
enum BattlerId battlerDef = battlers[i];
|
||||
if (battlerDef != gBattlerAttacker
|
||||
&& !IsBattlerUnaffectedByMove(battlerDef)
|
||||
&& GetBattlerAbility(battlerDef) == ABILITY_PICKPOCKET
|
||||
&& IsMoveMakingContact(gBattlerAttacker, battlerDef, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), gCurrentMove)
|
||||
&& IsBattlerTurnDamaged(battlerDef)
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove)
|
||||
&& IsBattlerAlive(battlerDef)
|
||||
&& gBattleMons[battlerDef].item == ITEM_NONE
|
||||
&& CanStealItem(battlerDef, gBattlerAttacker, gBattleMons[gBattlerAttacker].item))
|
||||
{
|
||||
gBattlerTarget = gBattlerAbility = battlerDef;
|
||||
// Battle scripting is super brittle so we shall do the item exchange now (if possible)
|
||||
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_STICKY_HOLD)
|
||||
StealTargetItem(battlerDef, gBattlerAttacker); // Target takes attacker's item
|
||||
|
||||
gEffectBattler = gBattlerAttacker;
|
||||
BattleScriptCall(BattleScript_Pickpocket); // Includes sticky hold check to print separate string
|
||||
result = MOVEEND_RESULT_RUN_SCRIPT;
|
||||
break; // Pickpocket activates on fastest mon, so exit loop.
|
||||
}
|
||||
ejectPackBattlers |= 1u << i;
|
||||
numEjectPackBattlers++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numEjectPackBattlers == 0)
|
||||
{
|
||||
gBattleScripting.moveendState++;
|
||||
return result;
|
||||
}
|
||||
|
||||
enum BattlerId battlers[MAX_BATTLERS_COUNT] = {0, 1, 2, 3};
|
||||
if (numEjectPackBattlers > 1)
|
||||
SortBattlersBySpeed(battlers, FALSE);
|
||||
|
||||
for (enum BattlerId i = 0; i < gBattlersCount; i++)
|
||||
gBattleMons[i].volatiles.tryEjectPack = FALSE;
|
||||
|
||||
for (u32 i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
enum BattlerId battler = battlers[i];
|
||||
|
||||
if (!(ejectPackBattlers & 1u << battler))
|
||||
continue;
|
||||
|
||||
gBattleScripting.battler = battler;
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
gBattleStruct->battlerState[battler].usedEjectItem = TRUE;
|
||||
BattleScriptCall(BattleScript_EjectPackActivates);
|
||||
gAiLogicData->ejectPackSwitch = TRUE;
|
||||
result = MOVEEND_RESULT_RUN_SCRIPT;
|
||||
break; // Only the fastest Eject item activates
|
||||
}
|
||||
|
||||
gBattleScripting.moveendState++;
|
||||
return result;
|
||||
}
|
||||
|
|
@ -3803,14 +3822,14 @@ static enum MoveEndResult (*const sMoveEndHandlers[])(void) =
|
|||
[MOVEEND_SKY_DROP_CONFUSE] = MoveEndSkyDropConfuse,
|
||||
[MOVEEND_UPDATE_LAST_MOVES] = MoveEndUpdateLastMoves,
|
||||
[MOVEEND_MIRROR_MOVE] = MoveEndMirrorMove,
|
||||
[MOVEEND_DEFROST] = MoveEndDefrost,
|
||||
[MOVEEND_NEXT_TARGET] = MoveEndNextTarget,
|
||||
[MOVEEND_HP_THRESHOLD_ITEMS_TARGET] = MoveEndHpThresholdItemsTarget,
|
||||
[MOVEEND_MULTIHIT_MOVE] = MoveEndMultihitMove,
|
||||
[MOVEEND_DEFROST] = MoveEndDefrost,
|
||||
[MOVEEND_SHEER_FORCE] = MoveEndSheerForce,
|
||||
[MOVEEND_MOVE_BLOCK] = MoveEndMoveBlock,
|
||||
[MOVEEND_ITEM_EFFECTS_ATTACKER_2] = MoveEndItemEffectsAttacker2,
|
||||
[MOVEEND_ABILITY_EFFECT_FOES_FAINTED] = MoveEndAbilityEffectFoesFainted,
|
||||
[MOVEEND_SHEER_FORCE] = MoveEndSheerForce,
|
||||
[MOVEEND_SHELL_TRAP] = MoveEndShellTrap,
|
||||
[MOVEEND_COLOR_CHANGE] = MoveEndColorChange,
|
||||
[MOVEEND_KEE_MARANGA_HP_THRESHOLD_ITEM_TARGET] = MoveEndKeeMarangaHpThresholdItemTarget,
|
||||
|
|
|
|||
|
|
@ -11650,11 +11650,11 @@ static bool32 CanAbilityPreventStatLoss(enum Ability abilityDef)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 CanBurnHitThaw(enum Move move)
|
||||
bool32 CanBurnHitThaw(enum Ability abilityAtk, enum Move move)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
if (GetConfig(CONFIG_BURN_HIT_THAW) >= GEN_6)
|
||||
if (GetConfig(CONFIG_BURN_HIT_THAW) >= GEN_6 && abilityAtk != ABILITY_SHEER_FORCE)
|
||||
{
|
||||
u32 numAdditionalEffects = GetMoveAdditionalEffectCount(move);
|
||||
for (i = 0; i < numAdditionalEffects; i++)
|
||||
|
|
|
|||
|
|
@ -92,3 +92,31 @@ SINGLE_BATTLE_TEST("Rapid Spin blows away all hazards")
|
|||
EXPECT_EQ(gBattleStruct->hazardsQueue[0][5], HAZARDS_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
TO_DO_BATTLE_TEST("Rapid Spin blows away Wrap, hazards, but doesn't raise Speed when Sheer Force boosted (Gen 8)");
|
||||
|
||||
SINGLE_BATTLE_TEST("Rapid Spin doesn't blow away Wrap, hazards or raise Speed when Sheer Force boosted (Gen 9+)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_RAPID_SPIN) == EFFECT_RAPID_SPIN);
|
||||
#if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8
|
||||
ASSUME(MoveHasAdditionalEffectSelf(MOVE_RAPID_SPIN, MOVE_EFFECT_SPD_PLUS_1) == TRUE);
|
||||
#endif
|
||||
PLAYER(SPECIES_TAUROS) { Ability(ABILITY_SHEER_FORCE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_WRAP); }
|
||||
TURN { MOVE(opponent, MOVE_STEALTH_ROCK); MOVE(player, MOVE_RAPID_SPIN); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_STEALTH_ROCK, opponent);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_RAPID_SPIN, player);
|
||||
NONE_OF {
|
||||
#if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player);
|
||||
MESSAGE("Tauros's Speed rose!");
|
||||
#endif
|
||||
MESSAGE("Tauros got free of the opposing Wobbuffet's Wrap!");
|
||||
MESSAGE("Tauros blew away Stealth Rock!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,60 @@ SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Fire-type attacks")
|
|||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_EMBER); MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
MESSAGE("The opposing Wobbuffet used Ember!");
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent);
|
||||
MESSAGE("Wobbuffet thawed out!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Fire-type attacks even if Sheer Force affected")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
|
||||
OPPONENT(SPECIES_TAUROS) { Ability(ABILITY_SHEER_FORCE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_EMBER); MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent);
|
||||
MESSAGE("Wobbuffet thawed out!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Freeze is thawed by opponent's attack that can burn (Gen 6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_BURN_HIT_THAW, GEN_6);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_SCALD, MOVE_EFFECT_BURN));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SCALD); MOVE(player, MOVE_CELEBRATE); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALD, opponent);
|
||||
MESSAGE("Wobbuffet thawed out!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player);
|
||||
}
|
||||
}
|
||||
SINGLE_BATTLE_TEST("Freeze isn't thawed by opponent's attack that can burn if Sheer Force affected (Gen 6+)")
|
||||
{
|
||||
GIVEN {
|
||||
WITH_CONFIG(CONFIG_BURN_HIT_THAW, GEN_6);
|
||||
ASSUME(MoveHasAdditionalEffect(MOVE_SCALD, MOVE_EFFECT_BURN));
|
||||
PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); }
|
||||
OPPONENT(SPECIES_TAUROS) { Ability(ABILITY_SHEER_FORCE); }
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_SCALD); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALD, opponent);
|
||||
NONE_OF {
|
||||
MESSAGE("Wobbuffet thawed out!");
|
||||
STATUS_ICON(player, none: TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user