mirror of
https://github.com/pret/pokefirered.git
synced 2026-09-08 09:25:28 -05:00
final mechanical changes
This commit is contained in:
@@ -452,6 +452,7 @@ BattleScript_DreamEaterWorked:
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
resultmessage
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
jumpifability BS_TARGET, ABILITY_LIQUID_OOZE, BattleScript_AbsorbLiquidOoze
|
||||
negativedamage
|
||||
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
|
||||
healthbarupdate BS_ATTACKER
|
||||
@@ -3992,6 +3993,8 @@ BattleScript_IntimidateActivationAnimLoop::
|
||||
jumpifability BS_TARGET, ABILITY_CLEAR_BODY, BattleScript_IntimidateAbilityFail
|
||||
jumpifability BS_TARGET, ABILITY_HYPER_CUTTER, BattleScript_IntimidateAbilityFail
|
||||
jumpifability BS_TARGET, ABILITY_WHITE_SMOKE, BattleScript_IntimidateAbilityFail
|
||||
jumpifability BS_TARGET, ABILITY_OBLIVIOUS, BattleScript_IntimidateAbilityFail
|
||||
jumpifability BS_TARGET, ABILITY_INNER_FOCUS, BattleScript_IntimidateAbilityFail
|
||||
statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_IntimidateFail
|
||||
jumpifbyte CMP_GREATER_THAN, cMULTISTRING_CHOOSER, 1, BattleScript_IntimidateFail
|
||||
setgraphicalstatchangevalues
|
||||
@@ -4037,9 +4040,9 @@ BattleScript_TookAttack::
|
||||
|
||||
BattleScript_SturdyPreventsOHKO::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printstring STRINGID_PKMNPROTECTEDBY
|
||||
pause B_WAIT_TIME_LONG
|
||||
goto BattleScript_MoveEnd
|
||||
printstring STRINGID_STURDY
|
||||
pause B_WAIT_TIME_SHORT
|
||||
return
|
||||
|
||||
BattleScript_DampStopsExplosion::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
@@ -4402,3 +4405,10 @@ BattleScript_DampCuresStatus::
|
||||
updatestatusicon BS_ATTACKER
|
||||
end3
|
||||
|
||||
BattleScript_TruantHeal::
|
||||
printstring STRINGID_TRUANTRESTOREDHP
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
|
||||
healthbarupdate BS_ATTACKER
|
||||
datahpupdate BS_ATTACKER
|
||||
end3
|
||||
@@ -450,6 +450,7 @@ struct BattleStruct
|
||||
u8 wishPerishSongState;
|
||||
u8 wishPerishSongBattlerId;
|
||||
u8 lastAttackerToFaintOpponent;
|
||||
u8 pickupUsed[MAX_BATTLERS_COUNT];
|
||||
// align 4
|
||||
union {
|
||||
struct LinkBattlerHeader linkBattlerHeader;
|
||||
|
||||
@@ -392,12 +392,20 @@
|
||||
//add boosting abilities tooltip
|
||||
|
||||
#define STRINGID_OVERGROWBOOSTED 389
|
||||
#define STRINGID_BLAZINGBOOSTED 390
|
||||
#define STRINGID_BLAZEBOOSTED 390
|
||||
#define STRINGID_TORRENTBOOSTED 391
|
||||
#define STRINGID_SWARMBOOSTED 392
|
||||
#define STRINGID_EARLYBIRDBOOSTED 393
|
||||
#define STRINGID_ILLUMINATEBOOSTED 394
|
||||
|
||||
#define BATTLESTRINGS_COUNT 394
|
||||
|
||||
//add sturdy
|
||||
#define STRINGID_STURDY 395
|
||||
|
||||
//add truant
|
||||
#define STRINGID_TRUANTRESTOREDHP 396
|
||||
|
||||
#define BATTLESTRINGS_COUNT 397
|
||||
|
||||
// This is the string id that gBattleStringsTable starts with.
|
||||
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
|
||||
|
||||
@@ -3197,16 +3197,18 @@ static void HandleTurnActionSelectionState(void)
|
||||
break;
|
||||
case B_ACTION_SWITCH:
|
||||
*(gBattleStruct->battlerPartyIndexes + gActiveBattler) = gBattlerPartyIndexes[gActiveBattler];
|
||||
if (gBattleMons[gActiveBattler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION) || gStatuses3[gActiveBattler] & STATUS3_ROOTED)
|
||||
if (gBattleMons[gActiveBattler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION) || gStatuses3[gActiveBattler] & STATUS3_ROOTED
|
||||
&& gBattleMons[gActiveBattler].ability != ABILITY_RUN_AWAY)) //added
|
||||
{
|
||||
BtlController_EmitChoosePokemon(BUFFER_A, PARTY_ACTION_CANT_SWITCH, 6, ABILITY_NONE, gBattleStruct->battlerPartyOrders[gActiveBattler]);
|
||||
}
|
||||
else if ((i = ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_SHADOW_TAG))
|
||||
|| ((i = ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_ARENA_TRAP))
|
||||
else if (gBattleMons[gActiveBattler].ability != ABILITY_RUN_AWAY // ADD
|
||||
&& ((i = ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_SHADOW_TAG))
|
||||
|| ((i = ABILITY_ON_OPPOSING_FIELD(gActiveBattler, ABILITY_ARENA_TRAP))
|
||||
&& !IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_FLYING)
|
||||
&& gBattleMons[gActiveBattler].ability != ABILITY_LEVITATE)
|
||||
|| ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BATTLER, gActiveBattler, ABILITY_MAGNET_PULL, 0, 0))
|
||||
&& IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_STEEL)))
|
||||
|| ((i = AbilityBattleEffects(ABILITYEFFECT_CHECK_FIELD_EXCEPT_BATTLER, gActiveBattler, ABILITY_MAGNET_PULL, 0, 0))
|
||||
&& IS_BATTLER_OF_TYPE(gActiveBattler, TYPE_ELECTRIC || TYPE_ROCK)))
|
||||
{
|
||||
BtlController_EmitChoosePokemon(BUFFER_A, ((i - 1) << 4) | PARTY_ACTION_ABILITY_PREVENTS, 6, gLastUsedAbility, gBattleStruct->battlerPartyOrders[gActiveBattler]);
|
||||
}
|
||||
@@ -3427,6 +3429,22 @@ u8 GetWhoStrikesFirst(u8 battler1, u8 battler2, bool8 ignoreChosenMoves)
|
||||
speedMultiplierBattler1 = (gBattleMons[battler1].ability == ABILITY_AIR_LOCK) ? 2 : 1;
|
||||
speedMultiplierBattler2 = (gBattleMons[battler2].ability == ABILITY_AIR_LOCK) ? 2 : 1;
|
||||
}
|
||||
// add vital spirit speed boost for both battlers
|
||||
if ((gBattleMons[battler1].ability == ABILITY_VITAL_SPIRIT && battler1->status1)
|
||||
speedMultiplierBattler1 = 2;
|
||||
if ((gBattleMons[battler2].ability == ABILITY_VITAL_SPIRIT && battler2->status1)
|
||||
speedMultiplierBattler2 = 2;
|
||||
|
||||
// add speed doubling if Minus/Plus ally
|
||||
if ((gBattleMons[battler1].ability == ABILITY_PLUS && ABILITY_ON_FIELD2(ABILITY_MINUS))
|
||||
speedMultiplierBattler1 = 2;
|
||||
if ((gBattleMons[battler2].ability == ABILITY_PLUS && ABILITY_ON_FIELD2(ABILITY_MINUS))
|
||||
speedMultiplierBattler2 = 2;
|
||||
if ((gBattleMons[battler1].ability == ABILITY_MINUS && ABILITY_ON_FIELD2(ABILITY_PLUS))
|
||||
speedMultiplierBattler1 = 2;
|
||||
if ((gBattleMons[battler2].ability == ABILITY_MINUS && ABILITY_ON_FIELD2(ABILITY_PLUS))
|
||||
speedMultiplierBattler2 = 2;
|
||||
|
||||
else
|
||||
{
|
||||
speedMultiplierBattler1 = 1;
|
||||
@@ -4331,7 +4349,8 @@ static void HandleAction_Run(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
|
||||
if (gBattleMons[gBattlerAttacker].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION)
|
||||
&& gBattleMons[gBattlerAttacker].ability != ABILITY_RUN_AWAY)) //added
|
||||
{
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
|
||||
gBattlescriptCurrInstr = BattleScript_PrintFailedToRunString;
|
||||
|
||||
@@ -428,20 +428,25 @@ static const u8 sText_ExclamationMark3[] = _("!");
|
||||
static const u8 sText_ExclamationMark4[] = _("!");
|
||||
static const u8 sText_ExclamationMark5[] = _("!");
|
||||
|
||||
static const u8 sText_Overgrow_Boosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Overgrow\nboosted its Grass moves!");
|
||||
static const u8 sText_Blaze_Boosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Blaze\nboosted its Fire moves!");
|
||||
static const u8 sText_Torrent_Boosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Torrent\nboosted its Water moves!");
|
||||
static const u8 sText_Swarm_Boosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Swarm\nboosted its Bug moves!");
|
||||
static const u8 sText_Early_Bird_Boosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Early Bird\nboosted its Flying moves!");
|
||||
static const u8 sText_OvergrowBoosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Overgrow\nboosted its Grass moves!");
|
||||
static const u8 sText_BlazeBoosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Blaze\nboosted its Fire moves!");
|
||||
static const u8 sText_TorrentBoosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Torrent\nboosted its Water moves!");
|
||||
static const u8 sText_SwarmBoosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Swarm\nboosted its Bug moves!");
|
||||
static const u8 sText_EarlyBirdBoosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Early Bird\nboosted its Flying moves!");
|
||||
static const u8 sText_IlluminateBoosted[] = _("{B_ATK_NAME_WITH_PREFIX}'s Illuminate\nboosted its Electric moves!");
|
||||
|
||||
const u16 gLowHpAbilityBoostStringIds[] = {
|
||||
STRINGID_OVERGROWBOOSTED, // 0
|
||||
STRINGID_BLAZEBOOSTED, // 1
|
||||
STRINGID_TORRENTBOOSTED, // 2
|
||||
STRINGID_SWARMBOOSTED, // 3
|
||||
STRINGID_EARLYBIRDBOOSTED, // 4
|
||||
STRINGID_EARLYBIRDBOOSTED, // 4
|
||||
STRINGID_ILLUMINATEBOOSTED, // 5
|
||||
};
|
||||
|
||||
static const u8 sText_Sturdy[] = _("{B_ATK_NAME_WITH_PREFIX}'s Sturdy\nallowed it to endure the hit!");
|
||||
static const u8 sText_Truant[] = _("{B_ATK_NAME_WITH_PREFIX} is loafing around and recovered HP!");
|
||||
|
||||
static const u8 sText_HP2[] = _("HP");
|
||||
static const u8 sText_Attack2[] = _("ATTACK");
|
||||
static const u8 sText_Defense2[] = _("DEFENSE");
|
||||
@@ -906,7 +911,15 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT - BATTLESTRINGS_TABLE_ST
|
||||
[STRINGID_TRAINER1MON1COMEBACK - BATTLESTRINGS_TABLE_START] = sText_Trainer1RecallPkmn1,
|
||||
[STRINGID_TRAINER1WINTEXT - BATTLESTRINGS_TABLE_START] = sText_Trainer1WinText,
|
||||
[STRINGID_TRAINER1MON2COMEBACK - BATTLESTRINGS_TABLE_START] = sText_Trainer1RecallPkmn2,
|
||||
[STRINGID_TRAINER1MON1AND2COMEBACK - BATTLESTRINGS_TABLE_START] = sText_Trainer1RecallBoth
|
||||
[STRINGID_TRAINER1MON1AND2COMEBACK - BATTLESTRINGS_TABLE_START] = sText_Trainer1RecallBoth,
|
||||
[STRINGID_STURDY - BATTLESTRINGS_TABLE_START] = sText_Sturdy,
|
||||
[STRINGID_TRUANTRESTOREDHP - BATTLESTRINGS_TABLE_START] = sText_Truant,
|
||||
[STRINGID_OVERGROWBOOSTED - BATTLESTRINGS_TABLE_START] = sText_OvergrowBoosted,
|
||||
[STRINGID_BLAZEBOOSTED - BATTLESTRINGS_TABLE_START] = sText_BlazeBoosted,
|
||||
[STRINGID_TORRENTBOOSTED- BATTLESTRINGS_TABLE_START] = sText_TorrentBoosted,
|
||||
[STRINGID_SWARMBOOSTED - BATTLESTRINGS_TABLE_START] = sText_SwarmBoosted,,
|
||||
[STRINGID_EARLYBIRDBOOSTED - BATTLESTRINGS_TABLE_START] = sText_EarlyBirdBoosted,
|
||||
[STRINGID_ILLUMINATEBOOSTED - BATTLESTRINGS_TABLE_START] = sText_IlluminateBoosted
|
||||
};
|
||||
|
||||
const u16 gMissStringIds[] =
|
||||
|
||||
@@ -1064,7 +1064,17 @@ static void Cmd_accuracycheck(void)
|
||||
else
|
||||
{
|
||||
u8 acc = gBattleMons[gBattlerAttacker].statStages[STAT_ACC];
|
||||
buff = acc + DEFAULT_STAT_STAGE - gBattleMons[gBattlerTarget].statStages[STAT_EVASION];
|
||||
if (gBattleMons[gBattlerAttacker].ability == ABILITY_KEEN_EYE)
|
||||
{
|
||||
u8 targetEvasion = gBattleMons[gBattlerTarget].statStages[STAT_EVASION];
|
||||
if (targetEvasion > DEFAULT_STAT_STAGE)
|
||||
targetEvasion = DEFAULT_STAT_STAGE; // cap at neutral, drops still apply
|
||||
buff = acc + DEFAULT_STAT_STAGE - targetEvasion;
|
||||
}
|
||||
else
|
||||
{
|
||||
buff = acc + DEFAULT_STAT_STAGE - gBattleMons[gBattlerTarget].statStages[STAT_EVASION];
|
||||
}
|
||||
}
|
||||
|
||||
if (buff < MIN_STAT_STAGE)
|
||||
@@ -1102,7 +1112,7 @@ static void Cmd_accuracycheck(void)
|
||||
|
||||
gPotentialItemEffectBattler = gBattlerTarget;
|
||||
|
||||
if (holdEffect == HOLD_EFFECT_EVASION_UP)
|
||||
if (holdEffect == HOLD_EFFECT_EVASION_UP && gBattleMons[gBattlerAttacker].ability != ABILITY_KEEN_EYE)
|
||||
calc = (calc * (100 - param)) / 100;
|
||||
|
||||
// final calculation
|
||||
@@ -1212,6 +1222,15 @@ static void Cmd_critcalc(void)
|
||||
+ 2 * (holdEffect == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY)
|
||||
+ 2 * (holdEffect == HOLD_EFFECT_STICK && gBattleMons[gBattlerAttacker].species == SPECIES_FARFETCHD);
|
||||
|
||||
// ADD: high crit moves guarantee at least stage 4
|
||||
if ((gBattleMoves[gCurrentMove].effect == EFFECT_HIGH_CRITICAL
|
||||
|| gBattleMoves[gCurrentMove].effect == EFFECT_SKY_ATTACK
|
||||
|| gBattleMoves[gCurrentMove].effect == EFFECT_BLAZE_KICK
|
||||
|| gBattleMoves[gCurrentMove].effect == EFFECT_POISON_TAIL)
|
||||
&& critChance < ARRAY_COUNT(sCriticalHitChance) - 1)
|
||||
critChance = ARRAY_COUNT(sCriticalHitChance) - 1;
|
||||
// END ADD
|
||||
|
||||
if (critChance >= ARRAY_COUNT(sCriticalHitChance))
|
||||
critChance = ARRAY_COUNT(sCriticalHitChance) - 1;
|
||||
|
||||
@@ -1222,9 +1241,9 @@ static void Cmd_critcalc(void)
|
||||
gen1Denominator = gen3Denominator;
|
||||
else
|
||||
{
|
||||
gen1Denominator = (68 * sCriticalHitChance[critChance]) / baseSpeed; // allows it to also scale based on crit stage, anything higher than 80 is better
|
||||
if (gen1Denominator < 2)
|
||||
gen1Denominator = 2;
|
||||
gen1Denominator = (sCriticalHitChance[critChance] * 680) / (13 * baseSpeed); // (1/stage) * (1.3 * speed / 68) inverted
|
||||
if (gen1Denominator < 1) // ADD: floor at 1 — effectively guaranteed crit
|
||||
gen1Denominator = 1;
|
||||
}
|
||||
effectiveDenominator = (gen1Denominator < gen3Denominator) ? gen1Denominator : gen3Denominator;
|
||||
// END ADD
|
||||
@@ -1232,7 +1251,7 @@ static void Cmd_critcalc(void)
|
||||
if ((gBattleMons[gBattlerTarget].ability != ABILITY_BATTLE_ARMOR && gBattleMons[gBattlerTarget].ability != ABILITY_SHELL_ARMOR)
|
||||
&& !(gStatuses3[gBattlerAttacker] & STATUS3_CANT_SCORE_A_CRIT)
|
||||
&& !(gBattleTypeFlags & BATTLE_TYPE_OLD_MAN_TUTORIAL)
|
||||
&& !(Random() % effectiveDenominator)
|
||||
&& ((Random() & 0xFF) < (256 / effectiveDenominator))
|
||||
&& (!(gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) || BtlCtrl_OakOldMan_TestState2Flag(1))
|
||||
&& !(gBattleTypeFlags & BATTLE_TYPE_POKEDUDE))
|
||||
gCritMultiplier = 2;
|
||||
@@ -1336,6 +1355,24 @@ static void Cmd_typecalc(void)
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_GROUND_MISS;
|
||||
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
|
||||
}
|
||||
else if (gBattleMons[gBattlerTarget].ability == ABILITY_IMMUNITY && moveType == TYPE_POISON)
|
||||
{
|
||||
gLastUsedAbility = gBattleMons[gBattlerTarget].ability;
|
||||
gMoveResultFlags |= (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE);
|
||||
gLastLandedMoves[gBattlerTarget] = 0;
|
||||
gLastHitByType[gBattlerTarget] = 0;
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_GROUND_MISS;
|
||||
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
|
||||
}
|
||||
else if (gBattleMons[gBattlerTarget].ability == ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC)
|
||||
{
|
||||
gLastUsedAbility = gBattleMons[gBattlerTarget].ability;
|
||||
gMoveResultFlags |= (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE);
|
||||
gLastLandedMoves[gBattlerTarget] = 0;
|
||||
gLastHitByType[gBattlerTarget] = 0;
|
||||
gBattleCommunication[MISS_TYPE] = B_MSG_GROUND_MISS;
|
||||
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
|
||||
@@ -2525,7 +2562,10 @@ void SetMoveEffect(bool8 primary, u8 certain)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleMons[gEffectBattler].status2 |= STATUS2_WRAPPED_TURN((Random() & 2) + 3); // 2-5 turns
|
||||
if (gBattleMons[gEffectBattler].ability == ABILITY_SUCTION_CUPS)
|
||||
gBattleMons[gEffectBattler].status2 |= STATUS2_WRAPPED_TURN((Random() & 1) + 4); // 4-5 turns
|
||||
else
|
||||
gBattleMons[gEffectBattler].status2 |= STATUS2_WRAPPED_TURN((Random() & 3) + 2); // 2-5 turns
|
||||
|
||||
*(gBattleStruct->wrappedMove + gEffectBattler * 2 + 0) = gCurrentMove;
|
||||
*(gBattleStruct->wrappedMove + gEffectBattler * 2 + 1) = gCurrentMove >> 8;
|
||||
@@ -4313,6 +4353,21 @@ static void Cmd_moveend(void)
|
||||
gBattleScripting.moveendState++;
|
||||
break;
|
||||
case MOVEEND_UPDATE_LAST_MOVES:
|
||||
// ADD: cancel wrap and attacker lock-in if trapping move missed
|
||||
if (gMoveResultFlags & MOVE_RESULT_MISSED)
|
||||
{
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if ((gBattleMons[i].status2 & STATUS2_WRAPPED)
|
||||
&& *(gBattleStruct->wrappedBy + i) == gBattlerAttacker)
|
||||
{
|
||||
gBattleMons[i].status2 &= ~STATUS2_WRAPPED;
|
||||
CancelMultiTurnMoves(gBattlerAttacker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// END ADD
|
||||
if (gHitMarker & HITMARKER_SWAP_ATTACKER_TARGET)
|
||||
{
|
||||
gActiveBattler = gBattlerAttacker;
|
||||
@@ -5729,6 +5784,15 @@ static void Cmd_removeitem(void)
|
||||
*usedHeldItem = gBattleMons[gActiveBattler].item;
|
||||
gBattleMons[gActiveBattler].item = ITEM_NONE;
|
||||
|
||||
// Pickup effect: restore consumed item once per battle
|
||||
if (gBattleMons[gActiveBattler].ability == ABILITY_PICKUP
|
||||
&& !gBattleStruct->pickupUsed[gActiveBattler]
|
||||
&& *usedHeldItem != ITEM_NONE)
|
||||
{
|
||||
gBattleMons[gActiveBattler].item = *usedHeldItem;
|
||||
gBattleStruct->pickupUsed[gActiveBattler] = TRUE;
|
||||
}
|
||||
|
||||
BtlController_EmitSetMonData(BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[gActiveBattler].item), &gBattleMons[gActiveBattler].item);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
|
||||
@@ -7203,9 +7267,12 @@ static void Cmd_tryKO(void)
|
||||
gSpecialStatuses[gBattlerTarget].focusBanded = 1;
|
||||
}
|
||||
|
||||
if (gBattleMons[gBattlerTarget].ability == ABILITY_STURDY)
|
||||
if (gBattleMons[gBattlerTarget].ability == ABILITY_STURDY
|
||||
&& gBattleMons[gBattlerTarget].hp == gBattleMons[gBattlerTarget].maxHP
|
||||
&& gBattleMoveDamage >= gBattleMons[gBattlerTarget].hp
|
||||
&& !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
|
||||
{
|
||||
gMoveResultFlags |= MOVE_RESULT_MISSED;
|
||||
gBattleMoveDamage = gBattleMons[gBattlerTarget].hp - 1;
|
||||
gLastUsedAbility = ABILITY_STURDY;
|
||||
gBattlescriptCurrInstr = BattleScript_SturdyPreventsOHKO;
|
||||
RecordAbilityBattle(gBattlerTarget, ABILITY_STURDY);
|
||||
|
||||
@@ -817,7 +817,7 @@ u8 DoBattlerEndTurnEffects(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8;
|
||||
gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16;
|
||||
}
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = 1;
|
||||
@@ -1309,7 +1309,7 @@ u8 AtkCanceller_UnableToUseMove(void)
|
||||
else
|
||||
{
|
||||
u8 toSub;
|
||||
if (gBattleMons[gBattlerAttacker].ability == ABILITY_EARLY_BIRD)
|
||||
if (gBattleMons[gBattlerAttacker].ability == ABILITY_LIMBER) // changed old Early Bird effect to Limber
|
||||
toSub = 2;
|
||||
else
|
||||
toSub = 1;
|
||||
@@ -1373,6 +1373,16 @@ u8 AtkCanceller_UnableToUseMove(void)
|
||||
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_LOAFING;
|
||||
gBattlescriptCurrInstr = BattleScript_MoveUsedLoafingAround;
|
||||
gMoveResultFlags |= MOVE_RESULT_MISSED;
|
||||
// ADD: heal 1/16 max HP on loafing turns
|
||||
if (gBattleMons[gBattlerAttacker].maxHP > gBattleMons[gBattlerAttacker].hp)
|
||||
{
|
||||
gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 16;
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = 1;
|
||||
gBattleMoveDamage *= -1;
|
||||
gBattleScripting.battler = gBattlerAttacker;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_TruantHeal);
|
||||
}
|
||||
effect = 1;
|
||||
}
|
||||
gBattleStruct->atkCancellerTracker++;
|
||||
@@ -1902,6 +1912,19 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
case ABILITY_TRUANT:
|
||||
if ((gBattleMons[battler].status1 & STATUS1_SLEEP)
|
||||
&& gBattleMons[battler].maxHP > gBattleMons[battler].hp)
|
||||
{
|
||||
gBattleMoveDamage = gBattleMons[battler].maxHP / 16;
|
||||
if (gBattleMoveDamage == 0)
|
||||
gBattleMoveDamage = 1;
|
||||
gBattleMoveDamage *= -1;
|
||||
gBattleScripting.battler = gActiveBattler = battler;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_TruantHeal);
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
case ABILITY_SHED_SKIN:
|
||||
if ((gBattleMons[battler].status1 & STATUS1_ANY) && (Random() % 3) == 0)
|
||||
{
|
||||
@@ -1982,24 +2005,8 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
|
||||
effect = 1;
|
||||
}
|
||||
}
|
||||
// ADD: Inner Focus blocks priority moves
|
||||
else if (gLastUsedAbility == ABILITY_INNER_FOCUS)
|
||||
{
|
||||
for (i = 0; sPrioMoves[i] != PRIO_MOVES_END; i++)
|
||||
{
|
||||
if (sPrioMoves[i] == move)
|
||||
break;
|
||||
}
|
||||
if (sPrioMoves[i] != PRIO_MOVES_END)
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
gBattlescriptCurrInstr = BattleScript_SoundproofProtected;
|
||||
effect = 1;
|
||||
}
|
||||
}
|
||||
// ADD: Oblivious blocks taunt/redirect moves
|
||||
else if (gLastUsedAbility == ABILITY_OBLIVIOUS)
|
||||
// ADD: Oblivious and Inner Focus blocks taunt/redirect moves
|
||||
else if (gLastUsedAbility == ABILITY_OBLIVIOUS || gLastUsedAbility == ABILITY_INNER_FOCUS)
|
||||
{
|
||||
for (i = 0; sTauntMoves[i] != TAUNT_MOVES_END; i++)
|
||||
{
|
||||
@@ -2068,7 +2075,19 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ABILITY_LIGHTNING_ROD:
|
||||
if (moveType == TYPE_ELECTRIC)
|
||||
{
|
||||
gLastUsedAbility = ABILITY_LIGHTNING_ROD;
|
||||
RecordAbilityBattle(battler, ABILITY_LIGHTNING_ROD);
|
||||
|
||||
// Apply permanent Charge boost until switch
|
||||
gStatuses3[battler] |= STATUS3_CHARGED_UP;
|
||||
|
||||
gBattlescriptCurrInstr = BattleScript_MoveHPDrain; // reuse generic ability popup
|
||||
effect = 2; // cancels the hit (immunity)
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (effect == 1)
|
||||
{
|
||||
@@ -2239,7 +2258,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
|
||||
}
|
||||
break;
|
||||
case ABILITY_INSOMNIA:
|
||||
case ABILITY_VITAL_SPIRIT:
|
||||
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
|
||||
{
|
||||
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
|
||||
|
||||
@@ -3365,7 +3365,7 @@ const struct SpeciesInfo gSpeciesInfo[] =
|
||||
.friendship = 70,
|
||||
.growthRate = GROWTH_MEDIUM_FAST,
|
||||
.eggGroups = {EGG_GROUP_MONSTER, EGG_GROUP_MONSTER},
|
||||
.abilities = {ABILITY_INSOMNIA, ABILITY_NONE},
|
||||
.abilities = {ABILITY_INSOMNIA, ABILITY_PICKUP},
|
||||
.safariZoneFleeRate = 125,
|
||||
.bodyColor = BODY_COLOR_BROWN,
|
||||
.noFlip = FALSE,
|
||||
@@ -3713,7 +3713,7 @@ const struct SpeciesInfo gSpeciesInfo[] =
|
||||
.friendship = 70,
|
||||
.growthRate = GROWTH_SLOW,
|
||||
.eggGroups = {EGG_GROUP_BUG, EGG_GROUP_BUG},
|
||||
.abilities = {ABILITY_HYPER_CUTTER, ABILITY_NONE},
|
||||
.abilities = {ABILITY_HYPER_CUTTER, ABILITY_GUTS},
|
||||
.safariZoneFleeRate = 125,
|
||||
.bodyColor = BODY_COLOR_BROWN,
|
||||
.noFlip = FALSE,
|
||||
@@ -5308,7 +5308,7 @@ const struct SpeciesInfo gSpeciesInfo[] =
|
||||
.friendship = 70,
|
||||
.growthRate = GROWTH_MEDIUM_SLOW,
|
||||
.eggGroups = {EGG_GROUP_GRASS, EGG_GROUP_GRASS},
|
||||
.abilities = {ABILITY_CHLOROPHYLL, ABILITY_NONE},
|
||||
.abilities = {ABILITY_CHLOROPHYLL, ABILITY_FLASH_FIRE},
|
||||
.safariZoneFleeRate = 0,
|
||||
.bodyColor = BODY_COLOR_GREEN,
|
||||
.noFlip = FALSE,
|
||||
|
||||
@@ -2412,6 +2412,36 @@ static bool8 IsMoveInList(u16 move, const u16 *list)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 HasOtherElectricType(u8 battler)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (i != battler
|
||||
&& gBattleMons[i].hp != 0
|
||||
&& (gBattleMons[i].type1 == TYPE_ELECTRIC || gBattleMons[i].type2 == TYPE_ELECTRIC))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 HasOtherRockType(u8 battler)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < gBattlersCount; i++)
|
||||
{
|
||||
if (i != battler
|
||||
&& gBattleMons[i].hp != 0
|
||||
&& (gBattleMons[i].type1 == TYPE_ROCK || gBattleMons[i].type2 == TYPE_ROCK))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideStatus, u16 powerOverride, u8 typeOverride, u8 battlerIdAtk, u8 battlerIdDef)
|
||||
{
|
||||
u32 i;
|
||||
@@ -2509,14 +2539,21 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
|
||||
defense *= 2;
|
||||
if (attackerHoldEffect == HOLD_EFFECT_THICK_CLUB && (attacker->species == SPECIES_CUBONE || attacker->species == SPECIES_MAROWAK))
|
||||
attack *= 2;
|
||||
// Apply effects of abilities
|
||||
if (defender->ability == ABILITY_THICK_FAT && (type == TYPE_FIRE || type == TYPE_ICE))
|
||||
spAttack /= 2;
|
||||
if (defender->ability == ABILITY_MAGMA_ARMOR && (type == TYPE_FIRE || type == TYPE_GROUND))
|
||||
gBattleMovePower = (50 * gBattleMovePower) / 100;
|
||||
if (attacker->ability == ABILITY_HUSTLE)
|
||||
&& (gBattleMoves[move].flags & FLAG_MAKES_CONTACT)) // boost only for contact moves
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100; // alternatively boost both attack and SpAttack but this is neater
|
||||
if (attacker->ability == ABILITY_PLUS && ABILITY_ON_FIELD2(ABILITY_MINUS))
|
||||
if (attacker->ability == ABILITY_PLUS && HasOtherRockType(gBattlerAttacker))
|
||||
spAttack = (150 * spAttack) / 100;
|
||||
if (attacker->ability == ABILITY_MINUS && ABILITY_ON_FIELD2(ABILITY_PLUS))
|
||||
if (attacker->ability == ABILITY_MINUS && HasOtherElectricType(gBattlerAttacker))
|
||||
spAttack = (150 * spAttack) / 100;
|
||||
if (defender->ability == ABILITY_PLUS && HasOtherRockType(gBattlerAttacker))
|
||||
spAttack = (150 * spAttack) / 100;
|
||||
if (defender->ability == ABILITY_MINUS && HasOtherElectricType(gBattlerAttacker))
|
||||
spAttack = (150 * spAttack) / 100;
|
||||
if (attacker->ability == ABILITY_GUTS && attacker->status1)
|
||||
attack = (150 * attack) / 100;
|
||||
@@ -2562,7 +2599,14 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
|
||||
damage = attack;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ADD: Pressure on defender ignores attacker's Attack boosts
|
||||
if (defender->ability == ABILITY_PRESSURE
|
||||
&& attacker->statStages[STAT_ATK] > DEFAULT_STAT_STAGE)
|
||||
damage = attack;
|
||||
else
|
||||
APPLY_STAT_MOD(damage, attacker, attack, STAT_ATK)
|
||||
}
|
||||
|
||||
damage = damage * gBattleMovePower;
|
||||
damage *= (2 * attacker->level / 5 + 2);
|
||||
@@ -2576,7 +2620,14 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
|
||||
damageHelper = defense;
|
||||
}
|
||||
else
|
||||
APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF)
|
||||
{
|
||||
// ADD: Pressure on attacker ignores foe Defense boosts
|
||||
if (attacker->ability == ABILITY_PRESSURE
|
||||
&& defender->statStages[STAT_DEF] > DEFAULT_STAT_STAGE)
|
||||
damageHelper = defense;
|
||||
else
|
||||
APPLY_STAT_MOD(damageHelper, defender, defense, STAT_DEF)
|
||||
}
|
||||
|
||||
damage = damage / damageHelper;
|
||||
damage /= 50;
|
||||
@@ -2617,8 +2668,14 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
|
||||
damage = spAttack;
|
||||
}
|
||||
else
|
||||
APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK)
|
||||
|
||||
{
|
||||
// ADD: Pressure on defender ignores attacker's SpAtk boosts
|
||||
if (defender->ability == ABILITY_PRESSURE
|
||||
&& attacker->statStages[STAT_SPATK] > DEFAULT_STAT_STAGE)
|
||||
damage = spAttack;
|
||||
else
|
||||
APPLY_STAT_MOD(damage, attacker, spAttack, STAT_SPATK)
|
||||
}
|
||||
damage = damage * gBattleMovePower;
|
||||
damage *= (2 * attacker->level / 5 + 2);
|
||||
|
||||
@@ -2631,7 +2688,14 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
|
||||
damageHelper = spDefense;
|
||||
}
|
||||
else
|
||||
APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF)
|
||||
{
|
||||
// ADD: Pressure ignores SpDef boosts
|
||||
if (attacker->ability == ABILITY_PRESSURE
|
||||
&& defender->statStages[STAT_SPATK] > DEFAULT_STAT_STAGE)
|
||||
damageHelper = spDefense;
|
||||
else
|
||||
APPLY_STAT_MOD(damageHelper, defender, spDefense, STAT_SPDEF)
|
||||
}
|
||||
|
||||
damage = (damage / damageHelper);
|
||||
damage /= 50;
|
||||
|
||||
Reference in New Issue
Block a user