mirror of
https://github.com/pret/pokefirered.git
synced 2026-08-23 09:44:23 -05:00
ability updates
This commit is contained in:
@@ -4389,3 +4389,16 @@ BattleScript_ActionSelectionItemsCantBeUsed::
|
||||
BattleScript_FlushMessageBox::
|
||||
printstring STRINGID_EMPTYSTRING3
|
||||
return
|
||||
|
||||
BattleScript_LowHpAbilityBoost::
|
||||
pause B_WAIT_TIME_SHORT
|
||||
printfromtable gLowHpAbilityBoostStringIds
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
return
|
||||
|
||||
BattleScript_DampCuresStatus::
|
||||
printstring STRINGID_PKMNSXCUREDYPROBLEM
|
||||
waitmessage B_WAIT_TIME_LONG
|
||||
updatestatusicon BS_ATTACKER
|
||||
end3
|
||||
|
||||
|
||||
@@ -234,6 +234,7 @@ extern const u8 *const gStatNamesTable2[];
|
||||
|
||||
extern const u16 gMissStringIds[];
|
||||
extern const u16 gTrappingMoves[];
|
||||
extern const u16 gLowHpAbilityBoostStringIds[];
|
||||
|
||||
extern const u8 gText_Sleep[];
|
||||
extern const u8 gText_Poison[];
|
||||
|
||||
@@ -152,6 +152,7 @@
|
||||
#define STATUS3_INTIMIDATE_POKES (1 << 19)
|
||||
#define STATUS3_TRACE (1 << 20)
|
||||
#define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER)
|
||||
#define STATUS3_LOW_HP_ABILITY_MSG (1 << 21) // added for blaze/torrent/overgrow message trigger
|
||||
|
||||
// Not really sure what a "hitmarker" is.
|
||||
#define HITMARKER_WAKE_UP_CLEAR (1 << 4) // Cleared when waking up. Never set or checked.
|
||||
|
||||
@@ -389,7 +389,15 @@
|
||||
#define STRINGID_PKMNCOPIEDSECONDARYTYPE 387 //add to redefine conversion2
|
||||
#define STRINGID_PKMNSXSUMMONEDHAIL 388 //ADD snow warning
|
||||
|
||||
#define BATTLESTRINGS_COUNT 389
|
||||
//add boosting abilities tooltip
|
||||
|
||||
#define STRINGID_OVERGROWBOOSTED 389
|
||||
#define STRINGID_BLAZINGBOOSTED 390
|
||||
#define STRINGID_TORRENTBOOSTED 391
|
||||
#define STRINGID_SWARMBOOSTED 392
|
||||
#define STRINGID_EARLYBIRDBOOSTED 393
|
||||
|
||||
#define BATTLESTRINGS_COUNT 394
|
||||
|
||||
// This is the string id that gBattleStringsTable starts with.
|
||||
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
|
||||
|
||||
@@ -3421,6 +3421,12 @@ u8 GetWhoStrikesFirst(u8 battler1, u8 battler2, bool8 ignoreChosenMoves)
|
||||
else
|
||||
speedMultiplierBattler2 = 1;
|
||||
}
|
||||
else if (gBattleWeather != B_WEATHER_NONE) // weather exists but is being suppressed
|
||||
{
|
||||
// ADD: Air Lock doubles speed when actively negating weather
|
||||
speedMultiplierBattler1 = (gBattleMons[battler1].ability == ABILITY_AIR_LOCK) ? 2 : 1;
|
||||
speedMultiplierBattler2 = (gBattleMons[battler2].ability == ABILITY_AIR_LOCK) ? 2 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
speedMultiplierBattler1 = 1;
|
||||
|
||||
@@ -428,6 +428,20 @@ 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!");
|
||||
|
||||
const u16 gLowHpAbilityBoostStringIds[] = {
|
||||
STRINGID_OVERGROWBOOSTED, // 0
|
||||
STRINGID_BLAZEBOOSTED, // 1
|
||||
STRINGID_TORRENTBOOSTED, // 2
|
||||
STRINGID_SWARMBOOSTED, // 3
|
||||
STRINGID_EARLYBIRDBOOSTED, // 4
|
||||
};
|
||||
|
||||
static const u8 sText_HP2[] = _("HP");
|
||||
static const u8 sText_Attack2[] = _("ATTACK");
|
||||
static const u8 sText_Defense2[] = _("DEFENSE");
|
||||
|
||||
@@ -1084,8 +1084,10 @@ static void Cmd_accuracycheck(void)
|
||||
calc = (calc * 130) / 100; // 1.3 compound eyes boost
|
||||
if (WEATHER_HAS_EFFECT && gBattleMons[gBattlerTarget].ability == ABILITY_SAND_VEIL && gBattleWeather & B_WEATHER_SANDSTORM)
|
||||
calc = (calc * 80) / 100; // 1.2 sand veil loss
|
||||
if (gBattleMons[gBattlerAttacker].ability == ABILITY_HUSTLE && IS_TYPE_PHYSICAL(type))
|
||||
calc = (calc * 80) / 100; // 1.2 hustle loss
|
||||
if (WEATHER_HAS_EFFECT && gBattleMons[gBattlerTarget].ability == ABILITY_WATER_VEIL && gBattleWeather & B_WEATHER_RAIN)
|
||||
calc = (calc * 80) / 100; // 1.2 water veil loss
|
||||
if (gBattleMons[gBattlerAttacker].ability == ABILITY_HUSTLE && (gBattleMoves[gCurrentMove].flags & FLAG_MAKES_CONTACT))
|
||||
calc = (calc * 80) / 100; // 1.2 hustle loss for contact moves
|
||||
|
||||
if (gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY)
|
||||
{
|
||||
@@ -1770,6 +1772,8 @@ static void Cmd_healthbarupdate(void)
|
||||
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleMoveDamage > 0)
|
||||
gBattleResults.playerMonWasDamaged = TRUE;
|
||||
}
|
||||
if (gBattleMons[gActiveBattler].hp < oldHp && gBattleMons[gActiveBattler].hp != 0) // trigger ability if HP dropped
|
||||
AbilityBattleEffects(ABILITYEFFECT_HP_CHANGE, gActiveBattler, 0, 0, 0);
|
||||
}
|
||||
|
||||
gBattlescriptCurrInstr += 2;
|
||||
|
||||
@@ -34,6 +34,21 @@ static const u16 sSoundMovesTable[] =
|
||||
MOVE_UPROAR, MOVE_METAL_SOUND, MOVE_GRASS_WHISTLE, MOVE_HYPER_VOICE, SOUND_MOVES_END
|
||||
};
|
||||
|
||||
#define PRIO_MOVES_END 0xFFFF
|
||||
|
||||
static const u16 sPrioMoves[] =
|
||||
{
|
||||
MOVE_QUICK_ATTACK, MOVE_EXTREMESPEED, MOVE_FAKE_OUT, MOVE_FEINT, MOVE_MACH_PUNCH, PRIO_MOVES_END
|
||||
};
|
||||
|
||||
#define TAUNT_MOVES_END 0xFFFF
|
||||
|
||||
static const u16 sTauntMoves[] =
|
||||
{
|
||||
MOVE_TAUNT, MOVE_FOLLOW_ME, TAUNT_MOVES_END
|
||||
};
|
||||
|
||||
|
||||
u8 GetBattlerForBattleScript(u8 caseId)
|
||||
{
|
||||
u8 ret = 0;
|
||||
@@ -1836,6 +1851,36 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_HP_CHANGE: // <-- ADD YOUR CODE HERE
|
||||
{
|
||||
u8 ability = gBattleMons[battler].ability;
|
||||
|
||||
if ((ability == ABILITY_BLAZE
|
||||
|| ability == ABILITY_TORRENT
|
||||
|| ability == ABILITY_OVERGROW
|
||||
|| ability == ABILITY_SWARM)
|
||||
|| ability == ABILITY_EARLY_BIRD
|
||||
&& gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 3
|
||||
&& !(gStatuses3[battler] & STATUS3_LOW_HP_ABILITY_MSG))
|
||||
{
|
||||
gStatuses3[battler] |= STATUS3_LOW_HP_ABILITY_MSG;
|
||||
|
||||
switch (ability)
|
||||
{
|
||||
case ABILITY_OVERGROW: gBattleCommunication[MULTISTRING_CHOOSER] = 0; break;
|
||||
case ABILITY_BLAZE: gBattleCommunication[MULTISTRING_CHOOSER] = 1; break;
|
||||
case ABILITY_TORRENT: gBattleCommunication[MULTISTRING_CHOOSER] = 2; break;
|
||||
case ABILITY_SWARM: gBattleCommunication[MULTISTRING_CHOOSER] = 3; break;
|
||||
case ABILITY_EARLY_BIRD: gBattleCommunication[MULTISTRING_CHOOSER] = 4; break;
|
||||
}
|
||||
|
||||
gBattlerAbility = battler;
|
||||
BattleScriptPushCursor();
|
||||
gBattlescriptCurrInstr = BattleScript_LowHpAbilityBoost;
|
||||
effect++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_ENDTURN: // 1
|
||||
@@ -1879,6 +1924,31 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
case ABILITY_DAMP:
|
||||
if (WEATHER_HAS_EFFECT
|
||||
&& (gBattleWeather & B_WEATHER_RAIN)
|
||||
&& (gBattleMons[battler].status1 & STATUS1_ANY))
|
||||
{
|
||||
// Copy the same status string pattern from Shed Skin
|
||||
if (gBattleMons[battler].status1 & (STATUS1_POISON | STATUS1_TOXIC_POISON))
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_PoisonJpn);
|
||||
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_SleepJpn);
|
||||
if (gBattleMons[battler].status1 & STATUS1_PARALYSIS)
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_ParalysisJpn);
|
||||
if (gBattleMons[battler].status1 & STATUS1_BURN)
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_BurnJpn);
|
||||
if (gBattleMons[battler].status1 & STATUS1_FREEZE)
|
||||
StringCopy(gBattleTextBuff1, gStatusConditionString_IceJpn);
|
||||
gBattleMons[battler].status1 = 0;
|
||||
gBattleMons[battler].status2 &= ~STATUS2_NIGHTMARE;
|
||||
gBattleScripting.battler = gActiveBattler = battler;
|
||||
BattleScriptPushCursorAndCallback(BattleScript_DampCuresStatus);
|
||||
BtlController_EmitSetMonData(BUFFER_A, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[battler].status1);
|
||||
MarkBattlerForControllerExec(gActiveBattler);
|
||||
effect++;
|
||||
}
|
||||
break;
|
||||
case ABILITY_SPEED_BOOST:
|
||||
if (gBattleMons[battler].statStages[STAT_SPEED] < MAX_STAT_STAGE && gDisableStructs[battler].isFirstTurn != 2)
|
||||
{
|
||||
@@ -1912,6 +1982,38 @@ 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)
|
||||
{
|
||||
for (i = 0; sTauntMoves[i] != TAUNT_MOVES_END; i++)
|
||||
{
|
||||
if (sTauntMoves[i] == move)
|
||||
break;
|
||||
}
|
||||
if (sTauntMoves[i] != TAUNT_MOVES_END)
|
||||
{
|
||||
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS)
|
||||
gHitMarker |= HITMARKER_NO_PPDEDUCT;
|
||||
gBattlescriptCurrInstr = BattleScript_SoundproofProtected;
|
||||
effect = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ABILITYEFFECT_ABSORBING: // 3
|
||||
if (move)
|
||||
@@ -1966,6 +2068,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
if (effect == 1)
|
||||
{
|
||||
|
||||
@@ -1637,6 +1637,26 @@ static const u16 sHMMoves[] =
|
||||
MOVE_ROCK_SMASH, MOVE_WATERFALL, MOVE_DIVE, HM_MOVES_END
|
||||
};
|
||||
|
||||
#define ABILITY_MOVE_LIST_END 0xFFFF
|
||||
|
||||
static const u16 sSlicingMoves[] =
|
||||
{
|
||||
MOVE_CUT, MOVE_RAZOR_LEAF, MOVE_SLASH, MOVE_FURY_CUTTER,
|
||||
MOVE_AIR_CUTTER, MOVE_AERIAL_ACE, MOVE_LEAF_BLADE, ABILITY_MOVE_LIST_END
|
||||
};
|
||||
|
||||
static const u16 sClawMoves[] =
|
||||
{
|
||||
MOVE_VISE_GRIP, MOVE_CLAMP, MOVE_CRABHAMMER, MOVE_METAL_CLAW,
|
||||
MOVE_CRUSH_CLAW, MOVE_DRAGON_CLAW, MOVE_GUILLOTINE, ABILITY_MOVE_LIST_END
|
||||
};
|
||||
|
||||
static const u16 sHeadMoves[] =
|
||||
{
|
||||
MOVE_HEADBUTT, MOVE_MEGAHORN, MOVE_HORN_ATTACK,
|
||||
MOVE_SKULL_BASH, MOVE_HORN_DRILL, ABILITY_MOVE_LIST_END
|
||||
};
|
||||
|
||||
#if defined(FIRERED)
|
||||
// Attack forme
|
||||
static const u16 sDeoxysBaseStats[] =
|
||||
@@ -2381,6 +2401,16 @@ static void DeleteFirstMoveAndGiveMoveToBoxMon(struct BoxPokemon *boxMon, u16 mo
|
||||
#define ShouldGetStatBadgeBoost(flag, battler)\
|
||||
(!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_EREADER_TRAINER)) && FlagGet(flag) && GetBattlerSide(battler) == B_SIDE_PLAYER)
|
||||
|
||||
static bool8 IsMoveInList(u16 move, const u16 *list)
|
||||
{
|
||||
u32 i;
|
||||
for (i = 0; list[i] != ABILITY_MOVE_LIST_END; i++)
|
||||
{
|
||||
if (list[i] == move)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideStatus, u16 powerOverride, u8 typeOverride, u8 battlerIdAtk, u8 battlerIdDef)
|
||||
{
|
||||
@@ -2434,8 +2464,10 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
|
||||
defenderHoldEffectParam = ItemId_GetHoldEffectParam(defender->item);
|
||||
}
|
||||
|
||||
if (attacker->ability == ABILITY_HUGE_POWER || attacker->ability == ABILITY_PURE_POWER)
|
||||
if (attacker->ability == ABILITY_HUGE_POWER)
|
||||
attack *= 2;
|
||||
if (attacker->ability == attacker->ability == ABILITY_PURE_POWER)
|
||||
spAttack *= 2;
|
||||
|
||||
if (ShouldGetStatBadgeBoost(FLAG_BADGE01_GET, battlerIdAtk))
|
||||
attack = (110 * attack) / 100;
|
||||
@@ -2480,7 +2512,8 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
|
||||
if (defender->ability == ABILITY_THICK_FAT && (type == TYPE_FIRE || type == TYPE_ICE))
|
||||
spAttack /= 2;
|
||||
if (attacker->ability == ABILITY_HUSTLE)
|
||||
attack = (150 * attack) / 100;
|
||||
&& (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))
|
||||
spAttack = (150 * spAttack) / 100;
|
||||
if (attacker->ability == ABILITY_MINUS && ABILITY_ON_FIELD2(ABILITY_PLUS))
|
||||
@@ -2501,6 +2534,18 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100;
|
||||
if (type == TYPE_BUG && attacker->ability == ABILITY_SWARM && attacker->hp <= (attacker->maxHP / 3))
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100;
|
||||
if (type == TYPE_FLYING && attacker->ability == ABILITY_EARLY_BIRD && attacker->hp <= (attacker->maxHP / 3))
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100;
|
||||
if (type == TYPE_ELECTRIC && attacker->ability == ABILITY_ILLUMINATE && attacker->hp <= (attacker->maxHP / 3)) // ADD illuminate electric boost
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100;
|
||||
// Hyper Cutter: 1.5x boost for slicing or claw moves
|
||||
if (attacker->ability == ABILITY_HYPER_CUTTER
|
||||
&& (IsMoveInList(move, sSlicingMoves) || IsMoveInList(move, sClawMoves)))
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100;
|
||||
// Rock Head: 1.5x boost for head moves
|
||||
if (attacker->ability == ABILITY_ROCK_HEAD
|
||||
&& IsMoveInList(move, sHeadMoves))
|
||||
gBattleMovePower = (150 * gBattleMovePower) / 100;
|
||||
|
||||
// Self-destruct / Explosion cut defense in half
|
||||
if (gBattleMoves[gCurrentMove].effect == EFFECT_EXPLOSION)
|
||||
|
||||
Reference in New Issue
Block a user