mirror of
https://github.com/rh-hideout/pokeemerald-expansion
synced 2025-10-05 23:42:46 +02:00
Immunity abilities trigger on turn 0 (leads) (#7814)
This commit is contained in:
@@ -8285,6 +8285,13 @@ BattleScript_AbilityCuredStatus::
|
||||
updatestatusicon BS_SCRIPTING
|
||||
return
|
||||
|
||||
BattleScript_AbilityCuredStatusEnd3::
|
||||
call BattleScript_AbilityPopUp
|
||||
printstring STRINGID_PKMNSXCUREDITSYPROBLEM
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_SCRIPTING
|
||||
end3
|
||||
|
||||
BattleScript_BattlerShookOffTaunt::
|
||||
call BattleScript_AbilityPopUp
|
||||
printstring STRINGID_PKMNSHOOKOFFTHETAUNT
|
||||
|
@@ -202,6 +202,7 @@ extern const u8 BattleScript_AbilityStatusEffect[];
|
||||
extern const u8 BattleScript_SynchronizeActivates[];
|
||||
extern const u8 BattleScript_NoItemSteal[];
|
||||
extern const u8 BattleScript_AbilityCuredStatus[];
|
||||
extern const u8 BattleScript_AbilityCuredStatusEnd3[];
|
||||
extern const u8 BattleScript_IgnoresWhileAsleep[];
|
||||
extern const u8 BattleScript_IgnoresAndUsesRandomMove[];
|
||||
extern const u8 BattleScript_MoveUsedLoafingAround[];
|
||||
|
@@ -55,6 +55,7 @@ enum {
|
||||
ABILITYEFFECT_SWITCH_IN_WEATHER,
|
||||
ABILITYEFFECT_OPPORTUNIST,
|
||||
ABILITYEFFECT_SWITCH_IN_STATUSES,
|
||||
ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES,
|
||||
};
|
||||
|
||||
// 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);
|
||||
u32 GetIllusionMonPartyId(struct Pokemon *party, struct Pokemon *mon, struct Pokemon *partnerMon, u32 battler);
|
||||
bool32 SetIllusionMon(struct Pokemon *mon, u32 battler);
|
||||
u32 TryImmunityAbilityHealStatus(u32 battler, u32 caseID);
|
||||
bool32 ShouldGetStatBadgeBoost(u16 flagId, u32 battler);
|
||||
enum DamageCategory GetBattleMoveCategory(u32 move);
|
||||
void SetDynamicMoveCategory(u32 battlerAtk, u32 battlerDef, u32 move);
|
||||
|
@@ -3870,6 +3870,8 @@ static void TryDoEventsBeforeFirstTurn(void)
|
||||
return;
|
||||
if (TryClearIllusion(i, ABILITYEFFECT_ON_SWITCHIN))
|
||||
return;
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES, i, 0, 0, 0) != 0)
|
||||
return;
|
||||
}
|
||||
gBattleStruct->switchInBattlerCounter = 0;
|
||||
gBattleStruct->eventsBeforeFirstTurnState++;
|
||||
|
@@ -6121,9 +6121,12 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_STATUS_IMMUNITY_ABILITIES: // status immunities
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, 0, 0, 0, 0))
|
||||
effect = TRUE; // it loops through all battlers, so we increment after its done with all battlers
|
||||
else
|
||||
for (u16 battler = 0; battler < gBattlersCount; battler++)
|
||||
{
|
||||
if (AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, 0, 0, 0))
|
||||
effect = TRUE;
|
||||
}
|
||||
if(!effect)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_SYNCHRONIZE_ATTACKER: // attacker synchronize
|
||||
@@ -17250,6 +17253,7 @@ void BS_SwitchinAbilities(void)
|
||||
AbilityBattleEffects(ABILITYEFFECT_NEUTRALIZINGGAS, battler, 0, 0, 0);
|
||||
AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, battler, 0, 0, 0);
|
||||
AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, battler, 0, 0, 0);
|
||||
AbilityBattleEffects(ABILITYEFFECT_IMMUNITY, battler, 0, 0, 0);
|
||||
|
||||
if (gBattleWeather & B_WEATHER_ANY && HasWeatherEffect())
|
||||
AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, battler, 0, 0, 0);
|
||||
|
@@ -5092,94 +5092,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_IMMUNITY:
|
||||
for (battler = 0; battler < gBattlersCount; battler++)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
effect = TryImmunityAbilityHealStatus(battler, caseID);
|
||||
if (effect)
|
||||
return effect;
|
||||
break;
|
||||
case ABILITYEFFECT_ON_SWITCHIN_IMMUNITIES:
|
||||
effect = TryImmunityAbilityHealStatus(battler, caseID);
|
||||
break;
|
||||
case ABILITYEFFECT_SYNCHRONIZE:
|
||||
if (gLastUsedAbility == ABILITY_SYNCHRONIZE && gBattleStruct->synchronizeMoveEffect != MOVE_EFFECT_NONE)
|
||||
@@ -10404,6 +10322,110 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battler)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
PARAMETRIZE { ability = ABILITY_VITAL_SPIRIT; }
|
||||
PARAMETRIZE { ability = ABILITY_INSOMNIA; }
|
||||
|
||||
GIVEN {
|
||||
FLAG_SET(B_FLAG_SLEEP_CLAUSE);
|
||||
ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS);
|
||||
|
Reference in New Issue
Block a user