Add B_FLAG_SLEEP_CLAUSE (#5566)
Co-authored-by: Isaac Rivera <isaacrivera2020@u.northwestern.edu> Co-authored-by: iriv24 <40581123+iriv24@users.noreply.github.com> Co-authored-by: Hedara <hedara90@gmail.com>
This commit is contained in:
parent
0322d51887
commit
2b7905beb1
@ -1667,6 +1667,11 @@
|
||||
callnative BS_DamageToQuarterTargetHP
|
||||
.endm
|
||||
|
||||
.macro jumpifsleepclause jumpInstr:req
|
||||
callnative BS_JumpIfSleepClause
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro ficklebeamdamagecalculation
|
||||
callnative BS_FickleBeamDamageCalculation
|
||||
.endm
|
||||
@ -2004,9 +2009,10 @@
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
|
||||
.macro trypsychoshift failInstr:req
|
||||
.macro trypsychoshift failInstr:req sleepClauseFailInstr:req
|
||||
various BS_ATTACKER, VARIOUS_PSYCHO_SHIFT
|
||||
.4byte \failInstr
|
||||
.4byte \sleepClauseFailInstr
|
||||
.endm
|
||||
|
||||
.macro curestatus battler:req
|
||||
|
||||
@ -1639,7 +1639,7 @@ BattleScript_EffectPsychoShift::
|
||||
BattleScript_EffectPsychoShiftCanWork:
|
||||
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
|
||||
jumpifsafeguard BattleScript_SafeguardProtected
|
||||
trypsychoshift BattleScript_ButItFailed
|
||||
trypsychoshift BattleScript_ButItFailed, BattleScript_SleepClauseBlocked
|
||||
attackanimation
|
||||
waitanimation
|
||||
copybyte gEffectBattler, gBattlerTarget
|
||||
@ -2892,6 +2892,7 @@ BattleScript_EffectSleep::
|
||||
jumpifleafguardprotected BS_TARGET, BattleScript_AbilityProtectsDoesntAffect
|
||||
jumpifshieldsdown BS_TARGET, BattleScript_AbilityProtectsDoesntAffect
|
||||
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
|
||||
jumpifsleepclause BattleScript_SleepClauseBlocked
|
||||
jumpifterrainaffected BS_TARGET, STATUS_FIELD_ELECTRIC_TERRAIN, BattleScript_ElectricTerrainPrevents
|
||||
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
|
||||
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
|
||||
@ -5154,6 +5155,7 @@ BattleScript_EffectYawn::
|
||||
jumpifflowerveil BattleScript_FlowerVeilProtects
|
||||
jumpifleafguardprotected BS_TARGET, BattleScript_AbilityProtectsDoesntAffect
|
||||
jumpifshieldsdown BS_TARGET, BattleScript_AbilityProtectsDoesntAffect
|
||||
jumpifsleepclause BattleScript_SleepClauseBlocked
|
||||
jumpifsubstituteblocks BattleScript_ButItFailed
|
||||
jumpifsafeguard BattleScript_SafeguardProtected
|
||||
accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON
|
||||
@ -10108,3 +10110,16 @@ BattleScript_EffectSnow::
|
||||
call BattleScript_CheckPrimalWeather
|
||||
setfieldweather ENUM_WEATHER_SNOW
|
||||
goto BattleScript_MoveWeatherChange
|
||||
|
||||
BattleScript_SleepClauseBlocked::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
|
||||
printstring STRINGID_BLOCKEDBYSLEEPCLAUSE
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_SleepClausePreventsEnd::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printstring STRINGID_BLOCKEDBYSLEEPCLAUSE
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
end2
|
||||
|
||||
@ -832,6 +832,8 @@ struct BattleStruct
|
||||
u8 padding:7;
|
||||
u8 usedEjectItem;
|
||||
u8 usedMicleBerry;
|
||||
u8 monCausingSleepClause[NUM_BATTLE_SIDES]; // Stores which pokemon on a given side is causing Sleep Clause to be active as the mon's index in the party
|
||||
u8 sleepClauseEffectExempt:4; // Stores whether effect should be exempt from triggering Sleep Clause (Effect Spore)
|
||||
};
|
||||
|
||||
// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,
|
||||
|
||||
@ -185,6 +185,7 @@ bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove);
|
||||
bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck);
|
||||
bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove);
|
||||
bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove);
|
||||
bool32 PartnerMoveActivatesSleepClause(u32 move);
|
||||
bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move);
|
||||
|
||||
// party logic
|
||||
|
||||
@ -520,6 +520,7 @@ extern const u8 BattleScript_Terastallization[];
|
||||
extern const u8 BattleScript_BoosterEnergyEnd2[];
|
||||
extern const u8 BattleScript_TeraShellDistortingTypeMatchups[];
|
||||
extern const u8 BattleScript_TeraFormChange[];
|
||||
extern const u8 BattleScript_SleepClausePreventsEnd[];
|
||||
|
||||
// zmoves
|
||||
extern const u8 BattleScript_ZMoveActivateDamaging[];
|
||||
|
||||
@ -291,7 +291,7 @@ bool32 MoveHasChargeTurnAdditionalEffect(u32 move);
|
||||
bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef);
|
||||
bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef);
|
||||
|
||||
bool32 CanBeSlept(u32 battler, u32 ability);
|
||||
bool32 CanBeSlept(u32 battler, u32 ability, u32 isBlockedBySleepClause);
|
||||
bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 defAbility);
|
||||
bool32 CanBeBurned(u32 battler, u32 ability);
|
||||
bool32 CanBeParalyzed(u32 battler, u32 ability);
|
||||
@ -314,5 +314,8 @@ bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon);
|
||||
bool8 IsMonBannedFromSkyBattles(u16 species);
|
||||
void RemoveBattlerType(u32 battler, u8 type);
|
||||
u32 GetMoveType(u32 move);
|
||||
void TryActivateSleepClause(u32 battler, u32 indexInParty);
|
||||
void TryDeactivateSleepClause(u32 battlerSide, u32 indexInParty);
|
||||
bool8 IsSleepClauseActiveForSide(u32 battlerSide);
|
||||
|
||||
#endif // GUARD_BATTLE_UTIL_H
|
||||
|
||||
@ -192,6 +192,7 @@
|
||||
#define B_FLAG_DYNAMAX_BATTLE 0 // If this flag is set, the ability to Dynamax in battle is enabled for all trainers.
|
||||
#define B_FLAG_TERA_ORB_CHARGED 0 // If this flag is set, the Tera Orb is charged. It is automatically set upon healing and cleared upon Terastallizing once configured.
|
||||
#define B_FLAG_TERA_ORB_NO_COST 0 // If this flag is set, the Tera Orb does not use up its charge upon Terastallization. In S/V, this occurs after an event with Terapagos.
|
||||
#define B_FLAG_SLEEP_CLAUSE 0 // If this flag is set, sleep clause is enabled; if the player / AI has already put a Pokémon on the opponent's side to sleep and it is still sleeping, another one can't be put to sleep. AI requires AI_FLAG_CHECK_BAD_MOVE to understand.
|
||||
|
||||
// Var Settings
|
||||
// To use the following features in scripting, replace the 0s with the var ID you're assigning it to.
|
||||
|
||||
@ -1129,4 +1129,8 @@
|
||||
#undef P_FAMILY_PECHARUNT
|
||||
#define P_FAMILY_PECHARUNT TRUE
|
||||
|
||||
// Flags
|
||||
#undef B_FLAG_SLEEP_CLAUSE
|
||||
#define B_FLAG_SLEEP_CLAUSE FLAG_SPECIAL_FLAG_UNUSED_0x4003
|
||||
|
||||
#endif // GUARD_CONFIG_TEST_H
|
||||
|
||||
@ -724,8 +724,9 @@
|
||||
#define STRINGID_ELECTRICCURRENTISRUNNING 722
|
||||
#define STRINGID_SEEMSWEIRD 723
|
||||
#define STRINGID_WAGGLINGAFINGER 724
|
||||
#define STRINGID_BLOCKEDBYSLEEPCLAUSE 725
|
||||
|
||||
#define BATTLESTRINGS_COUNT 725
|
||||
#define BATTLESTRINGS_COUNT 726
|
||||
|
||||
// This is the string id that gBattleStringsTable starts with.
|
||||
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
|
||||
|
||||
@ -982,6 +982,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
case EFFECT_SLEEP:
|
||||
if (!AI_CanPutToSleep(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, aiData->partnerMove))
|
||||
ADJUST_SCORE(-10);
|
||||
if (PartnerMoveActivatesSleepClause(aiData->partnerMove))
|
||||
ADJUST_SCORE(-20);
|
||||
break;
|
||||
case EFFECT_EXPLOSION:
|
||||
if (!(AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_WILL_SUICIDE))
|
||||
@ -1794,7 +1796,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_REST:
|
||||
if (!CanBeSlept(battlerAtk, aiData->abilities[battlerAtk]))
|
||||
if (!CanBeSlept(battlerAtk, aiData->abilities[battlerAtk], FALSE))
|
||||
ADJUST_SCORE(-10);
|
||||
//fallthrough
|
||||
case EFFECT_RESTORE_HP:
|
||||
@ -2077,6 +2079,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
ADJUST_SCORE(-10);
|
||||
else if (!AI_CanPutToSleep(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, aiData->partnerMove))
|
||||
ADJUST_SCORE(-10);
|
||||
if (PartnerMoveActivatesSleepClause(aiData->partnerMove))
|
||||
ADJUST_SCORE(-20);
|
||||
break;
|
||||
case EFFECT_SKILL_SWAP:
|
||||
if (aiData->abilities[battlerAtk] == ABILITY_NONE || aiData->abilities[battlerDef] == ABILITY_NONE
|
||||
@ -2676,7 +2680,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
if (IsMoveEffectWeather(move))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // check partner move effect
|
||||
|
||||
// Adjust for always crit moves
|
||||
@ -3454,7 +3458,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
}
|
||||
break;
|
||||
case EFFECT_REST:
|
||||
if (!(CanBeSlept(battlerAtk, aiData->abilities[battlerAtk])))
|
||||
if (!(CanBeSlept(battlerAtk, aiData->abilities[battlerAtk], FALSE)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
@ -502,7 +502,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler)
|
||||
{
|
||||
//Yawn
|
||||
if (gStatuses3[battler] & STATUS3_YAWN
|
||||
&& CanBeSlept(battler, monAbility)
|
||||
&& CanBeSlept(battler, monAbility, TRUE)
|
||||
&& gBattleMons[battler].hp > gBattleMons[battler].maxHP / 3)
|
||||
{
|
||||
switchMon = TRUE;
|
||||
|
||||
@ -2902,7 +2902,7 @@ bool32 IsBattlerIncapacitated(u32 battler, u32 ability)
|
||||
|
||||
bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove)
|
||||
{
|
||||
if (!CanBeSlept(battlerDef, defAbility)
|
||||
if (!CanBeSlept(battlerDef, defAbility, TRUE)
|
||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) // shouldn't try to sleep mon that partner is trying to make sleep
|
||||
return FALSE;
|
||||
@ -3392,6 +3392,17 @@ bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMov
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 PartnerMoveActivatesSleepClause(u32 partnerMove)
|
||||
{
|
||||
u32 effect = gMovesInfo[partnerMove].effect;
|
||||
if (!IsDoubleBattle() || !FlagGet(B_FLAG_SLEEP_CLAUSE))
|
||||
return FALSE;
|
||||
if (effect == EFFECT_SLEEP
|
||||
|| effect == EFFECT_YAWN)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
@ -759,7 +759,7 @@ void BS_SetMaxMoveEffect(void)
|
||||
{
|
||||
static const u8 sSnoozeEffects[] = {TRUE, FALSE};
|
||||
if (!(gStatuses3[gBattlerTarget] & STATUS3_YAWN)
|
||||
&& CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget))
|
||||
&& CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget), TRUE)
|
||||
&& RandomElement(RNG_G_MAX_SNOOZE, sSnoozeEffects)) // 50% chance of success
|
||||
{
|
||||
gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2);
|
||||
@ -881,12 +881,14 @@ void BS_TrySetStatus1(void)
|
||||
}
|
||||
break;
|
||||
case STATUS1_SLEEP:
|
||||
if (CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget)))
|
||||
if (CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget), TRUE))
|
||||
{
|
||||
if (B_SLEEP_TURNS >= GEN_5)
|
||||
gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 3) + 2);
|
||||
else
|
||||
gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 4) + 3);
|
||||
|
||||
TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]);
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
|
||||
effect++;
|
||||
}
|
||||
|
||||
@ -3121,6 +3121,13 @@ static void BattleStartClearSetData(void)
|
||||
|
||||
gSelectedMonPartyId = PARTY_SIZE; // Revival Blessing
|
||||
gCategoryIconSpriteId = 0xFF;
|
||||
|
||||
if(FlagGet(B_FLAG_SLEEP_CLAUSE))
|
||||
{
|
||||
// If monCausingSleepClause[side] equals PARTY_SIZE, Sleep Clause is not active for the given side.
|
||||
gBattleStruct->monCausingSleepClause[B_SIDE_PLAYER] = PARTY_SIZE;
|
||||
gBattleStruct->monCausingSleepClause[B_SIDE_OPPONENT] = PARTY_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void SwitchInClearSetData(u32 battler)
|
||||
|
||||
@ -890,6 +890,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
|
||||
[STRINGID_ELECTRICCURRENTISRUNNING] = COMPOUND_STRING("An electric current is running across the battlefield!"),
|
||||
[STRINGID_SEEMSWEIRD] = COMPOUND_STRING("The battlefield seems weird!"),
|
||||
[STRINGID_WAGGLINGAFINGER] = COMPOUND_STRING("Waggling a finger let it use {B_CURRENT_MOVE}!"),
|
||||
[STRINGID_BLOCKEDBYSLEEPCLAUSE] = COMPOUND_STRING("Sleep Clause kept {B_DEF_NAME_WITH_PREFIX2} awake!"),
|
||||
};
|
||||
|
||||
const u16 gTrainerUsedItemStringIds[] =
|
||||
|
||||
@ -3004,7 +3004,7 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
|
||||
if (i != gBattlersCount)
|
||||
break;
|
||||
if (!CanBeSlept(gEffectBattler, GetBattlerAbility(gEffectBattler)))
|
||||
if (!CanBeSlept(gEffectBattler, GetBattlerAbility(gEffectBattler), TRUE) && !(gBattleStruct->sleepClauseEffectExempt & (1u << gEffectBattler)))
|
||||
break;
|
||||
|
||||
cancelMultiTurnMovesResult = CancelMultiTurnMoves(gEffectBattler);
|
||||
@ -3223,6 +3223,8 @@ void SetMoveEffect(bool32 primary, bool32 certain)
|
||||
gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 1, 3));
|
||||
else
|
||||
gBattleMons[gEffectBattler].status1 |= STATUS1_SLEEP_TURN(1 + RandomUniform(RNG_SLEEP_TURNS, 2, 5));
|
||||
|
||||
TryActivateSleepClause(gEffectBattler, gBattlerPartyIndexes[gEffectBattler]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4188,6 +4190,8 @@ static void Cmd_tryfaintmon(void)
|
||||
|
||||
PREPARE_MOVE_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].moves[moveIndex])
|
||||
}
|
||||
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5931,6 +5935,7 @@ static void Cmd_moveend(void)
|
||||
gBattlescriptCurrInstr = BattleScript_TargetPRLZHeal;
|
||||
break;
|
||||
case STATUS1_SLEEP:
|
||||
TryDeactivateSleepClause(GetBattlerSide(gBattlerTarget), gBattlerPartyIndexes[gBattlerTarget]);
|
||||
gBattlescriptCurrInstr = BattleScript_TargetWokeUp;
|
||||
break;
|
||||
case STATUS1_BURN:
|
||||
@ -10171,7 +10176,7 @@ static void Cmd_various(void)
|
||||
}
|
||||
case VARIOUS_PSYCHO_SHIFT:
|
||||
{
|
||||
VARIOUS_ARGS(const u8 *failInstr);
|
||||
VARIOUS_ARGS(const u8 *failInstr, const u8 *sleepClauseFailInstr);
|
||||
u32 targetAbility = GetBattlerAbility(gBattlerTarget);
|
||||
// Psycho shift works
|
||||
if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_POISON) && CanBePoisoned(gBattlerAttacker, gBattlerTarget, targetAbility))
|
||||
@ -10182,10 +10187,15 @@ static void Cmd_various(void)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 2;
|
||||
else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && CanBeParalyzed(gBattlerTarget, targetAbility))
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
|
||||
else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanBeSlept(gBattlerTarget, targetAbility))
|
||||
else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP) && CanBeSlept(gBattlerTarget, targetAbility, TRUE))
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
|
||||
else if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE) && CanGetFrostbite(gBattlerTarget))
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 5;
|
||||
else if (IsSleepClauseActiveForSide(GetBattlerSide(battler)))
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->sleepClauseFailInstr;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
@ -10196,11 +10206,16 @@ static void Cmd_various(void)
|
||||
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
TryActivateSleepClause(battler, gBattlerPartyIndexes[battler]);
|
||||
return;
|
||||
}
|
||||
case VARIOUS_CURE_STATUS:
|
||||
{
|
||||
VARIOUS_ARGS();
|
||||
|
||||
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
|
||||
gBattleMons[battler].status1 = 0;
|
||||
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[battler].status1), &gBattleMons[battler].status1);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
@ -13269,12 +13284,11 @@ static void Cmd_healpartystatus(void)
|
||||
u32 zero = 0;
|
||||
u32 partner = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gBattlerAttacker)));
|
||||
u8 toHeal = 0;
|
||||
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
|
||||
s32 i;
|
||||
|
||||
if (gCurrentMove == MOVE_HEAL_BELL)
|
||||
{
|
||||
struct Pokemon *party = GetBattlerParty(gBattlerAttacker);
|
||||
s32 i;
|
||||
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_BELL;
|
||||
|
||||
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF
|
||||
@ -13340,7 +13354,10 @@ static void Cmd_healpartystatus(void)
|
||||
}
|
||||
|
||||
if (ability != ABILITY_SOUNDPROOF)
|
||||
{
|
||||
toHeal |= (1 << i);
|
||||
TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13349,6 +13366,11 @@ static void Cmd_healpartystatus(void)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SOOTHING_AROMA;
|
||||
toHeal = (1 << PARTY_SIZE) - 1;
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), i);
|
||||
}
|
||||
|
||||
gBattleMons[gBattlerAttacker].status1 = 0;
|
||||
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE;
|
||||
|
||||
@ -14123,6 +14145,9 @@ static void Cmd_curestatuswithmove(void)
|
||||
|
||||
if (shouldHeal)
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP)
|
||||
TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]);
|
||||
|
||||
gBattleMons[gBattlerAttacker].status1 = 0;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
BtlController_EmitSetMonData(gBattlerAttacker, BUFFER_A, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerAttacker].status1), &gBattleMons[gBattlerAttacker].status1);
|
||||
@ -14731,6 +14756,9 @@ static void Cmd_switchoutabilities(void)
|
||||
switch (GetBattlerAbility(battler))
|
||||
{
|
||||
case ABILITY_NATURAL_CURE:
|
||||
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
|
||||
gBattleMons[battler].status1 = 0;
|
||||
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE,
|
||||
1u << *(gBattleStruct->battlerPartyIndexes + battler),
|
||||
@ -17250,6 +17278,25 @@ void BS_DamageToQuarterTargetHP(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_JumpIfSleepClause(void)
|
||||
{
|
||||
NATIVE_ARGS(const u8 *jumpInstr);
|
||||
|
||||
// Can freely sleep own partner
|
||||
if (IsDoubleBattle() && B_FLAG_SLEEP_CLAUSE && GetBattlerSide(gBattlerAttacker) == GetBattlerSide(gBattlerTarget))
|
||||
{
|
||||
gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerTarget);
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
return;
|
||||
}
|
||||
gBattleStruct->sleepClauseEffectExempt &= ~(1u << gBattlerTarget);
|
||||
// Can't sleep if clause is active otherwise
|
||||
if (IsSleepClauseActiveForSide(GetBattlerSide(gBattlerTarget)))
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
else
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
void BS_FickleBeamDamageCalculation(void)
|
||||
{
|
||||
NATIVE_ARGS();
|
||||
|
||||
@ -2785,6 +2785,10 @@ u8 DoBattlerEndTurnEffects(void)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAINPREVENTS_MISTY;
|
||||
BattleScriptExecute(BattleScript_TerrainPreventsEnd2);
|
||||
}
|
||||
else if (IsSleepClauseActiveForSide(GetBattlerSide(battler)))
|
||||
{
|
||||
BattleScriptExecute(BattleScript_SleepClausePreventsEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (B_SLEEP_TURNS >= GEN_5)
|
||||
@ -2792,6 +2796,7 @@ u8 DoBattlerEndTurnEffects(void)
|
||||
else
|
||||
gBattleMons[battler].status1 |= ((Random() % 4) + 3);
|
||||
|
||||
TryActivateSleepClause(battler, gBattlerPartyIndexes[battler]);
|
||||
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
|
||||
MarkBattlerForControllerExec(battler);
|
||||
BattleScriptExecute(BattleScript_YawnMakesAsleep);
|
||||
@ -3239,6 +3244,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||
{
|
||||
if (UproarWakeUpCheck(gBattlerAttacker))
|
||||
{
|
||||
TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]);
|
||||
gBattleMons[gBattlerAttacker].status1 &= ~STATUS1_SLEEP;
|
||||
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE;
|
||||
BattleScriptPushCursor();
|
||||
@ -3268,6 +3274,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||
}
|
||||
else
|
||||
{
|
||||
TryDeactivateSleepClause(GetBattlerSide(gBattlerAttacker), gBattlerPartyIndexes[gBattlerAttacker]);
|
||||
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE;
|
||||
BattleScriptPushCursor();
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP;
|
||||
@ -3327,6 +3334,8 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType)
|
||||
gHitMarker |= HITMARKER_OBEYS;
|
||||
break;
|
||||
case DISOBEYS_FALL_ASLEEP:
|
||||
if (FlagGet(B_FLAG_SLEEP_CLAUSE))
|
||||
gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerAttacker);
|
||||
gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep;
|
||||
gMoveResultFlags |= MOVE_RESULT_MISSED;
|
||||
break;
|
||||
@ -5212,7 +5221,11 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
if (gBattleMons[battler].status1 & (STATUS1_POISON | STATUS1_TOXIC_POISON))
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
|
||||
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
|
||||
{
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
}
|
||||
|
||||
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS)
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
|
||||
if (gBattleMons[battler].status1 & STATUS1_BURN)
|
||||
@ -5816,10 +5829,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
&& IsBattlerAlive(gBattlerAttacker)
|
||||
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
|
||||
&& TARGET_TURN_DAMAGED
|
||||
&& CanBeSlept(gBattlerAttacker, ability)
|
||||
&& CanBeSlept(gBattlerAttacker, ability, FALSE)
|
||||
&& GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS
|
||||
&& IsMoveMakingContact(move, gBattlerAttacker))
|
||||
{
|
||||
if (FlagGet(B_FLAG_SLEEP_CLAUSE))
|
||||
gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerAttacker);
|
||||
gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_SLEEP;
|
||||
PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility);
|
||||
BattleScriptPushCursor();
|
||||
@ -6252,6 +6267,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
|
||||
case ABILITY_VITAL_SPIRIT:
|
||||
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
|
||||
{
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
|
||||
effect = 1;
|
||||
@ -6674,8 +6690,11 @@ bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag)
|
||||
return IsBattlerGrounded(battler);
|
||||
}
|
||||
|
||||
bool32 CanBeSlept(u32 battler, u32 ability)
|
||||
bool32 CanBeSlept(u32 battler, u32 ability, u32 isBlockedBySleepClause)
|
||||
{
|
||||
if(IsSleepClauseActiveForSide(GetBattlerSide(battler)) && isBlockedBySleepClause)
|
||||
return FALSE;
|
||||
|
||||
if (ability == ABILITY_INSOMNIA
|
||||
|| ability == ABILITY_VITAL_SPIRIT
|
||||
|| ability == ABILITY_COMATOSE
|
||||
@ -7345,6 +7364,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_BerryCureSlpRet;
|
||||
effect = ITEM_STATUS_CHANGE;
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_CURE_CONFUSION:
|
||||
@ -7376,6 +7396,7 @@ static u8 ItemEffectMoveEnd(u32 battler, u16 holdEffect)
|
||||
{
|
||||
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
}
|
||||
|
||||
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS)
|
||||
@ -7586,6 +7607,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
|
||||
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
|
||||
BattleScriptExecute(BattleScript_BerryCureSlpEnd2);
|
||||
effect = ITEM_STATUS_CHANGE;
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_CURE_STATUS:
|
||||
@ -7604,6 +7626,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
|
||||
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
|
||||
i++;
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
}
|
||||
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS)
|
||||
{
|
||||
@ -7883,6 +7906,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
|
||||
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
|
||||
BattleScriptExecute(BattleScript_BerryCureSlpEnd2);
|
||||
effect = ITEM_STATUS_CHANGE;
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
}
|
||||
break;
|
||||
case HOLD_EFFECT_CURE_CONFUSION:
|
||||
@ -7907,6 +7931,7 @@ u8 ItemBattleEffects(u8 caseID, u32 battler, bool32 moveTurn)
|
||||
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
|
||||
i++;
|
||||
TryDeactivateSleepClause(GetBattlerSide(battler), gBattlerPartyIndexes[battler]);
|
||||
}
|
||||
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS)
|
||||
{
|
||||
@ -8547,7 +8572,7 @@ u8 GetAttackerObedienceForAction()
|
||||
obedienceLevel = levelReferenced - obedienceLevel;
|
||||
|
||||
calc = ((rnd >> 16) & 255);
|
||||
if (calc < obedienceLevel && CanBeSlept(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)))
|
||||
if (calc < obedienceLevel && CanBeSlept(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), FALSE))
|
||||
{
|
||||
// try putting asleep
|
||||
int i;
|
||||
@ -11972,3 +11997,31 @@ u32 GetMoveType(u32 move)
|
||||
return TYPE_MYSTERY;
|
||||
return gMovesInfo[move].type;
|
||||
}
|
||||
|
||||
void TryActivateSleepClause(u32 battler, u32 indexInParty)
|
||||
{
|
||||
if (gBattleStruct->sleepClauseEffectExempt & (1u << battler))
|
||||
{
|
||||
gBattleStruct->sleepClauseEffectExempt &= ~(1u << battler);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FlagGet(B_FLAG_SLEEP_CLAUSE))
|
||||
gBattleStruct->monCausingSleepClause[GetBattlerSide(battler)] = indexInParty;
|
||||
}
|
||||
|
||||
void TryDeactivateSleepClause(u32 battlerSide, u32 indexInParty)
|
||||
{
|
||||
// If the pokemon on the given side at the given index in the party is the one causing Sleep Clause to be active,
|
||||
// set monCausingSleepClause[battlerSide] = PARTY_SIZE, which means Sleep Clause is not active for the given side
|
||||
if (FlagGet(B_FLAG_SLEEP_CLAUSE) && gBattleStruct->monCausingSleepClause[battlerSide] == indexInParty)
|
||||
gBattleStruct->monCausingSleepClause[battlerSide] = PARTY_SIZE;
|
||||
}
|
||||
|
||||
bool8 IsSleepClauseActiveForSide(u32 battlerSide)
|
||||
{
|
||||
// If monCausingSleepClause[battlerSide] == PARTY_SIZE, Sleep Clause is not active for the given side.
|
||||
// If monCausingSleepClause[battlerSide] < PARTY_SIZE, it means it is storing the index of the mon that is causing Sleep Clause to be active,
|
||||
// from which it follows that Sleep Clause is active.
|
||||
return (FlagGet(B_FLAG_SLEEP_CLAUSE) && (gBattleStruct->monCausingSleepClause[battlerSide] < PARTY_SIZE));
|
||||
}
|
||||
|
||||
@ -4199,7 +4199,24 @@ bool8 HealStatusConditions(struct Pokemon *mon, u32 healMask, u8 battlerId)
|
||||
status &= ~healMask;
|
||||
SetMonData(mon, MON_DATA_STATUS, &status);
|
||||
if (gMain.inBattle && battlerId != MAX_BATTLERS_COUNT)
|
||||
{
|
||||
gBattleMons[battlerId].status1 &= ~healMask;
|
||||
if((healMask & STATUS1_SLEEP))
|
||||
{
|
||||
u32 i = 0;
|
||||
u32 battlerSide = GetBattlerSide(battlerId);
|
||||
struct Pokemon *party = GetSideParty(battlerSide);
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (&party[i] == mon)
|
||||
{
|
||||
TryDeactivateSleepClause(battlerSide, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
|
||||
1816
test/battle/sleep_clause.c
Normal file
1816
test/battle/sleep_clause.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1371,7 +1371,6 @@ static inline rng_value_t MakeRngValue(const u16 seed)
|
||||
|
||||
static void CB2_BattleTest_NextTrial(void)
|
||||
{
|
||||
ClearFlagAfterTest();
|
||||
TearDownBattle();
|
||||
|
||||
SetMainCallback2(CB2_BattleTest_NextParameter);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user