Convert Status4 to volatiles (#7411)
Co-authored-by: hedara90 <90hedara@gmail.com>
This commit is contained in:
parent
1fb895ad48
commit
acc82e7d79
@ -416,8 +416,11 @@
|
||||
.4byte \argPtr
|
||||
.endm
|
||||
|
||||
.macro unused_0x47
|
||||
.macro jumpfifsemiinvulnerable battler:req, state:req, jumpInstr:req
|
||||
.byte 0x47
|
||||
.byte \battler
|
||||
.byte \state
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro unused_0x48
|
||||
|
||||
@ -2613,7 +2613,8 @@ BattleScript_EffectGravitySuccess::
|
||||
selectfirstvalidtarget
|
||||
BattleScript_GravityLoop:
|
||||
movevaluescleanup
|
||||
jumpifstatus3 BS_TARGET, STATUS3_ON_AIR | STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS, BattleScript_GravityLoopDrop
|
||||
jumpfifsemiinvulnerable BS_TARGET, STATE_ON_AIR, BattleScript_GravityLoopDrop
|
||||
jumpifstatus3 BS_TARGET, STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS, BattleScript_GravityLoopDrop
|
||||
goto BattleScript_GravityLoopEnd
|
||||
BattleScript_GravityLoopDrop:
|
||||
gravityonairbornemons
|
||||
@ -6982,7 +6983,7 @@ BattleScript_YawnMakesAsleep::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_EFFECT_BATTLER
|
||||
waitstate
|
||||
jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_SKY_DROPPED, BattleScript_YawnEnd
|
||||
jumpfifsemiinvulnerable BS_EFFECT_BATTLER, STATE_SKY_DROP, BattleScript_YawnEnd
|
||||
makevisible BS_EFFECT_BATTLER
|
||||
skydropyawn
|
||||
BattleScript_YawnEnd:
|
||||
|
||||
@ -1074,7 +1074,6 @@ extern u8 gBideTarget[MAX_BATTLERS_COUNT];
|
||||
extern u32 gSideStatuses[NUM_BATTLE_SIDES];
|
||||
extern struct SideTimer gSideTimers[NUM_BATTLE_SIDES];
|
||||
extern u32 gStatuses3[MAX_BATTLERS_COUNT];
|
||||
extern u32 gStatuses4[MAX_BATTLERS_COUNT];
|
||||
extern struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT];
|
||||
extern u16 gPauseCounterBattle;
|
||||
extern u16 gPaydayMoney;
|
||||
|
||||
@ -184,7 +184,6 @@ bool32 HasAnyKnownMove(u32 battlerId);
|
||||
bool32 IsAromaVeilProtectedEffect(enum BattleMoveEffects moveEffect);
|
||||
bool32 IsNonVolatileStatusMove(u32 moveEffect);
|
||||
bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, u32 atkAbility);
|
||||
bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move);
|
||||
bool32 IsHazardMove(u32 move);
|
||||
bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move);
|
||||
bool32 IsBattlerDamagedByStatus(u32 battler);
|
||||
@ -208,7 +207,6 @@ bool32 IsSwitchOutEffect(enum BattleMoveEffects effect);
|
||||
bool32 IsChaseEffect(enum BattleMoveEffects effect);
|
||||
bool32 IsAttackBoostMoveEffect(enum BattleMoveEffects effect);
|
||||
bool32 IsUngroundingEffect(enum BattleMoveEffects effect);
|
||||
bool32 IsSemiInvulnerable(u32 battlerDef, u32 move);
|
||||
bool32 HasMoveWithFlag(u32 battler, MoveFlag getFlag);
|
||||
bool32 IsHazardClearingMove(u32 move);
|
||||
bool32 IsSubstituteEffect(enum BattleMoveEffects effect);
|
||||
|
||||
@ -406,5 +406,7 @@ bool32 IsHazardOnSideAndClear(u32 side, enum Hazards hazardType);
|
||||
void RemoveHazardFromField(u32 side, enum Hazards hazardType);
|
||||
bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef, u32 move, enum FunctionCallOption option);
|
||||
u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect);
|
||||
bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander);
|
||||
bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move);
|
||||
|
||||
#endif // GUARD_BATTLE_UTIL_H
|
||||
|
||||
@ -169,8 +169,14 @@ enum VolatileFlags
|
||||
F(VOLATILE_FORESIGHT, foresight, (u32, 1)) \
|
||||
F(VOLATILE_DRAGON_CHEER, dragonCheer, (u32, 1), V_BATON_PASSABLE) \
|
||||
F(VOLATILE_FOCUS_ENERGY, focusEnergy, (u32, 1), V_BATON_PASSABLE) \
|
||||
F(VOLATILE_SEMI_INVULNERABLE, semiInvulnerable, (u32, 5)) \
|
||||
F(VOLATILE_ELECTRIFIED, electrified, (u32, 1)) \
|
||||
F(VOLATILE_MUD_SPORT, mudSport, (u32, 1), V_BATON_PASSABLE) \
|
||||
F(VOLATILE_WATER_SPORT, waterSport, (u32, 1), V_BATON_PASSABLE)
|
||||
F(VOLATILE_WATER_SPORT, waterSport, (u32, 1), V_BATON_PASSABLE) \
|
||||
F(VOLATILE_INFINITE_CONFUSION, infiniteConfusion, (u32, 1)) \
|
||||
F(VOLATILE_SALT_CURE, saltCure, (u32, 1)) \
|
||||
F(VOLATILE_SYRUP_BOMB, syrupBomb, (u32, 1)) \
|
||||
F(VOLATILE_GLAIVE_RUSH, glaiveRush, (u32, 1))
|
||||
|
||||
/* Use within a macro to get the maximum allowed value for a volatile. Requires _typeMaxValue as input. */
|
||||
#define GET_VOLATILE_MAXIMUM(_typeMaxValue, ...) INVOKE_WITH_B(GET_VOLATILE_MAXIMUM_, _typeMaxValue)
|
||||
@ -188,44 +194,13 @@ enum Volatile
|
||||
// Helper macros
|
||||
#define INFATUATED_WITH(battler) (battler + 1)
|
||||
|
||||
// Old flags
|
||||
#define STATUS2_CONFUSION (1 << 0 | 1 << 1 | 1 << 2)
|
||||
#define STATUS2_CONFUSION_TURN(num) ((num) << 0)
|
||||
#define STATUS2_FLINCHED (1 << 3)
|
||||
#define STATUS2_UPROAR (1 << 4 | 1 << 5 | 1 << 6)
|
||||
#define STATUS2_UPROAR_TURN(num) ((num) << 4)
|
||||
#define STATUS2_TORMENT (1 << 7)
|
||||
#define STATUS2_BIDE (1 << 8 | 1 << 9)
|
||||
#define STATUS2_BIDE_TURN(num) (((num) << 8) & STATUS2_BIDE)
|
||||
#define STATUS2_LOCK_CONFUSE (1 << 10 | 1 << 11) // e.g. Thrash
|
||||
#define STATUS2_LOCK_CONFUSE_TURN(num)((num) << 10)
|
||||
#define STATUS2_MULTIPLETURNS (1 << 12)
|
||||
#define STATUS2_WRAPPED (1 << 13)
|
||||
#define STATUS2_POWDER (1 << 14)
|
||||
//#define STATUS2_UNUSED (1 << 15)
|
||||
#define STATUS2_INFATUATION (1 << 16 | 1 << 17 | 1 << 18 | 1 << 19) // 4 bits, one for every battler
|
||||
#define STATUS2_INFATUATED_WITH(battler) (1u << (battler + 16))
|
||||
#define STATUS2_DEFENSE_CURL (1 << 20)
|
||||
#define STATUS2_TRANSFORMED (1 << 21)
|
||||
#define STATUS2_RECHARGE (1 << 22)
|
||||
#define STATUS2_RAGE (1 << 23)
|
||||
#define STATUS2_SUBSTITUTE (1 << 24)
|
||||
#define STATUS2_DESTINY_BOND (1 << 25)
|
||||
#define STATUS2_ESCAPE_PREVENTION (1 << 26)
|
||||
#define STATUS2_NIGHTMARE (1 << 27)
|
||||
#define STATUS2_CURSED (1 << 28)
|
||||
#define STATUS2_FORESIGHT (1 << 29)
|
||||
#define STATUS2_DRAGON_CHEER (1 << 30)
|
||||
#define STATUS2_FOCUS_ENERGY (1 << 31)
|
||||
#define STATUS2_FOCUS_ENERGY_ANY (STATUS2_DRAGON_CHEER | STATUS2_FOCUS_ENERGY)
|
||||
|
||||
#define STATUS3_LEECHSEED_BATTLER (1 << 0 | 1 << 1) // The battler to receive HP from Leech Seed
|
||||
#define STATUS3_LEECHSEED (1 << 2)
|
||||
#define STATUS3_ALWAYS_HITS (1 << 3 | 1 << 4)
|
||||
#define STATUS3_ALWAYS_HITS_TURN(num) (((num) << 3) & STATUS3_ALWAYS_HITS) // "Always Hits" is set as a 2 turn timer, i.e. next turn is the last turn when it's active
|
||||
#define STATUS3_PERISH_SONG (1 << 5)
|
||||
#define STATUS3_ON_AIR (1 << 6)
|
||||
#define STATUS3_UNDERGROUND (1 << 7)
|
||||
#define STATUS3_UNUSED_6 (1 << 6)
|
||||
#define STATUS3_UNUSED_7 (1 << 7)
|
||||
#define STATUS3_MINIMIZED (1 << 8)
|
||||
#define STATUS3_CHARGED_UP (1 << 9)
|
||||
#define STATUS3_ROOTED (1 << 10)
|
||||
@ -233,33 +208,39 @@ enum Volatile
|
||||
#define STATUS3_YAWN_TURN(num) (((num) << 11) & STATUS3_YAWN)
|
||||
#define STATUS3_IMPRISONED_OTHERS (1 << 13)
|
||||
#define STATUS3_GRUDGE (1 << 14)
|
||||
#define STATUS3_COMMANDER (1 << 15)
|
||||
#define STATUS3_UNUSED_15 (1 << 15)
|
||||
#define STATUS3_GASTRO_ACID (1 << 16)
|
||||
#define STATUS3_EMBARGO (1 << 17)
|
||||
#define STATUS3_UNDERWATER (1 << 18)
|
||||
#define STATUS3_UNUSED_18 (1 << 18)
|
||||
#define STATUS3_UNUSED_19 (1 << 19)
|
||||
#define STATUS3_UNUSED_20 (1 << 20)
|
||||
#define STATUS3_SMACKED_DOWN (1 << 21)
|
||||
#define STATUS3_UNUSED_22 (1 << 22)
|
||||
#define STATUS3_TELEKINESIS (1 << 23)
|
||||
#define STATUS3_PHANTOM_FORCE (1 << 24)
|
||||
#define STATUS3_UNUSED_24 (1 << 24)
|
||||
#define STATUS3_MIRACLE_EYED (1 << 25)
|
||||
#define STATUS3_MAGNET_RISE (1 << 26)
|
||||
#define STATUS3_HEAL_BLOCK (1 << 27)
|
||||
#define STATUS3_AQUA_RING (1 << 28)
|
||||
#define STATUS3_LASER_FOCUS (1 << 29)
|
||||
#define STATUS3_POWER_TRICK (1 << 30)
|
||||
#define STATUS3_SKY_DROPPED (1 << 31) // Target of Sky Drop
|
||||
#define STATUS3_SEMI_INVULNERABLE_NO_COMMANDER (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER | STATUS3_PHANTOM_FORCE) // Exception for Transform / Imposter
|
||||
#define STATUS3_SEMI_INVULNERABLE (STATUS3_SEMI_INVULNERABLE_NO_COMMANDER | STATUS3_COMMANDER)
|
||||
|
||||
#define STATUS4_ELECTRIFIED (1 << 0)
|
||||
#define STATUS4_MUD_SPORT (1 << 1) // Only used if B_SPORT_TURNS < GEN_6
|
||||
#define STATUS4_WATER_SPORT (1 << 2) // Only used if B_SPORT_TURNS < GEN_6
|
||||
#define STATUS4_INFINITE_CONFUSION (1 << 3) // Used for Berserk Gene
|
||||
#define STATUS4_SALT_CURE (1 << 4)
|
||||
#define STATUS4_SYRUP_BOMB (1 << 5)
|
||||
#define STATUS4_GLAIVE_RUSH (1 << 6)
|
||||
enum SemiInvulnerableState
|
||||
{
|
||||
STATE_NONE,
|
||||
STATE_UNDERGROUND,
|
||||
STATE_UNDERWATER,
|
||||
STATE_ON_AIR,
|
||||
STATE_PHANTOM_FORCE,
|
||||
STATE_SKY_DROP,
|
||||
STATE_COMMANDER,
|
||||
};
|
||||
|
||||
enum SemiInvulnerableExclusion
|
||||
{
|
||||
CHECK_ALL,
|
||||
EXCLUDE_COMMANDER,
|
||||
};
|
||||
|
||||
#define HITMARKER_STRING_PRINTED (1 << 4)
|
||||
#define HITMARKER_IGNORE_BIDE (1 << 5)
|
||||
|
||||
@ -489,7 +489,7 @@ static inline u32 GetMoveTwoTurnAttackStringId(u32 moveId)
|
||||
|
||||
static inline u32 GetMoveTwoTurnAttackStatus(u32 moveId)
|
||||
{
|
||||
return UNCOMPRESS_BITS(gMovesInfo[SanitizeMoveId(moveId)].argument.twoTurnAttack.status);
|
||||
return gMovesInfo[SanitizeMoveId(moveId)].argument.twoTurnAttack.status;
|
||||
}
|
||||
|
||||
static inline u32 GetMoveTwoTurnAttackWeather(u32 moveId)
|
||||
|
||||
@ -381,12 +381,7 @@ struct BattlePokemon
|
||||
/*0x45*/ u32 experience;
|
||||
/*0x49*/ u32 personality;
|
||||
/*0x4D*/ u32 status1;
|
||||
/*0x51*/ union {
|
||||
struct {
|
||||
u32 status2; // To be expanded to include Status3/4
|
||||
};
|
||||
struct Volatiles volatiles;
|
||||
};
|
||||
/*0x51*/ struct Volatiles volatiles;
|
||||
/*0x5D*/ u32 otId;
|
||||
/*0x61*/ u8 metLevel;
|
||||
/*0x62*/ bool8 isShiny;
|
||||
|
||||
@ -1083,7 +1083,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
if (IsPowderMove(move) && !IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef]))
|
||||
RETURN_SCORE_MINUS(10);
|
||||
|
||||
if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY))
|
||||
if (!BreaksThroughSemiInvulnerablity(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMove, CONSIDER_PRIORITY))
|
||||
RETURN_SCORE_MINUS(10);
|
||||
|
||||
if (IsTwoTurnNotSemiInvulnerableMove(battlerAtk, move) && CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
@ -2363,7 +2363,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
ADJUST_SCORE(-10); // Don't Fly/dig/etc if opponent is going to fly/dig/etc after you
|
||||
|
||||
if (BattlerWillFaintFromWeather(battlerAtk, aiData->abilities[battlerAtk])
|
||||
&& GetMoveTwoTurnAttackStatus(move) == STATUS3_ON_AIR)
|
||||
&& GetMoveTwoTurnAttackStatus(move) == STATE_ON_AIR)
|
||||
ADJUST_SCORE(-10); // Attacker will faint while in the air
|
||||
break;
|
||||
case EFFECT_HEALING_WISH: //healing wish, lunar dance
|
||||
@ -4524,7 +4524,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
|| predictedEffect == EFFECT_MISTY_EXPLOSION
|
||||
|| predictedEffect == EFFECT_PROTECT))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
else if (predictedEffect == EFFECT_SEMI_INVULNERABLE && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE))
|
||||
else if (predictedEffect == EFFECT_SEMI_INVULNERABLE && !IsSemiInvulnerable(battlerDef, CHECK_ALL))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -482,7 +482,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
|
||||
u32 opposingBattler = GetOppositeBattler(battler);
|
||||
u32 incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData);
|
||||
u32 incomingType = CheckDynamicMoveType(GetBattlerMon(opposingBattler), incomingMove, opposingBattler, MON_IN_BATTLE);
|
||||
bool32 isOpposingBattlerChargingOrInvulnerable = (IsSemiInvulnerable(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove));
|
||||
bool32 isOpposingBattlerChargingOrInvulnerable = !BreaksThroughSemiInvulnerablity(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove);
|
||||
s32 i, j;
|
||||
|
||||
if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING))
|
||||
@ -615,7 +615,7 @@ static bool32 ShouldSwitchIfOpponentChargingOrInvulnerable(u32 battler)
|
||||
u32 opposingBattler = GetOppositeBattler(battler);
|
||||
u32 incomingMove = GetIncomingMove(battler, opposingBattler, gAiLogicData);
|
||||
|
||||
bool32 isOpposingBattlerChargingOrInvulnerable = (IsSemiInvulnerable(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove));
|
||||
bool32 isOpposingBattlerChargingOrInvulnerable = !BreaksThroughSemiInvulnerablity(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove);
|
||||
|
||||
if (IsDoubleBattle() || !(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING))
|
||||
return FALSE;
|
||||
@ -2436,7 +2436,7 @@ static bool32 ShouldUseItem(u32 battler)
|
||||
|
||||
// If teaming up with player and Pokemon is on the right, or Pokemon is currently held by Sky Drop
|
||||
if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(battler) == B_POSITION_PLAYER_RIGHT)
|
||||
|| gStatuses3[battler] & STATUS3_SKY_DROPPED)
|
||||
|| gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP)
|
||||
return FALSE;
|
||||
|
||||
if (gStatuses3[battler] & STATUS3_EMBARGO)
|
||||
|
||||
@ -457,7 +457,9 @@ bool32 IsBattlerTrapped(u32 battlerAtk, u32 battlerDef)
|
||||
return TRUE;
|
||||
if (gBattleMons[battlerDef].volatiles.escapePrevention)
|
||||
return TRUE;
|
||||
if (gStatuses3[battlerDef] & (STATUS3_ROOTED | STATUS3_SKY_DROPPED))
|
||||
if (gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_SKY_DROP)
|
||||
return TRUE;
|
||||
if (gStatuses3[battlerDef] & STATUS3_ROOTED)
|
||||
return TRUE;
|
||||
if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK)
|
||||
return TRUE;
|
||||
@ -1860,60 +1862,6 @@ bool32 IsMoveRedirectionPrevented(u32 battlerAtk, u32 move, u32 atkAbility)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsSemiInvulnerable(u32 battlerDef, u32 move)
|
||||
{
|
||||
if (gStatuses3[battlerDef] & STATUS3_PHANTOM_FORCE)
|
||||
return TRUE;
|
||||
else if (gBattleStruct->battlerState[battlerDef].commandingDondozo)
|
||||
return TRUE;
|
||||
else if (!MoveDamagesAirborne(move) && gStatuses3[battlerDef] & STATUS3_ON_AIR)
|
||||
return TRUE;
|
||||
else if (!MoveDamagesUnderWater(move) && gStatuses3[battlerDef] & STATUS3_UNDERWATER)
|
||||
return TRUE;
|
||||
else if (!MoveDamagesUnderground(move) && gStatuses3[battlerDef] & STATUS3_UNDERGROUND)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
{
|
||||
u32 weather;
|
||||
if (IsSemiInvulnerable(battlerDef, move))
|
||||
return FALSE;
|
||||
|
||||
//TODO - anticipate protect move?
|
||||
|
||||
// always hits
|
||||
if (gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS || gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk)
|
||||
return TRUE;
|
||||
|
||||
if (gAiLogicData->abilities[battlerDef] == ABILITY_NO_GUARD || gAiLogicData->abilities[battlerAtk] == ABILITY_NO_GUARD)
|
||||
return TRUE;
|
||||
|
||||
u32 nonVolatileStatus = GetMoveNonVolatileStatus(move);
|
||||
if (B_TOXIC_NEVER_MISS >= GEN_6
|
||||
&& nonVolatileStatus == MOVE_EFFECT_TOXIC
|
||||
&& IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON))
|
||||
return TRUE;
|
||||
|
||||
// discouraged from hitting
|
||||
weather = AI_GetWeather();
|
||||
if ((weather & B_WEATHER_SUN) && MoveHas50AccuracyInSun(move))
|
||||
return FALSE;
|
||||
|
||||
if ((weather & B_WEATHER_RAIN) && MoveAlwaysHitsInRain(move))
|
||||
return TRUE;
|
||||
if ((weather & B_WEATHER_ICY_ANY) && MoveAlwaysHitsInHailSnow(move))
|
||||
return TRUE;
|
||||
if (B_MINIMIZE_DMG_ACC >= GEN_6 && (gStatuses3[battlerDef] & STATUS3_MINIMIZED) && MoveIncreasesPowerToMinimizedTargets(move))
|
||||
return TRUE;
|
||||
if (GetMoveAccuracy(move) == 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move)
|
||||
{
|
||||
enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[battlerDef];
|
||||
@ -1972,8 +1920,8 @@ bool32 IsBattlerDamagedByStatus(u32 battler)
|
||||
|| gBattleMons[battler].volatiles.wrapped
|
||||
|| gBattleMons[battler].volatiles.nightmare
|
||||
|| gBattleMons[battler].volatiles.cursed
|
||||
|| gBattleMons[battler].volatiles.saltCure
|
||||
|| gStatuses3[battler] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED)
|
||||
|| gStatuses4[battler] & (STATUS4_SALT_CURE)
|
||||
|| gSideStatuses[GetBattlerSide(battler)] & (SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_DAMAGE_NON_TYPES);
|
||||
}
|
||||
|
||||
@ -2980,7 +2928,8 @@ static u32 GetWeatherDamage(u32 battlerId)
|
||||
if (weather & B_WEATHER_SANDSTORM)
|
||||
{
|
||||
if (BattlerAffectedBySandstorm(battlerId, ability)
|
||||
&& !(gStatuses3[battlerId] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
|
||||
&& gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERGROUND
|
||||
&& gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERWATER
|
||||
&& holdEffect != HOLD_EFFECT_SAFETY_GOGGLES)
|
||||
{
|
||||
damage = GetNonDynamaxMaxHP(battlerId) / 16;
|
||||
@ -2991,7 +2940,8 @@ static u32 GetWeatherDamage(u32 battlerId)
|
||||
if ((weather & B_WEATHER_HAIL) && ability != ABILITY_ICE_BODY)
|
||||
{
|
||||
if (BattlerAffectedByHail(battlerId, ability)
|
||||
&& !(gStatuses3[battlerId] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
|
||||
&& gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERGROUND
|
||||
&& gBattleMons[battlerId].volatiles.semiInvulnerable != STATE_UNDERWATER
|
||||
&& holdEffect != HOLD_EFFECT_SAFETY_GOGGLES)
|
||||
{
|
||||
damage = GetNonDynamaxMaxHP(battlerId) / 16;
|
||||
|
||||
@ -6871,7 +6871,7 @@ static void SwapBattlerMoveData(u32 battler1, u32 battler2)
|
||||
SWAP(gBattleStruct->moveTarget[battler1], gBattleStruct->moveTarget[battler2], temp);
|
||||
SWAP(gMoveSelectionCursor[battler1], gMoveSelectionCursor[battler2], temp);
|
||||
SWAP(gLockedMoves[battler1], gLockedMoves[battler2], temp);
|
||||
|
||||
|
||||
// update last moves
|
||||
SWAP(gLastPrintedMoves[battler1], gLastPrintedMoves[battler2], temp);
|
||||
SWAP(gLastMoves[battler1], gLastMoves[battler2], temp);
|
||||
@ -6907,10 +6907,9 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId)
|
||||
SWAP(gTransformedPersonalities[battlerAtk], gTransformedPersonalities[battlerPartner], temp);
|
||||
SWAP(gTransformedShininess[battlerAtk], gTransformedShininess[battlerPartner], temp);
|
||||
SWAP(gStatuses3[battlerAtk], gStatuses3[battlerPartner], temp);
|
||||
SWAP(gStatuses4[battlerAtk], gStatuses4[battlerPartner], temp);
|
||||
|
||||
|
||||
SwapBattlerMoveData(battlerAtk, battlerPartner);
|
||||
|
||||
|
||||
// Swap turn order, so that all the battlers take action
|
||||
SWAP(gChosenActionByBattler[battlerAtk], gChosenActionByBattler[battlerPartner], temp);
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
|
||||
@ -106,7 +106,6 @@ enum
|
||||
LIST_ITEM_STATUS1,
|
||||
LIST_ITEM_VOLATILE,
|
||||
LIST_ITEM_STATUS3,
|
||||
LIST_ITEM_STATUS4,
|
||||
LIST_ITEM_HAZARDS,
|
||||
LIST_ITEM_SIDE_STATUS,
|
||||
LIST_ITEM_AI,
|
||||
@ -147,8 +146,6 @@ enum
|
||||
LIST_STATUS3_LEECH_SEEDED,
|
||||
LIST_STATUS3_ALWAYS_HITS,
|
||||
LIST_STATUS3_PERISH_SONG,
|
||||
LIST_STATUS3_ON_AIR,
|
||||
LIST_STATUS3_UNDERGROUND,
|
||||
LIST_STATUS3_MINIMIZED,
|
||||
LIST_STATUS3_CHARGED_UP,
|
||||
LIST_STATUS3_ROOTED,
|
||||
@ -157,7 +154,6 @@ enum
|
||||
LIST_STATUS3_GRUDGE,
|
||||
LIST_STATUS3_GASTRO_ACID,
|
||||
LIST_STATUS3_EMBARGO,
|
||||
LIST_STATUS3_UNDERWATER,
|
||||
LIST_STATUS3_SMACKED_DOWN,
|
||||
LIST_STATUS3_TELEKINESIS,
|
||||
LIST_STATUS3_MIRACLE_EYED,
|
||||
@ -168,14 +164,6 @@ enum
|
||||
LIST_STATUS3_POWER_TRICK,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
LIST_STATUS4_ELECTRIFIED,
|
||||
LIST_STATUS4_SALT_CURE,
|
||||
LIST_STATUS4_SYRUP_BOMB,
|
||||
LIST_STATUS4_GLAIVE_RUSH,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
LIST_SIDE_STICKY_WEB,
|
||||
@ -314,16 +302,6 @@ static const struct BitfieldInfo sStatus3Bitfield[] =
|
||||
{/*Power Trick*/ 1, 30},
|
||||
};
|
||||
|
||||
static const struct BitfieldInfo sStatus4Bitfield[] =
|
||||
{
|
||||
{/*Electrified*/ 1, 0},
|
||||
{/*Mud Sport*/ 1, 1},
|
||||
{/*Water Sport*/ 1, 2},
|
||||
{/*Salt Cure*/ 1, 4},
|
||||
{/*Syrup Bomb*/ 1, 5},
|
||||
{/*Glaive Rush*/ 1, 6},
|
||||
};
|
||||
|
||||
static const struct BitfieldInfo sAIBitfield[] =
|
||||
{
|
||||
{/*Check Bad Move*/ 1, 0},
|
||||
@ -369,7 +347,6 @@ static const struct ListMenuItem sMainListItems[] =
|
||||
{COMPOUND_STRING("Status1"), LIST_ITEM_STATUS1},
|
||||
{COMPOUND_STRING("Volatiles"), LIST_ITEM_VOLATILE},
|
||||
{COMPOUND_STRING("Status3"), LIST_ITEM_STATUS3},
|
||||
{COMPOUND_STRING("Status4"), LIST_ITEM_STATUS4},
|
||||
{COMPOUND_STRING("Hazards"), LIST_ITEM_HAZARDS},
|
||||
{COMPOUND_STRING("Side Status"), LIST_ITEM_SIDE_STATUS},
|
||||
{COMPOUND_STRING("AI"), LIST_ITEM_AI},
|
||||
@ -405,21 +382,26 @@ static const struct ListMenuItem sStatus1ListItems[] =
|
||||
|
||||
static const struct ListMenuItem sVolatileStatusListItems[] =
|
||||
{
|
||||
{COMPOUND_STRING("Confusion"), VOLATILE_CONFUSION},
|
||||
{COMPOUND_STRING("Flinched"), VOLATILE_FLINCHED},
|
||||
{COMPOUND_STRING("Torment"), VOLATILE_TORMENT},
|
||||
{COMPOUND_STRING("Powder"), VOLATILE_POWDER},
|
||||
{COMPOUND_STRING("DefenseCurl"), VOLATILE_DEFENSE_CURL},
|
||||
{COMPOUND_STRING("Recharge"), VOLATILE_RECHARGE},
|
||||
{COMPOUND_STRING("Rage"), VOLATILE_RAGE},
|
||||
{COMPOUND_STRING("DestinyBond"), VOLATILE_DESTINY_BOND},
|
||||
{COMPOUND_STRING("EscapePrevention"), VOLATILE_ESCAPE_PREVENTION},
|
||||
{COMPOUND_STRING("Cursed"), VOLATILE_CURSED},
|
||||
{COMPOUND_STRING("Foresight"), VOLATILE_FORESIGHT},
|
||||
{COMPOUND_STRING("DragonCheer"), VOLATILE_DRAGON_CHEER},
|
||||
{COMPOUND_STRING("FocusEnergy"), VOLATILE_FOCUS_ENERGY},
|
||||
{COMPOUND_STRING("MudSport"), VOLATILE_MUD_SPORT},
|
||||
{COMPOUND_STRING("WaterSport"), VOLATILE_WATER_SPORT},
|
||||
{COMPOUND_STRING("Confusion"), VOLATILE_CONFUSION},
|
||||
{COMPOUND_STRING("Flinched"), VOLATILE_FLINCHED},
|
||||
{COMPOUND_STRING("Torment"), VOLATILE_TORMENT},
|
||||
{COMPOUND_STRING("Powder"), VOLATILE_POWDER},
|
||||
{COMPOUND_STRING("DefenseCurl"), VOLATILE_DEFENSE_CURL},
|
||||
{COMPOUND_STRING("Recharge"), VOLATILE_RECHARGE},
|
||||
{COMPOUND_STRING("Rage"), VOLATILE_RAGE},
|
||||
{COMPOUND_STRING("DestinyBond"), VOLATILE_DESTINY_BOND},
|
||||
{COMPOUND_STRING("EscapePrevention"), VOLATILE_ESCAPE_PREVENTION},
|
||||
{COMPOUND_STRING("Cursed"), VOLATILE_CURSED},
|
||||
{COMPOUND_STRING("Foresight"), VOLATILE_FORESIGHT},
|
||||
{COMPOUND_STRING("DragonCheer"), VOLATILE_DRAGON_CHEER},
|
||||
{COMPOUND_STRING("FocusEnergy"), VOLATILE_FOCUS_ENERGY},
|
||||
{COMPOUND_STRING("Electrified"), VOLATILE_ELECTRIFIED},
|
||||
{COMPOUND_STRING("MudSport"), VOLATILE_MUD_SPORT},
|
||||
{COMPOUND_STRING("WaterSport"), VOLATILE_WATER_SPORT},
|
||||
{COMPOUND_STRING("Infinite Confusion"), VOLATILE_INFINITE_CONFUSION},
|
||||
{COMPOUND_STRING("Salt Cure"), VOLATILE_SALT_CURE},
|
||||
{COMPOUND_STRING("Syrup Bomb"), VOLATILE_SYRUP_BOMB},
|
||||
{COMPOUND_STRING("Glaive Rush"), VOLATILE_GLAIVE_RUSH},
|
||||
};
|
||||
|
||||
static const struct ListMenuItem sStatus3ListItems[] =
|
||||
@ -428,8 +410,6 @@ static const struct ListMenuItem sStatus3ListItems[] =
|
||||
{COMPOUND_STRING("Leech Seeded"), LIST_STATUS3_LEECH_SEEDED},
|
||||
{COMPOUND_STRING("Always Hits"), LIST_STATUS3_ALWAYS_HITS},
|
||||
{COMPOUND_STRING("Perish Song"), LIST_STATUS3_PERISH_SONG},
|
||||
{COMPOUND_STRING("On Air"), LIST_STATUS3_ON_AIR},
|
||||
{COMPOUND_STRING("Underground"), LIST_STATUS3_UNDERGROUND},
|
||||
{COMPOUND_STRING("Minimized"), LIST_STATUS3_MINIMIZED},
|
||||
{COMPOUND_STRING("Charged Up"), LIST_STATUS3_CHARGED_UP},
|
||||
{COMPOUND_STRING("Rooted"), LIST_STATUS3_ROOTED},
|
||||
@ -438,7 +418,6 @@ static const struct ListMenuItem sStatus3ListItems[] =
|
||||
{COMPOUND_STRING("Grudge"), LIST_STATUS3_GRUDGE},
|
||||
{COMPOUND_STRING("Gastro Acid"), LIST_STATUS3_GASTRO_ACID},
|
||||
{COMPOUND_STRING("Embargo"), LIST_STATUS3_EMBARGO},
|
||||
{COMPOUND_STRING("Underwater"), LIST_STATUS3_UNDERWATER},
|
||||
{COMPOUND_STRING("Smacked Down"), LIST_STATUS3_SMACKED_DOWN},
|
||||
{COMPOUND_STRING("Telekinesis"), LIST_STATUS3_TELEKINESIS},
|
||||
{COMPOUND_STRING("Miracle Eyed"), LIST_STATUS3_MIRACLE_EYED},
|
||||
@ -449,14 +428,6 @@ static const struct ListMenuItem sStatus3ListItems[] =
|
||||
{COMPOUND_STRING("Power Trick"), LIST_STATUS3_POWER_TRICK},
|
||||
};
|
||||
|
||||
static const struct ListMenuItem sStatus4ListItems[] =
|
||||
{
|
||||
{COMPOUND_STRING("Electrified"), LIST_STATUS4_ELECTRIFIED},
|
||||
{COMPOUND_STRING("Salt Cure"), LIST_STATUS4_SALT_CURE},
|
||||
{COMPOUND_STRING("Syrup Bomb"), LIST_STATUS4_SYRUP_BOMB},
|
||||
{COMPOUND_STRING("Glaive Rush"), LIST_STATUS4_GLAIVE_RUSH},
|
||||
};
|
||||
|
||||
static const struct ListMenuItem sHazardsListItems[] =
|
||||
{
|
||||
{COMPOUND_STRING("Spikes"), LIST_SIDE_SPIKES},
|
||||
@ -822,7 +793,7 @@ static void PutMovesPointsText(struct BattleDebugMenu *data)
|
||||
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, COMPOUND_STRING("Chosen move: "), 74, 64, 0, NULL);
|
||||
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, GetMoveName(gBattleMons[data->aiBattlerId].moves[chosenMoveIndex]), 74 + 68, 64, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL);
|
||||
Free(text);
|
||||
}
|
||||
@ -1437,11 +1408,6 @@ static void CreateSecondaryListMenu(struct BattleDebugMenu *data)
|
||||
itemsCount = ARRAY_COUNT(sStatus3ListItems);
|
||||
data->bitfield = sStatus3Bitfield;
|
||||
break;
|
||||
case LIST_ITEM_STATUS4:
|
||||
listTemplate.items = sStatus4ListItems;
|
||||
itemsCount = ARRAY_COUNT(sStatus4ListItems);
|
||||
data->bitfield = sStatus4Bitfield;
|
||||
break;
|
||||
case LIST_ITEM_AI:
|
||||
listTemplate.items = sAIListItems;
|
||||
itemsCount = ARRAY_COUNT(sAIListItems);
|
||||
@ -2084,11 +2050,6 @@ static void SetUpModifyArrows(struct BattleDebugMenu *data)
|
||||
data->modifyArrows.currValue = GetBitfieldValue(gStatuses3[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount);
|
||||
data->modifyArrows.typeOfVal = VAL_BITFIELD_32;
|
||||
goto CASE_ITEM_STATUS;
|
||||
case LIST_ITEM_STATUS4:
|
||||
data->modifyArrows.modifiedValPtr = &gStatuses4[data->battlerId];
|
||||
data->modifyArrows.currValue = GetBitfieldValue(gStatuses4[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount);
|
||||
data->modifyArrows.typeOfVal = VAL_BITFIELD_32;
|
||||
goto CASE_ITEM_STATUS;
|
||||
case LIST_ITEM_AI:
|
||||
data->modifyArrows.modifiedValPtr = &gAiThinkingStruct->aiFlags[data->battlerId];
|
||||
data->modifyArrows.currValue = GetBitfieldValue(gAiThinkingStruct->aiFlags[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount);
|
||||
|
||||
@ -232,9 +232,10 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler)
|
||||
&& ability != ABILITY_SAND_FORCE
|
||||
&& ability != ABILITY_SAND_RUSH
|
||||
&& ability != ABILITY_OVERCOAT
|
||||
&& !IS_BATTLER_ANY_TYPE(gBattlerAttacker, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)
|
||||
&& !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES
|
||||
&& !IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)
|
||||
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND
|
||||
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER
|
||||
&& GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES
|
||||
&& !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD))
|
||||
{
|
||||
gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16;
|
||||
@ -257,7 +258,8 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler)
|
||||
if (ability != ABILITY_SNOW_CLOAK
|
||||
&& ability != ABILITY_OVERCOAT
|
||||
&& !IS_BATTLER_OF_TYPE(battler, TYPE_ICE)
|
||||
&& !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
|
||||
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND
|
||||
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER
|
||||
&& GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES
|
||||
&& !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD))
|
||||
{
|
||||
@ -306,7 +308,7 @@ static bool32 HandleEndTurnEmergencyExit(u32 battler)
|
||||
&& (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER))
|
||||
&& !(gBattleTypeFlags & BATTLE_TYPE_ARENA)
|
||||
&& CountUsablePartyMons(battler) > 0
|
||||
&& !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) // Not currently held by Sky Drop
|
||||
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP) // Not currently held by Sky Drop
|
||||
{
|
||||
gBattlerAbility = battler;
|
||||
gLastUsedAbility = ability;
|
||||
@ -458,7 +460,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler)
|
||||
gBattleStruct->eventBlockCounter++;
|
||||
break;
|
||||
case FIRST_EVENT_BLOCK_THRASH:
|
||||
if (gBattleMons[battler].volatiles.lockConfusionTurns && !(gStatuses3[battler] & STATUS3_SKY_DROPPED))
|
||||
if (gBattleMons[battler].volatiles.lockConfusionTurns && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP)
|
||||
{
|
||||
gBattleMons[battler].volatiles.lockConfusionTurns--;
|
||||
if (WasUnableToUseMove(battler))
|
||||
@ -484,7 +486,8 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler)
|
||||
if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN
|
||||
&& IsBattlerAlive(battler)
|
||||
&& !IsBattlerAtMaxHp(battler)
|
||||
&& !(gStatuses3[battler] & (STATUS3_SEMI_INVULNERABLE | STATUS3_HEAL_BLOCK))
|
||||
&& !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)
|
||||
&& !IsSemiInvulnerable(battler, CHECK_ALL)
|
||||
&& IsBattlerGrounded(battler))
|
||||
{
|
||||
gBattlerAttacker = battler;
|
||||
@ -795,7 +798,7 @@ static bool32 HandleEndTurnSaltCure(u32 battler)
|
||||
|
||||
gBattleStruct->turnEffectsBattlerId++;
|
||||
|
||||
if (gStatuses4[battler] & STATUS4_SALT_CURE
|
||||
if (gBattleMons[battler].volatiles.saltCure
|
||||
&& IsBattlerAlive(battler)
|
||||
&& !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD))
|
||||
{
|
||||
@ -836,10 +839,10 @@ static bool32 HandleEndTurnSyrupBomb(u32 battler)
|
||||
|
||||
gBattleStruct->turnEffectsBattlerId++;
|
||||
|
||||
if ((gStatuses4[battler] & STATUS4_SYRUP_BOMB) && (IsBattlerAlive(battler)))
|
||||
if (gBattleMons[battler].volatiles.syrupBomb && (IsBattlerAlive(battler)))
|
||||
{
|
||||
if (gDisableStructs[battler].syrupBombTimer > 0 && --gDisableStructs[battler].syrupBombTimer == 0)
|
||||
gStatuses4[battler] &= ~STATUS4_SYRUP_BOMB;
|
||||
gBattleMons[battler].volatiles.syrupBomb = FALSE;
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_SYRUP_BOMB);
|
||||
gBattlescriptCurrInstr = BattleScript_SyrupBombEndTurn;
|
||||
BattleScriptExecute(gBattlescriptCurrInstr);
|
||||
|
||||
@ -194,7 +194,6 @@ EWRAM_DATA u8 gBideTarget[MAX_BATTLERS_COUNT] = {0};
|
||||
EWRAM_DATA u32 gSideStatuses[NUM_BATTLE_SIDES] = {0};
|
||||
EWRAM_DATA struct SideTimer gSideTimers[NUM_BATTLE_SIDES] = {0};
|
||||
EWRAM_DATA u32 gStatuses3[MAX_BATTLERS_COUNT] = {0};
|
||||
EWRAM_DATA u32 gStatuses4[MAX_BATTLERS_COUNT] = {0};
|
||||
EWRAM_DATA struct DisableStruct gDisableStructs[MAX_BATTLERS_COUNT] = {0};
|
||||
EWRAM_DATA u16 gPauseCounterBattle = 0;
|
||||
EWRAM_DATA u16 gPaydayMoney = 0;
|
||||
@ -3028,7 +3027,6 @@ static void BattleStartClearSetData(void)
|
||||
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
|
||||
{
|
||||
gStatuses3[i] = 0;
|
||||
gStatuses4[i] = 0;
|
||||
gDisableStructs[i].isFirstTurn = 2;
|
||||
gLastMoves[i] = MOVE_NONE;
|
||||
gLastLandedMoves[i] = MOVE_NONE;
|
||||
@ -3174,7 +3172,6 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
|
||||
gStatuses3[battler] &= (STATUS3_LEECHSEED_BATTLER | STATUS3_LEECHSEED | STATUS3_ALWAYS_HITS | STATUS3_PERISH_SONG | STATUS3_ROOTED
|
||||
| STATUS3_GASTRO_ACID | STATUS3_EMBARGO | STATUS3_TELEKINESIS | STATUS3_MAGNET_RISE | STATUS3_HEAL_BLOCK
|
||||
| STATUS3_AQUA_RING | STATUS3_POWER_TRICK);
|
||||
gStatuses4[battler] &= STATUS4_INFINITE_CONFUSION;
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (!IsBattlerAlly(battler, i)
|
||||
@ -3191,7 +3188,6 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
|
||||
else
|
||||
{
|
||||
gStatuses3[battler] = 0;
|
||||
gStatuses4[battler] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
@ -3200,8 +3196,8 @@ void SwitchInClearSetData(u32 battler, struct Volatiles *volatilesCopy)
|
||||
gBattleMons[i].volatiles.infatuation = 0;
|
||||
if (gBattleMons[i].volatiles.wrapped && gBattleStruct->wrappedBy[i] == battler)
|
||||
gBattleMons[i].volatiles.wrapped = FALSE;
|
||||
if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler)
|
||||
gStatuses4[i] &= ~STATUS4_SYRUP_BOMB;
|
||||
if (gBattleMons[i].volatiles.syrupBomb && gBattleStruct->stickySyrupdBy[i] == battler)
|
||||
gBattleMons[i].volatiles.syrupBomb = FALSE;
|
||||
}
|
||||
|
||||
gActionSelectionCursor[battler] = 0;
|
||||
@ -3308,7 +3304,6 @@ const u8* FaintClearSetData(u32 battler)
|
||||
|
||||
memset(&gBattleMons[battler].volatiles, 0, sizeof(struct Volatiles));
|
||||
gStatuses3[battler] &= STATUS3_GASTRO_ACID; // Edge case: Keep Gastro Acid if pokemon's ability can have effect after fainting, for example Innards Out.
|
||||
gStatuses4[battler] = 0;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
@ -3318,8 +3313,8 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gBattleMons[i].volatiles.infatuation = 0;
|
||||
if (gBattleMons[i].volatiles.wrapped && gBattleStruct->wrappedBy[i] == battler)
|
||||
gBattleMons[i].volatiles.wrapped = FALSE;
|
||||
if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler)
|
||||
gStatuses4[i] &= ~STATUS4_SYRUP_BOMB;
|
||||
if (gBattleMons[i].volatiles.syrupBomb && gBattleStruct->stickySyrupdBy[i] == battler)
|
||||
gBattleMons[i].volatiles.syrupBomb = FALSE;
|
||||
}
|
||||
|
||||
gActionSelectionCursor[battler] = 0;
|
||||
@ -3410,10 +3405,10 @@ const u8* FaintClearSetData(u32 battler)
|
||||
gBattleStruct->skyDropTargets[otherSkyDropper] = SKY_DROP_NO_TARGET;
|
||||
|
||||
// If the other Pokemon involved in this Sky Drop was the target, not the attacker
|
||||
if (gStatuses3[otherSkyDropper] & STATUS3_SKY_DROPPED)
|
||||
if (gBattleMons[otherSkyDropper].volatiles.semiInvulnerable == STATE_SKY_DROP)
|
||||
{
|
||||
// Release the target and take them out of the semi-invulnerable state
|
||||
gStatuses3[otherSkyDropper] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
|
||||
gBattleMons[otherSkyDropper].volatiles.semiInvulnerable = STATE_NONE;
|
||||
|
||||
// Make the target's sprite visible
|
||||
gSprites[gBattlerSpriteIds[otherSkyDropper]].invisible = FALSE;
|
||||
@ -4019,7 +4014,7 @@ void BattleTurnPassed(void)
|
||||
gChosenActionByBattler[i] = B_ACTION_NONE;
|
||||
gChosenMoveByBattler[i] = MOVE_NONE;
|
||||
gBattleStruct->monToSwitchIntoId[i] = PARTY_SIZE;
|
||||
gStatuses4[i] &= ~STATUS4_ELECTRIFIED;
|
||||
gBattleMons[i].volatiles.electrified = FALSE;
|
||||
gBattleMons[i].volatiles.flinched = FALSE;
|
||||
gBattleMons[i].volatiles.powder = FALSE;
|
||||
|
||||
@ -4308,7 +4303,7 @@ static void HandleTurnActionSelectionState(void)
|
||||
| BATTLE_TYPE_RECORDED_LINK))
|
||||
&& !gTestRunnerEnabled)
|
||||
// Or if currently held by Sky Drop
|
||||
|| gStatuses3[battler] & STATUS3_SKY_DROPPED)
|
||||
|| gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP)
|
||||
{
|
||||
RecordedBattle_ClearBattlerAction(battler, 1);
|
||||
gSelectionBattleScripts[battler] = BattleScript_ActionSelectionItemsCantBeUsed;
|
||||
@ -5133,7 +5128,7 @@ static void TurnValuesCleanUp(bool8 var0)
|
||||
if (gDisableStructs[i].substituteHP == 0)
|
||||
gBattleMons[i].volatiles.substitute = FALSE;
|
||||
|
||||
if (!(gStatuses3[i] & STATUS3_COMMANDER))
|
||||
if (gBattleMons[i].volatiles.semiInvulnerable != STATE_COMMANDER)
|
||||
gBattleStruct->battlerState[i].commandingDondozo = FALSE;
|
||||
|
||||
gSpecialStatuses[i].parentalBondState = PARENTAL_BOND_OFF;
|
||||
@ -6083,7 +6078,8 @@ void SetTypeBeforeUsingMove(u32 move, u32 battler)
|
||||
gBattleStruct->dynamicMoveType = moveType | F_DYNAMIC_TYPE_SET;
|
||||
|
||||
moveType = GetBattleMoveType(move);
|
||||
if ((gFieldStatuses & STATUS_FIELD_ION_DELUGE && moveType == TYPE_NORMAL) || gStatuses4[battler] & STATUS4_ELECTRIFIED)
|
||||
if ((gFieldStatuses & STATUS_FIELD_ION_DELUGE && moveType == TYPE_NORMAL)
|
||||
|| gBattleMons[battler].volatiles.electrified)
|
||||
gBattleStruct->dynamicMoveType = TYPE_ELECTRIC | F_DYNAMIC_TYPE_SET;
|
||||
|
||||
// Check if a gem should activate.
|
||||
|
||||
@ -407,7 +407,7 @@ static void Cmd_jumpifabilitypresent(void);
|
||||
static void Cmd_endselectionscript(void);
|
||||
static void Cmd_playanimation(void);
|
||||
static void Cmd_playanimation_var(void);
|
||||
static void Cmd_unused_0x47(void);
|
||||
static void Cmd_jumpfifsemiinvulnerable(void);
|
||||
static void Cmd_unused_0x48(void);
|
||||
static void Cmd_moveend(void);
|
||||
static void Cmd_sethealblock(void);
|
||||
@ -666,7 +666,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
|
||||
Cmd_endselectionscript, //0x44
|
||||
Cmd_playanimation, //0x45
|
||||
Cmd_playanimation_var, //0x46
|
||||
Cmd_unused_0x47, //0x47
|
||||
Cmd_jumpfifsemiinvulnerable, //0x47
|
||||
Cmd_unused_0x48, //0x48
|
||||
Cmd_moveend, //0x49
|
||||
Cmd_sethealblock, //0x4A
|
||||
@ -1079,7 +1079,7 @@ bool32 EmergencyExitCanBeTriggered(u32 battler)
|
||||
&& (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER))
|
||||
&& !(gBattleTypeFlags & BATTLE_TYPE_ARENA)
|
||||
&& CountUsablePartyMons(battler) > 0
|
||||
&& !(gStatuses3[battler] & STATUS3_SKY_DROPPED))
|
||||
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
@ -1366,7 +1366,7 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u
|
||||
{
|
||||
if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker)
|
||||
gBattlescriptCurrInstr = nextInstr;
|
||||
else if (gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE))
|
||||
else if (IsSemiInvulnerable(gBattlerTarget, CHECK_ALL))
|
||||
gBattlescriptCurrInstr = failInstr;
|
||||
else if (!JumpIfMoveAffectedByProtect(gCurrentMove, gBattlerTarget, TRUE, failInstr))
|
||||
gBattlescriptCurrInstr = nextInstr;
|
||||
@ -3372,7 +3372,7 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
break;
|
||||
case MOVE_EFFECT_FLAME_BURST:
|
||||
if (IsBattlerAlive(BATTLE_PARTNER(gBattlerTarget))
|
||||
&& !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_SEMI_INVULNERABLE)
|
||||
&& !IsSemiInvulnerable(BATTLE_PARTNER(gBattlerTarget), CHECK_ALL)
|
||||
&& GetBattlerAbility(BATTLE_PARTNER(gBattlerTarget)) != ABILITY_MAGIC_GUARD)
|
||||
{
|
||||
gBattleScripting.battler = i = BATTLE_PARTNER(gBattlerTarget);
|
||||
@ -3513,11 +3513,11 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_SYRUP_BOMB:
|
||||
if (!(gStatuses4[gEffectBattler] & STATUS4_SYRUP_BOMB))
|
||||
if (!gBattleMons[gEffectBattler].volatiles.syrupBomb)
|
||||
{
|
||||
struct Pokemon *mon = GetBattlerMon(gBattlerAttacker);
|
||||
|
||||
gStatuses4[gEffectBattler] |= STATUS4_SYRUP_BOMB;
|
||||
gBattleMons[gEffectBattler].volatiles.syrupBomb = TRUE;
|
||||
gDisableStructs[gEffectBattler].syrupBombTimer = 3;
|
||||
gDisableStructs[gEffectBattler].syrupBombIsShiny = IsMonShiny(mon);
|
||||
gBattleStruct->stickySyrupdBy[gEffectBattler] = gBattlerAttacker;
|
||||
@ -3655,9 +3655,9 @@ void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certai
|
||||
}
|
||||
break;
|
||||
case MOVE_EFFECT_SALT_CURE:
|
||||
if (!(gStatuses4[gBattlerTarget] & STATUS4_SALT_CURE))
|
||||
if (!gBattleMons[gBattlerTarget].volatiles.saltCure)
|
||||
{
|
||||
gStatuses4[gBattlerTarget] |= STATUS4_SALT_CURE;
|
||||
gBattleMons[gBattlerTarget].volatiles.saltCure = TRUE;
|
||||
BattleScriptPush(gBattlescriptCurrInstr + 1);
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEffectSaltCure;
|
||||
}
|
||||
@ -5455,7 +5455,7 @@ static void PlayAnimation(u32 battler, u8 animId, const u16 *argPtr, const u8 *n
|
||||
MarkBattlerForControllerExec(battler);
|
||||
gBattlescriptCurrInstr = nextInstr;
|
||||
}
|
||||
else if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE)
|
||||
else if (IsSemiInvulnerable(battler, CHECK_ALL))
|
||||
{
|
||||
gBattlescriptCurrInstr = nextInstr;
|
||||
}
|
||||
@ -5484,8 +5484,15 @@ static void Cmd_playanimation_var(void)
|
||||
PlayAnimation(battler, *(cmd->animIdPtr), cmd->argPtr, cmd->nextInstr);
|
||||
}
|
||||
|
||||
static void Cmd_unused_0x47(void)
|
||||
static void Cmd_jumpfifsemiinvulnerable(void)
|
||||
{
|
||||
CMD_ARGS(u8 battler, u8 state, const u8 *jumpInstr);
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
|
||||
if (gBattleMons[battler].volatiles.semiInvulnerable == cmd->state)
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static void Cmd_unused_0x48(void)
|
||||
@ -5764,7 +5771,7 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect)
|
||||
if (IsBattlerTurnDamaged(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerTarget)
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& !(gStatuses3[BATTLE_PARTNER(gBattlerTarget)] & STATUS3_COMMANDER))
|
||||
&& gBattleMons[BATTLE_PARTNER(gBattlerTarget)].volatiles.semiInvulnerable != STATE_COMMANDER)
|
||||
{
|
||||
u32 targetAbility = GetBattlerAbility(gBattlerTarget);
|
||||
if (targetAbility == ABILITY_GUARD_DOG)
|
||||
@ -5796,8 +5803,9 @@ static bool32 HandleMoveEndMoveBlock(u32 moveEffect)
|
||||
&& IsBattlerAlive(gBattlerTarget)
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove))
|
||||
{
|
||||
gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE;
|
||||
gStatuses3[gBattlerTarget] |= STATUS3_SMACKED_DOWN;
|
||||
gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR);
|
||||
gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS);
|
||||
BattleScriptCall(BattleScript_MoveEffectSmackDown);
|
||||
effect = TRUE;
|
||||
}
|
||||
@ -6156,7 +6164,7 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_ATTACKER_INVISIBLE: // make attacker sprite invisible
|
||||
if (gStatuses3[gBattlerAttacker] & (STATUS3_SEMI_INVULNERABLE)
|
||||
if (IsSemiInvulnerable(gBattlerAttacker, CHECK_ALL)
|
||||
&& gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION))
|
||||
{
|
||||
BtlController_EmitSpriteInvisibility(gBattlerAttacker, B_COMM_TO_CONTROLLER, TRUE);
|
||||
@ -6168,12 +6176,12 @@ static void Cmd_moveend(void)
|
||||
break;
|
||||
case MOVEEND_ATTACKER_VISIBLE: // make attacker sprite visible
|
||||
if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT
|
||||
|| !(gStatuses3[gBattlerAttacker] & (STATUS3_SEMI_INVULNERABLE))
|
||||
|| !IsSemiInvulnerable(gBattlerAttacker, CHECK_ALL)
|
||||
|| WasUnableToUseMove(gBattlerAttacker))
|
||||
{
|
||||
BtlController_EmitSpriteInvisibility(gBattlerAttacker, B_COMM_TO_CONTROLLER, FALSE);
|
||||
MarkBattlerForControllerExec(gBattlerAttacker);
|
||||
gStatuses3[gBattlerAttacker] &= ~STATUS3_SEMI_INVULNERABLE;
|
||||
gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable = STATE_NONE;
|
||||
gSpecialStatuses[gBattlerAttacker].restoredBattlerSprite = TRUE;
|
||||
gBattleScripting.moveendState++;
|
||||
return;
|
||||
@ -6182,11 +6190,11 @@ static void Cmd_moveend(void)
|
||||
break;
|
||||
case MOVEEND_TARGET_VISIBLE: // make target sprite visible
|
||||
if (!gSpecialStatuses[gBattlerTarget].restoredBattlerSprite && gBattlerTarget < gBattlersCount
|
||||
&& !(gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE))
|
||||
&& !IsSemiInvulnerable(gBattlerTarget, CHECK_ALL))
|
||||
{
|
||||
BtlController_EmitSpriteInvisibility(gBattlerTarget, B_COMM_TO_CONTROLLER, FALSE);
|
||||
MarkBattlerForControllerExec(gBattlerTarget);
|
||||
gStatuses3[gBattlerTarget] &= ~STATUS3_SEMI_INVULNERABLE;
|
||||
gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE;
|
||||
gBattleScripting.moveendState++;
|
||||
return;
|
||||
}
|
||||
@ -6927,7 +6935,7 @@ static void Cmd_moveend(void)
|
||||
u32 partner = BATTLE_PARTNER(i);
|
||||
gBattleStruct->battlerState[i].commanderSpecies = SPECIES_NONE;
|
||||
if (IsBattlerAlive(partner))
|
||||
gStatuses3[partner] &= ~STATUS3_COMMANDER;
|
||||
gBattleMons[partner].volatiles.semiInvulnerable = STATE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8468,7 +8476,7 @@ static void Cmd_statusanimation(void)
|
||||
{
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler),
|
||||
statusFlag = (cmd->isVolatile || cmd->status) ? cmd->status : gBattleMons[battler].status1;
|
||||
if (!(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE)
|
||||
if (!IsSemiInvulnerable(battler, CHECK_ALL)
|
||||
&& gDisableStructs[battler].substituteHP == 0
|
||||
&& !(gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION)))
|
||||
{
|
||||
@ -9322,7 +9330,7 @@ static bool32 IsRototillerAffected(u32 battler)
|
||||
return FALSE; // Only grounded battlers affected
|
||||
if (!IS_BATTLER_OF_TYPE(battler, TYPE_GRASS))
|
||||
return FALSE; // Only grass types affected
|
||||
if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE)
|
||||
if (IsSemiInvulnerable(battler, CHECK_ALL))
|
||||
return FALSE; // Rototiller doesn't affected semi-invulnerable battlers
|
||||
if (BlocksPrankster(MOVE_ROTOTILLER, gBattlerAttacker, battler, FALSE))
|
||||
return FALSE;
|
||||
@ -9352,7 +9360,7 @@ static bool32 IsTeatimeAffected(u32 battler)
|
||||
{
|
||||
if (GetItemPocket(gBattleMons[battler].item) != POCKET_BERRIES)
|
||||
return FALSE; // Only berries
|
||||
if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE)
|
||||
if (IsSemiInvulnerable(battler, CHECK_ALL))
|
||||
return FALSE; // Teatime doesn't affected semi-invulnerable battlers
|
||||
return TRUE;
|
||||
}
|
||||
@ -11151,7 +11159,7 @@ static void Cmd_transformdataexecution(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
if (gBattleMons[gBattlerTarget].volatiles.transformed
|
||||
|| gBattleStruct->illusion[gBattlerTarget].state == ILLUSION_ON
|
||||
|| gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER)
|
||||
|| IsSemiInvulnerable(gBattlerTarget, EXCLUDE_COMMANDER))
|
||||
{
|
||||
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_FAILED;
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TRANSFORM_FAILED;
|
||||
@ -11552,7 +11560,7 @@ static void Cmd_settypetorandomresistance(void)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else if (IsSemiInvulnerable(gBattlerTarget, gCurrentMove))
|
||||
else if (!BreaksThroughSemiInvulnerablity(gBattlerTarget, gCurrentMove))
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
@ -11705,7 +11713,7 @@ static void Cmd_trychoosesleeptalkmove(void)
|
||||
gCalledMove = gBattleMons[gBattlerAttacker].moves[movePosition];
|
||||
}
|
||||
gCurrMovePos = movePosition;
|
||||
gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED;
|
||||
gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED;
|
||||
gBattlerTarget = GetBattleMoveTarget(gCalledMove, NO_TARGET_OVERRIDE);
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
@ -12005,7 +12013,7 @@ static void Cmd_trysetperishsong(void)
|
||||
if (gStatuses3[i] & STATUS3_PERISH_SONG
|
||||
|| GetBattlerAbility(i) == ABILITY_SOUNDPROOF
|
||||
|| BlocksPrankster(gCurrentMove, gBattlerAttacker, i, TRUE)
|
||||
|| gStatuses3[i] & STATUS3_COMMANDER)
|
||||
|| gBattleMons[i].volatiles.semiInvulnerable == STATE_COMMANDER)
|
||||
{
|
||||
notAffectedCount++;
|
||||
}
|
||||
@ -12557,9 +12565,9 @@ static void Cmd_setsemiinvulnerablebit(void)
|
||||
{
|
||||
u32 semiInvulnerableEffect = GetMoveTwoTurnAttackStatus(gCurrentMove);
|
||||
if (cmd->clear)
|
||||
gStatuses3[gBattlerAttacker] &= ~semiInvulnerableEffect;
|
||||
gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable = STATE_NONE;
|
||||
else
|
||||
gStatuses3[gBattlerAttacker] |= semiInvulnerableEffect;
|
||||
gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable = semiInvulnerableEffect;
|
||||
}
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
@ -12618,7 +12626,7 @@ static void Cmd_trymemento(void)
|
||||
|
||||
if (B_MEMENTO_FAIL >= GEN_4
|
||||
&& (gBattleCommunication[MISS_TYPE] == B_MSG_PROTECTED
|
||||
|| gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE
|
||||
|| IsSemiInvulnerable(gBattlerTarget, CHECK_ALL)
|
||||
|| IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove)
|
||||
|| DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)))
|
||||
{
|
||||
@ -15094,7 +15102,7 @@ void BS_ItemCureStatus(void)
|
||||
if (GetItemStatus1Mask(gLastUsedItem) & STATUS1_SLEEP)
|
||||
gBattleMons[battler].volatiles.nightmare = FALSE;
|
||||
if (ItemHasVolatileFlag(gLastUsedItem, VOLATILE_CONFUSION))
|
||||
gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION;
|
||||
gBattleMons[battler].volatiles.infiniteConfusion = FALSE;
|
||||
}
|
||||
|
||||
if (statusChanged)
|
||||
@ -15234,15 +15242,6 @@ void BS_JumpIfElectricAbilityAffected(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_ApplySaltCure(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler);
|
||||
|
||||
u8 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
gStatuses4[battler] |= STATUS4_SALT_CURE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_SetTerrain(void)
|
||||
{
|
||||
NATIVE_ARGS(const u8 *jumpInstr);
|
||||
@ -15362,7 +15361,7 @@ void BS_TrySetOctolock(void)
|
||||
void BS_SetGlaiveRush(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
gStatuses4[gBattlerAttacker] |= STATUS4_GLAIVE_RUSH;
|
||||
gBattleMons[gBattlerAttacker].volatiles.glaiveRush = TRUE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
@ -15985,7 +15984,7 @@ void BS_TeatimeInvul(void)
|
||||
NATIVE_ARGS(u8 battler, const u8 *jumpInstr);
|
||||
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
if (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES && !(gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE)))
|
||||
if (GetItemPocket(gBattleMons[battler].item) == POCKET_BERRIES && !IsSemiInvulnerable(gBattlerTarget, CHECK_ALL))
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
@ -16107,7 +16106,7 @@ void BS_JumpIfCommanderActive(void)
|
||||
|
||||
if (gBattleStruct->battlerState[gBattlerTarget].commanderSpecies != SPECIES_NONE)
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
else if (gStatuses3[gBattlerTarget] & STATUS3_COMMANDER)
|
||||
else if (gBattleMons[gBattlerTarget].volatiles.semiInvulnerable == STATE_COMMANDER)
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
@ -16887,10 +16886,11 @@ void BS_GravityOnAirborneMons(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
// Cancel all multiturn moves of IN_AIR Pokemon except those being targeted by Sky Drop.
|
||||
if (gStatuses3[gBattlerTarget] & STATUS3_ON_AIR && !(gStatuses3[gBattlerTarget] & STATUS3_SKY_DROPPED))
|
||||
if (gBattleMons[gBattlerTarget].volatiles.semiInvulnerable == STATE_ON_AIR)
|
||||
CancelMultiTurnMoves(gBattlerTarget, SKY_DROP_GRAVITY_ON_AIRBORNE);
|
||||
|
||||
gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR | STATUS3_SKY_DROPPED);
|
||||
gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE;
|
||||
gStatuses3[gBattlerTarget] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
@ -17460,7 +17460,7 @@ void BS_TryElectrify(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
gStatuses4[gBattlerTarget] |= STATUS4_ELECTRIFIED;
|
||||
gBattleMons[gBattlerTarget].volatiles.electrified = TRUE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
@ -17964,7 +17964,7 @@ void BS_JumpIfUnder200(void)
|
||||
void BS_SetSkyDrop(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
gStatuses3[gBattlerTarget] |= (STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
|
||||
gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_SKY_DROP;
|
||||
/* skyDropTargets holds the information of who is in a particular instance of Sky Drop.
|
||||
This is needed in the case that multiple Pokemon use Sky Drop in the same turn or if
|
||||
the target of a Sky Drop faints while in the air.*/
|
||||
@ -17998,7 +17998,7 @@ void BS_ClearSkyDrop(void)
|
||||
{
|
||||
gBattleStruct->skyDropTargets[gBattlerAttacker] = SKY_DROP_NO_TARGET;
|
||||
gBattleStruct->skyDropTargets[gBattlerTarget] = SKY_DROP_NO_TARGET;
|
||||
gStatuses3[gBattlerTarget] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
|
||||
gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
@ -18010,7 +18010,7 @@ void BS_ClearSkyDrop(void)
|
||||
void BS_SkyDropYawn(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
if (gBattleStruct->skyDropTargets[gEffectBattler] != SKY_DROP_NO_TARGET && !(gStatuses3[gEffectBattler] & STATUS3_SKY_DROPPED))
|
||||
if (gBattleStruct->skyDropTargets[gEffectBattler] != SKY_DROP_NO_TARGET && gBattleMons[gEffectBattler].volatiles.semiInvulnerable != STATE_SKY_DROP)
|
||||
{
|
||||
// Set the target of Sky Drop as gEffectBattler
|
||||
gEffectBattler = gBattleStruct->skyDropTargets[gEffectBattler];
|
||||
|
||||
@ -1047,7 +1047,7 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState)
|
||||
const u8 *result = NULL;
|
||||
|
||||
u8 otherSkyDropper = gBattleStruct->skyDropTargets[battler];
|
||||
gStatuses3[otherSkyDropper] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
|
||||
gBattleMons[battler].volatiles.semiInvulnerable = STATE_NONE;
|
||||
|
||||
// Makes both attacker and target's sprites visible
|
||||
gSprites[gBattlerSpriteIds[battler]].invisible = FALSE;
|
||||
@ -1075,9 +1075,9 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState)
|
||||
}
|
||||
else if (skyDropState == SKY_DROP_GRAVITY_ON_AIRBORNE)
|
||||
{
|
||||
// Reapplying STATUS3_SKY_DROPPED allows for avoiding unecessary messages when Gravity is applied to the target.
|
||||
// Reapplying STATE_SKY_DROPPED allows for avoiding unecessary messages when Gravity is applied to the target.
|
||||
gBattleStruct->skyDropTargets[battler] = SKY_DROP_RELEASED_TARGET;
|
||||
gStatuses3[otherSkyDropper] |= STATUS3_SKY_DROPPED;
|
||||
gBattleMons[otherSkyDropper].volatiles.semiInvulnerable = STATE_SKY_DROP;
|
||||
}
|
||||
else if (skyDropState == SKY_DROP_CANCEL_MULTI_TURN_MOVES)
|
||||
{
|
||||
@ -1121,10 +1121,10 @@ const u8 *CancelMultiTurnMoves(u32 battler, enum SkyDropState skyDropState)
|
||||
}
|
||||
|
||||
// Clear battler's semi-invulnerable bits if they are not held by Sky Drop.
|
||||
if (!(gStatuses3[battler] & STATUS3_SKY_DROPPED))
|
||||
gStatuses3[battler] &= ~(STATUS3_SEMI_INVULNERABLE);
|
||||
if (gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP)
|
||||
gBattleMons[battler].volatiles.semiInvulnerable = STATE_NONE;
|
||||
|
||||
if (gBattleStruct->skyDropTargets[battler] != SKY_DROP_NO_TARGET && !(gStatuses3[battler] & STATUS3_SKY_DROPPED))
|
||||
if (gBattleStruct->skyDropTargets[battler] != SKY_DROP_NO_TARGET && gBattleMons[battler].volatiles.semiInvulnerable != STATE_SKY_DROP)
|
||||
result = CheckSkyDropState(battler, skyDropState);
|
||||
|
||||
gDisableStructs[battler].rolloutTimer = 0;
|
||||
@ -1893,7 +1893,7 @@ static enum MoveCanceller CancellerFlags(void)
|
||||
{
|
||||
gBattleMons[gBattlerAttacker].volatiles.destinyBond = FALSE;
|
||||
gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE;
|
||||
gStatuses4[gBattlerAttacker] &= ~STATUS4_GLAIVE_RUSH;
|
||||
gBattleMons[gBattlerAttacker].volatiles.glaiveRush = FALSE;
|
||||
return MOVE_STEP_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1907,7 +1907,7 @@ static enum MoveCanceller CancellerStanceChangeOne(void)
|
||||
static enum MoveCanceller CancellerSkyDrop(void)
|
||||
{
|
||||
// If Pokemon is being held in Sky Drop
|
||||
if (gStatuses3[gBattlerAttacker] & STATUS3_SKY_DROPPED)
|
||||
if (gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable == STATE_SKY_DROP)
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_MoveEnd;
|
||||
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
|
||||
@ -2157,7 +2157,7 @@ static enum MoveCanceller CancellerConfused(void)
|
||||
|
||||
if (gBattleMons[gBattlerAttacker].volatiles.confusionTurns)
|
||||
{
|
||||
if (!(gStatuses4[gBattlerAttacker] & STATUS4_INFINITE_CONFUSION))
|
||||
if (!gBattleMons[gBattlerAttacker].volatiles.infiniteConfusion)
|
||||
gBattleMons[gBattlerAttacker].volatiles.confusionTurns--;
|
||||
if (gBattleMons[gBattlerAttacker].volatiles.confusionTurns)
|
||||
{
|
||||
@ -3577,7 +3577,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& !gBattleMons[diagonalBattler].volatiles.transformed
|
||||
&& !gBattleMons[battler].volatiles.transformed
|
||||
&& gBattleStruct->illusion[diagonalBattler].state != ILLUSION_ON
|
||||
&& !(gStatuses3[diagonalBattler] & STATUS3_SEMI_INVULNERABLE_NO_COMMANDER))
|
||||
&& !IsSemiInvulnerable(diagonalBattler, EXCLUDE_COMMANDER))
|
||||
{
|
||||
SaveBattlerAttacker(gBattlerAttacker);
|
||||
SaveBattlerTarget(gBattlerTarget);
|
||||
@ -4169,9 +4169,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
gBattlerAttacker = partner;
|
||||
gBattleStruct->battlerState[battler].commandingDondozo = TRUE;
|
||||
gBattleStruct->battlerState[partner].commanderSpecies = gBattleMons[battler].species;
|
||||
gStatuses3[battler] |= STATUS3_COMMANDER;
|
||||
if (gBattleMons[battler].volatiles.confusionTurns > 0
|
||||
&& !(gStatuses4[battler] & STATUS4_INFINITE_CONFUSION))
|
||||
gBattleMons[battler].volatiles.semiInvulnerable = STATE_COMMANDER;
|
||||
if (gBattleMons[battler].volatiles.confusionTurns > 0 && !gBattleMons[battler].volatiles.infiniteConfusion)
|
||||
gBattleMons[battler].volatiles.confusionTurns--;
|
||||
BtlController_EmitSpriteInvisibility(battler, B_COMM_TO_CONTROLLER, TRUE);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
@ -4212,7 +4211,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_ICE_BODY:
|
||||
if (IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW)
|
||||
&& !IsBattlerAtMaxHp(battler)
|
||||
&& !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
|
||||
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERGROUND
|
||||
&& gBattleMons[battler].volatiles.semiInvulnerable != STATE_UNDERWATER
|
||||
&& !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
|
||||
{
|
||||
BattleScriptPushCursorAndCallback(BattleScript_IceBodyHeal);
|
||||
@ -4985,7 +4985,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
break;
|
||||
case ABILITY_GULP_MISSILE:
|
||||
if ((gBattleMons[gBattlerAttacker].species == SPECIES_CRAMORANT)
|
||||
&& ((gCurrentMove == MOVE_SURF && IsBattlerTurnDamaged(gBattlerTarget)) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER)
|
||||
&& ((gCurrentMove == MOVE_SURF && IsBattlerTurnDamaged(gBattlerTarget)) || gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable == STATE_UNDERWATER)
|
||||
&& TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT))
|
||||
{
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
@ -5506,7 +5506,7 @@ bool32 CanBattlerEscape(u32 battler) // no ability check
|
||||
return FALSE;
|
||||
else if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK)
|
||||
return FALSE;
|
||||
else if (gStatuses3[battler] & STATUS3_SKY_DROPPED)
|
||||
else if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP)
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
@ -5531,7 +5531,7 @@ bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag)
|
||||
{
|
||||
if (!(gFieldStatuses & terrainFlag))
|
||||
return FALSE;
|
||||
else if (gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE)
|
||||
if (IsSemiInvulnerable(battler, CHECK_ALL))
|
||||
return FALSE;
|
||||
|
||||
return IsBattlerGrounded(battler);
|
||||
@ -6066,7 +6066,7 @@ enum ItemEffect TryHandleSeed(u32 battler, u32 terrainFlag, u32 statId, u32 item
|
||||
static enum ItemEffect ConsumeBerserkGene(u32 battler, enum ItemCaseId caseID)
|
||||
{
|
||||
if (CanBeInfinitelyConfused(battler))
|
||||
gStatuses4[battler] |= STATUS4_INFINITE_CONFUSION;
|
||||
gBattleMons[battler].volatiles.infiniteConfusion = TRUE;
|
||||
|
||||
BufferStatChange(battler, STAT_ATK, STRINGID_STATROSE);
|
||||
gBattlerAttacker = gEffectBattler = battler;
|
||||
@ -7300,8 +7300,8 @@ void ClearVariousBattlerFlags(u32 battler)
|
||||
{
|
||||
gDisableStructs[battler].furyCutterCounter = 0;
|
||||
gBattleMons[battler].volatiles.destinyBond = FALSE;
|
||||
gBattleMons[battler].volatiles.glaiveRush = FALSE;
|
||||
gStatuses3[battler] &= ~STATUS3_GRUDGE;
|
||||
gStatuses4[battler] &= ~ STATUS4_GLAIVE_RUSH;
|
||||
}
|
||||
|
||||
void HandleAction_RunBattleScript(void) // identical to RunBattleScriptCommands
|
||||
@ -8286,7 +8286,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageContext *ctx)
|
||||
break;
|
||||
case EFFECT_MAGNITUDE:
|
||||
case EFFECT_EARTHQUAKE:
|
||||
if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE))
|
||||
if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && !IsSemiInvulnerable(battlerDef, CHECK_ALL))
|
||||
modifier = uq4_12_multiply(modifier, UQ_4_12(0.5));
|
||||
break;
|
||||
case EFFECT_KNOCK_OFF:
|
||||
@ -9077,7 +9077,7 @@ static inline uq4_12_t GetCriticalModifier(bool32 isCrit)
|
||||
|
||||
static inline uq4_12_t GetGlaiveRushModifier(u32 battlerDef)
|
||||
{
|
||||
if (gStatuses4[battlerDef] & STATUS4_GLAIVE_RUSH)
|
||||
if (gBattleMons[battlerDef].volatiles.glaiveRush)
|
||||
return UQ_4_12(2.0);
|
||||
return UQ_4_12(1.0);
|
||||
}
|
||||
@ -9102,21 +9102,21 @@ static inline uq4_12_t GetMinimizeModifier(u32 move, u32 battlerDef)
|
||||
|
||||
static inline uq4_12_t GetUndergroundModifier(u32 move, u32 battlerDef)
|
||||
{
|
||||
if (MoveDamagesUnderground(move) && gStatuses3[battlerDef] & STATUS3_UNDERGROUND)
|
||||
if (MoveDamagesUnderground(move) && gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_UNDERGROUND)
|
||||
return UQ_4_12(2.0);
|
||||
return UQ_4_12(1.0);
|
||||
}
|
||||
|
||||
static inline uq4_12_t GetDiveModifier(u32 move, u32 battlerDef)
|
||||
{
|
||||
if (MoveDamagesUnderWater(move) && gStatuses3[battlerDef] & STATUS3_UNDERWATER)
|
||||
if (MoveDamagesUnderWater(move) && gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_UNDERWATER)
|
||||
return UQ_4_12(2.0);
|
||||
return UQ_4_12(1.0);
|
||||
}
|
||||
|
||||
static inline uq4_12_t GetAirborneModifier(u32 move, u32 battlerDef)
|
||||
{
|
||||
if (MoveDamagesAirborneDoubleDamage(move) && gStatuses3[battlerDef] & STATUS3_ON_AIR)
|
||||
if (MoveDamagesAirborneDoubleDamage(move) && gBattleMons[battlerDef].volatiles.semiInvulnerable == STATE_ON_AIR)
|
||||
return UQ_4_12(2.0);
|
||||
return UQ_4_12(1.0);
|
||||
}
|
||||
@ -9934,7 +9934,7 @@ bool32 CanMegaEvolve(u32 battler)
|
||||
return FALSE;
|
||||
|
||||
// Check if battler is currently held by Sky Drop.
|
||||
if (gStatuses3[battler] & STATUS3_SKY_DROPPED)
|
||||
if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP)
|
||||
return FALSE;
|
||||
|
||||
// Check if battler is holding a Z-Crystal.
|
||||
@ -9972,7 +9972,7 @@ bool32 CanUltraBurst(u32 battler)
|
||||
return FALSE;
|
||||
|
||||
// Check if mon is currently held by Sky Drop
|
||||
if (gStatuses3[battler] & STATUS3_SKY_DROPPED)
|
||||
if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_SKY_DROP)
|
||||
return FALSE;
|
||||
|
||||
// Check if there is an entry in the form change table for Ultra Burst and battler is holding a Z-Crystal.
|
||||
@ -10784,7 +10784,7 @@ bool32 BlocksPrankster(u16 move, u32 battlerPrankster, u32 battlerDef, bool32 ch
|
||||
return FALSE;
|
||||
if (!IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK))
|
||||
return FALSE;
|
||||
if (gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)
|
||||
if (IsSemiInvulnerable(battlerDef, CHECK_ALL))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@ -10915,7 +10915,7 @@ void RecalcBattlerStats(u32 battler, struct Pokemon *mon, bool32 isDynamaxing)
|
||||
void RemoveConfusionStatus(u32 battler)
|
||||
{
|
||||
gBattleMons[battler].volatiles.confusionTurns = 0;
|
||||
gStatuses4[battler] &= ~STATUS4_INFINITE_CONFUSION;
|
||||
gBattleMons[battler].volatiles.infiniteConfusion = FALSE;
|
||||
}
|
||||
|
||||
static bool32 CanBeInfinitelyConfused(u32 battler)
|
||||
@ -11226,7 +11226,7 @@ bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef)
|
||||
u32 moveType = GetBattleMoveType(gCurrentMove);
|
||||
return ((CalcTypeEffectivenessMultiplierHelper(gCurrentMove, moveType, battlerAtk, battlerDef, GetBattlerAbility(battlerAtk), GetBattlerAbility(battlerDef), FALSE) == UQ_4_12(0.0))
|
||||
|| IsBattlerProtected(battlerAtk, battlerDef, gCurrentMove)
|
||||
|| IsSemiInvulnerable(battlerDef, gCurrentMove)
|
||||
|| !BreaksThroughSemiInvulnerablity(battlerDef, gCurrentMove)
|
||||
|| DoesBattlerHaveAbilityImmunity(battlerAtk, battlerDef, moveType));
|
||||
}
|
||||
|
||||
@ -11614,13 +11614,13 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u
|
||||
|
||||
if ((gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS && gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk)
|
||||
|| (B_TOXIC_NEVER_MISS >= GEN_6 && nonVolatileStatus == MOVE_EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON))
|
||||
|| gStatuses4[battlerDef] & STATUS4_GLAIVE_RUSH)
|
||||
|| gBattleMons[battlerDef].volatiles.glaiveRush)
|
||||
{
|
||||
effect = TRUE;
|
||||
}
|
||||
// If the attacker has the ability No Guard and they aren't targeting a Pokemon involved in a Sky Drop with the move Sky Drop, move hits.
|
||||
else if (abilityAtk == ABILITY_NO_GUARD
|
||||
&& !(gStatuses3[battlerDef] & STATUS3_COMMANDER)
|
||||
&& gBattleMons[battlerDef].volatiles.semiInvulnerable != STATE_COMMANDER
|
||||
&& (moveEffect != EFFECT_SKY_DROP || gBattleStruct->skyDropTargets[battlerDef] == SKY_DROP_NO_TARGET))
|
||||
{
|
||||
effect = TRUE;
|
||||
@ -11635,7 +11635,7 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u
|
||||
}
|
||||
// If the target is under the effects of Telekinesis, and the move isn't a OH-KO move, move hits.
|
||||
else if (gStatuses3[battlerDef] & STATUS3_TELEKINESIS
|
||||
&& !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE)
|
||||
&& !IsSemiInvulnerable(battlerDef, CHECK_ALL)
|
||||
&& moveEffect != EFFECT_OHKO
|
||||
&& moveEffect != EFFECT_SHEER_COLD)
|
||||
{
|
||||
@ -11645,15 +11645,11 @@ bool32 CanMoveSkipAccuracyCalc(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u
|
||||
{
|
||||
effect = TRUE;
|
||||
}
|
||||
else if (GetActiveGimmick(battlerAtk) == GIMMICK_Z_MOVE && !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE))
|
||||
else if (GetActiveGimmick(battlerAtk) == GIMMICK_Z_MOVE && !IsSemiInvulnerable(battlerDef, CHECK_ALL))
|
||||
{
|
||||
effect = TRUE;
|
||||
}
|
||||
else if ((gStatuses3[battlerDef] & STATUS3_COMMANDER)
|
||||
|| (gStatuses3[battlerDef] & STATUS3_PHANTOM_FORCE)
|
||||
|| ((gStatuses3[battlerDef] & STATUS3_ON_AIR) && !(MoveDamagesAirborne(move) || MoveDamagesAirborneDoubleDamage(move)))
|
||||
|| ((gStatuses3[battlerDef] & STATUS3_UNDERGROUND) && !MoveDamagesUnderground(move))
|
||||
|| ((gStatuses3[battlerDef] & STATUS3_UNDERWATER) && !MoveDamagesUnderWater(move)))
|
||||
else if (!BreaksThroughSemiInvulnerablity(battlerDef, move))
|
||||
{
|
||||
if (option == RUN_SCRIPT)
|
||||
{
|
||||
@ -11813,3 +11809,32 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u
|
||||
|
||||
return calc;
|
||||
}
|
||||
|
||||
bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander)
|
||||
{
|
||||
if (gBattleMons[battler].volatiles.semiInvulnerable == STATE_COMMANDER)
|
||||
return excludeCommander != EXCLUDE_COMMANDER;
|
||||
return gBattleMons[battler].volatiles.semiInvulnerable != STATE_NONE;
|
||||
}
|
||||
|
||||
bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move)
|
||||
{
|
||||
switch (gBattleMons[battler].volatiles.semiInvulnerable)
|
||||
{
|
||||
case STATE_UNDERGROUND:
|
||||
return MoveDamagesUnderground(move);
|
||||
case STATE_UNDERWATER:
|
||||
return MoveDamagesUnderWater(move);
|
||||
case STATE_ON_AIR:
|
||||
case STATE_SKY_DROP:
|
||||
return MoveDamagesAirborne(move) || MoveDamagesAirborneDoubleDamage(move);
|
||||
case STATE_PHANTOM_FORCE:
|
||||
return FALSE;
|
||||
case STATE_COMMANDER:
|
||||
return FALSE;
|
||||
case STATE_NONE:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -604,7 +604,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.sleepTalkBanned = TRUE,
|
||||
.instructBanned = TRUE,
|
||||
.assistBanned = TRUE,
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_PKMNFLEWHIGH, .status = COMPRESS_BITS(STATUS3_ON_AIR) },
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_PKMNFLEWHIGH, .status = STATE_ON_AIR },
|
||||
.contestEffect = CONTEST_EFFECT_AVOID_STARTLE,
|
||||
.contestCategory = CONTEST_CATEGORY_SMART,
|
||||
.contestComboStarterId = 0,
|
||||
@ -2461,7 +2461,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.instructBanned = TRUE,
|
||||
.assistBanned = TRUE,
|
||||
.skyBattleBanned = TRUE,
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_PKMNDUGHOLE, .status = COMPRESS_BITS(STATUS3_UNDERGROUND) },
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_PKMNDUGHOLE, .status = STATE_UNDERGROUND },
|
||||
.contestEffect = CONTEST_EFFECT_AVOID_STARTLE,
|
||||
.contestCategory = CONTEST_CATEGORY_SMART,
|
||||
.contestComboStarterId = 0,
|
||||
@ -7715,7 +7715,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.instructBanned = TRUE,
|
||||
.assistBanned = TRUE,
|
||||
.skyBattleBanned = TRUE,
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_PKMNHIDUNDERWATER, .status = COMPRESS_BITS(STATUS3_UNDERWATER) },
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_PKMNHIDUNDERWATER, .status = STATE_UNDERWATER },
|
||||
.contestEffect = CONTEST_EFFECT_AVOID_STARTLE_ONCE,
|
||||
.contestCategory = CONTEST_CATEGORY_BEAUTY,
|
||||
.contestComboStarterId = COMBO_STARTER_DIVE,
|
||||
@ -8974,7 +8974,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.sleepTalkBanned = TRUE,
|
||||
.instructBanned = TRUE,
|
||||
.assistBanned = TRUE,
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_PKMNSPRANGUP, .status = COMPRESS_BITS(STATUS3_ON_AIR) },
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_PKMNSPRANGUP, .status = STATE_ON_AIR },
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
.moveEffect = MOVE_EFFECT_PARALYSIS,
|
||||
.chance = 30,
|
||||
@ -12100,7 +12100,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.sleepTalkBanned = TRUE,
|
||||
.instructBanned = TRUE,
|
||||
.assistBanned = TRUE,
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = COMPRESS_BITS(STATUS3_PHANTOM_FORCE) },
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = STATE_PHANTOM_FORCE },
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
.moveEffect = MOVE_EFFECT_FEINT,
|
||||
}),
|
||||
@ -13065,7 +13065,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.sleepTalkBanned = TRUE,
|
||||
.instructBanned = TRUE,
|
||||
.assistBanned = TRUE,
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKTARGETHIGH, .status = COMPRESS_BITS(STATUS3_ON_AIR) },
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_PKMNTOOKTARGETHIGH, .status = STATE_ON_AIR },
|
||||
.contestEffect = CONTEST_EFFECT_AVOID_STARTLE,
|
||||
.contestCategory = CONTEST_CATEGORY_SMART,
|
||||
.contestComboStarterId = 0,
|
||||
@ -14505,7 +14505,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] =
|
||||
.sleepTalkBanned = TRUE,
|
||||
.instructBanned = TRUE,
|
||||
.assistBanned = TRUE,
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = COMPRESS_BITS(STATUS3_PHANTOM_FORCE) },
|
||||
.argument.twoTurnAttack = { .stringId = STRINGID_VANISHEDINSTANTLY, .status = STATE_PHANTOM_FORCE },
|
||||
.additionalEffects = ADDITIONAL_EFFECTS({
|
||||
.moveEffect = MOVE_EFFECT_FEINT,
|
||||
}),
|
||||
|
||||
@ -1110,7 +1110,7 @@ static u32 GetBallThrowableState(void)
|
||||
return BALL_THROW_UNABLE_TWO_MONS;
|
||||
else if (IsPlayerPartyAndPokemonStorageFull() == TRUE)
|
||||
return BALL_THROW_UNABLE_NO_ROOM;
|
||||
else if (B_SEMI_INVULNERABLE_CATCH >= GEN_4 && (gStatuses3[GetCatchingBattler()] & STATUS3_SEMI_INVULNERABLE))
|
||||
else if (B_SEMI_INVULNERABLE_CATCH >= GEN_4 && IsSemiInvulnerable(GetCatchingBattler(), CHECK_ALL))
|
||||
return BALL_THROW_UNABLE_SEMI_INVULNERABLE;
|
||||
else if (FlagGet(B_FLAG_NO_CATCHING))
|
||||
return BALL_THROW_UNABLE_DISABLED_FLAG;
|
||||
|
||||
@ -213,7 +213,7 @@ SINGLE_BATTLE_TEST("Berserk Gene causes infinite confusion") // check if bit is
|
||||
TURN {}
|
||||
} SCENE {
|
||||
} THEN {
|
||||
EXPECT(gStatuses4[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)] & STATUS4_INFINITE_CONFUSION);
|
||||
EXPECT(gBattleMons[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)].volatiles.infiniteConfusion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,17 +4,17 @@
|
||||
ASSUMPTIONS
|
||||
{
|
||||
ASSUME(GetMoveEffect(MOVE_FLY) == EFFECT_SEMI_INVULNERABLE);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_FLY) == STATUS3_ON_AIR);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_FLY) == STATE_ON_AIR);
|
||||
ASSUME(GetMoveEffect(MOVE_DIG) == EFFECT_SEMI_INVULNERABLE);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_DIG) == STATUS3_UNDERGROUND);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_DIG) == STATE_UNDERGROUND);
|
||||
ASSUME(GetMoveEffect(MOVE_BOUNCE) == EFFECT_SEMI_INVULNERABLE);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_BOUNCE) == STATUS3_ON_AIR);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_BOUNCE) == STATE_ON_AIR);
|
||||
ASSUME(GetMoveEffect(MOVE_DIVE) == EFFECT_SEMI_INVULNERABLE);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_DIVE) == STATUS3_UNDERWATER);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_DIVE) == STATE_UNDERWATER);
|
||||
ASSUME(GetMoveEffect(MOVE_PHANTOM_FORCE) == EFFECT_SEMI_INVULNERABLE);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_PHANTOM_FORCE) == STATUS3_PHANTOM_FORCE);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_PHANTOM_FORCE) == STATE_PHANTOM_FORCE);
|
||||
ASSUME(GetMoveEffect(MOVE_SHADOW_FORCE) == EFFECT_SEMI_INVULNERABLE);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_SHADOW_FORCE) == STATUS3_PHANTOM_FORCE);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_SHADOW_FORCE) == STATE_PHANTOM_FORCE);
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Semi-invulnerable moves make the user semi-invulnerable turn 1, then strike turn 2")
|
||||
|
||||
@ -41,9 +41,9 @@ SINGLE_BATTLE_TEST("Hurricane can hit airborne targets (Fly, Bounce)")
|
||||
PARAMETRIZE { move = MOVE_BOUNCE; }
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_FLY) == EFFECT_SEMI_INVULNERABLE);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_FLY) == STATUS3_ON_AIR);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_FLY) == STATE_ON_AIR);
|
||||
ASSUME(GetMoveEffect(MOVE_BOUNCE) == EFFECT_SEMI_INVULNERABLE);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_BOUNCE) == STATUS3_ON_AIR);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_BOUNCE) == STATE_ON_AIR);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(move); }
|
||||
} WHEN {
|
||||
@ -59,7 +59,7 @@ DOUBLE_BATTLE_TEST("Hurricane can hit airborne targets (Sky Drop)")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_SKY_DROP) == EFFECT_SKY_DROP);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_SKY_DROP) == STATUS3_ON_AIR);
|
||||
ASSUME(GetMoveTwoTurnAttackStatus(MOVE_SKY_DROP) == STATE_ON_AIR);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user