Merge pull request #1358 from ghoulslash/misty_terrain

Electric and Misty Terrain Effects
This commit is contained in:
ultima-soul 2021-09-16 19:09:39 -07:00 committed by GitHub
commit 58356fdcd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 230 additions and 93 deletions

View File

@ -1791,6 +1791,12 @@
.4byte \ptr
.endm
.macro jumpifterrainaffected battler:req, terrainFlags:req, ptr:req
various \battler, VARIOUS_JUMP_IF_TERRAIN_AFFECTED
.4byte \terrainFlags
.4byte \ptr
.endm
@ helpful macros
.macro setstatchanger stat:req, stages:req, down:req
setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7

View File

@ -2123,6 +2123,8 @@ BattleScript_EffectSleep::
jumpifleafguard BattleScript_LeafGuardProtects
jumpifshieldsdown BS_TARGET, BattleScript_LeafGuardProtects
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
jumpifterrainaffected BS_TARGET, STATUS_FIELD_ELECTRIC_TERRAIN, BattleScript_ElectricTerrainPrevents
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
jumpifsafeguard BattleScript_SafeguardProtected
attackanimation
@ -2130,6 +2132,26 @@ BattleScript_EffectSleep::
setmoveeffect MOVE_EFFECT_SLEEP
seteffectprimary
goto BattleScript_MoveEnd
BattleScript_TerrainPreventsEnd2::
pause B_WAIT_TIME_SHORT
printfromtable gTerrainPreventsStringIds
waitmessage B_WAIT_TIME_LONG
end2
BattleScript_ElectricTerrainPrevents::
pause B_WAIT_TIME_SHORT
printstring STRINGID_ELECTRICTERRAINPREVENTS
waitmessage B_WAIT_TIME_LONG
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
goto BattleScript_MoveEnd
BattleScript_MistyTerrainPrevents::
pause B_WAIT_TIME_SHORT
printstring STRINGID_MISTYTERRAINPREVENTS
waitmessage B_WAIT_TIME_LONG
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
goto BattleScript_MoveEnd
BattleScript_FlowerVeilProtectsRet::
pause B_WAIT_TIME_SHORT
@ -2645,6 +2667,7 @@ BattleScript_EffectToxic::
jumpifsubstituteblocks BattleScript_ButItFailed
jumpifstatus BS_TARGET, STATUS1_POISON | STATUS1_TOXIC_POISON, BattleScript_AlreadyPoisoned
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
trypoisontype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
jumpifsafeguard BattleScript_SafeguardProtected
@ -2869,6 +2892,7 @@ BattleScript_EffectConfuse:
jumpifability BS_TARGET, ABILITY_OWN_TEMPO, BattleScript_OwnTempoPrevents
jumpifsubstituteblocks BattleScript_ButItFailed
jumpifstatus2 BS_TARGET, STATUS2_CONFUSION, BattleScript_AlreadyConfused
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
jumpifsafeguard BattleScript_SafeguardProtected
attackanimation
@ -2987,6 +3011,7 @@ BattleScript_EffectPoison::
jumpifstatus BS_TARGET, STATUS1_TOXIC_POISON, BattleScript_AlreadyPoisoned
trypoisontype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
jumpifsafeguard BattleScript_SafeguardProtected
attackanimation
@ -3012,6 +3037,7 @@ BattleScript_EffectParalyze:
jumpifstatus BS_TARGET, STATUS1_PARALYSIS, BattleScript_AlreadyParalyzed
tryparalyzetype BS_ATTACKER, BS_TARGET, BattleScript_NotAffected
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
jumpifsafeguard BattleScript_SafeguardProtected
bichalfword gMoveResultFlags, MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE
@ -4316,6 +4342,7 @@ BattleScript_EffectWillOWisp::
jumpifleafguard BattleScript_LeafGuardProtects
jumpifshieldsdown BS_TARGET, BattleScript_LeafGuardProtects
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
jumpifsafeguard BattleScript_SafeguardProtected
attackanimation

View File

@ -119,10 +119,10 @@ bool32 IsUngroundingEffect(u16 effect);
bool32 IsSemiInvulnerable(u8 battlerDef, u16 move);
// status checks
bool32 CanBeBurned(u8 battler, u16 ability);
bool32 CanBePoisoned(u8 battler, u16 ability);
bool32 CanBeConfused(u8 battler, u16 ability);
bool32 CanSleep(u8 battler, u16 ability);
bool32 AI_CanBeBurned(u8 battler, u16 ability);
bool32 AI_CanBePoisoned(u8 battler, u16 ability);
bool32 AI_CanBeConfused(u8 battler, u16 ability);
bool32 AI_CanSleep(u8 battler, u16 ability);
bool32 IsBattlerIncapacitated(u8 battler, u16 ability);
bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove);
bool32 ShouldPoisonSelf(u8 battler, u16 ability);

View File

@ -381,5 +381,8 @@ extern const u8 BattleScript_EjectPackActivate_End2[];
extern const u8 BattleScript_EjectPackActivates[];
extern const u8 BattleScript_MentalHerbCureRet[];
extern const u8 BattleScript_MentalHerbCureEnd2[];
extern const u8 BattleScript_TerrainPreventsEnd2[];
extern const u8 BattleScript_MistyTerrainPrevents[];
extern const u8 BattleScript_ElectricTerrainPrevents[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@ -161,4 +161,12 @@ bool32 IsGastroAcidBannedAbility(u16 ability);
bool32 IsEntrainmentBannedAbilityAttacker(u16 ability);
bool32 IsEntrainmentTargetOrSimpleBeamBannedAbility(u16 ability);
bool32 CanSleep(u8 battlerId);
bool32 CanBePoisoned(u8 battlerId);
bool32 CanBeBurned(u8 battlerId);
bool32 CanBeParalyzed(u8 battlerId);
bool32 CanBeFrozen(u8 battlerId);
bool32 CanBeConfused(u8 battlerId);
bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag);
#endif // GUARD_BATTLE_UTIL_H

View File

@ -178,6 +178,7 @@
#define VARIOUS_TERRAIN_SEED 106
#define VARIOUS_MAKE_INVISIBLE 107
#define VARIOUS_ROOM_SERVICE 108
#define VARIOUS_JUMP_IF_TERRAIN_AFFECTED 109
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View File

@ -823,4 +823,9 @@
#define B_MSG_MENTALHERBCURE_HEALBLOCK 4
#define B_MSG_MENTALHERBCURE_DISABLE 5
// gTerrainPreventsStringIds
#define B_MSG_TERRAINPREVENTS_MISTY 0
#define B_MSG_TERRAINPREVENTS_ELECTRIC 1
#define B_MSG_TERRAINPREVENTS_PSYCHIC 2
#endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H

View File

@ -1570,7 +1570,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 10;
break;
case EFFECT_REST:
if (!CanSleep(battlerAtk, AI_DATA->atkAbility))
if (!AI_CanSleep(battlerAtk, AI_DATA->atkAbility))
score -= 10;
//fallthrough
case EFFECT_RESTORE_HP:
@ -2686,7 +2686,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_SWAGGER:
if (gBattleMons[battlerAtkPartner].statStages[STAT_ATK] < MAX_STAT_STAGE
&& HasMoveWithSplit(battlerAtkPartner, SPLIT_PHYSICAL)
&& (!CanBeConfused(battlerAtkPartner, TRUE)
&& (!AI_CanBeConfused(battlerAtkPartner, TRUE)
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_CONFUSION
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_STATUS))
{
@ -2696,7 +2696,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_FLATTER:
if (gBattleMons[battlerAtkPartner].statStages[STAT_SPATK] < MAX_STAT_STAGE
&& HasMoveWithSplit(battlerAtkPartner, SPLIT_SPECIAL)
&& (!CanBeConfused(battlerAtkPartner, TRUE)
&& (!AI_CanBeConfused(battlerAtkPartner, TRUE)
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_CONFUSION
|| atkPartnerHoldEffect == HOLD_EFFECT_CURE_STATUS))
{
@ -3248,7 +3248,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
}
break;
case EFFECT_REST:
if (!(CanSleep(battlerAtk, AI_DATA->atkAbility)))
if (!(AI_CanSleep(battlerAtk, AI_DATA->atkAbility)))
{
break;
}
@ -3937,11 +3937,11 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score += 2;
break;
case HOLD_EFFECT_TOXIC_ORB:
if (!ShouldPoisonSelf(battlerAtk, AI_DATA->atkAbility) && CanBePoisoned(battlerDef, AI_DATA->defAbility))
if (!ShouldPoisonSelf(battlerAtk, AI_DATA->atkAbility) && AI_CanBePoisoned(battlerDef, AI_DATA->defAbility))
score += 2;
break;
case HOLD_EFFECT_FLAME_ORB:
if (!ShouldBurnSelf(battlerAtk, AI_DATA->atkAbility) && CanBeBurned(battlerAtk, AI_DATA->defAbility))
if (!ShouldBurnSelf(battlerAtk, AI_DATA->atkAbility) && AI_CanBeBurned(battlerAtk, AI_DATA->defAbility))
score += 2;
break;
case HOLD_EFFECT_BLACK_SLUDGE:

View File

@ -2589,7 +2589,7 @@ bool32 IsBattlerIncapacitated(u8 battler, u16 ability)
return FALSE;
}
bool32 CanSleep(u8 battler, u16 ability)
bool32 AI_CanSleep(u8 battler, u16 ability)
{
if (ability == ABILITY_INSOMNIA
|| ability == ABILITY_VITAL_SPIRIT
@ -2603,7 +2603,7 @@ bool32 CanSleep(u8 battler, u16 ability)
bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{
if (!CanSleep(battlerDef, defAbility)
if (!AI_CanSleep(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) // shouldn't try to sleep mon that partner is trying to make sleep
@ -2611,7 +2611,7 @@ bool32 AI_CanPutToSleep(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move,
return TRUE;
}
bool32 CanBePoisoned(u8 battler, u16 ability)
bool32 AI_CanBePoisoned(u8 battler, u16 ability)
{
if (ability == ABILITY_IMMUNITY
|| ability == ABILITY_PASTEL_VEIL
@ -2624,7 +2624,7 @@ bool32 CanBePoisoned(u8 battler, u16 ability)
bool32 ShouldPoisonSelf(u8 battler, u16 ability)
{
if (CanBePoisoned(battler, ability) && (
if (AI_CanBePoisoned(battler, ability) && (
ability == ABILITY_MARVEL_SCALE
|| ability == ABILITY_POISON_HEAL
|| ability == ABILITY_QUICK_FEET
@ -2639,7 +2639,7 @@ bool32 ShouldPoisonSelf(u8 battler, u16 ability)
bool32 AI_CanPoison(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u16 partnerMove)
{
if (!CanBePoisoned(battlerDef, defAbility)
if (!AI_CanBePoisoned(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove))
@ -2673,7 +2673,7 @@ bool32 AI_CanParalyze(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u1
return TRUE;
}
bool32 CanBeConfused(u8 battler, u16 ability)
bool32 AI_CanBeConfused(u8 battler, u16 ability)
{
if ((gBattleMons[battler].status2 & STATUS2_CONFUSION)
|| (ability == ABILITY_OWN_TEMPO)
@ -2684,7 +2684,7 @@ bool32 CanBeConfused(u8 battler, u16 ability)
bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove)
{
if (!CanBeConfused(battlerDef, defAbility)
if (!AI_CanBeConfused(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_SAFEGUARD
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
@ -2696,7 +2696,7 @@ bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtk
return TRUE;
}
bool32 CanBeBurned(u8 battler, u16 ability)
bool32 AI_CanBeBurned(u8 battler, u16 ability)
{
if (ability == ABILITY_WATER_VEIL
|| ability == ABILITY_WATER_BUBBLE
@ -2710,7 +2710,7 @@ bool32 CanBeBurned(u8 battler, u16 ability)
bool32 ShouldBurnSelf(u8 battler, u16 ability)
{
if (CanBeBurned(battler, ability) && (
if (AI_CanBeBurned(battler, ability) && (
ability == ABILITY_QUICK_FEET
|| ability == ABILITY_HEATPROOF
|| ability == ABILITY_MAGIC_GUARD
@ -2724,7 +2724,7 @@ bool32 ShouldBurnSelf(u8 battler, u16 ability)
bool32 AI_CanBurn(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtkPartner, u16 move, u16 partnerMove)
{
if (!CanBeBurned(battlerDef, defAbility)
if (!AI_CanBeBurned(battlerDef, defAbility)
|| AI_GetMoveEffectiveness(move, battlerAtk, battlerDef) == AI_EFFECTIVENESS_x0
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| PartnerMoveEffectIsStatusSameTarget(battlerAtkPartner, battlerDef, partnerMove))

View File

@ -1292,7 +1292,9 @@ const u16 gTerrainStringIds[] =
const u16 gTerrainPreventsStringIds[] =
{
STRINGID_MISTYTERRAINPREVENTS, STRINGID_ELECTRICTERRAINPREVENTS, STRINGID_PSYCHICTERRAINPREVENTS
[B_MSG_TERRAINPREVENTS_MISTY] = STRINGID_MISTYTERRAINPREVENTS,
[B_MSG_TERRAINPREVENTS_ELECTRIC] = STRINGID_ELECTRICTERRAINPREVENTS,
[B_MSG_TERRAINPREVENTS_PSYCHIC] = STRINGID_PSYCHICTERRAINPREVENTS
};
const u16 gMagicCoatBounceStringIds[] =

View File

@ -2502,8 +2502,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
{
s32 i, byTwo, affectsUser = 0;
bool32 statusChanged = FALSE;
bool32 noSunCanFreeze = TRUE;
switch (gBattleScripting.moveEffect) // Set move effects which happen later on
{
case MOVE_EFFECT_KNOCK_OFF:
@ -2562,15 +2561,9 @@ void SetMoveEffect(bool32 primary, u32 certain)
else
gActiveBattler = gBattlersCount;
if (gBattleMons[gEffectBattler].status1)
break;
if (gActiveBattler != gBattlersCount)
break;
if (GetBattlerAbility(gEffectBattler) == ABILITY_VITAL_SPIRIT
|| GetBattlerAbility(gEffectBattler) == ABILITY_INSOMNIA
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|| IsAbilityOnSide(gEffectBattler, ABILITY_SWEET_VEIL)
|| IsAbilityStatusProtected(gEffectBattler))
if (!CanSleep(gEffectBattler))
break;
CancelMultiTurnMoves(gEffectBattler);
@ -2609,11 +2602,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
}
if (!CanPoisonType(gBattleScripting.battler, gEffectBattler))
break;
if (gBattleMons[gEffectBattler].status1)
break;
if (GetBattlerAbility(gEffectBattler) == ABILITY_IMMUNITY
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|| IsAbilityStatusProtected(gEffectBattler))
if (!CanBePoisoned(gEffectBattler))
break;
statusChanged = TRUE;
@ -2648,30 +2637,14 @@ void SetMoveEffect(bool32 primary, u32 certain)
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STATUS_HAD_NO_EFFECT;
RESET_RETURN
}
if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_FIRE))
break;
if (GetBattlerAbility(gEffectBattler) == ABILITY_WATER_VEIL
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|| GetBattlerAbility(gEffectBattler) == ABILITY_WATER_BUBBLE
|| IsAbilityStatusProtected(gEffectBattler))
break;
if (gBattleMons[gEffectBattler].status1)
if (!CanBeBurned(gEffectBattler))
break;
statusChanged = TRUE;
break;
case STATUS1_FREEZE:
if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY)
noSunCanFreeze = FALSE;
if (IS_BATTLER_OF_TYPE(gEffectBattler, TYPE_ICE))
break;
if (gBattleMons[gEffectBattler].status1)
break;
if (noSunCanFreeze == 0)
break;
if (GetBattlerAbility(gEffectBattler) == ABILITY_MAGMA_ARMOR
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|| IsAbilityStatusProtected(gEffectBattler))
if (!CanBeFrozen(gEffectBattler))
break;
CancelMultiTurnMoves(gEffectBattler);
@ -2714,11 +2687,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
}
if (!CanParalyzeType(gBattleScripting.battler, gEffectBattler))
break;
if (GetBattlerAbility(gEffectBattler) == ABILITY_LIMBER
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|| IsAbilityStatusProtected(gEffectBattler))
break;
if (gBattleMons[gEffectBattler].status1)
if (!CanBeParalyzed(gEffectBattler))
break;
statusChanged = TRUE;
@ -2757,9 +2726,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
break;
if (CanPoisonType(gBattleScripting.battler, gEffectBattler))
{
if (GetBattlerAbility(gEffectBattler) == ABILITY_IMMUNITY
|| GetBattlerAbility(gEffectBattler) == ABILITY_COMATOSE
|| IsAbilityStatusProtected(gEffectBattler))
if (!CanBePoisoned(gEffectBattler))
break;
// It's redundant, because at this point we know the status1 value is 0.
@ -2831,8 +2798,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
switch (gBattleScripting.moveEffect)
{
case MOVE_EFFECT_CONFUSION:
if (GetBattlerAbility(gEffectBattler) == ABILITY_OWN_TEMPO
|| gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION)
if (!CanBeConfused(gEffectBattler))
{
gBattlescriptCurrInstr++;
}
@ -6037,7 +6003,8 @@ static void Cmd_switchineffects(void)
if (!(gBattleMons[gActiveBattler].status1 & STATUS1_ANY)
&& !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL)
&& GetBattlerAbility(gActiveBattler) != ABILITY_IMMUNITY
&& !(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SAFEGUARD))
&& !(gSideStatuses[GetBattlerSide(gActiveBattler)] & SIDE_STATUS_SAFEGUARD)
&& !(gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN))
{
if (gSideTimers[GetBattlerSide(gActiveBattler)].toxicSpikesAmount >= 2)
gBattleMons[gActiveBattler].status1 |= STATUS1_TOXIC_POISON;
@ -8599,6 +8566,15 @@ static void Cmd_various(void)
BtlController_EmitSpriteInvisibility(0, TRUE);
MarkBattlerForControllerExec(gActiveBattler);
break;
case VARIOUS_JUMP_IF_TERRAIN_AFFECTED:
{
u32 flags = T1_READ_32(gBattlescriptCurrInstr + 3);
if (IsBattlerTerrainAffected(gActiveBattler, flags))
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 7);
else
gBattlescriptCurrInstr += 11;
}
return;
}
gBattlescriptCurrInstr += 3;
@ -8925,6 +8901,14 @@ static void Cmd_trysetrest(void)
{
gBattlescriptCurrInstr = failJump;
}
else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN))
{
gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents;
}
else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN))
{
gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents;
}
else
{
if (gBattleMons[gBattlerTarget].status1 & ((u8)(~STATUS1_SLEEP)))
@ -11602,6 +11586,18 @@ static void Cmd_setyawn(void)
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
}
else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_ELECTRIC_TERRAIN))
{
// When Yawn is used while Electric Terrain is set and drowsiness is set from Yawn being used against target in the previous turn:
// "But it failed" will display first.
gBattlescriptCurrInstr = BattleScript_ElectricTerrainPrevents;
}
else if (IsBattlerTerrainAffected(gBattlerTarget, STATUS_FIELD_MISTY_TERRAIN))
{
// When Yawn is used while Misty Terrain is set and drowsiness is set from Yawn being used against target in the previous turn:
// "But it failed" will display first.
gBattlescriptCurrInstr = BattleScript_MistyTerrainPrevents;
}
else
{
gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2);

View File

@ -2726,11 +2726,24 @@ u8 DoBattlerEndTurnEffects(void)
&& !IsLeafGuardProtected(gActiveBattler))
{
CancelMultiTurnMoves(gActiveBattler);
gBattleMons[gActiveBattler].status1 |= (Random() & 3) + 2;
BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1);
MarkBattlerForControllerExec(gActiveBattler);
gEffectBattler = gActiveBattler;
BattleScriptExecute(BattleScript_YawnMakesAsleep);
if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_ELECTRIC_TERRAIN))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_ELECTRIC;
BattleScriptExecute(BattleScript_TerrainPreventsEnd2);
}
else if (IsBattlerTerrainAffected(gActiveBattler, STATUS_FIELD_MISTY_TERRAIN))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_MISTY;
BattleScriptExecute(BattleScript_TerrainPreventsEnd2);
}
else
{
gBattleMons[gActiveBattler].status1 |= (Random() & 3) + 2;
BtlController_EmitSetMonData(0, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gActiveBattler].status1);
MarkBattlerForControllerExec(gActiveBattler);
BattleScriptExecute(BattleScript_YawnMakesAsleep);
}
effect++;
}
}
@ -4800,10 +4813,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
&& gBattleMons[gBattlerAttacker].hp != 0
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& TARGET_TURN_DAMAGED
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_INSOMNIA
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_VITAL_SPIRIT
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY)
&& !IsAbilityStatusProtected(gBattlerAttacker)
&& CanSleep(gBattlerAttacker)
&& IsMoveMakingContact(move, gBattlerAttacker)
&& (Random() % 3) == 0)
{
@ -4822,11 +4832,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
&& gBattleMons[gBattlerAttacker].hp != 0
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& TARGET_TURN_DAMAGED
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_POISON)
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_STEEL)
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_IMMUNITY
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY)
&& !IsAbilityStatusProtected(gBattlerAttacker)
&& CanBePoisoned(gBattlerAttacker)
&& IsMoveMakingContact(move, gBattlerAttacker)
&& (Random() % 3) == 0)
{
@ -4844,10 +4850,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
&& gBattleMons[gBattlerAttacker].hp != 0
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& TARGET_TURN_DAMAGED
&& CanParalyzeType(gBattlerTarget, gBattlerAttacker)
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_LIMBER
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY)
&& !IsAbilityStatusProtected(gBattlerAttacker)
&& CanBeParalyzed(gBattlerAttacker)
&& IsMoveMakingContact(move, gBattlerAttacker)
&& (Random() % 3) == 0)
{
@ -4864,11 +4867,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)
&& TARGET_TURN_DAMAGED
&& !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FIRE)
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_WATER_VEIL
&& GetBattlerAbility(gBattlerAttacker) != ABILITY_WATER_BUBBLE
&& !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY)
&& !IsAbilityStatusProtected(gBattlerAttacker)
&& CanBeBurned(gBattlerAttacker)
&& (Random() % 3) == 0)
{
gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_BURN;
@ -4976,11 +4975,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& gBattleMons[gBattlerTarget].hp != 0
&& !gProtectStructs[gBattlerTarget].confusionSelfDmg
&& !IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_POISON)
&& !IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_STEEL)
&& GetBattlerAbility(gBattlerTarget) != ABILITY_IMMUNITY
&& !(gBattleMons[gBattlerTarget].status1 & STATUS1_ANY)
&& !IsAbilityStatusProtected(gBattlerTarget)
&& CanBePoisoned(gBattlerTarget)
&& IsMoveMakingContact(move, gBattlerAttacker)
&& (Random() % 3) == 0)
{
@ -5383,6 +5378,100 @@ enum
ITEM_STATS_CHANGE, // 5
};
bool32 IsBattlerTerrainAffected(u8 battlerId, u32 terrainFlag)
{
if (!(gFieldStatuses & terrainFlag))
return FALSE;
else if (gStatuses3[battlerId] & STATUS3_SEMI_INVULNERABLE)
return FALSE;
return IsBattlerGrounded(battlerId);
}
bool32 CanSleep(u8 battlerId)
{
u16 ability = GetBattlerAbility(battlerId);
if (ability == ABILITY_INSOMNIA
|| ability == ABILITY_VITAL_SPIRIT
|| ability == ABILITY_COMATOSE
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|| IsAbilityOnSide(battlerId, ABILITY_SWEET_VEIL)
|| IsAbilityStatusProtected(battlerId)
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
}
bool32 CanBePoisoned(u8 battlerId)
{
u16 ability = GetBattlerAbility(battlerId);
if (IS_BATTLER_OF_TYPE(battlerId, TYPE_POISON)
|| IS_BATTLER_OF_TYPE(battlerId, TYPE_STEEL)
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|| ability == ABILITY_IMMUNITY
|| ability == ABILITY_COMATOSE
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|| IsAbilityStatusProtected(battlerId)
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
}
bool32 CanBeBurned(u8 battlerId)
{
u16 ability = GetBattlerAbility(battlerId);
if (IS_BATTLER_OF_TYPE(battlerId, TYPE_FIRE)
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|| ability == ABILITY_WATER_VEIL
|| ability == ABILITY_WATER_BUBBLE
|| ability == ABILITY_COMATOSE
|| IsAbilityStatusProtected(battlerId)
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
}
bool32 CanBeParalyzed(u8 battlerId)
{
u16 ability = GetBattlerAbility(battlerId);
if ((B_PARALYZE_ELECTRIC >= GEN_6 && IS_BATTLER_OF_TYPE(battlerId, TYPE_ELECTRIC))
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD
|| ability == ABILITY_LIMBER
|| ability == ABILITY_COMATOSE
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|| IsAbilityStatusProtected(battlerId)
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
}
bool32 CanBeFrozen(u8 battlerId)
{
u16 ability = GetBattlerAbility(battlerId);
if (IS_BATTLER_OF_TYPE(battlerId, TYPE_ICE)
|| (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY)
|| gSideStatuses[GetBattlerSide(battlerId)] & SIDE_STATUS_SAFEGUARD
|| ability == ABILITY_MAGMA_ARMOR
|| ability == ABILITY_COMATOSE
|| gBattleMons[battlerId].status1 & STATUS1_ANY
|| IsAbilityStatusProtected(battlerId)
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
}
bool32 CanBeConfused(u8 battlerId)
{
if (GetBattlerAbility(gEffectBattler) == ABILITY_OWN_TEMPO
|| gBattleMons[gEffectBattler].status2 & STATUS2_CONFUSION
|| IsBattlerTerrainAffected(battlerId, STATUS_FIELD_MISTY_TERRAIN))
return FALSE;
return TRUE;
}
// second argument is 1/X of current hp compared to max hp
bool32 HasEnoughHpToEatBerry(u32 battlerId, u32 hpFraction, u32 itemId)
{
@ -6901,7 +6990,7 @@ u8 IsMonDisobedient(void)
obedienceLevel = gBattleMons[gBattlerAttacker].level - obedienceLevel;
calc = (Random() & 255);
if (calc < obedienceLevel && !(gBattleMons[gBattlerAttacker].status1 & STATUS1_ANY) && gBattleMons[gBattlerAttacker].ability != ABILITY_VITAL_SPIRIT && gBattleMons[gBattlerAttacker].ability != ABILITY_INSOMNIA)
if (calc < obedienceLevel && CanSleep(gBattlerAttacker))
{
// try putting asleep
int i;