begin work on battle4, organize battle headers

This commit is contained in:
DizzyEggg 2017-09-19 21:01:12 +02:00
parent 148b995189
commit b3c788f2ca
7 changed files with 523 additions and 1198 deletions

View File

@ -8409,7 +8409,7 @@ bc_battle_begin_message: @ 803B120
strb r0, [r1]
ldrb r1, [r1]
movs r0, 0
bl b_std_message
bl PrepareStringBattle
ldr r1, =gBattleMainFunc
ldr r0, =sub_803B180
str r0, [r1]
@ -8431,7 +8431,7 @@ bc_8013568: @ 803B158
str r0, [r1]
movs r0, 0
movs r1, 0
bl b_std_message
bl PrepareStringBattle
_0803B170:
pop {r0}
bx r0
@ -8473,7 +8473,7 @@ _0803B1BA:
lsls r1, 24
lsrs r1, 24
movs r0, 0x1
bl b_std_message
bl PrepareStringBattle
ldr r1, =gBattleMainFunc
ldr r0, =sub_803B25C
str r0, [r1]
@ -8743,7 +8743,7 @@ _0803B3F6:
lsls r1, 24
lsrs r1, 24
movs r0, 0x1
bl b_std_message
bl PrepareStringBattle
_0803B412:
ldr r1, =gBattleMainFunc
ldr r0, =sub_803B4C8
@ -15698,8 +15698,8 @@ _0803F47A:
bx r1
thumb_func_end get_battle_side_of_something
thumb_func_start sub_803F480
sub_803F480: @ 803F480
thumb_func_start PressurePPLose
PressurePPLose: @ 803F480
push {r4-r7,lr}
sub sp, 0x4
lsls r0, 24
@ -15795,7 +15795,7 @@ _0803F532:
pop {r0}
bx r0
.pool
thumb_func_end sub_803F480
thumb_func_end PressurePPLose
thumb_func_start sub_803F548
sub_803F548: @ 803F548
@ -16300,8 +16300,8 @@ _0803F95E:
bx r1
thumb_func_end sub_803F90C
thumb_func_start b_std_message
b_std_message: @ 803F964
thumb_func_start PrepareStringBattle
PrepareStringBattle: @ 803F964
push {r4,lr}
adds r2, r0, 0
lsls r2, 16
@ -16317,7 +16317,7 @@ b_std_message: @ 803F964
pop {r0}
bx r0
.pool
thumb_func_end b_std_message
thumb_func_end PrepareStringBattle
thumb_func_start sub_803F988
sub_803F988: @ 803F988

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@ gUnknown_082D86A8:: @ 82D86A8
gUnknown_082D8A30:: @ 82D8A30
.incbin "baserom.gba", 0x2d8a30, 0x1e
gUnknown_082D8A4E:: @ 82D8A4E
BattleScript_MoveEnd:: @ 82D8A4E
.incbin "baserom.gba", 0x2d8a4e, 0x12
gUnknown_082D8A60:: @ 82D8A60
@ -198,7 +198,7 @@ BattleScript_NoMovesLeft:: @ 82DB072
gUnknown_082DB076:: @ 82DB076
.incbin "baserom.gba", 0x2db076, 0x4
gUnknown_082DB07A:: @ 82DB07A
BattleScript_NoPPForMove:: @ 82DB07A
.incbin "baserom.gba", 0x2db07a, 0xf
gUnknown_082DB089:: @ 82DB089
@ -240,10 +240,10 @@ gUnknown_082DB185:: @ 82DB185
gUnknown_082DB18D:: @ 82DB18D
.incbin "baserom.gba", 0x2db18d, 0x7
gUnknown_082DB194:: @ 82DB194
BattleScript_MagicCoatBounce:: @ 82DB194
.incbin "baserom.gba", 0x2db194, 0x18
gUnknown_082DB1AC:: @ 82DB1AC
BattleScript_SnatchedMove:: @ 82DB1AC
.incbin "baserom.gba", 0x2db1ac, 0x1b
gUnknown_082DB1C7:: @ 82DB1C7
@ -360,7 +360,7 @@ gUnknown_082DB4C1:: @ 82DB4C1
BattleScript_DroughtActivates:: @ 82DB52A
.incbin "baserom.gba", 0x2db52a, 0x14
gUnknown_082DB53E:: @ 82DB53E
BattleScript_TookAttack:: @ 82DB53E
.incbin "baserom.gba", 0x2db53e, 0x14
gUnknown_082DB552:: @ 82DB552

View File

@ -204,10 +204,14 @@
#define MULTISTRING_CHOOSER 0x5
#define MSG_DISPLAY 0x7
// functions
extern u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg);
extern u8 GetBankSide(u8 bank);
#define MOVE_TARGET_SELECTED 0x0
#define MOVE_TARGET_DEPENDS 0x1
#define MOVE_TARGET_USER 0x2
#define MOVE_TARGET_RANDOM 0x4
#define MOVE_TARGET_x10 0x10
#define MOVE_TARGET_BOTH 0x8
#define MOVE_TARGET_FOES_AND_ALLY 0x20
#define MOVE_TARGET_OPPONENTS_FIELD 0x40
struct Trainer
{
@ -636,6 +640,14 @@ extern struct BattleStruct* gBattleStruct;
var2[offsetof(struct structName, offsetField)] = value; \
}
#define GET_MOVE_TYPE(move, type) \
{ \
if (gBattleStruct->dynamicMoveType) \
type = gBattleStruct->dynamicMoveType & 0x3F; \
else \
type = gBattleMoves[move].type; \
}
struct BattleScripting
{
u8 field_0;
@ -666,6 +678,44 @@ struct BattleScripting
extern struct BattleScripting gBattleScripting;
// functions
// battle_2
void CancelMultiTurnMoves(u8 bank);
void PressurePPLose(u8 bankAtk, u8 bankDef, u16 move);
void PrepareStringBattle(u16 stringId, u8 bank);
// battle_3
void b_movescr_stack_push(const u8* bsPtr);
void b_movescr_stack_push_cursor(void);
u8 sub_803FB4C(void); // msg, can't select a move
u8 CheckMoveLimitations(u8 bank, u8 unusableMoves, u8 check);
bool8 AreAllMovesUnusable(void);
u8 IsImprisoned(u8 bank, u16 move);
u8 UpdateTurnCounters(void);
u8 TurnBasedEffects(void);
bool8 sub_8041364(void);
bool8 sub_8041728(void);
void b_clear_atk_up_if_hit_flag_unless_enraged(void);
u8 AtkCanceller_UnableToUseMove(void);
bool8 sub_80423F4(u8 bank, u8 r1, u8 r2);
u8 CastformDataTypeChange(u8 bank);
u8 AbilityBattleEffects(u8 caseID, u8 bank, u8 ability, u8 special, u16 moveArg);
void b_call_bc_move_exec(const u8* BS_ptr);
void b_push_move_exec(const u8* BS_ptr);
u8 ItemBattleEffects(u8 caseID, u8 bank, bool8 moveTurn);
void sub_8045868(u8 bank);
void sub_80458B4(void);
u8 GetMoveTarget(u16 move, u8 useMoveTarget);
u8 IsPokeDisobedient(void);
// rom_80A5C6C
u8 GetBankSide(u8 bank);
u8 GetBankIdentity(u8 bank);
u8 GetBankByPlayerAI(u8 bank);
// Move this somewhere else
#include "sprite.h"
struct BattleSpritesGfx

View File

@ -0,0 +1,6 @@
#ifndef GUARD_CALCULATE_BASE_DAMAGE_H
#define GUARD_CALCULATE_BASE_DAMAGE_H
s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideStatus, u16 powerOverride, u8 typeOverride, u8 bankAtk, u8 bankDef);
#endif // GUARD_CALCULATE_BASE_DAMAGE_H

View File

@ -15,6 +15,7 @@
#include "battle_message.h"
#include "battle_ai.h"
#include "event_data.h"
#include "calculate_base_damage.h"
extern const u8* gBattlescriptCurrInstr;
extern const u8* gUnknown_02024220[BATTLE_BANKS_COUNT];
@ -187,11 +188,8 @@ extern void SetMoveEffect(bool8 primary, u8 certainArg);
extern bool8 UproarWakeUpCheck(u8 bank);
extern void MarkBufferBankForExecution(u8 bank);
extern u8 sub_803F90C(u8 bank);
extern u8 GetBankIdentity(u8);
extern void sub_803F9EC();
extern bool8 sub_80423F4(u8 bank, u8, u8);
extern s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *defender, u32 move, u16 sideFlags, u16 powerOverride, u8 typeOverride, u8 bankAtk, u8 bankDef);
extern u8 GetBankByPlayerAI(u8);
extern u8 sub_806D864(u8);
extern u8 sub_806D82C(u8);
extern u8 weather_get_current(void);
@ -199,11 +197,6 @@ extern void sub_803E08C(void);
extern void bc_move_exec_returning(void);
extern s8 GetFlavourRelationByPersonality(u32 personality, u8 flavor);
u8 IsImprisoned(u8 bank, u16 move);
u8 ItemBattleEffects(u8 caseID, u8 bank, bool8 moveTurn);
u8 GetMoveTarget(u16 move, u8 useMoveTarget);
void b_push_move_exec(const u8* BS_ptr);
void b_movescr_stack_push(const u8* bsPtr)
{
BATTLESCRIPTS_STACK->ptr[BATTLESCRIPTS_STACK->size++] = bsPtr;
@ -6237,7 +6230,7 @@ u8 GetMoveTarget(u16 move, u8 useMoveTarget)
switch (moveTarget)
{
case 0:
case MOVE_TARGET_SELECTED:
side = GetBankSide(gBankAttacker) ^ 1;
if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp)
targetBank = gSideTimers[side].followmeTarget;
@ -6258,19 +6251,19 @@ u8 GetMoveTarget(u16 move, u8 useMoveTarget)
}
}
break;
case 1:
case 8:
case 32:
case 64:
case MOVE_TARGET_DEPENDS:
case MOVE_TARGET_BOTH:
case MOVE_TARGET_FOES_AND_ALLY:
case MOVE_TARGET_OPPONENTS_FIELD:
targetBank = GetBankByPlayerAI((GetBankIdentity(gBankAttacker) & 1) ^ 1);
if (gAbsentBankFlags & gBitTable[targetBank])
targetBank ^= 2;
break;
case 4:
case MOVE_TARGET_RANDOM:
side = GetBankSide(gBankAttacker) ^ 1;
if (gSideTimers[side].followmeTimer && gBattleMons[gSideTimers[side].followmeTarget].hp)
targetBank = gSideTimers[side].followmeTarget;
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && moveTarget & 4)
else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && moveTarget & MOVE_TARGET_RANDOM)
{
if (GetBankSide(gBankAttacker) == SIDE_PLAYER)
{
@ -6292,8 +6285,8 @@ u8 GetMoveTarget(u16 move, u8 useMoveTarget)
else
targetBank = GetBankByPlayerAI((GetBankIdentity(gBankAttacker) & 1) ^ 1);
break;
case 2:
case 16:
case MOVE_TARGET_USER:
case MOVE_TARGET_x10:
targetBank = gBankAttacker;
break;
}

View File

@ -1,11 +1,141 @@
#include "global.h"
#include "battle.h"
#include "battle_move_effects.h"
#include "battle_message.h"
#include "battle_ai.h"
#include "moves.h"
#include "abilities.h"
#include "item.h"
#include "items.h"
#include "hold_effects.h"
#include "util.h"
#include "pokemon.h"
#include "calculate_base_damage.h"
#include "rng.h"
// variables
extern u8 gCritMultiplier;
extern s32 gBattleMoveDamage;
extern u32 gStatuses3[BATTLE_BANKS_COUNT];
extern u32 gBattleTypeFlags;
extern struct BattleEnigmaBerry gEnigmaBerries[BATTLE_BANKS_COUNT];
extern struct BattlePokemon gBattleMons[BATTLE_BANKS_COUNT];
extern u8 gActiveBank;
extern u32 gBattleExecBuffer;
extern u8 gNoOfAllBanks;
extern u16 gBattlePartyID[BATTLE_BANKS_COUNT];
extern u8 gTurnOrder[BATTLE_BANKS_COUNT];
extern u8 gUnknown_02024A76[BATTLE_BANKS_COUNT];
extern u16 gCurrentMove;
extern u8 gLastUsedAbility;
extern u16 gBattleWeather;
extern u8 gStringBank;
extern u8 gEffectBank;
extern u8 gAbsentBankFlags;
extern u8 gMultiHitCounter;
extern u16 gChosenMovesByBanks[BATTLE_BANKS_COUNT];
extern u16 gSideAffecting[2];
extern u16 gPauseCounterBattle;
extern u16 gPaydayMoney;
extern u16 gRandomTurnNumber;
extern u8 gBattleOutcome;
extern u8 gBattleTerrain;
extern u16 gTrainerBattleOpponent;
extern u8 gBankAttacker;
extern u8 gBankTarget;
extern const u8* gBattlescriptCurrInstr;
extern u8 gCurrMovePos;
extern u8 gFightStateTracker;
extern u32 gHitMarker;
extern u8 gBattleMoveFlags;
extern u8 gBattleCommunication[];
extern u16 gUnknown_02024250[4];
extern u16 gUnknown_02024258[4];
extern u8 gStringBank;
extern u16 gDynamicBasePower;
extern u16 gLastUsedItem;
extern u16 gBattleMovePower;
extern s32 gHP_dealt;
extern s32 gTakenDmg[BATTLE_BANKS_COUNT];
extern u8 gTakenDmgBanks[BATTLE_BANKS_COUNT];
extern u8 gSentPokesToOpponent[2];
extern u8 gBank1;
extern u16 gExpShareExp;
extern u8 gLeveledUpInBattle;
extern void (*gBattleMainFunc)(void);
extern u8 gPlayerPartyCount;
extern u16 gMoveToLearn;
extern u16 gRandomMove;
extern u8 gBankInMenu;
extern u8 gActionForBanks[4];
extern u8 gCurrentMoveTurn;
extern u8 gBattleBufferB[4][0x200];
extern const struct BattleMove gBattleMoves[];
extern const u16 gMissStrings[];
extern const u8 gTrainerMoney[];
extern const u8 gTypeEffectiveness[];
extern const struct BaseStats gBaseStats[];
// functions
// BattleScripts
extern const u8 BattleScript_MoveEnd[];
extern const u8 BattleScript_NoPPForMove[];
extern const u8 BattleScript_MagicCoatBounce[];
extern const u8 BattleScript_TookAttack[];
extern const u8 BattleScript_SnatchedMove[];
extern const u8 BattleScript_Pausex20[];
extern const u8 BattleScript_SubstituteFade[];
extern const u8 BattleScript_HangedOnMsg[];
extern const u8 BattleScript_OneHitKOMsg[];
extern const u8 BattleScript_EnduredMsg[];
extern const u8 BattleScript_PSNPrevention[];
extern const u8 BattleScript_BRNPrevention[];
extern const u8 BattleScript_PRLZPrevention[];
extern const u8 BattleScript_FlinchPrevention[];
extern const u8 BattleScript_StatUp[];
extern const u8 BattleScript_StatDown[];
extern const u8 BattleScript_NoItemSteal[];
extern const u8 BattleScript_ItemSteal[];
extern const u8 BattleScript_RapidSpinAway[];
extern const u8 BattleScript_TargetPRLZHeal[];
extern const u8 BattleScript_KnockedOff[];
extern const u8 BattleScript_LevelUp[];
extern const u8 BattleScript_WrapFree[];
extern const u8 BattleScript_LeechSeedFree[];
extern const u8 BattleScript_SpikesFree[];
extern const u8 BattleScript_ButItFailed[];
extern const u8 BattleScript_ObliviousPreventsAttraction[];
extern const u8 BattleScript_MistProtected[];
extern const u8 BattleScript_AbilityNoStatLoss[];
extern const u8 BattleScript_AbilityNoSpecificStatLoss[];
extern const u8 BattleScript_TrainerBallBlock[];
extern const u8 BattleScript_WallyBallThrow[];
extern const u8 BattleScript_SuccessBallThrow[];
extern const u8 BattleScript_ShakeBallThrow[];
// read via orr
#define BSScriptRead32(ptr) ((ptr)[0] | (ptr)[1] << 8 | (ptr)[2] << 16 | (ptr)[3] << 24)
#define BSScriptRead8(ptr) (((u8)((ptr)[0])))
#define BSScriptReadPtr(ptr) ((void *)BSScriptRead32(ptr))
// read via add
#define BS2ScriptRead32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24))
#define BS2ScriptRead16(ptr) ((ptr)[0] + ((ptr)[1] << 8))
#define BS2ScriptReadPtr(ptr) ((void *)BS2ScriptRead32(ptr))
#define TARGET_PROTECT_AFFECTED ((gProtectStructs[gBankTarget].protected && gBattleMoves[gCurrentMove].flags & FLAG_PROTECT_AFFECTED))
#define TARGET_TURN_DAMAGED (((gSpecialStatuses[gBankTarget].moveturnLostHP_physical || gSpecialStatuses[gBankTarget].moveturnLostHP_physical.moveturnLostHP_special)))
// this file's functions
bool8 IsTwoTurnsMove(u16 move);
void DestinyBondFlagUpdate(void);
u8 AttacksThisTurn(u8 bank, u16 move); // Note: returns 1 if it's a charging turn, otherwise 2.
void b_wonderguard_and_levitate(void);
void atk00_attackcanceler(void);
void atk01_accuracycheck(void);
@ -510,13 +640,13 @@ void (* const gBattleScriptingCommandsTable[])(void) =
sub_8056EF8
};
struct statFractions
struct StatFractions
{
u8 dividend;
u8 divisor;
};
const struct statFractions gAccuracyStageRatios[] =
const struct StatFractions gAccuracyStageRatios[] =
{
{ 33, 100}, // -6
{ 36, 100}, // -5
@ -599,3 +729,292 @@ const u32 gStatusFlagsForMoveEffects[] =
0x00000000,
0x00000000
};
void atk00_attackcanceler(void)
{
s32 i;
if (gBattleOutcome)
{
gFightStateTracker = 0xC;
return;
}
if (gBattleMons[gBankAttacker].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, gBankTarget, 0, 0, 0))
return;
if (!gBattleMons[gBankAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE && !(gHitMarker & 0x800200)
&& !(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS))
{
gBattlescriptCurrInstr = BattleScript_NoPPForMove;
gBattleMoveFlags |= MOVESTATUS_MISSED;
return;
}
gHitMarker &= ~(HITMARKER_x800000);
if (!(gHitMarker & HITMARKER_OBEYS) && !(gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS))
{
i = IsPokeDisobedient(); // why use the 'i' variable...?
switch (i)
{
case 0:
break;
case 2:
gHitMarker |= HITMARKER_OBEYS;
return;
default:
gBattleMoveFlags |= MOVESTATUS_MISSED;
return;
}
}
gHitMarker |= HITMARKER_OBEYS;
if (gProtectStructs[gBankTarget].bounceMove && gBattleMoves[gCurrentMove].flags & FLAG_MAGICCOAT_AFFECTED)
{
PressurePPLose(gBankAttacker, gBankTarget, MOVE_MAGIC_COAT);
gProtectStructs[gBankTarget].bounceMove = 0;
b_movescr_stack_push_cursor();
gBattlescriptCurrInstr = BattleScript_MagicCoatBounce;
return;
}
for (i = 0; i < gNoOfAllBanks; i++)
{
if ((gProtectStructs[gTurnOrder[i]].stealMove) && gBattleMoves[gCurrentMove].flags & FLAG_SNATCH_AFFECTED)
{
PressurePPLose(gBankAttacker, gTurnOrder[i], MOVE_SNATCH);
gProtectStructs[gTurnOrder[i]].stealMove = 0;
gBattleScripting.bank = gTurnOrder[i];
b_movescr_stack_push_cursor();
gBattlescriptCurrInstr = BattleScript_SnatchedMove;
return;
}
}
if (gSpecialStatuses[gBankTarget].lightningRodRedirected)
{
gSpecialStatuses[gBankTarget].lightningRodRedirected = 0;
gLastUsedAbility = ABILITY_LIGHTNING_ROD;
b_movescr_stack_push_cursor();
gBattlescriptCurrInstr = BattleScript_TookAttack;
RecordAbilityBattle(gBankTarget, gLastUsedAbility);
}
else if (TARGET_PROTECT_AFFECTED
&& (gCurrentMove != MOVE_CURSE || (gBattleMons[gBankAttacker].type1 == TYPE_GHOST || gBattleMons[gBankAttacker].type2 == TYPE_GHOST))
&& ((!IsTwoTurnsMove(gCurrentMove) || (gBattleMons[gBankAttacker].status2 & STATUS2_MULTIPLETURNS))))
{
CancelMultiTurnMoves(gBankAttacker);
gBattleMoveFlags |= MOVESTATUS_MISSED;
gUnknown_02024250[gBankTarget] = 0;
gUnknown_02024258[gBankTarget] = 0;
gBattleCommunication[6] = 1;
gBattlescriptCurrInstr++;
}
else
{
gBattlescriptCurrInstr++;
}
}
void JumpIfMoveFailed(u8 adder, u16 move)
{
const void* BS_ptr = gBattlescriptCurrInstr + adder;
if (gBattleMoveFlags & MOVESTATUS_NOEFFECT)
{
gUnknown_02024250[gBankTarget] = 0;
gUnknown_02024258[gBankTarget] = 0;
BS_ptr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
}
else
{
DestinyBondFlagUpdate();
if (AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBankTarget, 0, 0, move))
return;
}
gBattlescriptCurrInstr = BS_ptr;
}
void atk40_jump_if_move_affected_by_protect(void)
{
if (TARGET_PROTECT_AFFECTED)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
JumpIfMoveFailed(5, 0);
gBattleCommunication[6] = 1;
}
else
{
gBattlescriptCurrInstr += 5;
}
}
bool8 JumpIfMoveAffectedByProtect(u16 move)
{
bool8 affected = FALSE;
if (TARGET_PROTECT_AFFECTED)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
JumpIfMoveFailed(7, move);
gBattleCommunication[6] = 1;
affected = TRUE;
}
return affected;
}
bool8 AccuracyCalcHelper(u16 move)
{
if (gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBankTarget].bankWithSureHit == gBankAttacker)
{
JumpIfMoveFailed(7, move);
return TRUE;
}
if (!(gHitMarker & HITMARKER_IGNORE_ON_AIR) && gStatuses3[gBankTarget] & STATUS3_ON_AIR)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
JumpIfMoveFailed(7, move);
return TRUE;
}
gHitMarker &= ~HITMARKER_IGNORE_ON_AIR;
if (!(gHitMarker & HITMARKER_IGNORE_UNDERGROUND) && gStatuses3[gBankTarget] & STATUS3_UNDERGROUND)
{
gBattleMoveFlags |= MOVESTATUS_MISSED;
JumpIfMoveFailed(7, move);
return TRUE;
}
gHitMarker &= ~HITMARKER_IGNORE_UNDERGROUND;
if (!(gHitMarker & HITMARKER_IGNORE_UNDERWATER) && gStatuses3[gBankTarget] & STATUS3_UNDERWATER)
{
gBattleMoveFlags |= MOVESTATUS_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 = BS2ScriptRead16(gBattlescriptCurrInstr + 5);
if (move == 0xFFFE || move == 0xFFFF)
{
if (gStatuses3[gBankTarget] & STATUS3_ALWAYS_HITS && move == 0xFFFF && gDisableStructs[gBankTarget].bankWithSureHit == gBankAttacker)
gBattlescriptCurrInstr += 7;
else if (gStatuses3[gBankTarget] & (STATUS3_ON_AIR | STATUS3_UNDERGROUND | STATUS3_UNDERWATER))
gBattlescriptCurrInstr = BSScriptReadPtr(gBattlescriptCurrInstr + 1);
else if (!JumpIfMoveAffectedByProtect(0))
gBattlescriptCurrInstr += 7;
}
else
{
u8 type, moveAcc, holdEffect, quality;
s8 buff;
u16 calc;
if (move == 0)
move = gCurrentMove;
GET_MOVE_TYPE(move, type);
if (JumpIfMoveAffectedByProtect(move))
return;
if (AccuracyCalcHelper(move))
return;
if (gBattleMons[gBankTarget].status2 & STATUS2_FORESIGHT)
{
u8 acc = gBattleMons[gBankAttacker].statStages[STAT_STAGE_ACC];
buff = acc;
}
else
{
u8 acc = gBattleMons[gBankAttacker].statStages[STAT_STAGE_ACC];
buff = acc + 6 - gBattleMons[gBankTarget].statStages[STAT_STAGE_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 = gAccuracyStageRatios[buff].dividend * moveAcc;
calc /= gAccuracyStageRatios[buff].divisor;
if (gBattleMons[gBankAttacker].ability == ABILITY_COMPOUND_EYES)
calc = (calc * 130) / 100; // 1.3 compound eyes boost
if (WEATHER_HAS_EFFECT && gBattleMons[gBankTarget].ability == ABILITY_SAND_VEIL && gBattleWeather & WEATHER_SANDSTORM_ANY)
calc = (calc * 80) / 100; // 1.2 sand veil loss
if (gBattleMons[gBankAttacker].ability == ABILITY_HUSTLE && type < 9)
calc = (calc * 80) / 100; // 1.2 hustle loss
if (gBattleMons[gBankTarget].item == ITEM_ENIGMA_BERRY)
{
holdEffect = gEnigmaBerries[gBankTarget].holdEffect;
quality = gEnigmaBerries[gBankTarget].holdEffectParam;
}
else
{
holdEffect = ItemId_GetHoldEffect(gBattleMons[gBankTarget].item);
quality = ItemId_GetHoldEffectParam(gBattleMons[gBankTarget].item);
}
gStringBank = gBankTarget;
if (holdEffect == HOLD_EFFECT_EVASION_UP)
calc = (calc * (100 - quality)) / 100;
// final calculation
if ((Random() % 100 + 1) > calc)
{
gBattleMoveFlags |= MOVESTATUS_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;
b_wonderguard_and_levitate();
}
JumpIfMoveFailed(7, move);
}
}
void atk02_attackstring(void)
{
if (gBattleExecBuffer)
return;
if (!(gHitMarker & (HITMARKER_NO_ATTACKSTRING | HITMARKER_ATTACKSTRING_PRINTED)))
{
PrepareStringBattle(4, gBankAttacker);
gHitMarker |= HITMARKER_ATTACKSTRING_PRINTED;
}
gBattlescriptCurrInstr++;
gBattleCommunication[MSG_DISPLAY] = 0;
}