summaryrefslogtreecommitdiff
path: root/src/battle_script_commands.c
diff options
context:
space:
mode:
authorjiangzhengwenjz <jiangzhengwenjzw@qq.com>2019-08-25 06:53:22 +0800
committerjiangzhengwenjz <jiangzhengwenjzw@qq.com>2019-08-25 06:53:22 +0800
commit41a7e6967dd4fd79eb01a45f4d77cf7c2ca11dc1 (patch)
treeaceec00f83489b61f2eed7cb9c61f3b55370a2b2 /src/battle_script_commands.c
parent29d7ae94dea8e35d098b60a786368f391324221e (diff)
thru atk14
Diffstat (limited to 'src/battle_script_commands.c')
-rw-r--r--src/battle_script_commands.c1223
1 files changed, 1223 insertions, 0 deletions
diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c
index 01ecae958..688f9e4a2 100644
--- a/src/battle_script_commands.c
+++ b/src/battle_script_commands.c
@@ -29,6 +29,7 @@
#include "battle_setup.h"
#include "battle_ai_script_commands.h"
#include "battle_scripts.h"
+#include "battle_string_ids.h"
#include "reshow_battle_screen.h"
#include "battle_controllers.h"
#include "battle_interface.h"
@@ -41,6 +42,7 @@
#include "constants/species.h"
#include "constants/moves.h"
#include "constants/abilities.h"
+#include "constants/pokemon.h"
#define DEFENDER_IS_PROTECTED ((gProtectStructs[gBattlerTarget].protected) && (gBattleMoves[gCurrentMove].flags & FLAG_PROTECT_AFFECTED))
@@ -865,3 +867,1224 @@ const u8 sBallCatchBonuses[] =
};
const u32 gUnknown_8250898 = 0xFF7EAE60;
+
+void atk00_attackcanceler(void)
+{
+ s32 i;
+
+ if (gBattleOutcome)
+ {
+ gCurrentActionFuncId = B_ACTION_FINISHED;
+ return;
+ }
+ if (gBattleMons[gBattlerAttacker].hp == 0 && !(gHitMarker & HITMARKER_NO_ATTACKSTRING))
+ {
+ gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
+ gBattlescriptCurrInstr = BattleScript_MoveEnd;
+ return;
+ }
+ if (AtkCanceller_UnableToUseMove())
+ return;
+ if (AbilityBattleEffects(ABILITYEFFECT_MOVES_BLOCK, gBattlerTarget, 0, 0, 0))
+ return;
+ if (!gBattleMons[gBattlerAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE && !(gHitMarker & (HITMARKER_x800000 | HITMARKER_NO_ATTACKSTRING))
+ && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
+ {
+ gBattlescriptCurrInstr = BattleScript_NoPPForMove;
+ gMoveResultFlags |= MOVE_RESULT_MISSED;
+ return;
+ }
+ gHitMarker &= ~(HITMARKER_x800000);
+ if (!(gHitMarker & HITMARKER_OBEYS)
+ && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
+ {
+ i = IsMonDisobedient();
+ switch (i)
+ {
+ case 0:
+ break;
+ case 2:
+ gHitMarker |= HITMARKER_OBEYS;
+ return;
+ default:
+ gMoveResultFlags |= MOVE_RESULT_MISSED;
+ return;
+ }
+ }
+ gHitMarker |= HITMARKER_OBEYS;
+ if (gProtectStructs[gBattlerTarget].bounceMove && gBattleMoves[gCurrentMove].flags & FLAG_MAGICCOAT_AFFECTED)
+ {
+ PressurePPLose(gBattlerAttacker, gBattlerTarget, MOVE_MAGIC_COAT);
+ gProtectStructs[gBattlerTarget].bounceMove = FALSE;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_MagicCoatBounce;
+ return;
+ }
+ for (i = 0; i < gBattlersCount; ++i)
+ {
+ if ((gProtectStructs[gBattlerByTurnOrder[i]].stealMove) && gBattleMoves[gCurrentMove].flags & FLAG_SNATCH_AFFECTED)
+ {
+ PressurePPLose(gBattlerAttacker, gBattlerByTurnOrder[i], MOVE_SNATCH);
+ gProtectStructs[gBattlerByTurnOrder[i]].stealMove = FALSE;
+ gBattleScripting.battler = gBattlerByTurnOrder[i];
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_SnatchedMove;
+ return;
+ }
+ }
+ if (gSpecialStatuses[gBattlerTarget].lightningRodRedirected)
+ {
+ gSpecialStatuses[gBattlerTarget].lightningRodRedirected = FALSE;
+ gLastUsedAbility = ABILITY_LIGHTNING_ROD;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_TookAttack;
+ RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
+ }
+ else if (DEFENDER_IS_PROTECTED
+ && (gCurrentMove != MOVE_CURSE || IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST))
+ && ((!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))))
+ {
+ CancelMultiTurnMoves(gBattlerAttacker);
+ gMoveResultFlags |= MOVE_RESULT_MISSED;
+ gLastLandedMoves[gBattlerTarget] = 0;
+ gLastHitByType[gBattlerTarget] = 0;
+ gBattleCommunication[6] = 1;
+ ++gBattlescriptCurrInstr;
+ }
+ else
+ {
+ ++gBattlescriptCurrInstr;
+ }
+}
+
+void 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);
+ }
+ else
+ {
+ TrySetDestinyBondToHappen();
+ if (AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBattlerTarget, 0, 0, move))
+ return;
+ }
+ gBattlescriptCurrInstr = BS_ptr;
+}
+
+void atk40_jumpifaffectedbyprotect(void)
+{
+ if (DEFENDER_IS_PROTECTED)
+ {
+ gMoveResultFlags |= MOVE_RESULT_MISSED;
+ JumpIfMoveFailed(5, 0);
+ gBattleCommunication[6] = 1;
+ }
+ else
+ {
+ gBattlescriptCurrInstr += 5;
+ }
+}
+
+bool8 JumpIfMoveAffectedByProtect(u16 move)
+{
+ bool8 affected = FALSE;
+
+ if (DEFENDER_IS_PROTECTED)
+ {
+ gMoveResultFlags |= MOVE_RESULT_MISSED;
+ JumpIfMoveFailed(7, move);
+ gBattleCommunication[6] = 1;
+ affected = TRUE;
+ }
+ return affected;
+}
+
+bool8 AccuracyCalcHelper(u16 move)
+{
+ if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker)
+ {
+ JumpIfMoveFailed(7, move);
+ return TRUE;
+ }
+ if (!(gHitMarker & HITMARKER_IGNORE_ON_AIR) && gStatuses3[gBattlerTarget] & STATUS3_ON_AIR)
+ {
+ gMoveResultFlags |= MOVE_RESULT_MISSED;
+ JumpIfMoveFailed(7, move);
+ return TRUE;
+ }
+ gHitMarker &= ~HITMARKER_IGNORE_ON_AIR;
+ if (!(gHitMarker & HITMARKER_IGNORE_UNDERGROUND) && gStatuses3[gBattlerTarget] & STATUS3_UNDERGROUND)
+ {
+ gMoveResultFlags |= MOVE_RESULT_MISSED;
+ JumpIfMoveFailed(7, move);
+ return TRUE;
+ }
+ gHitMarker &= ~HITMARKER_IGNORE_UNDERGROUND;
+ if (!(gHitMarker & HITMARKER_IGNORE_UNDERWATER) && gStatuses3[gBattlerTarget] & STATUS3_UNDERWATER)
+ {
+ gMoveResultFlags |= MOVE_RESULT_MISSED;
+ JumpIfMoveFailed(7, move);
+ return TRUE;
+ }
+ gHitMarker &= ~HITMARKER_IGNORE_UNDERWATER;
+ if ((WEATHER_HAS_EFFECT && (gBattleWeather & WEATHER_RAIN_ANY) && gBattleMoves[move].effect == EFFECT_THUNDER)
+ || (gBattleMoves[move].effect == EFFECT_ALWAYS_HIT || gBattleMoves[move].effect == EFFECT_VITAL_THROW))
+ {
+ JumpIfMoveFailed(7, move);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void atk01_accuracycheck(void)
+{
+ u16 move = T2_READ_16(gBattlescriptCurrInstr + 5);
+
+ if ((gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE
+ && !sub_80EB2E0(1)
+ && gBattleMoves[move].power != 0
+ && GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
+ || (gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE
+ && !sub_80EB2E0(2)
+ && gBattleMoves[move].power == 0
+ && GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER)
+ || (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE))
+ {
+ JumpIfMoveFailed(7, move);
+ return;
+ }
+ if (move == NO_ACC_CALC || move == NO_ACC_CALC_CHECK_LOCK_ON)
+ {
+ if (gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && move == NO_ACC_CALC_CHECK_LOCK_ON && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker)
+ gBattlescriptCurrInstr += 7;
+ else if (gStatuses3[gBattlerTarget] & (STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
+ gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
+ else if (!JumpIfMoveAffectedByProtect(0))
+ gBattlescriptCurrInstr += 7;
+ }
+ else
+ {
+ u8 type, moveAcc, holdEffect, param;
+ s8 buff;
+ u16 calc;
+
+ if (move == 0)
+ move = gCurrentMove;
+ GET_MOVE_TYPE(move, type);
+ if (JumpIfMoveAffectedByProtect(move) || AccuracyCalcHelper(move))
+ return;
+ if (gBattleMons[gBattlerTarget].status2 & STATUS2_FORESIGHT)
+ {
+ u8 acc = gBattleMons[gBattlerAttacker].statStages[STAT_ACC];
+
+ buff = acc;
+ }
+ else
+ {
+ u8 acc = gBattleMons[gBattlerAttacker].statStages[STAT_ACC];
+
+ buff = acc + 6 - gBattleMons[gBattlerTarget].statStages[STAT_EVASION];
+ }
+ if (buff < 0)
+ buff = 0;
+ if (buff > 0xC)
+ buff = 0xC;
+ moveAcc = gBattleMoves[move].accuracy;
+ // check Thunder on sunny weather
+ if (WEATHER_HAS_EFFECT && gBattleWeather & WEATHER_SUN_ANY && gBattleMoves[move].effect == EFFECT_THUNDER)
+ moveAcc = 50;
+ calc = sAccuracyStageRatios[buff].dividend * moveAcc;
+ calc /= sAccuracyStageRatios[buff].divisor;
+ if (gBattleMons[gBattlerAttacker].ability == ABILITY_COMPOUND_EYES)
+ calc = (calc * 130) / 100; // 1.3 compound eyes boost
+ if (WEATHER_HAS_EFFECT && gBattleMons[gBattlerTarget].ability == ABILITY_SAND_VEIL && gBattleWeather & WEATHER_SANDSTORM_ANY)
+ 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 (gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[gBattlerTarget].holdEffect;
+ param = gEnigmaBerries[gBattlerTarget].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gBattlerTarget].item);
+ param = ItemId_GetHoldEffectParam(gBattleMons[gBattlerTarget].item);
+ }
+ gPotentialItemEffectBattler = gBattlerTarget;
+
+ if (holdEffect == HOLD_EFFECT_EVASION_UP)
+ calc = (calc * (100 - param)) / 100;
+ // final calculation
+ if ((Random() % 100 + 1) > calc)
+ {
+ gMoveResultFlags |= MOVE_RESULT_MISSED;
+ if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
+ && (gBattleMoves[move].target == MOVE_TARGET_BOTH || gBattleMoves[move].target == MOVE_TARGET_FOES_AND_ALLY))
+ gBattleCommunication[6] = 2;
+ else
+ gBattleCommunication[6] = 0;
+ CheckWonderGuardAndLevitate();
+ }
+ JumpIfMoveFailed(7, move);
+ }
+}
+
+void atk02_attackstring(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ if (!(gHitMarker & (HITMARKER_NO_ATTACKSTRING | HITMARKER_ATTACKSTRING_PRINTED)))
+ {
+ PrepareStringBattle(STRINGID_USEDMOVE, gBattlerAttacker);
+ gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED;
+ }
+ ++gBattlescriptCurrInstr;
+ gBattleCommunication[MSG_DISPLAY] = 0;
+ }
+}
+
+ void atk03_ppreduce(void)
+{
+ s32 ppToDeduct = 1;
+
+ if (!gBattleControllerExecFlags)
+ {
+ if (!gSpecialStatuses[gBattlerAttacker].ppNotAffectedByPressure)
+ {
+ switch (gBattleMoves[gCurrentMove].target)
+ {
+ case MOVE_TARGET_FOES_AND_ALLY:
+ ppToDeduct += AbilityBattleEffects(ABILITYEFFECT_COUNT_ON_FIELD, gBattlerAttacker, ABILITY_PRESSURE, 0, 0);
+ break;
+ case MOVE_TARGET_BOTH:
+ case MOVE_TARGET_OPPONENTS_FIELD:
+ ppToDeduct += AbilityBattleEffects(ABILITYEFFECT_COUNT_OTHER_SIDE, gBattlerAttacker, ABILITY_PRESSURE, 0, 0);
+ break;
+ default:
+ if (gBattlerAttacker != gBattlerTarget && gBattleMons[gBattlerTarget].ability == ABILITY_PRESSURE)
+ ++ppToDeduct;
+ break;
+ }
+ }
+ if (!(gHitMarker & (HITMARKER_NO_PPDEDUCT | HITMARKER_NO_ATTACKSTRING)) && gBattleMons[gBattlerAttacker].pp[gCurrMovePos])
+ {
+ gProtectStructs[gBattlerAttacker].notFirstStrike = 1;
+
+ if (gBattleMons[gBattlerAttacker].pp[gCurrMovePos] > ppToDeduct)
+ gBattleMons[gBattlerAttacker].pp[gCurrMovePos] -= ppToDeduct;
+ else
+ gBattleMons[gBattlerAttacker].pp[gCurrMovePos] = 0;
+
+ if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED)
+ && !((gDisableStructs[gBattlerAttacker].mimickedMoves) & gBitTable[gCurrMovePos]))
+ {
+ gActiveBattler = gBattlerAttacker;
+ BtlController_EmitSetMonData(0, REQUEST_PPMOVE1_BATTLE + gCurrMovePos, 0, 1, &gBattleMons[gBattlerAttacker].pp[gCurrMovePos]);
+ MarkBattlerForControllerExec(gBattlerAttacker);
+ }
+ }
+ gHitMarker &= ~(HITMARKER_NO_PPDEDUCT);
+ ++gBattlescriptCurrInstr;
+ }
+}
+
+void atk04_critcalc(void)
+{
+ u8 holdEffect;
+ u16 item, critChance;
+
+ item = gBattleMons[gBattlerAttacker].item;
+ if (item == ITEM_ENIGMA_BERRY)
+ holdEffect = gEnigmaBerries[gBattlerAttacker].holdEffect;
+ else
+ holdEffect = ItemId_GetHoldEffect(item);
+ gPotentialItemEffectBattler = gBattlerAttacker;
+ critChance = 2 * ((gBattleMons[gBattlerAttacker].status2 & STATUS2_FOCUS_ENERGY) != 0)
+ + (gBattleMoves[gCurrentMove].effect == EFFECT_HIGH_CRITICAL)
+ + (gBattleMoves[gCurrentMove].effect == EFFECT_SKY_ATTACK)
+ + (gBattleMoves[gCurrentMove].effect == EFFECT_BLAZE_KICK)
+ + (gBattleMoves[gCurrentMove].effect == EFFECT_POISON_TAIL)
+ + (holdEffect == HOLD_EFFECT_SCOPE_LENS)
+ + 2 * (holdEffect == HOLD_EFFECT_LUCKY_PUNCH && gBattleMons[gBattlerAttacker].species == SPECIES_CHANSEY)
+ + 2 * (holdEffect == HOLD_EFFECT_STICK && gBattleMons[gBattlerAttacker].species == SPECIES_FARFETCHD);
+ if (critChance >= NELEMS(sCriticalHitChance))
+ critChance = NELEMS(sCriticalHitChance) - 1;
+ if ((gBattleMons[gBattlerTarget].ability != ABILITY_BATTLE_ARMOR && gBattleMons[gBattlerTarget].ability != ABILITY_SHELL_ARMOR)
+ && !(gStatuses3[gBattlerAttacker] & STATUS3_CANT_SCORE_A_CRIT)
+ && !(gBattleTypeFlags & BATTLE_TYPE_OLDMAN_TUTORIAL)
+ && !(Random() % sCriticalHitChance[critChance])
+ && (!(gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE) || sub_80EB2E0(1))
+ && !(gBattleTypeFlags & BATTLE_TYPE_POKEDUDE))
+ gCritMultiplier = 2;
+ else
+ gCritMultiplier = 1;
+ ++gBattlescriptCurrInstr;
+}
+
+void atk05_damagecalc(void)
+{
+ u16 sideStatus = gSideStatuses[GET_BATTLER_SIDE(gBattlerTarget)];
+
+ gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[gBattlerAttacker],
+ &gBattleMons[gBattlerTarget],
+ gCurrentMove,
+ sideStatus,
+ gDynamicBasePower,
+ gBattleStruct->dynamicMoveType,
+ gBattlerAttacker,
+ gBattlerTarget);
+ gBattleMoveDamage = gBattleMoveDamage * gCritMultiplier * gBattleScripting.dmgMultiplier;
+ if (gStatuses3[gBattlerAttacker] & STATUS3_CHARGED_UP && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC)
+ gBattleMoveDamage *= 2;
+ if (gProtectStructs[gBattlerAttacker].helpingHand)
+ gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
+ ++gBattlescriptCurrInstr;
+}
+
+void AI_CalcDmg(u8 attacker, u8 defender)
+{
+ u16 sideStatus = gSideStatuses[GET_BATTLER_SIDE(defender)];
+
+ gBattleMoveDamage = CalculateBaseDamage(&gBattleMons[attacker],
+ &gBattleMons[defender],
+ gCurrentMove,
+ sideStatus,
+ gDynamicBasePower,
+ gBattleStruct->dynamicMoveType,
+ attacker,
+ defender);
+ gDynamicBasePower = 0;
+ gBattleMoveDamage = gBattleMoveDamage * gCritMultiplier * gBattleScripting.dmgMultiplier;
+ if (gStatuses3[attacker] & STATUS3_CHARGED_UP && gBattleMoves[gCurrentMove].type == TYPE_ELECTRIC)
+ gBattleMoveDamage *= 2;
+ if (gProtectStructs[attacker].helpingHand)
+ gBattleMoveDamage = gBattleMoveDamage * 15 / 10;
+}
+
+void ModulateDmgByType(u8 multiplier)
+{
+ gBattleMoveDamage = gBattleMoveDamage * multiplier / 10;
+ if (gBattleMoveDamage == 0 && multiplier)
+ gBattleMoveDamage = 1;
+ switch (multiplier)
+ {
+ case TYPE_MUL_NO_EFFECT:
+ gMoveResultFlags |= MOVE_RESULT_DOESNT_AFFECT_FOE;
+ gMoveResultFlags &= ~MOVE_RESULT_NOT_VERY_EFFECTIVE;
+ gMoveResultFlags &= ~MOVE_RESULT_SUPER_EFFECTIVE;
+ break;
+ case TYPE_MUL_NOT_EFFECTIVE:
+ if (gBattleMoves[gCurrentMove].power && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
+ {
+ if (gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE)
+ gMoveResultFlags &= ~MOVE_RESULT_SUPER_EFFECTIVE;
+ else
+ gMoveResultFlags |= MOVE_RESULT_NOT_VERY_EFFECTIVE;
+ }
+ break;
+ case TYPE_MUL_SUPER_EFFECTIVE:
+ if (gBattleMoves[gCurrentMove].power && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
+ {
+ if (gMoveResultFlags & MOVE_RESULT_NOT_VERY_EFFECTIVE)
+ gMoveResultFlags &= ~MOVE_RESULT_NOT_VERY_EFFECTIVE;
+ else
+ gMoveResultFlags |= MOVE_RESULT_SUPER_EFFECTIVE;
+ }
+ break;
+ }
+}
+
+void atk06_typecalc(void)
+{
+ s32 i = 0;
+ u8 moveType;
+
+ if (gCurrentMove == MOVE_STRUGGLE)
+ {
+ ++gBattlescriptCurrInstr;
+ return;
+ }
+ GET_MOVE_TYPE(gCurrentMove, moveType);
+ // check stab
+ if (IS_BATTLER_OF_TYPE(gBattlerAttacker, moveType))
+ {
+ gBattleMoveDamage = gBattleMoveDamage * 15;
+ gBattleMoveDamage = gBattleMoveDamage / 10;
+ }
+
+ if (gBattleMons[gBattlerTarget].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
+ {
+ gLastUsedAbility = gBattleMons[gBattlerTarget].ability;
+ gMoveResultFlags |= (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE);
+ gLastLandedMoves[gBattlerTarget] = 0;
+ gLastHitByType[gBattlerTarget] = 0;
+ gBattleCommunication[6] = moveType;
+ RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
+ }
+ else
+ {
+ while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
+ {
+ if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
+ {
+ if (gBattleMons[gBattlerTarget].status2 & STATUS2_FORESIGHT)
+ break;
+ i += 3;
+ continue;
+ }
+ else if (TYPE_EFFECT_ATK_TYPE(i) == moveType)
+ {
+ // check type1
+ if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type1)
+ ModulateDmgByType(TYPE_EFFECT_MULTIPLIER(i));
+ // check type2
+ if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type2 &&
+ gBattleMons[gBattlerTarget].type1 != gBattleMons[gBattlerTarget].type2)
+ ModulateDmgByType(TYPE_EFFECT_MULTIPLIER(i));
+ }
+ i += 3;
+ }
+ }
+ if (gBattleMons[gBattlerTarget].ability == ABILITY_WONDER_GUARD && AttacksThisTurn(gBattlerAttacker, gCurrentMove) == 2
+ && (!(gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE) || ((gMoveResultFlags & (MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE)) == (MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE)))
+ && gBattleMoves[gCurrentMove].power)
+ {
+ gLastUsedAbility = ABILITY_WONDER_GUARD;
+ gMoveResultFlags |= MOVE_RESULT_MISSED;
+ gLastLandedMoves[gBattlerTarget] = 0;
+ gLastHitByType[gBattlerTarget] = 0;
+ gBattleCommunication[6] = 3;
+ RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
+ }
+ if (gMoveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE)
+ gProtectStructs[gBattlerAttacker].targetNotAffected = 1;
+ ++gBattlescriptCurrInstr;
+}
+
+void CheckWonderGuardAndLevitate(void)
+{
+ u8 flags = 0;
+ s32 i = 0;
+ u8 moveType;
+
+ if (gCurrentMove == MOVE_STRUGGLE || !gBattleMoves[gCurrentMove].power)
+ return;
+ GET_MOVE_TYPE(gCurrentMove, moveType);
+ if (gBattleMons[gBattlerTarget].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
+ {
+ gLastUsedAbility = ABILITY_LEVITATE;
+ gBattleCommunication[6] = moveType;
+ RecordAbilityBattle(gBattlerTarget, ABILITY_LEVITATE);
+ return;
+ }
+ while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
+ {
+ if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
+ {
+ if (gBattleMons[gBattlerTarget].status2 & STATUS2_FORESIGHT)
+ break;
+ i += 3;
+ continue;
+ }
+ if (TYPE_EFFECT_ATK_TYPE(i) == moveType)
+ {
+ // check no effect
+ if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type1
+ && TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NO_EFFECT)
+ {
+ gMoveResultFlags |= MOVE_RESULT_DOESNT_AFFECT_FOE;
+ gProtectStructs[gBattlerAttacker].targetNotAffected = 1;
+ }
+ if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type2 &&
+ gBattleMons[gBattlerTarget].type1 != gBattleMons[gBattlerTarget].type2 &&
+ TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NO_EFFECT)
+ {
+ gMoveResultFlags |= MOVE_RESULT_DOESNT_AFFECT_FOE;
+ gProtectStructs[gBattlerAttacker].targetNotAffected = 1;
+ }
+ // check super effective
+ if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type1 && TYPE_EFFECT_MULTIPLIER(i) == 20)
+ flags |= 1;
+ if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type2
+ && gBattleMons[gBattlerTarget].type1 != gBattleMons[gBattlerTarget].type2
+ && TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_SUPER_EFFECTIVE)
+ flags |= 1;
+ // check not very effective
+ if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type1 && TYPE_EFFECT_MULTIPLIER(i) == 5)
+ flags |= 2;
+ if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[gBattlerTarget].type2
+ && gBattleMons[gBattlerTarget].type1 != gBattleMons[gBattlerTarget].type2
+ && TYPE_EFFECT_MULTIPLIER(i) == TYPE_MUL_NOT_EFFECTIVE)
+ flags |= 2;
+ }
+ i += 3;
+ }
+ if (gBattleMons[gBattlerTarget].ability == ABILITY_WONDER_GUARD && AttacksThisTurn(gBattlerAttacker, gCurrentMove) == 2)
+ {
+ if (((flags & 2) || !(flags & 1)) && gBattleMoves[gCurrentMove].power)
+ {
+ gLastUsedAbility = ABILITY_WONDER_GUARD;
+ gBattleCommunication[6] = 3;
+ RecordAbilityBattle(gBattlerTarget, ABILITY_WONDER_GUARD);
+ }
+ }
+}
+
+// same as ModulateDmgByType except different arguments
+void ModulateDmgByType2(u8 multiplier, u16 move, u8* flags)
+{
+ gBattleMoveDamage = gBattleMoveDamage * multiplier / 10;
+ if (gBattleMoveDamage == 0 && multiplier != 0)
+ gBattleMoveDamage = 1;
+ switch (multiplier)
+ {
+ case TYPE_MUL_NO_EFFECT:
+ *flags |= MOVE_RESULT_DOESNT_AFFECT_FOE;
+ *flags &= ~MOVE_RESULT_NOT_VERY_EFFECTIVE;
+ *flags &= ~MOVE_RESULT_SUPER_EFFECTIVE;
+ break;
+ case TYPE_MUL_NOT_EFFECTIVE:
+ if (gBattleMoves[move].power && !(*flags & MOVE_RESULT_NO_EFFECT))
+ {
+ if (*flags & MOVE_RESULT_SUPER_EFFECTIVE)
+ *flags &= ~MOVE_RESULT_SUPER_EFFECTIVE;
+ else
+ *flags |= MOVE_RESULT_NOT_VERY_EFFECTIVE;
+ }
+ break;
+ case TYPE_MUL_SUPER_EFFECTIVE:
+ if (gBattleMoves[move].power && !(*flags & MOVE_RESULT_NO_EFFECT))
+ {
+ if (*flags & MOVE_RESULT_NOT_VERY_EFFECTIVE)
+ *flags &= ~MOVE_RESULT_NOT_VERY_EFFECTIVE;
+ else
+ *flags |= MOVE_RESULT_SUPER_EFFECTIVE;
+ }
+ break;
+ }
+}
+
+u8 TypeCalc(u16 move, u8 attacker, u8 defender)
+{
+ s32 i = 0;
+ u8 flags = 0;
+ u8 moveType;
+
+ if (move == MOVE_STRUGGLE)
+ return 0;
+ moveType = gBattleMoves[move].type;
+ // check stab
+ if (IS_BATTLER_OF_TYPE(attacker, moveType))
+ {
+ gBattleMoveDamage = gBattleMoveDamage * 15;
+ gBattleMoveDamage = gBattleMoveDamage / 10;
+ }
+
+ if (gBattleMons[defender].ability == ABILITY_LEVITATE && moveType == TYPE_GROUND)
+ {
+ flags |= (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE);
+ }
+ else
+ {
+ while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
+ {
+ if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
+ {
+ if (gBattleMons[defender].status2 & STATUS2_FORESIGHT)
+ break;
+ i += 3;
+ continue;
+ }
+
+ else if (TYPE_EFFECT_ATK_TYPE(i) == moveType)
+ {
+ // check type1
+ if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[defender].type1)
+ ModulateDmgByType2(TYPE_EFFECT_MULTIPLIER(i), move, &flags);
+ // check type2
+ if (TYPE_EFFECT_DEF_TYPE(i) == gBattleMons[defender].type2 &&
+ gBattleMons[defender].type1 != gBattleMons[defender].type2)
+ ModulateDmgByType2(TYPE_EFFECT_MULTIPLIER(i), move, &flags);
+ }
+ i += 3;
+ }
+ }
+ if (gBattleMons[defender].ability == ABILITY_WONDER_GUARD
+ && !(flags & MOVE_RESULT_MISSED)
+ && AttacksThisTurn(attacker, move) == 2
+ && (!(flags & MOVE_RESULT_SUPER_EFFECTIVE) || ((flags & (MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE)) == (MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE)))
+ && gBattleMoves[move].power)
+ flags |= MOVE_RESULT_MISSED;
+ return flags;
+}
+
+u8 AI_TypeCalc(u16 move, u16 targetSpecies, u8 targetAbility)
+{
+ s32 i = 0;
+ u8 flags = 0;
+ u8 type1 = gBaseStats[targetSpecies].type1, type2 = gBaseStats[targetSpecies].type2;
+ u8 moveType;
+
+ if (move == MOVE_STRUGGLE)
+ return 0;
+ moveType = gBattleMoves[move].type;
+ if (targetAbility == ABILITY_LEVITATE && moveType == TYPE_GROUND)
+ {
+ flags = MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE;
+ }
+ else
+ {
+ while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
+ {
+ if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
+ {
+ i += 3;
+ continue;
+ }
+ if (TYPE_EFFECT_ATK_TYPE(i) == moveType)
+ {
+ // check type1
+ if (TYPE_EFFECT_DEF_TYPE(i) == type1)
+ ModulateDmgByType2(TYPE_EFFECT_MULTIPLIER(i), move, &flags);
+ // check type2
+ if (TYPE_EFFECT_DEF_TYPE(i) == type2 && type1 != type2)
+ ModulateDmgByType2(TYPE_EFFECT_MULTIPLIER(i), move, &flags);
+ }
+ i += 3;
+ }
+ }
+ if (targetAbility == ABILITY_WONDER_GUARD
+ && (!(flags & MOVE_RESULT_SUPER_EFFECTIVE) || ((flags & (MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE)) == (MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE)))
+ && gBattleMoves[move].power)
+ flags |= MOVE_RESULT_DOESNT_AFFECT_FOE;
+ return flags;
+}
+
+static inline void ApplyRandomDmgMultiplier(void)
+{
+ u16 rand = Random();
+ u16 randPercent = 100 - (rand % 16);
+
+ if (gBattleMoveDamage != 0)
+ {
+ gBattleMoveDamage *= randPercent;
+ gBattleMoveDamage /= 100;
+ if (gBattleMoveDamage == 0)
+ gBattleMoveDamage = 1;
+ }
+}
+
+void Unused_ApplyRandomDmgMultiplier(void)
+{
+ ApplyRandomDmgMultiplier();
+}
+
+void atk07_adjustnormaldamage(void)
+{
+ u8 holdEffect, param;
+
+ ApplyRandomDmgMultiplier();
+ if (gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[gBattlerTarget].holdEffect;
+ param = gEnigmaBerries[gBattlerTarget].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gBattlerTarget].item);
+ param = ItemId_GetHoldEffectParam(gBattleMons[gBattlerTarget].item);
+ }
+ gPotentialItemEffectBattler = gBattlerTarget;
+ if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < param)
+ {
+ RecordItemEffectBattle(gBattlerTarget, holdEffect);
+ gSpecialStatuses[gBattlerTarget].focusBanded = 1;
+ }
+ if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_SUBSTITUTE)
+ && (gBattleMoves[gCurrentMove].effect == EFFECT_FALSE_SWIPE || gProtectStructs[gBattlerTarget].endured || gSpecialStatuses[gBattlerTarget].focusBanded)
+ && gBattleMons[gBattlerTarget].hp <= gBattleMoveDamage)
+ {
+ gBattleMoveDamage = gBattleMons[gBattlerTarget].hp - 1;
+ if (gProtectStructs[gBattlerTarget].endured)
+ {
+ gMoveResultFlags |= MOVE_RESULT_FOE_ENDURED;
+ }
+ else if (gSpecialStatuses[gBattlerTarget].focusBanded)
+ {
+ gMoveResultFlags |= MOVE_RESULT_FOE_HUNG_ON;
+ gLastUsedItem = gBattleMons[gBattlerTarget].item;
+ }
+ }
+ ++gBattlescriptCurrInstr;
+}
+
+// The same as 0x7 except it doesn't check for false swipe move effect.
+void atk08_adjustnormaldamage2(void)
+{
+ u8 holdEffect, param;
+
+ ApplyRandomDmgMultiplier();
+ if (gBattleMons[gBattlerTarget].item == ITEM_ENIGMA_BERRY)
+ {
+ holdEffect = gEnigmaBerries[gBattlerTarget].holdEffect;
+ param = gEnigmaBerries[gBattlerTarget].holdEffectParam;
+ }
+ else
+ {
+ holdEffect = ItemId_GetHoldEffect(gBattleMons[gBattlerTarget].item);
+ param = ItemId_GetHoldEffectParam(gBattleMons[gBattlerTarget].item);
+ }
+ gPotentialItemEffectBattler = gBattlerTarget;
+ if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < param)
+ {
+ RecordItemEffectBattle(gBattlerTarget, holdEffect);
+ gSpecialStatuses[gBattlerTarget].focusBanded = 1;
+ }
+ if (!(gBattleMons[gBattlerTarget].status2 & STATUS2_SUBSTITUTE)
+ && (gProtectStructs[gBattlerTarget].endured || gSpecialStatuses[gBattlerTarget].focusBanded)
+ && gBattleMons[gBattlerTarget].hp <= gBattleMoveDamage)
+ {
+ gBattleMoveDamage = gBattleMons[gBattlerTarget].hp - 1;
+ if (gProtectStructs[gBattlerTarget].endured)
+ {
+ gMoveResultFlags |= MOVE_RESULT_FOE_ENDURED;
+ }
+ else if (gSpecialStatuses[gBattlerTarget].focusBanded)
+ {
+ gMoveResultFlags |= MOVE_RESULT_FOE_HUNG_ON;
+ gLastUsedItem = gBattleMons[gBattlerTarget].item;
+ }
+ }
+ ++gBattlescriptCurrInstr;
+}
+
+void atk09_attackanimation(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ if ((gHitMarker & HITMARKER_NO_ANIMATIONS) && (gCurrentMove != MOVE_TRANSFORM && gCurrentMove != MOVE_SUBSTITUTE))
+ {
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_Pausex20;
+ ++gBattleScripting.animTurn;
+ ++gBattleScripting.animTargetsHit;
+ }
+ else
+ {
+ if ((gBattleMoves[gCurrentMove].target & MOVE_TARGET_BOTH
+ || gBattleMoves[gCurrentMove].target & MOVE_TARGET_FOES_AND_ALLY
+ || gBattleMoves[gCurrentMove].target & MOVE_TARGET_DEPENDS)
+ && gBattleScripting.animTargetsHit)
+ {
+ ++gBattlescriptCurrInstr;
+ return;
+ }
+ if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
+ {
+ gActiveBattler = gBattlerAttacker;
+ BtlController_EmitMoveAnimation(0, gCurrentMove, gBattleScripting.animTurn, gBattleMovePower, gBattleMoveDamage, gBattleMons[gBattlerAttacker].friendship, &gDisableStructs[gBattlerAttacker]);
+ ++gBattleScripting.animTurn;
+ ++gBattleScripting.animTargetsHit;
+ MarkBattlerForControllerExec(gBattlerAttacker);
+ ++gBattlescriptCurrInstr;
+ }
+ else
+ {
+ BattleScriptPush(gBattlescriptCurrInstr + 1);
+ gBattlescriptCurrInstr = BattleScript_Pausex20;
+ }
+ }
+ }
+}
+
+void atk0A_waitanimation(void)
+{
+ if (!gBattleControllerExecFlags)
+ ++gBattlescriptCurrInstr;
+}
+
+void atk0B_healthbarupdate(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
+ {
+ gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
+
+ if (gBattleMons[gActiveBattler].status2 & STATUS2_SUBSTITUTE && gDisableStructs[gActiveBattler].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE))
+ {
+ PrepareStringBattle(STRINGID_SUBSTITUTEDAMAGED, gActiveBattler);
+ }
+ else
+ {
+ s16 healthValue;
+ s32 currDmg = gBattleMoveDamage;
+ s32 maxPossibleDmgValue = 10000; // not present in R/S, ensures that huge damage values don't change sign
+
+ if (currDmg <= maxPossibleDmgValue)
+ healthValue = currDmg;
+ else
+ healthValue = maxPossibleDmgValue;
+ BtlController_EmitHealthBarUpdate(0, healthValue);
+ MarkBattlerForControllerExec(gActiveBattler);
+ if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER && gBattleMoveDamage > 0)
+ gBattleResults.playerMonWasDamaged = TRUE;
+ }
+ }
+ gBattlescriptCurrInstr += 2;
+ }
+}
+
+void atk0C_datahpupdate(void)
+{
+ u32 moveType;
+
+ if (!gBattleControllerExecFlags)
+ {
+ if (gBattleStruct->dynamicMoveType == 0)
+ moveType = gBattleMoves[gCurrentMove].type;
+ else if (!(gBattleStruct->dynamicMoveType & 0x40))
+ moveType = gBattleStruct->dynamicMoveType & 0x3F;
+ else
+ moveType = gBattleMoves[gCurrentMove].type;
+ if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
+ {
+ gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
+ if (gBattleMons[gActiveBattler].status2 & STATUS2_SUBSTITUTE && gDisableStructs[gActiveBattler].substituteHP && !(gHitMarker & HITMARKER_IGNORE_SUBSTITUTE))
+ {
+ if (gDisableStructs[gActiveBattler].substituteHP >= gBattleMoveDamage)
+ {
+ if (gSpecialStatuses[gActiveBattler].dmg == 0)
+ gSpecialStatuses[gActiveBattler].dmg = gBattleMoveDamage;
+ gDisableStructs[gActiveBattler].substituteHP -= gBattleMoveDamage;
+ gHpDealt = gBattleMoveDamage;
+ }
+ else
+ {
+ if (gSpecialStatuses[gActiveBattler].dmg == 0)
+ gSpecialStatuses[gActiveBattler].dmg = gDisableStructs[gActiveBattler].substituteHP;
+ gHpDealt = gDisableStructs[gActiveBattler].substituteHP;
+ gDisableStructs[gActiveBattler].substituteHP = 0;
+ }
+ // check substitute fading
+ if (gDisableStructs[gActiveBattler].substituteHP == 0)
+ {
+ gBattlescriptCurrInstr += 2;
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_SubstituteFade;
+ return;
+ }
+ }
+ else
+ {
+ gHitMarker &= ~(HITMARKER_IGNORE_SUBSTITUTE);
+ if (gBattleMoveDamage < 0) // hp goes up
+ {
+ gBattleMons[gActiveBattler].hp -= gBattleMoveDamage;
+ if (gBattleMons[gActiveBattler].hp > gBattleMons[gActiveBattler].maxHP)
+ gBattleMons[gActiveBattler].hp = gBattleMons[gActiveBattler].maxHP;
+
+ }
+ else // hp goes down
+ {
+ if (gHitMarker & HITMARKER_x20)
+ {
+ gHitMarker &= ~(HITMARKER_x20);
+ }
+ else
+ {
+ gTakenDmg[gActiveBattler] += gBattleMoveDamage;
+ if (gBattlescriptCurrInstr[1] == BS_TARGET)
+ gTakenDmgByBattler[gActiveBattler] = gBattlerAttacker;
+ else
+ gTakenDmgByBattler[gActiveBattler] = gBattlerTarget;
+ }
+
+ if (gBattleMons[gActiveBattler].hp > gBattleMoveDamage)
+ {
+ gBattleMons[gActiveBattler].hp -= gBattleMoveDamage;
+ gHpDealt = gBattleMoveDamage;
+ }
+ else
+ {
+ gHpDealt = gBattleMons[gActiveBattler].hp;
+ gBattleMons[gActiveBattler].hp = 0;
+ }
+ if (!gSpecialStatuses[gActiveBattler].dmg && !(gHitMarker & HITMARKER_x100000))
+ gSpecialStatuses[gActiveBattler].dmg = gHpDealt;
+ if (IS_TYPE_PHYSICAL(moveType) && !(gHitMarker & HITMARKER_x100000) && gCurrentMove != MOVE_PAIN_SPLIT)
+ {
+ gProtectStructs[gActiveBattler].physicalDmg = gHpDealt;
+ gSpecialStatuses[gActiveBattler].physicalDmg = gHpDealt;
+ if (gBattlescriptCurrInstr[1] == BS_TARGET)
+ {
+ gProtectStructs[gActiveBattler].physicalBattlerId = gBattlerAttacker;
+ gSpecialStatuses[gActiveBattler].physicalBattlerId = gBattlerAttacker;
+ }
+ else
+ {
+ gProtectStructs[gActiveBattler].physicalBattlerId = gBattlerTarget;
+ gSpecialStatuses[gActiveBattler].physicalBattlerId = gBattlerTarget;
+ }
+ }
+ else if (!IS_TYPE_PHYSICAL(moveType) && !(gHitMarker & HITMARKER_x100000))
+ {
+ gProtectStructs[gActiveBattler].specialDmg = gHpDealt;
+ gSpecialStatuses[gActiveBattler].specialDmg = gHpDealt;
+ if (gBattlescriptCurrInstr[1] == BS_TARGET)
+ {
+ gProtectStructs[gActiveBattler].specialBattlerId = gBattlerAttacker;
+ gSpecialStatuses[gActiveBattler].specialBattlerId = gBattlerAttacker;
+ }
+ else
+ {
+ gProtectStructs[gActiveBattler].specialBattlerId = gBattlerTarget;
+ gSpecialStatuses[gActiveBattler].specialBattlerId = gBattlerTarget;
+ }
+ }
+ }
+ gHitMarker &= ~(HITMARKER_x100000);
+ BtlController_EmitSetMonData(0, REQUEST_HP_BATTLE, 0, 2, &gBattleMons[gActiveBattler].hp);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ }
+ else
+ {
+ gActiveBattler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]);
+ if (gSpecialStatuses[gActiveBattler].dmg == 0)
+ gSpecialStatuses[gActiveBattler].dmg = 0xFFFF;
+ }
+ gBattlescriptCurrInstr += 2;
+ }
+}
+
+void atk0D_critmessage(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ if (gCritMultiplier == 2 && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT))
+ {
+ PrepareStringBattle(STRINGID_CRITICALHIT, gBattlerAttacker);
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ }
+ ++gBattlescriptCurrInstr;
+ }
+}
+
+void atk0E_effectivenesssound(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ gActiveBattler = gBattlerTarget;
+ if (!(gMoveResultFlags & MOVE_RESULT_MISSED))
+ {
+ switch (gMoveResultFlags & (u8)(~(MOVE_RESULT_MISSED)))
+ {
+ case MOVE_RESULT_SUPER_EFFECTIVE:
+ BtlController_EmitPlaySE(0, SE_KOUKA_H);
+ MarkBattlerForControllerExec(gActiveBattler);
+ break;
+ case MOVE_RESULT_NOT_VERY_EFFECTIVE:
+ BtlController_EmitPlaySE(0, SE_KOUKA_L);
+ MarkBattlerForControllerExec(gActiveBattler);
+ break;
+ case MOVE_RESULT_DOESNT_AFFECT_FOE:
+ case MOVE_RESULT_FAILED:
+ // no sound
+ break;
+ case MOVE_RESULT_FOE_ENDURED:
+ case MOVE_RESULT_ONE_HIT_KO:
+ case MOVE_RESULT_FOE_HUNG_ON:
+ default:
+ if (gMoveResultFlags & MOVE_RESULT_SUPER_EFFECTIVE)
+ {
+ BtlController_EmitPlaySE(0, SE_KOUKA_H);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ else if (gMoveResultFlags & MOVE_RESULT_NOT_VERY_EFFECTIVE)
+ {
+ BtlController_EmitPlaySE(0, SE_KOUKA_L);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ else if (!(gMoveResultFlags & (MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED)))
+ {
+ BtlController_EmitPlaySE(0, SE_KOUKA_M);
+ MarkBattlerForControllerExec(gActiveBattler);
+ }
+ break;
+ }
+ }
+ ++gBattlescriptCurrInstr;
+ }
+}
+
+void atk0F_resultmessage(void)
+{
+ u32 stringId = 0;
+
+ if (!gBattleControllerExecFlags)
+ {
+ if (gMoveResultFlags & MOVE_RESULT_MISSED && (!(gMoveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE) || gBattleCommunication[6] > 2))
+ {
+ stringId = gMissStringIds[gBattleCommunication[6]];
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ }
+ else
+ {
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ switch (gMoveResultFlags & (u8)(~(MOVE_RESULT_MISSED)))
+ {
+ case MOVE_RESULT_SUPER_EFFECTIVE:
+ stringId = STRINGID_SUPEREFFECTIVE;
+ break;
+ case MOVE_RESULT_NOT_VERY_EFFECTIVE:
+ stringId = STRINGID_NOTVERYEFFECTIVE;
+ break;
+ case MOVE_RESULT_ONE_HIT_KO:
+ stringId = STRINGID_ONEHITKO;
+ break;
+ case MOVE_RESULT_FOE_ENDURED:
+ stringId = STRINGID_PKMNENDUREDHIT;
+ break;
+ case MOVE_RESULT_FAILED:
+ stringId = STRINGID_BUTITFAILED;
+ break;
+ case MOVE_RESULT_DOESNT_AFFECT_FOE:
+ stringId = STRINGID_ITDOESNTAFFECT;
+ break;
+ case MOVE_RESULT_FOE_HUNG_ON:
+ gLastUsedItem = gBattleMons[gBattlerTarget].item;
+ gPotentialItemEffectBattler = gBattlerTarget;
+ gMoveResultFlags &= ~(MOVE_RESULT_FOE_ENDURED | MOVE_RESULT_FOE_HUNG_ON);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_HangedOnMsg;
+ return;
+ default:
+ if (gMoveResultFlags & MOVE_RESULT_DOESNT_AFFECT_FOE)
+ {
+ stringId = STRINGID_ITDOESNTAFFECT;
+ }
+ else if (gMoveResultFlags & MOVE_RESULT_ONE_HIT_KO)
+ {
+ gMoveResultFlags &= ~(MOVE_RESULT_ONE_HIT_KO);
+ gMoveResultFlags &= ~(MOVE_RESULT_SUPER_EFFECTIVE);
+ gMoveResultFlags &= ~(MOVE_RESULT_NOT_VERY_EFFECTIVE);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_OneHitKOMsg;
+ return;
+ }
+ else if (gMoveResultFlags & MOVE_RESULT_FOE_ENDURED)
+ {
+ gMoveResultFlags &= ~(MOVE_RESULT_FOE_ENDURED | MOVE_RESULT_FOE_HUNG_ON);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_EnduredMsg;
+ return;
+ }
+ else if (gMoveResultFlags & MOVE_RESULT_FOE_HUNG_ON)
+ {
+ gLastUsedItem = gBattleMons[gBattlerTarget].item;
+ gPotentialItemEffectBattler = gBattlerTarget;
+ gMoveResultFlags &= ~(MOVE_RESULT_FOE_ENDURED | MOVE_RESULT_FOE_HUNG_ON);
+ BattleScriptPushCursor();
+ gBattlescriptCurrInstr = BattleScript_HangedOnMsg;
+ return;
+ }
+ else if (gMoveResultFlags & MOVE_RESULT_FAILED)
+ {
+ stringId = STRINGID_BUTITFAILED;
+ }
+ else
+ {
+ gBattleCommunication[MSG_DISPLAY] = 0;
+ }
+ }
+ }
+ if (stringId)
+ PrepareStringBattle(stringId, gBattlerAttacker);
+ ++gBattlescriptCurrInstr;
+ }
+}
+
+void atk10_printstring(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ u16 var = T2_READ_16(gBattlescriptCurrInstr + 1);
+ PrepareStringBattle(var, gBattlerAttacker);
+ gBattlescriptCurrInstr += 3;
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ }
+}
+
+void atk11_printselectionstring(void)
+{
+ gActiveBattler = gBattlerAttacker;
+ BtlController_EmitPrintSelectionString(0, T2_READ_16(gBattlescriptCurrInstr + 1));
+ MarkBattlerForControllerExec(gActiveBattler);
+ gBattlescriptCurrInstr += 3;
+ gBattleCommunication[MSG_DISPLAY] = 1;
+}
+
+void atk12_waitmessage(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ if (!gBattleCommunication[MSG_DISPLAY])
+ {
+ gBattlescriptCurrInstr += 3;
+ }
+ else
+ {
+ u16 toWait = T2_READ_16(gBattlescriptCurrInstr + 1);
+ if (++gPauseCounterBattle >= toWait)
+ {
+ gPauseCounterBattle = 0;
+ gBattlescriptCurrInstr += 3;
+ gBattleCommunication[MSG_DISPLAY] = 0;
+ }
+ }
+ }
+}
+
+void atk13_printfromtable(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ const u16 *ptr = (const u16 *) T1_READ_PTR(gBattlescriptCurrInstr + 1);
+
+ ptr += gBattleCommunication[MULTISTRING_CHOOSER];
+ PrepareStringBattle(*ptr, gBattlerAttacker);
+ gBattlescriptCurrInstr += 5;
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ }
+}
+
+void atk14_printselectionstringfromtable(void)
+{
+ if (!gBattleControllerExecFlags)
+ {
+ const u16 *ptr = (const u16 *) T1_READ_PTR(gBattlescriptCurrInstr + 1);
+
+ ptr += gBattleCommunication[MULTISTRING_CHOOSER];
+ gActiveBattler = gBattlerAttacker;
+ BtlController_EmitPrintSelectionString(0, *ptr);
+ MarkBattlerForControllerExec(gActiveBattler);
+ gBattlescriptCurrInstr += 5;
+ gBattleCommunication[MSG_DISPLAY] = 1;
+ }
+}
+
+u8 GetBattlerTurnOrderNum(u8 battlerId)
+{
+ s32 i;
+
+ for (i = 0; i < gBattlersCount && gBattlerByTurnOrder[i] != battlerId; ++i);
+ return i;
+}
+