mirror of
https://github.com/pret/pokefirered.git
synced 2026-09-29 20:38:15 -05:00
updated up to Cmd_statbuffchange
This commit is contained in:
@@ -759,7 +759,7 @@
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
.macro negativedamage
|
||||
.macro setdrainedhp
|
||||
.byte 0x88
|
||||
.endm
|
||||
|
||||
@@ -1929,7 +1929,7 @@
|
||||
|
||||
@ helpful macros
|
||||
.macro setstatchanger stat:req, stages:req, down:req
|
||||
setbyte sSTATCHANGER, \stat | \stages << 4 | \down << 7
|
||||
setbyte sSTATCHANGER, \stat | \stages << 3 | \down << 7
|
||||
.endm
|
||||
|
||||
.macro setmoveeffect effect:req
|
||||
|
||||
@@ -119,31 +119,16 @@ BattleScript_EffectPoisonHit::
|
||||
goto BattleScript_EffectHit
|
||||
|
||||
BattleScript_EffectAbsorb::
|
||||
attackcanceler
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
attackstring
|
||||
ppreduce
|
||||
critcalc
|
||||
damagecalc
|
||||
typecalc
|
||||
adjustdamage
|
||||
attackanimation
|
||||
waitanimation
|
||||
effectivenesssound
|
||||
hitanimation BS_TARGET
|
||||
waitstate
|
||||
healthbarupdate BS_TARGET
|
||||
datahpupdate BS_TARGET
|
||||
critmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
negativedamage
|
||||
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
|
||||
call BattleScript_EffectHit_Ret
|
||||
jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_AbsorbHealBlock
|
||||
setdrainedhp
|
||||
manipulatedamage DMG_BIG_ROOT
|
||||
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE
|
||||
jumpifability BS_TARGET, ABILITY_LIQUID_OOZE, BattleScript_AbsorbLiquidOoze
|
||||
setbyte cMULTISTRING_CHOOSER, B_MSG_ABSORB
|
||||
goto BattleScript_AbsorbUpdateHp
|
||||
BattleScript_AbsorbLiquidOoze::
|
||||
call BattleScript_AbilityPopUpTarget
|
||||
manipulatedamage DMG_CHANGE_SIGN
|
||||
setbyte cMULTISTRING_CHOOSER, B_MSG_ABSORB_OOZE
|
||||
BattleScript_AbsorbUpdateHp::
|
||||
@@ -154,6 +139,7 @@ BattleScript_AbsorbUpdateHp::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_AbsorbTryFainting::
|
||||
tryfaintmon BS_ATTACKER
|
||||
BattleScript_AbsorbHealBlock::
|
||||
tryfaintmon BS_TARGET
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
@@ -222,8 +208,9 @@ BattleScript_PreserveMissedBitDoMoveAnim:
|
||||
|
||||
BattleScript_EffectDreamEater::
|
||||
attackcanceler
|
||||
jumpifstatus2 BS_TARGET, STATUS2_SUBSTITUTE, BattleScript_DreamEaterNoEffect
|
||||
jumpifsubstituteblocks BattleScript_DreamEaterNoEffect
|
||||
jumpifstatus BS_TARGET, STATUS1_SLEEP, BattleScript_DreamEaterWorked
|
||||
jumpifability BS_TARGET, ABILITY_COMATOSE, BattleScript_DreamEaterWorked
|
||||
BattleScript_DreamEaterNoEffect:
|
||||
attackstring
|
||||
ppreduce
|
||||
@@ -235,7 +222,6 @@ BattleScript_DreamEaterWorked:
|
||||
ppreduce
|
||||
critcalc
|
||||
damagecalc
|
||||
typecalc
|
||||
adjustdamage
|
||||
attackanimation
|
||||
waitanimation
|
||||
@@ -248,7 +234,9 @@ BattleScript_DreamEaterWorked:
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
negativedamage
|
||||
jumpifstatus3 BS_ATTACKER, STATUS3_HEAL_BLOCK, BattleScript_DreamEaterTryFaintEnd
|
||||
setdrainedhp
|
||||
manipulatedamage DMG_BIG_ROOT
|
||||
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
|
||||
healthbarupdate BS_ATTACKER
|
||||
datahpupdate BS_ATTACKER
|
||||
@@ -6323,3 +6311,34 @@ BattleScript_LeafGuardPreventsRest::
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
|
||||
BattleScript_EffectHit_Ret::
|
||||
attackcanceler
|
||||
BattleScript_EffectHit_RetFromAccCheck::
|
||||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
attackstring
|
||||
ppreduce
|
||||
BattleScript_EffectHit_RetFromCritCalc::
|
||||
critcalc
|
||||
damagecalc
|
||||
adjustdamage
|
||||
BattleScript_Hit_RetFromAtkAnimation::
|
||||
attackanimation
|
||||
waitanimation
|
||||
effectivenesssound
|
||||
hitanimation BS_TARGET
|
||||
waitstate
|
||||
healthbarupdate BS_TARGET
|
||||
datahpupdate BS_TARGET
|
||||
critmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
setadditionaleffects
|
||||
return
|
||||
|
||||
BattleScript_ItemNoStatLoss::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printstring STRINGID_CLEARAMULETWONTLOWERSTATS
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
return
|
||||
|
||||
|
||||
@@ -774,13 +774,12 @@ extern struct BattleStruct *gBattleStruct;
|
||||
|| gProtectStructs[battlerId].obstructed \
|
||||
|| gProtectStructs[battlerId].silkTrapped)
|
||||
|
||||
#define GET_STAT_BUFF_ID(n)((n & 0xF)) // first four bits 0x1, 0x2, 0x4, 0x8
|
||||
#define GET_STAT_BUFF_VALUE2(n)((n & 0xF0))
|
||||
#define GET_STAT_BUFF_ID(n)((n & 7)) // first three bits 0x1, 0x2, 0x4
|
||||
#define GET_STAT_BUFF_VALUE_WITH_SIGN(n)((n & 0xF8))
|
||||
#define GET_STAT_BUFF_VALUE(n)(((n >> 4) & 7)) // 0x10, 0x20, 0x40
|
||||
#define GET_STAT_BUFF_VALUE(n)(((n >> 3) & 0xF)) // 0x8, 0x10, 0x20, 0x40
|
||||
#define STAT_BUFF_NEGATIVE 0x80 // 0x80, the sign bit
|
||||
|
||||
#define SET_STAT_BUFF_VALUE(n)(((s8)(((s8)(n) << 4)) & 0xF0))
|
||||
#define SET_STAT_BUFF_VALUE(n)((((n) << 3) & 0xF8))
|
||||
|
||||
#define SET_STATCHANGER(statId, stage, goesDown)(gBattleScripting.statChanger = (statId) + (stage << 4) + (goesDown << 7))
|
||||
#define SET_STATCHANGER2(dst, statId, stage, goesDown)(dst = (statId) + ((stage) << 3) + (goesDown << 7))
|
||||
|
||||
@@ -563,8 +563,11 @@
|
||||
#define STRINGID_MISTYTERRAINPREVENTS 560
|
||||
#define STRINGID_PSYCHICTERRAINPREVENTS 561
|
||||
#define STRINGID_FLOWERVEILPROTECTED 562
|
||||
#define STRINGID_DRASTICALLY 563
|
||||
#define STRINGID_SEVERELY 564
|
||||
#define STRINGID_CLEARAMULETWONTLOWERSTATS 565
|
||||
|
||||
#define BATTLESTRINGS_COUNT 563
|
||||
#define BATTLESTRINGS_COUNT 566
|
||||
|
||||
// This is the string id that gBattleStringsTable starts with.
|
||||
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
|
||||
|
||||
@@ -692,6 +692,9 @@ static const u8 sText_ElectricTerrainPreventsSleep[] = _("{B_DEF_NAME_WITH_PREFI
|
||||
static const u8 sText_MistyTerrainPreventsStatus[] = _("{B_DEF_NAME_WITH_PREFIX} surrounds itself\nwith a protective mist!");
|
||||
static const u8 sText_PsychicTerrainPreventsPriority[] = _("{B_DEF_NAME_WITH_PREFIX} surrounds itself\nwith psychic terrain!");
|
||||
static const u8 sText_FlowerVeilProtected[] = _("{B_DEF_NAME_WITH_PREFIX} surrounded itself\nwith a veil of petals!");
|
||||
static const u8 sText_drastically[] = _("drastically ");
|
||||
static const u8 sText_severely[] = _("severely ");
|
||||
static const u8 sText_ClearAmuletWontLowerStats[] = _("{B_DEF_NAME_WITH_PREFIX}'s {B_LAST_ITEM} prevents\nits stats from being lowered!");
|
||||
|
||||
|
||||
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT - BATTLESTRINGS_TABLE_START] = {
|
||||
@@ -1246,6 +1249,9 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT - BATTLESTRINGS_TABLE_ST
|
||||
[STRINGID_MISTYTERRAINPREVENTS - BATTLESTRINGS_TABLE_START] = sText_MistyTerrainPreventsStatus,
|
||||
[STRINGID_PSYCHICTERRAINPREVENTS - BATTLESTRINGS_TABLE_START] = sText_PsychicTerrainPreventsPriority,
|
||||
[STRINGID_FLOWERVEILPROTECTED - BATTLESTRINGS_TABLE_START] = sText_FlowerVeilProtected,
|
||||
[STRINGID_DRASTICALLY - BATTLESTRINGS_TABLE_START] = sText_drastically,
|
||||
[STRINGID_SEVERELY - BATTLESTRINGS_TABLE_START] = sText_severely,
|
||||
[STRINGID_CLEARAMULETWONTLOWERSTATS - BATTLESTRINGS_TABLE_START] = sText_ClearAmuletWontLowerStats,
|
||||
};
|
||||
|
||||
const u16 gTrainerUsedItemStringIds[] =
|
||||
|
||||
@@ -323,7 +323,7 @@ static bool8 IsTwoTurnsMove(u16 move);
|
||||
static void TrySetDestinyBondToHappen(void);
|
||||
static u8 AttacksThisTurn(u8 battlerId, u16 move); // Note: returns 1 if it's a charging turn, otherwise 2.
|
||||
static void CheckWonderGuardAndLevitate(void);
|
||||
static u8 ChangeStatBuffs(s8 statValue, u32 statId, u32, const u8 *BS_ptr);
|
||||
static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr);
|
||||
static void InitLevelUpBanner(void);
|
||||
static bool8 SlideInLevelUpBanner(void);
|
||||
static bool8 SlideOutLevelUpBanner(void);
|
||||
@@ -340,6 +340,7 @@ static void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 fai
|
||||
static bool8 CanBurnHitThaw(u16 move);
|
||||
static bool32 ChangeOrderTargetAfterAttacker(void);
|
||||
static void TryUpdateEvolutionTracker(u32 evolutionMethod, u32 upAmount);
|
||||
static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 isIntimidate);
|
||||
|
||||
static void Cmd_attackcanceler(void);
|
||||
static void Cmd_accuracycheck(void);
|
||||
@@ -477,7 +478,7 @@ static void Cmd_jumpifuproarwakes(void);
|
||||
static void Cmd_stockpile(void);
|
||||
static void Cmd_stockpiletobasedamage(void);
|
||||
static void Cmd_stockpiletohpheal(void);
|
||||
static void Cmd_negativedamage(void);
|
||||
static void Cmd_setdrainedhp(void);
|
||||
static void Cmd_statbuffchange(void);
|
||||
static void Cmd_normalisebuffs(void);
|
||||
static void Cmd_setbide(void);
|
||||
@@ -729,8 +730,8 @@ void (* const gBattleScriptingCommandsTable[])(void) =
|
||||
Cmd_stockpile, //0x85 // done
|
||||
Cmd_stockpiletobasedamage, //0x86 // done
|
||||
Cmd_stockpiletohpheal, //0x87 // done
|
||||
Cmd_negativedamage, //0x88
|
||||
Cmd_statbuffchange, //0x89
|
||||
Cmd_setdrainedhp, //0x88 // done
|
||||
Cmd_statbuffchange, //0x89 // done
|
||||
Cmd_normalisebuffs, //0x8A
|
||||
Cmd_setbide, //0x8B
|
||||
Cmd_confuseifrepeatingattackends, //0x8C
|
||||
@@ -11689,120 +11690,264 @@ static void Cmd_stockpiletohpheal(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void Cmd_negativedamage(void)
|
||||
// Sign change for drained HP handled in GetDrainedBigRootHp
|
||||
static void Cmd_setdrainedhp(void)
|
||||
{
|
||||
gBattleMoveDamage = -(gHpDealt / 2);
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = -1;
|
||||
CMD_ARGS();
|
||||
|
||||
gBattlescriptCurrInstr++;
|
||||
if (gMovesInfo[gCurrentMove].argument != 0)
|
||||
gBattleMoveDamage = (gHpDealt * gMovesInfo[gCurrentMove].argument / 100);
|
||||
else
|
||||
gBattleMoveDamage = (gHpDealt / 2);
|
||||
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = 1;
|
||||
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static u8 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr)
|
||||
static u16 ReverseStatChangeMoveEffect(u16 moveEffect)
|
||||
{
|
||||
switch (moveEffect)
|
||||
{
|
||||
// +1
|
||||
case MOVE_EFFECT_ATK_PLUS_1:
|
||||
return MOVE_EFFECT_ATK_MINUS_1;
|
||||
case MOVE_EFFECT_DEF_PLUS_1:
|
||||
return MOVE_EFFECT_DEF_MINUS_1;
|
||||
case MOVE_EFFECT_SPD_PLUS_1:
|
||||
return MOVE_EFFECT_SPD_MINUS_1;
|
||||
case MOVE_EFFECT_SP_ATK_PLUS_1:
|
||||
return MOVE_EFFECT_SP_ATK_MINUS_1;
|
||||
case MOVE_EFFECT_SP_DEF_PLUS_1:
|
||||
return MOVE_EFFECT_SP_DEF_MINUS_1;
|
||||
case MOVE_EFFECT_ACC_PLUS_1:
|
||||
return MOVE_EFFECT_ACC_MINUS_1;
|
||||
case MOVE_EFFECT_EVS_PLUS_1:
|
||||
return MOVE_EFFECT_EVS_MINUS_1;
|
||||
// -1
|
||||
case MOVE_EFFECT_ATK_MINUS_1:
|
||||
return MOVE_EFFECT_ATK_PLUS_1;
|
||||
case MOVE_EFFECT_DEF_MINUS_1:
|
||||
return MOVE_EFFECT_DEF_PLUS_1;
|
||||
case MOVE_EFFECT_SPD_MINUS_1:
|
||||
return MOVE_EFFECT_SPD_PLUS_1;
|
||||
case MOVE_EFFECT_SP_ATK_MINUS_1:
|
||||
return MOVE_EFFECT_SP_ATK_PLUS_1;
|
||||
case MOVE_EFFECT_SP_DEF_MINUS_1:
|
||||
return MOVE_EFFECT_SP_DEF_PLUS_1;
|
||||
case MOVE_EFFECT_ACC_MINUS_1:
|
||||
return MOVE_EFFECT_ACC_PLUS_1;
|
||||
case MOVE_EFFECT_EVS_MINUS_1:
|
||||
// +2
|
||||
case MOVE_EFFECT_ATK_PLUS_2:
|
||||
return MOVE_EFFECT_ATK_MINUS_2;
|
||||
case MOVE_EFFECT_DEF_PLUS_2:
|
||||
return MOVE_EFFECT_DEF_MINUS_2;
|
||||
case MOVE_EFFECT_SPD_PLUS_2:
|
||||
return MOVE_EFFECT_SPD_MINUS_2;
|
||||
case MOVE_EFFECT_SP_ATK_PLUS_2:
|
||||
return MOVE_EFFECT_SP_ATK_MINUS_2;
|
||||
case MOVE_EFFECT_SP_DEF_PLUS_2:
|
||||
return MOVE_EFFECT_SP_DEF_MINUS_2;
|
||||
case MOVE_EFFECT_ACC_PLUS_2:
|
||||
return MOVE_EFFECT_ACC_MINUS_2;
|
||||
case MOVE_EFFECT_EVS_PLUS_2:
|
||||
return MOVE_EFFECT_EVS_MINUS_2;
|
||||
// -2
|
||||
case MOVE_EFFECT_ATK_MINUS_2:
|
||||
return MOVE_EFFECT_ATK_PLUS_2;
|
||||
case MOVE_EFFECT_DEF_MINUS_2:
|
||||
return MOVE_EFFECT_DEF_PLUS_2;
|
||||
case MOVE_EFFECT_SPD_MINUS_2:
|
||||
return MOVE_EFFECT_SPD_PLUS_2;
|
||||
case MOVE_EFFECT_SP_ATK_MINUS_2:
|
||||
return MOVE_EFFECT_SP_ATK_PLUS_2;
|
||||
case MOVE_EFFECT_SP_DEF_MINUS_2:
|
||||
return MOVE_EFFECT_SP_DEF_PLUS_2;
|
||||
case MOVE_EFFECT_ACC_MINUS_2:
|
||||
return MOVE_EFFECT_ACC_PLUS_2;
|
||||
case MOVE_EFFECT_EVS_MINUS_2:
|
||||
return MOVE_EFFECT_EVS_PLUS_2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr)
|
||||
{
|
||||
bool32 certain = FALSE;
|
||||
bool32 notProtectAffected = FALSE;
|
||||
u32 index;
|
||||
u32 index, battler, battlerAbility, battlerHoldEffect;
|
||||
bool32 affectsUser = (flags & MOVE_EFFECT_AFFECTS_USER);
|
||||
bool32 mirrorArmored = (flags & STAT_CHANGE_MIRROR_ARMOR);
|
||||
|
||||
if (flags & MOVE_EFFECT_AFFECTS_USER)
|
||||
gActiveBattler = gBattlerAttacker;
|
||||
if (affectsUser)
|
||||
battler = gBattlerAttacker;
|
||||
else
|
||||
gActiveBattler = gBattlerTarget;
|
||||
battler = gBattlerTarget;
|
||||
gActiveBattler = battler;
|
||||
|
||||
flags &= ~MOVE_EFFECT_AFFECTS_USER;
|
||||
battlerAbility = GetBattlerAbility(battler);
|
||||
battlerHoldEffect = GetBattlerHoldEffect(battler, TRUE);
|
||||
|
||||
gSpecialStatuses[battler].changedStatsBattlerId = gBattlerAttacker;
|
||||
|
||||
flags &= ~(MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_MIRROR_ARMOR);
|
||||
|
||||
if (flags & MOVE_EFFECT_CERTAIN)
|
||||
certain++;
|
||||
certain = TRUE;
|
||||
flags &= ~MOVE_EFFECT_CERTAIN;
|
||||
|
||||
if (flags & STAT_CHANGE_NOT_PROTECT_AFFECTED)
|
||||
notProtectAffected++;
|
||||
flags &= ~STAT_CHANGE_NOT_PROTECT_AFFECTED;
|
||||
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId)
|
||||
if (battlerAbility == ABILITY_CONTRARY)
|
||||
{
|
||||
statValue ^= STAT_BUFF_NEGATIVE;
|
||||
gBattleScripting.statChanger ^= STAT_BUFF_NEGATIVE;
|
||||
RecordAbilityBattle(battler, battlerAbility);
|
||||
if (flags & STAT_CHANGE_UPDATE_MOVE_EFFECT)
|
||||
{
|
||||
flags &= ~STAT_CHANGE_UPDATE_MOVE_EFFECT;
|
||||
gBattleScripting.moveEffect = ReverseStatChangeMoveEffect(gBattleScripting.moveEffect);
|
||||
}
|
||||
}
|
||||
else if (battlerAbility == ABILITY_SIMPLE)
|
||||
{
|
||||
statValue = (SET_STAT_BUFF_VALUE(GET_STAT_BUFF_VALUE(statValue) * 2)) | ((statValue <= -1) ? STAT_BUFF_NEGATIVE : 0);
|
||||
}
|
||||
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
||||
|
||||
if (statValue <= -1) // Stat decrease.
|
||||
{
|
||||
if (gSideTimers[GET_BATTLER_SIDE(gActiveBattler)].mistTimer
|
||||
&& !certain && gCurrentMove != MOVE_CURSE)
|
||||
if (gSideTimers[GetBattlerSide(battler)].mistTimer
|
||||
&& !certain && gCurrentMove != MOVE_CURSE
|
||||
&& !(battler == gBattlerTarget && GetBattlerAbility(gBattlerAttacker) == ABILITY_INFILTRATOR))
|
||||
{
|
||||
if (flags == STAT_CHANGE_ALLOW_PTR)
|
||||
{
|
||||
if (gSpecialStatuses[gActiveBattler].statLowered)
|
||||
if (gSpecialStatuses[battler].statLowered)
|
||||
{
|
||||
gBattlescriptCurrInstr = BS_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleScriptPush(BS_ptr);
|
||||
gBattleScripting.battler = gActiveBattler;
|
||||
gBattleScripting.battler = battler;
|
||||
gBattlescriptCurrInstr = BattleScript_MistProtected;
|
||||
gSpecialStatuses[gActiveBattler].statLowered = 1;
|
||||
gSpecialStatuses[battler].statLowered = TRUE;
|
||||
}
|
||||
}
|
||||
return STAT_CHANGE_DIDNT_WORK;
|
||||
}
|
||||
else if (gCurrentMove != MOVE_CURSE
|
||||
&& notProtectAffected != TRUE && JumpIfMoveAffectedByProtect(0))
|
||||
&& notProtectAffected != TRUE && JumpIfMoveAffectedByProtect(gCurrentMove))
|
||||
{
|
||||
gBattlescriptCurrInstr = BattleScript_ButItFailed;
|
||||
return STAT_CHANGE_DIDNT_WORK;
|
||||
}
|
||||
else if ((gBattleMons[gActiveBattler].ability == ABILITY_CLEAR_BODY
|
||||
|| gBattleMons[gActiveBattler].ability == ABILITY_WHITE_SMOKE)
|
||||
&& !certain && gCurrentMove != MOVE_CURSE)
|
||||
else if ((battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET
|
||||
|| CanAbilityPreventStatLoss(battlerAbility, GetBattlerAbility(gBattlerAttacker) == ABILITY_INTIMIDATE))
|
||||
&& (!affectsUser || mirrorArmored) && !certain && gCurrentMove != MOVE_CURSE)
|
||||
{
|
||||
if (flags == STAT_CHANGE_ALLOW_PTR)
|
||||
{
|
||||
if (gSpecialStatuses[gActiveBattler].statLowered)
|
||||
if (gSpecialStatuses[battler].statLowered)
|
||||
{
|
||||
gBattlescriptCurrInstr = BS_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleScriptPush(BS_ptr);
|
||||
gBattleScripting.battler = gActiveBattler;
|
||||
gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss;
|
||||
gLastUsedAbility = gBattleMons[gActiveBattler].ability;
|
||||
RecordAbilityBattle(gActiveBattler, gLastUsedAbility);
|
||||
gSpecialStatuses[gActiveBattler].statLowered = 1;
|
||||
gBattleScripting.battler = battler;
|
||||
if (battlerHoldEffect == HOLD_EFFECT_CLEAR_AMULET)
|
||||
{
|
||||
gLastUsedItem = gBattleMons[battler].item;
|
||||
gBattlescriptCurrInstr = BattleScript_ItemNoStatLoss;
|
||||
RecordItemEffectBattle(battler, HOLD_EFFECT_CLEAR_AMULET);
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlerAbility = battler;
|
||||
gBattlescriptCurrInstr = BattleScript_AbilityNoStatLoss;
|
||||
gLastUsedAbility = battlerAbility;
|
||||
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||
}
|
||||
gSpecialStatuses[battler].statLowered = TRUE;
|
||||
}
|
||||
}
|
||||
return STAT_CHANGE_DIDNT_WORK;
|
||||
}
|
||||
else if (gBattleMons[gActiveBattler].ability == ABILITY_KEEN_EYE
|
||||
&& !certain && statId == STAT_ACC)
|
||||
else if ((index = IsFlowerVeilProtected(battler)) && !certain)
|
||||
{
|
||||
if (flags == STAT_CHANGE_ALLOW_PTR)
|
||||
{
|
||||
if (gSpecialStatuses[battler].statLowered)
|
||||
{
|
||||
gBattlescriptCurrInstr = BS_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
BattleScriptPush(BS_ptr);
|
||||
gBattleScripting.battler = battler;
|
||||
gBattlerAbility = index - 1;
|
||||
gBattlescriptCurrInstr = BattleScript_FlowerVeilProtectsRet;
|
||||
gLastUsedAbility = ABILITY_FLOWER_VEIL;
|
||||
gSpecialStatuses[battler].statLowered = TRUE;
|
||||
}
|
||||
}
|
||||
return STAT_CHANGE_DIDNT_WORK;
|
||||
}
|
||||
else if (!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)
|
||||
{
|
||||
BattleScriptPush(BS_ptr);
|
||||
gBattleScripting.battler = gActiveBattler;
|
||||
gBattleScripting.battler = battler;
|
||||
gBattlerAbility = battler;
|
||||
gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss;
|
||||
gLastUsedAbility = gBattleMons[gActiveBattler].ability;
|
||||
RecordAbilityBattle(gActiveBattler, gLastUsedAbility);
|
||||
gLastUsedAbility = battlerAbility;
|
||||
RecordAbilityBattle(battler, gLastUsedAbility);
|
||||
}
|
||||
return STAT_CHANGE_DIDNT_WORK;
|
||||
}
|
||||
else if (gBattleMons[gActiveBattler].ability == ABILITY_HYPER_CUTTER
|
||||
&& !certain && statId == STAT_ATK)
|
||||
else if (battlerAbility == ABILITY_MIRROR_ARMOR && !affectsUser && !mirrorArmored && gBattlerAttacker != gBattlerTarget && battler == gBattlerTarget)
|
||||
{
|
||||
if (flags == STAT_CHANGE_ALLOW_PTR)
|
||||
{
|
||||
SET_STATCHANGER(statId, GET_STAT_BUFF_VALUE(statValue) | STAT_BUFF_NEGATIVE, TRUE);
|
||||
BattleScriptPush(BS_ptr);
|
||||
gBattleScripting.battler = gActiveBattler;
|
||||
gBattlescriptCurrInstr = BattleScript_AbilityNoSpecificStatLoss;
|
||||
gLastUsedAbility = gBattleMons[gActiveBattler].ability;
|
||||
RecordAbilityBattle(gActiveBattler, gLastUsedAbility);
|
||||
gBattleScripting.battler = battler;
|
||||
gBattlerAbility = battler;
|
||||
gBattlescriptCurrInstr = BattleScript_MirrorArmorReflect;
|
||||
RecordAbilityBattle(battler, gBattleMons[battler].ability);
|
||||
}
|
||||
return STAT_CHANGE_DIDNT_WORK;
|
||||
}
|
||||
else if (gBattleMons[gActiveBattler].ability == ABILITY_SHIELD_DUST && flags == 0)
|
||||
else if (battlerAbility == ABILITY_SHIELD_DUST && flags == 0)
|
||||
{
|
||||
RecordAbilityBattle(battler, ABILITY_SHIELD_DUST);
|
||||
return STAT_CHANGE_DIDNT_WORK;
|
||||
}
|
||||
else if (flags == 0 && battlerHoldEffect == HOLD_EFFECT_COVERT_CLOAK)
|
||||
{
|
||||
RecordItemEffectBattle(battler, HOLD_EFFECT_COVERT_CLOAK);
|
||||
return STAT_CHANGE_DIDNT_WORK;
|
||||
}
|
||||
else // try to decrease
|
||||
{
|
||||
statValue = -GET_STAT_BUFF_VALUE(statValue);
|
||||
if (gBattleMons[battler].statStages[statId] == 1)
|
||||
statValue = -1;
|
||||
else if (gBattleMons[battler].statStages[statId] == 2 && statValue < -2)
|
||||
statValue = -2;
|
||||
gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN;
|
||||
index = 1;
|
||||
if (statValue == -2)
|
||||
@@ -11812,20 +11957,36 @@ static u8 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr)
|
||||
gBattleTextBuff2[3] = STRINGID_STATHARSHLY >> 8;
|
||||
index = 4;
|
||||
}
|
||||
else if (statValue <= -3)
|
||||
{
|
||||
gBattleTextBuff2[1] = B_BUFF_STRING;
|
||||
gBattleTextBuff2[2] = STRINGID_SEVERELY & 0xFF;
|
||||
gBattleTextBuff2[3] = STRINGID_SEVERELY >> 8;
|
||||
index = 4;
|
||||
}
|
||||
gBattleTextBuff2[index++] = B_BUFF_STRING;
|
||||
gBattleTextBuff2[index++] = STRINGID_STATFELL;
|
||||
gBattleTextBuff2[index++] = STRINGID_STATFELL >> 8;
|
||||
gBattleTextBuff2[index] = B_BUFF_EOS;
|
||||
|
||||
if (gBattleMons[gActiveBattler].statStages[statId] == MIN_STAT_STAGE)
|
||||
if (gBattleMons[battler].statStages[statId] == MIN_STAT_STAGE)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_DECREASE;
|
||||
}
|
||||
else
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == gActiveBattler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL
|
||||
{
|
||||
gProtectStructs[battler].statFell = TRUE; // Eject pack, lash out
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL
|
||||
}
|
||||
}
|
||||
}
|
||||
else // stat increase
|
||||
{
|
||||
statValue = GET_STAT_BUFF_VALUE(statValue);
|
||||
if (gBattleMons[battler].statStages[statId] == 11)
|
||||
statValue = 1;
|
||||
else if (gBattleMons[battler].statStages[statId] == 10 && statValue > 2)
|
||||
statValue = 2;
|
||||
gBattleTextBuff2[0] = B_BUFF_PLACEHOLDER_BEGIN;
|
||||
index = 1;
|
||||
if (statValue == 2)
|
||||
@@ -11835,22 +11996,55 @@ static u8 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr)
|
||||
gBattleTextBuff2[3] = STRINGID_STATSHARPLY >> 8;
|
||||
index = 4;
|
||||
}
|
||||
else if (statValue >= 3)
|
||||
{
|
||||
gBattleTextBuff2[1] = B_BUFF_STRING;
|
||||
gBattleTextBuff2[2] = STRINGID_DRASTICALLY & 0xFF;
|
||||
gBattleTextBuff2[3] = STRINGID_DRASTICALLY >> 8;
|
||||
index = 4;
|
||||
}
|
||||
gBattleTextBuff2[index++] = B_BUFF_STRING;
|
||||
gBattleTextBuff2[index++] = STRINGID_STATROSE;
|
||||
gBattleTextBuff2[index++] = STRINGID_STATROSE >> 8;
|
||||
gBattleTextBuff2[index] = B_BUFF_EOS;
|
||||
|
||||
if (gBattleMons[gActiveBattler].statStages[statId] == MAX_STAT_STAGE)
|
||||
if (gBattleMons[battler].statStages[statId] == MAX_STAT_STAGE)
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STAT_WONT_INCREASE;
|
||||
}
|
||||
else
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == gActiveBattler); // B_MSG_ATTACKER_STAT_ROSE or B_MSG_DEFENDER_STAT_ROSE
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == battler);
|
||||
gProtectStructs[battler].statRaised = TRUE;
|
||||
|
||||
// check mirror herb
|
||||
for (index = 0; index < gBattlersCount; index++)
|
||||
{
|
||||
if (GetBattlerSide(index) == GetBattlerSide(battler))
|
||||
continue; // Only triggers on opposing side
|
||||
if (GetBattlerAbility(index) == ABILITY_OPPORTUNIST
|
||||
&& gProtectStructs[battler].activateOpportunist == 0) // don't activate opportunist on other mon's opportunist raises
|
||||
{
|
||||
gProtectStructs[index].activateOpportunist = 2; // set stats to copy
|
||||
gQueuedStatBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk
|
||||
gQueuedStatBoosts[index].statChanges[statId - 1] += statValue; // cumulative in case of multiple opponent boosts
|
||||
}
|
||||
else if (GetBattlerHoldEffect(index, TRUE) == HOLD_EFFECT_MIRROR_HERB
|
||||
&& gBattleMons[index].statStages[statId] < MAX_STAT_STAGE)
|
||||
{
|
||||
gProtectStructs[index].eatMirrorHerb = 1;
|
||||
gQueuedStatBoosts[index].stats |= (1 << (statId - 1)); // -1 to start at atk
|
||||
gQueuedStatBoosts[index].statChanges[statId - 1] = statValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gBattleMons[gActiveBattler].statStages[statId] += statValue;
|
||||
if (gBattleMons[gActiveBattler].statStages[statId] < MIN_STAT_STAGE)
|
||||
gBattleMons[gActiveBattler].statStages[statId] = MIN_STAT_STAGE;
|
||||
if (gBattleMons[gActiveBattler].statStages[statId] > MAX_STAT_STAGE)
|
||||
gBattleMons[gActiveBattler].statStages[statId] = MAX_STAT_STAGE;
|
||||
gBattleMons[battler].statStages[statId] += statValue;
|
||||
if (gBattleMons[battler].statStages[statId] < MIN_STAT_STAGE)
|
||||
gBattleMons[battler].statStages[statId] = MIN_STAT_STAGE;
|
||||
if (gBattleMons[battler].statStages[statId] > MAX_STAT_STAGE)
|
||||
gBattleMons[battler].statStages[statId] = MAX_STAT_STAGE;
|
||||
|
||||
if (gBattleCommunication[MULTISTRING_CHOOSER] == B_MSG_STAT_WONT_INCREASE && flags & STAT_CHANGE_ALLOW_PTR)
|
||||
gMoveResultFlags |= MOVE_RESULT_MISSED;
|
||||
@@ -11864,18 +12058,15 @@ static u8 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr)
|
||||
static void Cmd_statbuffchange(void)
|
||||
{
|
||||
CMD_ARGS(u16 flags, const u8 *failInstr);
|
||||
|
||||
u16 flags = cmd->flags;
|
||||
const u8 *ptrBefore = gBattlescriptCurrInstr;
|
||||
const u8 *failInstr = cmd->failInstr;
|
||||
|
||||
if (ChangeStatBuffs(gBattleScripting.statChanger & 0xF0, GET_STAT_BUFF_ID(gBattleScripting.statChanger), flags, failInstr) == STAT_CHANGE_WORKED)
|
||||
{
|
||||
if (ChangeStatBuffs(GET_STAT_BUFF_VALUE_WITH_SIGN(gBattleScripting.statChanger), GET_STAT_BUFF_ID(gBattleScripting.statChanger), flags, failInstr) == STAT_CHANGE_WORKED)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattlescriptCurrInstr = ptrBefore;
|
||||
}
|
||||
else if (gBattlescriptCurrInstr == ptrBefore) // Prevent infinite looping.
|
||||
gBattlescriptCurrInstr = failInstr;
|
||||
}
|
||||
|
||||
// Haze
|
||||
@@ -15493,3 +15684,22 @@ void BS_CheckParentalBondCounter(void)
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
|
||||
static bool8 CanAbilityPreventStatLoss(u16 abilityDef, bool8 byIntimidate)
|
||||
{
|
||||
switch (abilityDef)
|
||||
{
|
||||
case ABILITY_CLEAR_BODY:
|
||||
case ABILITY_FULL_METAL_BODY:
|
||||
case ABILITY_WHITE_SMOKE:
|
||||
return TRUE;
|
||||
case ABILITY_INNER_FOCUS:
|
||||
case ABILITY_SCRAPPY:
|
||||
case ABILITY_OWN_TEMPO:
|
||||
case ABILITY_OBLIVIOUS:
|
||||
if (byIntimidate && (B_UPDATED_INTIMIDATE >= GEN_8))
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user