Use battler arguments for SetMoveEffect (#7156)

This commit is contained in:
Alex 2025-06-23 15:26:31 +02:00 committed by GitHub
parent 625918daf6
commit 66e8200d95
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 364 additions and 351 deletions

View File

@ -102,18 +102,22 @@
jumpifhalfword CMP_EQUAL, sMOVE_EFFECT, MOVE_EFFECT_CONTINUE, 1b
.endm
.macro seteffectprimary moveEffect=0
.macro seteffectprimary battler:req, effectBattler:req, moveEffect=0
.if \moveEffect != 0
setmoveeffect \moveEffect
.endif
.byte 0x16
.byte \battler
.byte \effectBattler
.endm
.macro seteffectsecondary moveEffect=0
.macro seteffectsecondary battler:req, effectBattler:req, moveEffect=0
.if \moveEffect != 0
setmoveeffect \moveEffect
.endif
.byte 0x17
.byte \battler
.byte \effectBattler
.endm
.macro clearvolatile battler:req, volatile:req
@ -350,6 +354,10 @@
.2byte \frames
.endm
.macro setchargingturn
.byte 0x40
.endm
.macro waitstate
.byte 0x3a
.endm
@ -599,6 +607,11 @@
.4byte \status2
.endm
.macro setmoveeffect effect:req
sethword sMOVE_EFFECT, \effect
sethword sSAVED_MOVE_EFFECT, \effect
.endm
.macro chosenstatusanimation battler:req, isStatus2:req, status:req
.byte 0x66
.byte \battler
@ -767,8 +780,9 @@
.byte 0x88
.endm
.macro statbuffchange flags:req, failInstr:req, stats=0
.macro statbuffchange battler:req, flags:req, failInstr:req, stats=0
.byte 0x89
.byte \battler
.2byte \flags
.4byte \failInstr
.byte \stats
@ -2348,11 +2362,6 @@
setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7
.endm
.macro setmoveeffect effect:req
sethword sMOVE_EFFECT, \effect
sethword sSAVED_MOVE_EFFECT, \effect
.endm
.macro chosenstatus1animation battler:req, status:req
chosenstatusanimation \battler, 0x0, \status
.endm
@ -2517,7 +2526,7 @@
.if \animation == FALSE
setbyte sSTAT_ANIM_PLAYED, TRUE
.endif
statbuffchange STAT_CHANGE_ALLOW_PTR, \script
statbuffchange BS_TARGET, STAT_CHANGE_ALLOW_PTR, \script
.ifnb \customString
printstring \customString
.else

File diff suppressed because it is too large Load Diff

View File

@ -104,7 +104,7 @@ BattleScript_ItemHealAndCureStatusEnd::
BattleScript_ItemIncreaseStat::
call BattleScript_UseItemMessage
itemincreasestat
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_ItemEnd
statbuffchange BS_ATTACKER, STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_ItemEnd
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
end

View File

@ -22,6 +22,24 @@ struct PickupItem
u8 percentage[10];
};
union TRANSPARENT StatChangeFlags
{
int raw;
u32 raw_u32;
u16 raw_u16;
u8 raw_u8;
struct {
bool32 allowPtr:1; // STAT_CHANGE_ALLOW_PTR
bool32 mirrorArmored:1; // STAT_CHANGE_MIRROR_ARMOR
bool32 onlyChecking:1; // STAT_CHANGE_ONLY_CHECKING
bool32 notProtectAffected:1; // STAT_CHANGE_NOT_PROTECT_AFFECTED
bool32 updateMoveEffect:1; // STAT_CHANGE_UPDATE_MOVE_EFFECT
bool32 statDropPrevention:1; // STAT_CHANGE_CHECK_PREVENTION
bool32 certain:1; // STAT_CHANGE_CERTAIN
bool32 padding:25;
};
};
s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, enum ItemHoldEffect holdEffectAtk);
s32 CalcCritChanceStageGen1(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility, u32 abilityAtk, u32 abilityDef, enum ItemHoldEffect holdEffectAtk);
s32 GetCritHitOdds(s32 critChanceIndex);
@ -30,7 +48,7 @@ u8 GetBattlerTurnOrderNum(u8 battler);
bool32 NoAliveMonsForBattlerSide(u32 battler);
bool32 NoAliveMonsForPlayer(void);
bool32 NoAliveMonsForEitherParty(void);
void SetMoveEffect(bool32 primary, bool32 certain);
void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certain);
bool32 CanBattlerSwitch(u32 battlerId);
void BattleDestroyYesNoCursorAt(u8 cursorPosition);
void BattleCreateYesNoCursorAt(u8 cursorPosition);

View File

@ -141,7 +141,7 @@ enum VolatileFlags
// Volatile status ailments
// These are removed after exiting the battle or switching
/* Definitions with names e.g. "Confusion" are accessible in the debug menu
/* Definitions with names e.g. "Confusion" are accessible in the debug menu
* Enum, Type, (Field name, (optional)bitSize), Flags, (optional)(Debug menu header, (optional)max. value)
*/
#define VOLATILE_DEFINITIONS(F) \
@ -390,7 +390,6 @@ enum MoveEffects
MOVE_EFFECT_TRI_ATTACK,
MOVE_EFFECT_UPROAR,
MOVE_EFFECT_PAYDAY,
MOVE_EFFECT_CHARGING,
MOVE_EFFECT_WRAP,
MOVE_EFFECT_ATK_PLUS_1,
MOVE_EFFECT_DEF_PLUS_1,
@ -515,8 +514,6 @@ enum MoveEffects
#define MOVE_EFFECT_FREEZE_OR_FROSTBITE MOVE_EFFECT_FREEZE
#endif
#define MOVE_EFFECT_AFFECTS_USER 0x2000
#define MOVE_EFFECT_CERTAIN 0x4000
#define MOVE_EFFECT_CONTINUE 0x8000
// Battle environment defines for gBattleEnvironment.

View File

@ -222,8 +222,10 @@ enum CmdVarious
#define STAT_CHANGE_ALLOW_PTR (1 << 0) // If set, allow use of jumpptr. If not set and unable to raise/lower stats, jump to failInstr.
#define STAT_CHANGE_MIRROR_ARMOR (1 << 1) // Stat change redirection caused by Mirror Armor ability.
#define STAT_CHANGE_ONLY_CHECKING (1 << 2) // Checks if the stat change can occur. Does not change stats or play stat change animation.
#define STAT_CHANGE_NOT_PROTECT_AFFECTED (1 << 5)
#define STAT_CHANGE_UPDATE_MOVE_EFFECT (1 << 6)
#define STAT_CHANGE_NOT_PROTECT_AFFECTED (1 << 3)
#define STAT_CHANGE_UPDATE_MOVE_EFFECT (1 << 4)
#define STAT_CHANGE_CHECK_PREVENTION (1 << 5)
#define STAT_CHANGE_CERTAIN (1 << 6)
// stat flags for TryPlayStatChangeAnimation
#define BIT_HP (1 << 0)
@ -301,7 +303,7 @@ enum StatusTrigger
{
TRIGGER_ON_MOVE,
TRIGGER_ON_ABILITY,
TRIGGER_ON_ATTACKER,
TRIGGER_ON_PROTECT,
};
#endif // GUARD_CONSTANTS_BATTLE_SCRIPT_COMMANDS_H

View File

@ -24,6 +24,7 @@
#define ALIGNED(n) __attribute__((aligned(n)))
#define PACKED __attribute__((packed))
#define TRANSPARENT __attribute__ ((__transparent_union__))
#define SOUND_INFO_PTR (*(struct SoundInfo **)0x3007FF0)
#define INTR_CHECK (*(u16 *)0x3007FF8)

View File

@ -470,8 +470,8 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler)
gBattleMons[battler].status2 &= ~STATUS2_MULTIPLETURNS;
if (!(gBattleMons[battler].status2 & STATUS2_CONFUSION))
{
gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION | MOVE_EFFECT_AFFECTS_USER;
SetMoveEffect(TRUE, FALSE);
gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION;
SetMoveEffect(battler, battler, TRUE, FALSE);
if (gBattleMons[battler].status2 & STATUS2_CONFUSION)
BattleScriptExecute(BattleScript_ThrashConfuses);
effect = TRUE;

View File

@ -319,7 +319,7 @@ enum GiveCaughtMonStates
#define TAG_LVLUP_BANNER_MON_ICON 55130
static void TrySetDestinyBondToHappen(void);
static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const u8 *BS_ptr);
static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChangeFlags flags, u32 stats, const u8 *BS_ptr);
static bool32 IsMonGettingExpSentOut(void);
static void InitLevelUpBanner(void);
static bool8 SlideInLevelUpBanner(void);
@ -409,7 +409,7 @@ static void Cmd_return(void);
static void Cmd_end(void);
static void Cmd_end2(void);
static void Cmd_end3(void);
static void Cmd_unused5(void);
static void Cmd_setchargingturn(void);
static void Cmd_call(void);
static void Cmd_setroost(void);
static void Cmd_jumpifabilitypresent(void);
@ -668,7 +668,7 @@ void (*const gBattleScriptingCommandsTable[])(void) =
Cmd_end, //0x3D
Cmd_end2, //0x3E
Cmd_end3, //0x3F
Cmd_unused5, //0x40
Cmd_setchargingturn, //0x40
Cmd_call, //0x41
Cmd_setroost, //0x42
Cmd_jumpifabilitypresent, //0x43
@ -1434,8 +1434,17 @@ static void JumpIfMoveFailed(u32 adder, u32 move, u32 moveType, const u8 *failIn
gBattlescriptCurrInstr += adder;
}
static void Cmd_unused5(void)
static void Cmd_setchargingturn(void)
{
CMD_ARGS();
if (!gBattleMons[gBattlerAttacker].volatiles.multipleTurns)
{
gBattleMons[gBattlerAttacker].volatiles.multipleTurns = TRUE;
gLockedMoves[gBattlerAttacker] = gCurrentMove;
gProtectStructs[gBattlerAttacker].chargingTurn = TRUE;
}
gBattlescriptCurrInstr = cmd->nextInstr;
}
static bool32 JumpIfMoveAffectedByProtect(u32 move, u32 battler, u32 shouldJump, const u8 *failInstr)
@ -3244,11 +3253,13 @@ static void SetNonVolatileStatusCondition(u32 effectBattler, enum MoveEffects ef
gBattleStruct->poisonPuppeteerConfusion = TRUE;
}
void SetMoveEffect(bool32 primary, bool32 certain)
// To avoid confusion the arguments are naned battler/effectBattler since they can be different from gBattlerAttacker/gBattlerTarget
void SetMoveEffect(u32 battler, u32 effectBattler, bool32 primary, bool32 certain)
{
s32 i, affectsUser = 0;
s32 i;
bool32 affectsUser = (battler == effectBattler);
bool32 mirrorArmorReflected = (GetBattlerAbility(gBattlerTarget) == ABILITY_MIRROR_ARMOR);
u32 flags = 0;
union StatChangeFlags flags = {0};
u32 battlerAbility;
bool32 activateAfterFaint = FALSE;
@ -3275,37 +3286,22 @@ void SetMoveEffect(bool32 primary, bool32 certain)
break;
}
if (gBattleScripting.moveEffect & MOVE_EFFECT_AFFECTS_USER)
{
gEffectBattler = gBattlerAttacker; // battler that effects get applied on
gBattleScripting.moveEffect &= ~MOVE_EFFECT_AFFECTS_USER;
affectsUser = MOVE_EFFECT_AFFECTS_USER;
gBattleScripting.battler = gBattlerTarget; // theoretically the attacker
}
else
{
gEffectBattler = gBattlerTarget;
gBattleScripting.battler = gBattlerAttacker;
}
gBattleScripting.battler = battler;
gEffectBattler = effectBattler;
battlerAbility = GetBattlerAbility(gEffectBattler);
// Just in case this flag is still set
gBattleScripting.moveEffect &= ~MOVE_EFFECT_CERTAIN;
if (!primary && affectsUser != MOVE_EFFECT_AFFECTS_USER
if (!primary && !affectsUser
&& !(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT)
&& IsMoveEffectBlockedByTarget(battlerAbility))
gBattleScripting.moveEffect = MOVE_EFFECT_NONE;
else if (!(gHitMarker & HITMARKER_STATUS_ABILITY_EFFECT)
&& TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)
&& !(GetMoveEffect(gCurrentMove) == EFFECT_ORDER_UP && gBattleStruct->commanderActive[gBattlerAttacker])
&& !primary
&& gBattleScripting.moveEffect != MOVE_EFFECT_CHARGING)
&& !primary)
gBattleScripting.moveEffect = MOVE_EFFECT_NONE;
else if (!IsBattlerAlive(gEffectBattler) && !activateAfterFaint)
gBattleScripting.moveEffect = MOVE_EFFECT_NONE;
else if (DoesSubstituteBlockMove(gBattlerAttacker, gEffectBattler, gCurrentMove) && affectsUser != MOVE_EFFECT_AFFECTS_USER)
else if (DoesSubstituteBlockMove(gBattlerAttacker, gEffectBattler, gCurrentMove) && !affectsUser)
gBattleScripting.moveEffect = MOVE_EFFECT_NONE;
switch (gBattleScripting.moveEffect)
@ -3451,18 +3447,9 @@ void SetMoveEffect(bool32 primary, bool32 certain)
MOVE_EFFECT_PARALYSIS
};
gBattleScripting.moveEffect = RandomElement(RNG_TRI_ATTACK, sTriAttackEffects);
SetMoveEffect(primary, certain);
SetMoveEffect(battler, effectBattler, primary, certain);
}
break;
case MOVE_EFFECT_CHARGING:
if (!(gBattleMons[gEffectBattler].status2 & STATUS2_MULTIPLETURNS))
{
gBattleMons[gEffectBattler].status2 |= STATUS2_MULTIPLETURNS;
gLockedMoves[gEffectBattler] = gCurrentMove;
gProtectStructs[gEffectBattler].chargingTurn = TRUE;
}
gBattlescriptCurrInstr++;
break;
case MOVE_EFFECT_WRAP:
if (gBattleMons[gEffectBattler].status2 & STATUS2_WRAPPED)
{
@ -3497,16 +3484,18 @@ void SetMoveEffect(bool32 primary, bool32 certain)
case MOVE_EFFECT_ACC_PLUS_1:
case MOVE_EFFECT_EVS_PLUS_1:
if (NoAliveMonsForEitherParty()
|| ChangeStatBuffs(SET_STAT_BUFF_VALUE(1),
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_1 + 1,
affectsUser | STAT_CHANGE_UPDATE_MOVE_EFFECT,
0, 0) == STAT_CHANGE_DIDNT_WORK)
|| ChangeStatBuffs(
effectBattler,
SET_STAT_BUFF_VALUE(1),
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_1 + 1,
STAT_CHANGE_UPDATE_MOVE_EFFECT,
0, 0) == STAT_CHANGE_DIDNT_WORK)
{
gBattlescriptCurrInstr++;
}
else
{
gBattleScripting.animArg1 = gBattleScripting.moveEffect & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
gBattleScripting.animArg1 = gBattleScripting.moveEffect;
gBattleScripting.animArg2 = 0;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_StatUp;
@ -3519,26 +3508,25 @@ void SetMoveEffect(bool32 primary, bool32 certain)
case MOVE_EFFECT_SP_DEF_MINUS_1:
case MOVE_EFFECT_ACC_MINUS_1:
case MOVE_EFFECT_EVS_MINUS_1:
if (affectsUser == MOVE_EFFECT_AFFECTS_USER)
flags = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN;
else
flags = 0;
flags.certain = affectsUser;
if (mirrorArmorReflected && !affectsUser)
flags |= STAT_CHANGE_ALLOW_PTR;
flags.allowPtr = TRUE;
else
flags |= STAT_CHANGE_UPDATE_MOVE_EFFECT;
flags.updateMoveEffect = TRUE;
if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE,
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_1 + 1,
flags,
0, gBattlescriptCurrInstr + 1) == STAT_CHANGE_DIDNT_WORK)
if (ChangeStatBuffs(
effectBattler,
SET_STAT_BUFF_VALUE(1) | STAT_BUFF_NEGATIVE,
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_1 + 1,
flags,
0, gBattlescriptCurrInstr + 1) == STAT_CHANGE_DIDNT_WORK)
{
if (!mirrorArmorReflected)
gBattlescriptCurrInstr++;
}
else
{
gBattleScripting.animArg1 = gBattleScripting.moveEffect & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
gBattleScripting.animArg1 = gBattleScripting.moveEffect;
gBattleScripting.animArg2 = 0;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_StatDown;
@ -3552,16 +3540,18 @@ void SetMoveEffect(bool32 primary, bool32 certain)
case MOVE_EFFECT_ACC_PLUS_2:
case MOVE_EFFECT_EVS_PLUS_2:
if (NoAliveMonsForEitherParty()
|| ChangeStatBuffs(SET_STAT_BUFF_VALUE(2),
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_2 + 1,
affectsUser | STAT_CHANGE_UPDATE_MOVE_EFFECT,
0, 0) == STAT_CHANGE_DIDNT_WORK)
|| ChangeStatBuffs(
effectBattler,
SET_STAT_BUFF_VALUE(2),
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_PLUS_2 + 1,
STAT_CHANGE_UPDATE_MOVE_EFFECT,
0, 0) == STAT_CHANGE_DIDNT_WORK)
{
gBattlescriptCurrInstr++;
}
else
{
gBattleScripting.animArg1 = gBattleScripting.moveEffect & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
gBattleScripting.animArg1 = gBattleScripting.moveEffect;
gBattleScripting.animArg2 = 0;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_StatUp;
@ -3574,26 +3564,25 @@ void SetMoveEffect(bool32 primary, bool32 certain)
case MOVE_EFFECT_SP_DEF_MINUS_2:
case MOVE_EFFECT_ACC_MINUS_2:
case MOVE_EFFECT_EVS_MINUS_2:
if (affectsUser == MOVE_EFFECT_AFFECTS_USER)
flags = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN;
else
flags = 0;
flags.certain = affectsUser;
if (mirrorArmorReflected && !affectsUser)
flags |= STAT_CHANGE_ALLOW_PTR;
flags.allowPtr = TRUE;
else
flags |= STAT_CHANGE_UPDATE_MOVE_EFFECT;
flags.updateMoveEffect = TRUE;
if (ChangeStatBuffs(SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE,
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_2 + 1,
flags,
0, gBattlescriptCurrInstr + 1) == STAT_CHANGE_DIDNT_WORK)
if (ChangeStatBuffs(
effectBattler,
SET_STAT_BUFF_VALUE(2) | STAT_BUFF_NEGATIVE,
gBattleScripting.moveEffect - MOVE_EFFECT_ATK_MINUS_2 + 1,
flags,
0, gBattlescriptCurrInstr + 1) == STAT_CHANGE_DIDNT_WORK)
{
if (!mirrorArmorReflected)
gBattlescriptCurrInstr++;
}
else
{
gBattleScripting.animArg1 = gBattleScripting.moveEffect & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
gBattleScripting.animArg1 = gBattleScripting.moveEffect;
gBattleScripting.animArg2 = 0;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_StatDown;
@ -3838,7 +3827,7 @@ void SetMoveEffect(bool32 primary, bool32 certain)
{
static const u8 sDireClawEffects[] = { MOVE_EFFECT_POISON, MOVE_EFFECT_PARALYSIS, MOVE_EFFECT_SLEEP };
gBattleScripting.moveEffect = RandomElement(RNG_DIRE_CLAW, sDireClawEffects);
SetMoveEffect(primary, certain);
SetMoveEffect(battler, effectBattler, primary, certain);
}
break;
case MOVE_EFFECT_STEALTH_ROCK:
@ -3955,7 +3944,7 @@ void SetMoveEffect(bool32 primary, bool32 certain)
break;
}
}
SetMoveEffect(primary, certain);
SetMoveEffect(battler, effectBattler, primary, certain);
break;
case MOVE_EFFECT_PSYCHIC_NOISE:
battlerAbility = IsAbilityOnSide(gEffectBattler, ABILITY_AROMA_VEIL);
@ -4004,17 +3993,19 @@ void SetMoveEffect(bool32 primary, bool32 certain)
}
if (!commanderAffected
|| NoAliveMonsForEitherParty()
|| ChangeStatBuffs(SET_STAT_BUFF_VALUE(1),
stat,
affectsUser | STAT_CHANGE_UPDATE_MOVE_EFFECT,
0,
0) == STAT_CHANGE_DIDNT_WORK)
|| ChangeStatBuffs(
effectBattler,
SET_STAT_BUFF_VALUE(1),
stat,
STAT_CHANGE_UPDATE_MOVE_EFFECT,
0,
0) == STAT_CHANGE_DIDNT_WORK)
{
gBattlescriptCurrInstr++;
}
else
{
gBattleScripting.animArg1 = gBattleScripting.moveEffect & ~(MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN);
gBattleScripting.animArg1 = gBattleScripting.moveEffect;
gBattleScripting.animArg2 = 0;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_StatUp;
@ -4508,9 +4499,11 @@ static void Cmd_setadditionaleffects(void)
// Activate effect if it's primary (chance == 0) or if RNGesus says so
if ((percentChance == 0) || RandomPercentage(RNG_SECONDARY_EFFECT + gBattleStruct->additionalEffectsCounter, percentChance))
{
gBattleScripting.moveEffect = additionalEffect->moveEffect | (MOVE_EFFECT_AFFECTS_USER * (additionalEffect->self));
gBattleScripting.moveEffect = additionalEffect->moveEffect;
SetMoveEffect(
gBattlerAttacker,
additionalEffect->self ? gBattlerAttacker : gBattlerTarget,
percentChance == 0, // a primary effect
percentChance >= 100 // certain to happen
);
@ -4545,16 +4538,22 @@ static void Cmd_setadditionaleffects(void)
static void Cmd_seteffectprimary(void)
{
CMD_ARGS();
CMD_ARGS(u8 battler, u8 effectBattler);
SetMoveEffect(TRUE, FALSE);
u32 battler = GetBattlerForBattleScript(cmd->battler);
u32 effectBattler = GetBattlerForBattleScript(cmd->effectBattler);
gBattlescriptCurrInstr = cmd->nextInstr - 1;
SetMoveEffect(battler, effectBattler, TRUE, FALSE);
}
static void Cmd_seteffectsecondary(void)
{
CMD_ARGS();
CMD_ARGS(u8 battler, u8 effectBattler);
SetMoveEffect(FALSE, FALSE);
u32 battler = GetBattlerForBattleScript(cmd->battler);
u32 effectBattler = GetBattlerForBattleScript(cmd->effectBattler);
gBattlescriptCurrInstr = cmd->nextInstr - 1;
SetMoveEffect(battler, effectBattler, FALSE, FALSE);
}
static void Cmd_clearvolatile(void)
@ -11104,7 +11103,7 @@ static void Cmd_various(void)
// Confuse target if they were in the middle of Petal Dance/Outrage/Thrash when targeted.
if (gBattleMons[gBattlerTarget].status2 & STATUS2_LOCK_CONFUSE)
gBattleScripting.moveEffect = (MOVE_EFFECT_CONFUSION | MOVE_EFFECT_CERTAIN);
gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION;
return;
}
case VARIOUS_SKY_DROP_YAWN: // If the mon that's sleeping due to Yawn was holding a Pokemon in Sky Drop, release the target and clear Sky Drop data.
@ -12101,43 +12100,26 @@ static void TryPlayStatChangeAnimation(u32 battler, u32 ability, u32 stats, s32
}
}
static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const u8 *BS_ptr)
static u32 ChangeStatBuffs(u32 battler, s8 statValue, u32 statId, union StatChangeFlags flags, u32 stats, const u8 *BS_ptr)
{
u32 index, battler, battlerAbility;
u32 index, battlerAbility;
enum ItemHoldEffect battlerHoldEffect;
bool32 certain = (flags & MOVE_EFFECT_CERTAIN);
bool32 notProtectAffected = (flags & STAT_CHANGE_NOT_PROTECT_AFFECTED);
bool32 affectsUser = (flags & MOVE_EFFECT_AFFECTS_USER);
bool32 mirrorArmored = (flags & STAT_CHANGE_MIRROR_ARMOR);
bool32 onlyChecking = (flags & STAT_CHANGE_ONLY_CHECKING);
if (affectsUser)
battler = gBattlerAttacker;
else
battler = gBattlerTarget;
battlerAbility = GetBattlerAbility(battler);
battlerHoldEffect = GetBattlerHoldEffect(battler, TRUE);
gSpecialStatuses[battler].changedStatsBattlerId = gBattlerAttacker;
flags &= ~(STAT_CHANGE_ONLY_CHECKING | STAT_CHANGE_MIRROR_ARMOR | STAT_CHANGE_NOT_PROTECT_AFFECTED);
if (battlerAbility == ABILITY_CONTRARY)
{
statValue ^= STAT_BUFF_NEGATIVE;
if (!onlyChecking)
if (!flags.onlyChecking)
{
gBattleScripting.statChanger ^= STAT_BUFF_NEGATIVE;
RecordAbilityBattle(battler, battlerAbility);
if (flags & STAT_CHANGE_UPDATE_MOVE_EFFECT)
{
flags &= ~STAT_CHANGE_UPDATE_MOVE_EFFECT;
if (flags.updateMoveEffect)
gBattleScripting.moveEffect = ReverseStatChangeMoveEffect(gBattleScripting.moveEffect);
}
}
}
else if (battlerAbility == ABILITY_SIMPLE && !onlyChecking)
else if (battlerAbility == ABILITY_SIMPLE && !flags.onlyChecking)
{
statValue = (SET_STAT_BUFF_VALUE(GET_STAT_BUFF_VALUE(statValue) * 2)) | ((statValue <= -1) ? STAT_BUFF_NEGATIVE : 0);
RecordAbilityBattle(battler, battlerAbility);
@ -12148,10 +12130,10 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const
if (statValue <= -1) // Stat decrease.
{
if (gSideTimers[GetBattlerSide(battler)].mistTimer
&& !certain && gCurrentMove != MOVE_CURSE
&& !flags.certain && gCurrentMove != MOVE_CURSE
&& !(battler == gBattlerTarget && GetBattlerAbility(gBattlerAttacker) == ABILITY_INFILTRATOR))
{
if (flags & STAT_CHANGE_ALLOW_PTR)
if (flags.allowPtr)
{
if (gSpecialStatuses[battler].statLowered)
{
@ -12168,14 +12150,14 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const
return STAT_CHANGE_DIDNT_WORK;
}
else if (gCurrentMove != MOVE_CURSE
&& notProtectAffected != TRUE && JumpIfMoveAffectedByProtect(gCurrentMove, gBattlerTarget, TRUE, BattleScript_ButItFailed))
&& !flags.notProtectAffected && JumpIfMoveAffectedByProtect(gCurrentMove, gBattlerTarget, TRUE, BattleScript_ButItFailed))
{
return STAT_CHANGE_DIDNT_WORK;
}
else if ((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET || CanAbilityPreventStatLoss(battlerAbility))
&& (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE)
&& (flags.statDropPrevention || gBattlerAttacker != gBattlerTarget || flags.mirrorArmored) && !flags.certain && gCurrentMove != MOVE_CURSE)
{
if (flags & STAT_CHANGE_ALLOW_PTR)
if (flags.allowPtr)
{
if (gSpecialStatuses[battler].statLowered)
{
@ -12204,9 +12186,9 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const
}
return STAT_CHANGE_DIDNT_WORK;
}
else if ((index = IsFlowerVeilProtected(battler)) && !certain)
else if ((index = IsFlowerVeilProtected(battler)) && !flags.certain)
{
if (flags & STAT_CHANGE_ALLOW_PTR)
if (flags.allowPtr)
{
if (gSpecialStatuses[battler].statLowered)
{
@ -12224,13 +12206,13 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const
}
return STAT_CHANGE_DIDNT_WORK;
}
else if (!certain
else if (!flags.certain
&& (((battlerAbility == ABILITY_KEEN_EYE || battlerAbility == ABILITY_MINDS_EYE) && statId == STAT_ACC)
|| (B_ILLUMINATE_EFFECT >= GEN_9 && battlerAbility == ABILITY_ILLUMINATE && statId == STAT_ACC)
|| (battlerAbility == ABILITY_HYPER_CUTTER && statId == STAT_ATK)
|| (battlerAbility == ABILITY_BIG_PECKS && statId == STAT_DEF)))
{
if (flags & STAT_CHANGE_ALLOW_PTR)
if (flags.allowPtr)
{
BattleScriptPush(BS_ptr);
gBattleScripting.battler = battler;
@ -12241,9 +12223,9 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const
}
return STAT_CHANGE_DIDNT_WORK;
}
else if (battlerAbility == ABILITY_MIRROR_ARMOR && !affectsUser && !mirrorArmored && gBattlerAttacker != gBattlerTarget && battler == gBattlerTarget)
else if (battlerAbility == ABILITY_MIRROR_ARMOR && !flags.mirrorArmored && gBattlerAttacker != gBattlerTarget && battler == gBattlerTarget)
{
if (flags & STAT_CHANGE_ALLOW_PTR)
if (flags.allowPtr)
{
SET_STATCHANGER(statId, GET_STAT_BUFF_VALUE(statValue) | STAT_BUFF_NEGATIVE, TRUE);
BattleScriptPush(BS_ptr);
@ -12288,7 +12270,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_DECREASE;
}
else if (!onlyChecking)
else if (!flags.onlyChecking)
{
gProtectStructs[battler].statFell = TRUE;
gProtectStructs[battler].lashOutAffected = TRUE;
@ -12329,7 +12311,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_INCREASE;
}
else if (!onlyChecking)
else if (!flags.onlyChecking)
{
u32 statIncrease;
if ((statValue + gBattleMons[battler].statStages[statId]) > MAX_STAT_STAGE)
@ -12369,13 +12351,13 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const
if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_STAT_WONT_INCREASE) // same as B_MSG_STAT_WONT_DECREASE
{
if (!(flags & STAT_CHANGE_ALLOW_PTR))
if (!flags.allowPtr)
return STAT_CHANGE_DIDNT_WORK;
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED;
return STAT_CHANGE_WORKED;
}
if (onlyChecking)
if (flags.onlyChecking)
return STAT_CHANGE_WORKED;
gBattleMons[battler].statStages[statId] += statValue;
@ -12389,25 +12371,27 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, u32 stats, const
else
stats &= ~(1u << statId);
TryPlayStatChangeAnimation(battler, battlerAbility, stats, statValue, statId, certain);
TryPlayStatChangeAnimation(battler, battlerAbility, stats, statValue, statId, flags.certain);
return STAT_CHANGE_WORKED;
}
static void Cmd_statbuffchange(void)
{
CMD_ARGS(u16 flags, const u8 *failInstr, u8 stats);
CMD_ARGS(u8 battler, u16 flags, const u8 *failInstr, u8 stats);
u16 flags = cmd->flags;
u32 stats = cmd->stats;
const u8 *ptrBefore = gBattlescriptCurrInstr;
const u8 *failInstr = cmd->failInstr;
if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger),
GET_STAT_BUFF_ID(gBattleScripting.statChanger),
flags,
stats,
failInstr) == STAT_CHANGE_WORKED)
if (ChangeStatBuffs(
GetBattlerForBattleScript(cmd->battler),
GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger),
GET_STAT_BUFF_ID(gBattleScripting.statChanger),
flags,
stats,
failInstr) == STAT_CHANGE_WORKED)
gBattlescriptCurrInstr = cmd->nextInstr;
else if (gBattlescriptCurrInstr == ptrBefore) // Prevent infinite looping.
gBattlescriptCurrInstr = failInstr;
@ -16417,15 +16401,15 @@ static void Cmd_setnonvolatilestatus(void)
{
case TRIGGER_ON_ABILITY:
if (gBattleScripting.moveEffect == MOVE_EFFECT_CONFUSION)
SetMoveEffect(FALSE, FALSE);
SetMoveEffect(gBattleScripting.battler, gEffectBattler, FALSE, FALSE);
else
SetNonVolatileStatusCondition(gEffectBattler, gBattleScripting.moveEffect, TRIGGER_ON_ABILITY);
break;
case TRIGGER_ON_MOVE:
SetNonVolatileStatusCondition(gBattlerTarget, GetMoveNonVolatileStatus(gCurrentMove), TRIGGER_ON_MOVE);
break;
case TRIGGER_ON_ATTACKER:
SetNonVolatileStatusCondition(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_ATTACKER);
case TRIGGER_ON_PROTECT:
SetNonVolatileStatusCondition(gBattlerAttacker, gBattleScripting.moveEffect, TRIGGER_ON_PROTECT);
break;
}
}
@ -18190,10 +18174,12 @@ void BS_SpectralThiefPrintStats(void)
{
gBattleStruct->stolenStats[0] &= ~(1u << stat);
SET_STATCHANGER(stat, gBattleStruct->stolenStats[stat], FALSE);
if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger),
stat,
MOVE_EFFECT_CERTAIN | MOVE_EFFECT_AFFECTS_USER,
0, NULL) == STAT_CHANGE_WORKED)
if (ChangeStatBuffs(
gBattlerAttacker,
GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger),
stat,
STAT_CHANGE_CERTAIN,
0, NULL) == STAT_CHANGE_WORKED)
{
BattleScriptCall(BattleScript_StatUp);
return;

View File

@ -4960,7 +4960,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
{
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
BattleScriptPushCursor();
SetMoveEffect(FALSE, FALSE);
SetMoveEffect(gBattlerAttacker, gBattlerTarget, FALSE, FALSE);
BattleScriptPop();
effect++;
}
@ -7022,7 +7022,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn)
{
gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH;
BattleScriptPushCursor();
SetMoveEffect(FALSE, FALSE);
SetMoveEffect(gBattlerAttacker, gBattlerTarget, FALSE, FALSE);
BattleScriptPop();
}
}