A couple of gen4 abilities

This commit is contained in:
DizzyEggg 2018-07-22 18:40:18 +02:00
parent 51dc76c7e8
commit fee81d03ab
8 changed files with 934 additions and 723 deletions

View File

@ -589,7 +589,7 @@
.byte \bank
.endm
.macro recordlastability bank
.macro recordability bank
.byte 0x70
.byte \bank
.endm
@ -1347,6 +1347,14 @@
various \bank, VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC
.endm
.macro stattextbuffer battler
various \battler, VARIOUS_STAT_TEXT_BUFFER
.endm
.macro switchinabilities battler
various \battler, VARIOUS_SWITCHIN_ABILITIES
.endm
@ helpful macros
.macro setstatchanger stat, stages, down
setbyte sSTATCHANGER \stat | \stages << 4 | \down << 7

View File

@ -4109,6 +4109,16 @@ BattleScript_DoTurnDmg::
BattleScript_DoTurnDmgEnd::
end2
BattleScript_PoisonHealActivates::
printstring STRINGID_POISONHEALHPUP
waitmessage 0x40
recordability BS_ATTACKER
statusanimation BS_ATTACKER
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
end2
BattleScript_BurnTurnDmg::
printstring STRINGID_PKMNHURTBYBURN
waitmessage 0x40
@ -4142,7 +4152,20 @@ BattleScript_MoveUsedIsParalyzed::
BattleScript_MoveUsedFlinched::
printstring STRINGID_PKMNFLINCHED
waitmessage 0x40
jumpifability BS_ATTACKER ABILITY_STEADFAST BattleScript_TryActivateSteadFast
BattleScript_MoveUsedFlinchedEnd:
goto BattleScript_MoveEnd
BattleScript_TryActivateSteadFast:
setstatchanger STAT_SPEED, 1, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | 0x1, BattleScript_MoveUsedFlinchedEnd
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_MoveUsedFlinchedEnd
setgraphicalstatchangevalues
playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
setbyte gBattleCommunication STAT_SPEED
stattextbuffer BS_ATTACKER
printstring STRINGID_TARGETABILITYSTATRAISE
waitmessage 0x40
goto BattleScript_MoveUsedFlinchedEnd
BattleScript_PrintUproarOverTurns::
printfromtable gUproarOverTurnStringIds
@ -4354,6 +4377,7 @@ BattleScript_TraceActivates::
pause 0x20
printstring STRINGID_PKMNTRACED
waitmessage 0x40
switchinabilities BS_ATTACKER
end3
BattleScript_RainDishActivates::
@ -4471,6 +4495,18 @@ BattleScript_MoveHPDrain::
orhalfword gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE
goto BattleScript_MoveEnd
BattleScript_MoveStatDrain_PPLoss::
ppreduce
BattleScript_MoveStatDrain::
attackstring
pause 0x20
setgraphicalstatchangevalues
playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
waitanimation
printstring STRINGID_TARGETABILITYSTATRAISE
waitmessage 0x40
goto BattleScript_MoveEnd
BattleScript_MonMadeMoveUseless_PPLoss::
ppreduce
BattleScript_MonMadeMoveUseless::
@ -4564,6 +4600,34 @@ BattleScript_ColorChangeActivates::
waitmessage 0x40
return
BattleScript_AngryPointActivates::
setbyte sB_ANIM_ARG1 0x38
setbyte sB_ANIM_ARG2 0x0
playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
printstring STRINGID_ANGRYPOINTACTIVATES
waitmessage 0x40
return
BattleScript_TargetAbilityStatRaise::
setgraphicalstatchangevalues
playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
waitanimation
printstring STRINGID_TARGETABILITYSTATRAISE
waitmessage 0x40
return
BattleScript_AttackerAbilityStatRaise::
setgraphicalstatchangevalues
playanimation BS_ATTACKER, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
waitanimation
printstring STRINGID_ATTACKERABILITYSTATRAISE
waitmessage 0x40
return
BattleScript_AttackerAbilityStatRaiseEnd3::
call BattleScript_AttackerAbilityStatRaise
end3
BattleScript_RoughSkinActivates::
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000
healthbarupdate BS_ATTACKER

View File

@ -305,5 +305,12 @@ extern const u8 BattleScript_MudSportEnds[];
extern const u8 BattleScript_WaterSportEnds[];
extern const u8 BattleScript_SturdiedMsg[];
extern const u8 BattleScript_GravityEnds[];
extern const u8 BattleScript_MoveStatDrain[];
extern const u8 BattleScript_MoveStatDrain_PPLoss[];
extern const u8 BattleScript_TargetAbilityStatRaise[];
extern const u8 BattleScript_AngryPointActivates[];
extern const u8 BattleScript_AttackerAbilityStatRaise[];
extern const u8 BattleScript_AttackerAbilityStatRaiseEnd3[];
extern const u8 BattleScript_PoisonHealActivates[];
#endif // GUARD_BATTLE_SCRIPTS_H

View File

@ -72,6 +72,8 @@
#define VARIOUS_RETURN_OPPONENT_MON2 20
#define VARIOUS_SET_TELEPORT_OUTCOME 25
#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 26
#define VARIOUS_STAT_TEXT_BUFFER 27
#define VARIOUS_SWITCHIN_ABILITIES 28
// atk80, dmg manipulation
#define ATK80_DMG_CHANGE_SIGN 0

View File

@ -450,7 +450,11 @@
#define STRINGID_MISTYTERRAINENDS 447
#define STRINGID_PSYCHICTERRAINENDS 448
#define STRINGID_GRASSYTERRAINENDS 449
#define STRINGID_TARGETABILITYSTATRAISE 450
#define STRINGID_ANGRYPOINTACTIVATES 451
#define STRINGID_ATTACKERABILITYSTATRAISE 452
#define STRINGID_POISONHEALHPUP 453
#define BATTLESTRINGS_COUNT 438
#define BATTLESTRINGS_COUNT 442
#endif // GUARD_CONSTANTS_BATTLE_STRING_IDS_H

View File

@ -431,7 +431,7 @@ static const u8 sText_FoePkmnPrefix3[] = _("Foe");
static const u8 sText_AllyPkmnPrefix2[] = _("Ally");
static const u8 sText_FoePkmnPrefix4[] = _("Foe");
static const u8 sText_AllyPkmnPrefix3[] = _("Ally");
static const u8 sText_AttackerUsedX[] = _("{B_ATK_NAME_WITH_PREFIX} used\n{B_BUFF2}");
static const u8 sText_AttackerUsedX[] = _("{B_ATK_NAME_WITH_PREFIX} used\n{B_BUFF3}!");
static const u8 sText_ExclamationMark[] = _("!");
static const u8 sText_ExclamationMark2[] = _("!");
static const u8 sText_ExclamationMark3[] = _("!");
@ -586,6 +586,8 @@ static const u8 sText_MudSportEnds[] = _("The effects of Mud Sport have faded.")
static const u8 sText_WaterSportEnds[] = _("The effects of Water Sport have faded.");
static const u8 sText_GravityEnds[] = _("Gravity returned to normal!");
static const u8 sText_AquaRingHeal[] = _("Aqua Ring restored\n{B_ATK_NAME_WITH_PREFIX}s HP!");
static const u8 sText_TargetAbilityRaisedStat[] = _("{B_DEF_NAME_WITH_PREFIX}s {B_ATK_ABILITY}\n raised its {B_BUFF1}!");
static const u8 sText_AttackerAbilityRaisedStat[] = _("{B_ATK_NAME_WITH_PREFIX}s {B_ATK_ABILITY}\n raised its {B_BUFF1}!");
// These strings are currently placeholders, to be fixed.
static const u8 sText_AuroraVeilEnds[] = _("");
@ -593,6 +595,8 @@ static const u8 sText_ElectricTerrainEnds[] = _("");
static const u8 sText_MistyTerrainEnds[] = _("");
static const u8 sText_PsychicTerrainEnds[] = _("");
static const u8 sText_GrassyTerrainEnds[] = _("");
static const u8 sText_AngryPointActivates[] = _("");
static const u8 sText_PoisonHealHpUp[] = _("");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
@ -1035,6 +1039,10 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
sText_MistyTerrainEnds, // 447
sText_PsychicTerrainEnds, // 448
sText_GrassyTerrainEnds, // 449
sText_TargetAbilityRaisedStat, // 450
sText_AngryPointActivates, // 451
sText_AttackerAbilityRaisedStat, // 452
sText_PoisonHealHpUp, // 453
};
const u16 gMissStringIds[] =
@ -2297,14 +2305,11 @@ void BufferStringBattle(u16 stringID)
}
break;
case STRINGID_USEDMOVE: // pokemon used a move msg
ChooseMoveUsedParticle(gBattleTextBuff1); // buff1 doesn't appear in the string, leftover from japanese move names
if (gBattleMsgDataPtr->currentMove >= MOVES_COUNT)
StringCopy(gBattleTextBuff2, sATypeMove_Table[*(&gBattleStruct->stringMoveType)]);
StringCopy(gBattleTextBuff3, sATypeMove_Table[*(&gBattleStruct->stringMoveType)]);
else
StringCopy(gBattleTextBuff2, gMoveNames[gBattleMsgDataPtr->currentMove]);
StringCopy(gBattleTextBuff3, gMoveNames[gBattleMsgDataPtr->currentMove]);
ChooseTypeOfMoveUsedString(gBattleTextBuff2);
stringPtr = sText_AttackerUsedX;
break;
case STRINGID_BATTLEEND: // battle end

View File

@ -203,7 +203,7 @@ static void atk6C_drawlvlupbox(void);
static void atk6D_resetsentmonsvalue(void);
static void atk6E_setatktoplayer0(void);
static void atk6F_makevisible(void);
static void atk70_recordlastability(void);
static void atk70_recordability(void);
static void atk71_buffermovetolearn(void);
static void atk72_jumpifplayerran(void);
static void atk73_hpthresholds(void);
@ -459,7 +459,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
atk6D_resetsentmonsvalue,
atk6E_setatktoplayer0,
atk6F_makevisible,
atk70_recordlastability,
atk70_recordability,
atk71_buffermovetolearn,
atk72_jumpifplayerran,
atk73_hpthresholds,
@ -1013,22 +1013,23 @@ static void atk00_attackcanceler(void)
}
}
static void JumpIfMoveFailed(u8 adder, u16 move)
static bool32 JumpIfMoveFailed(u8 adder, u16 move)
{
const u8 *BS_ptr = gBattlescriptCurrInstr + adder;
if (gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
{
gLastLandedMoves[gBattlerTarget] = 0;
gLastHitByType[gBattlerTarget] = 0;
BS_ptr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
return TRUE;
}
else
{
TrySetDestinyBondToHappen();
if (AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBattlerTarget, 0, 0, move))
return;
return TRUE;
}
gBattlescriptCurrInstr = BS_ptr;
gBattlescriptCurrInstr += adder;
return FALSE;
}
static void atk40_jumpifaffectedbyprotect(void)
@ -1058,7 +1059,7 @@ bool8 JumpIfMoveAffectedByProtect(u16 move)
return affected;
}
static bool8 AccuracyCalcHelper(u16 move)
static bool32 AccuracyCalcHelper(u16 move)
{
if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker)
{
@ -1070,6 +1071,18 @@ static bool8 AccuracyCalcHelper(u16 move)
JumpIfMoveFailed(7, move);
return TRUE;
}
else if (GetBattlerAbility(gBattlerAttacker) == ABILITY_NO_GUARD)
{
if (!JumpIfMoveFailed(7, move))
RecordAbilityBattle(gBattlerAttacker, ABILITY_NO_GUARD);
return TRUE;
}
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_NO_GUARD)
{
if (!JumpIfMoveFailed(7, move))
RecordAbilityBattle(gBattlerTarget, ABILITY_NO_GUARD);
return TRUE;
}
if (!(gHitMarker & HITMARKER_IGNORE_ON_AIR) && gStatuses3[gBattlerTarget] & STATUS3_ON_AIR)
{
@ -6242,11 +6255,11 @@ static void atk6F_makevisible(void)
gBattlescriptCurrInstr += 2;
}
static void atk70_recordlastability(void)
static void atk70_recordability(void)
{
gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
RecordAbilityBattle(gActiveBattler, gLastUsedAbility);
gBattlescriptCurrInstr += 1; // UB: Should be + 2, one byte for command and one byte for battlerId argument.
u8 battler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
RecordAbilityBattle(battler, gBattleMons[battler].ability);
gBattlescriptCurrInstr += 2;
}
void BufferMoveToLearnIntoBattleTextBuff2(void)
@ -6502,6 +6515,13 @@ static void atk76_various(void)
BtlController_EmitPlayFanfareOrBGM(0, MUS_KACHI1, TRUE);
MarkBattlerForControllerExec(gActiveBattler);
break;
case VARIOUS_STAT_TEXT_BUFFER:
PREPARE_STAT_BUFFER(gBattleTextBuff1, gBattleCommunication[0]);
break;
case VARIOUS_SWITCHIN_ABILITIES:
gBattlescriptCurrInstr += 3;
AbilityBattleEffects(ABILITYEFFECT_ON_SWITCHIN, gActiveBattler, 0, 0, 0);
return;
}
gBattlescriptCurrInstr += 3;
@ -7158,6 +7178,9 @@ static void atk8D_setmultihitcounter(void)
gMultiHitCounter = (Random() & 3) + 2;
else
gMultiHitCounter += 2;
if (GetBattlerAbility(gBattlerAttacker) == ABILITY_SKILL_LINK)
gMultiHitCounter = 5;
}
gBattlescriptCurrInstr += 2;

View File

@ -1230,6 +1230,7 @@ u8 DoBattlerEndTurnEffects(void)
}
else
{
u8 ability = GetBattlerAbility(gActiveBattler);
switch (gBattleStruct->turnEffectsTracker)
{
case ENDTURN_INGRAIN: // ingrain
@ -1294,7 +1295,23 @@ u8 DoBattlerEndTurnEffects(void)
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_POISON: // poison
if ((gBattleMons[gActiveBattler].status1 & STATUS1_POISON) && gBattleMons[gActiveBattler].hp != 0)
if ((gBattleMons[gActiveBattler].status1 & STATUS1_POISON)
&& gBattleMons[gActiveBattler].hp != 0
&& ability != ABILITY_MAGIC_GUARD)
{
if (ability == ABILITY_POISON_HEAL)
{
if (!BATTLER_MAX_HP(gActiveBattler))
{
gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
BattleScriptExecute(BattleScript_PoisonHealActivates);
effect++;
}
}
else
{
gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8;
if (gBattleMoveDamage == 0)
@ -1302,24 +1319,44 @@ u8 DoBattlerEndTurnEffects(void)
BattleScriptExecute(BattleScript_PoisonTurnDmg);
effect++;
}
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_BAD_POISON: // toxic poison
if ((gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_POISON) && gBattleMons[gActiveBattler].hp != 0)
if ((gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_POISON)
&& gBattleMons[gActiveBattler].hp != 0
&& ability != ABILITY_MAGIC_GUARD)
{
if (ability == ABILITY_POISON_HEAL)
{
if (!BATTLER_MAX_HP(gActiveBattler))
{
gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
BattleScriptExecute(BattleScript_PoisonHealActivates);
effect++;
}
}
else
{
gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 16;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
if ((gBattleMons[gActiveBattler].status1 & 0xF00) != 0xF00) // not 16 turns
if ((gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_COUNTER) != STATUS1_TOXIC_COUNTER) // not 16 turns
gBattleMons[gActiveBattler].status1 += 0x100;
gBattleMoveDamage *= (gBattleMons[gActiveBattler].status1 & 0xF00) >> 8;
gBattleMoveDamage *= (gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_COUNTER) >> 8;
BattleScriptExecute(BattleScript_PoisonTurnDmg);
effect++;
}
}
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_BURN: // burn
if ((gBattleMons[gActiveBattler].status1 & STATUS1_BURN) && gBattleMons[gActiveBattler].hp != 0)
if ((gBattleMons[gActiveBattler].status1 & STATUS1_BURN)
&& gBattleMons[gActiveBattler].hp != 0
&& ability != ABILITY_MAGIC_GUARD)
{
gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 8;
if (gBattleMoveDamage == 0)
@ -1330,7 +1367,9 @@ u8 DoBattlerEndTurnEffects(void)
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_NIGHTMARES: // spooky nightmares
if ((gBattleMons[gActiveBattler].status2 & STATUS2_NIGHTMARE) && gBattleMons[gActiveBattler].hp != 0)
if ((gBattleMons[gActiveBattler].status2 & STATUS2_NIGHTMARE)
&& gBattleMons[gActiveBattler].hp != 0
&& ability != ABILITY_MAGIC_GUARD)
{
// R/S does not perform this sleep check, which causes the nightmare effect to
// persist even after the affected Pokemon has been awakened by Shed Skin.
@ -1350,7 +1389,9 @@ u8 DoBattlerEndTurnEffects(void)
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_CURSE: // curse
if ((gBattleMons[gActiveBattler].status2 & STATUS2_CURSED) && gBattleMons[gActiveBattler].hp != 0)
if ((gBattleMons[gActiveBattler].status2 & STATUS2_CURSED)
&& gBattleMons[gActiveBattler].hp != 0
&& ability != ABILITY_MAGIC_GUARD)
{
gBattleMoveDamage = gBattleMons[gActiveBattler].maxHP / 4;
if (gBattleMoveDamage == 0)
@ -2263,47 +2304,27 @@ u8 CastformDataTypeChange(u8 battler)
u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveArg)
{
u8 effect = 0;
struct Pokemon *pokeAtk;
struct Pokemon *pokeDef;
u16 speciesAtk;
u16 speciesDef;
u32 pidAtk;
u32 pidDef;
u32 speciesAtk, speciesDef;
u32 pidAtk, pidDef;
u32 moveType;
u32 i;
u32 move;
u8 side;
u8 target1;
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
return;
if (gBattlerAttacker >= gBattlersCount)
gBattlerAttacker = battler;
if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
pokeAtk = &gPlayerParty[gBattlerPartyIndexes[gBattlerAttacker]];
else
pokeAtk = &gEnemyParty[gBattlerPartyIndexes[gBattlerAttacker]];
speciesAtk = gBattleMons[gBattlerAttacker].species;
pidAtk = gBattleMons[gBattlerAttacker].personality;
if (gBattlerTarget >= gBattlersCount)
gBattlerTarget = battler;
speciesDef = gBattleMons[gBattlerTarget].species;
pidDef = gBattleMons[gBattlerTarget].personality;
if (GetBattlerSide(gBattlerTarget) == B_SIDE_PLAYER)
pokeDef = &gPlayerParty[gBattlerPartyIndexes[gBattlerTarget]];
else
pokeDef = &gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]];
speciesAtk = GetMonData(pokeAtk, MON_DATA_SPECIES);
pidAtk = GetMonData(pokeAtk, MON_DATA_PERSONALITY);
speciesDef = GetMonData(pokeDef, MON_DATA_SPECIES);
pidDef = GetMonData(pokeDef, MON_DATA_PERSONALITY);
if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI)) // Why isn't that check done at the beginning?
{
u8 moveType;
s32 i;
u16 move;
u8 side;
u8 target1;
if (special)
gLastUsedAbility = special;
else
gLastUsedAbility = gBattleMons[battler].ability;
gLastUsedAbility = GetBattlerAbility(battler);
if (moveArg)
move = moveArg;
@ -2315,8 +2336,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
switch (caseID)
{
case ABILITYEFFECT_ON_SWITCHIN: // 0
if (gBattlerAttacker >= gBattlersCount)
gBattlerAttacker = battler;
switch (gLastUsedAbility)
{
case ABILITYEFFECT_SWITCH_IN_WEATHER:
@ -2361,6 +2380,43 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
BattleScriptPushCursorAndCallback(BattleScript_OverworldWeatherStarts);
}
break;
case ABILITY_DOWNLOAD:
{
u8 statId;
u32 opposingBattler = BATTLE_OPPOSITE(battler);
u32 opposingDef = gBattleMons[opposingBattler].defense
* gStatStageRatios[gBattleMons[opposingBattler].statStages[STAT_DEF]][0]
/ gStatStageRatios[gBattleMons[opposingBattler].statStages[STAT_DEF]][1];
u32 opposingSpDef = gBattleMons[opposingBattler].spDefense
* gStatStageRatios[gBattleMons[opposingBattler].statStages[STAT_SPDEF]][0]
/ gStatStageRatios[gBattleMons[opposingBattler].statStages[STAT_SPDEF]][1];
opposingBattler = BATTLE_PARTNER(opposingBattler);
if (IsBattlerAlive(opposingBattler))
{
opposingDef += gBattleMons[opposingBattler].defense
* gStatStageRatios[gBattleMons[opposingBattler].statStages[STAT_DEF]][0]
/ gStatStageRatios[gBattleMons[opposingBattler].statStages[STAT_DEF]][1];
opposingSpDef += gBattleMons[opposingBattler].spDefense
* gStatStageRatios[gBattleMons[opposingBattler].statStages[STAT_SPDEF]][0]
/ gStatStageRatios[gBattleMons[opposingBattler].statStages[STAT_SPDEF]][1];
}
if (opposingSpDef > opposingDef)
statId = STAT_SPATK;
else
statId = STAT_ATK;
if (gBattleMons[battler].statStages[statId] != 0xC)
{
gBattleMons[battler].statStages[statId]++;
SET_STATCHANGER(statId, 1, FALSE);
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
BattleScriptPushCursorAndCallback(BattleScript_AttackerAbilityStatRaiseEnd3);
effect++;
}
}
break;
case ABILITY_DRIZZLE:
if (!(gBattleWeather & WEATHER_RAIN_PERMANENT))
{
@ -2508,29 +2564,33 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
case ABILITYEFFECT_ABSORBING: // 3
if (move)
{
u8 statId;
switch (gLastUsedAbility)
{
case ABILITY_VOLT_ABSORB:
if (moveType == TYPE_ELECTRIC && gBattleMoves[move].power != 0)
{
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
gBattlescriptCurrInstr = BattleScript_MoveHPDrain;
else
gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss;
if (moveType == TYPE_ELECTRIC)
effect = 1;
}
break;
case ABILITY_WATER_ABSORB:
if (moveType == TYPE_WATER && gBattleMoves[move].power != 0)
{
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
gBattlescriptCurrInstr = BattleScript_MoveHPDrain;
else
gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss;
case ABILITY_DRY_SKIN:
if (moveType == TYPE_WATER)
effect = 1;
}
break;
case ABILITY_MOTOR_DRIVE:
if (moveType == TYPE_ELECTRIC)
effect = 2, statId = STAT_SPEED;
break;
case ABILITY_LIGHTNING_ROD:
if (moveType == TYPE_ELECTRIC)
effect = 2, statId = STAT_SPATK;
break;
case ABILITY_STORM_DRAIN:
if (moveType == TYPE_WATER)
effect = 2, statId = STAT_SPATK;
break;
case ABILITY_SAP_SIPPER:
if (moveArg == TYPE_GRASS)
effect = 2, statId = STAT_ATK;
break;
case ABILITY_FLASH_FIRE:
if (moveType == TYPE_FIRE && !(gBattleMons[battler].status1 & STATUS1_FREEZE))
@ -2559,7 +2619,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
}
break;
}
if (effect == 1)
if (effect == 1) // Drain Hp ability.
{
if (gBattleMons[battler].maxHP == gBattleMons[battler].hp)
{
@ -2570,17 +2630,56 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
}
else
{
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
gBattlescriptCurrInstr = BattleScript_MoveHPDrain;
else
gBattlescriptCurrInstr = BattleScript_MoveHPDrain_PPLoss;
gBattleMoveDamage = gBattleMons[battler].maxHP / 4;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
gBattleMoveDamage *= -1;
}
}
else if (effect == 2) // Boost Stat ability;
{
if (gBattleMons[battler].statStages[statId] == 0xC)
{
if ((gProtectStructs[gBattlerAttacker].notFirstStrike))
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless;
else
gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless_PPLoss;
}
else
{
if (gProtectStructs[gBattlerAttacker].notFirstStrike)
gBattlescriptCurrInstr = BattleScript_MoveStatDrain;
else
gBattlescriptCurrInstr = BattleScript_MoveStatDrain_PPLoss;
SET_STATCHANGER(statId, 1, FALSE);
gBattleMons[battler].statStages[statId]++;
PREPARE_STAT_BUFFER(gBattleTextBuff1, statId);
}
}
}
break;
case ABILITYEFFECT_CONTACT: // 4
switch (gLastUsedAbility)
{
case ABILITY_ANGER_POINT:
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& gIsCriticalHit
&& TARGET_TURN_DAMAGED
&& IsBattlerAlive(battler)
&& gBattleMons[battler].statStages[STAT_ATK] != 0xC)
{
gBattleMons[battler].statStages[STAT_ATK] = 0xC;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_AngryPointActivates;
effect++;
}
break;
case ABILITY_COLOR_CHANGE:
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& move != MOVE_STRUGGLE
@ -2995,7 +3094,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA
if (effect && caseID < ABILITYEFFECT_CHECK_OTHER_SIDE && gLastUsedAbility != 0xFF)
RecordAbilityBattle(battler, gLastUsedAbility);
}
return effect;
}