Remove cases from ABE, add functionality of Flower Veil

This commit is contained in:
DizzyEggg 2019-03-31 21:38:58 +02:00
parent d90767c490
commit b12334c88b
13 changed files with 240 additions and 195 deletions

View File

@ -171,12 +171,21 @@
.4byte \ptr
.endm
.macro jumpiftype battler:req, type:req, ptr:req
.macro jumpbasedontype battler:req, type:req, case:req, ptr:req
.byte 0x22
.byte \battler
.byte \type
.byte \case
.4byte \ptr
.endm
.macro jumpiftype battler:req, type:req, ptr:req
jumpbasedontype \battler, \type, 1, \ptr
.endm
.macro jumpifnottype battler:req, type:req, ptr:req
jumpbasedontype \battler, \type, 0, \ptr
.endm
.macro getexp battler:req
.byte 0x23
@ -1728,3 +1737,10 @@
.macro dmgtocurrattackerhp
manipulatedamage ATK80_CURR_ATTACKER_HP
.endm
.macro jumpifflowerveil jumpptr:req
jumpifnottype BS_TARGET, TYPE_GRASS, 1f
jumpifability BS_TARGET_SIDE, ABILITY_FLOWER_VEIL, \jumpptr
1:
.endm

View File

@ -1818,6 +1818,7 @@ BattleScript_EffectSleep::
jumpifsubstituteblocks BattleScript_ButItFailed
jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_AlreadyAsleep
jumpifcantmakeasleep BattleScript_CantMakeAsleep
jumpifflowerveil BattleScript_FlowerVeilProtects
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
jumpifsideaffecting BS_TARGET, SIDE_STATUS_SAFEGUARD, BattleScript_SafeguardProtected
@ -1826,6 +1827,18 @@ BattleScript_EffectSleep::
setmoveeffect MOVE_EFFECT_SLEEP
seteffectprimary
goto BattleScript_MoveEnd
BattleScript_FlowerVeilProtectsRet::
pause 0x20
call BattleScript_AbilityPopUp
printstring STRINGID_FLOWERVEILPROTECTED
waitmessage 0x40
return
BattleScript_FlowerVeilProtects:
call BattleScript_FlowerVeilProtectsRet
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
goto BattleScript_MoveEnd
BattleScript_AlreadyAsleep::
setalreadystatusedmoveattempt BS_ATTACKER
@ -2265,6 +2278,7 @@ BattleScript_EffectToxic::
attackstring
ppreduce
jumpifability BS_TARGET, ABILITY_IMMUNITY, BattleScript_ImmunityProtected
jumpifflowerveil BattleScript_FlowerVeilProtects
jumpifsubstituteblocks BattleScript_ButItFailed
jumpifstatus BS_TARGET, STATUS1_POISON, BattleScript_AlreadyPoisoned
jumpifstatus BS_TARGET, STATUS1_TOXIC_POISON, BattleScript_AlreadyPoisoned
@ -2587,6 +2601,7 @@ BattleScript_EffectPoison::
attackstring
ppreduce
jumpifability BS_TARGET, ABILITY_IMMUNITY, BattleScript_ImmunityProtected
jumpifflowerveil BattleScript_FlowerVeilProtects
jumpifsubstituteblocks BattleScript_ButItFailed
jumpifstatus BS_TARGET, STATUS1_POISON, BattleScript_AlreadyPoisoned
jumpifstatus BS_TARGET, STATUS1_TOXIC_POISON, BattleScript_AlreadyPoisoned
@ -2608,6 +2623,7 @@ BattleScript_EffectParalyze:
attackstring
ppreduce
jumpifability BS_TARGET, ABILITY_LIMBER, BattleScript_LimberProtected
jumpifflowerveil BattleScript_FlowerVeilProtects
jumpifsubstituteblocks BattleScript_ButItFailed
typecalc
jumpifmovehadnoeffect BattleScript_ButItFailed
@ -3789,6 +3805,7 @@ BattleScript_EffectWillOWisp::
jumpifstatus BS_TARGET, STATUS1_BURN, BattleScript_AlreadyBurned
jumpiftype BS_TARGET, TYPE_FIRE, BattleScript_NotAffected
jumpifability BS_TARGET, ABILITY_WATER_VEIL, BattleScript_WaterVeilPrevents
jumpifflowerveil BattleScript_FlowerVeilProtects
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
jumpifsideaffecting BS_TARGET, SIDE_STATUS_SAFEGUARD, BattleScript_SafeguardProtected
@ -4050,6 +4067,7 @@ BattleScript_EffectYawn::
ppreduce
jumpifability BS_TARGET, ABILITY_VITAL_SPIRIT, BattleScript_PrintBankAbilityMadeIneffective
jumpifability BS_TARGET, ABILITY_INSOMNIA, BattleScript_PrintBankAbilityMadeIneffective
jumpifflowerveil BattleScript_FlowerVeilProtects
jumpifsubstituteblocks BattleScript_ButItFailed
jumpifsideaffecting BS_TARGET, SIDE_STATUS_SAFEGUARD, BattleScript_SafeguardProtected
accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON
@ -4061,7 +4079,7 @@ BattleScript_EffectYawn::
waitmessage 0x40
goto BattleScript_MoveEnd
BattleScript_PrintBankAbilityMadeIneffective::
copybyte sBATTLER, sBATTLER_WITH_ABILITY
copybyte sBATTLER, gBattlerAbility
BattleScript_PrintAbilityMadeIneffective::
pause 0x20
printstring STRINGID_PKMNSXMADEITINEFFECTIVE

View File

@ -620,7 +620,7 @@ struct BattleScripting
u8 animArg2;
u16 tripleKickPower;
u8 atk49_state;
u8 battlerWithAbility;
u8 unused_15;
u8 unused_16;
u8 battler;
u8 animTurn;

View File

@ -14,6 +14,7 @@ void HandleBattleWindow(u8 xStart, u8 yStart, u8 xEnd, u8 yEnd, u8 flags);
bool8 UproarWakeUpCheck(u8 battlerId);
bool32 DoesSubstituteBlockMove(u8 battlerAtk, u8 battlerDef, u32 move);
bool32 CanUseLastResort(u8 battlerId);
u32 IsFlowerVeilProtected(u32 battler);
extern void (* const gBattleScriptingCommandsTable[])(void);
extern const u8 gUnknown_0831C494[][4];

View File

@ -300,5 +300,6 @@ extern const u8 BattleScript_PowderMoveNoEffect[];
extern const u8 BattleScript_GrassyTerrainLoop[];
extern const u8 BattleScript_VCreateStatLoss[];
extern const u8 BattleScript_SpikyShieldEffect[];
extern const u8 BattleScript_FlowerVeilProtectsRet[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@ -6,7 +6,7 @@
#define MOVE_LIMITATION_DISABLED (1 << 2)
#define MOVE_LIMITATION_TORMENTED (1 << 3)
#define MOVE_LIMITATION_TAUNT (1 << 4)
#define MOVE_LIMITATION_IMPRISON (1 << 5)
#define MOVE_LIMITATION_IMPRISON (1 << 5)
#define ABILITYEFFECT_ON_SWITCHIN 0x0
#define ABILITYEFFECT_ENDTURN 0x1
@ -20,23 +20,13 @@
#define ABILITYEFFECT_INTIMIDATE1 0x9
#define ABILITYEFFECT_INTIMIDATE2 0xA
#define ABILITYEFFECT_TRACE 0xB
#define ABILITYEFFECT_CHECK_OTHER_SIDE 0xC
#define ABILITYEFFECT_CHECK_BATTLER_SIDE 0xD
#define ABILITYEFFECT_CHECK_FIELD_EXCEPT_BATTLER 0xF
#define ABILITYEFFECT_COUNT_OTHER_SIDE 0x10
#define ABILITYEFFECT_COUNT_BATTLER_SIDE 0x11
#define ABILITYEFFECT_COUNT_ON_FIELD 0x12
#define ABILITYEFFECT_CHECK_ON_FIELD 0x13
#define ABILITYEFFECT_SWITCH_IN_WEATHER 0xFF
#define ABILITY_ON_OPPOSING_FIELD(battlerId, abilityId)(AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, battlerId, abilityId, 0, 0))
#define ABILITY_ON_FIELD(abilityId)(AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, abilityId, 0, 0))
#define ITEMEFFECT_ON_SWITCH_IN 0x0
#define ITEMEFFECT_MOVE_END 0x3
#define ITEMEFFECT_KINGSROCK_SHELLBELL 0x4
#define WEATHER_HAS_EFFECT ((!ABILITY_ON_FIELD(ABILITY_CLOUD_NINE) && !ABILITY_ON_FIELD(ABILITY_AIR_LOCK)))
#define WEATHER_HAS_EFFECT ((!IsAbilityOnField(ABILITY_CLOUD_NINE) && !IsAbilityOnField(ABILITY_AIR_LOCK)))
#define IS_WHOLE_SIDE_ALIVE(battler)((IsBattlerAlive(battler) && IsBattlerAlive(BATTLE_PARTNER(battler))))
@ -72,6 +62,11 @@ bool8 HasNoMonsToSwitch(u8 battlerId, u8 r1, u8 r2);
u8 CastformDataTypeChange(u8 battlerId);
bool32 TryChangeBattleWeather(u8 battler, u32 weatherEnumId, bool32 viaAbility);
u8 AbilityBattleEffects(u8 caseID, u8 battlerId, u8 ability, u8 special, u16 moveArg);
u32 GetBattlerAbility(u8 battlerId);
u32 IsAbilityOnSide(u32 battlerId, u32 ability);
u32 IsAbilityOnOpposingSide(u32 battlerId, u32 ability);
u32 IsAbilityOnField(u32 ability);
u32 IsAbilityOnFieldExcept(u32 battlerId, u32 ability);
void BattleScriptExecute(const u8* BS_ptr);
void BattleScriptPushCursorAndCallback(const u8* BS_ptr);
u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn);
@ -79,7 +74,6 @@ void ClearFuryCutterDestinyBondGrudge(u8 battlerId);
void HandleAction_RunBattleScript(void);
u8 GetMoveTarget(u16 move, u8 setTarget);
u8 IsMonDisobedient(void);
u32 GetBattlerAbility(u8 battlerId);
u32 GetBattlerHoldEffect(u8 battlerId, bool32 checkNegating);
u32 GetBattlerHoldEffectParam(u8 battlerId);
bool32 IsMoveMakingContact(u16 move, u8 battlerAtk);

View File

@ -11,7 +11,7 @@
#define sB_ANIM_ARG2 gBattleScripting + 0x11
#define sTRIPLE_KICK_POWER gBattleScripting + 0x12
#define sMOVEEND_STATE gBattleScripting + 0x14
#define sBATTLER_WITH_ABILITY gBattleScripting + 0x15
#define sUNUSED_15 gBattleScripting + 0x15
#define sUNUSED_16 gBattleScripting + 0x16
#define sBATTLER gBattleScripting + 0x17
#define sB_ANIM_TURN gBattleScripting + 0x18
@ -45,7 +45,7 @@
#define BS_BATTLER_0 7
#define BS_ATTACKER_WITH_PARTNER 4 // for atk98_status_icon_update
#define BS_ATTACKER_SIDE 8 // for atk1E_jumpifability
#define BS_NOT_ATTACKER_SIDE 9 // for atk1E_jumpifability
#define BS_TARGET_SIDE 9 // for atk1E_jumpifability
#define BS_SCRIPTING 10
#define BS_PLAYER1 11
#define BS_OPPONENT1 12
@ -139,6 +139,7 @@
#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 76
#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 77
#define VARIOUS_JUMP_IF_ROAR_FAILS 78
#define VARIOUS_JUMP_IF_FLOWER_VEIL 79
// atk80, dmg manipulation
#define ATK80_DMG_CHANGE_SIGN 0

View File

@ -524,6 +524,7 @@
#define STRINGID_ELECTRICTERRAINPREVENTS 520
#define STRINGID_PSYCHICTERRAINPREVENTS 521
#define STRINGID_SAFETYGOOGLESPROTECTED 522
#define STRINGID_FLOWERVEILPROTECTED 523
#define BATTLESTRINGS_COUNT 529

View File

@ -414,11 +414,11 @@ static bool8 ShouldSwitch(void)
return FALSE;
if (gStatuses3[gActiveBattler] & STATUS3_ROOTED)
return FALSE;
if (ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_SHADOW_TAG))
if (IsAbilityOnOpposingSide(gActiveBattler, ABILITY_SHADOW_TAG))
return FALSE;
if (ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_ARENA_TRAP)) // Misses the flying type and Levitate check.
if (IsAbilityOnOpposingSide(gActiveBattler, ABILITY_ARENA_TRAP)) // Misses the flying type and Levitate check.
return FALSE;
if (ABILITY_ON_FIELD(ABILITY_MAGNET_PULL))
if (IsAbilityOnField(ABILITY_MAGNET_PULL))
{
if (gBattleMons[gActiveBattler].type1 == TYPE_STEEL)
return FALSE;

View File

@ -3711,7 +3711,7 @@ u8 IsRunningFromBattleImpossible(void)
return 2;
}
}
i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BATTLER, gActiveBattler, ABILITY_MAGNET_PULL, 0, 0);
i = IsAbilityOnFieldExcept(gActiveBattler, ABILITY_MAGNET_PULL);
if (i != 0 && IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL))
{
gBattleScripting.battler = i - 1;
@ -3902,11 +3902,11 @@ static void HandleTurnActionSelectionState(void)
{
BtlController_EmitChoosePokemon(0, PARTY_CANT_SWITCH, 6, ABILITY_NONE, gBattleStruct->field_60[gActiveBattler]);
}
else if ((i = ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_SHADOW_TAG))
|| ((i = ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_ARENA_TRAP))
else if ((i = IsAbilityOnOpposingSide(gActiveBattler, ABILITY_SHADOW_TAG))
|| ((i = IsAbilityOnOpposingSide(gActiveBattler, ABILITY_ARENA_TRAP))
&& !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_FLYING)
&& gBattleMons[gActiveBattler].ability != ABILITY_LEVITATE)
|| ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BATTLER, gActiveBattler, ABILITY_MAGNET_PULL, 0, 0))
|| ((i = IsAbilityOnFieldExcept(gActiveBattler, ABILITY_MAGNET_PULL))
&& IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL)))
{
BtlController_EmitChoosePokemon(0, ((i - 1) << 4) | PARTY_ABILITY_PREVENTS, 6, gLastUsedAbility, gBattleStruct->field_60[gActiveBattler]);

View File

@ -649,9 +649,11 @@ static const u8 sText_GrassyTerrainHeals[] = _("{B_ATK_NAME_WITH_PREFIX} is heal
static const u8 sText_ElectricTerrainPreventsSleep[] = _("{B_DEF_NAME_WITH_PREFIX} surrounds itself\nwith electrified terrain!");
static const u8 sText_PsychicTerrainPreventsPriority[] = _("{B_DEF_NAME_WITH_PREFIX} surrounds itself\nwith psychic terrain!");
static const u8 sText_SafetyGooglesProtected[] = _("{B_DEF_NAME_WITH_PREFIX} is not affected\nthanks to its {B_LAST_ITEM}!");
static const u8 sText_FlowerVeilProtected[] = _("{B_DEF_NAME_WITH_PREFIX} surrounded itself\nwith a veil of petals!");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_FLOWERVEILPROTECTED - 12] = sText_FlowerVeilProtected,
[STRINGID_SAFETYGOOGLESPROTECTED - 12] = sText_SafetyGooglesProtected,
[STRINGID_SPECTRALTHIEFSTEAL - 12] = sText_SpectralThiefSteal,
[STRINGID_BELCHCANTSELECT - 12] = sText_BelchCantUse,

View File

@ -109,7 +109,7 @@ static void atk1E_jumpifability(void);
static void atk1F_jumpifsideaffecting(void);
static void atk20_jumpifstat(void);
static void atk21_jumpifstatus3condition(void);
static void atk22_jumpiftype(void);
static void atk22_jumpbasedontype(void);
static void atk23_getexp(void);
static void atk24(void);
static void atk25_movevaluescleanup(void);
@ -368,7 +368,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
atk1F_jumpifsideaffecting,
atk20_jumpifstat,
atk21_jumpifstatus3condition,
atk22_jumpiftype,
atk22_jumpbasedontype,
atk23_getexp,
atk24,
atk25_movevaluescleanup,
@ -1285,7 +1285,7 @@ static void atk02_attackstring(void)
static void atk03_ppreduce(void)
{
s32 ppToDeduct = 1;
s32 i, ppToDeduct = 1;
if (gBattleControllerExecFlags)
return;
@ -1295,14 +1295,22 @@ static void atk03_ppreduce(void)
switch (gBattleMoves[gCurrentMove].target)
{
case MOVE_TARGET_FOES_AND_ALLY:
ppToDeduct += AbilityBattleEffects(ABILITYEFFECT_COUNT_ON_FIELD, gBattlerAttacker, ABILITY_PRESSURE, 0, 0);
for (i = 0; i < gBattlersCount; i++)
{
if (i != gBattlerAttacker && IsBattlerAlive(i))
ppToDeduct += (GetBattlerAbility(i) == ABILITY_PRESSURE);
}
break;
case MOVE_TARGET_BOTH:
case MOVE_TARGET_OPPONENTS_FIELD:
ppToDeduct += AbilityBattleEffects(ABILITYEFFECT_COUNT_OTHER_SIDE, gBattlerAttacker, ABILITY_PRESSURE, 0, 0);
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerSide(i) != GetBattlerSide(gBattlerAttacker) && IsBattlerAlive(i))
ppToDeduct += (GetBattlerAbility(i) == ABILITY_PRESSURE);
}
break;
default:
if (gBattlerAttacker != gBattlerTarget && gBattleMons[gBattlerTarget].ability == ABILITY_PRESSURE)
if (gBattlerAttacker != gBattlerTarget && GetBattlerAbility(gBattlerTarget) == ABILITY_PRESSURE)
ppToDeduct++;
break;
}
@ -2004,7 +2012,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
gBattleScripting.battler = gBattlerAttacker;
}
if (gBattleMons[gEffectBattler].ability == ABILITY_SHIELD_DUST && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
if (GetBattlerAbility(gEffectBattler) == ABILITY_SHIELD_DUST && !(gHitMarker & HITMARKER_IGNORE_SAFEGUARD)
&& !primary && gBattleScripting.moveEffect <= 9)
INCREMENT_RESET_RETURN
@ -2026,7 +2034,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
{
case STATUS1_SLEEP:
// check active uproar
if (gBattleMons[gEffectBattler].ability != ABILITY_SOUNDPROOF)
if (GetBattlerAbility(gEffectBattler) != ABILITY_SOUNDPROOF)
{
for (gActiveBattler = 0;
gActiveBattler < gBattlersCount && !(gBattleMons[gActiveBattler].status2 & STATUS2_UPROAR);
@ -2040,16 +2048,16 @@ void SetMoveEffect(bool32 primary, u32 certain)
break;
if (gActiveBattler != gBattlersCount)
break;
if (gBattleMons[gEffectBattler].ability == ABILITY_VITAL_SPIRIT)
break;
if (gBattleMons[gEffectBattler].ability == ABILITY_INSOMNIA)
if (GetBattlerAbility(gEffectBattler) == ABILITY_VITAL_SPIRIT
|| GetBattlerAbility(gEffectBattler) == ABILITY_INSOMNIA
|| IsFlowerVeilProtected(gEffectBattler))
break;
CancelMultiTurnMoves(gEffectBattler);
statusChanged = TRUE;
break;
case STATUS1_POISON:
if (gBattleMons[gEffectBattler].ability == ABILITY_IMMUNITY
if (GetBattlerAbility(gEffectBattler) == ABILITY_IMMUNITY
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
{
gLastUsedAbility = ABILITY_IMMUNITY;
@ -2085,13 +2093,13 @@ void SetMoveEffect(bool32 primary, u32 certain)
break;
if (gBattleMons[gEffectBattler].status1)
break;
if (gBattleMons[gEffectBattler].ability == ABILITY_IMMUNITY)
if (GetBattlerAbility(gEffectBattler) == ABILITY_IMMUNITY || IsFlowerVeilProtected(gEffectBattler))
break;
statusChanged = TRUE;
break;
case STATUS1_BURN:
if (gBattleMons[gEffectBattler].ability == ABILITY_WATER_VEIL
if (GetBattlerAbility(gEffectBattler) == ABILITY_WATER_VEIL
&& (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
{
gLastUsedAbility = ABILITY_WATER_VEIL;
@ -2122,7 +2130,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
}
if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_FIRE))
break;
if (gBattleMons[gEffectBattler].ability == ABILITY_WATER_VEIL)
if (GetBattlerAbility(gEffectBattler) == ABILITY_WATER_VEIL || IsFlowerVeilProtected(gEffectBattler))
break;
if (gBattleMons[gEffectBattler].status1)
break;
@ -2138,14 +2146,14 @@ void SetMoveEffect(bool32 primary, u32 certain)
break;
if (noSunCanFreeze == 0)
break;
if (gBattleMons[gEffectBattler].ability == ABILITY_MAGMA_ARMOR)
if (GetBattlerAbility(gEffectBattler) == ABILITY_MAGMA_ARMOR || IsFlowerVeilProtected(gEffectBattler))
break;
CancelMultiTurnMoves(gEffectBattler);
statusChanged = TRUE;
break;
case STATUS1_PARALYSIS:
if (gBattleMons[gEffectBattler].ability == ABILITY_LIMBER)
if (GetBattlerAbility(gEffectBattler) == ABILITY_LIMBER)
{
if (primary == TRUE || certain == MOVE_EFFECT_CERTAIN)
{
@ -2181,7 +2189,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
}
if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_ELECTRIC))
break;
if (gBattleMons[gEffectBattler].ability == ABILITY_LIMBER)
if (GetBattlerAbility(gEffectBattler) == ABILITY_LIMBER || IsFlowerVeilProtected(gEffectBattler))
break;
if (gBattleMons[gEffectBattler].status1)
break;
@ -2189,7 +2197,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
statusChanged = TRUE;
break;
case STATUS1_TOXIC_POISON:
if (gBattleMons[gEffectBattler].ability == ABILITY_IMMUNITY && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
if (GetBattlerAbility(gEffectBattler) == ABILITY_IMMUNITY && (primary == TRUE || certain == MOVE_EFFECT_CERTAIN))
{
gLastUsedAbility = ABILITY_IMMUNITY;
RecordAbilityBattle(gEffectBattler, ABILITY_IMMUNITY);
@ -2222,7 +2230,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
break;
if (!IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_POISON) && !IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_STEEL))
{
if (gBattleMons[gEffectBattler].ability == ABILITY_IMMUNITY)
if (GetBattlerAbility(gEffectBattler) == ABILITY_IMMUNITY || IsFlowerVeilProtected(gEffectBattler))
break;
// It's redundant, because at this point we know the status1 value is 0.
@ -2269,8 +2277,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
|| gBattleScripting.moveEffect == MOVE_EFFECT_PARALYSIS
|| gBattleScripting.moveEffect == MOVE_EFFECT_BURN)
{
u8* synchronizeEffect = &gBattleStruct->synchronizeMoveEffect;
*synchronizeEffect = gBattleScripting.moveEffect;
gBattleStruct->synchronizeMoveEffect = gBattleScripting.moveEffect;
gHitMarker |= HITMARKER_SYNCHRONISE_EFFECT;
}
return;
@ -2295,7 +2302,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
switch (gBattleScripting.moveEffect)
{
case MOVE_EFFECT_CONFUSION:
if (gBattleMons[gEffectBattler].ability == ABILITY_OWN_TEMPO
if (GetBattlerAbility(gEffectBattler) == ABILITY_OWN_TEMPO
|| gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION)
{
gBattlescriptCurrInstr++;
@ -2648,7 +2655,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
}
break;
case MOVE_EFFECT_KNOCK_OFF:
if (gBattleMons[gEffectBattler].ability == ABILITY_STICKY_HOLD)
if (GetBattlerAbility(gEffectBattler) == ABILITY_STICKY_HOLD)
{
if (gBattleMons[gEffectBattler].item == 0)
{
@ -2991,48 +2998,45 @@ static void atk1D_jumpifstatus2(void)
static void atk1E_jumpifability(void)
{
u8 battlerId;
u8 ability = gBattlescriptCurrInstr[2];
const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 3);
u32 battlerId;
bool32 hasAbility = FALSE;
u32 ability = gBattlescriptCurrInstr[2];
if (gBattlescriptCurrInstr[1] == BS_ATTACKER_SIDE)
switch (gBattlescriptCurrInstr[1])
{
battlerId = AbilityBattleEffects(ABILITYEFFECT_CHECK_BATTLER_SIDE, gBattlerAttacker, ability, 0, 0);
default:
battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
if (GetBattlerAbility(battlerId) == ability)
hasAbility = TRUE;
break;
case BS_ATTACKER_SIDE:
battlerId = IsAbilityOnSide(gBattlerAttacker, ability);
if (battlerId)
{
gLastUsedAbility = ability;
gBattlescriptCurrInstr = jumpPtr;
RecordAbilityBattle(battlerId - 1, gLastUsedAbility);
gBattleScripting.battlerWithAbility = battlerId - 1;
battlerId--;
hasAbility = TRUE;
}
else
gBattlescriptCurrInstr += 7;
break;
case BS_TARGET_SIDE:
battlerId = IsAbilityOnOpposingSide(gBattlerAttacker, ability);
if (battlerId)
{
battlerId--;
hasAbility = TRUE;
}
break;
}
else if (gBattlescriptCurrInstr[1] == BS_NOT_ATTACKER_SIDE)
if (hasAbility)
{
battlerId = AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gBattlerAttacker, ability, 0, 0);
if (battlerId)
{
gLastUsedAbility = ability;
gBattlescriptCurrInstr = jumpPtr;
RecordAbilityBattle(battlerId - 1, gLastUsedAbility);
gBattleScripting.battlerWithAbility = battlerId - 1;
}
else
gBattlescriptCurrInstr += 7;
gLastUsedAbility = ability;
gBattlescriptCurrInstr = T2_READ_PTR(gBattlescriptCurrInstr + 3);
RecordAbilityBattle(battlerId, gLastUsedAbility);
gBattlerAbility = battlerId;
}
else
{
battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
if (gBattleMons[battlerId].ability == ability)
{
gLastUsedAbility = ability;
gBattlescriptCurrInstr = jumpPtr;
RecordAbilityBattle(battlerId, gLastUsedAbility);
gBattleScripting.battlerWithAbility = battlerId;
}
else
gBattlescriptCurrInstr += 7;
gBattlescriptCurrInstr += 7;
}
}
@ -3138,16 +3142,28 @@ static void atk21_jumpifstatus3condition(void)
}
}
static void atk22_jumpiftype(void)
static void atk22_jumpbasedontype(void)
{
u8 battlerId = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
u8 type = gBattlescriptCurrInstr[2];
const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 3);
const u8* jumpPtr = T2_READ_PTR(gBattlescriptCurrInstr + 4);
if (IS_BATTLER_OF_TYPE(battlerId, type))
gBattlescriptCurrInstr = jumpPtr;
// jumpiftype
if (gBattlescriptCurrInstr[3])
{
if (IS_BATTLER_OF_TYPE(battlerId, type))
gBattlescriptCurrInstr = jumpPtr;
else
gBattlescriptCurrInstr += 8;
}
// jumpifnottype
else
gBattlescriptCurrInstr += 7;
{
if (!IS_BATTLER_OF_TYPE(battlerId, type))
gBattlescriptCurrInstr = jumpPtr;
else
gBattlescriptCurrInstr += 8;
}
}
static void atk23_getexp(void)
@ -3918,7 +3934,7 @@ static void atk42_setroost(void)
static void atk43_jumpifabilitypresent(void)
{
if (AbilityBattleEffects(ABILITYEFFECT_CHECK_ON_FIELD, 0, gBattlescriptCurrInstr[1], 0, 0))
if (IsAbilityOnField(gBattlescriptCurrInstr[1]))
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 2);
else
gBattlescriptCurrInstr += 6;
@ -6360,6 +6376,14 @@ static bool32 ClearDefogHazards(u8 battlerAtk, bool32 clear)
return FALSE;
}
u32 IsFlowerVeilProtected(u32 battler)
{
if (IS_BATTLER_OF_TYPE(battler, TYPE_GRASS))
return IsAbilityOnSide(battler, ABILITY_FLOWER_VEIL);
else
return 0;
}
static void atk76_various(void)
{
struct Pokemon *mon;
@ -7689,15 +7713,15 @@ bool8 UproarWakeUpCheck(u8 battlerId)
static void atk84_jumpifcantmakeasleep(void)
{
const u8 *jumpPtr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
u32 ability = GetBattlerAbility(gBattlerTarget);
if (UproarWakeUpCheck(gBattlerTarget))
{
gBattlescriptCurrInstr = jumpPtr;
}
else if (gBattleMons[gBattlerTarget].ability == ABILITY_INSOMNIA
|| gBattleMons[gBattlerTarget].ability == ABILITY_VITAL_SPIRIT)
else if (ability == ABILITY_INSOMNIA || ability == ABILITY_VITAL_SPIRIT)
{
gLastUsedAbility = gBattleMons[gBattlerTarget].ability;
gLastUsedAbility = ability;
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
gBattlescriptCurrInstr = jumpPtr;
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
@ -7851,8 +7875,8 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
gBattlescriptCurrInstr = BattleScript_ButItFailed;
return STAT_CHANGE_DIDNT_WORK;
}
else if ((gBattleMons[gActiveBattler].ability == ABILITY_CLEAR_BODY
|| gBattleMons[gActiveBattler].ability == ABILITY_WHITE_SMOKE)
else if ((GetBattlerAbility(gActiveBattler) == ABILITY_CLEAR_BODY
|| GetBattlerAbility(gActiveBattler) == ABILITY_WHITE_SMOKE)
&& !certain && gCurrentMove != MOVE_CURSE)
{
if (flags == STAT_CHANGE_BS_PTR)
@ -7867,14 +7891,34 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
gBattleScripting.battler = gActiveBattler;
gBattlerAbility = gActiveBattler;
gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss;
gLastUsedAbility = gBattleMons[gActiveBattler].ability;
gLastUsedAbility = GetBattlerAbility(gActiveBattler);
RecordAbilityBattle(gActiveBattler, gLastUsedAbility);
gSpecialStatuses[gActiveBattler].statLowered = 1;
}
}
return STAT_CHANGE_DIDNT_WORK;
}
else if (gBattleMons[gActiveBattler].ability == ABILITY_KEEN_EYE
else if ((index = IsFlowerVeilProtected(gActiveBattler)) && !certain)
{
if (flags == STAT_CHANGE_BS_PTR)
{
if (gSpecialStatuses[gActiveBattler].statLowered)
{
gBattlescriptCurrInstr = BS_ptr;
}
else
{
BattleScriptPush(BS_ptr);
gBattleScripting.battler = gActiveBattler;
gBattlerAbility = index - 1;
gBattlescriptCurrInstr = BattleScript_FlowerVeilProtectsRet;
gLastUsedAbility = ABILITY_FLOWER_VEIL;
gSpecialStatuses[gActiveBattler].statLowered = 1;
}
}
return STAT_CHANGE_DIDNT_WORK;
}
else if (GetBattlerAbility(gActiveBattler) == ABILITY_KEEN_EYE
&& !certain && statId == STAT_ACC)
{
if (flags == STAT_CHANGE_BS_PTR)
@ -7883,12 +7927,12 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
gBattleScripting.battler = gActiveBattler;
gBattlerAbility = gActiveBattler;
gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss;
gLastUsedAbility = gBattleMons[gActiveBattler].ability;
gLastUsedAbility = GetBattlerAbility(gActiveBattler);
RecordAbilityBattle(gActiveBattler, gLastUsedAbility);
}
return STAT_CHANGE_DIDNT_WORK;
}
else if (gBattleMons[gActiveBattler].ability == ABILITY_HYPER_CUTTER
else if (GetBattlerAbility(gActiveBattler) == ABILITY_HYPER_CUTTER
&& !certain && statId == STAT_ATK)
{
if (flags == STAT_CHANGE_BS_PTR)
@ -7897,12 +7941,12 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
gBattleScripting.battler = gActiveBattler;
gBattlerAbility = gActiveBattler;
gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss;
gLastUsedAbility = gBattleMons[gActiveBattler].ability;
gLastUsedAbility = GetBattlerAbility(gActiveBattler);
RecordAbilityBattle(gActiveBattler, gLastUsedAbility);
}
return STAT_CHANGE_DIDNT_WORK;
}
else if (gBattleMons[gActiveBattler].ability == ABILITY_SHIELD_DUST && flags == 0)
else if (GetBattlerAbility(gActiveBattler) == ABILITY_SHIELD_DUST && flags == 0)
{
return STAT_CHANGE_DIDNT_WORK;
}

View File

@ -3560,83 +3560,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
}
}
break;
case ABILITYEFFECT_CHECK_OTHER_SIDE: // 12
side = GetBattlerSide(battler);
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerSide(i) != side && gBattleMons[i].ability == ability)
{
gLastUsedAbility = ability;
effect = i + 1;
}
}
break;
case ABILITYEFFECT_CHECK_BATTLER_SIDE: // 13
side = GetBattlerSide(battler);
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerSide(i) == side && gBattleMons[i].ability == ability)
{
gLastUsedAbility = ability;
effect = i + 1;
}
}
break;
case ABILITYEFFECT_CHECK_ON_FIELD: // 19
for (i = 0; i < gBattlersCount; i++)
{
if (gBattleMons[i].ability == ability && gBattleMons[i].hp != 0)
{
gLastUsedAbility = ability;
effect = i + 1;
}
}
break;
case ABILITYEFFECT_CHECK_FIELD_EXCEPT_BATTLER: // 15
for (i = 0; i < gBattlersCount; i++)
{
if (gBattleMons[i].ability == ability && i != battler)
{
gLastUsedAbility = ability;
effect = i + 1;
}
}
break;
case ABILITYEFFECT_COUNT_OTHER_SIDE: // 16
side = GetBattlerSide(battler);
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerSide(i) != side && gBattleMons[i].ability == ability)
{
gLastUsedAbility = ability;
effect++;
}
}
break;
case ABILITYEFFECT_COUNT_BATTLER_SIDE: // 17
side = GetBattlerSide(battler);
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerSide(i) == side && gBattleMons[i].ability == ability)
{
gLastUsedAbility = ability;
effect++;
}
}
break;
case ABILITYEFFECT_COUNT_ON_FIELD: // 18
for (i = 0; i < gBattlersCount; i++)
{
if (gBattleMons[i].ability == ability && i != battler)
{
gLastUsedAbility = ability;
effect++;
}
}
break;
}
if (effect && caseID < ABILITYEFFECT_CHECK_OTHER_SIDE && gLastUsedAbility != 0xFF)
if (effect && gLastUsedAbility != 0xFF)
RecordAbilityBattle(battler, gLastUsedAbility);
if (effect && caseID <= ABILITYEFFECT_MOVE_END)
gBattlerAbility = battler;
@ -3644,6 +3570,64 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
return effect;
}
u32 GetBattlerAbility(u8 battlerId)
{
if (gStatuses3[battlerId] & STATUS3_GASTRO_ACID)
return ABILITY_NONE;
else if ((gBattleMons[gBattlerAttacker].ability == ABILITY_MOLD_BREAKER
|| gBattleMons[gBattlerAttacker].ability == ABILITY_TERAVOLT
|| gBattleMons[gBattlerAttacker].ability == ABILITY_TURBOBLAZE)
&& sAbilitiesAffectedByMoldBreaker[gBattleMons[battlerId].ability]
&& gBattlerByTurnOrder[gCurrentTurnActionNumber] == gBattlerAttacker
&& gActionsByTurnOrder[gBattlerByTurnOrder[gBattlerAttacker]] == B_ACTION_USE_MOVE
&& gCurrentTurnActionNumber < gBattlersCount
&& !(gStatuses3[gBattlerAttacker] & STATUS3_GASTRO_ACID))
return ABILITY_NONE;
else
return gBattleMons[battlerId].ability;
}
u32 IsAbilityOnSide(u32 battlerId, u32 ability)
{
if (IsBattlerAlive(battlerId) && GetBattlerAbility(battlerId) == ability)
return battlerId + 1;
else if (IsBattlerAlive(BATTLE_PARTNER(battlerId)) && GetBattlerAbility(BATTLE_PARTNER(battlerId)) == ability)
return BATTLE_PARTNER(battlerId) + 1;
else
return 0;
}
u32 IsAbilityOnOpposingSide(u32 battlerId, u32 ability)
{
return IsAbilityOnSide(BATTLE_OPPOSITE(battlerId), ability);
}
u32 IsAbilityOnField(u32 ability)
{
u32 i;
for (i = 0; i < gBattlersCount; i++)
{
if (IsBattlerAlive(i) && GetBattlerAbility(i) == ability)
return i + 1;
}
return 0;
}
u32 IsAbilityOnFieldExcept(u32 battlerId, u32 ability)
{
u32 i;
for (i = 0; i < gBattlersCount; i++)
{
if (i != battlerId && IsBattlerAlive(i) && GetBattlerAbility(i) == ability)
return i + 1;
}
return 0;
}
void BattleScriptExecute(const u8 *BS_ptr)
{
gBattlescriptCurrInstr = BS_ptr;
@ -4372,7 +4356,7 @@ u8 GetMoveTarget(u16 move, u8 setTarget)
targetBattler = Random() % gBattlersCount;
} while (targetBattler == gBattlerAttacker || side == GetBattlerSide(targetBattler) || gAbsentBattlerFlags & gBitTable[targetBattler]);
if (gBattleMoves[move].type == TYPE_ELECTRIC
&& AbilityBattleEffects(ABILITYEFFECT_COUNT_OTHER_SIDE, gBattlerAttacker, ABILITY_LIGHTNING_ROD, 0, 0)
&& IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_LIGHTNING_ROD)
&& gBattleMons[targetBattler].ability != ABILITY_LIGHTNING_ROD)
{
targetBattler ^= BIT_FLANK;
@ -4380,7 +4364,7 @@ u8 GetMoveTarget(u16 move, u8 setTarget)
gSpecialStatuses[targetBattler].lightningRodRedirected = 1;
}
else if (gBattleMoves[move].type == TYPE_WATER
&& AbilityBattleEffects(ABILITYEFFECT_COUNT_OTHER_SIDE, gBattlerAttacker, ABILITY_STORM_DRAIN, 0, 0)
&& IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_STORM_DRAIN)
&& gBattleMons[targetBattler].ability != ABILITY_STORM_DRAIN)
{
targetBattler ^= BIT_FLANK;
@ -4564,23 +4548,6 @@ u8 IsMonDisobedient(void)
}
}
u32 GetBattlerAbility(u8 battlerId)
{
if (gStatuses3[battlerId] & STATUS3_GASTRO_ACID)
return ABILITY_NONE;
else if ((gBattleMons[gBattlerAttacker].ability == ABILITY_MOLD_BREAKER
|| gBattleMons[gBattlerAttacker].ability == ABILITY_TERAVOLT
|| gBattleMons[gBattlerAttacker].ability == ABILITY_TURBOBLAZE)
&& sAbilitiesAffectedByMoldBreaker[gBattleMons[battlerId].ability]
&& gBattlerByTurnOrder[gCurrentTurnActionNumber] == gBattlerAttacker
&& gActionsByTurnOrder[gBattlerByTurnOrder[gBattlerAttacker]] == B_ACTION_USE_MOVE
&& gCurrentTurnActionNumber < gBattlersCount
&& !(gStatuses3[gBattlerAttacker] & STATUS3_GASTRO_ACID))
return ABILITY_NONE;
else
return gBattleMons[battlerId].ability;
}
u32 GetBattlerHoldEffect(u8 battlerId, bool32 checkNegating)
{
if (checkNegating)
@ -5052,10 +5019,10 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
}
// field abilities
if ((ABILITY_ON_FIELD(ABILITY_DARK_AURA) && moveType == TYPE_DARK)
|| (ABILITY_ON_FIELD(ABILITY_FAIRY_AURA) && moveType == TYPE_FAIRY))
if ((IsAbilityOnField(ABILITY_DARK_AURA) && moveType == TYPE_DARK)
|| (IsAbilityOnField(ABILITY_FAIRY_AURA) && moveType == TYPE_FAIRY))
{
if (ABILITY_ON_FIELD(ABILITY_AURA_BREAK))
if (IsAbilityOnField(ABILITY_AURA_BREAK))
MulModifier(&modifier, UQ_4_12(0.75));
else
MulModifier(&modifier, UQ_4_12(1.25));