mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2025-03-14 01:32:23 +01:00
merge with be
This commit is contained in:
commit
a2d885c0d4
@ -1242,13 +1242,13 @@ BattleScript_ShellSmashTryDef::
|
||||
setbyte sSTAT_ANIM_PLAYED, FALSE
|
||||
playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE | STAT_CHANGE_CANT_PREVENT
|
||||
setstatchanger STAT_DEF, 1, TRUE
|
||||
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_ShellSmashTrySpDef
|
||||
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR | MOVE_EFFECT_CERTAIN, BattleScript_ShellSmashTrySpDef
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTrySpDef
|
||||
printfromtable gStatUpStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
BattleScript_ShellSmashTrySpDef:
|
||||
setstatchanger STAT_SPDEF, 1, TRUE
|
||||
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR, BattleScript_ShellSmashTryAttack
|
||||
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_BUFF_ALLOW_PTR | MOVE_EFFECT_CERTAIN, BattleScript_ShellSmashTryAttack
|
||||
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_INCREASE, BattleScript_ShellSmashTryAttack
|
||||
printfromtable gStatUpStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
|
@ -192,7 +192,8 @@ struct SideTimer
|
||||
u8 safeguardTimer;
|
||||
u8 safeguardBattlerId;
|
||||
u8 followmeTimer;
|
||||
u8 followmeTarget;
|
||||
u8 followmeTarget:3;
|
||||
u8 followmePowder:1; // Rage powder, does not affect grass type pokemon.
|
||||
u8 spikesAmount;
|
||||
u8 toxicSpikesAmount;
|
||||
u8 stealthRockAmount;
|
||||
|
@ -47,6 +47,7 @@ struct TypePower
|
||||
extern const struct TypePower gNaturalGiftTable[];
|
||||
|
||||
void HandleAction_ThrowBall(void);
|
||||
bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide);
|
||||
void HandleAction_UseMove(void);
|
||||
void HandleAction_Switch(void);
|
||||
void HandleAction_UseItem(void);
|
||||
|
@ -283,7 +283,7 @@ static const s8 sAiAbilityRatings[ABILITIES_COUNT] =
|
||||
[ABILITY_GORILLA_TACTICS] = 4,
|
||||
};
|
||||
|
||||
static const u16 sEncouragedEncoreEffects[] =
|
||||
static const u16 sEncouragedEncoreEffects[] =
|
||||
{
|
||||
EFFECT_DREAM_EATER,
|
||||
EFFECT_ATTACK_UP,
|
||||
@ -365,7 +365,7 @@ static const u16 sDiscouragedPowerfulMoveEffects[] =
|
||||
0xFFFF
|
||||
};
|
||||
|
||||
static const u16 sIgnoreMoldBreakerMoves[] =
|
||||
static const u16 sIgnoreMoldBreakerMoves[] =
|
||||
{
|
||||
MOVE_MOONGEIST_BEAM,
|
||||
MOVE_SUNSTEEL_STRIKE,
|
||||
@ -381,7 +381,7 @@ static const u16 sIgnoreMoldBreakerMoves[] =
|
||||
#endif
|
||||
};
|
||||
|
||||
static const u16 sInstructBannedMoves[] =
|
||||
static const u16 sInstructBannedMoves[] =
|
||||
{
|
||||
MOVE_INSTRUCT,
|
||||
MOVE_BIDE,
|
||||
@ -410,7 +410,7 @@ static const u16 sInstructBannedMoves[] =
|
||||
MOVE_SOLAR_BLADE,
|
||||
};
|
||||
|
||||
static const u16 sRechargeMoves[] =
|
||||
static const u16 sRechargeMoves[] =
|
||||
{
|
||||
MOVE_HYPER_BEAM,
|
||||
MOVE_BLAST_BURN,
|
||||
@ -424,7 +424,7 @@ static const u16 sRechargeMoves[] =
|
||||
MOVE_ETERNABEAM,
|
||||
};
|
||||
|
||||
static const u16 sOtherMoveCallingMoves[] =
|
||||
static const u16 sOtherMoveCallingMoves[] =
|
||||
{
|
||||
MOVE_ASSIST,
|
||||
MOVE_COPYCAT,
|
||||
@ -640,7 +640,7 @@ bool32 IsAffectedByPowder(u8 battler, u16 ability, u16 holdEffect)
|
||||
{
|
||||
if ((B_POWDER_GRASS >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS))
|
||||
|| ability == ABILITY_OVERCOAT
|
||||
|| GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_SAFETY_GOOGLES)
|
||||
|| holdEffect == HOLD_EFFECT_SAFETY_GOOGLES)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
@ -929,7 +929,7 @@ u8 AI_GetMoveEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef)
|
||||
gMoveResultFlags = 0;
|
||||
gCurrentMove = move;
|
||||
effectivenessMultiplier = AI_GetTypeEffectiveness(gCurrentMove, battlerAtk, battlerDef);
|
||||
|
||||
|
||||
switch (effectivenessMultiplier)
|
||||
{
|
||||
case UQ_4_12(0.0):
|
||||
@ -1047,7 +1047,7 @@ bool32 CanTargetFaintAiWithMod(u8 battlerDef, u8 battlerAtk, s32 hpMod, s32 dmgM
|
||||
u32 hpCheck = gBattleMons[battlerAtk].hp + hpMod;
|
||||
if (dmgMod)
|
||||
dmg *= dmgMod;
|
||||
|
||||
|
||||
if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && !(unusable & gBitTable[i]) && dmg >= hpCheck)
|
||||
{
|
||||
return TRUE;
|
||||
@ -1091,22 +1091,22 @@ s32 AI_GetAbility(u32 battlerId)
|
||||
u16 AI_GetHoldEffect(u32 battlerId)
|
||||
{
|
||||
u32 holdEffect;
|
||||
|
||||
|
||||
if (!IsBattlerAIControlled(battlerId))
|
||||
holdEffect = BATTLE_HISTORY->itemEffects[battlerId];
|
||||
else
|
||||
holdEffect = GetBattlerHoldEffect(battlerId, FALSE);
|
||||
|
||||
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE)
|
||||
return holdEffect;
|
||||
|
||||
|
||||
if (gStatuses3[battlerId] & STATUS3_EMBARGO)
|
||||
return HOLD_EFFECT_NONE;
|
||||
if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM)
|
||||
return HOLD_EFFECT_NONE;
|
||||
if (AI_GetAbility(battlerId) == ABILITY_KLUTZ && !(gStatuses3[battlerId] & STATUS3_GASTRO_ACID))
|
||||
return HOLD_EFFECT_NONE;
|
||||
|
||||
|
||||
return holdEffect;
|
||||
}
|
||||
|
||||
@ -1123,7 +1123,7 @@ bool32 AI_IsTerrainAffected(u8 battlerId, u32 flags)
|
||||
bool32 AI_IsBattlerGrounded(u8 battlerId)
|
||||
{
|
||||
u32 holdEffect = AI_GetHoldEffect(battlerId);
|
||||
|
||||
|
||||
if (holdEffect == HOLD_EFFECT_IRON_BALL)
|
||||
return TRUE;
|
||||
else if (gFieldStatuses & STATUS_FIELD_GRAVITY)
|
||||
@ -1149,10 +1149,10 @@ bool32 AI_IsBattlerGrounded(u8 battlerId)
|
||||
bool32 DoesBattlerIgnoreAbilityChecks(u16 atkAbility, u16 move)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE)
|
||||
return FALSE; // AI handicap flag: doesn't understand ability suppression concept
|
||||
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(sIgnoreMoldBreakerMoves); i++)
|
||||
{
|
||||
if (move == sIgnoreMoldBreakerMoves[i])
|
||||
@ -1172,7 +1172,7 @@ bool32 AI_WeatherHasEffect(void)
|
||||
u32 i;
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE)
|
||||
return TRUE; // AI doesn't understand weather supression (handicap)
|
||||
|
||||
|
||||
// need to manually check since we don't necessarily know opponent ability
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
@ -1186,7 +1186,7 @@ bool32 AI_WeatherHasEffect(void)
|
||||
bool32 IsAromaVeilProtectedMove(u16 move)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
|
||||
switch (move)
|
||||
{
|
||||
case MOVE_DISABLE:
|
||||
@ -1273,7 +1273,7 @@ bool32 IsMoveRedirectionPrevented(u16 move, u16 atkAbility)
|
||||
{
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_NEGATE_UNAWARE)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (move == MOVE_SKY_DROP
|
||||
|| move == MOVE_SNIPE_SHOT
|
||||
|| atkAbility == ABILITY_PROPELLER_TAIL
|
||||
@ -1287,7 +1287,7 @@ u32 AI_GetMoveAccuracy(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbil
|
||||
{
|
||||
u32 calc, moveAcc, atkParam, defParam;
|
||||
s8 buff, accStage, evasionStage;
|
||||
|
||||
|
||||
gPotentialItemEffectBattler = battlerDef;
|
||||
accStage = gBattleMons[battlerAtk].statStages[STAT_ACC];
|
||||
evasionStage = gBattleMons[battlerDef].statStages[STAT_EVASION];
|
||||
@ -1366,25 +1366,25 @@ bool32 IsMoveEncouragedToHit(u8 battlerAtk, u8 battlerDef, u16 move)
|
||||
{
|
||||
if (IsSemiInvulnerable(battlerDef, move))
|
||||
return FALSE;
|
||||
|
||||
|
||||
//TODO - anticipate protect move?
|
||||
|
||||
|
||||
// always hits
|
||||
if (gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS || gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk)
|
||||
return TRUE;
|
||||
|
||||
|
||||
if (AI_GetAbility(battlerDef) == ABILITY_NO_GUARD || AI_GetAbility(battlerAtk) == ABILITY_NO_GUARD)
|
||||
return TRUE;
|
||||
|
||||
|
||||
if (B_TOXIC_NEVER_MISS >= GEN_6 && gBattleMoves[move].effect == EFFECT_TOXIC && IS_BATTLER_OF_TYPE(battlerAtk, TYPE_POISON))
|
||||
return TRUE;
|
||||
|
||||
|
||||
// discouraged from hitting
|
||||
if (AI_WeatherHasEffect() && (gBattleWeather & WEATHER_SUN_ANY)
|
||||
&& (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE))
|
||||
return FALSE;
|
||||
|
||||
// increased accuracy but don't always hit
|
||||
|
||||
// increased accuracy but don't always hit
|
||||
if ((AI_WeatherHasEffect() &&
|
||||
(((gBattleWeather & WEATHER_RAIN_ANY) && (gBattleMoves[move].effect == EFFECT_THUNDER || gBattleMoves[move].effect == EFFECT_HURRICANE))
|
||||
|| (((gBattleWeather & WEATHER_HAIL_ANY) && move == MOVE_BLIZZARD))))
|
||||
@ -1394,23 +1394,23 @@ bool32 IsMoveEncouragedToHit(u8 battlerAtk, u8 battlerDef, u16 move)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 ShouldTryOHKO(u8 battlerAtk, u8 battlerDef, u16 atkAbility, u16 defAbility, u32 accuracy, u16 move)
|
||||
{
|
||||
u32 holdEffect = AI_GetHoldEffect(battlerDef);
|
||||
|
||||
|
||||
gPotentialItemEffectBattler = battlerDef;
|
||||
if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < GetBattlerHoldEffectParam(battlerDef))
|
||||
return FALSE; //probabilistically speaking, focus band should activate so dont OHKO
|
||||
else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && AtMaxHp(battlerDef))
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (!DoesBattlerIgnoreAbilityChecks(atkAbility, move) && defAbility == ABILITY_STURDY)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if ((((gStatuses3[battlerDef] & STATUS3_ALWAYS_HITS)
|
||||
&& gDisableStructs[battlerDef].battlerWithSureHit == battlerAtk)
|
||||
|| atkAbility == ABILITY_NO_GUARD || defAbility == ABILITY_NO_GUARD)
|
||||
@ -1433,7 +1433,7 @@ bool32 ShouldSetSandstorm(u8 battler, u16 ability, u16 holdEffect)
|
||||
return FALSE;
|
||||
else if (gBattleWeather & WEATHER_SANDSTORM_ANY)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (ability == ABILITY_SAND_VEIL
|
||||
|| ability == ABILITY_SAND_RUSH
|
||||
|| ability == ABILITY_SAND_FORCE
|
||||
@ -1458,7 +1458,7 @@ bool32 ShouldSetHail(u8 battler, u16 ability, u16 holdEffect)
|
||||
return FALSE;
|
||||
else if (gBattleWeather & WEATHER_HAIL_ANY)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (ability == ABILITY_SNOW_CLOAK
|
||||
|| ability == ABILITY_ICE_BODY
|
||||
|| ability == ABILITY_FORECAST
|
||||
@ -1472,7 +1472,7 @@ bool32 ShouldSetHail(u8 battler, u16 ability, u16 holdEffect)
|
||||
|| HasMoveEffect(battler, EFFECT_WEATHER_BALL))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -1482,7 +1482,7 @@ bool32 ShouldSetRain(u8 battlerAtk, u16 atkAbility, u16 holdEffect)
|
||||
return FALSE;
|
||||
else if (gBattleWeather & WEATHER_RAIN_ANY)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA
|
||||
&& (atkAbility == ABILITY_SWIFT_SWIM
|
||||
|| atkAbility == ABILITY_FORECAST
|
||||
@ -1505,7 +1505,7 @@ bool32 ShouldSetSun(u8 battlerAtk, u16 atkAbility, u16 holdEffect)
|
||||
return FALSE;
|
||||
else if (gBattleWeather & WEATHER_SUN_ANY)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA
|
||||
&& (atkAbility == ABILITY_CHLOROPHYLL
|
||||
|| atkAbility == ABILITY_FLOWER_GIFT
|
||||
@ -1533,13 +1533,13 @@ void ProtectChecks(u8 battlerAtk, u8 battlerDef, u16 move, u16 predictedMove, s1
|
||||
u16 predictedEffect = gBattleMoves[predictedMove].effect;
|
||||
u8 defAbility = AI_GetAbility(battlerDef);
|
||||
u32 uses = gDisableStructs[battlerAtk].protectUses;
|
||||
|
||||
|
||||
/*if (GetMoveResultFlags(predictedMove) & (MOVE_RESULT_NO_EFFECT | MOVE_RESULT_MISSED))
|
||||
{
|
||||
(*score) -= 5;
|
||||
return;
|
||||
}*/
|
||||
|
||||
|
||||
if (uses == 0)
|
||||
{
|
||||
if (predictedMove != MOVE_NONE && predictedMove != 0xFFFF && !IS_MOVE_STATUS(predictedMove))
|
||||
@ -1561,7 +1561,7 @@ void ProtectChecks(u8 battlerAtk, u8 battlerDef, u16 move, u16 predictedMove, s1
|
||||
{
|
||||
(*score)--;
|
||||
}
|
||||
|
||||
|
||||
if (gBattleMons[battlerDef].status1 & STATUS1_TOXIC_POISON
|
||||
|| gBattleMons[battlerDef].status2 & (STATUS2_CURSED | STATUS2_INFATUATION)
|
||||
|| gStatuses3[battlerDef] & (STATUS3_PERISH_SONG | STATUS3_LEECHSEED | STATUS3_YAWN))
|
||||
@ -1578,10 +1578,10 @@ bool32 ShouldLowerStat(u8 battler, u16 battlerAbility, u8 stat)
|
||||
|| battlerAbility == ABILITY_WHITE_SMOKE
|
||||
|| battlerAbility == ABILITY_FULL_METAL_BODY)
|
||||
return FALSE;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -1595,7 +1595,7 @@ bool32 BattlerStatCanRise(u8 battler, u16 battlerAbility, u8 stat)
|
||||
|
||||
bool32 AreBattlersStatsMaxed(u8 battlerId)
|
||||
{
|
||||
u32 i;
|
||||
u32 i;
|
||||
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
|
||||
{
|
||||
if (gBattleMons[battlerId].statStages[i] < MAX_STAT_STAGE)
|
||||
@ -1607,7 +1607,7 @@ bool32 AreBattlersStatsMaxed(u8 battlerId)
|
||||
bool32 AnyStatIsRaised(u8 battlerId)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
|
||||
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
|
||||
{
|
||||
if (gBattleMons[battlerId].statStages[i] > DEFAULT_STAT_STAGE)
|
||||
@ -1747,10 +1747,10 @@ bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility)
|
||||
bool32 CanAttackerFaintTarget(u8 battlerAtk, u8 battlerDef, u8 index, u8 numHits)
|
||||
{
|
||||
s32 dmg = AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][index];
|
||||
|
||||
|
||||
if (numHits)
|
||||
dmg *= numHits;
|
||||
|
||||
|
||||
if (gBattleMons[battlerDef].hp <= dmg)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
@ -1776,7 +1776,7 @@ bool32 HasOnlyMovesWithSplit(u32 battlerId, u32 split, bool32 onlyOffensive)
|
||||
if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && GetBattleMoveSplit(moves[i]) != split)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1841,12 +1841,12 @@ bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32
|
||||
s32 i;
|
||||
u16 *moves = GetMovesArray(battlerAtk);
|
||||
u8 moveLimitations = CheckMoveLimitations(battlerAtk, 0, 0xFF);
|
||||
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i] == MOVE_NONE || moves[i] == 0xFFFF)
|
||||
continue;
|
||||
|
||||
|
||||
if (!(gBitTable[i] & moveLimitations))
|
||||
{
|
||||
if (ignoreStatus && IS_MOVE_STATUS(moves[i]))
|
||||
@ -1854,12 +1854,12 @@ bool32 HasMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef, u8 accCheck, bool32
|
||||
else if ((!IS_MOVE_STATUS(moves[i]) && gBattleMoves[moves[i]].accuracy == 0)
|
||||
|| gBattleMoves[moves[i]].target & (MOVE_TARGET_USER | MOVE_TARGET_OPPONENTS_FIELD))
|
||||
continue;
|
||||
|
||||
|
||||
if (AI_GetMoveAccuracy(battlerAtk, battlerDef, atkAbility, defAbility, atkHoldEffect, defHoldEffect, moves[i]) <= accCheck)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -1868,7 +1868,7 @@ bool32 HasSleepMoveWithLowAccuracy(u8 battlerAtk, u8 battlerDef)
|
||||
u8 moveLimitations = CheckMoveLimitations(battlerAtk, 0, 0xFF);
|
||||
u32 i;
|
||||
u16 *moves = GetMovesArray(battlerAtk);
|
||||
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i] == MOVE_NONE)
|
||||
@ -2067,7 +2067,7 @@ bool32 HasDamagingMove(u8 battlerId)
|
||||
{
|
||||
u32 i;
|
||||
u16 *moves = GetMovesArray(battlerId);
|
||||
|
||||
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
if (moves[i] != MOVE_NONE && moves[i] != 0xFFFF && gBattleMoves[moves[i]].power != 0)
|
||||
@ -2106,7 +2106,7 @@ bool32 IsInstructBannedMove(u16 move)
|
||||
bool32 IsEncoreEncouragedEffect(u16 moveEffect)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(sEncouragedEncoreEffects); i++)
|
||||
{
|
||||
if (moveEffect == sEncouragedEncoreEffects[i])
|
||||
@ -2208,10 +2208,10 @@ static u32 GetTrapDamage(u8 battlerId)
|
||||
static u32 GetPoisonDamage(u8 battlerId)
|
||||
{
|
||||
u32 damage = 0;
|
||||
|
||||
|
||||
if (AI_GetAbility(battlerId) == ABILITY_POISON_HEAL)
|
||||
return damage;
|
||||
|
||||
|
||||
if (gBattleMons[battlerId].status1 & STATUS1_POISON)
|
||||
{
|
||||
damage = gBattleMons[battlerId].maxHP / 8;
|
||||
@ -2260,7 +2260,7 @@ static u32 GetWeatherDamage(u8 battlerId)
|
||||
u32 damage = 0;
|
||||
if (!AI_WeatherHasEffect())
|
||||
return 0;
|
||||
|
||||
|
||||
if (gBattleWeather & WEATHER_SANDSTORM_ANY)
|
||||
{
|
||||
if (BattlerAffectedBySandstorm(battlerId, ability)
|
||||
@ -2289,17 +2289,17 @@ static u32 GetWeatherDamage(u8 battlerId)
|
||||
u32 GetBattlerSecondaryDamage(u8 battlerId)
|
||||
{
|
||||
u32 secondaryDamage;
|
||||
|
||||
|
||||
if (AI_GetAbility(battlerId) == ABILITY_MAGIC_GUARD)
|
||||
return FALSE;
|
||||
|
||||
|
||||
secondaryDamage = GetLeechSeedDamage(battlerId)
|
||||
+ GetNightmareDamage(battlerId)
|
||||
+ GetCurseDamage(battlerId)
|
||||
+ GetTrapDamage(battlerId)
|
||||
+ GetPoisonDamage(battlerId)
|
||||
+ GetWeatherDamage(battlerId);
|
||||
|
||||
|
||||
return secondaryDamage;
|
||||
}
|
||||
|
||||
@ -2323,7 +2323,7 @@ bool32 BattlerWillFaintFromSecondaryDamage(u8 battler, u16 ability)
|
||||
static bool32 AnyUsefulStatIsRaised(u8 battler)
|
||||
{
|
||||
u8 statId;
|
||||
|
||||
|
||||
for (statId = STAT_ATK; statId < NUM_BATTLE_STATS; statId++)
|
||||
{
|
||||
if (gBattleMons[battler].statStages[statId] > DEFAULT_STAT_STAGE)
|
||||
@ -2353,17 +2353,17 @@ static bool32 PartyBattlerShouldAvoidHazards(u8 currBattler, u8 switchBattler)
|
||||
u16 ability = GetMonAbility(mon); // we know our own party data
|
||||
u16 holdEffect = GetBattlerHoldEffect(GetMonData(mon, MON_DATA_HELD_ITEM), TRUE);
|
||||
u32 flags = gSideStatuses[GetBattlerSide(currBattler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES);
|
||||
|
||||
|
||||
if (flags == 0)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (ability == ABILITY_MAGIC_GUARD || ability == ABILITY_LEVITATE
|
||||
|| holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (flags & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK) && GetMonData(mon, MON_DATA_HP) < (GetMonData(mon, MON_DATA_MAX_HP) / 8))
|
||||
return TRUE;
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -2378,9 +2378,9 @@ bool32 ShouldPivot(u8 battlerAtk, u8 battlerDef, u16 defAbility, u16 move, u8 mo
|
||||
u8 backupBattler = gActiveBattler;
|
||||
bool32 shouldSwitch;
|
||||
u8 battlerToSwitch;
|
||||
|
||||
|
||||
gActiveBattler = battlerAtk;
|
||||
shouldSwitch = ShouldSwitch();
|
||||
shouldSwitch = ShouldSwitch();
|
||||
battlerToSwitch = *(gBattleStruct->AI_monToSwitchIntoId + gActiveBattler);
|
||||
gActiveBattler = backupBattler;
|
||||
|
||||
@ -2558,7 +2558,7 @@ bool32 CanKnockOffItem(u8 battler, u16 item)
|
||||
#endif
|
||||
)) && GetBattlerSide(battler) == B_SIDE_PLAYER)
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (AI_GetAbility(battler) == ABILITY_STICKY_HOLD)
|
||||
return FALSE;
|
||||
|
||||
@ -2573,7 +2573,7 @@ bool32 IsBattlerIncapacitated(u8 battler, u16 ability)
|
||||
{
|
||||
if ((gBattleMons[battler].status1 & STATUS1_FREEZE) && !HasThawingMove(battler))
|
||||
return TRUE; // if battler has thawing move we assume they will definitely use it, and thus being frozen should be neglected
|
||||
|
||||
|
||||
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
|
||||
return TRUE;
|
||||
|
||||
@ -2686,7 +2686,7 @@ bool32 AI_CanConfuse(u8 battlerAtk, u8 battlerDef, u16 defAbility, u8 battlerAtk
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -2767,7 +2767,7 @@ bool32 ShouldTrap(u8 battlerAtk, u8 battlerDef, u16 move)
|
||||
{
|
||||
if (BattlerWillFaintFromSecondaryDamage(battlerDef, AI_DATA->defAbility))
|
||||
return TRUE; // battler is taking secondary damage with low HP
|
||||
|
||||
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_STALL)
|
||||
{
|
||||
if (!CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
@ -2781,12 +2781,12 @@ bool32 ShouldFakeOut(u8 battlerAtk, u8 battlerDef, u16 move)
|
||||
{
|
||||
if (AI_DATA->atkHoldEffect == HOLD_EFFECT_CHOICE_BAND && CountUsablePartyMons(battlerAtk) == 0)
|
||||
return FALSE; // don't lock attacker into fake out if can't switch out
|
||||
|
||||
|
||||
if (gDisableStructs[battlerAtk].isFirstTurn
|
||||
&& ShouldTryToFlinch(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, move)
|
||||
&& !DoesSubstituteBlockMove(battlerAtk, battlerDef, move))
|
||||
return TRUE;
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -2814,12 +2814,12 @@ bool32 AnyPartyMemberStatused(u8 battlerId, bool32 checkSoundproof)
|
||||
{
|
||||
struct Pokemon *party;
|
||||
u32 i;
|
||||
|
||||
|
||||
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
else
|
||||
party = gEnemyParty;
|
||||
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (checkSoundproof && GetMonAbility(&party[i]) == ABILITY_SOUNDPROOF)
|
||||
@ -2863,21 +2863,21 @@ bool32 ShouldUseRecoilMove(u8 battlerAtk, u8 battlerDef, u32 recoilDmg, u8 moveI
|
||||
else
|
||||
return FALSE; //Not as good to use move if you'll faint and not win
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool32 ShouldAbsorb(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage)
|
||||
{
|
||||
{
|
||||
if (move == 0xFFFF || GetWhoStrikesFirst(battlerAtk, gBattlerTarget, TRUE) == 0)
|
||||
{
|
||||
// using item or user goes first
|
||||
u8 healPercent = (gBattleMoves[move].argument == 0) ? 50 : gBattleMoves[move].argument;
|
||||
s32 healDmg = (healPercent * damage) / 100;
|
||||
|
||||
|
||||
if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK)
|
||||
healDmg = 0;
|
||||
|
||||
|
||||
if (CanTargetFaintAi(battlerDef, battlerAtk)
|
||||
&& !CanTargetFaintAiWithMod(battlerDef, battlerAtk, healDmg, 0))
|
||||
return TRUE; // target can faint attacker unless they heal
|
||||
@ -2890,7 +2890,7 @@ bool32 ShouldAbsorb(u8 battlerAtk, u8 battlerDef, u16 move, s32 damage)
|
||||
if (!CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -2953,7 +2953,7 @@ bool32 IsValidDoubleBattle(u8 battlerAtk)
|
||||
u16 GetAllyChosenMove(void)
|
||||
{
|
||||
u8 partnerBattler = BATTLE_PARTNER(sBattler_AI);
|
||||
|
||||
|
||||
if (!IsBattlerAlive(partnerBattler) || !IsBattlerAIControlled(partnerBattler))
|
||||
return MOVE_NONE; // TODO: prediction?
|
||||
else if (partnerBattler > sBattler_AI) // Battler with the lower id chooses the move first.
|
||||
@ -2966,7 +2966,7 @@ bool32 IsTargetingPartner(u8 battlerAtk, u8 battlerDef)
|
||||
{
|
||||
if ((battlerAtk & BIT_SIDE) == (battlerDef & BIT_SIDE))
|
||||
return TRUE;
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -2975,7 +2975,7 @@ bool32 DoesPartnerHaveSameMoveEffect(u8 battlerAtkPartner, u8 battlerDef, u16 mo
|
||||
{
|
||||
if (!IsDoubleBattle())
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (gBattleMoves[move].effect == gBattleMoves[partnerMove].effect
|
||||
&& gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE
|
||||
&& gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef)
|
||||
@ -2990,7 +2990,7 @@ bool32 PartnerHasSameMoveEffectWithoutTarget(u8 battlerAtkPartner, u16 move, u16
|
||||
{
|
||||
if (!IsDoubleBattle())
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (gBattleMoves[move].effect == gBattleMoves[partnerMove].effect
|
||||
&& gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE)
|
||||
return TRUE;
|
||||
@ -3002,7 +3002,7 @@ bool32 PartnerMoveEffectIsStatusSameTarget(u8 battlerAtkPartner, u8 battlerDef,
|
||||
{
|
||||
if (!IsDoubleBattle())
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE
|
||||
&& gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef
|
||||
&& (gBattleMoves[partnerMove].effect == EFFECT_SLEEP
|
||||
@ -3020,14 +3020,14 @@ bool32 PartnerMoveEffectIsWeather(u8 battlerAtkPartner, u16 partnerMove)
|
||||
{
|
||||
if (!IsDoubleBattle())
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE
|
||||
&& (gBattleMoves[partnerMove].effect == EFFECT_SUNNY_DAY
|
||||
|| gBattleMoves[partnerMove].effect == EFFECT_RAIN_DANCE
|
||||
|| gBattleMoves[partnerMove].effect == EFFECT_SANDSTORM
|
||||
|| gBattleMoves[partnerMove].effect == EFFECT_HAIL))
|
||||
return TRUE;
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -3036,14 +3036,14 @@ bool32 PartnerMoveEffectIsTerrain(u8 battlerAtkPartner, u16 partnerMove)
|
||||
{
|
||||
if (!IsDoubleBattle())
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE
|
||||
&& (gBattleMoves[partnerMove].effect == EFFECT_GRASSY_TERRAIN
|
||||
|| gBattleMoves[partnerMove].effect == EFFECT_MISTY_TERRAIN
|
||||
|| gBattleMoves[partnerMove].effect == EFFECT_ELECTRIC_TERRAIN
|
||||
|| gBattleMoves[partnerMove].effect == EFFECT_PSYCHIC_TERRAIN))
|
||||
return TRUE;
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -3052,7 +3052,7 @@ bool32 PartnerMoveIs(u8 battlerAtkPartner, u16 partnerMove, u16 moveCheck)
|
||||
{
|
||||
if (!IsDoubleBattle())
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE && partnerMove == moveCheck)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
@ -3063,7 +3063,7 @@ bool32 PartnerMoveIsSameAsAttacker(u8 battlerAtkPartner, u8 battlerDef, u16 move
|
||||
{
|
||||
if (!IsDoubleBattle())
|
||||
return FALSE;
|
||||
|
||||
|
||||
if (gChosenMoveByBattler[battlerAtkPartner] != MOVE_NONE && move == partnerMove && gBattleStruct->moveTarget[battlerAtkPartner] == battlerDef)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
@ -3088,7 +3088,7 @@ bool32 ShouldUseWishAromatherapy(u8 battlerAtk, u8 battlerDef, u16 move)
|
||||
bool32 needHealing = FALSE;
|
||||
|
||||
GetAIPartyIndexes(battlerAtk, &firstId, &lastId);
|
||||
|
||||
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
else
|
||||
@ -3208,12 +3208,12 @@ bool32 IsPartyFullyHealedExceptBattler(u8 battlerId)
|
||||
{
|
||||
struct Pokemon *party;
|
||||
u32 i;
|
||||
|
||||
|
||||
if (GetBattlerSide(battlerId) == B_SIDE_PLAYER)
|
||||
party = gPlayerParty;
|
||||
else
|
||||
party = gEnemyParty;
|
||||
|
||||
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
{
|
||||
if (i != gBattlerPartyIndexes[battlerId]
|
||||
@ -3236,7 +3236,7 @@ bool32 PartyHasMoveSplit(u8 battlerId, u8 split)
|
||||
{
|
||||
if (GetMonData(&party[i], MON_DATA_HP, NULL) == 0)
|
||||
continue;
|
||||
|
||||
|
||||
for (j = 0; j < MAX_MON_MOVES; j++)
|
||||
{
|
||||
u16 move = GetMonData(&party[i], MON_DATA_MOVE1 + j, NULL);
|
||||
@ -3281,7 +3281,7 @@ s8 GetAbilityRating(u16 ability)
|
||||
return sAiAbilityRatings[ability];
|
||||
}
|
||||
|
||||
static const u16 sRecycleEncouragedItems[] =
|
||||
static const u16 sRecycleEncouragedItems[] =
|
||||
{
|
||||
ITEM_CHESTO_BERRY,
|
||||
ITEM_LUM_BERRY,
|
||||
@ -3309,15 +3309,15 @@ bool32 IsRecycleEncouragedItem(u16 item)
|
||||
|
||||
// score increases
|
||||
#define STAT_UP_2_STAGE 8
|
||||
#define STAT_UP_STAGE 10
|
||||
#define STAT_UP_STAGE 10
|
||||
void IncreaseStatUpScore(u8 battlerAtk, u8 battlerDef, u8 statId, s16 *score)
|
||||
{
|
||||
if (AI_DATA->atkAbility == ABILITY_CONTRARY)
|
||||
return;
|
||||
|
||||
|
||||
if (GetHealthPercentage(battlerAtk) < 80 && AI_RandLessThan(128))
|
||||
return;
|
||||
|
||||
|
||||
switch (statId)
|
||||
{
|
||||
case STAT_ATK:
|
||||
@ -3393,10 +3393,10 @@ void IncreasePoisonScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
|
||||
{
|
||||
if (!HasDamagingMove(battlerDef))
|
||||
*score += 2;
|
||||
|
||||
|
||||
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_STALL && HasMoveEffect(battlerAtk, EFFECT_PROTECT))
|
||||
(*score)++; // stall tactic
|
||||
|
||||
|
||||
if (HasMoveEffect(battlerAtk, EFFECT_VENOSHOCK)
|
||||
|| HasMoveEffect(battlerAtk, EFFECT_HEX)
|
||||
|| HasMoveEffect(battlerAtk, EFFECT_VENOM_DRENCH)
|
||||
@ -3417,7 +3417,7 @@ void IncreaseBurnScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
|
||||
if (CanTargetFaintAi(battlerDef, battlerAtk))
|
||||
*score += 2; // burning the target to stay alive is cool
|
||||
}
|
||||
|
||||
|
||||
if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(AI_DATA->battlerAtkPartner, EFFECT_HEX))
|
||||
(*score)++;
|
||||
}
|
||||
@ -3429,7 +3429,7 @@ void IncreaseParalyzeScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
|
||||
{
|
||||
u8 atkSpeed = GetBattlerTotalSpeedStat(battlerAtk);
|
||||
u8 defSpeed = GetBattlerTotalSpeedStat(battlerDef);
|
||||
|
||||
|
||||
if ((defSpeed >= atkSpeed && defSpeed / 2 < atkSpeed) // You'll go first after paralyzing foe
|
||||
|| HasMoveEffect(battlerAtk, EFFECT_HEX)
|
||||
|| HasMoveEffect(battlerAtk, EFFECT_FLINCH_HIT)
|
||||
@ -3447,11 +3447,11 @@ void IncreaseSleepScore(u8 battlerAtk, u8 battlerDef, u16 move, s16 *score)
|
||||
*score += 2;
|
||||
else
|
||||
return;
|
||||
|
||||
|
||||
if ((HasMoveEffect(battlerAtk, EFFECT_DREAM_EATER) || HasMoveEffect(battlerAtk, EFFECT_NIGHTMARE))
|
||||
&& !(HasMoveEffect(battlerDef, EFFECT_SNORE) || HasMoveEffect(battlerDef, EFFECT_SLEEP_TALK)))
|
||||
(*score)++;
|
||||
|
||||
|
||||
if (HasMoveEffect(battlerAtk, EFFECT_HEX) || HasMoveEffect(AI_DATA->battlerAtkPartner, EFFECT_HEX))
|
||||
(*score)++;
|
||||
}
|
||||
|
@ -7408,7 +7408,7 @@ static void Cmd_various(void)
|
||||
case VARIOUS_SET_MAGIC_COAT_TARGET:
|
||||
gBattlerAttacker = gBattlerTarget;
|
||||
side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
|
||||
if (gSideTimers[side].followmeTimer != 0 && gBattleMons[gSideTimers[side].followmeTarget].hp != 0)
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side))
|
||||
gBattlerTarget = gSideTimers[side].followmeTarget;
|
||||
else
|
||||
gBattlerTarget = gActiveBattler;
|
||||
@ -9980,7 +9980,7 @@ static void Cmd_counterdamagecalculator(void)
|
||||
{
|
||||
gBattleMoveDamage = gProtectStructs[gBattlerAttacker].physicalDmg * 2;
|
||||
|
||||
if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp)
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget))
|
||||
gBattlerTarget = gSideTimers[sideTarget].followmeTarget;
|
||||
else
|
||||
gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId;
|
||||
@ -9999,11 +9999,13 @@ static void Cmd_mirrorcoatdamagecalculator(void) // a copy of atkA1 with the phy
|
||||
u8 sideAttacker = GetBattlerSide(gBattlerAttacker);
|
||||
u8 sideTarget = GetBattlerSide(gProtectStructs[gBattlerAttacker].specialBattlerId);
|
||||
|
||||
if (gProtectStructs[gBattlerAttacker].specialDmg && sideAttacker != sideTarget && gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp)
|
||||
if (gProtectStructs[gBattlerAttacker].specialDmg
|
||||
&& sideAttacker != sideTarget
|
||||
&& gBattleMons[gProtectStructs[gBattlerAttacker].specialBattlerId].hp)
|
||||
{
|
||||
gBattleMoveDamage = gProtectStructs[gBattlerAttacker].specialDmg * 2;
|
||||
|
||||
if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp)
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget))
|
||||
gBattlerTarget = gSideTimers[sideTarget].followmeTarget;
|
||||
else
|
||||
gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId;
|
||||
@ -11084,6 +11086,7 @@ static void Cmd_setforcedtarget(void) // follow me
|
||||
{
|
||||
gSideTimers[GetBattlerSide(gBattlerAttacker)].followmeTimer = 1;
|
||||
gSideTimers[GetBattlerSide(gBattlerAttacker)].followmeTarget = gBattlerAttacker;
|
||||
gSideTimers[GetBattlerSide(gBattlerAttacker)].followmePowder = TestMoveFlags(gCurrentMove, FLAG_POWDER);
|
||||
gBattlescriptCurrInstr++;
|
||||
}
|
||||
|
||||
@ -12557,7 +12560,7 @@ static void Cmd_metalburstdamagecalculator(void)
|
||||
{
|
||||
gBattleMoveDamage = gProtectStructs[gBattlerAttacker].physicalDmg * 150 / 100;
|
||||
|
||||
if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp)
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget))
|
||||
gBattlerTarget = gSideTimers[sideTarget].followmeTarget;
|
||||
else
|
||||
gBattlerTarget = gProtectStructs[gBattlerAttacker].physicalBattlerId;
|
||||
@ -12570,7 +12573,7 @@ static void Cmd_metalburstdamagecalculator(void)
|
||||
{
|
||||
gBattleMoveDamage = gProtectStructs[gBattlerAttacker].specialDmg * 150 / 100;
|
||||
|
||||
if (gSideTimers[sideTarget].followmeTimer && gBattleMons[gSideTimers[sideTarget].followmeTarget].hp)
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, sideTarget))
|
||||
gBattlerTarget = gSideTimers[sideTarget].followmeTarget;
|
||||
else
|
||||
gBattlerTarget = gProtectStructs[gBattlerAttacker].specialBattlerId;
|
||||
|
@ -90,7 +90,7 @@ static const u8 sPkblToEscapeFactor[][3] = {
|
||||
static const u8 sGoNearCounterToCatchFactor[] = {4, 3, 2, 1};
|
||||
static const u8 sGoNearCounterToEscapeFactor[] = {4, 4, 4, 4};
|
||||
|
||||
static const u16 sSkillSwapBannedAbilities[] =
|
||||
static const u16 sSkillSwapBannedAbilities[] =
|
||||
{
|
||||
ABILITY_WONDER_GUARD,
|
||||
ABILITY_MULTITYPE,
|
||||
@ -109,9 +109,9 @@ static const u16 sSkillSwapBannedAbilities[] =
|
||||
ABILITY_GULP_MISSILE,
|
||||
};
|
||||
|
||||
static const u16 sRolePlayBannedAbilities[] =
|
||||
static const u16 sRolePlayBannedAbilities[] =
|
||||
{
|
||||
ABILITY_TRACE,
|
||||
ABILITY_TRACE,
|
||||
ABILITY_WONDER_GUARD,
|
||||
ABILITY_FORECAST,
|
||||
ABILITY_FLOWER_GIFT,
|
||||
@ -134,7 +134,7 @@ static const u16 sRolePlayBannedAbilities[] =
|
||||
ABILITY_GULP_MISSILE,
|
||||
};
|
||||
|
||||
static const u16 sRolePlayBannedAttackerAbilities[] =
|
||||
static const u16 sRolePlayBannedAttackerAbilities[] =
|
||||
{
|
||||
ABILITY_MULTITYPE,
|
||||
ABILITY_ZEN_MODE,
|
||||
@ -150,7 +150,7 @@ static const u16 sRolePlayBannedAttackerAbilities[] =
|
||||
ABILITY_GULP_MISSILE,
|
||||
};
|
||||
|
||||
static const u16 sWorrySeedBannedAbilities[] =
|
||||
static const u16 sWorrySeedBannedAbilities[] =
|
||||
{
|
||||
ABILITY_MULTITYPE,
|
||||
ABILITY_STANCE_CHANGE,
|
||||
@ -166,7 +166,7 @@ static const u16 sWorrySeedBannedAbilities[] =
|
||||
ABILITY_GULP_MISSILE,
|
||||
};
|
||||
|
||||
static const u16 sGastroAcidBannedAbilities[] =
|
||||
static const u16 sGastroAcidBannedAbilities[] =
|
||||
{
|
||||
ABILITY_AS_ONE_ICE_RIDER,
|
||||
ABILITY_AS_ONE_SHADOW_RIDER,
|
||||
@ -184,7 +184,7 @@ static const u16 sGastroAcidBannedAbilities[] =
|
||||
ABILITY_ZEN_MODE,
|
||||
};
|
||||
|
||||
static const u16 sEntrainmentBannedAttackerAbilities[] =
|
||||
static const u16 sEntrainmentBannedAttackerAbilities[] =
|
||||
{
|
||||
ABILITY_TRACE,
|
||||
ABILITY_FORECAST,
|
||||
@ -202,7 +202,7 @@ static const u16 sEntrainmentBannedAttackerAbilities[] =
|
||||
ABILITY_GULP_MISSILE,
|
||||
};
|
||||
|
||||
static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
|
||||
static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
|
||||
{
|
||||
ABILITY_TRUANT,
|
||||
ABILITY_MULTITYPE,
|
||||
@ -217,6 +217,21 @@ static const u16 sEntrainmentTargetSimpleBeamBannedAbilities[] =
|
||||
ABILITY_GULP_MISSILE,
|
||||
};
|
||||
|
||||
bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide)
|
||||
{
|
||||
u32 ability = GetBattlerAbility(battlerAtk);
|
||||
|
||||
if (gSideTimers[defSide].followmeTimer == 0
|
||||
|| gBattleMons[gSideTimers[defSide].followmeTarget].hp == 0
|
||||
|| ability == ABILITY_PROPELLER_TAIL || ability == ABILITY_STALWART)
|
||||
return FALSE;
|
||||
|
||||
if (gSideTimers[defSide].followmePowder && !IsAffectedByPowder(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE)))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Functions
|
||||
void HandleAction_UseMove(void)
|
||||
{
|
||||
@ -292,12 +307,9 @@ void HandleAction_UseMove(void)
|
||||
|
||||
// choose target
|
||||
side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
|
||||
if (gSideTimers[side].followmeTimer != 0
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side)
|
||||
&& gBattleMoves[gCurrentMove].target == MOVE_TARGET_SELECTED
|
||||
&& GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget)
|
||||
&& gBattleMons[gSideTimers[side].followmeTarget].hp != 0
|
||||
&& (GetBattlerAbility(gBattlerAttacker) != ABILITY_PROPELLER_TAIL
|
||||
|| GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART))
|
||||
&& GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget))
|
||||
{
|
||||
gBattlerTarget = gSideTimers[side].followmeTarget;
|
||||
}
|
||||
@ -1553,7 +1565,7 @@ bool32 IsHealBlockPreventingMove(u32 battler, u32 move)
|
||||
{
|
||||
if (!(gStatuses3[battler] & STATUS3_HEAL_BLOCK))
|
||||
return FALSE;
|
||||
|
||||
|
||||
switch (gBattleMoves[move].effect)
|
||||
{
|
||||
case EFFECT_ABSORB:
|
||||
@ -3842,7 +3854,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
BattleScriptPushCursorAndCallback(BattleScript_OverworldTerrain);
|
||||
effect++;
|
||||
}
|
||||
@ -5410,13 +5422,13 @@ static u8 HealConfuseBerry(u32 battlerId, u32 itemId, u8 flavorId, bool32 end2)
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = 1;
|
||||
gBattleMoveDamage *= -1;
|
||||
|
||||
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
|
||||
{
|
||||
gBattleMoveDamage *= 2;
|
||||
gBattlerAbility = battlerId;
|
||||
}
|
||||
|
||||
|
||||
if (end2)
|
||||
{
|
||||
if (GetFlavorRelationByPersonality(gBattleMons[battlerId].personality, flavorId) < 0)
|
||||
@ -5450,10 +5462,10 @@ static u8 StatRaiseBerry(u32 battlerId, u32 itemId, u32 statId, bool32 end2)
|
||||
SET_STATCHANGER(statId, 2, FALSE);
|
||||
else
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
|
||||
|
||||
gBattleScripting.animArg1 = 14 + statId;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
|
||||
|
||||
if (end2)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
|
||||
@ -5496,15 +5508,15 @@ static u8 RandomStatRaiseBerry(u32 battlerId, u32 itemId, bool32 end2)
|
||||
gBattleTextBuff2[7] = EOS;
|
||||
|
||||
gEffectBattler = battlerId;
|
||||
|
||||
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
|
||||
SET_STATCHANGER(i + 1, 4, FALSE);
|
||||
else
|
||||
SET_STATCHANGER(i + 1, 2, FALSE);
|
||||
|
||||
|
||||
gBattleScripting.animArg1 = 0x21 + i + 6;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
|
||||
|
||||
if (end2)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_BerryStatRaiseEnd2);
|
||||
@ -5524,7 +5536,7 @@ static u8 TrySetMicleBerry(u32 battlerId, u32 itemId, bool32 end2)
|
||||
if (HasEnoughHpToEatBerry(battlerId, 4, itemId))
|
||||
{
|
||||
gProtectStructs[battlerId].micle = TRUE; // battler's next attack has increased accuracy
|
||||
|
||||
|
||||
if (end2)
|
||||
{
|
||||
BattleScriptExecute(BattleScript_MicleBerryActivateEnd2);
|
||||
@ -5547,7 +5559,7 @@ static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split)
|
||||
&& !DoesSubstituteBlockMove(gBattlerAttacker, battlerId, gCurrentMove)
|
||||
&& GetBattleMoveSplit(gCurrentMove) == split)
|
||||
{
|
||||
|
||||
|
||||
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
|
||||
PREPARE_STRING_BUFFER(gBattleTextBuff2, STRINGID_STATROSE);
|
||||
|
||||
@ -5556,7 +5568,7 @@ static u8 DamagedStatBoostBerryEffect(u8 battlerId, u8 statId, u8 split)
|
||||
SET_STATCHANGER(statId, 2, FALSE);
|
||||
else
|
||||
SET_STATCHANGER(statId, 1, FALSE);
|
||||
|
||||
|
||||
gBattleScripting.animArg1 = 14 + statId;
|
||||
gBattleScripting.animArg2 = 0;
|
||||
BattleScriptPushCursor();
|
||||
@ -5574,11 +5586,11 @@ static u8 ItemHealHp(u32 battlerId, u32 itemId, bool32 end2, bool32 percentHeal)
|
||||
gBattleMoveDamage = (gBattleMons[battlerId].maxHP * GetBattlerHoldEffectParam(battlerId) / 100) * -1;
|
||||
else
|
||||
gBattleMoveDamage = GetBattlerHoldEffectParam(battlerId) * -1;
|
||||
|
||||
|
||||
// check ripen
|
||||
if (ItemId_GetPocket(itemId) == POCKET_BERRIES && GetBattlerAbility(battlerId) == ABILITY_RIPEN)
|
||||
gBattleMoveDamage *= 2;
|
||||
|
||||
|
||||
gBattlerAbility = battlerId; // in SWSH, berry juice shows ability pop up but has no effect. This is mimicked here
|
||||
if (end2)
|
||||
{
|
||||
@ -5850,7 +5862,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
||||
{
|
||||
u8 maxPP = CalculatePPWithBonus(move, ppBonuses, i);
|
||||
u8 ppRestored = GetBattlerHoldEffectParam(battlerId);
|
||||
|
||||
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
|
||||
{
|
||||
ppRestored *= 2;
|
||||
@ -6428,7 +6440,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
||||
gBattleMoveDamage = 1;
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
|
||||
gBattleMoveDamage *= 2;
|
||||
|
||||
|
||||
effect = ITEM_HP_CHANGE;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_JabocaRowapBerryActivates;
|
||||
@ -6448,7 +6460,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
|
||||
gBattleMoveDamage = 1;
|
||||
if (GetBattlerAbility(battlerId) == ABILITY_RIPEN)
|
||||
gBattleMoveDamage *= 2;
|
||||
|
||||
|
||||
effect = ITEM_HP_CHANGE;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_JabocaRowapBerryActivates;
|
||||
@ -6563,7 +6575,7 @@ u8 GetMoveTarget(u16 move, u8 setTarget)
|
||||
{
|
||||
case MOVE_TARGET_SELECTED:
|
||||
side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
|
||||
if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp)
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side))
|
||||
{
|
||||
targetBattler = gSideTimers[side].followmeTarget;
|
||||
}
|
||||
@ -6598,7 +6610,7 @@ u8 GetMoveTarget(u16 move, u8 setTarget)
|
||||
break;
|
||||
case MOVE_TARGET_RANDOM:
|
||||
side = GetBattlerSide(gBattlerAttacker) ^ BIT_SIDE;
|
||||
if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp)
|
||||
if (IsAffectedByFollowMe(gBattlerAttacker, side))
|
||||
targetBattler = gSideTimers[side].followmeTarget;
|
||||
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && moveTarget & MOVE_TARGET_RANDOM)
|
||||
targetBattler = SetRandomTarget(gBattlerAttacker);
|
||||
@ -7628,7 +7640,7 @@ static u32 CalcAttackStat(u16 move, u8 battlerAtk, u8 battlerDef, u8 moveType, b
|
||||
break;
|
||||
case ABILITY_ICE_SCALES:
|
||||
if (IS_MOVE_SPECIAL(move))
|
||||
MulModifier(&modifier, UQ_4_12(0.5));
|
||||
MulModifier(&modifier, UQ_4_12(0.5));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -8507,7 +8519,7 @@ static bool32 TryRemoveScreens(u8 battler)
|
||||
bool32 removed = FALSE;
|
||||
u8 battlerSide = GetBattlerSide(battler);
|
||||
u8 enemySide = GetBattlerSide(BATTLE_OPPOSITE(battler));
|
||||
|
||||
|
||||
// try to remove from battler's side
|
||||
if (gSideStatuses[battlerSide] & (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL))
|
||||
{
|
||||
@ -8517,7 +8529,7 @@ static bool32 TryRemoveScreens(u8 battler)
|
||||
gSideTimers[battlerSide].auroraVeilTimer = 0;
|
||||
removed = TRUE;
|
||||
}
|
||||
|
||||
|
||||
// try to remove from battler opponent's side
|
||||
if (gSideStatuses[enemySide] & (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL))
|
||||
{
|
||||
@ -8527,7 +8539,7 @@ static bool32 TryRemoveScreens(u8 battler)
|
||||
gSideTimers[enemySide].auroraVeilTimer = 0;
|
||||
removed = TRUE;
|
||||
}
|
||||
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
@ -8554,7 +8566,7 @@ struct Pokemon *GetBattlerPartyData(u8 battlerId)
|
||||
mon = &gPlayerParty[gBattlerPartyIndexes[battlerId]];
|
||||
else
|
||||
mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]];
|
||||
|
||||
|
||||
return mon;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user