mirror of
https://github.com/rh-hideout/pokeemerald-expansion
synced 2025-10-06 02:12:52 +02:00
Immunity abilities trigger on turn 0 (leads) (#7814)
This commit is contained in:
@@ -8285,6 +8285,13 @@ BattleScript_AbilityCuredStatus::
|
|||||||
updatestatusicon BS_SCRIPTING
|
updatestatusicon BS_SCRIPTING
|
||||||
return
|
return
|
||||||
|
|
||||||
|
BattleScript_AbilityCuredStatusEnd3::
|
||||||
|
call BattleScript_AbilityPopUp
|
||||||
|
printstring STRINGID_PKMNSXCUREDITSYPROBLEM
|
||||||
|
waitmessage B_WAIT_TIME_LONG
|
||||||
|
updatestatusicon BS_SCRIPTING
|
||||||
|
end3
|
||||||
|
|
||||||
BattleScript_BattlerShookOffTaunt::
|
BattleScript_BattlerShookOffTaunt::
|
||||||
call BattleScript_AbilityPopUp
|
call BattleScript_AbilityPopUp
|
||||||
printstring STRINGID_PKMNSHOOKOFFTHETAUNT
|
printstring STRINGID_PKMNSHOOKOFFTHETAUNT
|
||||||
|
@@ -202,6 +202,7 @@ extern const u8 BattleScript_AbilityStatusEffect[];
|
|||||||
extern const u8 BattleScript_SynchronizeActivates[];
|
extern const u8 BattleScript_SynchronizeActivates[];
|
||||||
extern const u8 BattleScript_NoItemSteal[];
|
extern const u8 BattleScript_NoItemSteal[];
|
||||||
extern const u8 BattleScript_AbilityCuredStatus[];
|
extern const u8 BattleScript_AbilityCuredStatus[];
|
||||||
|
extern const u8 BattleScript_AbilityCuredStatusEnd3[];
|
||||||
extern const u8 BattleScript_IgnoresWhileAsleep[];
|
extern const u8 BattleScript_IgnoresWhileAsleep[];
|
||||||
extern const u8 BattleScript_IgnoresAndUsesRandomMove[];
|
extern const u8 BattleScript_IgnoresAndUsesRandomMove[];
|
||||||
extern const u8 BattleScript_MoveUsedLoafingAround[];
|
extern const u8 BattleScript_MoveUsedLoafingAround[];
|
||||||
|
@@ -55,6 +55,7 @@ enum {
|
|||||||
ABILITYEFFECT_SWITCH_IN_WEATHER,
|
ABILITYEFFECT_SWITCH_IN_WEATHER,
|
||||||
ABILITYEFFECT_OPPORTUNIST,
|
ABILITYEFFECT_OPPORTUNIST,
|
||||||
ABILITYEFFECT_SWITCH_IN_STATUSES,
|
ABILITYEFFECT_SWITCH_IN_STATUSES,
|
||||||
|
ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES,
|
||||||
};
|
};
|
||||||
|
|
||||||
// For the first argument of ItemBattleEffects, to deteremine which block of item effects to try
|
// For the first argument of ItemBattleEffects, to deteremine which block of item effects to try
|
||||||
@@ -307,6 +308,7 @@ struct Pokemon *GetIllusionMonPtr(u32 battler);
|
|||||||
void ClearIllusionMon(u32 battler);
|
void ClearIllusionMon(u32 battler);
|
||||||
u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler);
|
u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler);
|
||||||
bool32 SetIllusionMon(struct Pokemon *mon, u32 battler);
|
bool32 SetIllusionMon(struct Pokemon *mon, u32 battler);
|
||||||
|
u32 TryImmunityAbilityHealStatus(u32 battler, u32 caseID);
|
||||||
bool32 ShouldGetStatBadgeBoost(u16 flagId, u32 battler);
|
bool32 ShouldGetStatBadgeBoost(u16 flagId, u32 battler);
|
||||||
enum DamageCategory GetBattleMoveCategory(u32 move);
|
enum DamageCategory GetBattleMoveCategory(u32 move);
|
||||||
void SetDynamicMoveCategory(u32 battlerAtk, u32 battlerDef, u32 move);
|
void SetDynamicMoveCategory(u32 battlerAtk, u32 battlerDef, u32 move);
|
||||||
|
@@ -3870,6 +3870,8 @@ static void TryDoEventsBeforeFirstTurn(void)
|
|||||||
return;
|
return;
|
||||||
if (TryClearIllusion(i, ABILITYEFFECT_ON_SWITCHIN))
|
if (TryClearIllusion(i, ABILITYEFFECT_ON_SWITCHIN))
|
||||||
return;
|
return;
|
||||||
|
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES, i, 0, 0, 0) != 0)
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
gBattleStruct->switchInBattlerCounter = 0;
|
gBattleStruct->switchInBattlerCounter = 0;
|
||||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||||
|
@@ -6121,9 +6121,12 @@ static void Cmd_moveend(void)
|
|||||||
gBattleScripting.moveendState++;
|
gBattleScripting.moveendState++;
|
||||||
break;
|
break;
|
||||||
case MOVEEND_STATUS_IMMUNITY_ABILITIES: // status immunities
|
case MOVEEND_STATUS_IMMUNITY_ABILITIES: // status immunities
|
||||||
if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, 0, 0, 0, 0))
|
for (u16 battler = 0; battler < gBattlersCount; battler++)
|
||||||
effect = TRUE; // it loops through all battlers, so we increment after its done with all battlers
|
{
|
||||||
else
|
if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, 0, 0, 0))
|
||||||
|
effect = TRUE;
|
||||||
|
}
|
||||||
|
if(!effect)
|
||||||
gBattleScripting.moveendState++;
|
gBattleScripting.moveendState++;
|
||||||
break;
|
break;
|
||||||
case MOVEEND_SYNCHRONIZE_ATTACKER: // attacker synchronize
|
case MOVEEND_SYNCHRONIZE_ATTACKER: // attacker synchronize
|
||||||
@@ -17250,6 +17253,7 @@ void BS_SwitchinAbilities(void)
|
|||||||
AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0);
|
AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0);
|
||||||
AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0);
|
AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0);
|
||||||
AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0);
|
AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0);
|
||||||
|
AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, 0, 0, 0);
|
||||||
|
|
||||||
if (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect())
|
if (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect())
|
||||||
AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0);
|
AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0);
|
||||||
|
@@ -5092,94 +5092,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ABILITYEFFECT_IMMUNITY:
|
case ABILITYEFFECT_IMMUNITY:
|
||||||
for (battler = 0; battler < gBattlersCount; battler++)
|
effect = TryImmunityAbilityHealStatus(battler, caseID);
|
||||||
{
|
if (effect)
|
||||||
switch (GetBattlerAbilityIgnoreMoldBreaker(battler))
|
return effect;
|
||||||
{
|
break;
|
||||||
case ABILITY_IMMUNITY:
|
case ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES:
|
||||||
case ABILITY_PASTEL_VEIL:
|
effect = TryImmunityAbilityHealStatus(battler, caseID);
|
||||||
if (gBattleMons[battler].status1 & (STATUS1_POISON | STATUS1_TOXIC_POISON | STATUS1_TOXIC_COUNTER))
|
|
||||||
{
|
|
||||||
StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
|
|
||||||
effect = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ABILITY_OWN_TEMPO:
|
|
||||||
if (gBattleMons[battler].volatiles.confusionTurns > 0)
|
|
||||||
{
|
|
||||||
StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn);
|
|
||||||
effect = 2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ABILITY_LIMBER:
|
|
||||||
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS)
|
|
||||||
{
|
|
||||||
StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
|
|
||||||
effect = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ABILITY_INSOMNIA:
|
|
||||||
case ABILITY_VITAL_SPIRIT:
|
|
||||||
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
|
|
||||||
{
|
|
||||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
|
||||||
gBattleMons[battler].volatiles.nightmare = FALSE;
|
|
||||||
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
|
|
||||||
effect = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ABILITY_WATER_VEIL:
|
|
||||||
case ABILITY_WATER_BUBBLE:
|
|
||||||
case ABILITY_THERMAL_EXCHANGE:
|
|
||||||
if (gBattleMons[battler].status1 & STATUS1_BURN)
|
|
||||||
{
|
|
||||||
StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn);
|
|
||||||
effect = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ABILITY_MAGMA_ARMOR:
|
|
||||||
if (gBattleMons[battler].status1 & (STATUS1_FREEZE | STATUS1_FROSTBITE))
|
|
||||||
{
|
|
||||||
StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn);
|
|
||||||
effect = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ABILITY_OBLIVIOUS:
|
|
||||||
if (gBattleMons[battler].volatiles.infatuation)
|
|
||||||
effect = 3;
|
|
||||||
else if (gDisableStructs[battler].tauntTimer != 0)
|
|
||||||
effect = 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (effect != 0)
|
|
||||||
{
|
|
||||||
switch (effect)
|
|
||||||
{
|
|
||||||
case 1: // status cleared
|
|
||||||
gBattleMons[battler].status1 = 0;
|
|
||||||
BattleScriptCall(BattleScript_AbilityCuredStatus);
|
|
||||||
break;
|
|
||||||
case 2: // get rid of confusion
|
|
||||||
RemoveConfusionStatus(battler);
|
|
||||||
BattleScriptCall(BattleScript_AbilityCuredStatus);
|
|
||||||
break;
|
|
||||||
case 3: // get rid of infatuation
|
|
||||||
gBattleMons[battler].volatiles.infatuation = 0;
|
|
||||||
BattleScriptCall(BattleScript_BattlerGotOverItsInfatuation);
|
|
||||||
break;
|
|
||||||
case 4: // get rid of taunt
|
|
||||||
gDisableStructs[battler].tauntTimer = 0;
|
|
||||||
BattleScriptCall(BattleScript_BattlerShookOffTaunt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gBattleScripting.battler = gBattlerAbility = battler;
|
|
||||||
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
|
|
||||||
MarkBattlerForControllerExec(battler);
|
|
||||||
return effect;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ABILITYEFFECT_SYNCHRONIZE:
|
case ABILITYEFFECT_SYNCHRONIZE:
|
||||||
if (gLastUsedAbility == ABILITY_SYNCHRONIZE && gBattleStruct->synchronizeMoveEffect != MOVE_EFFECT_NONE)
|
if (gLastUsedAbility == ABILITY_SYNCHRONIZE && gBattleStruct->synchronizeMoveEffect != MOVE_EFFECT_NONE)
|
||||||
@@ -10404,6 +10322,110 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battler)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 TryImmunityAbilityHealStatus(u32 battler, u32 caseID)
|
||||||
|
{
|
||||||
|
u32 effect = 0;
|
||||||
|
switch (GetBattlerAbilityIgnoreMoldBreaker(battler))
|
||||||
|
{
|
||||||
|
case ABILITY_IMMUNITY:
|
||||||
|
case ABILITY_PASTEL_VEIL:
|
||||||
|
if (gBattleMons[battler].status1 & (STATUS1_POISON | STATUS1_TOXIC_POISON | STATUS1_TOXIC_COUNTER))
|
||||||
|
{
|
||||||
|
StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
|
||||||
|
effect = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ABILITY_OWN_TEMPO:
|
||||||
|
if (gBattleMons[battler].volatiles.confusionTurns > 0)
|
||||||
|
{
|
||||||
|
StringCopy(gBattleTextBuff1, gStatusConditionString_ConfusionJpn);
|
||||||
|
effect = 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ABILITY_LIMBER:
|
||||||
|
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS)
|
||||||
|
{
|
||||||
|
StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
|
||||||
|
effect = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ABILITY_INSOMNIA:
|
||||||
|
case ABILITY_VITAL_SPIRIT:
|
||||||
|
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
|
||||||
|
{
|
||||||
|
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||||
|
gBattleMons[battler].volatiles.nightmare = FALSE;
|
||||||
|
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
|
||||||
|
effect = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ABILITY_WATER_VEIL:
|
||||||
|
case ABILITY_WATER_BUBBLE:
|
||||||
|
case ABILITY_THERMAL_EXCHANGE:
|
||||||
|
if (gBattleMons[battler].status1 & STATUS1_BURN)
|
||||||
|
{
|
||||||
|
StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn);
|
||||||
|
effect = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ABILITY_MAGMA_ARMOR:
|
||||||
|
if (gBattleMons[battler].status1 & (STATUS1_FREEZE | STATUS1_FROSTBITE))
|
||||||
|
{
|
||||||
|
StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn);
|
||||||
|
effect = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ABILITY_OBLIVIOUS:
|
||||||
|
if (gBattleMons[battler].volatiles.infatuation)
|
||||||
|
effect = 3;
|
||||||
|
else if (gDisableStructs[battler].tauntTimer != 0)
|
||||||
|
effect = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effect != 0)
|
||||||
|
{
|
||||||
|
switch (effect)
|
||||||
|
{
|
||||||
|
case 1: // status cleared
|
||||||
|
gBattleMons[battler].status1 = 0;
|
||||||
|
if(caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES)
|
||||||
|
BattleScriptExecute(BattleScript_AbilityCuredStatusEnd3);
|
||||||
|
else
|
||||||
|
BattleScriptCall(BattleScript_AbilityCuredStatus);
|
||||||
|
break;
|
||||||
|
case 2: // get rid of confusion
|
||||||
|
RemoveConfusionStatus(battler);
|
||||||
|
if(caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES)
|
||||||
|
BattleScriptExecute(BattleScript_AbilityCuredStatusEnd3);
|
||||||
|
else
|
||||||
|
BattleScriptCall(BattleScript_AbilityCuredStatus);
|
||||||
|
break;
|
||||||
|
case 3: // get rid of infatuation
|
||||||
|
gBattleMons[battler].volatiles.infatuation = 0;
|
||||||
|
if(caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES)
|
||||||
|
BattleScriptExecute(BattleScript_AbilityCuredStatusEnd3);
|
||||||
|
else
|
||||||
|
BattleScriptCall(BattleScript_AbilityCuredStatus);
|
||||||
|
break;
|
||||||
|
case 4: // get rid of taunt
|
||||||
|
gDisableStructs[battler].tauntTimer = 0;
|
||||||
|
if(caseID == ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES)
|
||||||
|
BattleScriptExecute(BattleScript_AbilityCuredStatusEnd3);
|
||||||
|
else
|
||||||
|
BattleScriptCall(BattleScript_AbilityCuredStatus);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gBattleScripting.battler = gBattlerAbility = battler;
|
||||||
|
BtlController_EmitSetMonData(battler, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
|
||||||
|
MarkBattlerForControllerExec(battler);
|
||||||
|
return effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool32 ShouldGetStatBadgeBoost(u16 badgeFlag, u32 battler)
|
bool32 ShouldGetStatBadgeBoost(u16 badgeFlag, u32 battler)
|
||||||
{
|
{
|
||||||
if (B_BADGE_BOOST == GEN_3 && badgeFlag != 0)
|
if (B_BADGE_BOOST == GEN_3 && badgeFlag != 0)
|
||||||
|
@@ -63,3 +63,19 @@ SINGLE_BATTLE_TEST("Immunity doesn't prevent Pokémon from being poisoned by Tox
|
|||||||
NOT HP_BAR(player);
|
NOT HP_BAR(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Immunity cures existing poison on turn 0")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_ZANGOOSE) {
|
||||||
|
Ability(ABILITY_IMMUNITY);
|
||||||
|
Status1(STATUS1_POISON);
|
||||||
|
}
|
||||||
|
OPPONENT(SPECIES_WOBBUFFET);
|
||||||
|
} SCENE {
|
||||||
|
ABILITY_POPUP(player, ABILITY_IMMUNITY);
|
||||||
|
TURN { MOVE(player, MOVE_SPLASH); }
|
||||||
|
} THEN {
|
||||||
|
EXPECT_EQ(player->status1, STATUS1_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1075,6 +1075,7 @@ SINGLE_BATTLE_TEST("Sleep Clause: Sleep clause is deactivated when a sleeping mo
|
|||||||
u32 ability;
|
u32 ability;
|
||||||
PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; }
|
PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; }
|
||||||
PARAMETRIZE { ability = ABILITY_INSOMNIA; }
|
PARAMETRIZE { ability = ABILITY_INSOMNIA; }
|
||||||
|
|
||||||
GIVEN {
|
GIVEN {
|
||||||
FLAG_SET(B_FLAG_SLEEP_CLAUSE);
|
FLAG_SET(B_FLAG_SLEEP_CLAUSE);
|
||||||
ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS);
|
ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS);
|
||||||
|
Reference in New Issue
Block a user